diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2003-05-07 21:52:24 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2003-05-07 21:52:24 (GMT) |
commit | 43e3b450214310728cbb6904211319a8459f06e4 (patch) | |
tree | 13cc61b9f713aa60fdcaf606665f03189689046d /src | |
parent | db543f1a23194e81d0a984c346398e72bf4be87f (diff) | |
download | hdf5-43e3b450214310728cbb6904211319a8459f06e4.zip hdf5-43e3b450214310728cbb6904211319a8459f06e4.tar.gz hdf5-43e3b450214310728cbb6904211319a8459f06e4.tar.bz2 |
[svn-r6825] Purpose:
New feature/enhancement
Description:
Chunked datasets are handled poorly in several circumstances involving
certain selections and chunks that are too large for the chunk cache and/or
chunks with filters, causing the chunk to be read from disk multiple times.
Solution:
Rearrange raw data I/O infrastructure to handle chunked datasets in a much
more friendly way by creating a selection in memory and on disk for each chunk
in a chunked dataset and performing all of the I/O on that chunk at one time.
There are still some scalability (the current code attempts to
create a selection for all the chunks in the dataset, instead of just the
chunks that are accessed, requiring portions of the istore.c and fillval.c
tests to be commented out) and performance issues, but checking this in will
allow the changes to be tested by a much wider audience while I address the
remaining issues.
Platforms tested:
h5committested, FreeBSD 4.8 (sleipnir) serial & parallel, Linux 2.4 (eirene)
Diffstat (limited to 'src')
-rw-r--r-- | src/Dependencies | 862 | ||||
-rw-r--r-- | src/H5D.c | 1215 | ||||
-rw-r--r-- | src/H5Dcompact.c | 92 | ||||
-rw-r--r-- | src/H5Dcontig.c | 1271 | ||||
-rw-r--r-- | src/H5Dio.c | 2293 | ||||
-rw-r--r-- | src/H5Distore.c | 431 | ||||
-rw-r--r-- | src/H5Dpkg.h | 76 | ||||
-rw-r--r-- | src/H5Dprivate.h | 46 | ||||
-rw-r--r-- | src/H5Dseq.c | 754 | ||||
-rw-r--r-- | src/H5E.c | 3 | ||||
-rw-r--r-- | src/H5Epublic.h | 3 | ||||
-rw-r--r-- | src/H5Farray.c | 511 | ||||
-rw-r--r-- | src/H5Fcompact.c | 92 | ||||
-rw-r--r-- | src/H5Fcontig.c | 1271 | ||||
-rw-r--r-- | src/H5Fistore.c | 431 | ||||
-rw-r--r-- | src/H5Fpkg.h | 56 | ||||
-rw-r--r-- | src/H5Fprivate.h | 53 | ||||
-rw-r--r-- | src/H5Fseq.c | 754 | ||||
-rw-r--r-- | src/H5G.c | 2 | ||||
-rw-r--r-- | src/H5Oefl.c | 172 | ||||
-rw-r--r-- | src/H5Oprivate.h | 12 | ||||
-rw-r--r-- | src/H5S.c | 16 | ||||
-rw-r--r-- | src/H5Sall.c | 122 | ||||
-rw-r--r-- | src/H5Shyper.c | 1115 | ||||
-rw-r--r-- | src/H5Snone.c | 91 | ||||
-rw-r--r-- | src/H5Spkg.h | 69 | ||||
-rw-r--r-- | src/H5Spoint.c | 118 | ||||
-rw-r--r-- | src/H5Sprivate.h | 78 | ||||
-rw-r--r-- | src/H5Sselect.c | 638 | ||||
-rw-r--r-- | src/H5V.c | 322 | ||||
-rw-r--r-- | src/H5Vprivate.h | 15 | ||||
-rw-r--r-- | src/H5Z.c | 2 | ||||
-rw-r--r-- | src/Makefile.in | 32 |
33 files changed, 6666 insertions, 6352 deletions
diff --git a/src/Dependencies b/src/Dependencies index 43961a9..b488a04 100644 --- a/src/Dependencies +++ b/src/Dependencies @@ -19,10 +19,6 @@ H5.lo: \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ - $(srcdir)/H5Gprivate.h \ - $(srcdir)/H5Gpublic.h \ - $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Oprivate.h \ $(srcdir)/H5Opublic.h \ $(srcdir)/H5Spublic.h \ @@ -30,19 +26,23 @@ H5.lo: \ $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Tprivate.h \ $(srcdir)/H5Tpublic.h \ + $(srcdir)/H5Gprivate.h \ + $(srcdir)/H5Gpublic.h \ + $(srcdir)/H5RSprivate.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5FDprivate.h \ $(srcdir)/H5FLprivate.h \ $(srcdir)/H5Iprivate.h \ $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ + $(srcdir)/H5Sprivate.h \ $(srcdir)/H5FDmpio.h H5A.lo: \ $(srcdir)/H5A.c \ @@ -104,12 +104,6 @@ H5AC.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ - $(srcdir)/H5Gprivate.h \ - $(srcdir)/H5Gpublic.h \ - $(srcdir)/H5Bprivate.h \ - $(srcdir)/H5Bpublic.h \ - $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Oprivate.h \ $(srcdir)/H5Opublic.h \ $(srcdir)/H5Spublic.h \ @@ -117,13 +111,15 @@ H5AC.lo: \ $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Tprivate.h \ $(srcdir)/H5Tpublic.h \ + $(srcdir)/H5Gprivate.h \ + $(srcdir)/H5Gpublic.h \ + $(srcdir)/H5Bprivate.h \ + $(srcdir)/H5Bpublic.h \ + $(srcdir)/H5RSprivate.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5Fpkg.h \ @@ -132,6 +128,9 @@ H5AC.lo: \ $(srcdir)/H5FLprivate.h \ $(srcdir)/H5Iprivate.h \ $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ $(srcdir)/H5FDfphdf5.h \ $(srcdir)/H5FDmpio.h \ $(srcdir)/H5FDmpiposix.h @@ -174,12 +173,20 @@ H5D.lo: \ $(srcdir)/H5api_adpt.h \ $(srcdir)/H5MPprivate.h \ $(srcdir)/H5FSprivate.h \ + $(srcdir)/H5Dpkg.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -187,14 +194,57 @@ H5D.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ + $(srcdir)/H5Rprivate.h \ + $(srcdir)/H5Rpublic.h \ + $(srcdir)/H5Zprivate.h \ + $(srcdir)/H5Zpublic.h \ + $(srcdir)/H5Sprivate.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Eprivate.h \ + $(srcdir)/H5Epublic.h \ + $(srcdir)/H5FDprivate.h \ + $(srcdir)/H5FLprivate.h \ + $(srcdir)/H5FOprivate.h \ + $(srcdir)/H5TBprivate.h \ + $(srcdir)/H5HLprivate.h \ + $(srcdir)/H5HLpublic.h \ + $(srcdir)/H5Iprivate.h \ + $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5Vprivate.h \ + $(srcdir)/H5FDfphdf5.h \ + $(srcdir)/H5FDmpio.h \ + $(srcdir)/H5FDmpiposix.h +H5Dio.lo: \ + $(srcdir)/H5Dio.c \ + $(srcdir)/H5private.h \ + $(srcdir)/H5public.h \ + H5pubconf.h \ + $(srcdir)/H5api_adpt.h \ + $(srcdir)/H5MPprivate.h \ + $(srcdir)/H5FSprivate.h \ + $(srcdir)/H5Dpkg.h \ + $(srcdir)/H5Dprivate.h \ + $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Ipublic.h \ $(srcdir)/H5Oprivate.h \ $(srcdir)/H5Opublic.h \ $(srcdir)/H5Spublic.h \ $(srcdir)/H5HGprivate.h \ $(srcdir)/H5HGpublic.h \ + $(srcdir)/H5Fprivate.h \ + $(srcdir)/H5Fpublic.h \ + $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Tprivate.h \ $(srcdir)/H5Tpublic.h \ + $(srcdir)/H5Gprivate.h \ + $(srcdir)/H5Gpublic.h \ + $(srcdir)/H5Bprivate.h \ + $(srcdir)/H5Bpublic.h \ + $(srcdir)/H5ACprivate.h \ + $(srcdir)/H5ACpublic.h \ + $(srcdir)/H5RSprivate.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ @@ -202,18 +252,12 @@ H5D.lo: \ $(srcdir)/H5Sprivate.h \ $(srcdir)/H5Pprivate.h \ $(srcdir)/H5Ppublic.h \ + $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ - $(srcdir)/H5FDprivate.h \ $(srcdir)/H5FLprivate.h \ - $(srcdir)/H5FOprivate.h \ - $(srcdir)/H5TBprivate.h \ - $(srcdir)/H5HLprivate.h \ - $(srcdir)/H5HLpublic.h \ $(srcdir)/H5Iprivate.h \ - $(srcdir)/H5MFprivate.h \ $(srcdir)/H5MMprivate.h \ - $(srcdir)/H5Spkg.h \ $(srcdir)/H5Vprivate.h \ $(srcdir)/H5FDfphdf5.h \ $(srcdir)/H5FDmpio.h \ @@ -280,8 +324,6 @@ H5F.lo: \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5Fpkg.h \ @@ -291,9 +333,10 @@ H5F.lo: \ $(srcdir)/H5FLprivate.h \ $(srcdir)/H5FPprivate.h \ $(srcdir)/H5Iprivate.h \ - $(srcdir)/H5MMprivate.h -H5Farray.lo: \ - $(srcdir)/H5Farray.c \ + $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5Pprivate.h +H5Fcontig.lo: \ + $(srcdir)/H5Fcontig.c \ $(srcdir)/H5private.h \ $(srcdir)/H5public.h \ H5pubconf.h \ @@ -303,55 +346,16 @@ H5Farray.lo: \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ - $(srcdir)/H5Fprivate.h \ - $(srcdir)/H5Fpublic.h \ - $(srcdir)/H5FDpublic.h \ - $(srcdir)/H5Gprivate.h \ - $(srcdir)/H5Gpublic.h \ - $(srcdir)/H5Bprivate.h \ - $(srcdir)/H5Bpublic.h \ - $(srcdir)/H5ACprivate.h \ - $(srcdir)/H5ACpublic.h \ - $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Oprivate.h \ $(srcdir)/H5Opublic.h \ $(srcdir)/H5Spublic.h \ $(srcdir)/H5HGprivate.h \ $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ - $(srcdir)/H5Rprivate.h \ - $(srcdir)/H5Rpublic.h \ - $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ - $(srcdir)/H5Eprivate.h \ - $(srcdir)/H5Epublic.h \ - $(srcdir)/H5Fpkg.h \ - $(srcdir)/H5FOprivate.h \ - $(srcdir)/H5TBprivate.h \ - $(srcdir)/H5FDprivate.h \ - $(srcdir)/H5Iprivate.h \ - $(srcdir)/H5MMprivate.h \ - $(srcdir)/H5Vprivate.h \ - $(srcdir)/H5FDmpio.h -H5Fcontig.lo: \ - $(srcdir)/H5Fcontig.c \ - $(srcdir)/H5private.h \ - $(srcdir)/H5public.h \ - H5pubconf.h \ - $(srcdir)/H5api_adpt.h \ - $(srcdir)/H5MPprivate.h \ - $(srcdir)/H5FSprivate.h \ - $(srcdir)/H5Dprivate.h \ - $(srcdir)/H5Dpublic.h \ - $(srcdir)/H5Ipublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -359,21 +363,10 @@ H5Fcontig.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5Fpkg.h \ @@ -381,6 +374,11 @@ H5Fcontig.lo: \ $(srcdir)/H5TBprivate.h \ $(srcdir)/H5FDprivate.h \ $(srcdir)/H5FLprivate.h \ + $(srcdir)/H5MFprivate.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Sprivate.h \ $(srcdir)/H5Vprivate.h \ $(srcdir)/H5FDfphdf5.h \ $(srcdir)/H5FDmpio.h \ @@ -422,7 +420,8 @@ H5Fcompact.lo: \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ $(srcdir)/H5FDprivate.h \ - $(srcdir)/H5FLprivate.h + $(srcdir)/H5FLprivate.h \ + $(srcdir)/H5Vprivate.h H5Fistore.lo: \ $(srcdir)/H5Fistore.c \ $(srcdir)/H5private.h \ @@ -441,10 +440,6 @@ H5Fistore.lo: \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ - $(srcdir)/H5Gprivate.h \ - $(srcdir)/H5Gpublic.h \ - $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Oprivate.h \ $(srcdir)/H5Opublic.h \ $(srcdir)/H5Spublic.h \ @@ -452,13 +447,13 @@ H5Fistore.lo: \ $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Tprivate.h \ $(srcdir)/H5Tpublic.h \ + $(srcdir)/H5Gprivate.h \ + $(srcdir)/H5Gpublic.h \ + $(srcdir)/H5RSprivate.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5Fpkg.h \ @@ -469,6 +464,10 @@ H5Fistore.lo: \ $(srcdir)/H5MFprivate.h \ $(srcdir)/H5FDprivate.h \ $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ + $(srcdir)/H5Sprivate.h \ $(srcdir)/H5Vprivate.h \ $(srcdir)/H5FDfphdf5.h \ $(srcdir)/H5FDmpio.h \ @@ -484,9 +483,16 @@ H5Fseq.lo: \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -494,21 +500,10 @@ H5Fseq.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5Fpkg.h \ @@ -518,6 +513,9 @@ H5Fseq.lo: \ $(srcdir)/H5Iprivate.h \ $(srcdir)/H5MFprivate.h \ $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Vprivate.h \ $(srcdir)/H5FDmpio.h \ $(srcdir)/H5FDmpiposix.h @@ -532,9 +530,16 @@ H5FD.lo: \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -542,21 +547,10 @@ H5FD.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5Fpkg.h \ @@ -565,7 +559,10 @@ H5FD.lo: \ $(srcdir)/H5FDprivate.h \ $(srcdir)/H5FLprivate.h \ $(srcdir)/H5Iprivate.h \ - $(srcdir)/H5MMprivate.h + $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h H5FDcore.lo: \ $(srcdir)/H5FDcore.c \ $(srcdir)/H5private.h \ @@ -628,12 +625,6 @@ H5FDfphdf5.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ - $(srcdir)/H5Gprivate.h \ - $(srcdir)/H5Gpublic.h \ - $(srcdir)/H5Bprivate.h \ - $(srcdir)/H5Bpublic.h \ - $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Oprivate.h \ $(srcdir)/H5Opublic.h \ $(srcdir)/H5Spublic.h \ @@ -641,20 +632,25 @@ H5FDfphdf5.lo: \ $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Tprivate.h \ $(srcdir)/H5Tpublic.h \ + $(srcdir)/H5Gprivate.h \ + $(srcdir)/H5Gpublic.h \ + $(srcdir)/H5Bprivate.h \ + $(srcdir)/H5Bpublic.h \ + $(srcdir)/H5RSprivate.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5FDprivate.h \ $(srcdir)/H5FDfphdf5.h \ $(srcdir)/H5FDmpio.h \ $(srcdir)/H5Iprivate.h \ - $(srcdir)/H5MMprivate.h + $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h H5FDgass.lo: \ $(srcdir)/H5FDgass.c \ $(srcdir)/H5private.h \ @@ -718,12 +714,6 @@ H5FDmpio.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ - $(srcdir)/H5Gprivate.h \ - $(srcdir)/H5Gpublic.h \ - $(srcdir)/H5Bprivate.h \ - $(srcdir)/H5Bpublic.h \ - $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Oprivate.h \ $(srcdir)/H5Opublic.h \ $(srcdir)/H5Spublic.h \ @@ -731,19 +721,24 @@ H5FDmpio.lo: \ $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Tprivate.h \ $(srcdir)/H5Tpublic.h \ + $(srcdir)/H5Gprivate.h \ + $(srcdir)/H5Gpublic.h \ + $(srcdir)/H5Bprivate.h \ + $(srcdir)/H5Bpublic.h \ + $(srcdir)/H5RSprivate.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5FDprivate.h \ $(srcdir)/H5FDmpio.h \ $(srcdir)/H5Iprivate.h \ - $(srcdir)/H5MMprivate.h + $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h H5FDmpiposix.lo: \ $(srcdir)/H5FDmpiposix.c \ $(srcdir)/H5private.h \ @@ -895,7 +890,20 @@ H5FDstream.lo: \ H5pubconf.h \ $(srcdir)/H5api_adpt.h \ $(srcdir)/H5MPprivate.h \ - $(srcdir)/H5FSprivate.h + $(srcdir)/H5FSprivate.h \ + $(srcdir)/H5Eprivate.h \ + $(srcdir)/H5Epublic.h \ + $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Fpublic.h \ + $(srcdir)/H5FDstream.h \ + $(srcdir)/H5Iprivate.h \ + $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ + $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Zpublic.h H5FL.lo: \ $(srcdir)/H5FL.c \ $(srcdir)/H5private.h \ @@ -928,7 +936,25 @@ H5FO.lo: \ $(srcdir)/H5FOprivate.h \ $(srcdir)/H5TBprivate.h \ $(srcdir)/H5Bpublic.h \ - $(srcdir)/H5FLprivate.h + $(srcdir)/H5FLprivate.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ + $(srcdir)/H5Gprivate.h \ + $(srcdir)/H5Gpublic.h \ + $(srcdir)/H5Bprivate.h \ + $(srcdir)/H5ACprivate.h \ + $(srcdir)/H5ACpublic.h \ + $(srcdir)/H5RSprivate.h \ + $(srcdir)/H5Rprivate.h \ + $(srcdir)/H5Rpublic.h \ + $(srcdir)/H5Zprivate.h \ + $(srcdir)/H5Zpublic.h H5FP.lo: \ $(srcdir)/H5FP.c \ $(srcdir)/H5private.h \ @@ -979,12 +1005,6 @@ H5FPclient.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ - $(srcdir)/H5Gprivate.h \ - $(srcdir)/H5Gpublic.h \ - $(srcdir)/H5Bprivate.h \ - $(srcdir)/H5Bpublic.h \ - $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Oprivate.h \ $(srcdir)/H5Opublic.h \ $(srcdir)/H5Spublic.h \ @@ -992,20 +1012,26 @@ H5FPclient.lo: \ $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Tprivate.h \ $(srcdir)/H5Tpublic.h \ + $(srcdir)/H5Gprivate.h \ + $(srcdir)/H5Gpublic.h \ + $(srcdir)/H5Bprivate.h \ + $(srcdir)/H5Bpublic.h \ + $(srcdir)/H5RSprivate.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5FDprivate.h \ $(srcdir)/H5Gpkg.h \ $(srcdir)/H5Iprivate.h \ $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Spkg.h \ + $(srcdir)/H5Sprivate.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ $(srcdir)/H5TBprivate.h H5FPserver.lo: \ $(srcdir)/H5FPserver.c \ @@ -1075,7 +1101,6 @@ H5G.lo: \ $(srcdir)/H5RSprivate.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ - $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Oprivate.h \ $(srcdir)/H5Opublic.h \ $(srcdir)/H5Spublic.h \ @@ -1087,9 +1112,6 @@ H5G.lo: \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5Fpkg.h \ @@ -1100,7 +1122,8 @@ H5G.lo: \ $(srcdir)/H5HLprivate.h \ $(srcdir)/H5HLpublic.h \ $(srcdir)/H5Iprivate.h \ - $(srcdir)/H5MMprivate.h + $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h H5Gent.lo: \ $(srcdir)/H5Gent.c \ $(srcdir)/H5private.h \ @@ -1551,10 +1574,7 @@ H5Odtype.lo: \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ $(srcdir)/H5Tpkg.h \ - $(srcdir)/H5Dprivate.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Dprivate.h H5Oefl.lo: \ $(srcdir)/H5Oefl.c \ $(srcdir)/H5private.h \ @@ -1647,9 +1667,16 @@ H5Olayout.lo: \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -1657,25 +1684,17 @@ H5Olayout.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5FLprivate.h \ + $(srcdir)/H5MFprivate.h \ + $(srcdir)/H5FDprivate.h \ $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Opkg.h H5Omtime.lo: \ $(srcdir)/H5Omtime.c \ @@ -1944,9 +1963,16 @@ H5P.lo: \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -1954,27 +1980,19 @@ H5P.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5FLprivate.h \ $(srcdir)/H5Iprivate.h \ $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Ppkg.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ $(srcdir)/H5TBprivate.h H5Pdcpl.lo: \ $(srcdir)/H5Pdcpl.c \ @@ -1987,9 +2005,16 @@ H5Pdcpl.lo: \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -1997,26 +2022,18 @@ H5Pdcpl.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5Iprivate.h \ $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Ppkg.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ $(srcdir)/H5TBprivate.h H5Pdxpl.lo: \ $(srcdir)/H5Pdxpl.c \ @@ -2029,9 +2046,16 @@ H5Pdxpl.lo: \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2039,24 +2063,16 @@ H5Pdxpl.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5Ppkg.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ + $(srcdir)/H5MMpublic.h \ $(srcdir)/H5TBprivate.h H5Pfapl.lo: \ $(srcdir)/H5Pfapl.c \ @@ -2069,9 +2085,16 @@ H5Pfapl.lo: \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2079,26 +2102,18 @@ H5Pfapl.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5FDprivate.h \ $(srcdir)/H5Iprivate.h \ $(srcdir)/H5Ppkg.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ + $(srcdir)/H5MMpublic.h \ $(srcdir)/H5TBprivate.h \ $(srcdir)/H5FDsec2.h H5Pfcpl.lo: \ @@ -2138,9 +2153,16 @@ H5R.lo: \ $(srcdir)/H5Ipublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2148,28 +2170,21 @@ H5R.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5Fpkg.h \ $(srcdir)/H5FOprivate.h \ $(srcdir)/H5TBprivate.h \ $(srcdir)/H5MMprivate.h \ - $(srcdir)/H5Spkg.h + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Spkg.h \ + $(srcdir)/H5Sprivate.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h H5RS.lo: \ $(srcdir)/H5RS.c \ $(srcdir)/H5Eprivate.h \ @@ -2443,9 +2458,16 @@ H5Sselect.lo: \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2453,26 +2475,19 @@ H5Sselect.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5FLprivate.h \ $(srcdir)/H5Iprivate.h \ $(srcdir)/H5Spkg.h \ + $(srcdir)/H5Sprivate.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ + $(srcdir)/H5MMpublic.h \ $(srcdir)/H5Vprivate.h H5ST.lo: \ $(srcdir)/H5ST.c \ @@ -2498,9 +2513,16 @@ H5T.lo: \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2508,26 +2530,18 @@ H5T.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5FLprivate.h \ $(srcdir)/H5Iprivate.h \ $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Tpkg.h H5Tarray.lo: \ $(srcdir)/H5Tarray.c \ @@ -2550,6 +2564,11 @@ H5Tarray.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2557,19 +2576,10 @@ H5Tarray.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tbit.lo: \ $(srcdir)/H5Tbit.c \ $(srcdir)/H5private.h \ @@ -2590,6 +2600,11 @@ H5Tbit.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2597,19 +2612,10 @@ H5Tbit.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tcommit.lo: \ $(srcdir)/H5Tcommit.c \ $(srcdir)/H5private.h \ @@ -2630,6 +2636,11 @@ H5Tcommit.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2637,19 +2648,10 @@ H5Tcommit.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tcompound.lo: \ $(srcdir)/H5Tcompound.c \ $(srcdir)/H5private.h \ @@ -2672,6 +2674,11 @@ H5Tcompound.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2679,18 +2686,10 @@ H5Tcompound.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tconv.lo: \ $(srcdir)/H5Tconv.c \ $(srcdir)/H5private.h \ @@ -2717,6 +2716,11 @@ H5Tconv.lo: \ $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Dprivate.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2724,15 +2728,9 @@ H5Tconv.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ - $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Sprivate.h + $(srcdir)/H5Zprivate.h H5Tcset.lo: \ $(srcdir)/H5Tcset.c \ $(srcdir)/H5private.h \ @@ -2753,6 +2751,11 @@ H5Tcset.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2760,19 +2763,10 @@ H5Tcset.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tenum.lo: \ $(srcdir)/H5Tenum.c \ $(srcdir)/H5private.h \ @@ -2796,6 +2790,11 @@ H5Tenum.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2803,18 +2802,10 @@ H5Tenum.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tfields.lo: \ $(srcdir)/H5Tfields.c \ $(srcdir)/H5private.h \ @@ -2837,6 +2828,11 @@ H5Tfields.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2844,18 +2840,10 @@ H5Tfields.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tfixed.lo: \ $(srcdir)/H5Tfixed.c \ $(srcdir)/H5private.h \ @@ -2876,6 +2864,11 @@ H5Tfixed.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2883,19 +2876,10 @@ H5Tfixed.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tfloat.lo: \ $(srcdir)/H5Tfloat.c \ $(srcdir)/H5private.h \ @@ -2916,6 +2900,11 @@ H5Tfloat.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2923,19 +2912,49 @@ H5Tfloat.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ + $(srcdir)/H5Rprivate.h \ + $(srcdir)/H5Rpublic.h \ + $(srcdir)/H5Zprivate.h \ + $(srcdir)/H5Zpublic.h +H5Tinit.lo: \ + H5Tinit.c \ + $(srcdir)/H5private.h \ + $(srcdir)/H5public.h \ + H5pubconf.h \ + $(srcdir)/H5api_adpt.h \ + $(srcdir)/H5MPprivate.h \ + $(srcdir)/H5FSprivate.h \ + $(srcdir)/H5Iprivate.h \ + $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Eprivate.h \ + $(srcdir)/H5Epublic.h \ + $(srcdir)/H5FLprivate.h \ + $(srcdir)/H5MMprivate.h \ $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Tpkg.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ + $(srcdir)/H5Fprivate.h \ + $(srcdir)/H5Fpublic.h \ + $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Dprivate.h \ + $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Oprivate.h \ $(srcdir)/H5Opublic.h \ $(srcdir)/H5Spublic.h \ $(srcdir)/H5Tprivate.h \ $(srcdir)/H5Tpublic.h \ + $(srcdir)/H5Gprivate.h \ + $(srcdir)/H5Gpublic.h \ + $(srcdir)/H5Bprivate.h \ + $(srcdir)/H5Bpublic.h \ + $(srcdir)/H5ACprivate.h \ + $(srcdir)/H5ACpublic.h \ + $(srcdir)/H5RSprivate.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tnative.lo: \ $(srcdir)/H5Tnative.c \ $(srcdir)/H5private.h \ @@ -2958,6 +2977,11 @@ H5Tnative.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -2965,18 +2989,10 @@ H5Tnative.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Toffset.lo: \ $(srcdir)/H5Toffset.c \ $(srcdir)/H5private.h \ @@ -2997,6 +3013,11 @@ H5Toffset.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -3004,19 +3025,10 @@ H5Toffset.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Topaque.lo: \ $(srcdir)/H5Topaque.c \ $(srcdir)/H5private.h \ @@ -3039,6 +3051,11 @@ H5Topaque.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -3046,18 +3063,10 @@ H5Topaque.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Torder.lo: \ $(srcdir)/H5Torder.c \ $(srcdir)/H5private.h \ @@ -3078,6 +3087,11 @@ H5Torder.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -3085,19 +3099,10 @@ H5Torder.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tpad.lo: \ $(srcdir)/H5Tpad.c \ $(srcdir)/H5private.h \ @@ -3118,6 +3123,11 @@ H5Tpad.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -3125,19 +3135,10 @@ H5Tpad.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tprecis.lo: \ $(srcdir)/H5Tprecis.c \ $(srcdir)/H5private.h \ @@ -3158,6 +3159,11 @@ H5Tprecis.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -3165,19 +3171,10 @@ H5Tprecis.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tstrpad.lo: \ $(srcdir)/H5Tstrpad.c \ $(srcdir)/H5private.h \ @@ -3198,6 +3195,11 @@ H5Tstrpad.lo: \ $(srcdir)/H5FDpublic.h \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -3205,19 +3207,10 @@ H5Tstrpad.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h + $(srcdir)/H5Zpublic.h H5Tvlen.lo: \ $(srcdir)/H5Tvlen.c \ $(srcdir)/H5private.h \ @@ -3244,6 +3237,11 @@ H5Tvlen.lo: \ $(srcdir)/H5Zpublic.h \ $(srcdir)/H5Tpkg.h \ $(srcdir)/H5Dprivate.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -3251,15 +3249,9 @@ H5Tvlen.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ - $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Sprivate.h + $(srcdir)/H5Zprivate.h H5TB.lo: \ $(srcdir)/H5TB.c \ $(srcdir)/H5private.h \ @@ -3336,9 +3328,16 @@ H5Z.lo: \ $(srcdir)/H5Dprivate.h \ $(srcdir)/H5Dpublic.h \ $(srcdir)/H5Ipublic.h \ + $(srcdir)/H5Oprivate.h \ + $(srcdir)/H5Opublic.h \ + $(srcdir)/H5Spublic.h \ + $(srcdir)/H5HGprivate.h \ + $(srcdir)/H5HGpublic.h \ $(srcdir)/H5Fprivate.h \ $(srcdir)/H5Fpublic.h \ $(srcdir)/H5FDpublic.h \ + $(srcdir)/H5Tprivate.h \ + $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Gprivate.h \ $(srcdir)/H5Gpublic.h \ $(srcdir)/H5Bprivate.h \ @@ -3346,25 +3345,18 @@ H5Z.lo: \ $(srcdir)/H5ACprivate.h \ $(srcdir)/H5ACpublic.h \ $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ $(srcdir)/H5Rprivate.h \ $(srcdir)/H5Rpublic.h \ $(srcdir)/H5Zprivate.h \ $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Eprivate.h \ $(srcdir)/H5Epublic.h \ $(srcdir)/H5Iprivate.h \ $(srcdir)/H5MMprivate.h \ + $(srcdir)/H5MMpublic.h \ + $(srcdir)/H5Pprivate.h \ + $(srcdir)/H5Ppublic.h \ + $(srcdir)/H5Sprivate.h \ $(srcdir)/H5Zpkg.h H5Zdeflate.lo: \ $(srcdir)/H5Zdeflate.c \ @@ -3459,45 +3451,3 @@ H5Zszip.lo: \ $(srcdir)/H5Zpublic.h \ $(srcdir)/H5Ppublic.h \ $(srcdir)/H5Zpkg.h -H5Tinit.lo: \ - H5Tinit.c \ - $(srcdir)/H5private.h \ - $(srcdir)/H5public.h \ - H5pubconf.h \ - $(srcdir)/H5api_adpt.h \ - $(srcdir)/H5MPprivate.h \ - $(srcdir)/H5FSprivate.h \ - $(srcdir)/H5Iprivate.h \ - $(srcdir)/H5Ipublic.h \ - $(srcdir)/H5Eprivate.h \ - $(srcdir)/H5Epublic.h \ - $(srcdir)/H5FLprivate.h \ - $(srcdir)/H5MMprivate.h \ - $(srcdir)/H5MMpublic.h \ - $(srcdir)/H5Tpkg.h \ - $(srcdir)/H5HGprivate.h \ - $(srcdir)/H5HGpublic.h \ - $(srcdir)/H5Fprivate.h \ - $(srcdir)/H5Fpublic.h \ - $(srcdir)/H5FDpublic.h \ - $(srcdir)/H5Dprivate.h \ - $(srcdir)/H5Dpublic.h \ - $(srcdir)/H5Gprivate.h \ - $(srcdir)/H5Gpublic.h \ - $(srcdir)/H5Bprivate.h \ - $(srcdir)/H5Bpublic.h \ - $(srcdir)/H5ACprivate.h \ - $(srcdir)/H5ACpublic.h \ - $(srcdir)/H5RSprivate.h \ - $(srcdir)/H5Oprivate.h \ - $(srcdir)/H5Opublic.h \ - $(srcdir)/H5Spublic.h \ - $(srcdir)/H5Tprivate.h \ - $(srcdir)/H5Tpublic.h \ - $(srcdir)/H5Rprivate.h \ - $(srcdir)/H5Rpublic.h \ - $(srcdir)/H5Zprivate.h \ - $(srcdir)/H5Zpublic.h \ - $(srcdir)/H5Sprivate.h \ - $(srcdir)/H5Pprivate.h \ - $(srcdir)/H5Ppublic.h @@ -12,24 +12,19 @@ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#define H5S_PACKAGE /*suppress error about including H5Spkg */ +#define H5D_PACKAGE /*suppress error about including H5Dpkg */ #include "H5private.h" /* Generic Functions */ -#include "H5Dprivate.h" /* Dataset functions */ +#include "H5Dpkg.h" /* Dataset functions */ #include "H5Eprivate.h" /* Error handling */ #include "H5FDprivate.h" /* File drivers */ #include "H5FLprivate.h" /* Free Lists */ #include "H5FOprivate.h" /* File objects */ -#include "H5Gprivate.h" /* Group headers */ #include "H5HLprivate.h" /* Name heap */ #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 "H5Spkg.h" /* Dataspace functions */ +#include "H5Sprivate.h" /* Dataspace functions */ #include "H5Vprivate.h" /* Vector and array functions */ -#include "H5Zprivate.h" /* Data filters */ /*#define H5D_DEBUG*/ @@ -42,45 +37,20 @@ #include "H5FDmpio.h" #include "H5FDmpiposix.h" -#ifdef H5_HAVE_PARALLEL -/* Remove this if H5R_DATASET_REGION is no longer used in this file */ -# include "H5Rpublic.h" -#endif /*H5_HAVE_PARALLEL*/ - /* Pablo information */ #define PABLO_MASK H5D_mask -/* Local typedefs */ - -/* Enumerated type for allocating dataset's storage */ -typedef enum { - H5D_ALLOC_CREATE, /* Dataset is being created */ - H5D_ALLOC_OPEN, /* Dataset is being opened */ - H5D_ALLOC_EXTEND, /* Dataset's dataspace is being extended */ - H5D_ALLOC_WRITE /* Dataset is being extended */ -} H5D_time_alloc_t; - /* Interface initialization */ static int interface_initialize_g = 0; #define INTERFACE_INIT H5D_init_interface /* Local functions */ static herr_t H5D_init_interface(void); -static 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); static herr_t H5D_init_storage(H5D_t *dataset, hbool_t full_overwrite, hid_t dxpl_id); static H5D_t * H5D_new(hid_t dcpl_id, hbool_t creating); static H5D_t * H5D_create(H5G_entry_t *loc, const char *name, hid_t type_id, const H5S_t *space, hid_t dcpl_id, hid_t dxpl_id); static H5D_t * H5D_open_oid(H5G_entry_t *ent, hid_t dxpl_id); -static herr_t H5D_read(H5D_t *dataset, const H5T_t *mem_type, - 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, const H5T_t *mem_type, - const H5S_t *mem_space, const H5S_t *file_space, - hid_t dset_xfer_plist, const void *buf); -static 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); static herr_t H5D_get_space_status(H5D_t *dset, H5D_space_status_t *allocation, hid_t dxpl_id); static hsize_t H5D_get_storage_size(H5D_t *dset, hid_t dxpl_id); static haddr_t H5D_get_offset(H5D_t *dset); @@ -91,12 +61,6 @@ static herr_t H5D_close(H5D_t *dataset); /* Declare a free list to manage the H5D_t struct */ H5FL_DEFINE_STATIC(H5D_t); -/* Declare a free list to manage blocks of type conversion data */ -H5FL_BLK_DEFINE(type_conv); - -/* Declare a free list to manage blocks of single datatype element data */ -H5FL_BLK_DEFINE(type_elem); - /* Declare a free list to manage blocks of VL data */ H5FL_BLK_DEFINE_STATIC(vlen_vl_buf); @@ -1192,193 +1156,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5Dread - * - * Purpose: Reads (part of) a DSET from the file into application - * memory BUF. The part of the dataset to read is defined with - * MEM_SPACE_ID and FILE_SPACE_ID. The data points are - * converted from their file type to the MEM_TYPE_ID specified. - * Additional miscellaneous data transfer properties can be - * passed to this function with the PLIST_ID argument. - * - * The FILE_SPACE_ID can be the constant H5S_ALL which indicates - * that the entire file data space is to be referenced. - * - * The MEM_SPACE_ID can be the constant H5S_ALL in which case - * the memory data space is the same as the file data space - * defined when the dataset was created. - * - * The number of elements in the memory data space must match - * the number of elements in the file data space. - * - * The PLIST_ID can be the constant H5P_DEFAULT in which - * case the default data transfer properties are used. - * - * Return: Non-negative on success/Negative on failure - * - * Errors: - * ARGS BADTYPE Not a data space. - * ARGS BADTYPE Not a data type. - * ARGS BADTYPE Not a dataset. - * ARGS BADTYPE Not xfer parms. - * ARGS BADVALUE No output buffer. - * DATASET READERROR Can't read data. - * - * Programmer: Robb Matzke - * Thursday, December 4, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, - hid_t file_space_id, hid_t plist_id, void *buf/*out*/) -{ - H5D_t *dset = NULL; - const H5T_t *mem_type = NULL; - const H5S_t *mem_space = NULL; - const H5S_t *file_space = NULL; - 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))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); - if (NULL == dset->ent.file) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); - if (NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5S_ALL != mem_space_id) { - if (NULL == (mem_space = H5I_object_verify(mem_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); - - /* Check for valid selection */ - if((*mem_space->select.is_valid)(mem_space)!=TRUE) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); - } - if (H5S_ALL != file_space_id) { - if (NULL == (file_space = H5I_object_verify(file_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); - - /* Check for valid selection */ - if((*file_space->select.is_valid)(file_space)!=TRUE) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); - } - - /* 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)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); - if (!buf) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer"); - - /* read raw data */ - if (H5D_read(dset, mem_type, 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); -} - - -/*------------------------------------------------------------------------- - * Function: H5Dwrite - * - * Purpose: Writes (part of) a DSET from application memory BUF to the - * file. The part of the dataset to write is defined with the - * MEM_SPACE_ID and FILE_SPACE_ID arguments. The data points - * are converted from their current type (MEM_TYPE_ID) to their - * file data type. Additional miscellaneous data transfer - * properties can be passed to this function with the - * PLIST_ID argument. - * - * The FILE_SPACE_ID can be the constant H5S_ALL which indicates - * that the entire file data space is to be referenced. - * - * The MEM_SPACE_ID can be the constant H5S_ALL in which case - * the memory data space is the same as the file data space - * defined when the dataset was created. - * - * The number of elements in the memory data space must match - * the number of elements in the file data space. - * - * The PLIST_ID can be the constant H5P_DEFAULT in which - * case the default data transfer properties are used. - * - * Return: Non-negative on success/Negative on failure - * - * Errors: - * - * Programmer: Robb Matzke - * Thursday, December 4, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, - hid_t file_space_id, hid_t plist_id, const void *buf) -{ - H5D_t *dset = NULL; - const H5T_t *mem_type = NULL; - const H5S_t *mem_space = NULL; - const H5S_t *file_space = NULL; - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Dwrite, 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))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); - if (NULL == dset->ent.file) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); - if (NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_DATATYPE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); - if (H5S_ALL != mem_space_id) { - if (NULL == (mem_space = H5I_object_verify(mem_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); - - /* Check for valid selection */ - if ((*mem_space->select.is_valid)(mem_space)!=TRUE) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); - } - if (H5S_ALL != file_space_id) { - if (NULL == (file_space = H5I_object_verify(file_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); - - /* Check for valid selection */ - if ((*file_space->select.is_valid)(file_space)!=TRUE) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); - } - - /* 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)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); - if (!buf) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer"); - - /* write raw data */ - if (H5D_write(dset, mem_type, mem_space, file_space, plist_id, buf) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data"); - -done: - FUNC_LEAVE_API(ret_value); -} - - -/*------------------------------------------------------------------------- * Function: H5Dextend * * Purpose: This function makes sure that the dataset is at least of size @@ -2434,837 +2211,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5D_read - * - * Purpose: Reads (part of) a DATASET into application memory BUF. See - * H5Dread() for complete details. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Thursday, December 4, 1997 - * - * Modifications: - * Robb Matzke, 1998-06-09 - * The data space is no longer cached in the dataset struct. - * - * Robb Matzke, 1998-08-11 - * Added timing calls around all the data space I/O functions. - * - * rky, 1998-09-18 - * Added must_convert to do non-optimized read when necessary. - * - * Quincey Koziol, 1999-07-02 - * Changed xfer_parms parameter to xfer plist parameter, so it - * could be passed to H5T_convert. - * - * Albert Cheng, 2000-11-21 - * Added the code that when it detects it is not safe to process a - * COLLECTIVE read request without hanging, it changes it to - * INDEPENDENT calls. - * - * Albert Cheng, 2000-11-27 - * Changed to use the optimized MPIO transfer for Collective calls only. - * - * Raymond Lu, 2001-10-2 - * Changed the way to retrieve property for generic property list. - * - * Raymond Lu, 2002-2-26 - * For the new fill value design, data space can either be allocated - * or not allocated at this stage. Fill value or data from space is - * returned to outgoing buffer. - * - * QAK - 2002/04/02 - * Removed the must_convert parameter and move preconditions to - * H5S_<foo>_opt_possible() routine - * - *------------------------------------------------------------------------- - */ -static herr_t -H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, - const H5S_t *file_space, hid_t dxpl_id, void *buf/*out*/) -{ - hsize_t nelmts; /*total number of elmts */ - hsize_t smine_start; /*strip mine start loc */ - hsize_t n, smine_nelmts; /*elements per strip */ - uint8_t *tconv_buf = NULL; /*data type conv buffer */ - uint8_t *bkg_buf = NULL; /*background buffer */ - H5T_path_t *tpath = NULL; /*type conversion info */ - hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ - H5S_conv_t *sconv=NULL; /*space conversion funcs*/ - 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 */ - herr_t ret_value = SUCCEED; /*return value */ - herr_t status; /*function return status*/ - size_t src_type_size; /*size of source type */ - size_t dst_type_size; /*size of destination type*/ - size_t target_size; /*desired buffer size */ - hsize_t request_nelmts; /*requested strip mine */ - H5T_bkg_t need_bkg; /*type of background buf*/ -#ifdef H5_HAVE_PARALLEL - H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; /*xfer_mode for this request */ - hbool_t xfer_mode_changed=0; /*xfer_mode needs restore */ - hbool_t doing_mpio=0; /*This is an MPIO access */ -#endif /*H5_HAVE_PARALLEL*/ -#ifdef H5S_DEBUG - H5_timer_t timer; -#endif - H5P_genplist_t *dx_plist=NULL; /* Data transfer property list */ - H5P_genplist_t *dc_plist; /* Dataset creation roperty list */ - unsigned sconv_flags=0; /* Flags for the space conversion */ - - FUNC_ENTER_NOAPI(H5D_read, FAIL); - - /* check args */ - assert(dataset && dataset->ent.file); - assert(mem_type); - assert(buf); - - /* Get the dataset's creation property list */ - if (NULL == (dc_plist = H5I_object(dataset->dcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); - - /* Get the dataset transfer property list */ - if (NULL == (dx_plist = H5I_object(dxpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); - - if (!file_space) - file_space = dataset->space; - if (!mem_space) - mem_space = file_space; - nelmts = (*mem_space->select.get_npoints)(mem_space); - -#ifdef H5_HAVE_PARALLEL - /* Collect Parallel I/O information for possible later use */ - if (H5FD_MPIO==H5P_peek_hid_t(dx_plist,H5D_XFER_VFL_ID_NAME)) { - doing_mpio++; - xfer_mode=H5P_peek_unsigned(dx_plist, H5D_XFER_IO_XFER_MODE_NAME); - } /* end if */ - /* Collective access is not permissible without the MPIO or MPIPOSIX driver */ - if (doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE && - !(IS_H5FD_MPIO(dataset->ent.file) || IS_H5FD_MPIPOSIX(dataset->ent.file) || IS_H5FD_FPHDF5(dataset->ent.file))) - HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access for MPIO & MPIPOSIX drivers only"); - - /* Set the "parallel I/O possible" flag, for H5S_find() */ - if (H5S_mpi_opt_types_g && IS_H5FD_MPIO(dataset->ent.file)) { - /* Only collective write should call this since it eventually - * calls MPI_File_set_view which is a collective call. - * See H5S_mpio_spaces_xfer() for details. - */ - if (doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE) - sconv_flags |= H5S_CONV_PAR_IO_POSSIBLE; - } /* end if */ -#endif /*H5_HAVE_PARALLEL*/ - - /* Make certain that the number of elements in each selection is the same */ - if (nelmts!=(*file_space->select.get_npoints) (file_space)) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes"); - - /* Retrieve dataset properties */ - /* <none needed in the general case> */ - - /* If space hasn't been allocated and not using external storage, - * return fill value to buffer if fill time is upon allocation, or - * do nothing if fill time is never. If the dataset is compact and - * fill time is NEVER, there is no way to tell whether part of data - * has been overwritten. So just proceed in reading. - */ - if(nelmts > 0 && dataset->efl.nused==0 && dataset->layout.type!=H5D_COMPACT - && dataset->layout.addr==HADDR_UNDEF) { - H5O_fill_t fill; /* Fill value info */ - H5D_fill_time_t fill_time; /* When to write the fill values */ - H5D_fill_value_t fill_status; /* Whether/How the fill value is defined */ - - /* Retrieve dataset's fill-value properties */ - if(H5P_fill_value_defined(dc_plist, &fill_status)<0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined"); - if((fill_status==H5D_FILL_VALUE_DEFAULT || fill_status==H5D_FILL_VALUE_USER_DEFINED) - && H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,"can't retrieve fill value"); - if(H5P_get(dc_plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,"can't retrieve fill time"); - - /* Should be impossible, but check anyway... */ - if(fill_status == H5D_FILL_VALUE_UNDEFINED && fill_time == H5D_FILL_TIME_ALLOC) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "read failed: dataset doesn't exist, no data can be read"); - - /* If we're never going to fill this dataset, just leave the junk in the user's buffer */ - if(fill_time == H5D_FILL_TIME_NEVER) - HGOTO_DONE(SUCCEED); - - /* Go fill the user's selection with the dataset's fill value */ - if(H5D_fill(fill.buf,fill.type,buf,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 data type 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 data type conversion also - * turns off background preservation. - */ - if (NULL==(tpath=H5T_path_find(dataset->type, mem_type, NULL, NULL, dxpl_id))) { - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); - } else if (!H5T_IS_NOOP(tpath)) { - if ((src_id=H5I_register(H5I_DATATYPE, H5T_copy(dataset->type, H5T_COPY_ALL)))<0 || - (dst_id=H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL)))<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion"); - } /* end if */ - - /* Set the storage flags for the space conversion check */ - switch(dataset->layout.type) { - case H5D_COMPACT: - sconv_flags |= H5S_CONV_STORAGE_COMPACT; - break; - - case H5D_CONTIGUOUS: - sconv_flags |= H5S_CONV_STORAGE_CONTIGUOUS; - break; - - case H5D_CHUNKED: - sconv_flags |= H5S_CONV_STORAGE_CHUNKED; - break; - - default: - assert(0 && "Unhandled layout type!"); - } /* end switch */ - - /* Get dataspace functions */ - if (NULL==(sconv=H5S_find(mem_space, file_space, sconv_flags))) - HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert from file to memory data space"); - - /* - * If there is no type conversion then read directly into the - * application's buffer. This saves at least one mem-to-mem copy. - */ - if (H5T_IS_NOOP(tpath)) { -#ifdef H5S_DEBUG - H5_timer_begin(&timer); -#endif - /* Sanity check dataset, then read it */ - assert(dataset->layout.addr!=HADDR_UNDEF || dataset->efl.nused>0 || dataset->layout.type==H5D_COMPACT); - status = (sconv->read)(dataset->ent.file, &(dataset->layout), - dc_plist, &(dataset->efl), H5T_get_size(dataset->type), - file_space, mem_space, dxpl_id, buf/*out*/); -#ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[1].read_timer), &timer); - sconv->stats[1].read_nbytes += nelmts * H5T_get_size(dataset->type); - sconv->stats[1].read_ncalls++; -#endif - - /* Check return value from optimized read */ - if (status<0) { - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed"); - } else - /* direct xfer accomplished successfully */ - HGOTO_DONE(SUCCEED); - } /* end if */ - -#ifdef H5_HAVE_PARALLEL - /* The following may not handle a collective call correctly - * since it does not ensure all processes can handle the read - * request according to the MPI collective specification. - * Do the collective request via independent mode. - */ - if (doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE) { - /* Kludge: change the xfer_mode to independent, handle the request, - * then xfer_mode before return. - * Better way is to get a temporary data_xfer property with - * INDEPENDENT xfer_mode and pass it downwards. - */ - xfer_mode = H5FD_MPIO_INDEPENDENT; - if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); - xfer_mode_changed++; /* restore it before return */ -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - fprintf(H5DEBUG(D), - "H5D: Cannot handle this COLLECTIVE read request. Do it via INDEPENDENT calls\n"); -#endif - } /* end if */ -#endif /*H5_HAVE_PARALLEL*/ - /* - * This is the general case. - */ - - /* Compute element sizes and other parameters */ - src_type_size = H5T_get_size(dataset->type); - dst_type_size = H5T_get_size(mem_type); - target_size = H5P_peek_size_t(dx_plist,H5D_XFER_MAX_TEMP_BUF_NAME); - request_nelmts = target_size / MAX(src_type_size, dst_type_size); - - /* Figure out the strip mine size. */ - if ((*file_space->select.iter_init)(file_space, src_type_size, &file_iter)<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 ((*mem_space->select.iter_init)(mem_space, dst_type_size, &mem_iter)<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 ((*mem_space->select.iter_init)(mem_space, dst_type_size, &bkg_iter)<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 */ - - /* 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 (tpath->cdata.need_bkg) { - /* Retrieve the bkgr buffer property */ - if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_TYPE_NAME, &need_bkg)<0) - HGOTO_ERROR (H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer type"); - need_bkg = MAX(tpath->cdata.need_bkg, need_bkg); - } else { - need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ - } /* end else */ - if (NULL==(tconv_buf=H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME))) { - /* 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=H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))) { - /* Allocate background buffer */ - H5_CHECK_OVERFLOW((request_nelmts*dst_type_size),hsize_t,size_t); - if((bkg_buf=H5FL_BLK_MALLOC(type_conv,(size_t)(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((*file_space->select.iter_nelmts)(&file_iter)==(nelmts-smine_start)); - smine_nelmts = MIN(request_nelmts, (nelmts-smine_start)); - - /* - * Gather the data from disk into the data type 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 */ - assert(dataset->layout.addr!=HADDR_UNDEF || dataset->efl.nused>0 || dataset->layout.type==H5D_COMPACT); - n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), - dc_plist, &(dataset->efl), src_type_size, file_space, - &file_iter, smine_nelmts, dxpl_id, tconv_buf/*out*/); - -#ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[1].gath_timer), &timer); - sconv->stats[1].gath_nbytes += n * src_type_size; - sconv->stats[1].gath_ncalls++; -#endif - if (n!=smine_nelmts) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed"); - - if (need_bkg) { -#ifdef H5S_DEBUG - H5_timer_begin(&timer); -#endif - n = H5S_select_mgath(buf, dst_type_size, mem_space, &bkg_iter, - smine_nelmts, dxpl_id, bkg_buf/*out*/); -#ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[1].bkg_timer), &timer); - sconv->stats[1].bkg_nbytes += n * dst_type_size; - sconv->stats[1].bkg_ncalls++; -#endif - if (n!=smine_nelmts) - HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "mem gather failed"); - } /* end if */ - - /* - * Perform data type conversion. - */ - if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, 0, 0, tconv_buf, bkg_buf, dxpl_id)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); - - /* - * Scatter the data into memory. - */ -#ifdef H5S_DEBUG - H5_timer_begin(&timer); -#endif - status = H5S_select_mscat(tconv_buf, dst_type_size, mem_space, - &mem_iter, smine_nelmts, dxpl_id, buf/*out*/); -#ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[1].scat_timer), &timer); - sconv->stats[1].scat_nbytes += smine_nelmts * dst_type_size; - sconv->stats[1].scat_ncalls++; -#endif - if (status<0) - HGOTO_ERROR (H5E_DATASET, H5E_READERROR, FAIL, "scatter failed"); - - } /* end for */ - -done: -#ifdef H5_HAVE_PARALLEL - /* restore xfer_mode due to the kludge */ - if (doing_mpio && xfer_mode_changed) { -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - fprintf (H5DEBUG(D), "H5D: dx->xfer_mode was COLLECTIVE, restored to INDEPENDENT\n"); -#endif - xfer_mode = H5FD_MPIO_COLLECTIVE; - if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); - } /* end if */ -#endif /*H5_HAVE_PARALLEL*/ - /* Release selection iterators */ - if(file_iter_init) - (*file_space->select.iter_release)(&file_iter); - if(mem_iter_init) - (*mem_space->select.iter_release)(&mem_iter); - if(bkg_iter_init) - (*mem_space->select.iter_release)(&bkg_iter); - - if (src_id >= 0) - H5I_dec_ref(src_id); - if (dst_id >= 0) - H5I_dec_ref(dst_id); - assert(dx_plist); - if (tconv_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME)) - H5FL_BLK_FREE(type_conv,tconv_buf); - if (bkg_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME)) - H5FL_BLK_FREE(type_conv,bkg_buf); - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5D_read() */ - - -/*------------------------------------------------------------------------- - * Function: H5D_write - * - * Purpose: Writes (part of) a DATASET to a file from application memory - * BUF. See H5Dwrite() for complete details. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Thursday, December 4, 1997 - * - * Modifications: - * Robb Matzke, 9 Jun 1998 - * The data space is no longer cached in the dataset struct. - * - * rky 980918 - * Added must_convert to do non-optimized read when necessary. - * - * Quincey Koziol, 2 July 1999 - * Changed xfer_parms parameter to xfer plist parameter, so it could - * be passed to H5T_convert - * - * Albert Cheng, 2000-11-21 - * Added the code that when it detects it is not safe to process a - * COLLECTIVE write request without hanging, it changes it to - * INDEPENDENT calls. - * - * Albert Cheng, 2000-11-27 - * Changed to use the optimized MPIO transfer for Collective calls only. - * - * Raymond Lu, 2001-10-2 - * Changed the way to retrieve property for generic property list. - * - * Raymond Lu, 2002-2-26 - * For the new fill value design, space may not be allocated until - * this function is called. Allocate and initialize space if it - * hasn't been. - * - * QAK - 2002/04/02 - * Removed the must_convert parameter and move preconditions to - * H5S_<foo>_opt_possible() routine - * - *------------------------------------------------------------------------- - */ -static herr_t -H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, - const H5S_t *file_space, hid_t dxpl_id, const void *buf) -{ - hsize_t nelmts; /*total number of elmts */ - hsize_t smine_start; /*strip mine start loc */ - hsize_t n, smine_nelmts; /*elements per strip */ - uint8_t *tconv_buf = NULL; /*data type conv buffer */ - uint8_t *bkg_buf = NULL; /*background buffer */ - H5T_path_t *tpath = NULL; /*type conversion info */ - hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ - H5S_conv_t *sconv=NULL; /*space conversion funcs*/ - 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 */ - herr_t ret_value = SUCCEED; /*return value */ - herr_t status; /*function return status*/ - size_t src_type_size; /*size of source type */ - size_t dst_type_size; /*size of destination type*/ - size_t target_size; /*desired buffer size */ - hsize_t request_nelmts; /*requested strip mine */ - H5T_bkg_t need_bkg; /*type of background buf*/ -#ifdef H5_HAVE_PARALLEL - H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; /*xfer_mode for this request */ - hbool_t xfer_mode_changed=0; /*xfer_mode needs restore */ - hbool_t doing_mpio=0; /*This is an MPIO access */ -#endif /*H5_HAVE_PARALLEL*/ -#ifdef H5S_DEBUG - H5_timer_t timer; -#endif - H5P_genplist_t *dx_plist=NULL; /* Data transfer property list */ - H5P_genplist_t *dc_plist; /* Dataset creation roperty list */ - unsigned sconv_flags=0; /* Flags for the space conversion */ - - FUNC_ENTER_NOAPI(H5D_write, FAIL); - - /* check args */ - assert(dataset && dataset->ent.file); - assert(mem_type); - assert(H5I_GENPROP_LST==H5I_get_type(dxpl_id)); - assert(buf); - - /* Get the dataset's creation property list */ - if (NULL == (dc_plist = H5I_object(dataset->dcpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); - - /* Get the dataset transfer property list */ - if (NULL == (dx_plist = H5I_object(dxpl_id))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); - - if (!file_space) - file_space = dataset->space; - if (!mem_space) - mem_space = file_space; - nelmts = (*mem_space->select.get_npoints)(mem_space); - - /* If MPIO, MPIPOSIX, or FPHDF5 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 ( (IS_H5FD_MPIO(dataset->ent.file) || IS_H5FD_MPIPOSIX(dataset->ent.file) || IS_H5FD_FPHDF5(dataset->ent.file)) && H5T_get_class(mem_type)==H5T_VLEN) - HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Parallel IO does not support writing VL datatypes yet"); - /* If MPIO, MPIPOSIX, or FPHDF5 is used, no dataset region reference 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 ((IS_H5FD_MPIO(dataset->ent.file) || IS_H5FD_MPIPOSIX(dataset->ent.file) || IS_H5FD_FPHDF5(dataset->ent.file)) && - H5T_get_class(mem_type)==H5T_REFERENCE && - H5T_get_ref_type(mem_type)==H5R_DATASET_REGION) - HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Parallel IO does not support writing region reference datatypes yet"); - - if (0==(H5F_get_intent(dataset->ent.file) & H5F_ACC_RDWR)) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "no write intent on file"); - -#ifdef H5_HAVE_PARALLEL - /* Collect Parallel I/O information for possible later use */ - if (H5FD_MPIO==H5P_peek_hid_t(dx_plist,H5D_XFER_VFL_ID_NAME)) { - doing_mpio++; - xfer_mode=H5P_peek_unsigned(dx_plist, H5D_XFER_IO_XFER_MODE_NAME); - } /* end if */ - - /* Collective access is not permissible without the MPIO or MPIPOSIX driver */ - if (doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE && - !(IS_H5FD_MPIO(dataset->ent.file) || IS_H5FD_MPIPOSIX(dataset->ent.file) || IS_H5FD_FPHDF5(dataset->ent.file))) - HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access for MPIO driver only"); - - /* If dataset is compact, collective access is only allowed when file space - * selection is H5S_ALL */ - if(doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE - && dataset->layout.type==H5D_COMPACT) { - if(file_space->select.type != H5S_SEL_ALL) - HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access to compact dataset doesn't support partial access"); - } - - /* Set the "parallel I/O possible" flag, for H5S_find() */ - if (H5S_mpi_opt_types_g && IS_H5FD_MPIO(dataset->ent.file)) { - /* Only collective write should call this since it eventually - * calls MPI_File_set_view which is a collective call. - * See H5S_mpio_spaces_xfer() for details. - */ - if (doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE) - sconv_flags |= H5S_CONV_PAR_IO_POSSIBLE; - } /* end if */ -#endif /*H5_HAVE_PARALLEL*/ - - /* Make certain that the number of elements in each selection is the same */ - if (nelmts!=(*file_space->select.get_npoints) (file_space)) - HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes"); - - /* Retrieve dataset properties */ - /* <none needed currently> */ - - /* Allocate data space and initialize it if it hasn't been. */ - if(nelmts > 0 && dataset->layout.type!=H5D_COMPACT && - dataset->layout.addr==HADDR_UNDEF) { - hssize_t file_nelmts; /* Number of elements in file dataset's dataspace */ - - /* Get the number of elements in file dataset's dataspace */ - if((file_nelmts=H5S_get_simple_extent_npoints(file_space))<0) - HGOTO_ERROR (H5E_DATASET, H5E_BADVALUE, FAIL, "can't retrieve number of elements in file dataset"); - - /* Allocate storage */ - if(H5D_alloc_storage(dataset->ent.file,dxpl_id,dataset,H5D_ALLOC_WRITE, TRUE, (hbool_t)((hsize_t)file_nelmts==nelmts ? TRUE : FALSE))<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 data type 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 data type conversion also - * turns off background preservation. - */ - if (NULL==(tpath=H5T_path_find(mem_type, dataset->type, NULL, NULL, dxpl_id))) { - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); - } else if (!H5T_IS_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(dataset->type, H5T_COPY_ALL)))<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion"); - } /* end if */ - - /* Set the storage flags for the space conversion check */ - switch(dataset->layout.type) { - case H5D_COMPACT: - sconv_flags |= H5S_CONV_STORAGE_COMPACT; - break; - - case H5D_CONTIGUOUS: - sconv_flags |= H5S_CONV_STORAGE_CONTIGUOUS; - break; - - case H5D_CHUNKED: - sconv_flags |= H5S_CONV_STORAGE_CHUNKED; - break; - - default: - assert(0 && "Unhandled layout type!"); - } /* end switch */ - - /* Get dataspace functions */ - if (NULL==(sconv=H5S_find(mem_space, file_space, sconv_flags))) - HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert from memory to file data space"); - - /* - * If there is no type conversion then write directly from the - * application's buffer. This saves at least one mem-to-mem copy. - */ - if (H5T_IS_NOOP(tpath)) { -#ifdef H5S_DEBUG - H5_timer_begin(&timer); -#endif - status = (sconv->write)(dataset->ent.file, &(dataset->layout), - dc_plist, &(dataset->efl), H5T_get_size(dataset->type), - file_space, mem_space, dxpl_id, buf); -#ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[0].write_timer), &timer); - sconv->stats[0].write_nbytes += nelmts * H5T_get_size(mem_type); - sconv->stats[0].write_ncalls++; -#endif - - /* Check return value from optimized write */ - if (status<0) { - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed"); - } else - /* direct xfer accomplished successfully */ - HGOTO_DONE(SUCCEED); - } /* end if */ - -#ifdef H5_HAVE_PARALLEL - /* The following may not handle a collective call correctly - * since it does not ensure all processes can handle the write - * request according to the MPI collective specification. - * Do the collective request via independent mode. - */ - if (doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE) { - /* Kludge: change the xfer_mode to independent, handle the request, - * then xfer_mode before return. - * Better way is to get a temporary data_xfer property with - * INDEPENDENT xfer_mode and pass it downwards. - */ - xfer_mode = H5FD_MPIO_INDEPENDENT; - if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); - xfer_mode_changed++; /* restore it before return */ -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - fprintf(H5DEBUG(D), "H5D: Cannot handle this COLLECTIVE write request. Do it via INDEPENDENT calls\n"); -#endif - } /* end if */ -#endif /*H5_HAVE_PARALLEL*/ - /* - * This is the general case. - */ - - /* Compute element sizes and other parameters */ - src_type_size = H5T_get_size(mem_type); - dst_type_size = H5T_get_size(dataset->type); - target_size = H5P_peek_size_t(dx_plist,H5D_XFER_MAX_TEMP_BUF_NAME); - request_nelmts = target_size / MAX (src_type_size, dst_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 ((*file_space->select.iter_init)(file_space, dst_type_size, &file_iter)<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 ((*mem_space->select.iter_init)(mem_space, src_type_size, &mem_iter)<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 ((*file_space->select.iter_init)(file_space, dst_type_size, &bkg_iter)<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 (tpath->cdata.need_bkg) { - /* Retrieve the bkgr buffer property */ - if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_TYPE_NAME, &need_bkg)<0) - HGOTO_ERROR (H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer type"); - need_bkg = MAX (tpath->cdata.need_bkg, need_bkg); - } else if(H5T_detect_class(dataset->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 { - need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ - } /* end else */ - if (NULL==(tconv_buf=H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME))) { - /* 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=H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))) { - /* Allocate background buffer */ - H5_CHECK_OVERFLOW((request_nelmts*dst_type_size),hsize_t,size_t); - if((bkg_buf=H5FL_BLK_CALLOC(type_conv,(size_t)(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((*file_space->select.iter_nelmts)(&file_iter)==(nelmts-smine_start)); - smine_nelmts = MIN(request_nelmts, (nelmts-smine_start)); - - /* - * Gather data from application buffer into the data type conversion - * buffer. Also gather data from the file into the background buffer - * if necessary. - */ -#ifdef H5S_DEBUG - H5_timer_begin(&timer); -#endif - n = H5S_select_mgath(buf, src_type_size, mem_space, &mem_iter, - smine_nelmts, dxpl_id, tconv_buf/*out*/); -#ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[0].gath_timer), &timer); - sconv->stats[0].gath_nbytes += n * src_type_size; - sconv->stats[0].gath_ncalls++; -#endif - if (n!=smine_nelmts) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed"); - - if (need_bkg) { -#ifdef H5S_DEBUG - H5_timer_begin(&timer); -#endif - n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), - dc_plist, &(dataset->efl), dst_type_size, file_space, - &bkg_iter, smine_nelmts, dxpl_id, bkg_buf/*out*/); - -#ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[0].bkg_timer), &timer); - sconv->stats[0].bkg_nbytes += n * dst_type_size; - sconv->stats[0].bkg_ncalls++; -#endif - if (n!=smine_nelmts) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed"); - } /* end if */ - - /* - * Perform data type conversion. - */ - if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, 0, 0, tconv_buf, bkg_buf, dxpl_id)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); - - /* - * Scatter the data out to the file. - */ -#ifdef H5S_DEBUG - H5_timer_begin(&timer); -#endif - status = H5S_select_fscat(dataset->ent.file, &(dataset->layout), - dc_plist, &(dataset->efl), dst_type_size, file_space, &file_iter, - smine_nelmts, dxpl_id, tconv_buf); - -#ifdef H5S_DEBUG - H5_timer_end(&(sconv->stats[0].scat_timer), &timer); - sconv->stats[0].scat_nbytes += smine_nelmts * dst_type_size; - sconv->stats[0].scat_ncalls++; -#endif - if (status<0) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "scatter failed"); - } /* end for */ - - /* - * Update modification time. We have to do this explicitly because - * writing to a dataset doesn't necessarily change the object header. - */ - if (H5O_touch(&(dataset->ent), FALSE, dxpl_id)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update modification time"); - -done: -#ifdef H5_HAVE_PARALLEL - /* restore xfer_mode due to the kludge */ - if (doing_mpio && xfer_mode_changed) { -#ifdef H5D_DEBUG - if (H5DEBUG(D)) - fprintf (H5DEBUG(D), "H5D: dx->xfer_mode was COLLECTIVE, restored to INDEPENDENT\n"); -#endif - xfer_mode = H5FD_MPIO_COLLECTIVE; - if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); - } /* end if */ -#endif /*H5_HAVE_PARALLEL*/ - /* Release selection iterators */ - if(file_iter_init) - (*file_space->select.iter_release)(&file_iter); - if(mem_iter_init) - (*mem_space->select.iter_release)(&mem_iter); - if(bkg_iter_init) - (*file_space->select.iter_release)(&bkg_iter); - - if (src_id >= 0) - H5I_dec_ref(src_id); - if (dst_id >= 0) - H5I_dec_ref(dst_id); - assert(dx_plist); - if (tconv_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME)) - H5FL_BLK_FREE(type_conv,tconv_buf); - if (bkg_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME)) - H5FL_BLK_FREE(type_conv,bkg_buf); - - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5D_write() */ - - -/*------------------------------------------------------------------------- * Function: H5D_extend * * Purpose: Increases the size of a dataset. @@ -3426,14 +2372,12 @@ H5D_get_file (const H5D_t *dset) * *------------------------------------------------------------------------- */ -static herr_t +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) { struct H5O_layout_t *layout; /* The dataset's layout information */ - hsize_t nbytes; /* The number of bytes in the dataset */ unsigned space_allocated=0; /* Flag to indicate that space was allocated */ - unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOINIT(H5D_alloc_storage); @@ -3454,11 +2398,8 @@ H5D_alloc_storage (H5F_t *f, hid_t dxpl_id, H5D_t *dset/*in,out*/, H5D_time_allo case H5D_CONTIGUOUS: if(layout->addr==HADDR_UNDEF) { /* Reserve space in the file for the entire array */ - for (u=0, nbytes=1; u<layout->ndims; u++) - nbytes *= layout->dim[u]; - assert (nbytes>0); - if (HADDR_UNDEF==(layout->addr=H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, nbytes))) - HGOTO_ERROR (H5E_IO, H5E_NOSPACE, FAIL, "unable to reserve file space"); + if (H5F_contig_create (f, dxpl_id, layout/*out*/)<0) + HGOTO_ERROR (H5E_IO, H5E_CANTINIT, FAIL, "unable to initialize contiguous storage"); /* Indicate that we allocated space */ space_allocated=1; @@ -3587,7 +2528,7 @@ H5D_init_storage(H5D_t *dset, hbool_t full_overwrite, hid_t dxpl_id) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); if (H5F_contig_fill(dset->ent.file, dxpl_id, &(dset->layout), - plist, &(dset->efl), space, &dset->fill, H5T_get_size(dset->type))<0) + plist, space, &dset->fill, H5T_get_size(dset->type))<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to allocate all chunks of dataset"); } /* end if */ break; @@ -4148,148 +3089,6 @@ done: } /* end H5Dvlen_get_buf_size() */ -/*-------------------------------------------------------------------------- - NAME - H5D_fill - PURPOSE - Fill a selection in memory with a value (internal version) - USAGE - herr_t H5Dfill(fill, fill_type, buf, buf_type, space) - const void *fill; IN: Pointer to fill value to use - H5T_t *fill_type; IN: Datatype of the fill value - void *buf; IN/OUT: Memory buffer to fill selection within - H5T_t *buf_type; IN: Datatype of the elements in buffer - H5S_t *space; IN: Dataspace describing memory buffer & - containing selection to use. - RETURNS - Non-negative on success/Negative on failure. - DESCRIPTION - Use the selection in the dataspace to fill elements in a memory buffer. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - If "fill" parameter is NULL, use all zeros as fill value. If "fill_type" - parameter is NULL, use "buf_type" for the fill value datatype. - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -static 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) -{ - H5T_path_t *tpath = NULL; /* Conversion information*/ - uint8_t *tconv_buf = NULL; /* Data type conv buffer */ - uint8_t *bkg_buf = NULL; /* Temp conversion buffer */ - hid_t src_id = -1, dst_id = -1; /* Temporary type IDs */ - size_t src_type_size; /* Size of source type */ - size_t dst_type_size; /* Size of destination type*/ - size_t buf_size; /* Desired buffer size */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOINIT(H5D_fill); - - /* Check args */ - assert(buf); - assert(buf_type); - assert(space); - - /* Check for "default" fill value */ - if(fill_type==NULL) - fill_type=buf_type; - - /* Get the memory and file datatype sizes */ - src_type_size = H5T_get_size(fill_type); - dst_type_size = H5T_get_size(buf_type); - - /* Get the maximum buffer size needed and allocate it */ - buf_size=MAX(src_type_size,dst_type_size); - if (NULL==(tconv_buf = H5FL_BLK_MALLOC(type_elem,buf_size)) || NULL==(bkg_buf = H5FL_BLK_CALLOC(type_elem,buf_size))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - - /* Copy the user's data into the buffer for conversion */ - if(fill==NULL) - HDmemset(tconv_buf,0,src_type_size); - else - HDmemcpy(tconv_buf,fill,src_type_size); - - /* Convert memory buffer into disk buffer */ - /* Set up type conversion function */ - if (NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL, dxpl_id))) { - HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); - } else if (!H5T_IS_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(buf_type, H5T_COPY_ALL)))<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion"); - } - - /* Perform data type conversion */ - if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, tconv_buf, bkg_buf, dxpl_id)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed"); - - /* Fill the selection in the memory buffer */ - if(H5S_select_fill(tconv_buf, dst_type_size, space, buf)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed"); - -done: - if (tconv_buf) - H5FL_BLK_FREE(type_elem,tconv_buf); - if (bkg_buf) - H5FL_BLK_FREE(type_elem,bkg_buf); - FUNC_LEAVE_NOAPI(ret_value); -} /* H5D_fill() */ - - -/*-------------------------------------------------------------------------- - NAME - H5Dfill - PURPOSE - Fill a selection in memory with a value - USAGE - herr_t H5Dfill(fill, fill_type, space, buf, buf_type) - const void *fill; IN: Pointer to fill value to use - hid_t fill_type_id; IN: Datatype of the fill value - void *buf; IN/OUT: Memory buffer to fill selection within - hid_t buf_type_id; IN: Datatype of the elements in buffer - hid_t space_id; IN: Dataspace describing memory buffer & - containing selection to use. - RETURNS - Non-negative on success/Negative on failure. - DESCRIPTION - Use the selection in the dataspace to fill elements in a memory buffer. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - If "fill" parameter is NULL, use all zeros as fill value - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -herr_t -H5Dfill(const void *fill, hid_t fill_type_id, void *buf, hid_t buf_type_id, hid_t space_id) -{ - H5S_t *space; /* Dataspace */ - H5T_t *fill_type; /* Fill-value datatype */ - H5T_t *buf_type; /* Buffer datatype */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(H5Dfill, FAIL); - H5TRACE5("e","xixii",fill,fill_type_id,buf,buf_type_id,space_id); - - /* Check args */ - if (buf==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer"); - if (NULL == (space=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))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype"); - if (NULL == (buf_type=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 */ - if(H5D_fill(fill,fill_type,buf,buf_type,space, H5AC_dxpl_id)<0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed"); - -done: - FUNC_LEAVE_API(ret_value); -} /* H5Dfill() */ - - /*------------------------------------------------------------------------- * Function: H5Dset_extent * diff --git a/src/H5Dcompact.c b/src/H5Dcompact.c index 1f77d92..829ba63 100644 --- a/src/H5Dcompact.c +++ b/src/H5Dcompact.c @@ -28,60 +28,55 @@ #include "H5Oprivate.h" #include "H5FDprivate.h" /*file driver */ #include "H5FLprivate.h" /*Free Lists */ +#include "H5Vprivate.h" /* Vector and array functions */ /* Interface initialization */ #define PABLO_MASK H5Fcompact_mask static int interface_initialize_g = 0; #define INTERFACE_INIT NULL + /*------------------------------------------------------------------------- - * Function: H5F_compact_readv - * + * Function: H5F_compact_readvv + * * Purpose: Reads some data vectors from a dataset into a buffer. * The data is in compact dataset. The address is relative * to the beginning address of the dataset. The offsets and * sequence lengths are in bytes. - * + * * Return: Non-negative on success/Negative on failure - * - * Programmer: Raymond Lu - * August 5, 2002 - * - * Notes: - * Offsets in the sequences must be monotonically increasing * + * Programmer: Quincey Koziol + * May 7, 2003 + * + * Notes: + * Offsets in the sequences must be monotonically increasing + * * Modifications: - * + * *------------------------------------------------------------------------- */ -herr_t -H5F_compact_readv(H5F_t UNUSED *f, const H5O_layout_t *layout, size_t nseq, - size_t size_arr[], hsize_t offset_arr[], - hid_t UNUSED dxpl_id, void *_buf/*out*/) +ssize_t +H5F_compact_readvv(H5F_t UNUSED *f, const H5O_layout_t *layout, + 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[], + hid_t UNUSED dxpl_id, void *buf) { - unsigned char *buf=(unsigned char *)_buf; - size_t size; - haddr_t offset; - unsigned u; - herr_t ret_value=SUCCEED; + ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5F_compact_readv, FAIL); + FUNC_ENTER_NOAPI(H5F_compact_readvv, FAIL); - for(u=0; u<nseq; u++) { - size=size_arr[u]; - offset=offset_arr[u]; - if(size > 0) { - HDmemcpy(buf, (unsigned char*)layout->buf+offset, size); - buf +=size; - } - } + /* 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,layout->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: +done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_compact_readv() */ +} /* end H5F_compact_readvv() */ + /*------------------------------------------------------------------------- - * Function: H5F_compact_writev + * Function: H5F_compact_writevv * * Purpose: Writes some data vectors from a dataset into a buffer. * The data is in compact dataset. The address is relative @@ -93,8 +88,8 @@ done: * * Return: Non-negative on success/Negative on failure * - * Programmer: Raymond Lu - * August 5, 2002 + * Programmer: Quincey Koziol + * May 2, 2003 * * Notes: * Offsets in the sequences must be monotonically increasing @@ -103,30 +98,23 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5F_compact_writev(H5F_t UNUSED *f, H5O_layout_t *layout, size_t nseq, - size_t size_arr[], hsize_t offset_arr[], - hid_t UNUSED dxpl_id, const void *_buf) +ssize_t +H5F_compact_writevv(H5F_t UNUSED *f, H5O_layout_t *layout, + 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[], + hid_t UNUSED dxpl_id, const void *buf) { - const unsigned char *buf=(const unsigned char *)_buf; - size_t size; - haddr_t offset; - unsigned u; - herr_t ret_value=SUCCEED; + ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5F_compact_writev, FAIL); + FUNC_ENTER_NOAPI(H5F_compact_writevv, FAIL); - for(u=0; u<nseq; u++) { - size=size_arr[u]; - offset=offset_arr[u]; - if(size > 0) { - HDmemcpy((unsigned char*)layout->buf+offset, buf, size); - buf += size; - } - } + /* Use the vectorized memory copy routine to do actual work */ + if((ret_value=H5V_memcpyvv(layout->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) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed"); layout->dirty = TRUE; done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_compact_writev */ +} /* end H5F_compact_writevv() */ + diff --git a/src/H5Dcontig.c b/src/H5Dcontig.c index 2593d83..3a14175 100644 --- a/src/H5Dcontig.c +++ b/src/H5Dcontig.c @@ -18,9 +18,8 @@ * * Purpose: * Contiguous dataset I/O functions. These routines are similar to - * the H5F_istore_* routines and really only abstract away dealing - * with the data sieve buffer from the H5F_arr_read/write and - * H5F_seg_read/write. + * the H5F_istore_* routines and really only an abstract way of dealing + * with the data sieve buffer from H5F_seg_read/write. */ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ @@ -34,6 +33,7 @@ #include "H5MFprivate.h" /*file memory management */ #include "H5Oprivate.h" /* Object headers */ #include "H5Pprivate.h" /* Property lists */ +#include "H5Sprivate.h" /* Dataspace functions */ #include "H5Vprivate.h" /* Vector and array functions */ /* MPIO, MPIPOSIX, & FPHDF5 drivers needed for special checks */ @@ -41,6 +41,11 @@ #include "H5FDmpio.h" #include "H5FDmpiposix.h" +/* Private prototypes */ +static herr_t +H5F_contig_write(H5F_t *f, hsize_t max_data, haddr_t addr, + const size_t size, hid_t dxpl_id, const void *buf); + /* Interface initialization */ #define PABLO_MASK H5Fcontig_mask static int interface_initialize_g = 0; @@ -57,6 +62,48 @@ H5FL_BLK_DEFINE_STATIC(zero_fill); /*------------------------------------------------------------------------- + * Function: H5F_contig_create + * + * Purpose: Allocate file space for a contiguously stored dataset + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * April 19, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_contig_create(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout) +{ + hsize_t size; /* Size of contiguous block of data */ + unsigned u; /* Local index variable */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_contig_create, FAIL); + + /* check args */ + assert(f); + assert(layout); + + /* Compute size */ + size=layout->dim[0]; + for (u = 1; u < layout->ndims; u++) + size *= layout->dim[u]; + assert (size>0); + + /* Allocate space for the contiguous data */ + if (HADDR_UNDEF==(layout->addr=H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, size))) + HGOTO_ERROR (H5E_IO, H5E_NOSPACE, FAIL, "unable to reserve file space"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5F_contig_create */ + + +/*------------------------------------------------------------------------- * Function: H5F_contig_fill * * Purpose: Write fill values to a contiguously stored dataset. @@ -75,8 +122,7 @@ H5FL_BLK_DEFINE_STATIC(zero_fill); */ herr_t H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, - const struct H5S_t *space, + struct H5P_genplist_t *dc_plist, const struct H5S_t *space, const struct H5O_fill_t *fill, size_t elmt_size) { hssize_t snpoints; /* Number of points in space (for error checking) */ @@ -84,7 +130,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, size_t ptsperbuf; /* Maximum # of points which fit in the buffer */ size_t bufsize=64*1024; /* Size of buffer to write */ size_t size; /* Current # of points to write */ - hsize_t addr; /* Offset in dataset */ + haddr_t addr; /* Offset of dataset */ void *buf = NULL; /* Buffer for fill value writing */ #ifdef H5_HAVE_PARALLEL MPI_Comm mpi_comm=MPI_COMM_NULL; /* MPI communicator for file */ @@ -173,8 +219,8 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, * this quite efficiently by making sure we copy the fill value * in relatively large pieces. */ - ptsperbuf = MAX(1, bufsize/elmt_size); - bufsize = ptsperbuf*elmt_size; + ptsperbuf = MAX(1, bufsize/elmt_size); + bufsize = ptsperbuf*elmt_size; /* Fill the buffer with the user's fill value */ if(fill->buf) { @@ -207,7 +253,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, } /* end else */ /* Start at the beginning of the dataset */ - addr = 0; + addr = layout->addr; /* Loop through writing the fill value to the dataset */ while (npoints>0) { @@ -218,8 +264,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, if(using_mpi) { /* Round-robin write the chunks out from only one process */ if(mpi_round==mpi_rank) { - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space, - elmt_size, size, addr, buf)<0) + if (H5F_contig_write(f, size, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset"); } /* end if */ ++mpi_round; @@ -230,8 +275,8 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, } /* end if */ else { #endif /* H5_HAVE_PARALLEL */ - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space, - elmt_size, size, addr, buf)<0) + H5_CHECK_OVERFLOW(size,size_t,hsize_t); + if (H5F_contig_write(f, (hsize_t)size, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset"); #ifdef H5_HAVE_PARALLEL } /* end else */ @@ -314,44 +359,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_contig_read - * - * Purpose: Reads some data from a dataset 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: Quincey Koziol - * Thursday, September 28, 2000 - * - * Modifications: - * Re-written in terms of the new readv call, QAK, 7/7/01 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_contig_read(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr, - size_t size, hid_t dxpl_id, void *buf/*out*/) -{ - hsize_t offset=0; /* Offset for vector call */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_contig_read, FAIL); - - /* Check args */ - assert(f); - assert(buf); - - if (H5F_contig_readv(f, max_data, type, addr, 1, &size, &offset, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vector read failed"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_contig_read() */ - - -/*------------------------------------------------------------------------- * Function: H5F_contig_write * * Purpose: Writes some data from a dataset into a buffer. @@ -364,23 +371,28 @@ done: * Thursday, September 28, 2000 * * Modifications: - * Re-written in terms of the new readv call, QAK, 7/7/01 + * Re-written in terms of the new writevv call, QAK, 5/7/03 * *------------------------------------------------------------------------- */ -herr_t -H5F_contig_write(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr, size_t size, - hid_t dxpl_id, const void *buf) +static herr_t +H5F_contig_write(H5F_t *f, hsize_t max_data, haddr_t addr, + const size_t size, hid_t dxpl_id, const void *buf) { - hsize_t offset=0; /* Offset for vector call */ - herr_t ret_value=SUCCEED; /* Return value */ + hsize_t dset_off=0; /* Offset in dataset */ + hsize_t mem_off=0; /* Offset in memory */ + size_t dset_len=size; /* Length in dataset */ + size_t mem_len=size; /* Length in memory */ + size_t mem_curr_seq=0; /* "Current sequence" in memory */ + size_t dset_curr_seq=0; /* "Current sequence" in dataset */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_contig_write, FAIL); assert (f); assert (buf); - if (H5F_contig_writev(f, max_data, type, addr, 1, &size, &offset, dxpl_id, buf)<0) + if (H5F_contig_writevv(f, max_data, addr, 1, &dset_curr_seq, &dset_len, &dset_off, 1, &mem_curr_seq, &mem_len, &mem_off, dxpl_id, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed"); done: @@ -389,7 +401,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_contig_readv + * Function: H5F_contig_readvv * * Purpose: Reads some data vectors from a dataset into a buffer. * The data is contiguous. The address is the start of the dataset, @@ -409,9 +421,10 @@ done: *------------------------------------------------------------------------- */ herr_t -H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, - size_t nseq, size_t size_arr[], hsize_t offset_arr[], hid_t dxpl_id, - void *_buf/*out*/) +H5F_contig_readvv(H5F_t *f, hsize_t _max_data, haddr_t _addr, + 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[], + hid_t dxpl_id, void *_buf) { unsigned char *buf=(unsigned char *)_buf; /* Pointer to buffer to fill */ haddr_t abs_eoa; /* Absolute end of file address */ @@ -420,18 +433,10 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, hsize_t max_data; /* Actual maximum size of data to cache */ size_t size; /* Size of sequence in bytes */ size_t u; /* Counting variable */ -#ifndef SLOW_WAY - size_t max_seq; /* Maximum sequence to copy */ - haddr_t temp_end; /* Temporary end of buffer variable */ - size_t max_search; /* Maximum number of sequences to search */ - size_t mask; /* Bit mask */ - int bit_loc; /* Bit location of the leftmost '1' in max_search */ - size_t *size_arr_p; /* Pointer into the size array */ - hsize_t *offset_arr_p; /* Pointer into the offset array */ -#endif /* SLOW_WAY */ - herr_t ret_value=SUCCEED; /* Return value */ + size_t v; /* Counting variable */ + ssize_t ret_value=0; /* Return value */ - FUNC_ENTER_NOAPI(H5F_contig_readv, FAIL); + FUNC_ENTER_NOAPI(H5F_contig_readvv, FAIL); /* Check args */ assert(f); @@ -439,325 +444,143 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, /* Check if data sieving is enabled */ if(f->shared->lf->feature_flags&H5FD_FEAT_DATA_SIEVE) { + haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */ + haddr_t contig_end; /* End locations of block to write */ + size_t sieve_size; /* size of sieve buffer */ + + /* Set offsets in sequence lists */ + u=*dset_curr_seq; + v=*mem_curr_seq; + + /* No data sieve buffer yet, go allocate one */ + if(f->shared->sieve_buf==NULL) { + /* Choose smallest buffer to write */ + if(mem_len_arr[v]<dset_len_arr[u]) + size=mem_len_arr[v]; + else + size=dset_len_arr[u]; + + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (unsigned char *)_buf + mem_offset_arr[v]; + + /* Set up the buffer parameters */ + max_data=_max_data-dset_offset_arr[u]; + + /* Check if we can actually hold the I/O request in the sieve buffer */ + if(size>f->shared->sieve_buf_size) { + if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + } /* end if */ + else { + /* Allocate room for the data sieve buffer */ + if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - /* Outer loop, guarantees working through all the sequences */ - for(u=0; u<nseq; ) { - - /* Try reading from the data sieve buffer */ - if(f->shared->sieve_buf) { - haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */ - haddr_t contig_end; /* End locations of block to write */ - size_t sieve_size; /* size of sieve buffer */ - - /* Stash local copies of these value */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - /* Next-outer loop works through sequences as fast as possible */ - for(; u<nseq; ) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; - - /* Compute end of sequence to retrieve */ - 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=f->shared->sieve_buf+(_addr-sieve_start); - unsigned char *temp_sieve_buf; - haddr_t temp_addr=_addr-1; /* Temporary address */ - -#ifdef SLOW_WAY - /* Retrieve all the sequences out of the current sieve buffer */ - while(contig_end<sieve_end) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+offset_arr[u]; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,size_arr[u]); - - /* Increment offset in buffer */ - buf += size_arr[u]; - - /* Increment sequence number, check for finished with sequences */ - if((++u) >= nseq) - break; - - /* Re-compute end of sequence to retrieve */ - contig_end=temp_addr+offset_arr[u]+size_arr[u]; - } /* end while */ -#else /* SLOW_WAY */ - /* Find log2(n) where n is the number of elements to search */ - - /* Set initial parameters */ - mask=(size_t)0xff<<((sizeof(size_t)-1)*8); /* Get a mask for the leftmost byte */ - max_search=((nseq-1)-u)+1; /* Compute 'n' for the log2 */ - assert(max_search>0); /* Sanity check */ - bit_loc=(sizeof(size_t)*8)-1; /* Initial bit location */ - - /* Search for the first byte with a bit set */ - while((max_search & mask)==0) { - mask>>=8; - bit_loc-=8; - } /* end while */ - - /* Switch to searching for a bit */ - mask=1<<bit_loc; - while((max_search & mask)==0) { - mask>>=1; - bit_loc--; - } /* end while */ - - /* location of the leftmost bit, plus 1, is log2(n) */ - max_seq=bit_loc+1; - - /* Don't walk off the array */ - max_seq=MIN(u+max_seq,nseq-1); - - /* Determine if a linear search is faster than a binary search */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - if(temp_end>=sieve_end) { - /* Linear search is faster */ - - /* Set the initial search values */ - max_seq=u; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Search for the first sequence ending greater than the sieve buffer end */ - while(temp_end<sieve_end) { - if(++max_seq>=nseq) - break; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - } /* end while */ - - /* Adjust back one element */ - max_seq--; - - } /* end if */ - else { - size_t lo,hi; /* Low and high bounds for binary search */ - unsigned found=0; /* Flag to indicate bounds have been found */ - - /* Binary search is faster */ - - /* Find the value 'u' which will be beyond the end of the sieve buffer */ - lo=u; - hi=nseq-1; - max_seq=(lo+hi)/2; - while(!found) { - /* Get the address of the end of sequence for the 'max_seq' position */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Current high bound is too large */ - if(temp_end>=sieve_end) { - if((lo+1)<hi) { - hi=max_seq; - max_seq=(lo+hi)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end if */ - /* Current low bound is too small */ - else { - if((lo+1)<hi) { - lo=max_seq; - max_seq=(lo+hi+1)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end else */ - } /* end while */ - - /* Check for non-exact match */ - if(lo!=hi) { - temp_end=temp_addr+offset_arr[hi]+size_arr[hi]; - if(temp_end<sieve_end) - max_seq=hi; - else - max_seq=lo; - } /* end if */ - } /* end else */ - - /* Set the pointers to the correct locations in the offset & size arrays */ - size_arr_p=&size_arr[u]; - offset_arr_p=&offset_arr[u]; - -#ifdef NO_DUFFS_DEVICE - /* Retrieve all the sequences out of the current sieve buffer */ - while(u<=max_seq) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - } /* end while */ -#else /* NO_DUFFS_DEVICE */ -{ - size_t seq_count; - - seq_count=(max_seq-u)+1; - switch (seq_count % 4) { - case 0: - do - { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - case 3: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - case 2: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - case 1: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - } while (u<=max_seq); - } /* end switch */ - -} -#endif /* NO_DUFFS_DEVICE */ -#endif /* SLOW_WAY */ - } /* end if */ - /* Entire request is not within this data sieve buffer */ - else { - /* Check if we can actually hold the I/O request in the sieve buffer */ - if(size>f->shared->sieve_buf_size) { - /* Check for any overlap with the current sieve buffer */ - if((sieve_start>=addr && sieve_start<(contig_end+1)) - || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { - /* Flush the sieve buffer, if it's dirty */ - if(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - } /* end if */ - - /* Read directly into the user's buffer */ - if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - } /* end if */ - /* Element size fits within the buffer size */ - else { - /* Flush the sieve buffer if it's dirty */ - if(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - - /* Determine the new sieve buffer size & location */ - f->shared->sieve_loc=addr; - - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); + /* Determine the new sieve buffer size & location */ + f->shared->sieve_loc=addr; - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-f->shared->base_addr; + /* Make certain we don't read off the end of the file */ + if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - /* Only need this when resizing sieve buffer */ - max_data=_max_data-offset_arr[u]; + /* Adjust absolute EOA address to relative EOA address */ + rel_eoa=abs_eoa-f->shared->base_addr; - /* Compute the size of the sieve buffer */ - /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ - H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); + /* Compute the size of the sieve buffer */ + H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - /* Update local copies of sieve information */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->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,f->shared->sieve_buf,size); - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; + } /* end else */ - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(buf,f->shared->sieve_buf,size); - } /* end else */ + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) + u++; - /* Increment sequence number */ - u++; - } /* end else */ - } /* end for */ + /* Increment number of bytes copied */ + ret_value+=size; + } /* end if */ + + /* Stash local copies of these value */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; + + /* Works through sequences as fast as possible */ + 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]; + else + size=dset_len_arr[u]; + + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (unsigned char *)_buf + mem_offset_arr[v]; + + /* Compute end of sequence to retrieve */ + 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=f->shared->sieve_buf+(addr-sieve_start); + + /* Grab the data out of the buffer */ + HDmemcpy(buf,base_sieve_buf,size); } /* end if */ - /* No data sieve buffer yet, go allocate one */ + /* Entire request is not within this data sieve buffer */ else { - /* Set up the buffer parameters */ - size=size_arr[u]; - addr=_addr+offset_arr[u]; - max_data=_max_data-offset_arr[u]; - /* Check if we can actually hold the I/O request in the sieve buffer */ if(size>f->shared->sieve_buf_size) { - if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0) + /* Check for any overlap with the current sieve buffer */ + if((sieve_start>=addr && sieve_start<(contig_end+1)) + || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { + /* Flush the sieve buffer, if it's dirty */ + if(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; + } /* end if */ + } /* end if */ + + /* Read directly into the user's buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); } /* end if */ + /* Element size fits within the buffer size */ else { - /* Allocate room for the data sieve buffer */ - if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + /* Flush the sieve buffer if it's dirty */ + if(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; + } /* end if */ /* Determine the new sieve buffer size & location */ f->shared->sieve_loc=addr; @@ -769,59 +592,103 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, /* Adjust absolute EOA address to relative EOA address */ rel_eoa=abs_eoa-f->shared->base_addr; + /* Only need this when resizing sieve buffer */ + max_data=_max_data-dset_offset_arr[u]; + /* Compute the size of the sieve buffer */ + /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); + /* Update local copies of sieve information */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; + /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ HDmemcpy(buf,f->shared->sieve_buf,size); + + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; } /* end else */ + } /* end else */ - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - /* Increment sequence number */ + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) u++; - } /* end else */ + + /* Increment number of bytes copied */ + ret_value+=size; } /* end for */ } /* end if */ else { /* Work through all the sequences */ - for(u=0; u<nseq; u++) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; + 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]; + else + size=dset_len_arr[u]; - if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (unsigned char *)_buf + mem_offset_arr[v]; + + /* Write data */ + if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update memory information */ + 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) + u++; + + /* Increment number of bytes copied */ + ret_value+=size; } /* end for */ } /* end else */ + /* Update current sequence vectors */ + *dset_curr_seq=u; + *mem_curr_seq=v; + done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_contig_readv() */ +} /* end H5F_contig_readvv() */ /*------------------------------------------------------------------------- - * Function: H5F_contig_writev + * Function: H5F_contig_writevv * - * Purpose: Writes some data vectors into a dataset from a buffer. - * The data is contiguous. The address is the start of the dataset, + * Purpose: Writes some data vectors into a dataset from vectors into a + * buffer. The address is the start of the dataset, * relative to the base address for the file and the offsets and * sequence lengths are in bytes. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Thursday, July 5, 2001 + * Friday, May 2, 2003 * * Notes: * Offsets in the sequences must be monotonically increasing @@ -830,10 +697,11 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, - size_t nseq, size_t size_arr[], hsize_t offset_arr[], hid_t dxpl_id, - const void *_buf) +ssize_t +H5F_contig_writevv(H5F_t *f, hsize_t _max_data, haddr_t _addr, + 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[], + hid_t dxpl_id, const void *_buf) { const unsigned char *buf=_buf; /* Pointer to buffer to fill */ haddr_t abs_eoa; /* Absolute end of file address */ @@ -842,18 +710,10 @@ H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, hsize_t max_data; /* Actual maximum size of data to cache */ size_t size; /* Size of sequence in bytes */ size_t u; /* Counting variable */ -#ifndef SLOW_WAY - size_t max_seq; /* Maximum sequence to copy */ - haddr_t temp_end; /* Temporary end of buffer variable */ - size_t max_search; /* Maximum number of sequences to search */ - size_t mask; /* Bit mask */ - int bit_loc; /* Bit location of the leftmost '1' in max_search */ - size_t *size_arr_p; /* Pointer into the size array */ - hsize_t *offset_arr_p; /* Pointer into the offset array */ -#endif /* SLOW_WAY */ - herr_t ret_value=SUCCEED; /* Return value */ + size_t v; /* Counting variable */ + ssize_t ret_value=0; /* Return value */ - FUNC_ENTER_NOAPI(H5F_contig_writev, FAIL); + FUNC_ENTER_NOAPI(H5F_contig_writevv, FAIL); /* Check args */ assert(f); @@ -861,421 +721,284 @@ H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, /* Check if data sieving is enabled */ if(f->shared->lf->feature_flags&H5FD_FEAT_DATA_SIEVE) { + haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */ + haddr_t contig_end; /* End locations of block to write */ + size_t sieve_size; /* size of sieve buffer */ + + /* Set offsets in sequence lists */ + u=*dset_curr_seq; + v=*mem_curr_seq; + + /* No data sieve buffer yet, go allocate one */ + if(f->shared->sieve_buf==NULL) { + /* Choose smallest buffer to write */ + if(mem_len_arr[v]<dset_len_arr[u]) + size=mem_len_arr[v]; + else + size=dset_len_arr[u]; + + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (const unsigned char *)_buf + mem_offset_arr[v]; + + /* Set up the buffer parameters */ + max_data=_max_data-dset_offset_arr[u]; + + /* Check if we can actually hold the I/O request in the sieve buffer */ + if(size>f->shared->sieve_buf_size) { + if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, 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==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - /* Outer loop, guarantees working through all the sequences */ - for(u=0; u<nseq; ) { - - /* Try writing into the data sieve buffer */ - if(f->shared->sieve_buf) { - haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */ - haddr_t contig_end; /* End locations of block to write */ - size_t sieve_size; /* size of sieve buffer */ - - /* Stash local copies of these value */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - /* Next-outer loop works through sequences as fast as possible */ - for(; u<nseq; ) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; - - /* Compute end of sequence to retrieve */ - contig_end=addr+size-1; - - /* 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=f->shared->sieve_buf+(_addr-sieve_start); - unsigned char *temp_sieve_buf; - haddr_t temp_addr=_addr-1; /* Temporary address */ - -#ifdef SLOW_WAY - /* Retrieve all the sequences out of the current sieve buffer */ - while(contig_end<sieve_end) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+offset_arr[u]; - - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,size_arr[u]); - - /* Increment offset in buffer */ - buf += size_arr[u]; - - /* Increment sequence number, check for finished with sequences */ - if((++u) >= nseq) - break; - - /* Re-compute end of sequence to retrieve */ - contig_end=temp_addr+offset_arr[u]+size_arr[u]; - } /* end while */ -#else /* SLOW_WAY */ - /* Find log2(n) where n is the number of elements to search */ - - /* Set initial parameters */ - mask=(size_t)0xff<<((sizeof(size_t)-1)*8); /* Get a mask for the leftmost byte */ - max_search=((nseq-1)-u)+1; /* Compute 'n' for the log2 */ - assert(max_search>0); /* Sanity check */ - bit_loc=(sizeof(size_t)*8)-1; /* Initial bit location */ - - /* Search for the first byte with a bit set */ - while((max_search & mask)==0) { - mask>>=8; - bit_loc-=8; - } /* end while */ - - /* Switch to searching for a bit */ - mask=1<<bit_loc; - while((max_search & mask)==0) { - mask>>=1; - bit_loc--; - } /* end while */ - - /* location of the leftmost bit, plus 1, is log2(n) */ - max_seq=bit_loc+1; - - /* Don't walk off the array */ - max_seq=MIN(u+max_seq,nseq-1); - - /* Determine if a linear search is faster than a binary search */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - if(temp_end>=sieve_end) { - /* Linear search is faster */ - - /* Set the initial search values */ - max_seq=u; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Search for the first sequence ending greater than the sieve buffer end */ - while(temp_end<sieve_end) { - if(++max_seq>=nseq) - break; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - } /* end while */ - - /* Adjust back one element */ - max_seq--; - - } /* end if */ - else { - size_t lo,hi; /* Low and high bounds for binary search */ - unsigned found=0; /* Flag to indicate bounds have been found */ - - /* Binary search is faster */ - - /* Find the value 'u' which will be beyond the end of the sieve buffer */ - lo=u; - hi=nseq-1; - max_seq=(lo+hi)/2; - while(!found) { - /* Get the address of the end of sequence for the 'max_seq' position */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Current high bound is too large */ - if(temp_end>=sieve_end) { - if((lo+1)<hi) { - hi=max_seq; - max_seq=(lo+hi)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end if */ - /* Current low bound is too small */ - else { - if((lo+1)<hi) { - lo=max_seq; - max_seq=(lo+hi+1)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end else */ - } /* end while */ - - /* Check for non-exact match */ - if(lo!=hi) { - temp_end=temp_addr+offset_arr[hi]+size_arr[hi]; - if(temp_end<sieve_end) - max_seq=hi; - else - max_seq=lo; - } /* end if */ - } /* end else */ - - /* Set the pointers to the correct locations in the offset & size arrays */ - size_arr_p=&size_arr[u]; - offset_arr_p=&offset_arr[u]; - -#ifdef NO_DUFFS_DEVICE - /* Retrieve all the sequences out of the current sieve buffer */ - while(u<=max_seq) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Determine the new sieve buffer size & location */ + f->shared->sieve_loc=addr; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Make certain we don't read off the end of the file */ + if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Adjust absolute EOA address to relative EOA address */ + rel_eoa=abs_eoa-f->shared->base_addr; - /* Increment the offset in the array */ - u++; - } /* end while */ -#else /* NO_DUFFS_DEVICE */ -{ - size_t seq_count; + /* Compute the size of the sieve buffer */ + H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - seq_count=(max_seq-u)+1; - switch (seq_count % 4) { - case 0: - do - { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Check if there is any point in reading the data from the file */ + if(f->shared->sieve_size>size) { + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + } /* end if */ - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Grab the data out of the buffer (must be first piece of data in buffer ) */ + HDmemcpy(f->shared->sieve_buf,buf,size); - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Set sieve buffer dirty flag */ + f->shared->sieve_dirty=1; + } /* end else */ - /* Increment the offset in the array */ - u++; + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - case 3: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) + u++; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Increment number of bytes copied */ + ret_value+=size; + } /* end if */ - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Stash local copies of these value */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; + + /* Works through sequences as fast as possible */ + 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]; + else + size=dset_len_arr[u]; - /* Increment the offset in the array */ - u++; + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; - case 2: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Compute offset in memory */ + buf = (const unsigned char *)_buf + mem_offset_arr[v]; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Compute end of sequence to retrieve */ + contig_end=addr+size-1; - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* 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=f->shared->sieve_buf+(addr-sieve_start); - /* Increment the offset in the array */ - u++; + /* Put the data into the sieve buffer */ + HDmemcpy(base_sieve_buf,buf,size); - case 1: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Set sieve buffer dirty flag */ + f->shared->sieve_dirty=1; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + } /* end if */ + /* Entire request is not within this data sieve buffer */ + else { + /* Check if we can actually hold the I/O request in the sieve buffer */ + if(size>f->shared->sieve_buf_size) { + /* Check for any overlap with the current sieve buffer */ + if((sieve_start>=addr && sieve_start<(contig_end+1)) + || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { + /* Flush the sieve buffer, if it's dirty */ + if(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; + } /* end if */ - /* Increment the offset in the array */ - u++; + /* Force the sieve buffer to be re-read the next time */ + f->shared->sieve_loc=HADDR_UNDEF; + f->shared->sieve_size=0; + } /* end if */ - } while (u<=max_seq); - } /* end switch */ + /* Write directly from the user's buffer */ + if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + } /* end if */ + /* Element size fits within the buffer size */ + else { + /* Check if it is possible to (exactly) prepend or append to existing (dirty) sieve buffer */ + if(((addr+size)==sieve_start || addr==sieve_end) && + (size+sieve_size)<=f->shared->sieve_buf_size && + f->shared->sieve_dirty) { + /* Prepend to existing sieve buffer */ + if((addr+size)==sieve_start) { + /* Move existing sieve information to correct location */ + HDmemmove(f->shared->sieve_buf+size,f->shared->sieve_buf,sieve_size); + + /* Copy in new information (must be first in sieve buffer) */ + HDmemcpy(f->shared->sieve_buf,buf,size); + + /* Adjust sieve location */ + f->shared->sieve_loc=addr; + + } /* end if */ + /* Append to existing sieve buffer */ + else { + /* Copy in new information */ + HDmemcpy(f->shared->sieve_buf+sieve_size,buf,size); + } /* end else */ -} -#endif /* NO_DUFFS_DEVICE */ -#endif /* SLOW_WAY */ - /* Set sieve buffer dirty flag */ - f->shared->sieve_dirty=1; + /* Adjust sieve size */ + f->shared->sieve_size += size; + + /* Update local copies of sieve information */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; } /* end if */ - /* Entire request is not within this data sieve buffer */ + /* Can't add the new data onto the existing sieve buffer */ else { - /* Check if we can actually hold the I/O request in the sieve buffer */ - if(size>f->shared->sieve_buf_size) { - /* Check for any overlap with the current sieve buffer */ - if((sieve_start>=addr && sieve_start<(contig_end+1)) - || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { - /* Flush the sieve buffer, if it's dirty */ - if(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - - /* Force the sieve buffer to be re-read the next time */ - f->shared->sieve_loc=HADDR_UNDEF; - f->shared->sieve_size=0; - } /* end if */ - - /* Write directly from the user's buffer */ - if (H5F_block_write(f, type, addr, size, dxpl_id, buf)<0) + /* Flush the sieve buffer if it's dirty */ + if(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; } /* end if */ - /* Element size fits within the buffer size */ - else { - /* Check if it is possible to (exactly) prepend or append to existing (dirty) sieve buffer */ - if(((addr+size)==sieve_start || addr==sieve_end) && - (size+sieve_size)<=f->shared->sieve_buf_size && - f->shared->sieve_dirty) { - /* Prepend to existing sieve buffer */ - if((addr+size)==sieve_start) { - /* Move existing sieve information to correct location */ - HDmemmove(f->shared->sieve_buf+size,f->shared->sieve_buf,sieve_size); - - /* Copy in new information (must be first in sieve buffer) */ - HDmemcpy(f->shared->sieve_buf,buf,size); - - /* Adjust sieve location */ - f->shared->sieve_loc=addr; - - } /* end if */ - /* Append to existing sieve buffer */ - else { - /* Copy in new information */ - HDmemcpy(f->shared->sieve_buf+sieve_size,buf,size); - } /* end else */ - - /* Adjust sieve size */ - f->shared->sieve_size += size; - - /* Update local copies of sieve information */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - } /* end if */ - /* Can't add the new data onto the existing sieve buffer */ - else { - /* Flush the sieve buffer if it's dirty */ - if(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - - /* Determine the new sieve buffer size & location */ - f->shared->sieve_loc=addr; - - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-f->shared->base_addr; - - /* Only need this when resizing sieve buffer */ - max_data=_max_data-offset_arr[u]; - - /* Compute the size of the sieve buffer */ - /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ - H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - - /* Update local copies of sieve information */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - /* Check if there is any point in reading the data from the file */ - if(f->shared->sieve_size>size) { - /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - } /* end if */ - - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(f->shared->sieve_buf,buf,size); - - /* Set sieve buffer dirty flag */ - f->shared->sieve_dirty=1; - - } /* end else */ - } /* end else */ - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Determine the new sieve buffer size & location */ + f->shared->sieve_loc=addr; - /* Increment sequence number */ - u++; - } /* end else */ - } /* end for */ - } /* end if */ - /* No data sieve buffer yet, go allocate one */ - else { - /* Set up the buffer parameters */ - size=size_arr[u]; - addr=_addr+offset_arr[u]; - max_data=_max_data-offset_arr[u]; + /* Make certain we don't read off the end of the file */ + if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - /* Check if we can actually hold the I/O request in the sieve buffer */ - if(size>f->shared->sieve_buf_size) { - if (H5F_block_write(f, type, addr, size, 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==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + /* Adjust absolute EOA address to relative EOA address */ + rel_eoa=abs_eoa-f->shared->base_addr; - /* Determine the new sieve buffer size & location */ - f->shared->sieve_loc=addr; + /* Only need this when resizing sieve buffer */ + max_data=_max_data-dset_offset_arr[u]; - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); + /* Compute the size of the sieve buffer */ + /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ + H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-f->shared->base_addr; + /* Update local copies of sieve information */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; - /* Compute the size of the sieve buffer */ - H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); + /* Check if there is any point in reading the data from the file */ + if(f->shared->sieve_size>size) { + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + } /* end if */ - /* Check if there is any point in reading the data from the file */ - if(f->shared->sieve_size>size) { - /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - } /* end if */ + /* Grab the data out of the buffer (must be first piece of data in buffer ) */ + HDmemcpy(f->shared->sieve_buf,buf,size); - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(f->shared->sieve_buf,buf,size); + /* Set sieve buffer dirty flag */ + f->shared->sieve_dirty=1; - /* Set sieve buffer dirty flag */ - f->shared->sieve_dirty=1; + } /* end else */ } /* end else */ + } /* end else */ - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - /* Increment sequence number */ + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) u++; - } /* end else */ + + /* Increment number of bytes copied */ + ret_value+=size; } /* end for */ } /* end if */ else { /* Work through all the sequences */ - for(u=0; u<nseq; u++) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; + 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]; + else + size=dset_len_arr[u]; - if (H5F_block_write(f, type, addr, size, dxpl_id, buf)<0) + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (const unsigned char *)_buf + mem_offset_arr[v]; + + /* Write data */ + if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update memory information */ + 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) + u++; + + /* Increment number of bytes copied */ + ret_value+=size; } /* end for */ } /* end else */ + /* Update current sequence vectors */ + *dset_curr_seq=u; + *mem_curr_seq=v; + done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_contig_writev() */ +} /* end H5F_contig_writevv() */ diff --git a/src/H5Dio.c b/src/H5Dio.c new file mode 100644 index 0000000..51e66a3 --- /dev/null +++ b/src/H5Dio.c @@ -0,0 +1,2293 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define H5D_PACKAGE /*suppress error about including H5Dpkg */ + +#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 "H5Sprivate.h" /* Dataspace functions */ +#include "H5Vprivate.h" /* Vector and array functions */ + +/*#define H5D_DEBUG*/ + +/* + * The MPIO, MPIPOSIX, & FPHDF5 drivers are needed because there are + * file and places where we check for things that aren't handled by these + * drivers. + */ +#include "H5FDfphdf5.h" +#include "H5FDmpio.h" +#include "H5FDmpiposix.h" + +#ifdef H5_HAVE_PARALLEL +/* Remove this if H5R_DATASET_REGION is no longer used in this file */ +# include "H5Rpublic.h" +#endif /*H5_HAVE_PARALLEL*/ + +/* Pablo information */ +#define PABLO_MASK H5Dio_mask + +/* Local typedefs */ + +/*information for mapping between file space and memory space*/ +typedef struct fm_map { + H5S_t **fspace; /*file spaces for all chunks*/ + H5S_t **mspace; /*memory spaces for all chunks*/ + hsize_t elmt_count; /*indicate which element is being processed*/ + hsize_t nchunks; /*total number of chunks*/ + 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 down_chunks[H5O_LAYOUT_NDIMS]; /* "down" size of number of chunks in each dimension */ + hssize_t *chunk_coords; /*coordinates for all chunks*/ + H5O_layout_t *layout; /*dataset layout information*/ +} fm_map; + +/* Interface initialization */ +static int interface_initialize_g = 0; +#define INTERFACE_INIT NULL + +/* Local functions */ +static herr_t H5D_read(H5D_t *dataset, const H5T_t *mem_type, + 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, const H5T_t *mem_type, + const H5S_t *mem_space, const H5S_t *file_space, + hid_t dset_xfer_plist, const void *buf); +static herr_t +H5D_contig_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, + const H5S_t *file_space, H5T_path_t *tpath, H5S_conv_t *sconv, H5P_genplist_t *dc_plist, + H5P_genplist_t *dx_plist, hid_t dxpl_id, hbool_t doing_mpio, H5FD_mpio_xfer_t xfer_mode, + hid_t src_id, hid_t dst_id, void *buf/*out*/); +static herr_t +H5D_contig_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, + const H5S_t *file_space, H5T_path_t *tpath, H5S_conv_t *sconv, H5P_genplist_t *dc_plist, + H5P_genplist_t *dx_plist, hid_t dxpl_id, hbool_t doing_mpio, H5FD_mpio_xfer_t xfer_mode, + hid_t src_id, hid_t dst_id, const void *buf); +static herr_t +H5D_chunk_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, + const H5S_t *file_space, H5T_path_t *tpath, H5S_conv_t *sconv, H5P_genplist_t *dc_plist, + H5P_genplist_t *dx_plist, hid_t dxpl_id, hbool_t doing_mpio, H5FD_mpio_xfer_t xfer_mode, + hid_t src_id, hid_t dst_id, void *buf/*out*/); +static herr_t +H5D_chunk_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, + const H5S_t *file_space, H5T_path_t *tpath, H5S_conv_t *sconv, H5P_genplist_t *dc_plist, + H5P_genplist_t *dx_plist, hid_t dxpl_id, hbool_t doing_mpio, H5FD_mpio_xfer_t xfer_mode, + hid_t src_id, hid_t dst_id, const void *buf); +#ifdef H5_HAVE_PARALLEL +static herr_t +H5D_io_assist_mpio(H5P_genplist_t *dx_plist, hbool_t doing_mpio, H5FD_mpio_xfer_t xfer_mode, + hbool_t *xfer_mode_changed); +#endif /*H5_HAVE_PARALLEL*/ +static herr_t +H5D_chunk_mem_file_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_space, + const H5S_t *mem_space, fm_map *fm_struct); +static herr_t H5D_chunk_coords_assist(hssize_t *coords, size_t ndims, + hsize_t chunks[], hsize_t chunk_ptr); +static herr_t H5D_chunk_cb(void *elem, hid_t type_id, hsize_t ndims, + hssize_t *coords, void *fm); +static 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); + + +/* Declare a free list to manage blocks of single datatype element data */ +H5FL_BLK_DEFINE(type_elem); + +/* Declare a free list to manage blocks of type conversion data */ +H5FL_BLK_DEFINE(type_conv); + + +/*-------------------------------------------------------------------------- + NAME + H5Dfill + PURPOSE + Fill a selection in memory with a value + USAGE + herr_t H5Dfill(fill, fill_type, space, buf, buf_type) + const void *fill; IN: Pointer to fill value to use + hid_t fill_type_id; IN: Datatype of the fill value + void *buf; IN/OUT: Memory buffer to fill selection within + hid_t buf_type_id; IN: Datatype of the elements in buffer + hid_t space_id; IN: Dataspace describing memory buffer & + containing selection to use. + RETURNS + Non-negative on success/Negative on failure. + DESCRIPTION + Use the selection in the dataspace to fill elements in a memory buffer. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + If "fill" parameter is NULL, use all zeros as fill value + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5Dfill(const void *fill, hid_t fill_type_id, void *buf, hid_t buf_type_id, hid_t space_id) +{ + H5S_t *space; /* Dataspace */ + H5T_t *fill_type; /* Fill-value datatype */ + H5T_t *buf_type; /* Buffer datatype */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Dfill, FAIL); + H5TRACE5("e","xixii",fill,fill_type_id,buf,buf_type_id,space_id); + + /* Check args */ + if (buf==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer"); + if (NULL == (space=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))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a datatype"); + if (NULL == (buf_type=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 */ + if(H5D_fill(fill,fill_type,buf,buf_type,space, H5AC_dxpl_id)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed"); + +done: + FUNC_LEAVE_API(ret_value); +} /* H5Dfill() */ + + +/*-------------------------------------------------------------------------- + NAME + H5D_fill + PURPOSE + Fill a selection in memory with a value (internal version) + USAGE + herr_t H5D_fill(fill, fill_type, buf, buf_type, space) + const void *fill; IN: Pointer to fill value to use + H5T_t *fill_type; IN: Datatype of the fill value + void *buf; IN/OUT: Memory buffer to fill selection within + H5T_t *buf_type; IN: Datatype of the elements in buffer + H5S_t *space; IN: Dataspace describing memory buffer & + containing selection to use. + RETURNS + Non-negative on success/Negative on failure. + DESCRIPTION + Use the selection in the dataspace to fill elements in a memory buffer. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + If "fill" parameter is NULL, use all zeros as fill value. If "fill_type" + parameter is NULL, use "buf_type" for the fill value datatype. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static 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) +{ + H5T_path_t *tpath = NULL; /* Conversion information*/ + uint8_t *tconv_buf = NULL; /* Data type conv buffer */ + uint8_t *bkg_buf = NULL; /* Temp conversion buffer */ + hid_t src_id = -1, dst_id = -1; /* Temporary type IDs */ + size_t src_type_size; /* Size of source type */ + size_t dst_type_size; /* Size of destination type*/ + size_t buf_size; /* Desired buffer size */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5D_fill); + + /* Check args */ + assert(buf); + assert(buf_type); + assert(space); + + /* Check for "default" fill value */ + if(fill_type==NULL) + fill_type=buf_type; + + /* Get the memory and file datatype sizes */ + src_type_size = H5T_get_size(fill_type); + dst_type_size = H5T_get_size(buf_type); + + /* Get the maximum buffer size needed and allocate it */ + buf_size=MAX(src_type_size,dst_type_size); + if (NULL==(tconv_buf = H5FL_BLK_MALLOC(type_elem,buf_size)) || NULL==(bkg_buf = H5FL_BLK_CALLOC(type_elem,buf_size))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + + /* Copy the user's data into the buffer for conversion */ + if(fill==NULL) + HDmemset(tconv_buf,0,src_type_size); + else + HDmemcpy(tconv_buf,fill,src_type_size); + + /* Convert memory buffer into disk buffer */ + /* Set up type conversion function */ + if (NULL == (tpath = H5T_path_find(fill_type, buf_type, NULL, NULL, dxpl_id))) { + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); + } else if (!H5T_IS_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(buf_type, H5T_COPY_ALL)))<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion"); + } + + /* Perform data type conversion */ + if (H5T_convert(tpath, src_id, dst_id, (hsize_t)1, 0, 0, tconv_buf, bkg_buf, dxpl_id)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "data type conversion failed"); + + /* Fill the selection in the memory buffer */ + if(H5S_select_fill(tconv_buf, dst_type_size, space, buf)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTENCODE, FAIL, "filling selection failed"); + +done: + if (tconv_buf) + H5FL_BLK_FREE(type_elem,tconv_buf); + if (bkg_buf) + H5FL_BLK_FREE(type_elem,bkg_buf); + FUNC_LEAVE_NOAPI(ret_value); +} /* H5D_fill() */ + + +/*------------------------------------------------------------------------- + * Function: H5Dread + * + * Purpose: Reads (part of) a DSET from the file into application + * memory BUF. The part of the dataset to read is defined with + * MEM_SPACE_ID and FILE_SPACE_ID. The data points are + * converted from their file type to the MEM_TYPE_ID specified. + * Additional miscellaneous data transfer properties can be + * passed to this function with the PLIST_ID argument. + * + * The FILE_SPACE_ID can be the constant H5S_ALL which indicates + * that the entire file data space is to be referenced. + * + * The MEM_SPACE_ID can be the constant H5S_ALL in which case + * the memory data space is the same as the file data space + * defined when the dataset was created. + * + * The number of elements in the memory data space must match + * the number of elements in the file data space. + * + * The PLIST_ID can be the constant H5P_DEFAULT in which + * case the default data transfer properties are used. + * + * Return: Non-negative on success/Negative on failure + * + * Errors: + * ARGS BADTYPE Not a data space. + * ARGS BADTYPE Not a data type. + * ARGS BADTYPE Not a dataset. + * ARGS BADTYPE Not xfer parms. + * ARGS BADVALUE No output buffer. + * DATASET READERROR Can't read data. + * + * Programmer: Robb Matzke + * Thursday, December 4, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t plist_id, void *buf/*out*/) +{ + H5D_t *dset = NULL; + const H5T_t *mem_type = NULL; + const H5S_t *mem_space = NULL; + const H5S_t *file_space = NULL; + 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))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + if (NULL == dset->ent.file) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + if (NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5S_ALL != mem_space_id) { + if (NULL == (mem_space = 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) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); + } + if (H5S_ALL != file_space_id) { + if (NULL == (file_space = 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) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); + } + + /* 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)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + if (!buf) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer"); + + /* read raw data */ + if (H5D_read(dset, mem_type, 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); +} + + +/*------------------------------------------------------------------------- + * Function: H5Dwrite + * + * Purpose: Writes (part of) a DSET from application memory BUF to the + * file. The part of the dataset to write is defined with the + * MEM_SPACE_ID and FILE_SPACE_ID arguments. The data points + * are converted from their current type (MEM_TYPE_ID) to their + * file data type. Additional miscellaneous data transfer + * properties can be passed to this function with the + * PLIST_ID argument. + * + * The FILE_SPACE_ID can be the constant H5S_ALL which indicates + * that the entire file data space is to be referenced. + * + * The MEM_SPACE_ID can be the constant H5S_ALL in which case + * the memory data space is the same as the file data space + * defined when the dataset was created. + * + * The number of elements in the memory data space must match + * the number of elements in the file data space. + * + * The PLIST_ID can be the constant H5P_DEFAULT in which + * case the default data transfer properties are used. + * + * Return: Non-negative on success/Negative on failure + * + * Errors: + * + * Programmer: Robb Matzke + * Thursday, December 4, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, + hid_t file_space_id, hid_t plist_id, const void *buf) +{ + H5D_t *dset = NULL; + const H5T_t *mem_type = NULL; + const H5S_t *mem_space = NULL; + const H5S_t *file_space = NULL; + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Dwrite, 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))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + if (NULL == dset->ent.file) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset"); + if (NULL == (mem_type = H5I_object_verify(mem_type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data type"); + if (H5S_ALL != mem_space_id) { + if (NULL == (mem_space = 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) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); + } + if (H5S_ALL != file_space_id) { + if (NULL == (file_space = 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) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection+offset not within extent"); + } + + /* 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)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not xfer parms"); + if (!buf) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no output buffer"); + + /* write raw data */ + if (H5D_write(dset, mem_type, mem_space, file_space, plist_id, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data"); + +done: + FUNC_LEAVE_API(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5D_read + * + * Purpose: Reads (part of) a DATASET into application memory BUF. See + * H5Dread() for complete details. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Thursday, December 4, 1997 + * + * Modifications: + * Robb Matzke, 1998-06-09 + * The data space is no longer cached in the dataset struct. + * + * Robb Matzke, 1998-08-11 + * Added timing calls around all the data space I/O functions. + * + * rky, 1998-09-18 + * Added must_convert to do non-optimized read when necessary. + * + * Quincey Koziol, 1999-07-02 + * Changed xfer_parms parameter to xfer plist parameter, so it + * could be passed to H5T_convert. + * + * Albert Cheng, 2000-11-21 + * Added the code that when it detects it is not safe to process a + * COLLECTIVE read request without hanging, it changes it to + * INDEPENDENT calls. + * + * Albert Cheng, 2000-11-27 + * Changed to use the optimized MPIO transfer for Collective calls only. + * + * Raymond Lu, 2001-10-2 + * Changed the way to retrieve property for generic property list. + * + * Raymond Lu, 2002-2-26 + * For the new fill value design, data space can either be allocated + * or not allocated at this stage. Fill value or data from space is + * returned to outgoing buffer. + * + * QAK - 2002/04/02 + * Removed the must_convert parameter and move preconditions to + * H5S_<foo>_opt_possible() routine + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_read(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, + const H5S_t *file_space, hid_t dxpl_id, void *buf/*out*/) +{ + hssize_t snelmts; /*total number of elmts (signed) */ + hsize_t nelmts; /*total number of elmts */ + H5T_path_t *tpath = NULL; /*type conversion info */ + hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ + H5S_conv_t *sconv=NULL; /*space conversion funcs*/ + H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; /*xfer_mode for this request */ + hbool_t doing_mpio=0; /*This is an MPIO access */ + H5P_genplist_t *dx_plist=NULL; /* Data transfer property list */ + H5P_genplist_t *dc_plist; /* Dataset creation roperty list */ + unsigned sconv_flags=0; /* Flags for the space conversion */ + H5S_sel_type fsel_type; /* Selection type on disk */ + H5S_sel_type msel_type; /* Selection type in memory */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5D_read); + + /* check args */ + assert(dataset && dataset->ent.file); + assert(mem_type); + assert(buf); + + /* Get the dataset's creation property list */ + if (NULL == (dc_plist = H5I_object(dataset->dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); + + /* Get the dataset transfer property list */ + if (NULL == (dx_plist = H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); + + if (!file_space) + file_space = dataset->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"); + nelmts=snelmts; + +#ifdef H5_HAVE_PARALLEL + /* Collect Parallel I/O information for possible later use */ + if (H5FD_MPIO==H5P_peek_hid_t(dx_plist,H5D_XFER_VFL_ID_NAME)) { + doing_mpio++; + xfer_mode=H5P_peek_unsigned(dx_plist, H5D_XFER_IO_XFER_MODE_NAME); + } /* end if */ + /* Collective access is not permissible without the MPIO or MPIPOSIX driver */ + if (doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE && + !(IS_H5FD_MPIO(dataset->ent.file) || IS_H5FD_MPIPOSIX(dataset->ent.file) || IS_H5FD_FPHDF5(dataset->ent.file))) + HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access for MPIO & MPIPOSIX drivers only"); + + /* Set the "parallel I/O possible" flag, for H5S_find() */ + if (H5S_mpi_opt_types_g && IS_H5FD_MPIO(dataset->ent.file)) { + /* Only collective write should call this since it eventually + * calls MPI_File_set_view which is a collective call. + * See H5S_mpio_spaces_xfer() for details. + */ + if (doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE) + sconv_flags |= H5S_CONV_PAR_IO_POSSIBLE; + } /* end if */ +#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)) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes"); + + /* Retrieve dataset properties */ + /* <none needed in the general case> */ + + /* If space hasn't been allocated and not using external storage, + * return fill value to buffer if fill time is upon allocation, or + * do nothing if fill time is never. If the dataset is compact and + * fill time is NEVER, there is no way to tell whether part of data + * has been overwritten. So just proceed in reading. + */ + if(nelmts > 0 && dataset->efl.nused==0 && dataset->layout.type!=H5D_COMPACT + && dataset->layout.addr==HADDR_UNDEF) { + H5O_fill_t fill; /* Fill value info */ + H5D_fill_time_t fill_time; /* When to write the fill values */ + H5D_fill_value_t fill_status; /* Whether/How the fill value is defined */ + + /* Retrieve dataset's fill-value properties */ + if(H5P_fill_value_defined(dc_plist, &fill_status)<0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't tell if fill value defined"); + if((fill_status==H5D_FILL_VALUE_DEFAULT || fill_status==H5D_FILL_VALUE_USER_DEFINED) + && H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,"can't retrieve fill value"); + if(H5P_get(dc_plist, H5D_CRT_FILL_TIME_NAME, &fill_time) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL,"can't retrieve fill time"); + + /* Should be impossible, but check anyway... */ + if(fill_status == H5D_FILL_VALUE_UNDEFINED && fill_time == H5D_FILL_TIME_ALLOC) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "read failed: dataset doesn't exist, no data can be read"); + + /* If we're never going to fill this dataset, just leave the junk in the user's buffer */ + if(fill_time == H5D_FILL_TIME_NEVER) + HGOTO_DONE(SUCCEED); + + /* Go fill the user's selection with the dataset's fill value */ + if(H5D_fill(fill.buf,fill.type,buf,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 data type 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 data type conversion also + * turns off background preservation. + */ + if (NULL==(tpath=H5T_path_find(dataset->type, mem_type, NULL, NULL, dxpl_id))) { + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); + } else if (!H5T_IS_NOOP(tpath)) { + if ((src_id=H5I_register(H5I_DATATYPE, H5T_copy(dataset->type, H5T_COPY_ALL)))<0 || + (dst_id=H5I_register(H5I_DATATYPE, H5T_copy(mem_type, H5T_COPY_ALL)))<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion"); + } /* end if */ + + /* Set the storage flags for the space conversion check */ + switch(dataset->layout.type) { + case H5D_COMPACT: + sconv_flags |= H5S_CONV_STORAGE_COMPACT; + break; + + case H5D_CONTIGUOUS: + sconv_flags |= H5S_CONV_STORAGE_CONTIGUOUS; + break; + + case H5D_CHUNKED: + sconv_flags |= H5S_CONV_STORAGE_CHUNKED; + break; + + default: + assert(0 && "Unhandled layout type!"); + } /* end switch */ + + /* Get dataspace functions */ + if (NULL==(sconv=H5S_find(mem_space, file_space, sconv_flags))) + HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert from file to memory data space"); + + /* Get type of selection on disk & in memory */ + if((fsel_type=H5S_get_select_type(file_space))<0) + HGOTO_ERROR (H5E_DATASET, H5E_BADSELECT, FAIL, "unable to convert from file to memory data space"); + if((msel_type=H5S_get_select_type(mem_space))<0) + HGOTO_ERROR (H5E_DATASET, H5E_BADSELECT, FAIL, "unable to convert from file to memory data space"); + + /* Determine correct I/O routine to invoke */ + if((fsel_type==H5S_SEL_POINTS || msel_type==H5S_SEL_POINTS) || + dataset->layout.type!=H5D_CHUNKED) { + /* Must use "contiguous" code for point selections, + * since order of I/O accesses can be different from that of the + * other kinds of selections + */ + if(H5D_contig_read(nelmts, dataset, mem_type, mem_space, file_space, tpath, sconv, dc_plist, + dx_plist, dxpl_id, doing_mpio, xfer_mode, src_id, dst_id, buf)<0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data"); + } /* end if */ + else { + if(H5D_chunk_read(nelmts, dataset, mem_type, mem_space, file_space, tpath, sconv, dc_plist, + dx_plist, dxpl_id, doing_mpio, xfer_mode, src_id, dst_id, buf)<0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "can't read data"); + } /* end else */ + +done: + if (src_id >= 0) + H5I_dec_ref(src_id); + if (dst_id >= 0) + H5I_dec_ref(dst_id); + + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5D_read() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_write + * + * Purpose: Writes (part of) a DATASET to a file from application memory + * BUF. See H5Dwrite() for complete details. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * Thursday, December 4, 1997 + * + * Modifications: + * Robb Matzke, 9 Jun 1998 + * The data space is no longer cached in the dataset struct. + * + * rky 980918 + * Added must_convert to do non-optimized read when necessary. + * + * Quincey Koziol, 2 July 1999 + * Changed xfer_parms parameter to xfer plist parameter, so it could + * be passed to H5T_convert + * + * Albert Cheng, 2000-11-21 + * Added the code that when it detects it is not safe to process a + * COLLECTIVE write request without hanging, it changes it to + * INDEPENDENT calls. + * + * Albert Cheng, 2000-11-27 + * Changed to use the optimized MPIO transfer for Collective calls only. + * + * Raymond Lu, 2001-10-2 + * Changed the way to retrieve property for generic property list. + * + * Raymond Lu, 2002-2-26 + * For the new fill value design, space may not be allocated until + * this function is called. Allocate and initialize space if it + * hasn't been. + * + * QAK - 2002/04/02 + * Removed the must_convert parameter and move preconditions to + * H5S_<foo>_opt_possible() routine + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_write(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, + const H5S_t *file_space, hid_t dxpl_id, const void *buf) +{ + hssize_t snelmts; /*total number of elmts (signed) */ + hsize_t nelmts; /*total number of elmts */ + H5T_path_t *tpath = NULL; /*type conversion info */ + hid_t src_id = -1, dst_id = -1;/*temporary type atoms */ + H5S_conv_t *sconv=NULL; /*space conversion funcs*/ + H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; /*xfer_mode for this request */ + hbool_t doing_mpio=0; /*This is an MPIO access */ + H5P_genplist_t *dx_plist=NULL; /* Data transfer property list */ + H5P_genplist_t *dc_plist; /* Dataset creation roperty list */ + unsigned sconv_flags=0; /* Flags for the space conversion */ + H5S_sel_type fsel_type; /* Selection type on disk */ + H5S_sel_type msel_type; /* Selection type in memory */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5D_write); + + /* check args */ + assert(dataset && dataset->ent.file); + assert(mem_type); + assert(buf); + + /* If MPIO, MPIPOSIX, or FPHDF5 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 ( (IS_H5FD_MPIO(dataset->ent.file) || IS_H5FD_MPIPOSIX(dataset->ent.file) || IS_H5FD_FPHDF5(dataset->ent.file)) && + H5T_get_class(mem_type)==H5T_VLEN) + HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Parallel IO does not support writing VL datatypes yet"); + /* If MPIO, MPIPOSIX, or FPHDF5 is used, no dataset region reference 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 ((IS_H5FD_MPIO(dataset->ent.file) || IS_H5FD_MPIPOSIX(dataset->ent.file) || IS_H5FD_FPHDF5(dataset->ent.file)) && + H5T_get_class(mem_type)==H5T_REFERENCE && + H5T_get_ref_type(mem_type)==H5R_DATASET_REGION) + HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "Parallel IO does not support writing region reference datatypes yet"); + + /* Check if we are allowed to write to this file */ + if (0==(H5F_get_intent(dataset->ent.file) & H5F_ACC_RDWR)) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "no write intent on file"); + + /* Get the dataset's creation property list */ + if (NULL == (dc_plist = H5I_object(dataset->dcpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); + + /* Get the dataset transfer property list */ + if (NULL == (dx_plist = H5I_object(dxpl_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset creation property list"); + + if (!file_space) + file_space = dataset->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"); + nelmts=snelmts; + +#ifdef H5_HAVE_PARALLEL + /* Collect Parallel I/O information for possible later use */ + if (H5FD_MPIO==H5P_peek_hid_t(dx_plist,H5D_XFER_VFL_ID_NAME)) { + doing_mpio++; + xfer_mode=H5P_peek_unsigned(dx_plist, H5D_XFER_IO_XFER_MODE_NAME); + } /* end if */ + + /* Collective access is not permissible without the MPIO or MPIPOSIX driver */ + if (doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE && + !(IS_H5FD_MPIO(dataset->ent.file) || IS_H5FD_MPIPOSIX(dataset->ent.file) || IS_H5FD_FPHDF5(dataset->ent.file))) + HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access for MPIO driver only"); + + /* If dataset is compact, collective access is only allowed when file space + * selection is H5S_ALL */ + if(doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE + && dataset->layout.type==H5D_COMPACT) { + if(H5S_get_select_type(file_space) != H5S_SEL_ALL) + HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "collective access to compact dataset doesn't support partial access"); + } + + /* Set the "parallel I/O possible" flag, for H5S_find() */ + if (H5S_mpi_opt_types_g && IS_H5FD_MPIO(dataset->ent.file)) { + /* Only collective write should call this since it eventually + * calls MPI_File_set_view which is a collective call. + * See H5S_mpio_spaces_xfer() for details. + */ + if (doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE) + sconv_flags |= H5S_CONV_PAR_IO_POSSIBLE; + } /* end if */ +#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)) + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "src and dest data spaces have different sizes"); + + /* Retrieve dataset properties */ + /* <none needed currently> */ + + /* Allocate data space and initialize it if it hasn't been. */ + if(nelmts > 0 && dataset->efl.nused==0 && dataset->layout.type!=H5D_COMPACT + && dataset->layout.addr==HADDR_UNDEF) { + hssize_t file_nelmts; /* Number of elements in file dataset's dataspace */ + + /* Get the number of elements in file dataset's dataspace */ + if((file_nelmts=H5S_get_simple_extent_npoints(file_space))<0) + HGOTO_ERROR (H5E_DATASET, H5E_BADVALUE, FAIL, "can't retrieve number of elements in file dataset"); + + /* Allocate storage */ + if(H5D_alloc_storage(dataset->ent.file,dxpl_id,dataset,H5D_ALLOC_WRITE, TRUE, (hbool_t)((hsize_t)file_nelmts==nelmts ? TRUE : FALSE))<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 data type 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 data type conversion also + * turns off background preservation. + */ + if (NULL==(tpath=H5T_path_find(mem_type, dataset->type, NULL, NULL, dxpl_id))) { + HGOTO_ERROR(H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert between src and dest data types"); + } else if (!H5T_IS_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(dataset->type, H5T_COPY_ALL)))<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTREGISTER, FAIL, "unable to register types for conversion"); + } /* end if */ + + /* Set the storage flags for the space conversion check */ + switch(dataset->layout.type) { + case H5D_COMPACT: + sconv_flags |= H5S_CONV_STORAGE_COMPACT; + break; + + case H5D_CONTIGUOUS: + sconv_flags |= H5S_CONV_STORAGE_CONTIGUOUS; + break; + + case H5D_CHUNKED: + sconv_flags |= H5S_CONV_STORAGE_CHUNKED; + break; + + default: + assert(0 && "Unhandled layout type!"); + } /* end switch */ + + /* Get dataspace functions */ + if (NULL==(sconv=H5S_find(mem_space, file_space, sconv_flags))) + HGOTO_ERROR (H5E_DATASET, H5E_UNSUPPORTED, FAIL, "unable to convert from memory to file data space"); + + /* Get type of selection on disk & in memory */ + if((fsel_type=H5S_get_select_type(file_space))<0) + HGOTO_ERROR (H5E_DATASET, H5E_BADSELECT, FAIL, "unable to convert from file to memory data space"); + if((msel_type=H5S_get_select_type(mem_space))<0) + HGOTO_ERROR (H5E_DATASET, H5E_BADSELECT, FAIL, "unable to convert from file to memory data space"); + + /* Determine correct I/O routine to invoke */ + if((fsel_type==H5S_SEL_POINTS || msel_type==H5S_SEL_POINTS) || + dataset->layout.type!=H5D_CHUNKED) { + /* Must use "contiguous" code for point selections, + * since order of I/O accesses can be different from that of the + * other kinds of selections + */ + if(H5D_contig_write(nelmts, dataset, mem_type, mem_space, file_space, tpath, sconv, dc_plist, + dx_plist, dxpl_id, doing_mpio, xfer_mode, src_id, dst_id, buf)<0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data"); + } /* end if */ + else { + if(H5D_chunk_write(nelmts, dataset, mem_type, mem_space, file_space, tpath, sconv, dc_plist, + dx_plist, dxpl_id, doing_mpio, xfer_mode, src_id, dst_id, buf)<0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "can't write data"); + } /* end else */ + + /* + * Update modification time. We have to do this explicitly because + * writing to a dataset doesn't necessarily change the object header. + */ + if (H5O_touch(&(dataset->ent), FALSE, dxpl_id)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update modification time"); + +done: + if (src_id >= 0) + H5I_dec_ref(src_id); + if (dst_id >= 0) + H5I_dec_ref(dst_id); + + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5D_write() */ + + +/*------------------------------------------------------------------------- + * 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 + * + * Modifications: + * QAK - 2003/04/17 + * Hacked on it a lot. :-) + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_contig_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, + const H5S_t *file_space, H5T_path_t *tpath, H5S_conv_t *sconv, H5P_genplist_t *dc_plist, + H5P_genplist_t *dx_plist, hid_t dxpl_id, hbool_t +#ifndef H5_HAVE_PARALLEL + UNUSED +#endif /*H5_HAVE_PARALLEL*/ + doing_mpio, H5FD_mpio_xfer_t +#ifndef H5_HAVE_PARALLEL + UNUSED +#endif /*H5_HAVE_PARALLEL*/ + xfer_mode, + hid_t src_id, hid_t dst_id, void *buf/*out*/) +{ + 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 target_size; /*desired buffer size */ + hsize_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; /*data type conv buffer */ + uint8_t *bkg_buf = NULL; /*background buffer */ + hsize_t smine_start; /*strip mine start loc */ + hsize_t n, smine_nelmts; /*elements per strip */ +#ifdef H5_HAVE_PARALLEL + hbool_t xfer_mode_changed; /* Whether the transfer mode was changed */ +#endif /*H5_HAVE_PARALLEL*/ + herr_t ret_value = SUCCEED; /*return value */ + + FUNC_ENTER_NOINIT(H5D_contig_read); + + /* + * If there is no type conversion then read directly into the + * application's buffer. This saves at least one mem-to-mem copy. + */ + if (H5T_IS_NOOP(tpath)) { +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + /* Sanity check dataset, then read it */ + assert(dataset->layout.addr!=HADDR_UNDEF || dataset->efl.nused>0 || + dataset->layout.type==H5D_COMPACT); + status = (sconv->read)(dataset->ent.file, &(dataset->layout), + dc_plist, (H5D_storage_t *)&(dataset->efl), H5T_get_size(dataset->type), + file_space, mem_space, dxpl_id, buf/*out*/); +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[1].read_timer), &timer); + sconv->stats[1].read_nbytes += nelmts * H5T_get_size(dataset->type); + sconv->stats[1].read_ncalls++; +#endif + + /* Check return value from optimized read */ + if (status<0) { + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed"); + } else + /* direct xfer accomplished successfully */ + HGOTO_DONE(SUCCEED); + } /* end if */ + + /* + * This is the general case(type conversion). + */ + +#ifdef H5_HAVE_PARALLEL + H5D_io_assist_mpio(dx_plist, doing_mpio, xfer_mode, &xfer_mode_changed); +#endif /*H5_HAVE_PARALLEL*/ + + /* Compute element sizes and other parameters */ + src_type_size = H5T_get_size(dataset->type); + dst_type_size = H5T_get_size(mem_type); + target_size = H5P_peek_size_t(dx_plist,H5D_XFER_MAX_TEMP_BUF_NAME); + request_nelmts = target_size / MAX(src_type_size, dst_type_size); + + /* 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 */ + + /* 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 (tpath->cdata.need_bkg) { + /* Retrieve the bkgr buffer property */ + if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_TYPE_NAME, &need_bkg)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer type"); + need_bkg = MAX(tpath->cdata.need_bkg, need_bkg); + } else { + need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ + } /* end else */ + if (NULL==(tconv_buf=H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME))) { + /* 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=H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))) { + /* Allocate background buffer */ + H5_CHECK_OVERFLOW((request_nelmts*dst_type_size),hsize_t,size_t); + if((bkg_buf=H5FL_BLK_MALLOC(type_conv,(size_t)(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 = MIN(request_nelmts, (nelmts-smine_start)); + + /* + * Gather the data from disk into the data type 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 */ + assert(dataset->layout.addr!=HADDR_UNDEF || dataset->efl.nused>0 || + dataset->layout.type==H5D_COMPACT); + n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), + dc_plist, (H5D_storage_t *)&dataset->efl, src_type_size, file_space, + &file_iter, smine_nelmts, dxpl_id, tconv_buf/*out*/); + +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[1].gath_timer), &timer); + sconv->stats[1].gath_nbytes += n * src_type_size; + sconv->stats[1].gath_ncalls++; +#endif + if (n!=smine_nelmts) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed"); + + if (need_bkg) { +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + n = H5S_select_mgath(buf, dst_type_size, mem_space, &bkg_iter, + smine_nelmts, dxpl_id, bkg_buf/*out*/); +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[1].bkg_timer), &timer); + sconv->stats[1].bkg_nbytes += n * dst_type_size; + sconv->stats[1].bkg_ncalls++; +#endif + if (n!=smine_nelmts) + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "mem gather failed"); + } /* end if */ + + /* + * Perform data type conversion. + */ + if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, 0, 0, tconv_buf, bkg_buf, dxpl_id)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); + + /* + * Scatter the data into memory. + */ +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + status = H5S_select_mscat(tconv_buf, dst_type_size, mem_space, + &mem_iter, smine_nelmts, dxpl_id, buf/*out*/); +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[1].scat_timer), &timer); + sconv->stats[1].scat_nbytes += smine_nelmts * dst_type_size; + sconv->stats[1].scat_ncalls++; +#endif + if (status<0) + HGOTO_ERROR (H5E_DATASET, H5E_READERROR, FAIL, "scatter failed"); + + } /* end for */ + +done: +#ifdef H5_HAVE_PARALLEL + /* restore xfer_mode due to the kludge */ + if (doing_mpio && xfer_mode_changed) { +#ifdef H5D_DEBUG + if (H5DEBUG(D)) + fprintf (H5DEBUG(D), "H5D: dx->xfer_mode was COLLECTIVE, restored to INDEPENDENT\n"); +#endif + xfer_mode = H5FD_MPIO_COLLECTIVE; + if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); + } /* end if */ +#endif /*H5_HAVE_PARALLEL*/ + /* Release selection iterators */ + if(file_iter_init) + H5S_select_iter_release(&file_iter); + if(mem_iter_init) + H5S_select_iter_release(&mem_iter); + if(bkg_iter_init) + H5S_select_iter_release(&bkg_iter); + + assert(dx_plist); + if (tconv_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME)) + H5FL_BLK_FREE(type_conv,tconv_buf); + if (bkg_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME)) + 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 + * + * Modifications: + * QAK - 2003/04/17 + * Hacked on it a lot. :-) + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_contig_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, + const H5S_t *file_space, H5T_path_t *tpath, H5S_conv_t *sconv, H5P_genplist_t *dc_plist, + H5P_genplist_t *dx_plist, hid_t dxpl_id, hbool_t +#ifndef H5_HAVE_PARALLEL + UNUSED +#endif /*H5_HAVE_PARALLEL*/ + doing_mpio, H5FD_mpio_xfer_t +#ifndef H5_HAVE_PARALLEL + UNUSED +#endif /*H5_HAVE_PARALLEL*/ + xfer_mode, + hid_t src_id, hid_t dst_id, const void *buf) +{ + 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 target_size; /*desired buffer size */ + hsize_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; /*data type conv buffer */ + uint8_t *bkg_buf = NULL; /*background buffer */ + hsize_t smine_start; /*strip mine start loc */ + hsize_t n, smine_nelmts; /*elements per strip */ +#ifdef H5_HAVE_PARALLEL + hbool_t xfer_mode_changed; /* Whether the transfer mode was changed */ +#endif /*H5_HAVE_PARALLEL*/ + herr_t ret_value = SUCCEED; /*return value */ + + FUNC_ENTER_NOINIT(H5D_contig_write); + + /* + * If there is no type conversion then write directly from the + * application's buffer. This saves at least one mem-to-mem copy. + */ + if (H5T_IS_NOOP(tpath)) { +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + status = (sconv->write)(dataset->ent.file, &(dataset->layout), + dc_plist, (H5D_storage_t *)&(dataset->efl), H5T_get_size(dataset->type), + file_space, mem_space, dxpl_id, buf); +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[0].write_timer), &timer); + sconv->stats[0].write_nbytes += nelmts * H5T_get_size(mem_type); + sconv->stats[0].write_ncalls++; +#endif + + /* Check return value from optimized write */ + if (status<0) { + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed"); + } else + /* direct xfer accomplished successfully */ + HGOTO_DONE(SUCCEED); + } /* end if */ + + /* + * This is the general case. + */ + +#ifdef H5_HAVE_PARALLEL + H5D_io_assist_mpio(dx_plist, doing_mpio, xfer_mode, &xfer_mode_changed); +#endif /*H5_HAVE_PARALLEL*/ + + /* Compute element sizes and other parameters */ + src_type_size = H5T_get_size(mem_type); + dst_type_size = H5T_get_size(dataset->type); + target_size = H5P_peek_size_t(dx_plist,H5D_XFER_MAX_TEMP_BUF_NAME); + request_nelmts = target_size / MAX (src_type_size, dst_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 (tpath->cdata.need_bkg) { + /* Retrieve the bkgr buffer property */ + if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_TYPE_NAME, &need_bkg)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer type"); + need_bkg = MAX (tpath->cdata.need_bkg, need_bkg); + } else if(H5T_detect_class(dataset->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 { + need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ + } /* end else */ + if (NULL==(tconv_buf=H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME))) { + /* 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=H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))) { + /* Allocate background buffer */ + H5_CHECK_OVERFLOW((request_nelmts*dst_type_size),hsize_t,size_t); + if((bkg_buf=H5FL_BLK_CALLOC(type_conv,(size_t)(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 = MIN(request_nelmts, (nelmts-smine_start)); + + /* + * Gather data from application buffer into the data type conversion + * buffer. Also gather data from the file into the background buffer + * if necessary. + */ +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + n = H5S_select_mgath(buf, src_type_size, mem_space, &mem_iter, + smine_nelmts, dxpl_id, tconv_buf/*out*/); +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[0].gath_timer), &timer); + sconv->stats[0].gath_nbytes += n * src_type_size; + sconv->stats[0].gath_ncalls++; +#endif + if (n!=smine_nelmts) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "mem gather failed"); + + if (need_bkg) { +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), + dc_plist, (H5D_storage_t *)&(dataset->efl), dst_type_size, file_space, + &bkg_iter, smine_nelmts, dxpl_id, bkg_buf/*out*/); + +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[0].bkg_timer), &timer); + sconv->stats[0].bkg_nbytes += n * dst_type_size; + sconv->stats[0].bkg_ncalls++; +#endif + if (n!=smine_nelmts) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed"); + } /* end if */ + + /* + * Perform data type conversion. + */ + if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, 0, 0, tconv_buf, bkg_buf, dxpl_id)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); + + /* + * Scatter the data out to the file. + */ +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + status = H5S_select_fscat(dataset->ent.file, &(dataset->layout), + dc_plist, (H5D_storage_t *)&(dataset->efl), dst_type_size, file_space, &file_iter, + smine_nelmts, dxpl_id, tconv_buf); + +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[0].scat_timer), &timer); + sconv->stats[0].scat_nbytes += smine_nelmts * dst_type_size; + sconv->stats[0].scat_ncalls++; +#endif + if (status<0) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "scatter failed"); + } /* end for */ + +done: +#ifdef H5_HAVE_PARALLEL + /* restore xfer_mode due to the kludge */ + if (doing_mpio && xfer_mode_changed) { +#ifdef H5D_DEBUG + if (H5DEBUG(D)) + fprintf (H5DEBUG(D), "H5D: dx->xfer_mode was COLLECTIVE, restored to INDEPENDENT\n"); +#endif + xfer_mode = H5FD_MPIO_COLLECTIVE; + if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); + } /* end if */ +#endif /*H5_HAVE_PARALLEL*/ + /* Release selection iterators */ + if(file_iter_init) + H5S_select_iter_release(&file_iter); + if(mem_iter_init) + H5S_select_iter_release(&mem_iter); + if(bkg_iter_init) + H5S_select_iter_release(&bkg_iter); + + assert(dx_plist); + if (tconv_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME)) + H5FL_BLK_FREE(type_conv,tconv_buf); + if (bkg_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME)) + 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 + * + * Modifications: + * QAK - 2003/04/17 + * Hacked on it a lot. :-) + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_chunk_read(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, + const H5S_t *file_space, H5T_path_t *tpath, H5S_conv_t *sconv, H5P_genplist_t *dc_plist, + H5P_genplist_t *dx_plist, hid_t dxpl_id, hbool_t +#ifndef H5_HAVE_PARALLEL + UNUSED +#endif /*H5_HAVE_PARALLEL*/ + doing_mpio, H5FD_mpio_xfer_t +#ifndef H5_HAVE_PARALLEL + UNUSED +#endif /*H5_HAVE_PARALLEL*/ + xfer_mode, hid_t src_id, hid_t dst_id, void *buf/*out*/) +{ + fm_map fm_struct; + 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 target_size; /*desired buffer size */ + hsize_t request_nelmts; /*requested strip mine */ + hsize_t smine_start; /*strip mine start loc */ + hsize_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; /*data type conv buffer */ + uint8_t *bkg_buf = NULL; /*background buffer */ + H5D_storage_t store; /*union of EFL and chunk pointer in file space */ + hsize_t h; /* Local index variable */ +#ifdef H5_HAVE_PARALLEL + hbool_t xfer_mode_changed; /* Whether the transfer mode was changed */ +#endif /*H5_HAVE_PARALLEL*/ + herr_t ret_value = SUCCEED; /*return value */ + + FUNC_ENTER_NOINIT(H5D_chunk_read); + + /* Initialize fm_map*/ + HDmemset(&fm_struct, 0, sizeof(fm_map)); + fm_struct.layout = &(dataset->layout); + + /* Map elements between file and memory for each chunk*/ + H5D_chunk_mem_file_map(dataset, mem_type, file_space, mem_space, &fm_struct); + + /* + * If there is no type conversion then read directly into the + * application's buffer. This saves at least one mem-to-mem copy. + */ + if (H5T_IS_NOOP(tpath)) { +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + /* Sanity check dataset, then read it */ + assert(dataset->layout.addr!=HADDR_UNDEF || dataset->efl.nused>0 || + dataset->layout.type==H5D_COMPACT); + + /*loop through each chunk, read data*/ + for(h=0; h<fm_struct.nchunks; h++) { + if(H5S_get_select_npoints(fm_struct.fspace[h]) > 0) { + /*pass in chunk's coordinates in a union. LAYOUT puts datatype size as an extra dimension, + * have to take it out.*/ + store.chunk_coords = fm_struct.chunk_coords + h*dataset->layout.ndims; + + status = (sconv->read)(dataset->ent.file, &(dataset->layout), + dc_plist, &store, H5T_get_size(dataset->type), + fm_struct.fspace[h], fm_struct.mspace[h], dxpl_id, buf/*out*/); + + /* Check return value from optimized read */ + if (status<0) + HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "optimized read failed"); + } /* end if */ + } /* end for */ + +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[1].read_timer), &timer); + sconv->stats[1].read_nbytes += nelmts * H5T_get_size(dataset->type); + sconv->stats[1].read_ncalls++; +#endif + + /* direct xfer accomplished successfully */ + HGOTO_DONE(SUCCEED); + } /* end if */ + + /* + * This is the general case(type conversion). + */ + +#ifdef H5_HAVE_PARALLEL + H5D_io_assist_mpio(dx_plist, doing_mpio, xfer_mode, &xfer_mode_changed); +#endif /*H5_HAVE_PARALLEL*/ + + /* Compute element sizes and other parameters */ + src_type_size = H5T_get_size(dataset->type); + dst_type_size = H5T_get_size(mem_type); + target_size = H5P_peek_size_t(dx_plist,H5D_XFER_MAX_TEMP_BUF_NAME); + request_nelmts = target_size / MAX(src_type_size, dst_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 (tpath->cdata.need_bkg) { + /* Retrieve the bkgr buffer property */ + if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_TYPE_NAME, &need_bkg)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer type"); + need_bkg = MAX(tpath->cdata.need_bkg, need_bkg); + } else { + need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ + } /* end else */ + if (NULL==(tconv_buf=H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME))) { + /* 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=H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))) { + /* Allocate background buffer */ + H5_CHECK_OVERFLOW((request_nelmts*dst_type_size),hsize_t,size_t); + if((bkg_buf=H5FL_BLK_MALLOC(type_conv,(size_t)(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 */ + for(h=0; h<fm_struct.nchunks; h++) { + hsize_t chunk_nelmts; /* Number of elements selected in current chunk */ + + /* Get the number of elements selected in this chunk */ + chunk_nelmts=H5S_get_select_npoints(fm_struct.fspace[h]); + assert(chunk_nelmts<=nelmts); + if(chunk_nelmts > 0) { + /* initialize selection iterator */ + if (H5S_select_iter_init(&file_iter, fm_struct.fspace[h], 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, fm_struct.mspace[h], 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, fm_struct.mspace[h], 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_coords = fm_struct.chunk_coords + h*dataset->layout.ndims; + + for (smine_start=0; smine_start<chunk_nelmts; smine_start+=smine_nelmts) { + /* Go figure out how many elements to read from the file */ + assert(H5S_select_iter_nelmts(&file_iter)==(chunk_nelmts-smine_start)); + smine_nelmts = MIN(request_nelmts, (chunk_nelmts-smine_start)); + + /* + * Gather the data from disk into the data type 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 */ + assert(dataset->layout.addr!=HADDR_UNDEF || dataset->efl.nused>0 || + dataset->layout.type==H5D_COMPACT); + n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), + dc_plist, &store, src_type_size, fm_struct.fspace[h], + &file_iter, smine_nelmts, dxpl_id, tconv_buf/*out*/); + +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[1].gath_timer), &timer); + sconv->stats[1].gath_nbytes += n * src_type_size; + sconv->stats[1].gath_ncalls++; +#endif + if (n!=smine_nelmts) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed"); + + if (need_bkg) { +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + n = H5S_select_mgath(buf, dst_type_size, fm_struct.mspace[h], &bkg_iter, + smine_nelmts, dxpl_id, bkg_buf/*out*/); +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[1].bkg_timer), &timer); + sconv->stats[1].bkg_nbytes += n * dst_type_size; + sconv->stats[1].bkg_ncalls++; +#endif + if (n!=smine_nelmts) + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "mem gather failed"); + } /* end if */ + + /* + * Perform data type conversion. + */ + if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, 0, 0, + tconv_buf, bkg_buf, dxpl_id)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); + + /* + * Scatter the data into memory. + */ +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + status = H5S_select_mscat(tconv_buf, dst_type_size, fm_struct.mspace[h], + &mem_iter, smine_nelmts, dxpl_id, buf/*out*/); +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[1].scat_timer), &timer); + sconv->stats[1].scat_nbytes += smine_nelmts * dst_type_size; + sconv->stats[1].scat_ncalls++; +#endif + if (status<0) + HGOTO_ERROR (H5E_DATASET, H5E_READERROR, FAIL, "scatter failed"); + } /* end for */ + + /* Release selection iterators */ + if(file_iter_init) { + H5S_select_iter_release(&file_iter); + file_iter_init=0; + } /* end if */ + if(mem_iter_init) { + H5S_select_iter_release(&mem_iter); + mem_iter_init=0; + } /* end if */ + if(bkg_iter_init) { + H5S_select_iter_release(&bkg_iter); + bkg_iter_init=0; + } /* end if */ + } /* end if */ + + /*close file space and memory space for each chunk*/ + /*H5S_close(fm_struct.mspace[h]); + H5S_close(fm_struct.fspace[h]);*/ + } /* end for */ + +done: +#ifdef H5_HAVE_PARALLEL + /* restore xfer_mode due to the kludge */ + if (doing_mpio && xfer_mode_changed) { +#ifdef H5D_DEBUG + if (H5DEBUG(D)) + fprintf (H5DEBUG(D), "H5D: dx->xfer_mode was COLLECTIVE, restored to INDEPENDENT\n"); +#endif + xfer_mode = H5FD_MPIO_COLLECTIVE; + if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); + } /* end if */ +#endif /*H5_HAVE_PARALLEL*/ + + assert(dx_plist); + if (tconv_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME)) + H5FL_BLK_FREE(type_conv,tconv_buf); + if (bkg_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME)) + H5FL_BLK_FREE(type_conv,bkg_buf); + + /* Release selection iterators, if necessary */ + if(file_iter_init) + H5S_select_iter_release(&file_iter); + if(mem_iter_init) + H5S_select_iter_release(&mem_iter); + if(bkg_iter_init) + H5S_select_iter_release(&bkg_iter); + + /* Close file space and memory space for each chunk*/ + for(h=0; h<fm_struct.nchunks; h++) { + if(fm_struct.mspace[h]) + H5S_close(fm_struct.mspace[h]); + if(fm_struct.fspace[h]) + H5S_close(fm_struct.fspace[h]); + } + if(fm_struct.fspace) + H5MM_free(fm_struct.fspace); + if(fm_struct.mspace) + H5MM_free(fm_struct.mspace); + + 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 + * + * Modifications: + * QAK - 2003/04/17 + * Hacked on it a lot. :-) + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_chunk_write(hsize_t nelmts, H5D_t *dataset, const H5T_t *mem_type, const H5S_t *mem_space, + const H5S_t *file_space, H5T_path_t *tpath, H5S_conv_t *sconv, H5P_genplist_t *dc_plist, + H5P_genplist_t *dx_plist, hid_t dxpl_id, hbool_t +#ifndef H5_HAVE_PARALLEL + UNUSED +#endif /*H5_HAVE_PARALLEL*/ + doing_mpio, H5FD_mpio_xfer_t +#ifndef H5_HAVE_PARALLEL + UNUSED +#endif /*H5_HAVE_PARALLEL*/ + xfer_mode, hid_t src_id, hid_t dst_id, const void *buf) +{ + fm_map fm_struct; + 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 target_size; /*desired buffer size */ + hsize_t request_nelmts; /*requested strip mine */ + hsize_t smine_start; /*strip mine start loc */ + hsize_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; /*data type conv buffer */ + uint8_t *bkg_buf = NULL; /*background buffer */ + H5D_storage_t store; /*union of EFL and chunk pointer in file space */ + hsize_t h; /* Local index variable */ +#ifdef H5_HAVE_PARALLEL + hbool_t xfer_mode_changed; /* Whether the transfer mode was changed */ +#endif /*H5_HAVE_PARALLEL*/ + herr_t ret_value = SUCCEED; /*return value */ + + FUNC_ENTER_NOINIT(H5D_chunk_write); + + /* Initialize fm_map*/ + HDmemset(&fm_struct, 0, sizeof(fm_map)); + fm_struct.layout = &(dataset->layout); + + /* Map elements between file and memory for each chunk*/ + H5D_chunk_mem_file_map(dataset, mem_type, file_space, mem_space, &fm_struct); + + /* + * If there is no type conversion then write directly from the + * application's buffer. This saves at least one mem-to-mem copy. + */ + if (H5T_IS_NOOP(tpath)) { +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + /*loop through each chunk, write data*/ + for(h=0; h<fm_struct.nchunks; h++) { + if(H5S_get_select_npoints(fm_struct.fspace[h]) > 0) { + /*pass in chunk's coordinates in a union. LAYOUT puts datatype size as an extra dimension, + * have to take it out.*/ + store.chunk_coords = fm_struct.chunk_coords + h*dataset->layout.ndims; + + status = (sconv->write)(dataset->ent.file, &(dataset->layout), + dc_plist, &store, H5T_get_size(dataset->type), + fm_struct.fspace[h], fm_struct.mspace[h], dxpl_id, buf); + + /* Check return value from optimized write */ + if (status<0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "optimized write failed"); + } + } + +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[0].write_timer), &timer); + sconv->stats[0].write_nbytes += nelmts * H5T_get_size(mem_type); + sconv->stats[0].write_ncalls++; +#endif + + /* direct xfer accomplished successfully */ + HGOTO_DONE(SUCCEED); + } /* end if */ + + /* + * This is the general case(type conversion). + */ + +#ifdef H5_HAVE_PARALLEL + H5D_io_assist_mpio(dx_plist, doing_mpio, xfer_mode, &xfer_mode_changed); +#endif /*H5_HAVE_PARALLEL*/ + + /* Compute element sizes and other parameters */ + src_type_size = H5T_get_size(mem_type); + dst_type_size = H5T_get_size(dataset->type); + target_size = H5P_peek_size_t(dx_plist,H5D_XFER_MAX_TEMP_BUF_NAME); + request_nelmts = target_size / MAX (src_type_size, dst_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 (tpath->cdata.need_bkg) { + /* Retrieve the bkgr buffer property */ + if(H5P_get(dx_plist, H5D_XFER_BKGR_BUF_TYPE_NAME, &need_bkg)<0) + HGOTO_ERROR (H5E_PLIST, H5E_CANTGET, FAIL, "Can't retrieve background buffer type"); + need_bkg = MAX (tpath->cdata.need_bkg, need_bkg); + } else if(H5T_detect_class(dataset->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 { + need_bkg = H5T_BKG_NO; /*never needed even if app says yes*/ + } /* end else */ + if (NULL==(tconv_buf=H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME))) { + /* 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=H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME))) { + /* Allocate background buffer */ + H5_CHECK_OVERFLOW((request_nelmts*dst_type_size),hsize_t,size_t); + if((bkg_buf=H5FL_BLK_CALLOC(type_conv,(size_t)(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 */ + for(h=0; h<fm_struct.nchunks; h++) { + hsize_t chunk_nelmts; /* Number of elements selected in current chunk */ + + /* Get the number of elements selected in this chunk */ + chunk_nelmts=H5S_get_select_npoints(fm_struct.fspace[h]); + assert(chunk_nelmts<=nelmts); + if(chunk_nelmts > 0) { + + /* initialize selection iterator */ + if (H5S_select_iter_init(&file_iter, fm_struct.fspace[h], 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, fm_struct.mspace[h], 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, fm_struct.fspace[h], 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_coords = fm_struct.chunk_coords + h*dataset->layout.ndims; + + for (smine_start=0; smine_start<chunk_nelmts; smine_start+=smine_nelmts) { + /* Go figure out how many elements to read from the file */ + assert(H5S_select_iter_nelmts(&file_iter)==(chunk_nelmts-smine_start)); + smine_nelmts = MIN(request_nelmts, (chunk_nelmts-smine_start)); + + /* + * Gather the data from disk into the data type conversion + * buffer. Also gather data from application to background buffer + * if necessary. + */ +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + n = H5S_select_mgath(buf, src_type_size, fm_struct.mspace[h], &mem_iter, + smine_nelmts, dxpl_id, tconv_buf/*out*/); + +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[1].gath_timer), &timer); + sconv->stats[1].gath_nbytes += n * src_type_size; + sconv->stats[1].gath_ncalls++; +#endif + if (n!=smine_nelmts) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed"); + + if (need_bkg) { +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + n = H5S_select_fgath(dataset->ent.file, &(dataset->layout), + dc_plist, &store, dst_type_size, fm_struct.fspace[h], + &bkg_iter, smine_nelmts, dxpl_id, bkg_buf/*out*/); + +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[0].bkg_timer), &timer); + sconv->stats[0].bkg_nbytes += n * dst_type_size; + sconv->stats[0].bkg_ncalls++; +#endif + if (n!=smine_nelmts) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "file gather failed"); + } /* end if */ + + /* + * Perform data type conversion. + */ + if (H5T_convert(tpath, src_id, dst_id, smine_nelmts, 0, 0, + tconv_buf, bkg_buf, dxpl_id)<0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "data type conversion failed"); + + /* + * Scatter the data out to the file. + */ +#ifdef H5S_DEBUG + H5_timer_begin(&timer); +#endif + status = H5S_select_fscat(dataset->ent.file, &(dataset->layout), + dc_plist, &store, dst_type_size, fm_struct.fspace[h], + &file_iter, smine_nelmts, dxpl_id, tconv_buf); + +#ifdef H5S_DEBUG + H5_timer_end(&(sconv->stats[0].scat_timer), &timer); + sconv->stats[0].scat_nbytes += n * dst_type_size; + sconv->stats[0].scat_ncalls++; +#endif + if (status<0) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "scatter failed"); + } /* end for */ + + /* Release selection iterators */ + if(file_iter_init) { + H5S_select_iter_release(&file_iter); + file_iter_init=0; + } /* end if */ + if(mem_iter_init) { + H5S_select_iter_release(&mem_iter); + mem_iter_init=0; + } /* end if */ + if(bkg_iter_init) { + H5S_select_iter_release(&bkg_iter); + bkg_iter_init=0; + } /* end if */ + } /* end if */ + + /*close file space and memory space for each chunk*/ + /*H5S_close(fm_struct.mspace[h]); + H5S_close(fm_struct.fspace[h]);*/ + } /* end for */ + +done: +#ifdef H5_HAVE_PARALLEL + /* restore xfer_mode due to the kludge */ + if (doing_mpio && xfer_mode_changed) { +#ifdef H5D_DEBUG + if (H5DEBUG(D)) + fprintf (H5DEBUG(D), "H5D: dx->xfer_mode was COLLECTIVE, restored to INDEPENDENT\n"); +#endif + xfer_mode = H5FD_MPIO_COLLECTIVE; + if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); + } /* end if */ +#endif /*H5_HAVE_PARALLEL*/ + + assert(dx_plist); + if (tconv_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_TCONV_BUF_NAME)) + H5FL_BLK_FREE(type_conv,tconv_buf); + if (bkg_buf && NULL==H5P_peek_voidp(dx_plist,H5D_XFER_BKGR_BUF_NAME)) + H5FL_BLK_FREE(type_conv,bkg_buf); + + /* Release selection iterators, if necessary */ + if(file_iter_init) + H5S_select_iter_release(&file_iter); + if(mem_iter_init) + H5S_select_iter_release(&mem_iter); + if(bkg_iter_init) + H5S_select_iter_release(&bkg_iter); + + /* Close file space and memory space for each chunk*/ + for(h=0; h<fm_struct.nchunks; h++) { + if(fm_struct.mspace[h]) + H5S_close(fm_struct.mspace[h]); + if(fm_struct.fspace[h]) + H5S_close(fm_struct.fspace[h]); + } + if(fm_struct.fspace) + H5MM_free(fm_struct.fspace); + if(fm_struct.mspace) + H5MM_free(fm_struct.mspace); + + FUNC_LEAVE_NOAPI(ret_value); +} /* H5D_chunk_write() */ + +#ifdef H5_HAVE_PARALLEL + +/*------------------------------------------------------------------------- + * Function: H5D_io_assist_mpio + * + * Purpose: Common logic for determining if the MPI transfer mode should + * be changed. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * Thursday, April 10, 2003 + * + * Modifications: + * QAK - 2003/04/17 + * Hacked on it a lot. :-) + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_io_assist_mpio(H5P_genplist_t *dx_plist, hbool_t doing_mpio, H5FD_mpio_xfer_t xfer_mode, + hbool_t *xfer_mode_changed) +{ + herr_t ret_value = SUCCEED; /*return value */ + + FUNC_ENTER_NOINIT(H5D_io_assist_mpio); + + /* The following may not handle a collective call correctly + * since it does not ensure all processes can handle the write + * request according to the MPI collective specification. + * Do the collective request via independent mode. + */ + if (doing_mpio && xfer_mode==H5FD_MPIO_COLLECTIVE) { + /* Kludge: change the xfer_mode to independent, handle the request, + * then xfer_mode before return. + * Better way is to get a temporary data_xfer property with + * INDEPENDENT xfer_mode and pass it downwards. + */ + xfer_mode = H5FD_MPIO_INDEPENDENT; + if(H5P_set (dx_plist, H5D_XFER_IO_XFER_MODE_NAME, &xfer_mode) < 0) + HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode"); + *xfer_mode_changed=TRUE; /* restore it before return */ +#ifdef H5D_DEBUG + if (H5DEBUG(D)) + fprintf(H5DEBUG(D), "H5D: Cannot handle this COLLECTIVE write request. Do it via INDEPENDENT calls\n"); +#endif + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} +#endif /*H5_HAVE_PARALLEL*/ + + +/*------------------------------------------------------------------------- + * Function: H5D_chunk_coords_assist + * + * Purpose: Compute the coords for a particular chunk (in CHUNK_PTR), + * based on the size of the dataset's dataspace (given in + * NDIMS and CHUNKS), putting the resulting chunk's coordinate + * offsets in the COORDS array. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * Thursday, April 10, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_chunk_coords_assist(hssize_t *coords, size_t ndims, hsize_t chunks[], hsize_t chunk_ptr) +{ + hsize_t tmp; /* Size of "down elements" in each dimension */ + size_t i, j; /* Local index variables */ + + FUNC_ENTER_NOINIT(H5D_chunk_coords_assist); + + for(i=0; i<ndims; i++) { + tmp=1; + for(j=i+1; j<ndims; j++) + tmp *= chunks[j]; + coords[i] = (hssize_t)(chunk_ptr / tmp); + chunk_ptr = chunk_ptr % tmp; + } + coords[ndims] = 0; + + FUNC_LEAVE_NOAPI(SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5D_chunk_mem_file_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 + * + * Modifications: + * QAK - 2003/04/17 + * Hacked on it a lot. :-) + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_chunk_mem_file_map(H5D_t *dataset, const H5T_t *mem_type, const H5S_t *file_space, + const H5S_t *mem_space, fm_map *fm) +{ + H5S_t *tmp_fspace=NULL, /* Temporary file dataspace */ + *tmp_mspace=NULL; /* Temporary memory dataspace */ + hid_t f_tid=(-1); /* Temporary copy of file datatype for iteration */ + size_t elmt_size; /* Memory datatype size */ + hbool_t iter_init=0; /* 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) */ + unsigned m_ndims; /* The number of dimensions of the memory buffer's dataspace */ + hsize_t f_dims[H5O_LAYOUT_NDIMS]; /* Dimensionality of file dataspace */ + char bogus; /* "bogus" buffer to pass to selection iterator */ + unsigned u; /* Local index variable */ + hsize_t j; /* Local index variable */ + herr_t ret_value = SUCCEED; /*return value */ + + FUNC_ENTER_NOINIT(H5D_chunk_mem_file_map); + + /* Create a file space of a chunk's size, instead of whole file space*/ + if(NULL==(tmp_fspace=H5S_create_simple((dataset->layout.ndims-1),dataset->layout.dim,NULL))) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace"); + + /*make a copy of mem_space*/ + if((tmp_mspace = H5S_copy(mem_space))==NULL) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space"); + + /*de-select the file space and mem space copies*/ + if(H5S_select_none(tmp_fspace)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select file space"); + if(H5S_select_none(tmp_mspace)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to de-select memory space"); + + /* Get dim number and dimensionality for each dataspace */ + f_ndims=dataset->layout.ndims-1; + if((sm_ndims = H5S_get_simple_extent_ndims(tmp_mspace))<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimension number"); + fm->m_ndims=m_ndims=sm_ndims; + + if(H5S_get_simple_extent_dims(file_space, f_dims, NULL)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality"); + + /* Decide the number of chunks in each dimension*/ + fm->nchunks = 1; + for(u=0; u<f_ndims; u++) { + fm->chunks[u] = ((f_dims[u]+dataset->layout.dim[u])-1) / dataset->layout.dim[u]; + fm->nchunks *= fm->chunks[u]; + } + + /* 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"); + + /* Allocate arrays to hold each chunk's dataspace & selection, for both the + * file and memory */ + H5_CHECK_OVERFLOW((sizeof(H5S_t*)*fm->nchunks),hsize_t,size_t); + fm->fspace = (H5S_t**)H5MM_malloc((size_t)(sizeof(H5S_t*)*fm->nchunks)); + fm->mspace = (H5S_t**)H5MM_malloc((size_t)(sizeof(H5S_t*)*fm->nchunks)); + fm->elmt_count = 0; + + /* Allocate array to hold coordinates of each chunk in file's dataspace */ + H5_CHECK_OVERFLOW((sizeof(hsize_t)*fm->nchunks*(f_ndims+1)),hsize_t,size_t); + fm->chunk_coords = (hssize_t*)H5MM_malloc((size_t)(sizeof(hsize_t)*fm->nchunks*(f_ndims+1))); + + /* Make per-chunk copies of memory and chunk dataspaces + * (with each one's selection set to "none" + */ + for(j=0; j<fm->nchunks; j++) { + if((fm->mspace[j] = H5S_copy(tmp_mspace))==NULL) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy memory space"); + if((fm->fspace[j] = H5S_copy(tmp_fspace))==NULL) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCOPY, FAIL, "unable to copy file space"); + + /* Initialize chunk_coords for each chunk. each stride is the number of + * file space dimensions, with fast-growing dimension at the last + */ + H5D_chunk_coords_assist(fm->chunk_coords+j*(f_ndims+1), f_ndims, fm->chunks, j); + } + + /* Create temporary datatypes for selection iteration */ + if((f_tid = H5I_register(H5I_DATATYPE, H5T_copy(dataset->type, H5T_COPY_ALL)))<0) + HGOTO_ERROR (H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register file datatype"); + + /* 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), mem_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 */ + + /* Build the file & memory selection for each chunk */ + if(H5S_select_iterate(&bogus, f_tid, file_space, H5D_chunk_cb, fm)<0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTINIT, FAIL, "unable to iterate file space"); + + /* Clean hyperslab span "scratch" information */ + for(j=0; j<fm->nchunks; j++) { + if(H5S_hyper_reset_scratch(fm->fspace[j])<0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info"); + if(H5S_hyper_reset_scratch(fm->mspace[j])<0) + HGOTO_ERROR (H5E_DATASET, H5E_CANTFREE, FAIL, "unable to reset span scratch info"); + } /* end for */ + +done: + if(iter_init) { + if (H5S_select_iter_release(&(fm->mem_iter))<0) + HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); + } + if(tmp_fspace) + H5S_close(tmp_fspace); + if(tmp_mspace) + H5S_close(tmp_mspace); + if(f_tid!=(-1)) + H5Tclose(f_tid); + + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5D_chunk_mem_file_map() */ + + +/*------------------------------------------------------------------------- + * Function: H5D_chunk_cb + * + * Purpose: Callback routine for file selection iterator. Used when + * creating selections in memory and each chunk for each chunk. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * Thursday, April 10, 2003 + * + * Modifications: + * QAK - 2003/04/17 + * Hacked on it a lot. :-) + * + *------------------------------------------------------------------------- + */ +static herr_t +H5D_chunk_cb(void UNUSED *elem, hid_t UNUSED type_id, hsize_t ndims, hssize_t *coords, void *_fm) +{ + fm_map *fm = (fm_map*)_fm; /* File<->memory chunk mapping info */ + hssize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */ + hssize_t coords_in_mem[H5O_LAYOUT_NDIMS]; /* Coordinates of element in memory */ + hsize_t chunk_idx; /* Chunk index */ + hsize_t u; /* Local index variables */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5D_chunk_cb); +#ifdef QAK +{ + unsigned u; + HDfprintf(stderr,"%s: coords={",FUNC); + for(u=0; u<ndims; u++) + HDfprintf(stderr,"%Hd%s",coords[u],(u<(ndims-1)?", ":"}\n")); +} +#endif /* QAK */ + + /* Calculate the index of this chunk */ + if(H5V_chunk_index((unsigned)ndims,coords,fm->layout->dim,fm->chunks,fm->down_chunks,&chunk_idx)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index"); +#ifdef QAK +HDfprintf(stderr,"%s: chunk_idx=%Hu\n",FUNC,chunk_idx); +#endif /* QAK */ + + /*convert coords from relative to whole file space to relative to its chunk space, + *pass into H5S_select_hyperslab.*/ + for(u=0; u<ndims; u++) + coords_in_chunk[u] = coords[u] % fm->layout->dim[u]; + +#ifdef QAK +{ + unsigned u; + HDfprintf(stderr,"%s: coords_in_chunk={",FUNC); + for(u=0; u<ndims; u++) + HDfprintf(stderr,"%Hd%s",coords_in_chunk[u],(u<(ndims-1)?", ":"}\n")); +} +#endif /* QAK */ + /* Add point to file selection for chunk */ + if(H5S_hyper_add_span_element(fm->fspace[chunk_idx], (unsigned)ndims, coords_in_chunk)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element"); + + /* 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"); + +#ifdef QAK +{ + unsigned u; + HDfprintf(stderr,"%s: coords_in_mem={",FUNC); + for(u=0; u<fm->m_ndims; u++) + HDfprintf(stderr,"%Hd%s",coords_in_mem[u],(u<(fm->m_ndims-1)?", ":"}\n")); +} +#endif /* QAK */ + /* Add point to memory selection for chunk */ + if(H5S_hyper_add_span_element(fm->mspace[chunk_idx], fm->m_ndims, coords_in_mem)<0) + HGOTO_ERROR (H5E_DATASPACE, H5E_CANTSELECT, FAIL, "unable to select element"); + + /* Move memory selection iterator to next element in selection */ + if(H5S_select_iter_next(&fm->mem_iter,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_cb() */ diff --git a/src/H5Distore.c b/src/H5Distore.c index 7f8d7e1..9629963 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -1685,246 +1685,154 @@ H5F_istore_unlock(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, /*------------------------------------------------------------------------- - * Function: H5F_istore_read + * Function: H5F_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: Robb Matzke - * Wednesday, October 15, 1997 + * Programmer: Quincey Koziol + * Wednesday, May 7, 2003 * * Modifications: - * Robb Matzke, 1999-08-02 - * The data transfer property list is passed as an object ID - * since that's how the virtual file layer wants it. * - * Quincey Koziol, 2002-04-02 - * Enable hyperslab I/O into memory buffer *------------------------------------------------------------------------- */ -herr_t -H5F_istore_read(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, - const hsize_t size_m[], const hssize_t offset_m[], - const hssize_t offset_f[], const hsize_t size[], void *buf) +ssize_t +H5F_istore_readvv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, + H5P_genplist_t *dc_plist, hssize_t chunk_coords[], + 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[], + void *buf) { - hsize_t idx_cur[H5O_LAYOUT_NDIMS]; - hsize_t idx_min[H5O_LAYOUT_NDIMS]; - hsize_t idx_max[H5O_LAYOUT_NDIMS]; - hsize_t sub_size[H5O_LAYOUT_NDIMS]; - hssize_t offset_wrt_chunk[H5O_LAYOUT_NDIMS]; - hssize_t sub_offset_m[H5O_LAYOUT_NDIMS]; - hssize_t chunk_offset[H5O_LAYOUT_NDIMS]; - int i, carry; - unsigned u; - hsize_t naccessed; /*bytes accessed in chnk*/ - uint8_t *chunk=NULL; /*ptr to a chunk buffer */ - unsigned idx_hint=0; /*cache index hint */ - hsize_t chunk_size; /* Bytes in chunk */ + hsize_t chunk_size; /* Chunk size, in bytes */ haddr_t chunk_addr; /* Chunk address on disk */ + hssize_t chunk_coords_in_elmts[H5O_LAYOUT_NDIMS]; H5O_pline_t pline; /* I/O pipeline information */ - H5O_fill_t fill; /* Fill value information */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_istore_read, FAIL); + size_t u; /* Local index variables */ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_istore_readvv, FAIL); /* Check args */ assert(f); assert(layout && H5D_CHUNKED==layout->type); assert(layout->ndims>0 && layout->ndims<=H5O_LAYOUT_NDIMS); - assert(H5F_addr_defined(layout->addr)); - assert(size_m); - assert(offset_m); - assert(offset_f); - assert(size); + assert(chunk_len_arr); + assert(chunk_offset_arr); + assert(mem_len_arr); + assert(mem_offset_arr); assert(buf); /* Get necessary properties from property list */ - if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value"); if(H5P_get(dc_plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data pipeline"); /* Compute chunk size */ for (u=0, chunk_size=1; u<layout->ndims; u++) chunk_size *= layout->dim[u]; - + #ifndef NDEBUG - for (u=0; u<layout->ndims; u++) { - assert(offset_f[u]>=0); /*negative offsets not supported*/ - assert(offset_m[u]>=0); /*negative offsets not supported*/ - assert(size[u]<SIZET_MAX); - assert(offset_m[u]+(hssize_t)size[u]<=(hssize_t)size_m[u]); - assert(layout->dim[u]>0); - } + for (u=0; u<layout->ndims; u++) + assert(chunk_coords[u]>=0); /*negative coordinates not supported (yet) */ #endif + + for (u=0; u<layout->ndims; u++) + chunk_coords_in_elmts[u] = chunk_coords[u] * (hssize_t)(layout->dim[u]); + + /* Get the address of this chunk on disk */ + chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_coords_in_elmts); /* - * Set up multi-dimensional counters (idx_min, idx_max, and idx_cur) and - * loop through the chunks copying each to its final destination in the - * application buffer. + * 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. */ - for (u=0; u<layout->ndims; u++) { - idx_min[u] = offset_f[u] / layout->dim[u]; - idx_max[u] = (offset_f[u]+size[u]-1) / layout->dim[u] + 1; - idx_cur[u] = idx_min[u]; - } - - /* Loop over all chunks */ - carry=0; - while (carry==0) { - for (u=0, naccessed=1; u<layout->ndims; u++) { - /* The location and size of the chunk being accessed */ - assert(layout->dim[u] < HSSIZET_MAX); - chunk_offset[u] = idx_cur[u] * (hssize_t)(layout->dim[u]); - - /* The offset and size wrt the chunk */ - offset_wrt_chunk[u] = MAX(offset_f[u], chunk_offset[u]) - - chunk_offset[u]; - sub_size[u] = MIN((idx_cur[u]+1)*layout->dim[u], - offset_f[u]+size[u]) - - (chunk_offset[u] + offset_wrt_chunk[u]); - naccessed *= sub_size[u]; - - /* Offset into mem buffer */ - sub_offset_m[u] = chunk_offset[u] + offset_wrt_chunk[u] + - offset_m[u] - offset_f[u]; - } + if (chunk_size>f->shared->rdcc_nbytes && pline.nfilters==0 && + chunk_addr!=HADDR_UNDEF) { + if ((ret_value=H5F_contig_readvv(f, chunk_size, chunk_addr, chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_offset_arr, mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, dxpl_id, buf))<0) + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "unable to read raw data to file"); + } /* end if */ + else { + uint8_t *chunk; /* Pointer to cached chunk in memory */ + H5O_fill_t fill; /* Fill value information */ + unsigned idx_hint=0; /* Cache index hint */ + ssize_t naccessed; /* Number of bytes accessed in chunk */ - /* Get the address of this chunk on disk */ - chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_offset); + /* Get necessary properties from property list */ + if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value"); /* - * 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. + * Lock the chunk, copy from application to chunk, then unlock the + * chunk. */ - if ((chunk_size>f->shared->rdcc_nbytes && pline.nfilters==0 && - chunk_addr!=HADDR_UNDEF) + if (NULL==(chunk=H5F_istore_lock(f, dxpl_id, layout, &pline, &fill, + chunk_coords_in_elmts, FALSE, &idx_hint))) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk"); - /* - * If MPIO, MPIPOSIX, or FPHDF5 is used and file can be written - * to, we 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. - */ - || ((IS_H5FD_MPIO(f) ||IS_H5FD_MPIPOSIX(f) || IS_H5FD_FPHDF5(f)) && (H5F_ACC_RDWR & f->shared->flags)) - ) { - H5O_layout_t l; /* temporary layout */ + /* 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"); -#ifdef H5_HAVE_PARALLEL - /* Additional sanity checks when operating in parallel */ - if (chunk_addr==HADDR_UNDEF || pline.nfilters>0) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to locate raw data chunk"); -#endif /* H5_HAVE_PARALLEL */ - - /* - * use default transfer mode as we do not support collective - * transfer mode since each data write could decompose into - * multiple chunk writes and we are not doing the calculation yet. - */ - l.type = H5D_CONTIGUOUS; - l.ndims = layout->ndims; - for (u=l.ndims; u-- > 0; /*void*/) - l.dim[u] = layout->dim[u]; - l.addr = chunk_addr; - if (H5F_arr_read(f, dxpl_id, &l, dc_plist, sub_size, size_m, sub_offset_m, offset_wrt_chunk, buf)<0) - HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "unable to read raw data from file"); - } /* end if */ - else { - /* - * Lock the chunk, transfer data to the application, then unlock - * the chunk. - */ - if (NULL==(chunk=H5F_istore_lock(f, dxpl_id, layout, &pline, &fill, - chunk_offset, FALSE, &idx_hint))) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk"); - H5V_hyper_copy(layout->ndims, sub_size, size_m, sub_offset_m, - (void*)buf, layout->dim, offset_wrt_chunk, chunk); - H5_CHECK_OVERFLOW(naccessed,hsize_t,size_t); - if (H5F_istore_unlock(f, dxpl_id, layout, &pline, FALSE, - chunk_offset, &idx_hint, chunk, (size_t)naccessed)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk"); - } /* end else */ - - /* Increment indices */ - for (i=(int)(layout->ndims-1), carry=1; i>=0 && carry; --i) { - if (++idx_cur[i]>=idx_max[i]) - idx_cur[i] = idx_min[i]; - else - carry = 0; - } - } + H5_CHECK_OVERFLOW(naccessed,ssize_t,size_t); + if (H5F_istore_unlock(f, dxpl_id, layout, &pline, FALSE, + chunk_coords_in_elmts, &idx_hint, chunk, (size_t)naccessed)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk"); + /* Set return value */ + ret_value=naccessed; + } /* end else */ + done: FUNC_LEAVE_NOAPI(ret_value); -} +} /* H5F_istore_readvv() */ /*------------------------------------------------------------------------- - * Function: H5F_istore_write + * Function: H5F_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: Robb Matzke - * Wednesday, October 15, 1997 + * Programmer: Quincey Koziol + * Friday, May 2, 2003 * * Modifications: - * Robb Matzke, 1999-08-02 - * The data transfer property list is passed as an object ID - * since that's how the virtual file layer wants it. * - * Quincey Koziol, 2002-04-02 - * Enable hyperslab I/O into memory buffer *------------------------------------------------------------------------- */ -herr_t -H5F_istore_write(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, - const hsize_t size_m[], const hssize_t offset_m[], - const hssize_t offset_f[], const hsize_t size[], - const void *buf) +ssize_t +H5F_istore_writevv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, + H5P_genplist_t *dc_plist, hssize_t chunk_coords[], + 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[], + const void *buf) { - int i, carry; - unsigned u; - hsize_t idx_cur[H5O_LAYOUT_NDIMS]; - hsize_t idx_min[H5O_LAYOUT_NDIMS]; - hsize_t idx_max[H5O_LAYOUT_NDIMS]; - hsize_t sub_size[H5O_LAYOUT_NDIMS]; - hssize_t chunk_offset[H5O_LAYOUT_NDIMS]; - hssize_t offset_wrt_chunk[H5O_LAYOUT_NDIMS]; - hssize_t sub_offset_m[H5O_LAYOUT_NDIMS]; - uint8_t *chunk=NULL; - unsigned idx_hint=0; - hsize_t chunk_size, naccessed; + hsize_t chunk_size; /* Chunk size, in bytes */ haddr_t chunk_addr; /* Chunk address on disk */ + hssize_t chunk_coords_in_elmts[H5O_LAYOUT_NDIMS]; H5O_pline_t pline; /* I/O pipeline information */ - H5O_fill_t fill; /* Fill value information */ - herr_t ret_value = SUCCEED; /* Return value */ + size_t u; /* Local index variables */ + ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5F_istore_write, FAIL); + FUNC_ENTER_NOAPI(H5F_istore_writevv, FAIL); /* Check args */ assert(f); assert(layout && H5D_CHUNKED==layout->type); assert(layout->ndims>0 && layout->ndims<=H5O_LAYOUT_NDIMS); - assert(H5F_addr_defined(layout->addr)); - assert(size_m); - assert(offset_m); - assert(offset_f); - assert(size); + assert(chunk_len_arr); + assert(chunk_offset_arr); + assert(mem_len_arr); + assert(mem_offset_arr); assert(buf); /* Get necessary properties from property list */ - if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value"); if(H5P_get(dc_plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data pipeline"); @@ -1933,118 +1841,79 @@ H5F_istore_write(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, chunk_size *= layout->dim[u]; #ifndef NDEBUG - for (u=0; u<layout->ndims; u++) { - assert(offset_f[u]>=0); /*negative offsets not supported*/ - assert(offset_m[u]>=0); /*negative offsets not supported*/ - assert(size[u]<SIZET_MAX); - assert(offset_m[u]+(hssize_t)size[u]<=(hssize_t)size_m[u]); - assert(layout->dim[u]>0); - } + for (u=0; u<layout->ndims; u++) + assert(chunk_coords[u]>=0); /*negative coordinates not supported (yet) */ #endif + + for (u=0; u<layout->ndims; u++) + chunk_coords_in_elmts[u] = chunk_coords[u] * (hssize_t)(layout->dim[u]); + + /* Get the address of this chunk on disk */ + chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_coords_in_elmts); /* - * Set up multi-dimensional counters (idx_min, idx_max, and idx_cur) and - * loop through the chunks copying each chunk from the application to the - * chunk 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 write the data to it directly. + * + * If MPIO, MPIPOSIX, or FPHDF5 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. */ - for (u=0; u<layout->ndims; u++) { - idx_min[u] = offset_f[u] / layout->dim[u]; - idx_max[u] = (offset_f[u]+size[u]-1) / layout->dim[u] + 1; - idx_cur[u] = idx_min[u]; - } - - - /* Loop over all chunks */ - carry=0; - while (carry==0) { - for (u=0, naccessed=1; u<layout->ndims; u++) { - /* The location and size of the chunk being accessed */ - assert(layout->dim[u] < HSSIZET_MAX); - chunk_offset[u] = idx_cur[u] * (hssize_t)(layout->dim[u]); - - /* The offset and size wrt the chunk */ - offset_wrt_chunk[u] = MAX(offset_f[u], chunk_offset[u]) - - chunk_offset[u]; - sub_size[u] = MIN((idx_cur[u]+1)*layout->dim[u], - offset_f[u]+size[u]) - - (chunk_offset[u] + offset_wrt_chunk[u]); - naccessed *= sub_size[u]; - - /* Offset into mem buffer */ - sub_offset_m[u] = chunk_offset[u] + offset_wrt_chunk[u] + - offset_m[u] - offset_f[u]; - } - - /* Get the address of this chunk on disk */ - chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_offset); + if ((chunk_size>f->shared->rdcc_nbytes && pline.nfilters==0 && + chunk_addr!=HADDR_UNDEF) + || ((IS_H5FD_MPIO(f) ||IS_H5FD_MPIPOSIX(f) || IS_H5FD_FPHDF5(f)) && + (H5F_ACC_RDWR & f->shared->flags))) { +#ifdef H5_HAVE_PARALLEL + /* Additional sanity check when operating in parallel */ + if (chunk_addr==HADDR_UNDEF || pline.nfilters>0) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to locate raw data chunk"); +#endif /* H5_HAVE_PARALLEL */ + if ((ret_value=H5F_contig_writevv(f, chunk_size, chunk_addr, chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_offset_arr, mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, dxpl_id, buf))<0) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file"); + } /* end if */ + else { + uint8_t *chunk; /* Pointer to cached chunk in memory */ + H5O_fill_t fill; /* Fill value information */ + unsigned idx_hint=0; /* Cache index hint */ + ssize_t naccessed; /* Number of bytes accessed in chunk */ + hbool_t relax; /* Whether whole chunk is selected */ - /* - * 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 ((chunk_size>f->shared->rdcc_nbytes && pline.nfilters==0 && - chunk_addr!=HADDR_UNDEF) + /* Get necessary properties from property list */ + if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value"); /* - * If MPIO, MPIPOSIX, or FPHDF5 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. + * Lock the chunk, copy from application to chunk, then unlock the + * chunk. */ - || ((IS_H5FD_MPIO(f) ||IS_H5FD_MPIPOSIX(f) || IS_H5FD_FPHDF5(f)) && (H5F_ACC_RDWR & f->shared->flags)) - ) { - H5O_layout_t l; /* temporary layout */ - -#ifdef H5_HAVE_PARALLEL - /* Additional sanity check when operating in parallel */ - if (chunk_addr==HADDR_UNDEF || pline.nfilters>0) { - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to locate raw data chunk"); - } -#endif /* H5_HAVE_PARALLEL */ - - /* - * use default transfer mode as we do not support collective - * transfer mode since each data write could decompose into - * multiple chunk writes and we are not doing the calculation yet. - */ - l.type = H5D_CONTIGUOUS; - l.ndims = layout->ndims; - for (u=l.ndims; u-- > 0; /*void*/) - l.dim[u] = layout->dim[u]; - l.addr = chunk_addr; - if (H5F_arr_write(f, dxpl_id, &l, dc_plist, sub_size, size_m, sub_offset_m, offset_wrt_chunk, buf)<0) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file"); - } /* end if */ - else { - /* - * Lock the chunk, copy from application to chunk, then unlock the - * chunk. - */ - if (NULL==(chunk=H5F_istore_lock(f, dxpl_id, layout, &pline, &fill, - chunk_offset, (hbool_t)(naccessed==chunk_size), &idx_hint))) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to read raw data chunk"); - H5V_hyper_copy(layout->ndims, sub_size, - layout->dim, offset_wrt_chunk, chunk, size_m, sub_offset_m, buf); - H5_CHECK_OVERFLOW(naccessed,hsize_t,size_t); - if (H5F_istore_unlock(f, dxpl_id, layout, &pline, TRUE, - chunk_offset, &idx_hint, chunk, (size_t)naccessed)<0) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "uanble to unlock raw data chunk"); - } /* end else */ + if(chunk_max_nseq==1 && chunk_len_arr[0] == chunk_size) + relax = TRUE; + else + relax = FALSE; + + if (NULL==(chunk=H5F_istore_lock(f, dxpl_id, layout, &pline, &fill, + chunk_coords_in_elmts, relax, &idx_hint))) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to read raw data 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); + if (H5F_istore_unlock(f, dxpl_id, layout, &pline, TRUE, + chunk_coords_in_elmts, &idx_hint, chunk, (size_t)naccessed)<0) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "uanble to unlock raw data chunk"); + + /* Set return value */ + ret_value=naccessed; + } /* end else */ - /* Increment indices */ - for (i=layout->ndims-1, carry=1; i>=0 && carry; --i) { - if (++idx_cur[i]>=idx_max[i]) - idx_cur[i] = idx_min[i]; - else - carry = 0; - } - } /* end while */ - done: FUNC_LEAVE_NOAPI(ret_value); -} +} /* H5F_istore_writevv() */ /*------------------------------------------------------------------------- @@ -2808,7 +2677,8 @@ H5F_istore_initialize_by_extent(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *lay hsize_t size[H5O_LAYOUT_NDIMS]; /*current size of dimensions */ H5S_t *space_chunk = NULL; /*dataspace for a chunk */ hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /*current dataspace dimensions */ - int rank; /*current # of dimensions */ + int srank; /*current # of dimensions (signed) */ + unsigned rank; /*current # of dimensions */ int i, carry; /*counters */ unsigned u; int found = 0; /*initialize this entry */ @@ -2836,13 +2706,14 @@ H5F_istore_initialize_by_extent(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *lay HDmemset(count, 0, sizeof(count)); /* Go get the rank & dimensions */ - if((rank = H5S_get_simple_extent_dims(space, curr_dims, NULL)) < 0) + if((srank = H5S_get_simple_extent_dims(space, curr_dims, NULL)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions"); + rank=srank; /* Copy current dimensions */ - for(i = 0; i < rank; i++) - size[i] = curr_dims[i]; - size[i] = layout->dim[i]; + for(u = 0; u < rank; u++) + size[u] = curr_dims[u]; + size[u] = layout->dim[u]; /* Create a data space for a chunk & set the extent */ if(NULL == (space_chunk = H5S_create_simple(rank,layout->dim,NULL))) @@ -2891,8 +2762,8 @@ H5F_istore_initialize_by_extent(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *lay if(H5S_select_all(space_chunk,1) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to select space"); - for(i = 0; i < rank; i++) - count[i] = MIN((idx_cur[i] + 1) * layout->dim[i], size[i] - chunk_offset[i]); + for(u = 0; u < rank; u++) + count[u] = MIN((idx_cur[u] + 1) * layout->dim[u], size[u] - chunk_offset[u]); #if defined (H5F_ISTORE_DEBUG) HDfputs("cache:initialize:offset:[", stdout); diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h new file mode 100644 index 0000000..093360b --- /dev/null +++ b/src/H5Dpkg.h @@ -0,0 +1,76 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Monday, April 14, 2003 + * + * Purpose: This file contains declarations which are visible only within + * the H5D package. Source files outside the H5D package should + * include H5Dprivate.h instead. + */ +#ifndef H5D_PACKAGE +#error "Do not include this file outside the H5D package!" +#endif + +#ifndef _H5Dpkg_H +#define _H5Dpkg_H + +/* Get package's private header */ +#include "H5Dprivate.h" + +/* Other private headers needed by this file */ +#include "H5Gprivate.h" /* Group headers */ +#include "H5Oprivate.h" /* Object headers */ +#include "H5Sprivate.h" /* Dataspace functions */ +#include "H5Tprivate.h" /* Datatype functions */ + +/* The number of reserved IDs in dataset ID group */ +#define H5D_RESERVED_ATOMS 0 + +/* Set the minimum object header size to create objects with */ +#define H5D_MINHDR_SIZE 256 + +/****************************/ +/* Package Private Typedefs */ +/****************************/ + +/* + * A dataset is the following struct. + */ +struct H5D_t { + H5G_entry_t ent; /* cached object header stuff */ + H5T_t *type; /* datatype of this dataset */ + H5S_t *space; /* dataspace of this dataset */ + hid_t dcpl_id; /* dataset creation property id */ + H5O_layout_t layout; /* data layout */ + /* Cache some frequently accessed values from the DCPL */ + H5O_efl_t efl; /* External file list information */ + H5D_alloc_time_t alloc_time; /* Dataset allocation time */ + H5D_fill_time_t fill_time; /* Dataset fill value writing time */ + H5O_fill_t fill; /* Dataset fill value information */ +}; + +/* Enumerated type for allocating dataset's storage */ +typedef enum { + H5D_ALLOC_CREATE, /* Dataset is being created */ + H5D_ALLOC_OPEN, /* Dataset is being opened */ + H5D_ALLOC_EXTEND, /* Dataset's dataspace is being extended */ + H5D_ALLOC_WRITE /* Dataset is being extended */ +} H5D_time_alloc_t; + +/* Package-private functions defined in H5D package */ +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); +#endif /*_H5Dpkg_H*/ diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index e69b0ad..38c13b7 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -21,13 +21,7 @@ #include "H5Dpublic.h" /* Private headers needed by this file */ -#include "H5private.h" -#include "H5Fprivate.h" /*for the H5F_t type */ -#include "H5Gprivate.h" /*symbol tables */ -#include "H5MMpublic.h" /*for H5MM_allocate_t and H5MM_free_t types */ -#include "H5Oprivate.h" /*object Headers */ -#include "H5Sprivate.h" /*for the H5S_t type */ -#include "H5Tprivate.h" /*for the H5T_t type */ +#include "H5Oprivate.h" /* Object headers */ /* * Feature: Define H5D_DEBUG on the compiler command line if you want to @@ -38,11 +32,6 @@ # undef H5D_DEBUG #endif -#define H5D_RESERVED_ATOMS 0 - -/* Set the minimum object header size to create objects with */ -#define H5D_MINHDR_SIZE 256 - /* ======== Dataset creation properties ======== */ /* Definitions for storage layout property */ #define H5D_CRT_LAYOUT_NAME "layout" @@ -50,7 +39,7 @@ #define H5D_CRT_LAYOUT_DEF H5D_CONTIGUOUS /* Definitions for chunk dimensionality property */ #define H5D_CRT_CHUNK_DIM_NAME "chunk_ndims" -#define H5D_CRT_CHUNK_DIM_SIZE sizeof(int) +#define H5D_CRT_CHUNK_DIM_SIZE sizeof(unsigned) #define H5D_CRT_CHUNK_DIM_DEF 1 /* Definitions for chunk size */ #define H5D_CRT_CHUNK_SIZE_NAME "chunk_size" @@ -155,23 +144,20 @@ #define H5D_XFER_FILTER_CB_SIZE sizeof(H5Z_cb_t) #define H5D_XFER_FILTER_CB_DEF {NULL,NULL} -/* - * A dataset is the following struct. - */ -typedef struct H5D_t { - H5G_entry_t ent; /* cached object header stuff */ - H5T_t *type; /* datatype of this dataset */ - H5S_t *space; /* dataspace of this dataset */ - hid_t dcpl_id; /* dataset creation property id */ - H5O_layout_t layout; /* data layout */ - /* Cache some frequently accessed values from the DCPL */ - H5O_efl_t efl; /* External file list information */ - H5D_alloc_time_t alloc_time; /* Dataset allocation time */ - H5D_fill_time_t fill_time; /* Dataset fill value writing time */ - H5O_fill_t fill; /* Dataset fill value information */ -} H5D_t; - -/* Functions defined in H5D.c */ +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +/* Typedef for reference counted string (defined in H5Dpkg.h) */ +typedef struct H5D_t H5D_t; + +/* Typedef for dataset storage information */ +typedef union H5D_storage_t { + H5O_efl_t efl; /* External file list information for dataset */ + hssize_t *chunk_coords; /* chunk's coordinates in file chunks */ +} H5D_storage_t; + +/* Library-private functions defined in H5D package */ H5_DLL herr_t H5D_init(void); H5_DLL hid_t H5D_open(H5G_entry_t *ent, hid_t dxpl_id); H5_DLL htri_t H5D_isa(H5G_entry_t *ent, hid_t dxpl_id); diff --git a/src/H5Dseq.c b/src/H5Dseq.c index 113a8d5..5248b0a 100644 --- a/src/H5Dseq.c +++ b/src/H5Dseq.c @@ -70,22 +70,24 @@ static int interface_initialize_g = 0; */ herr_t H5F_seq_read(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, + H5P_genplist_t *dc_plist, const H5D_storage_t *store, size_t seq_len, hsize_t dset_offset, void *buf/*out*/) { - herr_t ret_value=SUCCEED; /* Return value */ + hsize_t mem_off=0; /* Offset in memory */ + size_t mem_len=seq_len; /* Length in memory */ + size_t mem_curr_seq=0; /* "Current sequence" in memory */ + size_t dset_curr_seq=0; /* "Current sequence" in dataset */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_seq_read, FAIL); /* Check args */ assert(f); assert(layout); - assert(efl); assert(buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) + if (H5F_seq_readvv(f, dxpl_id, layout, dc_plist, store, 1, &dset_curr_seq, &seq_len, &dset_offset, 1, &mem_curr_seq, &mem_len, &mem_off, buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vector read failed"); done: @@ -116,22 +118,24 @@ done: */ herr_t H5F_seq_write(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, + H5P_genplist_t *dc_plist, const H5D_storage_t *store, size_t seq_len, hsize_t dset_offset, const void *buf) { - herr_t ret_value=SUCCEED; /* Return value */ + hsize_t mem_off=0; /* Offset in memory */ + size_t mem_len=seq_len; /* Length in memory */ + size_t mem_curr_seq=0; /* "Current sequence" in memory */ + size_t dset_curr_seq=0; /* "Current sequence" in dataset */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_seq_write, FAIL); /* Check args */ assert(f); assert(layout); - assert(efl); assert(buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) + if (H5F_seq_writevv(f, dxpl_id, layout, dc_plist, store, 1, &dset_curr_seq, &seq_len, &dset_offset, 1, &mem_curr_seq, &mem_len, &mem_off, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed"); done: @@ -140,7 +144,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_seq_readv + * Function: H5F_seq_readvv * * Purpose: Reads in a vector of byte sequences from a file dataset into a * buffer in in memory. The data is read from file F and the array's size @@ -152,53 +156,61 @@ done: * Bytes read into BUF are sequentially stored in the buffer, each sequence * from the vector stored directly after the previous. The number of * sequences is NSEQ. + * Purpose: Reads a vector of byte sequences from a vector of byte + * sequences in a file dataset into a buffer in memory. The data is + * read from file F and the array's size and storage information is in + * LAYOUT. External files and chunks are described according to the + * storage information, STORE. The vector of byte sequences offsets for + * the file is in the DSET_OFFSET_ARR array into the dataset (offsets are + * in terms of bytes) and the size of each sequence is in the DSET_LEN_ARR + * array. The vector of byte sequences offsets for memory is in the + * MEM_OFFSET_ARR array into the dataset (offsets are in terms of bytes) + * and the size of each sequence is in the MEM_LEN_ARR array. The total + * size of the file array is implied in the LAYOUT argument. The maximum + * number of sequences in the file dataset and the memory buffer are + * DSET_MAX_NSEQ & MEM_MAX_NSEQ respectively. The current sequence being + * operated on in the file dataset and the memory buffer are DSET_CURR_SEQ + * & MEM_CURR_SEQ respectively. The current sequence being operated on + * will be updated as a result of the operation, as will the offsets and + * lengths of the file dataset and memory buffer sequences. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Wednesday, May 1, 2001 + * Wednesday, May 7, 2003 * * Modifications: * *------------------------------------------------------------------------- */ -herr_t -H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, - size_t nseq, size_t seq_len_arr[], hsize_t dset_offset_arr[], - void *_buf/*out*/) +ssize_t +H5F_seq_readvv(H5F_t *f, hid_t dxpl_id, const struct H5O_layout_t *layout, + struct H5P_genplist_t *dc_plist, const H5D_storage_t *store, + 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[], + void *buf/*out*/) { - unsigned char *real_buf=(unsigned char *)_buf; /* Local pointer to buffer to fill */ - unsigned char *buf; /* Local pointer to buffer to fill */ - hsize_t dset_offset; /* Offset in dataset */ - hsize_t seq_len; /* Number of bytes to read */ - hsize_t dset_dims[H5O_LAYOUT_NDIMS]; /* dataspace dimensions */ - hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in memory buffer */ - hssize_t coords[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in dataspace */ - hsize_t hslab_size[H5O_LAYOUT_NDIMS]; /* hyperslab size in dataspace*/ - hsize_t down_size[H5O_LAYOUT_NDIMS]; /* Cumulative yperslab sizes (in elements) */ - hsize_t acc; /* Accumulator for hyperslab sizes (in elements) */ - int ndims; - hsize_t max_data; /*bytes in dataset */ - haddr_t addr=0; /*address in file */ - unsigned u; /*counters */ - size_t v; /*counters */ - int i,j; /*counters */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; #endif /* H5_HAVE_PARALLEL */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5F_seq_readv, FAIL); + FUNC_ENTER_NOAPI(H5F_seq_readvv, FAIL); /* Check args */ assert(f); + assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); /* Make certain we have the correct type of property list */ assert(layout); - assert(efl); - assert(real_buf); - /* Make certain we have the correct type of property list */ - assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); + assert(dc_plist); + assert(dset_curr_seq); + assert(*dset_curr_seq<dset_max_nseq); + assert(dset_len_arr); + assert(dset_offset_arr); + assert(mem_curr_seq); + assert(*mem_curr_seq<mem_max_nseq); + assert(mem_len_arr); + assert(mem_offset_arr); + assert(buf); #ifdef H5_HAVE_PARALLEL /* Get the transfer mode for MPIO transfers */ @@ -229,285 +241,52 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, switch (layout->type) { case H5D_CONTIGUOUS: /* Read directly from file if the dataset is in an external file */ - if (efl->nused>0) { - /* Iterate through the sequence vectors */ - for(v=0; v<nseq; v++) { -#ifdef H5_HAVE_PARALLEL - if (H5FD_MPIO_COLLECTIVE==xfer_mode) { - /* - * Currently supports same number of collective access. Need to - * be changed LATER to combine all reads into one collective MPIO - * call. - */ - unsigned long max, min, temp; - - temp = seq_len_arr[v]; - assert(temp==seq_len_arr[v]); /* verify no overflow */ - MPI_Allreduce(&temp, &max, 1, MPI_UNSIGNED_LONG, MPI_MAX, - H5FD_mpio_communicator(f->shared->lf)); - MPI_Allreduce(&temp, &min, 1, MPI_UNSIGNED_LONG, MPI_MIN, - H5FD_mpio_communicator(f->shared->lf)); -#ifdef AKC - printf("seq_len=%lu, min=%lu, max=%lu\n", temp, min, max); -#endif - if (max != min) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, - "collective access with unequal number of blocks not supported yet"); - } -#endif /* H5_HAVE_PARALLEL */ - /* Note: We can't use data sieve buffers for datasets in external files - * because the 'addr' of all external files is set to 0 (above) and - * all datasets in external files would alias to the same set of - * file offsets, totally mixing up the data sieve buffer information. -QAK - */ - H5_CHECK_OVERFLOW(dset_offset_arr[v],hsize_t,haddr_t); - if (H5O_efl_read(f, efl, (haddr_t)dset_offset_arr[v], seq_len_arr[v], real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "external data read failed"); - - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ + if (store && store->efl.nused>0) { + /* Note: We can't use data sieve buffers for datasets in external files + * because the 'addr' of all external files is set to 0 (above) and + * all datasets in external files would alias to the same set of + * file offsets, totally mixing up the data sieve buffer information. -QAK + */ + if((ret_value=H5O_efl_readvv(&(store->efl), + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "external data read failed"); } else { + hsize_t max_data; /*bytes in dataset */ + unsigned u; /*counters */ + /* Compute the size of the dataset in bytes */ for(u=1, max_data=layout->dim[0]; u<layout->ndims; u++) max_data *= layout->dim[u]; /* Pass along the vector of sequences to read */ - if (H5F_contig_readv(f, max_data, H5FD_MEM_DRAW, layout->addr, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) + if((ret_value=H5F_contig_readvv(f, max_data, layout->addr, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); } /* end else */ break; case H5D_CHUNKED: - /* - * This method is unable to access external raw data files - */ - if (efl->nused>0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); - - /* Compute the file offset coordinates and hyperslab size */ - if((ndims=H5S_get_simple_extent_dims(file_space,dset_dims,NULL))<0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unable to retrieve dataspace dimensions"); - - /* Build the array of cumulative hyperslab sizes */ - /* (And set the memory offset to zero) */ - for(acc=1, i=(ndims-1); i>=0; i--) { - mem_offset[i]=0; - down_size[i]=acc; - acc*=dset_dims[i]; - } /* end for */ - mem_offset[ndims]=0; - - /* Brute-force, stupid way to implement the vectors, but too complex to do other ways... */ - for(v=0; v<nseq; v++) { - dset_offset=dset_offset_arr[v]; - seq_len=seq_len_arr[v]; - buf=real_buf; - - { - /* Set location in dataset from the dset_offset */ - addr=dset_offset; - - /* Convert the bytes into elements */ - seq_len/=elmt_size; - addr/=elmt_size; - - /* Compute the hyperslab offset from the address given */ - for(i=ndims-1; i>=0; i--) { - coords[i]=addr%dset_dims[i]; - addr/=dset_dims[i]; - } /* end for */ - coords[ndims]=0; /* No offset for element info */ - - /* - * Peel off initial partial hyperslabs until we've got a hyperslab which starts - * at coord[n]==0 for dimensions 1->(ndims-1) (i.e. starting at coordinate - * zero for all dimensions except the slowest changing one - */ - for(i=ndims-1; i>0 && seq_len>=down_size[i]; i--) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* Check if we have a partial hyperslab in this lower dimension */ - if(coords[i]>0) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(i==j) - hslab_size[j]=MIN(seq_len/down_size[i],dset_dims[i]-coords[i]); - else - if(j>i) - hslab_size[j]=dset_dims[j]; - else - hslab_size[j]=1; - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read in the partial hyperslab */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, - buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Increment the buffer offset */ - buf=(unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=0; - coords[i-1]++; - - /* Carry the coord array correction up the array, if the dimension is finished */ - while(i>0 && coords[i-1]==(hssize_t)dset_dims[i-1]) { - i--; - coords[i]=0; - if(i>0) { - coords[i-1]++; - assert(coords[i-1]<=(hssize_t)dset_dims[i-1]); - } /* end if */ - } /* end while */ - } /* end if */ - } /* end for */ - - /* Check if there is more than just a partial hyperslab to read */ - if(seq_len>=down_size[0]) { - hsize_t tmp_seq_len; /* Temp. size of the sequence in elements */ - hsize_t full_size; /* Size of the full hyperslab in bytes */ - - /* Get the sequence length for computing the hyperslab sizes */ - tmp_seq_len=seq_len; - - /* Reset the size of the hyperslab read in */ - full_size=1; - - /* Compute the hyperslab size from the length given */ - for(i=ndims-1; i>=0; i--) { - /* Check if the hyperslab is wider than the width of the dimension */ - if(tmp_seq_len>dset_dims[i]) { - assert(0==coords[i]); - hslab_size[i]=dset_dims[i]; - } /* end if */ - else - hslab_size[i]=tmp_seq_len; - - /* compute the number of elements read in */ - full_size*=hslab_size[i]; - - /* Fold the length into the length in the next highest dimension */ - tmp_seq_len/=dset_dims[i]; - - /* Make certain the hyperslab sizes don't go less than 1 for dimensions less than 0*/ - assert(tmp_seq_len>=1 || i==0); - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read the full hyperslab in */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Increment the buffer offset */ - buf=(unsigned char *)buf+(full_size*elmt_size); - - /* Decrement the sequence length left */ - seq_len-=full_size; - - /* Increment coordinate of slowest changing dimension */ - coords[0]+=hslab_size[0]; - - } /* end if */ - - /* - * Peel off final partial hyperslabs until we've finished reading all the data - */ - if(seq_len>0) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* - * Peel off remaining partial hyperslabs, from the next-slowest dimension - * on down to the next-to-fastest changing dimension - */ - for(i=1; i<(ndims-1); i++) { - /* Check if there are enough elements to read in a row in this dimension */ - if(seq_len>=down_size[i]) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j<i) - hslab_size[j]=1; - else - if(j==i) - hslab_size[j]=seq_len/down_size[j]; - else - hslab_size[j]=dset_dims[j]; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read in the partial hyperslab */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Increment the buffer offset */ - buf=(unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=hslab_size[i]; - } /* end if */ - } /* end for */ - - /* Handle fastest changing dimension if there are any elements left */ - if(seq_len>0) { - assert(seq_len<dset_dims[ndims-1]); - - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j==(ndims-1)) - hslab_size[j]=seq_len; - else - hslab_size[j]=1; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read in the partial hyperslab */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Double-check the amount read in */ - assert(seq_len==partial_size); - } /* end if */ - } /* end if */ - } - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ - + assert(store); + if((ret_value=H5F_istore_readvv(f, dxpl_id, layout, dc_plist, store->chunk_coords, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "istore read failed"); break; case H5D_COMPACT: - /* Pass along the vector of sequences to read */ - if (H5F_compact_readv(f, layout, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - + if((ret_value=H5F_compact_readvv(f, layout, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "compact read failed"); break; + default: assert("not implemented yet" && 0); HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout"); @@ -515,69 +294,67 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, done: FUNC_LEAVE_NOAPI(ret_value); -} /* H5F_seq_readv() */ +} /* H5F_seq_readvv() */ /*------------------------------------------------------------------------- - * Function: H5F_seq_writev + * Function: H5F_seq_writevv * * Purpose: Writes a vector of byte sequences from a buffer in memory into - * a file dataset. The data is written to file F and the array's size - * and storage information is in LAYOUT. External files are described - * according to the external file list, EFL. The vector of byte sequences - * offsets is in the DSET_OFFSET array into the dataset (offsets are in - * terms of bytes) and the size of each sequence is in the SEQ_LEN array. - * The total size of the file array is implied in the LAYOUT argument. - * Bytes written from BUF are sequentially stored in the buffer, each sequence - * from the vector stored directly after the previous. The number of - * sequences is NSEQ. + * a vector of byte sequences in a file dataset. The data is written to + * file F and the array's size and storage information is in LAYOUT. + * External files and chunks are described according to the storage + * information, STORE. The vector of byte sequences offsets for the file + * is in the DSET_OFFSET_ARR array into the dataset (offsets are in + * terms of bytes) and the size of each sequence is in the DSET_LEN_ARR + * array. The vector of byte sequences offsets for memory is in the + * MEM_OFFSET_ARR array into the dataset (offsets are in terms of bytes) + * and the size of each sequence is in the MEM_LEN_ARR array. The total + * size of the file array is implied in the LAYOUT argument. The maximum + * number of sequences in the file dataset and the memory buffer are + * DSET_MAX_NSEQ & MEM_MAX_NSEQ respectively. The current sequence being + * operated on in the file dataset and the memory buffer are DSET_CURR_SEQ + * & MEM_CURR_SEQ respectively. The current sequence being operated on + * will be updated as a result of the operation, as will the offsets and + * lengths of the file dataset and memory buffer sequences. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Friday, July 6, 2001 + * Friday, May 2, 2003 * * Modifications: * *------------------------------------------------------------------------- */ -herr_t -H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, - size_t nseq, size_t seq_len_arr[], hsize_t dset_offset_arr[], - const void *_buf) +ssize_t +H5F_seq_writevv(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, + struct H5P_genplist_t *dc_plist, const H5D_storage_t *store, + 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[], + const void *buf) { - const unsigned char *real_buf=(const unsigned char *)_buf; /* Local pointer to buffer to fill */ - const unsigned char *buf; /* Local pointer to buffer to fill */ - hsize_t dset_offset; /* Offset in dataset */ - hsize_t seq_len; /* Number of bytes to read */ - hsize_t dset_dims[H5O_LAYOUT_NDIMS]; /* dataspace dimensions */ - hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in memory buffer */ - hssize_t coords[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in dataspace */ - hsize_t hslab_size[H5O_LAYOUT_NDIMS]; /* hyperslab size in dataspace*/ - hsize_t down_size[H5O_LAYOUT_NDIMS]; /* Cumulative hyperslab sizes (in elements) */ - hsize_t acc; /* Accumulator for hyperslab sizes (in elements) */ - int ndims; - hsize_t max_data; /*bytes in dataset */ - haddr_t addr; /*address in file */ - unsigned u; /*counters */ - size_t v; /*counters */ - int i,j; /*counters */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; #endif /* H5_HAVE_PARALLEL */ - herr_t ret_value = SUCCEED; /* Return value */ + ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5F_seq_writev, FAIL); + FUNC_ENTER_NOAPI(H5F_seq_writevv, FAIL); /* Check args */ assert(f); + assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); /* Make certain we have the correct type of property list */ assert(layout); - assert(efl); - assert(real_buf); - /* Make certain we have the correct type of property list */ - assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); + assert(dc_plist); + assert(dset_curr_seq); + assert(*dset_curr_seq<dset_max_nseq); + assert(dset_len_arr); + assert(dset_offset_arr); + assert(mem_curr_seq); + assert(*mem_curr_seq<mem_max_nseq); + assert(mem_len_arr); + assert(mem_offset_arr); + assert(buf); #ifdef H5_HAVE_PARALLEL /* Get the transfer mode for MPIO transfers */ @@ -608,282 +385,50 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, switch (layout->type) { case H5D_CONTIGUOUS: /* Write directly to file if the dataset is in an external file */ - if (efl->nused>0) { - /* Iterate through the sequence vectors */ - for(v=0; v<nseq; v++) { -#ifdef H5_HAVE_PARALLEL - if (H5FD_MPIO_COLLECTIVE==xfer_mode) { - /* - * Currently supports same number of collective access. Need to - * be changed LATER to combine all reads into one collective MPIO - * call. - */ - unsigned long max, min, temp; - - temp = seq_len_arr[v]; - assert(temp==seq_len_arr[v]); /* verify no overflow */ - MPI_Allreduce(&temp, &max, 1, MPI_UNSIGNED_LONG, MPI_MAX, - H5FD_mpio_communicator(f->shared->lf)); - MPI_Allreduce(&temp, &min, 1, MPI_UNSIGNED_LONG, MPI_MIN, - H5FD_mpio_communicator(f->shared->lf)); -#ifdef AKC - printf("seq_len=%lu, min=%lu, max=%lu\n", temp, min, max); -#endif - if (max != min) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "collective access with unequal number of blocks not supported yet"); - } -#endif /* H5_HAVE_PARALLEL */ - /* Note: We can't use data sieve buffers for datasets in external files - * because the 'addr' of all external files is set to 0 (above) and - * all datasets in external files would alias to the same set of - * file offsets, totally mixing up the data sieve buffer information. -QAK - */ - H5_CHECK_OVERFLOW(dset_offset_arr[v],hsize_t,haddr_t); - if (H5O_efl_write(f, efl, (haddr_t)dset_offset_arr[v], seq_len_arr[v], real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "external data write failed"); - - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ + if (store && store->efl.nused>0) { + /* Note: We can't use data sieve buffers for datasets in external files + * because the 'addr' of all external files is set to 0 (above) and + * all datasets in external files would alias to the same set of + * file offsets, totally mixing up the data sieve buffer information. -QAK + */ + if ((ret_value=H5O_efl_writevv(&(store->efl), + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "external data write failed"); } else { + hsize_t max_data; /* Bytes in dataset */ + unsigned u; /* Local index variable */ + /* Compute the size of the dataset in bytes */ for(u=1, max_data=layout->dim[0]; u<layout->ndims; u++) max_data *= layout->dim[u]; /* Pass along the vector of sequences to write */ - if (H5F_contig_writev(f, max_data, H5FD_MEM_DRAW, layout->addr, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) + if ((ret_value=H5F_contig_writevv(f, max_data, layout->addr, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); } /* end else */ break; case H5D_CHUNKED: - /* - * This method is unable to access external raw data files - */ - if (efl->nused>0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); - - /* Compute the file offset coordinates and hyperslab size */ - if((ndims=H5S_get_simple_extent_dims(file_space,dset_dims,NULL))<0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unable to retrieve dataspace dimensions"); - - /* Build the array of cumulative hyperslab sizes */ - /* (And set the memory offset to zero) */ - for(acc=1, i=(ndims-1); i>=0; i--) { - mem_offset[i]=0; - down_size[i]=acc; - acc*=dset_dims[i]; - } /* end for */ - mem_offset[ndims]=0; - - /* Brute-force, stupid way to implement the vectors, but too complex to do other ways... */ - for(v=0; v<nseq; v++) { - dset_offset=dset_offset_arr[v]; - seq_len=seq_len_arr[v]; - buf=real_buf; - - { - /* Set location in dataset from the dset_offset */ - addr=dset_offset; - - /* Convert the bytes into elements */ - seq_len/=elmt_size; - addr/=elmt_size; - - /* Compute the hyperslab offset from the address given */ - for(i=ndims-1; i>=0; i--) { - coords[i]=addr%dset_dims[i]; - addr/=dset_dims[i]; - } /* end for */ - coords[ndims]=0; /* No offset for element info */ - - /* - * Peel off initial partial hyperslabs until we've got a hyperslab which starts - * at coord[n]==0 for dimensions 1->(ndims-1) (i.e. starting at coordinate - * zero for all dimensions except the slowest changing one - */ - for(i=ndims-1; i>0 && seq_len>=down_size[i]; i--) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* Check if we have a partial hyperslab in this lower dimension */ - if(coords[i]>0) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(i==j) - hslab_size[j]=MIN(seq_len/down_size[i],dset_dims[i]-coords[i]); - else - if(j>i) - hslab_size[j]=dset_dims[j]; - else - hslab_size[j]=1; - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write out the partial hyperslab */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset,coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Increment the buffer offset */ - buf=(const unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=0; - coords[i-1]++; - - /* Carry the coord array correction up the array, if the dimension is finished */ - while(i>0 && coords[i-1]==(hssize_t)dset_dims[i-1]) { - i--; - coords[i]=0; - if(i>0) { - coords[i-1]++; - assert(coords[i-1]<=(hssize_t)dset_dims[i-1]); - } /* end if */ - } /* end while */ - } /* end if */ - } /* end for */ - - /* Check if there is more than just a partial hyperslab to read */ - if(seq_len>=down_size[0]) { - hsize_t tmp_seq_len; /* Temp. size of the sequence in elements */ - hsize_t full_size; /* Size of the full hyperslab in bytes */ - - /* Get the sequence length for computing the hyperslab sizes */ - tmp_seq_len=seq_len; - - /* Reset the size of the hyperslab read in */ - full_size=1; - - /* Compute the hyperslab size from the length given */ - for(i=ndims-1; i>=0; i--) { - /* Check if the hyperslab is wider than the width of the dimension */ - if(tmp_seq_len>dset_dims[i]) { - assert(0==coords[i]); - hslab_size[i]=dset_dims[i]; - } /* end if */ - else - hslab_size[i]=tmp_seq_len; - - /* compute the number of elements read in */ - full_size*=hslab_size[i]; - - /* Fold the length into the length in the next highest dimension */ - tmp_seq_len/=dset_dims[i]; - - /* Make certain the hyperslab sizes don't go less than 1 for dimensions less than 0*/ - assert(tmp_seq_len>=1 || i==0); - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write the full hyperslab in */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Increment the buffer offset */ - buf=(const unsigned char *)buf+(full_size*elmt_size); - - /* Decrement the sequence length left */ - seq_len-=full_size; - - /* Increment coordinate of slowest changing dimension */ - coords[0]+=hslab_size[0]; - - } /* end if */ - - /* - * Peel off final partial hyperslabs until we've finished reading all the data - */ - if(seq_len>0) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* - * Peel off remaining partial hyperslabs, from the next-slowest dimension - * on down to the next-to-fastest changing dimension - */ - for(i=1; i<(ndims-1); i++) { - /* Check if there are enough elements to read in a row in this dimension */ - if(seq_len>=down_size[i]) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j<i) - hslab_size[j]=1; - else - if(j==i) - hslab_size[j]=seq_len/down_size[j]; - else - hslab_size[j]=dset_dims[j]; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write out the partial hyperslab */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Increment the buffer offset */ - buf=(const unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=hslab_size[i]; - } /* end if */ - } /* end for */ - - /* Handle fastest changing dimension if there are any elements left */ - if(seq_len>0) { - assert(seq_len<dset_dims[ndims-1]); - - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j==(ndims-1)) - hslab_size[j]=seq_len; - else - hslab_size[j]=1; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write out the final partial hyperslab */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Double-check the amount read in */ - assert(seq_len==partial_size); - } /* end if */ - } /* end if */ - } - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ - + assert(store); + if((ret_value=H5F_istore_writevv(f, dxpl_id, layout, dc_plist, store->chunk_coords, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "istore write failed"); break; case H5D_COMPACT: - /* Pass along the vector of sequences to write */ - if (H5F_compact_writev(f, layout, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - + if((ret_value=H5F_compact_writevv(f, layout, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "compact write failed"); break; default: @@ -893,5 +438,4 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, done: FUNC_LEAVE_NOAPI(ret_value); -} /* H5F_seq_writev() */ - +} /* H5F_seq_writevv() */ @@ -162,6 +162,9 @@ static const H5E_minor_mesg_t H5E_minor_mesg_g[] = { /* Dataspace errors */ {H5E_CANTCLIP, "Can't clip hyperslab region"}, {H5E_CANTCOUNT, "Can't count elements"}, + {H5E_CANTSELECT, "Can't select hyperslab"}, + {H5E_CANTNEXT, "Can't move to next iterator location"}, + {H5E_BADSELECT, "Invalid selection"}, /* Property list errors */ {H5E_CANTGET, "Can't get value"}, diff --git a/src/H5Epublic.h b/src/H5Epublic.h index d390f22..d970ab9 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -193,6 +193,9 @@ typedef enum H5E_minor_t { /* Dataspace errors */ H5E_CANTCLIP, /*Can't clip hyperslab region */ H5E_CANTCOUNT, /*Can't count elements */ + H5E_CANTSELECT, /*Can't select hyperslab */ + H5E_CANTNEXT, /*Can't move to next iterator location */ + H5E_BADSELECT, /*Invalid selection */ /* Property list errors */ H5E_CANTGET, /*Can't get value */ diff --git a/src/H5Farray.c b/src/H5Farray.c deleted file mode 100644 index 1965a59..0000000 --- a/src/H5Farray.c +++ /dev/null @@ -1,511 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by the Board of Trustees of the University of Illinois. * - * All rights reserved. * - * * - * This file is part of HDF5. The full HDF5 copyright notice, including * - * terms governing use, modification, and redistribution, is contained in * - * the files COPYING and Copyright.html. COPYING can be found at the root * - * of the source code distribution tree; Copyright.html can be found at the * - * root level of an installed copy of the electronic HDF5 document set and * - * is linked from the top-level documents page. It can also be found at * - * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * - * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* - * Programmer: Robb Matzke <matzke@llnl.gov> - * Thursday, January 15, 1998 - * - * Purpose: Provides I/O facilities for multi-dimensional arrays of bytes - * stored with various layout policies. If the caller is - * interested in arrays of elements >1 byte then add an extra - * dimension. For example, a 10x20 array of int would - * translate to a 10x20x4 array of bytes at this level. - */ - -#define H5F_PACKAGE /*suppress error about including H5Fpkg */ - -#include "H5private.h" -#include "H5Dprivate.h" -#include "H5Eprivate.h" -#include "H5Fpkg.h" -#include "H5FDprivate.h" /*file driver */ -#include "H5Iprivate.h" -#include "H5MMprivate.h" /*memory management */ -#include "H5Oprivate.h" -#include "H5Pprivate.h" -#include "H5Vprivate.h" - -/* MPIO driver functions are needed for some special checks */ -#include "H5FDmpio.h" - -/* Interface initialization */ -#define PABLO_MASK H5Farray_mask -#define INTERFACE_INIT NULL -static int interface_initialize_g = 0; - - - -/*------------------------------------------------------------------------- - * Function: H5F_arr_read - * - * Purpose: Reads a hyperslab of a file byte array into a hyperslab of - * a byte array in memory. The data is read from file F and the - * array's size and storage information is in LAYOUT. External - * files are described according to the external file list, EFL. - * The hyperslab offset is FILE_OFFSET[] in the file and - * MEM_OFFSET[] in memory (offsets are relative to the origin of - * the array) and the size of the hyperslab is HSLAB_SIZE[]. The - * total size of the file array is implied in the LAYOUT - * argument and the total size of the memory array is - * MEM_SIZE[]. The dimensionality of these vectors is implied by - * the LAYOUT argument. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Friday, January 16, 1998 - * - * Modifications: - * Albert Cheng, 1998-06-02 - * Added xfer_mode argument - * - * Robb Matzke, 1998-09-28 - * Added the `xfer' argument and removed the `xfer_mode' - * argument since it's a field of `xfer'. - * - * Robb Matzke, 1999-08-02 - * Data transfer properties are passed by ID since that's how - * the virtual file layer wants them. - *------------------------------------------------------------------------- - */ -herr_t -H5F_arr_read(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const hsize_t _hslab_size[], - const hsize_t mem_size[], const hssize_t mem_offset[], - const hssize_t file_offset[], void *_buf/*out*/) -{ - uint8_t *buf = (uint8_t*)_buf; /*cast for arithmetic */ - hssize_t file_stride[H5O_LAYOUT_NDIMS]; /*strides through file */ - hssize_t mem_stride[H5O_LAYOUT_NDIMS]; /*strides through memory*/ - hsize_t hslab_size[H5O_LAYOUT_NDIMS]; /*hyperslab size */ - hsize_t idx[H5O_LAYOUT_NDIMS]; /*multi-dim counter */ - size_t mem_start; /*byte offset to start */ - hsize_t file_start; /*byte offset to start */ - hsize_t max_data = 0; /*bytes in dataset */ - hsize_t elmt_size = 1; /*bytes per element */ - hsize_t nelmts, z; /*number of elements */ - unsigned ndims; /*stride dimensionality */ - haddr_t addr; /*address in file */ - int j; /*counters */ - unsigned u; /*counters */ - hbool_t carray; /*carry for subtraction */ - struct H5O_efl_t efl; /* External File List info */ -#ifdef H5_HAVE_PARALLEL - H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; -#endif /* H5_HAVE_PARALLEL */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_arr_read, FAIL); - - /* Check args */ - assert(f); - assert(layout); - assert(_hslab_size); - assert(file_offset); - assert(mem_offset); - assert(mem_size); - assert(buf); - /* Make certain we have the correct type of property list */ - assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - - /* Make a local copy of size so we can modify it */ - H5V_vector_cpy(layout->ndims, hslab_size, _hslab_size); - -#ifdef H5_HAVE_PARALLEL - /* Get the transfer mode for MPIO transfers */ - if(IS_H5FD_MPIO(f)) { - hid_t driver_id; /* VFL driver ID */ - H5P_genplist_t *plist; /* Property list */ - - /* Get the plist structure */ - if(NULL == (plist = H5I_object(dxpl_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); - - /* Get the driver ID */ - 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"); - - /* Check if we are using the MPIO driver (for the DXPL) */ - if(H5FD_MPIO==driver_id) { - /* Get the transfer mode */ - xfer_mode=H5P_peek_unsigned(plist, H5D_XFER_IO_XFER_MODE_NAME); - } /* end if */ - } /* end if */ - - /* Collective MPIO access is unsupported for non-contiguous datasets */ - if (H5D_CONTIGUOUS!=layout->type && H5FD_MPIO_COLLECTIVE==xfer_mode) - HGOTO_ERROR (H5E_DATASET, H5E_READERROR, FAIL, "collective access on non-contiguous datasets not supported yet"); -#endif /* H5_HAVE_PARALLEL */ - - /* Get necessary properties from property list */ - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get EFL value"); - - switch (layout->type) { - case H5D_CONTIGUOUS: - ndims = layout->ndims; - /* - * Offsets must not be negative for this type of storage. - */ - for (u=0; u<ndims; u++) { - if (mem_offset[u]<0 || file_offset[u]<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "negative offsets are not valid"); - } - - /* - * Calculate the strides needed to walk through the array on disk - * and memory. Optimize the strides to result in the fewest number of - * I/O requests. - */ - H5_ASSIGN_OVERFLOW(mem_start,H5V_hyper_stride(ndims, hslab_size, mem_size, mem_offset, mem_stride/*out*/),hsize_t,size_t); - file_start = H5V_hyper_stride(ndims, hslab_size, layout->dim, - file_offset, file_stride/*out*/); - H5V_stride_optimize2(&ndims, &elmt_size, hslab_size, - mem_stride, file_stride); - - /* - * Initialize loop variables. The loop is a multi-dimensional loop - * that counts from SIZE down to zero and IDX is the counter. Each - * element of IDX is treated as a digit with IDX[0] being the least - * significant digit. - */ - H5V_vector_cpy(ndims, idx, hslab_size); - nelmts = H5V_vector_reduce_product(ndims, hslab_size); - if (efl.nused>0) { - addr = 0; - } else { - addr = layout->addr; - - /* Compute the size of the dataset in bytes */ - for(u=0, max_data=1; u<layout->ndims; u++) - max_data *= layout->dim[u]; - - /* Adjust the maximum size of the data by the offset into it */ - max_data -= file_start; - } - addr += file_start; - buf += mem_start; - - /* - * Now begin to walk through the array, copying data from disk to - * memory. - */ -#ifdef H5_HAVE_PARALLEL - if (H5FD_MPIO_COLLECTIVE==xfer_mode) { - /* - * Currently supports same number of collective access. Need to - * be changed LATER to combine all reads into one collective MPIO - * call. - */ - unsigned long max, min, temp; - - H5_ASSIGN_OVERFLOW(temp,nelmts,hsize_t,unsigned long); - MPI_Allreduce(&temp, &max, 1, MPI_UNSIGNED_LONG, MPI_MAX, - H5FD_mpio_communicator(f->shared->lf)); - MPI_Allreduce(&temp, &min, 1, MPI_UNSIGNED_LONG, MPI_MIN, - H5FD_mpio_communicator(f->shared->lf)); -#ifdef AKC - printf("nelmts=%lu, min=%lu, max=%lu\n", temp, min, max); -#endif - if (max != min) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "collective access with unequal number of blocks not supported yet"); - } -#endif /* H5_HAVE_PARALLEL */ - - for (z=0; z<nelmts; z++) { - /* Read directly from file if the dataset is in an external file */ - /* Note: We can't use data sieve buffers for datasets in external files - * because the 'addr' of all external files is set to 0 (above) and - * all datasets in external files would alias to the same set of - * file offsets, totally mixing up the data sieve buffer information. -QAK - */ - if (efl.nused>0) { - H5_CHECK_OVERFLOW(elmt_size,hsize_t,size_t); - if (H5O_efl_read(f, &efl, addr, (size_t)elmt_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "external data read failed"); - } else { - H5_CHECK_OVERFLOW(elmt_size,hsize_t,size_t); - if (H5F_contig_read(f, max_data, H5FD_MEM_DRAW, addr, (size_t)elmt_size, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - } /* end else */ - - /* Decrement indices and advance pointers */ - for (j=ndims-1, carray=TRUE; j>=0 && carray; --j) { - addr += file_stride[j]; - buf += mem_stride[j]; - - /* Adjust the maximum size of the data by the offset into it */ - max_data -= file_stride[j]; - - if (--idx[j]) - carray = FALSE; - else - idx[j] = hslab_size[j]; - } - } - break; - - case H5D_CHUNKED: - /* - * This method is unable to access external raw data files - */ - if (efl.nused>0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); - - /* Go get the data from the chunks */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, mem_size, - mem_offset, file_offset, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - break; - - default: - assert("not implemented yet" && 0); - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout"); - } - -done: - FUNC_LEAVE_NOAPI(ret_value); -} - - -/*------------------------------------------------------------------------- - * Function: H5F_arr_write - * - * Purpose: Copies a hyperslab of a memory array to a hyperslab of a - * file array. The data is written to file F and the file - * array's size and storage information is implied by LAYOUT. - * The data is stored in external files according to the - * external file list, EFL. The hyperslab offset is - * FILE_OFFSET[] in the file and MEM_OFFSET[] in memory (offsets - * are relative to the origin of the array) and the size of the - * hyperslab is HSLAB_SIZE[]. The total size of the file array - * is implied by the LAYOUT argument and the total size of the - * memory array is MEM_SIZE[]. The dimensionality of these - * vectors is implied by the LAYOUT argument. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Friday, January 16, 1998 - * - * Modifications: - * Albert Cheng, 1998-06-02 - * Added xfer_mode argument - * - * Robb Matzke, 1998-09-28 - * Added `xfer' argument, removed `xfer_mode' argument since it - * is a member of H5D_xfer_t. - * - * Robb Matzke, 1999-08-02 - * Data transfer properties are passed by ID since that's how - * the virtual file layer wants them. - *------------------------------------------------------------------------- - */ -herr_t -H5F_arr_write(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, - H5P_genplist_t *dc_plist, - const hsize_t _hslab_size[], const hsize_t mem_size[], - const hssize_t mem_offset[], const hssize_t file_offset[], - const void *_buf) -{ - const uint8_t *buf = (const uint8_t *)_buf; /*cast for arithmetic */ - hssize_t file_stride[H5O_LAYOUT_NDIMS]; /*strides through file */ - hssize_t mem_stride[H5O_LAYOUT_NDIMS]; /*strides through memory*/ - hsize_t hslab_size[H5O_LAYOUT_NDIMS]; /*hyperslab size */ - hsize_t idx[H5O_LAYOUT_NDIMS]; /*multi-dim counter */ - hsize_t mem_start; /*byte offset to start */ - hsize_t file_start; /*byte offset to start */ - hsize_t max_data = 0; /*bytes in dataset */ - hsize_t elmt_size = 1; /*bytes per element */ - hsize_t nelmts, z; /*number of elements */ - unsigned ndims; /*dimensionality */ - haddr_t addr; /*address in file */ - int j; /*counters */ - unsigned u; /*counters */ - hbool_t carray; /*carry for subtraction */ - struct H5O_efl_t efl; /* External File List info */ -#ifdef H5_HAVE_PARALLEL - H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; -#endif /* H5_HAVE_PARALLEL */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_arr_write, FAIL); - - /* Check args */ - assert(f); - assert(layout); - assert(_hslab_size); - assert(file_offset); - assert(mem_offset); - assert(mem_size); - assert(buf); - /* Make certain we have the correct type of property list */ - assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - - /* Make a local copy of _size so we can modify it */ - H5V_vector_cpy(layout->ndims, hslab_size, _hslab_size); - -#ifdef H5_HAVE_PARALLEL - /* Get the transfer mode for MPIO transfers */ - if(IS_H5FD_MPIO(f)) { - hid_t driver_id; /* VFL driver ID */ - H5P_genplist_t *plist; /* Property list */ - - /* Get the plist structure */ - if(NULL == (plist = H5I_object(dxpl_id))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for ID"); - - /* Get the driver ID */ - 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"); - - /* Check if we are using the MPIO driver (for the DXPL) */ - if(H5FD_MPIO==driver_id) { - /* Get the transfer mode */ - xfer_mode=H5P_peek_unsigned(plist, H5D_XFER_IO_XFER_MODE_NAME); - } /* end if */ - } /* end if */ - - if (H5D_CONTIGUOUS!=layout->type && H5FD_MPIO_COLLECTIVE==xfer_mode) - HGOTO_ERROR (H5E_DATASET, H5E_WRITEERROR, FAIL, "collective access on non-contiguous datasets not supported yet"); -#endif /* H5_HAVE_PARALLEL */ - - /* Get necessary properties from property list */ - if(H5P_get(dc_plist, H5D_CRT_EXT_FILE_LIST_NAME, &efl) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get EFL value"); - - switch (layout->type) { - case H5D_CONTIGUOUS: - ndims = layout->ndims; - /* - * Offsets must not be negative for this type of storage. - */ - for (u=0; u<ndims; u++) { - if (mem_offset[u]<0 || file_offset[u]<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "negative offsets are not valid"); - } - - /* - * Calculate the strides needed to walk through the array on disk. - * Optimize the strides to result in the fewest number of I/O - * requests. - */ - mem_start = H5V_hyper_stride(ndims, hslab_size, mem_size, - mem_offset, mem_stride/*out*/); - file_start = H5V_hyper_stride(ndims, hslab_size, layout->dim, - file_offset, file_stride/*out*/); - H5V_stride_optimize2(&ndims, &elmt_size, hslab_size, - mem_stride, file_stride); - - /* - * Initialize loop variables. The loop is a multi-dimensional loop - * that counts from SIZE down to zero and IDX is the counter. Each - * element of IDX is treated as a digit with IDX[0] being the least - * significant digit. - */ - H5V_vector_cpy(ndims, idx, hslab_size); - nelmts = H5V_vector_reduce_product(ndims, hslab_size); - - if (efl.nused>0) { - addr = 0; - } else { - addr = layout->addr; - - /* Compute the size of the dataset in bytes */ - for(u=0, max_data=1; u<layout->ndims; u++) - max_data *= layout->dim[u]; - - /* Adjust the maximum size of the data by the offset into it */ - max_data -= file_start; - } - addr += file_start; - buf += mem_start; - - /* - * Now begin to walk through the array, copying data from memory to - * disk. - */ -#ifdef H5_HAVE_PARALLEL - if (H5FD_MPIO_COLLECTIVE==xfer_mode){ - /* - * Currently supports same number of collective access. Need to - * be changed LATER to combine all writes into one collective - * MPIO call. - */ - unsigned long max, min, temp; - - H5_ASSIGN_OVERFLOW(temp,nelmts,hsize_t,unsigned long); - MPI_Allreduce(&temp, &max, 1, MPI_UNSIGNED_LONG, MPI_MAX, - H5FD_mpio_communicator(f->shared->lf)); - MPI_Allreduce(&temp, &min, 1, MPI_UNSIGNED_LONG, MPI_MIN, - H5FD_mpio_communicator(f->shared->lf)); -#ifdef AKC - printf("nelmts=%lu, min=%lu, max=%lu\n", temp, min, max); -#endif - if (max != min) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "collective access with unequal number of blocks not supported yet"); - } -#endif /* H5_HAVE_PARALLEL */ - - for (z=0; z<nelmts; z++) { - - /* Write to file */ - if (efl.nused>0) { - H5_CHECK_OVERFLOW(elmt_size,hsize_t,size_t); - if (H5O_efl_write(f, &efl, addr, (size_t)elmt_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "external data write failed"); - } else { - H5_CHECK_OVERFLOW(elmt_size,hsize_t,size_t); - if (H5F_contig_write(f, max_data, H5FD_MEM_DRAW, addr, (size_t)elmt_size, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - } /* end else */ - - /* Decrement indices and advance pointers */ - for (j=ndims-1, carray=TRUE; j>=0 && carray; --j) { - addr += file_stride[j]; - buf += mem_stride[j]; - - /* Adjust the maximum size of the data by the offset into it */ - max_data -= file_stride[j]; - - if (--idx[j]) - carray = FALSE; - else - idx[j] = hslab_size[j]; - } - - } - break; - - case H5D_CHUNKED: - /* - * This method is unable to access external raw data files - */ - if (efl.nused>0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); - - /* Write the read to the chunks */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, mem_size, - mem_offset, file_offset, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - break; - - default: - assert("not implemented yet" && 0); - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout"); - } - -done: - FUNC_LEAVE_NOAPI(ret_value); -} diff --git a/src/H5Fcompact.c b/src/H5Fcompact.c index 1f77d92..829ba63 100644 --- a/src/H5Fcompact.c +++ b/src/H5Fcompact.c @@ -28,60 +28,55 @@ #include "H5Oprivate.h" #include "H5FDprivate.h" /*file driver */ #include "H5FLprivate.h" /*Free Lists */ +#include "H5Vprivate.h" /* Vector and array functions */ /* Interface initialization */ #define PABLO_MASK H5Fcompact_mask static int interface_initialize_g = 0; #define INTERFACE_INIT NULL + /*------------------------------------------------------------------------- - * Function: H5F_compact_readv - * + * Function: H5F_compact_readvv + * * Purpose: Reads some data vectors from a dataset into a buffer. * The data is in compact dataset. The address is relative * to the beginning address of the dataset. The offsets and * sequence lengths are in bytes. - * + * * Return: Non-negative on success/Negative on failure - * - * Programmer: Raymond Lu - * August 5, 2002 - * - * Notes: - * Offsets in the sequences must be monotonically increasing * + * Programmer: Quincey Koziol + * May 7, 2003 + * + * Notes: + * Offsets in the sequences must be monotonically increasing + * * Modifications: - * + * *------------------------------------------------------------------------- */ -herr_t -H5F_compact_readv(H5F_t UNUSED *f, const H5O_layout_t *layout, size_t nseq, - size_t size_arr[], hsize_t offset_arr[], - hid_t UNUSED dxpl_id, void *_buf/*out*/) +ssize_t +H5F_compact_readvv(H5F_t UNUSED *f, const H5O_layout_t *layout, + 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[], + hid_t UNUSED dxpl_id, void *buf) { - unsigned char *buf=(unsigned char *)_buf; - size_t size; - haddr_t offset; - unsigned u; - herr_t ret_value=SUCCEED; + ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5F_compact_readv, FAIL); + FUNC_ENTER_NOAPI(H5F_compact_readvv, FAIL); - for(u=0; u<nseq; u++) { - size=size_arr[u]; - offset=offset_arr[u]; - if(size > 0) { - HDmemcpy(buf, (unsigned char*)layout->buf+offset, size); - buf +=size; - } - } + /* 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,layout->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: +done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_compact_readv() */ +} /* end H5F_compact_readvv() */ + /*------------------------------------------------------------------------- - * Function: H5F_compact_writev + * Function: H5F_compact_writevv * * Purpose: Writes some data vectors from a dataset into a buffer. * The data is in compact dataset. The address is relative @@ -93,8 +88,8 @@ done: * * Return: Non-negative on success/Negative on failure * - * Programmer: Raymond Lu - * August 5, 2002 + * Programmer: Quincey Koziol + * May 2, 2003 * * Notes: * Offsets in the sequences must be monotonically increasing @@ -103,30 +98,23 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5F_compact_writev(H5F_t UNUSED *f, H5O_layout_t *layout, size_t nseq, - size_t size_arr[], hsize_t offset_arr[], - hid_t UNUSED dxpl_id, const void *_buf) +ssize_t +H5F_compact_writevv(H5F_t UNUSED *f, H5O_layout_t *layout, + 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[], + hid_t UNUSED dxpl_id, const void *buf) { - const unsigned char *buf=(const unsigned char *)_buf; - size_t size; - haddr_t offset; - unsigned u; - herr_t ret_value=SUCCEED; + ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5F_compact_writev, FAIL); + FUNC_ENTER_NOAPI(H5F_compact_writevv, FAIL); - for(u=0; u<nseq; u++) { - size=size_arr[u]; - offset=offset_arr[u]; - if(size > 0) { - HDmemcpy((unsigned char*)layout->buf+offset, buf, size); - buf += size; - } - } + /* Use the vectorized memory copy routine to do actual work */ + if((ret_value=H5V_memcpyvv(layout->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) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vectorized memcpy failed"); layout->dirty = TRUE; done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_compact_writev */ +} /* end H5F_compact_writevv() */ + diff --git a/src/H5Fcontig.c b/src/H5Fcontig.c index 2593d83..3a14175 100644 --- a/src/H5Fcontig.c +++ b/src/H5Fcontig.c @@ -18,9 +18,8 @@ * * Purpose: * Contiguous dataset I/O functions. These routines are similar to - * the H5F_istore_* routines and really only abstract away dealing - * with the data sieve buffer from the H5F_arr_read/write and - * H5F_seg_read/write. + * the H5F_istore_* routines and really only an abstract way of dealing + * with the data sieve buffer from H5F_seg_read/write. */ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ @@ -34,6 +33,7 @@ #include "H5MFprivate.h" /*file memory management */ #include "H5Oprivate.h" /* Object headers */ #include "H5Pprivate.h" /* Property lists */ +#include "H5Sprivate.h" /* Dataspace functions */ #include "H5Vprivate.h" /* Vector and array functions */ /* MPIO, MPIPOSIX, & FPHDF5 drivers needed for special checks */ @@ -41,6 +41,11 @@ #include "H5FDmpio.h" #include "H5FDmpiposix.h" +/* Private prototypes */ +static herr_t +H5F_contig_write(H5F_t *f, hsize_t max_data, haddr_t addr, + const size_t size, hid_t dxpl_id, const void *buf); + /* Interface initialization */ #define PABLO_MASK H5Fcontig_mask static int interface_initialize_g = 0; @@ -57,6 +62,48 @@ H5FL_BLK_DEFINE_STATIC(zero_fill); /*------------------------------------------------------------------------- + * Function: H5F_contig_create + * + * Purpose: Allocate file space for a contiguously stored dataset + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * April 19, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_contig_create(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout) +{ + hsize_t size; /* Size of contiguous block of data */ + unsigned u; /* Local index variable */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_contig_create, FAIL); + + /* check args */ + assert(f); + assert(layout); + + /* Compute size */ + size=layout->dim[0]; + for (u = 1; u < layout->ndims; u++) + size *= layout->dim[u]; + assert (size>0); + + /* Allocate space for the contiguous data */ + if (HADDR_UNDEF==(layout->addr=H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, size))) + HGOTO_ERROR (H5E_IO, H5E_NOSPACE, FAIL, "unable to reserve file space"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5F_contig_create */ + + +/*------------------------------------------------------------------------- * Function: H5F_contig_fill * * Purpose: Write fill values to a contiguously stored dataset. @@ -75,8 +122,7 @@ H5FL_BLK_DEFINE_STATIC(zero_fill); */ herr_t H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, - const struct H5S_t *space, + struct H5P_genplist_t *dc_plist, const struct H5S_t *space, const struct H5O_fill_t *fill, size_t elmt_size) { hssize_t snpoints; /* Number of points in space (for error checking) */ @@ -84,7 +130,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, size_t ptsperbuf; /* Maximum # of points which fit in the buffer */ size_t bufsize=64*1024; /* Size of buffer to write */ size_t size; /* Current # of points to write */ - hsize_t addr; /* Offset in dataset */ + haddr_t addr; /* Offset of dataset */ void *buf = NULL; /* Buffer for fill value writing */ #ifdef H5_HAVE_PARALLEL MPI_Comm mpi_comm=MPI_COMM_NULL; /* MPI communicator for file */ @@ -173,8 +219,8 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, * this quite efficiently by making sure we copy the fill value * in relatively large pieces. */ - ptsperbuf = MAX(1, bufsize/elmt_size); - bufsize = ptsperbuf*elmt_size; + ptsperbuf = MAX(1, bufsize/elmt_size); + bufsize = ptsperbuf*elmt_size; /* Fill the buffer with the user's fill value */ if(fill->buf) { @@ -207,7 +253,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, } /* end else */ /* Start at the beginning of the dataset */ - addr = 0; + addr = layout->addr; /* Loop through writing the fill value to the dataset */ while (npoints>0) { @@ -218,8 +264,7 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, if(using_mpi) { /* Round-robin write the chunks out from only one process */ if(mpi_round==mpi_rank) { - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space, - elmt_size, size, addr, buf)<0) + if (H5F_contig_write(f, size, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset"); } /* end if */ ++mpi_round; @@ -230,8 +275,8 @@ H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, } /* end if */ else { #endif /* H5_HAVE_PARALLEL */ - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, space, - elmt_size, size, addr, buf)<0) + H5_CHECK_OVERFLOW(size,size_t,hsize_t); + if (H5F_contig_write(f, (hsize_t)size, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to write fill value to dataset"); #ifdef H5_HAVE_PARALLEL } /* end else */ @@ -314,44 +359,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_contig_read - * - * Purpose: Reads some data from a dataset 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: Quincey Koziol - * Thursday, September 28, 2000 - * - * Modifications: - * Re-written in terms of the new readv call, QAK, 7/7/01 - * - *------------------------------------------------------------------------- - */ -herr_t -H5F_contig_read(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr, - size_t size, hid_t dxpl_id, void *buf/*out*/) -{ - hsize_t offset=0; /* Offset for vector call */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_contig_read, FAIL); - - /* Check args */ - assert(f); - assert(buf); - - if (H5F_contig_readv(f, max_data, type, addr, 1, &size, &offset, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vector read failed"); - -done: - FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_contig_read() */ - - -/*------------------------------------------------------------------------- * Function: H5F_contig_write * * Purpose: Writes some data from a dataset into a buffer. @@ -364,23 +371,28 @@ done: * Thursday, September 28, 2000 * * Modifications: - * Re-written in terms of the new readv call, QAK, 7/7/01 + * Re-written in terms of the new writevv call, QAK, 5/7/03 * *------------------------------------------------------------------------- */ -herr_t -H5F_contig_write(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr, size_t size, - hid_t dxpl_id, const void *buf) +static herr_t +H5F_contig_write(H5F_t *f, hsize_t max_data, haddr_t addr, + const size_t size, hid_t dxpl_id, const void *buf) { - hsize_t offset=0; /* Offset for vector call */ - herr_t ret_value=SUCCEED; /* Return value */ + hsize_t dset_off=0; /* Offset in dataset */ + hsize_t mem_off=0; /* Offset in memory */ + size_t dset_len=size; /* Length in dataset */ + size_t mem_len=size; /* Length in memory */ + size_t mem_curr_seq=0; /* "Current sequence" in memory */ + size_t dset_curr_seq=0; /* "Current sequence" in dataset */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_contig_write, FAIL); assert (f); assert (buf); - if (H5F_contig_writev(f, max_data, type, addr, 1, &size, &offset, dxpl_id, buf)<0) + if (H5F_contig_writevv(f, max_data, addr, 1, &dset_curr_seq, &dset_len, &dset_off, 1, &mem_curr_seq, &mem_len, &mem_off, dxpl_id, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed"); done: @@ -389,7 +401,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_contig_readv + * Function: H5F_contig_readvv * * Purpose: Reads some data vectors from a dataset into a buffer. * The data is contiguous. The address is the start of the dataset, @@ -409,9 +421,10 @@ done: *------------------------------------------------------------------------- */ herr_t -H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, - size_t nseq, size_t size_arr[], hsize_t offset_arr[], hid_t dxpl_id, - void *_buf/*out*/) +H5F_contig_readvv(H5F_t *f, hsize_t _max_data, haddr_t _addr, + 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[], + hid_t dxpl_id, void *_buf) { unsigned char *buf=(unsigned char *)_buf; /* Pointer to buffer to fill */ haddr_t abs_eoa; /* Absolute end of file address */ @@ -420,18 +433,10 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, hsize_t max_data; /* Actual maximum size of data to cache */ size_t size; /* Size of sequence in bytes */ size_t u; /* Counting variable */ -#ifndef SLOW_WAY - size_t max_seq; /* Maximum sequence to copy */ - haddr_t temp_end; /* Temporary end of buffer variable */ - size_t max_search; /* Maximum number of sequences to search */ - size_t mask; /* Bit mask */ - int bit_loc; /* Bit location of the leftmost '1' in max_search */ - size_t *size_arr_p; /* Pointer into the size array */ - hsize_t *offset_arr_p; /* Pointer into the offset array */ -#endif /* SLOW_WAY */ - herr_t ret_value=SUCCEED; /* Return value */ + size_t v; /* Counting variable */ + ssize_t ret_value=0; /* Return value */ - FUNC_ENTER_NOAPI(H5F_contig_readv, FAIL); + FUNC_ENTER_NOAPI(H5F_contig_readvv, FAIL); /* Check args */ assert(f); @@ -439,325 +444,143 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, /* Check if data sieving is enabled */ if(f->shared->lf->feature_flags&H5FD_FEAT_DATA_SIEVE) { + haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */ + haddr_t contig_end; /* End locations of block to write */ + size_t sieve_size; /* size of sieve buffer */ + + /* Set offsets in sequence lists */ + u=*dset_curr_seq; + v=*mem_curr_seq; + + /* No data sieve buffer yet, go allocate one */ + if(f->shared->sieve_buf==NULL) { + /* Choose smallest buffer to write */ + if(mem_len_arr[v]<dset_len_arr[u]) + size=mem_len_arr[v]; + else + size=dset_len_arr[u]; + + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (unsigned char *)_buf + mem_offset_arr[v]; + + /* Set up the buffer parameters */ + max_data=_max_data-dset_offset_arr[u]; + + /* Check if we can actually hold the I/O request in the sieve buffer */ + if(size>f->shared->sieve_buf_size) { + if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + } /* end if */ + else { + /* Allocate room for the data sieve buffer */ + if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - /* Outer loop, guarantees working through all the sequences */ - for(u=0; u<nseq; ) { - - /* Try reading from the data sieve buffer */ - if(f->shared->sieve_buf) { - haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */ - haddr_t contig_end; /* End locations of block to write */ - size_t sieve_size; /* size of sieve buffer */ - - /* Stash local copies of these value */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - /* Next-outer loop works through sequences as fast as possible */ - for(; u<nseq; ) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; - - /* Compute end of sequence to retrieve */ - 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=f->shared->sieve_buf+(_addr-sieve_start); - unsigned char *temp_sieve_buf; - haddr_t temp_addr=_addr-1; /* Temporary address */ - -#ifdef SLOW_WAY - /* Retrieve all the sequences out of the current sieve buffer */ - while(contig_end<sieve_end) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+offset_arr[u]; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,size_arr[u]); - - /* Increment offset in buffer */ - buf += size_arr[u]; - - /* Increment sequence number, check for finished with sequences */ - if((++u) >= nseq) - break; - - /* Re-compute end of sequence to retrieve */ - contig_end=temp_addr+offset_arr[u]+size_arr[u]; - } /* end while */ -#else /* SLOW_WAY */ - /* Find log2(n) where n is the number of elements to search */ - - /* Set initial parameters */ - mask=(size_t)0xff<<((sizeof(size_t)-1)*8); /* Get a mask for the leftmost byte */ - max_search=((nseq-1)-u)+1; /* Compute 'n' for the log2 */ - assert(max_search>0); /* Sanity check */ - bit_loc=(sizeof(size_t)*8)-1; /* Initial bit location */ - - /* Search for the first byte with a bit set */ - while((max_search & mask)==0) { - mask>>=8; - bit_loc-=8; - } /* end while */ - - /* Switch to searching for a bit */ - mask=1<<bit_loc; - while((max_search & mask)==0) { - mask>>=1; - bit_loc--; - } /* end while */ - - /* location of the leftmost bit, plus 1, is log2(n) */ - max_seq=bit_loc+1; - - /* Don't walk off the array */ - max_seq=MIN(u+max_seq,nseq-1); - - /* Determine if a linear search is faster than a binary search */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - if(temp_end>=sieve_end) { - /* Linear search is faster */ - - /* Set the initial search values */ - max_seq=u; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Search for the first sequence ending greater than the sieve buffer end */ - while(temp_end<sieve_end) { - if(++max_seq>=nseq) - break; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - } /* end while */ - - /* Adjust back one element */ - max_seq--; - - } /* end if */ - else { - size_t lo,hi; /* Low and high bounds for binary search */ - unsigned found=0; /* Flag to indicate bounds have been found */ - - /* Binary search is faster */ - - /* Find the value 'u' which will be beyond the end of the sieve buffer */ - lo=u; - hi=nseq-1; - max_seq=(lo+hi)/2; - while(!found) { - /* Get the address of the end of sequence for the 'max_seq' position */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Current high bound is too large */ - if(temp_end>=sieve_end) { - if((lo+1)<hi) { - hi=max_seq; - max_seq=(lo+hi)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end if */ - /* Current low bound is too small */ - else { - if((lo+1)<hi) { - lo=max_seq; - max_seq=(lo+hi+1)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end else */ - } /* end while */ - - /* Check for non-exact match */ - if(lo!=hi) { - temp_end=temp_addr+offset_arr[hi]+size_arr[hi]; - if(temp_end<sieve_end) - max_seq=hi; - else - max_seq=lo; - } /* end if */ - } /* end else */ - - /* Set the pointers to the correct locations in the offset & size arrays */ - size_arr_p=&size_arr[u]; - offset_arr_p=&offset_arr[u]; - -#ifdef NO_DUFFS_DEVICE - /* Retrieve all the sequences out of the current sieve buffer */ - while(u<=max_seq) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - } /* end while */ -#else /* NO_DUFFS_DEVICE */ -{ - size_t seq_count; - - seq_count=(max_seq-u)+1; - switch (seq_count % 4) { - case 0: - do - { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - case 3: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - case 2: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - case 1: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; - - /* Grab the data out of the buffer */ - HDmemcpy(buf,temp_sieve_buf,*size_arr_p); - - /* Increment offset in buffer */ - buf += *size_arr_p++; - - /* Increment the offset in the array */ - u++; - - } while (u<=max_seq); - } /* end switch */ - -} -#endif /* NO_DUFFS_DEVICE */ -#endif /* SLOW_WAY */ - } /* end if */ - /* Entire request is not within this data sieve buffer */ - else { - /* Check if we can actually hold the I/O request in the sieve buffer */ - if(size>f->shared->sieve_buf_size) { - /* Check for any overlap with the current sieve buffer */ - if((sieve_start>=addr && sieve_start<(contig_end+1)) - || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { - /* Flush the sieve buffer, if it's dirty */ - if(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - } /* end if */ - - /* Read directly into the user's buffer */ - if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - } /* end if */ - /* Element size fits within the buffer size */ - else { - /* Flush the sieve buffer if it's dirty */ - if(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - - /* Determine the new sieve buffer size & location */ - f->shared->sieve_loc=addr; - - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); + /* Determine the new sieve buffer size & location */ + f->shared->sieve_loc=addr; - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-f->shared->base_addr; + /* Make certain we don't read off the end of the file */ + if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - /* Only need this when resizing sieve buffer */ - max_data=_max_data-offset_arr[u]; + /* Adjust absolute EOA address to relative EOA address */ + rel_eoa=abs_eoa-f->shared->base_addr; - /* Compute the size of the sieve buffer */ - /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ - H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); + /* Compute the size of the sieve buffer */ + H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - /* Update local copies of sieve information */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->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,f->shared->sieve_buf,size); - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; + } /* end else */ - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(buf,f->shared->sieve_buf,size); - } /* end else */ + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) + u++; - /* Increment sequence number */ - u++; - } /* end else */ - } /* end for */ + /* Increment number of bytes copied */ + ret_value+=size; + } /* end if */ + + /* Stash local copies of these value */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; + + /* Works through sequences as fast as possible */ + 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]; + else + size=dset_len_arr[u]; + + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (unsigned char *)_buf + mem_offset_arr[v]; + + /* Compute end of sequence to retrieve */ + 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=f->shared->sieve_buf+(addr-sieve_start); + + /* Grab the data out of the buffer */ + HDmemcpy(buf,base_sieve_buf,size); } /* end if */ - /* No data sieve buffer yet, go allocate one */ + /* Entire request is not within this data sieve buffer */ else { - /* Set up the buffer parameters */ - size=size_arr[u]; - addr=_addr+offset_arr[u]; - max_data=_max_data-offset_arr[u]; - /* Check if we can actually hold the I/O request in the sieve buffer */ if(size>f->shared->sieve_buf_size) { - if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0) + /* Check for any overlap with the current sieve buffer */ + if((sieve_start>=addr && sieve_start<(contig_end+1)) + || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { + /* Flush the sieve buffer, if it's dirty */ + if(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; + } /* end if */ + } /* end if */ + + /* Read directly into the user's buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); } /* end if */ + /* Element size fits within the buffer size */ else { - /* Allocate room for the data sieve buffer */ - if (NULL==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + /* Flush the sieve buffer if it's dirty */ + if(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; + } /* end if */ /* Determine the new sieve buffer size & location */ f->shared->sieve_loc=addr; @@ -769,59 +592,103 @@ H5F_contig_readv(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, /* Adjust absolute EOA address to relative EOA address */ rel_eoa=abs_eoa-f->shared->base_addr; + /* Only need this when resizing sieve buffer */ + max_data=_max_data-dset_offset_arr[u]; + /* Compute the size of the sieve buffer */ + /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); + /* Update local copies of sieve information */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; + /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ HDmemcpy(buf,f->shared->sieve_buf,size); + + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; } /* end else */ + } /* end else */ - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - /* Increment sequence number */ + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) u++; - } /* end else */ + + /* Increment number of bytes copied */ + ret_value+=size; } /* end for */ } /* end if */ else { /* Work through all the sequences */ - for(u=0; u<nseq; u++) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; + 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]; + else + size=dset_len_arr[u]; - if (H5F_block_read(f, type, addr, size, dxpl_id, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (unsigned char *)_buf + mem_offset_arr[v]; + + /* Write data */ + if (H5F_block_read(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update memory information */ + 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) + u++; + + /* Increment number of bytes copied */ + ret_value+=size; } /* end for */ } /* end else */ + /* Update current sequence vectors */ + *dset_curr_seq=u; + *mem_curr_seq=v; + done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_contig_readv() */ +} /* end H5F_contig_readvv() */ /*------------------------------------------------------------------------- - * Function: H5F_contig_writev + * Function: H5F_contig_writevv * - * Purpose: Writes some data vectors into a dataset from a buffer. - * The data is contiguous. The address is the start of the dataset, + * Purpose: Writes some data vectors into a dataset from vectors into a + * buffer. The address is the start of the dataset, * relative to the base address for the file and the offsets and * sequence lengths are in bytes. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Thursday, July 5, 2001 + * Friday, May 2, 2003 * * Notes: * Offsets in the sequences must be monotonically increasing @@ -830,10 +697,11 @@ done: * *------------------------------------------------------------------------- */ -herr_t -H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, - size_t nseq, size_t size_arr[], hsize_t offset_arr[], hid_t dxpl_id, - const void *_buf) +ssize_t +H5F_contig_writevv(H5F_t *f, hsize_t _max_data, haddr_t _addr, + 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[], + hid_t dxpl_id, const void *_buf) { const unsigned char *buf=_buf; /* Pointer to buffer to fill */ haddr_t abs_eoa; /* Absolute end of file address */ @@ -842,18 +710,10 @@ H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, hsize_t max_data; /* Actual maximum size of data to cache */ size_t size; /* Size of sequence in bytes */ size_t u; /* Counting variable */ -#ifndef SLOW_WAY - size_t max_seq; /* Maximum sequence to copy */ - haddr_t temp_end; /* Temporary end of buffer variable */ - size_t max_search; /* Maximum number of sequences to search */ - size_t mask; /* Bit mask */ - int bit_loc; /* Bit location of the leftmost '1' in max_search */ - size_t *size_arr_p; /* Pointer into the size array */ - hsize_t *offset_arr_p; /* Pointer into the offset array */ -#endif /* SLOW_WAY */ - herr_t ret_value=SUCCEED; /* Return value */ + size_t v; /* Counting variable */ + ssize_t ret_value=0; /* Return value */ - FUNC_ENTER_NOAPI(H5F_contig_writev, FAIL); + FUNC_ENTER_NOAPI(H5F_contig_writevv, FAIL); /* Check args */ assert(f); @@ -861,421 +721,284 @@ H5F_contig_writev(H5F_t *f, hsize_t _max_data, H5FD_mem_t type, haddr_t _addr, /* Check if data sieving is enabled */ if(f->shared->lf->feature_flags&H5FD_FEAT_DATA_SIEVE) { + haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */ + haddr_t contig_end; /* End locations of block to write */ + size_t sieve_size; /* size of sieve buffer */ + + /* Set offsets in sequence lists */ + u=*dset_curr_seq; + v=*mem_curr_seq; + + /* No data sieve buffer yet, go allocate one */ + if(f->shared->sieve_buf==NULL) { + /* Choose smallest buffer to write */ + if(mem_len_arr[v]<dset_len_arr[u]) + size=mem_len_arr[v]; + else + size=dset_len_arr[u]; + + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (const unsigned char *)_buf + mem_offset_arr[v]; + + /* Set up the buffer parameters */ + max_data=_max_data-dset_offset_arr[u]; + + /* Check if we can actually hold the I/O request in the sieve buffer */ + if(size>f->shared->sieve_buf_size) { + if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, 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==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); - /* Outer loop, guarantees working through all the sequences */ - for(u=0; u<nseq; ) { - - /* Try writing into the data sieve buffer */ - if(f->shared->sieve_buf) { - haddr_t sieve_start, sieve_end; /* Start & end locations of sieve buffer */ - haddr_t contig_end; /* End locations of block to write */ - size_t sieve_size; /* size of sieve buffer */ - - /* Stash local copies of these value */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - /* Next-outer loop works through sequences as fast as possible */ - for(; u<nseq; ) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; - - /* Compute end of sequence to retrieve */ - contig_end=addr+size-1; - - /* 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=f->shared->sieve_buf+(_addr-sieve_start); - unsigned char *temp_sieve_buf; - haddr_t temp_addr=_addr-1; /* Temporary address */ - -#ifdef SLOW_WAY - /* Retrieve all the sequences out of the current sieve buffer */ - while(contig_end<sieve_end) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+offset_arr[u]; - - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,size_arr[u]); - - /* Increment offset in buffer */ - buf += size_arr[u]; - - /* Increment sequence number, check for finished with sequences */ - if((++u) >= nseq) - break; - - /* Re-compute end of sequence to retrieve */ - contig_end=temp_addr+offset_arr[u]+size_arr[u]; - } /* end while */ -#else /* SLOW_WAY */ - /* Find log2(n) where n is the number of elements to search */ - - /* Set initial parameters */ - mask=(size_t)0xff<<((sizeof(size_t)-1)*8); /* Get a mask for the leftmost byte */ - max_search=((nseq-1)-u)+1; /* Compute 'n' for the log2 */ - assert(max_search>0); /* Sanity check */ - bit_loc=(sizeof(size_t)*8)-1; /* Initial bit location */ - - /* Search for the first byte with a bit set */ - while((max_search & mask)==0) { - mask>>=8; - bit_loc-=8; - } /* end while */ - - /* Switch to searching for a bit */ - mask=1<<bit_loc; - while((max_search & mask)==0) { - mask>>=1; - bit_loc--; - } /* end while */ - - /* location of the leftmost bit, plus 1, is log2(n) */ - max_seq=bit_loc+1; - - /* Don't walk off the array */ - max_seq=MIN(u+max_seq,nseq-1); - - /* Determine if a linear search is faster than a binary search */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - if(temp_end>=sieve_end) { - /* Linear search is faster */ - - /* Set the initial search values */ - max_seq=u; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Search for the first sequence ending greater than the sieve buffer end */ - while(temp_end<sieve_end) { - if(++max_seq>=nseq) - break; - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - } /* end while */ - - /* Adjust back one element */ - max_seq--; - - } /* end if */ - else { - size_t lo,hi; /* Low and high bounds for binary search */ - unsigned found=0; /* Flag to indicate bounds have been found */ - - /* Binary search is faster */ - - /* Find the value 'u' which will be beyond the end of the sieve buffer */ - lo=u; - hi=nseq-1; - max_seq=(lo+hi)/2; - while(!found) { - /* Get the address of the end of sequence for the 'max_seq' position */ - temp_end=temp_addr+offset_arr[max_seq]+size_arr[max_seq]; - - /* Current high bound is too large */ - if(temp_end>=sieve_end) { - if((lo+1)<hi) { - hi=max_seq; - max_seq=(lo+hi)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end if */ - /* Current low bound is too small */ - else { - if((lo+1)<hi) { - lo=max_seq; - max_seq=(lo+hi+1)/2; - } /* end if */ - else { - found=1; - } /* end else */ - } /* end else */ - } /* end while */ - - /* Check for non-exact match */ - if(lo!=hi) { - temp_end=temp_addr+offset_arr[hi]+size_arr[hi]; - if(temp_end<sieve_end) - max_seq=hi; - else - max_seq=lo; - } /* end if */ - } /* end else */ - - /* Set the pointers to the correct locations in the offset & size arrays */ - size_arr_p=&size_arr[u]; - offset_arr_p=&offset_arr[u]; - -#ifdef NO_DUFFS_DEVICE - /* Retrieve all the sequences out of the current sieve buffer */ - while(u<=max_seq) { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Determine the new sieve buffer size & location */ + f->shared->sieve_loc=addr; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Make certain we don't read off the end of the file */ + if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Adjust absolute EOA address to relative EOA address */ + rel_eoa=abs_eoa-f->shared->base_addr; - /* Increment the offset in the array */ - u++; - } /* end while */ -#else /* NO_DUFFS_DEVICE */ -{ - size_t seq_count; + /* Compute the size of the sieve buffer */ + H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - seq_count=(max_seq-u)+1; - switch (seq_count % 4) { - case 0: - do - { - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Check if there is any point in reading the data from the file */ + if(f->shared->sieve_size>size) { + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + } /* end if */ - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Grab the data out of the buffer (must be first piece of data in buffer ) */ + HDmemcpy(f->shared->sieve_buf,buf,size); - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Set sieve buffer dirty flag */ + f->shared->sieve_dirty=1; + } /* end else */ - /* Increment the offset in the array */ - u++; + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - case 3: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) + u++; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Increment number of bytes copied */ + ret_value+=size; + } /* end if */ - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Stash local copies of these value */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; + + /* Works through sequences as fast as possible */ + 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]; + else + size=dset_len_arr[u]; - /* Increment the offset in the array */ - u++; + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; - case 2: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Compute offset in memory */ + buf = (const unsigned char *)_buf + mem_offset_arr[v]; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + /* Compute end of sequence to retrieve */ + contig_end=addr+size-1; - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* 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=f->shared->sieve_buf+(addr-sieve_start); - /* Increment the offset in the array */ - u++; + /* Put the data into the sieve buffer */ + HDmemcpy(base_sieve_buf,buf,size); - case 1: - /* Set the location within the sieve buffer to the correct offset */ - temp_sieve_buf=base_sieve_buf+*offset_arr_p++; + /* Set sieve buffer dirty flag */ + f->shared->sieve_dirty=1; - /* Grab the data out of the buffer */ - HDmemcpy(temp_sieve_buf,buf,*size_arr_p); + } /* end if */ + /* Entire request is not within this data sieve buffer */ + else { + /* Check if we can actually hold the I/O request in the sieve buffer */ + if(size>f->shared->sieve_buf_size) { + /* Check for any overlap with the current sieve buffer */ + if((sieve_start>=addr && sieve_start<(contig_end+1)) + || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { + /* Flush the sieve buffer, if it's dirty */ + if(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - /* Increment offset in buffer */ - buf += *size_arr_p++; + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; + } /* end if */ - /* Increment the offset in the array */ - u++; + /* Force the sieve buffer to be re-read the next time */ + f->shared->sieve_loc=HADDR_UNDEF; + f->shared->sieve_size=0; + } /* end if */ - } while (u<=max_seq); - } /* end switch */ + /* Write directly from the user's buffer */ + if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + } /* end if */ + /* Element size fits within the buffer size */ + else { + /* Check if it is possible to (exactly) prepend or append to existing (dirty) sieve buffer */ + if(((addr+size)==sieve_start || addr==sieve_end) && + (size+sieve_size)<=f->shared->sieve_buf_size && + f->shared->sieve_dirty) { + /* Prepend to existing sieve buffer */ + if((addr+size)==sieve_start) { + /* Move existing sieve information to correct location */ + HDmemmove(f->shared->sieve_buf+size,f->shared->sieve_buf,sieve_size); + + /* Copy in new information (must be first in sieve buffer) */ + HDmemcpy(f->shared->sieve_buf,buf,size); + + /* Adjust sieve location */ + f->shared->sieve_loc=addr; + + } /* end if */ + /* Append to existing sieve buffer */ + else { + /* Copy in new information */ + HDmemcpy(f->shared->sieve_buf+sieve_size,buf,size); + } /* end else */ -} -#endif /* NO_DUFFS_DEVICE */ -#endif /* SLOW_WAY */ - /* Set sieve buffer dirty flag */ - f->shared->sieve_dirty=1; + /* Adjust sieve size */ + f->shared->sieve_size += size; + + /* Update local copies of sieve information */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; } /* end if */ - /* Entire request is not within this data sieve buffer */ + /* Can't add the new data onto the existing sieve buffer */ else { - /* Check if we can actually hold the I/O request in the sieve buffer */ - if(size>f->shared->sieve_buf_size) { - /* Check for any overlap with the current sieve buffer */ - if((sieve_start>=addr && sieve_start<(contig_end+1)) - || ((sieve_end-1)>=addr && (sieve_end-1)<(contig_end+1))) { - /* Flush the sieve buffer, if it's dirty */ - if(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - - /* Force the sieve buffer to be re-read the next time */ - f->shared->sieve_loc=HADDR_UNDEF; - f->shared->sieve_size=0; - } /* end if */ - - /* Write directly from the user's buffer */ - if (H5F_block_write(f, type, addr, size, dxpl_id, buf)<0) + /* Flush the sieve buffer if it's dirty */ + if(f->shared->sieve_dirty) { + /* Write to file */ + if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); + + /* Reset sieve buffer dirty flag */ + f->shared->sieve_dirty=0; } /* end if */ - /* Element size fits within the buffer size */ - else { - /* Check if it is possible to (exactly) prepend or append to existing (dirty) sieve buffer */ - if(((addr+size)==sieve_start || addr==sieve_end) && - (size+sieve_size)<=f->shared->sieve_buf_size && - f->shared->sieve_dirty) { - /* Prepend to existing sieve buffer */ - if((addr+size)==sieve_start) { - /* Move existing sieve information to correct location */ - HDmemmove(f->shared->sieve_buf+size,f->shared->sieve_buf,sieve_size); - - /* Copy in new information (must be first in sieve buffer) */ - HDmemcpy(f->shared->sieve_buf,buf,size); - - /* Adjust sieve location */ - f->shared->sieve_loc=addr; - - } /* end if */ - /* Append to existing sieve buffer */ - else { - /* Copy in new information */ - HDmemcpy(f->shared->sieve_buf+sieve_size,buf,size); - } /* end else */ - - /* Adjust sieve size */ - f->shared->sieve_size += size; - - /* Update local copies of sieve information */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - } /* end if */ - /* Can't add the new data onto the existing sieve buffer */ - else { - /* Flush the sieve buffer if it's dirty */ - if(f->shared->sieve_dirty) { - /* Write to file */ - if (H5F_block_write(f, H5FD_MEM_DRAW, sieve_start, sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - - /* Reset sieve buffer dirty flag */ - f->shared->sieve_dirty=0; - } /* end if */ - - /* Determine the new sieve buffer size & location */ - f->shared->sieve_loc=addr; - - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-f->shared->base_addr; - - /* Only need this when resizing sieve buffer */ - max_data=_max_data-offset_arr[u]; - - /* Compute the size of the sieve buffer */ - /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ - H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - - /* Update local copies of sieve information */ - sieve_start=f->shared->sieve_loc; - sieve_size=f->shared->sieve_size; - sieve_end=sieve_start+sieve_size; - - /* Check if there is any point in reading the data from the file */ - if(f->shared->sieve_size>size) { - /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - } /* end if */ - - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(f->shared->sieve_buf,buf,size); - - /* Set sieve buffer dirty flag */ - f->shared->sieve_dirty=1; - - } /* end else */ - } /* end else */ - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Determine the new sieve buffer size & location */ + f->shared->sieve_loc=addr; - /* Increment sequence number */ - u++; - } /* end else */ - } /* end for */ - } /* end if */ - /* No data sieve buffer yet, go allocate one */ - else { - /* Set up the buffer parameters */ - size=size_arr[u]; - addr=_addr+offset_arr[u]; - max_data=_max_data-offset_arr[u]; + /* Make certain we don't read off the end of the file */ + if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); - /* Check if we can actually hold the I/O request in the sieve buffer */ - if(size>f->shared->sieve_buf_size) { - if (H5F_block_write(f, type, addr, size, 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==(f->shared->sieve_buf=H5FL_BLK_MALLOC(sieve_buf,f->shared->sieve_buf_size))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed"); + /* Adjust absolute EOA address to relative EOA address */ + rel_eoa=abs_eoa-f->shared->base_addr; - /* Determine the new sieve buffer size & location */ - f->shared->sieve_loc=addr; + /* Only need this when resizing sieve buffer */ + max_data=_max_data-dset_offset_arr[u]; - /* Make certain we don't read off the end of the file */ - if (HADDR_UNDEF==(abs_eoa=H5FD_get_eoa(f->shared->lf))) - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to determine file size"); + /* Compute the size of the sieve buffer */ + /* Don't read off the end of the file, don't read past the end of the data element and don't read more than the buffer size */ + H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); - /* Adjust absolute EOA address to relative EOA address */ - rel_eoa=abs_eoa-f->shared->base_addr; + /* Update local copies of sieve information */ + sieve_start=f->shared->sieve_loc; + sieve_size=f->shared->sieve_size; + sieve_end=sieve_start+sieve_size; - /* Compute the size of the sieve buffer */ - H5_ASSIGN_OVERFLOW(f->shared->sieve_size,MIN(rel_eoa-f->shared->sieve_loc,MIN(max_data,f->shared->sieve_buf_size)),hsize_t,size_t); + /* Check if there is any point in reading the data from the file */ + if(f->shared->sieve_size>size) { + /* Read the new sieve buffer */ + if (H5F_block_read(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); + } /* end if */ - /* Check if there is any point in reading the data from the file */ - if(f->shared->sieve_size>size) { - /* Read the new sieve buffer */ - if (H5F_block_read(f, type, f->shared->sieve_loc, f->shared->sieve_size, dxpl_id, f->shared->sieve_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - } /* end if */ + /* Grab the data out of the buffer (must be first piece of data in buffer ) */ + HDmemcpy(f->shared->sieve_buf,buf,size); - /* Grab the data out of the buffer (must be first piece of data in buffer ) */ - HDmemcpy(f->shared->sieve_buf,buf,size); + /* Set sieve buffer dirty flag */ + f->shared->sieve_dirty=1; - /* Set sieve buffer dirty flag */ - f->shared->sieve_dirty=1; + } /* end else */ } /* end else */ + } /* end else */ - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update memory information */ + mem_len_arr[v]-=size; + mem_offset_arr[v]+=size; + if(mem_len_arr[v]==0) + v++; - /* Increment sequence number */ + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) u++; - } /* end else */ + + /* Increment number of bytes copied */ + ret_value+=size; } /* end for */ } /* end if */ else { /* Work through all the sequences */ - for(u=0; u<nseq; u++) { - size=size_arr[u]; - addr=_addr+offset_arr[u]; + 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]; + else + size=dset_len_arr[u]; - if (H5F_block_write(f, type, addr, size, dxpl_id, buf)<0) + /* Compute offset on disk */ + addr=_addr+dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (const unsigned char *)_buf + mem_offset_arr[v]; + + /* Write data */ + if (H5F_block_write(f, H5FD_MEM_DRAW, addr, size, dxpl_id, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - /* Increment offset in buffer */ - buf += size_arr[u]; + /* Update memory information */ + 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) + u++; + + /* Increment number of bytes copied */ + ret_value+=size; } /* end for */ } /* end else */ + /* Update current sequence vectors */ + *dset_curr_seq=u; + *mem_curr_seq=v; + done: FUNC_LEAVE_NOAPI(ret_value); -} /* end H5F_contig_writev() */ +} /* end H5F_contig_writevv() */ diff --git a/src/H5Fistore.c b/src/H5Fistore.c index 7f8d7e1..9629963 100644 --- a/src/H5Fistore.c +++ b/src/H5Fistore.c @@ -1685,246 +1685,154 @@ H5F_istore_unlock(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, /*------------------------------------------------------------------------- - * Function: H5F_istore_read + * Function: H5F_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: Robb Matzke - * Wednesday, October 15, 1997 + * Programmer: Quincey Koziol + * Wednesday, May 7, 2003 * * Modifications: - * Robb Matzke, 1999-08-02 - * The data transfer property list is passed as an object ID - * since that's how the virtual file layer wants it. * - * Quincey Koziol, 2002-04-02 - * Enable hyperslab I/O into memory buffer *------------------------------------------------------------------------- */ -herr_t -H5F_istore_read(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, - const hsize_t size_m[], const hssize_t offset_m[], - const hssize_t offset_f[], const hsize_t size[], void *buf) +ssize_t +H5F_istore_readvv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, + H5P_genplist_t *dc_plist, hssize_t chunk_coords[], + 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[], + void *buf) { - hsize_t idx_cur[H5O_LAYOUT_NDIMS]; - hsize_t idx_min[H5O_LAYOUT_NDIMS]; - hsize_t idx_max[H5O_LAYOUT_NDIMS]; - hsize_t sub_size[H5O_LAYOUT_NDIMS]; - hssize_t offset_wrt_chunk[H5O_LAYOUT_NDIMS]; - hssize_t sub_offset_m[H5O_LAYOUT_NDIMS]; - hssize_t chunk_offset[H5O_LAYOUT_NDIMS]; - int i, carry; - unsigned u; - hsize_t naccessed; /*bytes accessed in chnk*/ - uint8_t *chunk=NULL; /*ptr to a chunk buffer */ - unsigned idx_hint=0; /*cache index hint */ - hsize_t chunk_size; /* Bytes in chunk */ + hsize_t chunk_size; /* Chunk size, in bytes */ haddr_t chunk_addr; /* Chunk address on disk */ + hssize_t chunk_coords_in_elmts[H5O_LAYOUT_NDIMS]; H5O_pline_t pline; /* I/O pipeline information */ - H5O_fill_t fill; /* Fill value information */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5F_istore_read, FAIL); + size_t u; /* Local index variables */ + ssize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5F_istore_readvv, FAIL); /* Check args */ assert(f); assert(layout && H5D_CHUNKED==layout->type); assert(layout->ndims>0 && layout->ndims<=H5O_LAYOUT_NDIMS); - assert(H5F_addr_defined(layout->addr)); - assert(size_m); - assert(offset_m); - assert(offset_f); - assert(size); + assert(chunk_len_arr); + assert(chunk_offset_arr); + assert(mem_len_arr); + assert(mem_offset_arr); assert(buf); /* Get necessary properties from property list */ - if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value"); if(H5P_get(dc_plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data pipeline"); /* Compute chunk size */ for (u=0, chunk_size=1; u<layout->ndims; u++) chunk_size *= layout->dim[u]; - + #ifndef NDEBUG - for (u=0; u<layout->ndims; u++) { - assert(offset_f[u]>=0); /*negative offsets not supported*/ - assert(offset_m[u]>=0); /*negative offsets not supported*/ - assert(size[u]<SIZET_MAX); - assert(offset_m[u]+(hssize_t)size[u]<=(hssize_t)size_m[u]); - assert(layout->dim[u]>0); - } + for (u=0; u<layout->ndims; u++) + assert(chunk_coords[u]>=0); /*negative coordinates not supported (yet) */ #endif + + for (u=0; u<layout->ndims; u++) + chunk_coords_in_elmts[u] = chunk_coords[u] * (hssize_t)(layout->dim[u]); + + /* Get the address of this chunk on disk */ + chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_coords_in_elmts); /* - * Set up multi-dimensional counters (idx_min, idx_max, and idx_cur) and - * loop through the chunks copying each to its final destination in the - * application buffer. + * 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. */ - for (u=0; u<layout->ndims; u++) { - idx_min[u] = offset_f[u] / layout->dim[u]; - idx_max[u] = (offset_f[u]+size[u]-1) / layout->dim[u] + 1; - idx_cur[u] = idx_min[u]; - } - - /* Loop over all chunks */ - carry=0; - while (carry==0) { - for (u=0, naccessed=1; u<layout->ndims; u++) { - /* The location and size of the chunk being accessed */ - assert(layout->dim[u] < HSSIZET_MAX); - chunk_offset[u] = idx_cur[u] * (hssize_t)(layout->dim[u]); - - /* The offset and size wrt the chunk */ - offset_wrt_chunk[u] = MAX(offset_f[u], chunk_offset[u]) - - chunk_offset[u]; - sub_size[u] = MIN((idx_cur[u]+1)*layout->dim[u], - offset_f[u]+size[u]) - - (chunk_offset[u] + offset_wrt_chunk[u]); - naccessed *= sub_size[u]; - - /* Offset into mem buffer */ - sub_offset_m[u] = chunk_offset[u] + offset_wrt_chunk[u] + - offset_m[u] - offset_f[u]; - } + if (chunk_size>f->shared->rdcc_nbytes && pline.nfilters==0 && + chunk_addr!=HADDR_UNDEF) { + if ((ret_value=H5F_contig_readvv(f, chunk_size, chunk_addr, chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_offset_arr, mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, dxpl_id, buf))<0) + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "unable to read raw data to file"); + } /* end if */ + else { + uint8_t *chunk; /* Pointer to cached chunk in memory */ + H5O_fill_t fill; /* Fill value information */ + unsigned idx_hint=0; /* Cache index hint */ + ssize_t naccessed; /* Number of bytes accessed in chunk */ - /* Get the address of this chunk on disk */ - chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_offset); + /* Get necessary properties from property list */ + if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value"); /* - * 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. + * Lock the chunk, copy from application to chunk, then unlock the + * chunk. */ - if ((chunk_size>f->shared->rdcc_nbytes && pline.nfilters==0 && - chunk_addr!=HADDR_UNDEF) + if (NULL==(chunk=H5F_istore_lock(f, dxpl_id, layout, &pline, &fill, + chunk_coords_in_elmts, FALSE, &idx_hint))) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk"); - /* - * If MPIO, MPIPOSIX, or FPHDF5 is used and file can be written - * to, we 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. - */ - || ((IS_H5FD_MPIO(f) ||IS_H5FD_MPIPOSIX(f) || IS_H5FD_FPHDF5(f)) && (H5F_ACC_RDWR & f->shared->flags)) - ) { - H5O_layout_t l; /* temporary layout */ + /* 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"); -#ifdef H5_HAVE_PARALLEL - /* Additional sanity checks when operating in parallel */ - if (chunk_addr==HADDR_UNDEF || pline.nfilters>0) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to locate raw data chunk"); -#endif /* H5_HAVE_PARALLEL */ - - /* - * use default transfer mode as we do not support collective - * transfer mode since each data write could decompose into - * multiple chunk writes and we are not doing the calculation yet. - */ - l.type = H5D_CONTIGUOUS; - l.ndims = layout->ndims; - for (u=l.ndims; u-- > 0; /*void*/) - l.dim[u] = layout->dim[u]; - l.addr = chunk_addr; - if (H5F_arr_read(f, dxpl_id, &l, dc_plist, sub_size, size_m, sub_offset_m, offset_wrt_chunk, buf)<0) - HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL, "unable to read raw data from file"); - } /* end if */ - else { - /* - * Lock the chunk, transfer data to the application, then unlock - * the chunk. - */ - if (NULL==(chunk=H5F_istore_lock(f, dxpl_id, layout, &pline, &fill, - chunk_offset, FALSE, &idx_hint))) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to read raw data chunk"); - H5V_hyper_copy(layout->ndims, sub_size, size_m, sub_offset_m, - (void*)buf, layout->dim, offset_wrt_chunk, chunk); - H5_CHECK_OVERFLOW(naccessed,hsize_t,size_t); - if (H5F_istore_unlock(f, dxpl_id, layout, &pline, FALSE, - chunk_offset, &idx_hint, chunk, (size_t)naccessed)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk"); - } /* end else */ - - /* Increment indices */ - for (i=(int)(layout->ndims-1), carry=1; i>=0 && carry; --i) { - if (++idx_cur[i]>=idx_max[i]) - idx_cur[i] = idx_min[i]; - else - carry = 0; - } - } + H5_CHECK_OVERFLOW(naccessed,ssize_t,size_t); + if (H5F_istore_unlock(f, dxpl_id, layout, &pline, FALSE, + chunk_coords_in_elmts, &idx_hint, chunk, (size_t)naccessed)<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk"); + /* Set return value */ + ret_value=naccessed; + } /* end else */ + done: FUNC_LEAVE_NOAPI(ret_value); -} +} /* H5F_istore_readvv() */ /*------------------------------------------------------------------------- - * Function: H5F_istore_write + * Function: H5F_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: Robb Matzke - * Wednesday, October 15, 1997 + * Programmer: Quincey Koziol + * Friday, May 2, 2003 * * Modifications: - * Robb Matzke, 1999-08-02 - * The data transfer property list is passed as an object ID - * since that's how the virtual file layer wants it. * - * Quincey Koziol, 2002-04-02 - * Enable hyperslab I/O into memory buffer *------------------------------------------------------------------------- */ -herr_t -H5F_istore_write(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, - const hsize_t size_m[], const hssize_t offset_m[], - const hssize_t offset_f[], const hsize_t size[], - const void *buf) +ssize_t +H5F_istore_writevv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, + H5P_genplist_t *dc_plist, hssize_t chunk_coords[], + 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[], + const void *buf) { - int i, carry; - unsigned u; - hsize_t idx_cur[H5O_LAYOUT_NDIMS]; - hsize_t idx_min[H5O_LAYOUT_NDIMS]; - hsize_t idx_max[H5O_LAYOUT_NDIMS]; - hsize_t sub_size[H5O_LAYOUT_NDIMS]; - hssize_t chunk_offset[H5O_LAYOUT_NDIMS]; - hssize_t offset_wrt_chunk[H5O_LAYOUT_NDIMS]; - hssize_t sub_offset_m[H5O_LAYOUT_NDIMS]; - uint8_t *chunk=NULL; - unsigned idx_hint=0; - hsize_t chunk_size, naccessed; + hsize_t chunk_size; /* Chunk size, in bytes */ haddr_t chunk_addr; /* Chunk address on disk */ + hssize_t chunk_coords_in_elmts[H5O_LAYOUT_NDIMS]; H5O_pline_t pline; /* I/O pipeline information */ - H5O_fill_t fill; /* Fill value information */ - herr_t ret_value = SUCCEED; /* Return value */ + size_t u; /* Local index variables */ + ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5F_istore_write, FAIL); + FUNC_ENTER_NOAPI(H5F_istore_writevv, FAIL); /* Check args */ assert(f); assert(layout && H5D_CHUNKED==layout->type); assert(layout->ndims>0 && layout->ndims<=H5O_LAYOUT_NDIMS); - assert(H5F_addr_defined(layout->addr)); - assert(size_m); - assert(offset_m); - assert(offset_f); - assert(size); + assert(chunk_len_arr); + assert(chunk_offset_arr); + assert(mem_len_arr); + assert(mem_offset_arr); assert(buf); /* Get necessary properties from property list */ - if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value"); if(H5P_get(dc_plist, H5D_CRT_DATA_PIPELINE_NAME, &pline) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get data pipeline"); @@ -1933,118 +1841,79 @@ H5F_istore_write(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, chunk_size *= layout->dim[u]; #ifndef NDEBUG - for (u=0; u<layout->ndims; u++) { - assert(offset_f[u]>=0); /*negative offsets not supported*/ - assert(offset_m[u]>=0); /*negative offsets not supported*/ - assert(size[u]<SIZET_MAX); - assert(offset_m[u]+(hssize_t)size[u]<=(hssize_t)size_m[u]); - assert(layout->dim[u]>0); - } + for (u=0; u<layout->ndims; u++) + assert(chunk_coords[u]>=0); /*negative coordinates not supported (yet) */ #endif + + for (u=0; u<layout->ndims; u++) + chunk_coords_in_elmts[u] = chunk_coords[u] * (hssize_t)(layout->dim[u]); + + /* Get the address of this chunk on disk */ + chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_coords_in_elmts); /* - * Set up multi-dimensional counters (idx_min, idx_max, and idx_cur) and - * loop through the chunks copying each chunk from the application to the - * chunk 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 write the data to it directly. + * + * If MPIO, MPIPOSIX, or FPHDF5 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. */ - for (u=0; u<layout->ndims; u++) { - idx_min[u] = offset_f[u] / layout->dim[u]; - idx_max[u] = (offset_f[u]+size[u]-1) / layout->dim[u] + 1; - idx_cur[u] = idx_min[u]; - } - - - /* Loop over all chunks */ - carry=0; - while (carry==0) { - for (u=0, naccessed=1; u<layout->ndims; u++) { - /* The location and size of the chunk being accessed */ - assert(layout->dim[u] < HSSIZET_MAX); - chunk_offset[u] = idx_cur[u] * (hssize_t)(layout->dim[u]); - - /* The offset and size wrt the chunk */ - offset_wrt_chunk[u] = MAX(offset_f[u], chunk_offset[u]) - - chunk_offset[u]; - sub_size[u] = MIN((idx_cur[u]+1)*layout->dim[u], - offset_f[u]+size[u]) - - (chunk_offset[u] + offset_wrt_chunk[u]); - naccessed *= sub_size[u]; - - /* Offset into mem buffer */ - sub_offset_m[u] = chunk_offset[u] + offset_wrt_chunk[u] + - offset_m[u] - offset_f[u]; - } - - /* Get the address of this chunk on disk */ - chunk_addr=H5F_istore_get_addr(f, dxpl_id, layout, chunk_offset); + if ((chunk_size>f->shared->rdcc_nbytes && pline.nfilters==0 && + chunk_addr!=HADDR_UNDEF) + || ((IS_H5FD_MPIO(f) ||IS_H5FD_MPIPOSIX(f) || IS_H5FD_FPHDF5(f)) && + (H5F_ACC_RDWR & f->shared->flags))) { +#ifdef H5_HAVE_PARALLEL + /* Additional sanity check when operating in parallel */ + if (chunk_addr==HADDR_UNDEF || pline.nfilters>0) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to locate raw data chunk"); +#endif /* H5_HAVE_PARALLEL */ + if ((ret_value=H5F_contig_writevv(f, chunk_size, chunk_addr, chunk_max_nseq, chunk_curr_seq, chunk_len_arr, chunk_offset_arr, mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, dxpl_id, buf))<0) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file"); + } /* end if */ + else { + uint8_t *chunk; /* Pointer to cached chunk in memory */ + H5O_fill_t fill; /* Fill value information */ + unsigned idx_hint=0; /* Cache index hint */ + ssize_t naccessed; /* Number of bytes accessed in chunk */ + hbool_t relax; /* Whether whole chunk is selected */ - /* - * 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 ((chunk_size>f->shared->rdcc_nbytes && pline.nfilters==0 && - chunk_addr!=HADDR_UNDEF) + /* Get necessary properties from property list */ + if(H5P_get(dc_plist, H5D_CRT_FILL_VALUE_NAME, &fill) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get fill value"); /* - * If MPIO, MPIPOSIX, or FPHDF5 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. + * Lock the chunk, copy from application to chunk, then unlock the + * chunk. */ - || ((IS_H5FD_MPIO(f) ||IS_H5FD_MPIPOSIX(f) || IS_H5FD_FPHDF5(f)) && (H5F_ACC_RDWR & f->shared->flags)) - ) { - H5O_layout_t l; /* temporary layout */ - -#ifdef H5_HAVE_PARALLEL - /* Additional sanity check when operating in parallel */ - if (chunk_addr==HADDR_UNDEF || pline.nfilters>0) { - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to locate raw data chunk"); - } -#endif /* H5_HAVE_PARALLEL */ - - /* - * use default transfer mode as we do not support collective - * transfer mode since each data write could decompose into - * multiple chunk writes and we are not doing the calculation yet. - */ - l.type = H5D_CONTIGUOUS; - l.ndims = layout->ndims; - for (u=l.ndims; u-- > 0; /*void*/) - l.dim[u] = layout->dim[u]; - l.addr = chunk_addr; - if (H5F_arr_write(f, dxpl_id, &l, dc_plist, sub_size, size_m, sub_offset_m, offset_wrt_chunk, buf)<0) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file"); - } /* end if */ - else { - /* - * Lock the chunk, copy from application to chunk, then unlock the - * chunk. - */ - if (NULL==(chunk=H5F_istore_lock(f, dxpl_id, layout, &pline, &fill, - chunk_offset, (hbool_t)(naccessed==chunk_size), &idx_hint))) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to read raw data chunk"); - H5V_hyper_copy(layout->ndims, sub_size, - layout->dim, offset_wrt_chunk, chunk, size_m, sub_offset_m, buf); - H5_CHECK_OVERFLOW(naccessed,hsize_t,size_t); - if (H5F_istore_unlock(f, dxpl_id, layout, &pline, TRUE, - chunk_offset, &idx_hint, chunk, (size_t)naccessed)<0) - HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "uanble to unlock raw data chunk"); - } /* end else */ + if(chunk_max_nseq==1 && chunk_len_arr[0] == chunk_size) + relax = TRUE; + else + relax = FALSE; + + if (NULL==(chunk=H5F_istore_lock(f, dxpl_id, layout, &pline, &fill, + chunk_coords_in_elmts, relax, &idx_hint))) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "unable to read raw data 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); + if (H5F_istore_unlock(f, dxpl_id, layout, &pline, TRUE, + chunk_coords_in_elmts, &idx_hint, chunk, (size_t)naccessed)<0) + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL, "uanble to unlock raw data chunk"); + + /* Set return value */ + ret_value=naccessed; + } /* end else */ - /* Increment indices */ - for (i=layout->ndims-1, carry=1; i>=0 && carry; --i) { - if (++idx_cur[i]>=idx_max[i]) - idx_cur[i] = idx_min[i]; - else - carry = 0; - } - } /* end while */ - done: FUNC_LEAVE_NOAPI(ret_value); -} +} /* H5F_istore_writevv() */ /*------------------------------------------------------------------------- @@ -2808,7 +2677,8 @@ H5F_istore_initialize_by_extent(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *lay hsize_t size[H5O_LAYOUT_NDIMS]; /*current size of dimensions */ H5S_t *space_chunk = NULL; /*dataspace for a chunk */ hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /*current dataspace dimensions */ - int rank; /*current # of dimensions */ + int srank; /*current # of dimensions (signed) */ + unsigned rank; /*current # of dimensions */ int i, carry; /*counters */ unsigned u; int found = 0; /*initialize this entry */ @@ -2836,13 +2706,14 @@ H5F_istore_initialize_by_extent(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *lay HDmemset(count, 0, sizeof(count)); /* Go get the rank & dimensions */ - if((rank = H5S_get_simple_extent_dims(space, curr_dims, NULL)) < 0) + if((srank = H5S_get_simple_extent_dims(space, curr_dims, NULL)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions"); + rank=srank; /* Copy current dimensions */ - for(i = 0; i < rank; i++) - size[i] = curr_dims[i]; - size[i] = layout->dim[i]; + for(u = 0; u < rank; u++) + size[u] = curr_dims[u]; + size[u] = layout->dim[u]; /* Create a data space for a chunk & set the extent */ if(NULL == (space_chunk = H5S_create_simple(rank,layout->dim,NULL))) @@ -2891,8 +2762,8 @@ H5F_istore_initialize_by_extent(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *lay if(H5S_select_all(space_chunk,1) < 0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to select space"); - for(i = 0; i < rank; i++) - count[i] = MIN((idx_cur[i] + 1) * layout->dim[i], size[i] - chunk_offset[i]); + for(u = 0; u < rank; u++) + count[u] = MIN((idx_cur[u] + 1) * layout->dim[u], size[u] - chunk_offset[u]); #if defined (H5F_ISTORE_DEBUG) HDfputs("cache:initialize:offset:[", stdout); diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h index 1b7e49c..0b875b7 100644 --- a/src/H5Fpkg.h +++ b/src/H5Fpkg.h @@ -81,7 +81,7 @@ #else # define H5F_OVERFLOW_HSIZET2OFFT(X) 0 #endif - + /* The raw data chunk cache */ typedef struct H5F_rdcc_t { unsigned ninits; /* Number of chunk creations */ @@ -198,40 +198,38 @@ H5_DLL herr_t H5F_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, H5_DLL herr_t H5F_istore_init (H5F_t *f); H5_DLL herr_t H5F_istore_flush (H5F_t *f, hid_t dxpl_id, unsigned flags); H5_DLL herr_t H5F_istore_dest (H5F_t *f, hid_t dxpl_id); -H5_DLL herr_t H5F_istore_read(H5F_t *f, hid_t dxpl_id, - const struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, - const hsize_t size_m[], const hssize_t offset_m[], - const hssize_t offset_f[], const hsize_t size[], - void *buf/*out*/); -H5_DLL herr_t H5F_istore_write(H5F_t *f, hid_t dxpl_id, - const struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, - const hsize_t size_m[], const hssize_t offset_m[], - const hssize_t offset[], const hsize_t size[], - const void *buf); +H5_DLL ssize_t H5F_istore_readvv(H5F_t *f, hid_t dxpl_id, + const struct H5O_layout_t *layout, struct H5P_genplist_t *dc_plist, hssize_t chunk_coords[], + 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[], + void *buf); +H5_DLL ssize_t H5F_istore_writevv(H5F_t *f, hid_t dxpl_id, + const struct H5O_layout_t *layout, struct H5P_genplist_t *dc_plist, hssize_t chunk_coords[], + 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[], + const void *buf); H5_DLL herr_t H5F_istore_stats (H5F_t *f, hbool_t headers); H5_DLL herr_t H5F_istore_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int fwidth, int ndims); /* Functions that operate on contiguous storage wrt boot block */ -H5_DLL herr_t H5F_contig_read(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr, - size_t size, hid_t dxpl_id, void *_buf/*out*/); -H5_DLL herr_t H5F_contig_write(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr, - size_t size, hid_t dxpl_id, const void *buf); -H5_DLL herr_t H5F_contig_readv(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr, - size_t nseq, size_t size[], hsize_t offset[], hid_t dxpl_id, void *_buf/*out*/); -H5_DLL herr_t H5F_contig_writev(H5F_t *f, hsize_t max_data, H5FD_mem_t type, haddr_t addr, - size_t nseq, size_t size[], hsize_t offset[], hid_t dxpl_id, const void *buf); +H5_DLL herr_t H5F_contig_readvv(H5F_t *f, hsize_t _max_data, haddr_t _addr, + 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[], + hid_t dxpl_id, void *buf); +H5_DLL ssize_t H5F_contig_writevv(H5F_t *f, hsize_t _max_data, haddr_t _addr, + 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[], + hid_t dxpl_id, const void *buf); /* Functions that operate on compact dataset storage */ -H5_DLL herr_t H5F_compact_readv(H5F_t *f, const struct H5O_layout_t *layout, size_t nseq, - size_t size_arr[], hsize_t offset_arr[], - hid_t dxpl_id, void *_buf/*out*/); -H5_DLL herr_t H5F_compact_writev(H5F_t *f, struct H5O_layout_t *layout, size_t nseq, - size_t size_arr[], hsize_t offset_arr[], - hid_t dxpl_id, const void *_buf); - - +H5_DLL ssize_t H5F_compact_readvv(H5F_t UNUSED *f, const struct H5O_layout_t *layout, + 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[], + hid_t UNUSED dxpl_id, void *buf); +H5_DLL ssize_t H5F_compact_writevv(H5F_t UNUSED *f, struct H5O_layout_t *layout, + 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[], + hid_t UNUSED dxpl_id, const void *buf); #endif diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 6276422..26bd833 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -369,6 +369,7 @@ struct H5O_fill_t; struct H5P_genplist_t; struct H5S_t; struct H5B_class_t; +union H5D_storage_t; /* Private functions, not part of the publicly documented API */ H5_DLL herr_t H5F_init(void); @@ -392,23 +393,6 @@ H5_DLL size_t H5F_sizeof_size(const H5F_t *f); H5_DLL unsigned H5F_sym_leaf_k(const H5F_t *f); H5_DLL int H5F_Kvalue(const H5F_t *f, const struct H5B_class_t *type); - -/* Functions that operate on array storage */ -H5_DLL herr_t H5F_arr_read (H5F_t *f, hid_t dxpl_id, - const struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, - const hsize_t _hslab_size[], - const hsize_t mem_size[], - const hssize_t mem_offset[], - const hssize_t file_offset[], void *_buf/*out*/); -H5_DLL herr_t H5F_arr_write (H5F_t *f, hid_t dxpl_id, - struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, - const hsize_t _hslab_size[], - const hsize_t mem_size[], - const hssize_t mem_offset[], - const hssize_t file_offset[], const void *_buf); - /* Functions that operate on blocks of bytes wrt boot block */ H5_DLL herr_t H5F_block_read(H5F_t *f, H5FD_mem_t type, haddr_t addr, size_t size, hid_t dxpl_id, void *buf/*out*/); @@ -418,32 +402,33 @@ H5_DLL herr_t H5F_block_write(H5F_t *f, H5FD_mem_t type, haddr_t addr, /* Functions that operate on byte sequences */ H5_DLL herr_t H5F_seq_read(H5F_t *f, hid_t dxpl_id, const struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, - const struct H5S_t *file_space, size_t elmt_size, size_t seq_len, + struct H5P_genplist_t *dc_plist, const union H5D_storage_t *store, + size_t seq_len, hsize_t file_offset, void *_buf/*out*/); H5_DLL herr_t H5F_seq_write (H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, - const struct H5S_t *file_space, size_t elmt_size, size_t seq_len, + struct H5P_genplist_t *dc_plist, const union H5D_storage_t *store, + size_t seq_len, hsize_t file_offset, const void *_buf); -/* Functions that operate on vectors of byte sequences */ -H5_DLL herr_t H5F_seq_readv(H5F_t *f, hid_t dxpl_id, - const struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, - const struct H5S_t *file_space, size_t elmt_size, size_t nseq, - size_t seq_len[], hsize_t file_offset[], void *_buf/*out*/); -H5_DLL herr_t H5F_seq_writev(H5F_t *f, hid_t dxpl_id, - struct H5O_layout_t *layout, - struct H5P_genplist_t *dc_plist, const struct H5O_efl_t *efl, - const struct H5S_t *file_space, size_t elmt_size, size_t nseq, - size_t seq_len[], hsize_t file_offset[], const void *_buf); - +/* Functions that operate on byte sequences in memory and on disk */ +H5_DLL ssize_t H5F_seq_readvv(H5F_t *f, hid_t dxpl_id, const struct H5O_layout_t *layout, + struct H5P_genplist_t *dc_plist, const union H5D_storage_t *store, + 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[], + void *buf); +H5_DLL ssize_t H5F_seq_writevv(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, + struct H5P_genplist_t *dc_plist, const union H5D_storage_t *store, + 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[], + const void *buf); /* Functions that operate on contiguous storage */ +H5_DLL herr_t H5F_contig_create(H5F_t *f, hid_t dxpl_id, + struct H5O_layout_t *layout); H5_DLL herr_t H5F_contig_fill(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, struct H5P_genplist_t *dc_plist, - const struct H5O_efl_t *efl, const struct H5S_t *space, + const struct H5S_t *space, const struct H5O_fill_t *fill, size_t elmt_size); H5_DLL herr_t H5F_contig_delete(H5F_t *f, hid_t dxpl_id, const struct H5O_layout_t *layout); diff --git a/src/H5Fseq.c b/src/H5Fseq.c index 113a8d5..5248b0a 100644 --- a/src/H5Fseq.c +++ b/src/H5Fseq.c @@ -70,22 +70,24 @@ static int interface_initialize_g = 0; */ herr_t H5F_seq_read(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, + H5P_genplist_t *dc_plist, const H5D_storage_t *store, size_t seq_len, hsize_t dset_offset, void *buf/*out*/) { - herr_t ret_value=SUCCEED; /* Return value */ + hsize_t mem_off=0; /* Offset in memory */ + size_t mem_len=seq_len; /* Length in memory */ + size_t mem_curr_seq=0; /* "Current sequence" in memory */ + size_t dset_curr_seq=0; /* "Current sequence" in dataset */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_seq_read, FAIL); /* Check args */ assert(f); assert(layout); - assert(efl); assert(buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) + if (H5F_seq_readvv(f, dxpl_id, layout, dc_plist, store, 1, &dset_curr_seq, &seq_len, &dset_offset, 1, &mem_curr_seq, &mem_len, &mem_off, buf)<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "vector read failed"); done: @@ -116,22 +118,24 @@ done: */ herr_t H5F_seq_write(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, + H5P_genplist_t *dc_plist, const H5D_storage_t *store, size_t seq_len, hsize_t dset_offset, const void *buf) { - herr_t ret_value=SUCCEED; /* Return value */ + hsize_t mem_off=0; /* Offset in memory */ + size_t mem_len=seq_len; /* Length in memory */ + size_t mem_curr_seq=0; /* "Current sequence" in memory */ + size_t dset_curr_seq=0; /* "Current sequence" in dataset */ + herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5F_seq_write, FAIL); /* Check args */ assert(f); assert(layout); - assert(efl); assert(buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, 1, &seq_len, &dset_offset, buf)<0) + if (H5F_seq_writevv(f, dxpl_id, layout, dc_plist, store, 1, &dset_curr_seq, &seq_len, &dset_offset, 1, &mem_curr_seq, &mem_len, &mem_off, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "vector write failed"); done: @@ -140,7 +144,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5F_seq_readv + * Function: H5F_seq_readvv * * Purpose: Reads in a vector of byte sequences from a file dataset into a * buffer in in memory. The data is read from file F and the array's size @@ -152,53 +156,61 @@ done: * Bytes read into BUF are sequentially stored in the buffer, each sequence * from the vector stored directly after the previous. The number of * sequences is NSEQ. + * Purpose: Reads a vector of byte sequences from a vector of byte + * sequences in a file dataset into a buffer in memory. The data is + * read from file F and the array's size and storage information is in + * LAYOUT. External files and chunks are described according to the + * storage information, STORE. The vector of byte sequences offsets for + * the file is in the DSET_OFFSET_ARR array into the dataset (offsets are + * in terms of bytes) and the size of each sequence is in the DSET_LEN_ARR + * array. The vector of byte sequences offsets for memory is in the + * MEM_OFFSET_ARR array into the dataset (offsets are in terms of bytes) + * and the size of each sequence is in the MEM_LEN_ARR array. The total + * size of the file array is implied in the LAYOUT argument. The maximum + * number of sequences in the file dataset and the memory buffer are + * DSET_MAX_NSEQ & MEM_MAX_NSEQ respectively. The current sequence being + * operated on in the file dataset and the memory buffer are DSET_CURR_SEQ + * & MEM_CURR_SEQ respectively. The current sequence being operated on + * will be updated as a result of the operation, as will the offsets and + * lengths of the file dataset and memory buffer sequences. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Wednesday, May 1, 2001 + * Wednesday, May 7, 2003 * * Modifications: * *------------------------------------------------------------------------- */ -herr_t -H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, - size_t nseq, size_t seq_len_arr[], hsize_t dset_offset_arr[], - void *_buf/*out*/) +ssize_t +H5F_seq_readvv(H5F_t *f, hid_t dxpl_id, const struct H5O_layout_t *layout, + struct H5P_genplist_t *dc_plist, const H5D_storage_t *store, + 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[], + void *buf/*out*/) { - unsigned char *real_buf=(unsigned char *)_buf; /* Local pointer to buffer to fill */ - unsigned char *buf; /* Local pointer to buffer to fill */ - hsize_t dset_offset; /* Offset in dataset */ - hsize_t seq_len; /* Number of bytes to read */ - hsize_t dset_dims[H5O_LAYOUT_NDIMS]; /* dataspace dimensions */ - hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in memory buffer */ - hssize_t coords[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in dataspace */ - hsize_t hslab_size[H5O_LAYOUT_NDIMS]; /* hyperslab size in dataspace*/ - hsize_t down_size[H5O_LAYOUT_NDIMS]; /* Cumulative yperslab sizes (in elements) */ - hsize_t acc; /* Accumulator for hyperslab sizes (in elements) */ - int ndims; - hsize_t max_data; /*bytes in dataset */ - haddr_t addr=0; /*address in file */ - unsigned u; /*counters */ - size_t v; /*counters */ - int i,j; /*counters */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; #endif /* H5_HAVE_PARALLEL */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5F_seq_readv, FAIL); + FUNC_ENTER_NOAPI(H5F_seq_readvv, FAIL); /* Check args */ assert(f); + assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); /* Make certain we have the correct type of property list */ assert(layout); - assert(efl); - assert(real_buf); - /* Make certain we have the correct type of property list */ - assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); + assert(dc_plist); + assert(dset_curr_seq); + assert(*dset_curr_seq<dset_max_nseq); + assert(dset_len_arr); + assert(dset_offset_arr); + assert(mem_curr_seq); + assert(*mem_curr_seq<mem_max_nseq); + assert(mem_len_arr); + assert(mem_offset_arr); + assert(buf); #ifdef H5_HAVE_PARALLEL /* Get the transfer mode for MPIO transfers */ @@ -229,285 +241,52 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, switch (layout->type) { case H5D_CONTIGUOUS: /* Read directly from file if the dataset is in an external file */ - if (efl->nused>0) { - /* Iterate through the sequence vectors */ - for(v=0; v<nseq; v++) { -#ifdef H5_HAVE_PARALLEL - if (H5FD_MPIO_COLLECTIVE==xfer_mode) { - /* - * Currently supports same number of collective access. Need to - * be changed LATER to combine all reads into one collective MPIO - * call. - */ - unsigned long max, min, temp; - - temp = seq_len_arr[v]; - assert(temp==seq_len_arr[v]); /* verify no overflow */ - MPI_Allreduce(&temp, &max, 1, MPI_UNSIGNED_LONG, MPI_MAX, - H5FD_mpio_communicator(f->shared->lf)); - MPI_Allreduce(&temp, &min, 1, MPI_UNSIGNED_LONG, MPI_MIN, - H5FD_mpio_communicator(f->shared->lf)); -#ifdef AKC - printf("seq_len=%lu, min=%lu, max=%lu\n", temp, min, max); -#endif - if (max != min) - HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, - "collective access with unequal number of blocks not supported yet"); - } -#endif /* H5_HAVE_PARALLEL */ - /* Note: We can't use data sieve buffers for datasets in external files - * because the 'addr' of all external files is set to 0 (above) and - * all datasets in external files would alias to the same set of - * file offsets, totally mixing up the data sieve buffer information. -QAK - */ - H5_CHECK_OVERFLOW(dset_offset_arr[v],hsize_t,haddr_t); - if (H5O_efl_read(f, efl, (haddr_t)dset_offset_arr[v], seq_len_arr[v], real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "external data read failed"); - - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ + if (store && store->efl.nused>0) { + /* Note: We can't use data sieve buffers for datasets in external files + * because the 'addr' of all external files is set to 0 (above) and + * all datasets in external files would alias to the same set of + * file offsets, totally mixing up the data sieve buffer information. -QAK + */ + if((ret_value=H5O_efl_readvv(&(store->efl), + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "external data read failed"); } else { + hsize_t max_data; /*bytes in dataset */ + unsigned u; /*counters */ + /* Compute the size of the dataset in bytes */ for(u=1, max_data=layout->dim[0]; u<layout->ndims; u++) max_data *= layout->dim[u]; /* Pass along the vector of sequences to read */ - if (H5F_contig_readv(f, max_data, H5FD_MEM_DRAW, layout->addr, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) + if((ret_value=H5F_contig_readvv(f, max_data, layout->addr, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); } /* end else */ break; case H5D_CHUNKED: - /* - * This method is unable to access external raw data files - */ - if (efl->nused>0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); - - /* Compute the file offset coordinates and hyperslab size */ - if((ndims=H5S_get_simple_extent_dims(file_space,dset_dims,NULL))<0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unable to retrieve dataspace dimensions"); - - /* Build the array of cumulative hyperslab sizes */ - /* (And set the memory offset to zero) */ - for(acc=1, i=(ndims-1); i>=0; i--) { - mem_offset[i]=0; - down_size[i]=acc; - acc*=dset_dims[i]; - } /* end for */ - mem_offset[ndims]=0; - - /* Brute-force, stupid way to implement the vectors, but too complex to do other ways... */ - for(v=0; v<nseq; v++) { - dset_offset=dset_offset_arr[v]; - seq_len=seq_len_arr[v]; - buf=real_buf; - - { - /* Set location in dataset from the dset_offset */ - addr=dset_offset; - - /* Convert the bytes into elements */ - seq_len/=elmt_size; - addr/=elmt_size; - - /* Compute the hyperslab offset from the address given */ - for(i=ndims-1; i>=0; i--) { - coords[i]=addr%dset_dims[i]; - addr/=dset_dims[i]; - } /* end for */ - coords[ndims]=0; /* No offset for element info */ - - /* - * Peel off initial partial hyperslabs until we've got a hyperslab which starts - * at coord[n]==0 for dimensions 1->(ndims-1) (i.e. starting at coordinate - * zero for all dimensions except the slowest changing one - */ - for(i=ndims-1; i>0 && seq_len>=down_size[i]; i--) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* Check if we have a partial hyperslab in this lower dimension */ - if(coords[i]>0) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(i==j) - hslab_size[j]=MIN(seq_len/down_size[i],dset_dims[i]-coords[i]); - else - if(j>i) - hslab_size[j]=dset_dims[j]; - else - hslab_size[j]=1; - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read in the partial hyperslab */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, - buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Increment the buffer offset */ - buf=(unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=0; - coords[i-1]++; - - /* Carry the coord array correction up the array, if the dimension is finished */ - while(i>0 && coords[i-1]==(hssize_t)dset_dims[i-1]) { - i--; - coords[i]=0; - if(i>0) { - coords[i-1]++; - assert(coords[i-1]<=(hssize_t)dset_dims[i-1]); - } /* end if */ - } /* end while */ - } /* end if */ - } /* end for */ - - /* Check if there is more than just a partial hyperslab to read */ - if(seq_len>=down_size[0]) { - hsize_t tmp_seq_len; /* Temp. size of the sequence in elements */ - hsize_t full_size; /* Size of the full hyperslab in bytes */ - - /* Get the sequence length for computing the hyperslab sizes */ - tmp_seq_len=seq_len; - - /* Reset the size of the hyperslab read in */ - full_size=1; - - /* Compute the hyperslab size from the length given */ - for(i=ndims-1; i>=0; i--) { - /* Check if the hyperslab is wider than the width of the dimension */ - if(tmp_seq_len>dset_dims[i]) { - assert(0==coords[i]); - hslab_size[i]=dset_dims[i]; - } /* end if */ - else - hslab_size[i]=tmp_seq_len; - - /* compute the number of elements read in */ - full_size*=hslab_size[i]; - - /* Fold the length into the length in the next highest dimension */ - tmp_seq_len/=dset_dims[i]; - - /* Make certain the hyperslab sizes don't go less than 1 for dimensions less than 0*/ - assert(tmp_seq_len>=1 || i==0); - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read the full hyperslab in */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Increment the buffer offset */ - buf=(unsigned char *)buf+(full_size*elmt_size); - - /* Decrement the sequence length left */ - seq_len-=full_size; - - /* Increment coordinate of slowest changing dimension */ - coords[0]+=hslab_size[0]; - - } /* end if */ - - /* - * Peel off final partial hyperslabs until we've finished reading all the data - */ - if(seq_len>0) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* - * Peel off remaining partial hyperslabs, from the next-slowest dimension - * on down to the next-to-fastest changing dimension - */ - for(i=1; i<(ndims-1); i++) { - /* Check if there are enough elements to read in a row in this dimension */ - if(seq_len>=down_size[i]) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j<i) - hslab_size[j]=1; - else - if(j==i) - hslab_size[j]=seq_len/down_size[j]; - else - hslab_size[j]=dset_dims[j]; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read in the partial hyperslab */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Increment the buffer offset */ - buf=(unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=hslab_size[i]; - } /* end if */ - } /* end for */ - - /* Handle fastest changing dimension if there are any elements left */ - if(seq_len>0) { - assert(seq_len<dset_dims[ndims-1]); - - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j==(ndims-1)) - hslab_size[j]=seq_len; - else - hslab_size[j]=1; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Read in the partial hyperslab */ - if (H5F_istore_read(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "chunked read failed"); - - /* Double-check the amount read in */ - assert(seq_len==partial_size); - } /* end if */ - } /* end if */ - } - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ - + assert(store); + if((ret_value=H5F_istore_readvv(f, dxpl_id, layout, dc_plist, store->chunk_coords, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "istore read failed"); break; case H5D_COMPACT: - /* Pass along the vector of sequences to read */ - if (H5F_compact_readv(f, layout, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "block read failed"); - + if((ret_value=H5F_compact_readvv(f, layout, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "compact read failed"); break; + default: assert("not implemented yet" && 0); HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unsupported storage layout"); @@ -515,69 +294,67 @@ H5F_seq_readv(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout, done: FUNC_LEAVE_NOAPI(ret_value); -} /* H5F_seq_readv() */ +} /* H5F_seq_readvv() */ /*------------------------------------------------------------------------- - * Function: H5F_seq_writev + * Function: H5F_seq_writevv * * Purpose: Writes a vector of byte sequences from a buffer in memory into - * a file dataset. The data is written to file F and the array's size - * and storage information is in LAYOUT. External files are described - * according to the external file list, EFL. The vector of byte sequences - * offsets is in the DSET_OFFSET array into the dataset (offsets are in - * terms of bytes) and the size of each sequence is in the SEQ_LEN array. - * The total size of the file array is implied in the LAYOUT argument. - * Bytes written from BUF are sequentially stored in the buffer, each sequence - * from the vector stored directly after the previous. The number of - * sequences is NSEQ. + * a vector of byte sequences in a file dataset. The data is written to + * file F and the array's size and storage information is in LAYOUT. + * External files and chunks are described according to the storage + * information, STORE. The vector of byte sequences offsets for the file + * is in the DSET_OFFSET_ARR array into the dataset (offsets are in + * terms of bytes) and the size of each sequence is in the DSET_LEN_ARR + * array. The vector of byte sequences offsets for memory is in the + * MEM_OFFSET_ARR array into the dataset (offsets are in terms of bytes) + * and the size of each sequence is in the MEM_LEN_ARR array. The total + * size of the file array is implied in the LAYOUT argument. The maximum + * number of sequences in the file dataset and the memory buffer are + * DSET_MAX_NSEQ & MEM_MAX_NSEQ respectively. The current sequence being + * operated on in the file dataset and the memory buffer are DSET_CURR_SEQ + * & MEM_CURR_SEQ respectively. The current sequence being operated on + * will be updated as a result of the operation, as will the offsets and + * lengths of the file dataset and memory buffer sequences. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol - * Friday, July 6, 2001 + * Friday, May 2, 2003 * * Modifications: * *------------------------------------------------------------------------- */ -herr_t -H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, - const H5S_t *file_space, size_t elmt_size, - size_t nseq, size_t seq_len_arr[], hsize_t dset_offset_arr[], - const void *_buf) +ssize_t +H5F_seq_writevv(H5F_t *f, hid_t dxpl_id, struct H5O_layout_t *layout, + struct H5P_genplist_t *dc_plist, const H5D_storage_t *store, + 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[], + const void *buf) { - const unsigned char *real_buf=(const unsigned char *)_buf; /* Local pointer to buffer to fill */ - const unsigned char *buf; /* Local pointer to buffer to fill */ - hsize_t dset_offset; /* Offset in dataset */ - hsize_t seq_len; /* Number of bytes to read */ - hsize_t dset_dims[H5O_LAYOUT_NDIMS]; /* dataspace dimensions */ - hssize_t mem_offset[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in memory buffer */ - hssize_t coords[H5O_LAYOUT_NDIMS]; /* offset of hyperslab in dataspace */ - hsize_t hslab_size[H5O_LAYOUT_NDIMS]; /* hyperslab size in dataspace*/ - hsize_t down_size[H5O_LAYOUT_NDIMS]; /* Cumulative hyperslab sizes (in elements) */ - hsize_t acc; /* Accumulator for hyperslab sizes (in elements) */ - int ndims; - hsize_t max_data; /*bytes in dataset */ - haddr_t addr; /*address in file */ - unsigned u; /*counters */ - size_t v; /*counters */ - int i,j; /*counters */ #ifdef H5_HAVE_PARALLEL H5FD_mpio_xfer_t xfer_mode=H5FD_MPIO_INDEPENDENT; #endif /* H5_HAVE_PARALLEL */ - herr_t ret_value = SUCCEED; /* Return value */ + ssize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5F_seq_writev, FAIL); + FUNC_ENTER_NOAPI(H5F_seq_writevv, FAIL); /* Check args */ assert(f); + assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); /* Make certain we have the correct type of property list */ assert(layout); - assert(efl); - assert(real_buf); - /* Make certain we have the correct type of property list */ - assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); + assert(dc_plist); + assert(dset_curr_seq); + assert(*dset_curr_seq<dset_max_nseq); + assert(dset_len_arr); + assert(dset_offset_arr); + assert(mem_curr_seq); + assert(*mem_curr_seq<mem_max_nseq); + assert(mem_len_arr); + assert(mem_offset_arr); + assert(buf); #ifdef H5_HAVE_PARALLEL /* Get the transfer mode for MPIO transfers */ @@ -608,282 +385,50 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, switch (layout->type) { case H5D_CONTIGUOUS: /* Write directly to file if the dataset is in an external file */ - if (efl->nused>0) { - /* Iterate through the sequence vectors */ - for(v=0; v<nseq; v++) { -#ifdef H5_HAVE_PARALLEL - if (H5FD_MPIO_COLLECTIVE==xfer_mode) { - /* - * Currently supports same number of collective access. Need to - * be changed LATER to combine all reads into one collective MPIO - * call. - */ - unsigned long max, min, temp; - - temp = seq_len_arr[v]; - assert(temp==seq_len_arr[v]); /* verify no overflow */ - MPI_Allreduce(&temp, &max, 1, MPI_UNSIGNED_LONG, MPI_MAX, - H5FD_mpio_communicator(f->shared->lf)); - MPI_Allreduce(&temp, &min, 1, MPI_UNSIGNED_LONG, MPI_MIN, - H5FD_mpio_communicator(f->shared->lf)); -#ifdef AKC - printf("seq_len=%lu, min=%lu, max=%lu\n", temp, min, max); -#endif - if (max != min) - HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "collective access with unequal number of blocks not supported yet"); - } -#endif /* H5_HAVE_PARALLEL */ - /* Note: We can't use data sieve buffers for datasets in external files - * because the 'addr' of all external files is set to 0 (above) and - * all datasets in external files would alias to the same set of - * file offsets, totally mixing up the data sieve buffer information. -QAK - */ - H5_CHECK_OVERFLOW(dset_offset_arr[v],hsize_t,haddr_t); - if (H5O_efl_write(f, efl, (haddr_t)dset_offset_arr[v], seq_len_arr[v], real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "external data write failed"); - - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ + if (store && store->efl.nused>0) { + /* Note: We can't use data sieve buffers for datasets in external files + * because the 'addr' of all external files is set to 0 (above) and + * all datasets in external files would alias to the same set of + * file offsets, totally mixing up the data sieve buffer information. -QAK + */ + if ((ret_value=H5O_efl_writevv(&(store->efl), + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "external data write failed"); } else { + hsize_t max_data; /* Bytes in dataset */ + unsigned u; /* Local index variable */ + /* Compute the size of the dataset in bytes */ for(u=1, max_data=layout->dim[0]; u<layout->ndims; u++) max_data *= layout->dim[u]; /* Pass along the vector of sequences to write */ - if (H5F_contig_writev(f, max_data, H5FD_MEM_DRAW, layout->addr, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) + if ((ret_value=H5F_contig_writevv(f, max_data, layout->addr, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); } /* end else */ break; case H5D_CHUNKED: - /* - * This method is unable to access external raw data files - */ - if (efl->nused>0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "chunking and external files are mutually exclusive"); - - /* Compute the file offset coordinates and hyperslab size */ - if((ndims=H5S_get_simple_extent_dims(file_space,dset_dims,NULL))<0) - HGOTO_ERROR(H5E_IO, H5E_UNSUPPORTED, FAIL, "unable to retrieve dataspace dimensions"); - - /* Build the array of cumulative hyperslab sizes */ - /* (And set the memory offset to zero) */ - for(acc=1, i=(ndims-1); i>=0; i--) { - mem_offset[i]=0; - down_size[i]=acc; - acc*=dset_dims[i]; - } /* end for */ - mem_offset[ndims]=0; - - /* Brute-force, stupid way to implement the vectors, but too complex to do other ways... */ - for(v=0; v<nseq; v++) { - dset_offset=dset_offset_arr[v]; - seq_len=seq_len_arr[v]; - buf=real_buf; - - { - /* Set location in dataset from the dset_offset */ - addr=dset_offset; - - /* Convert the bytes into elements */ - seq_len/=elmt_size; - addr/=elmt_size; - - /* Compute the hyperslab offset from the address given */ - for(i=ndims-1; i>=0; i--) { - coords[i]=addr%dset_dims[i]; - addr/=dset_dims[i]; - } /* end for */ - coords[ndims]=0; /* No offset for element info */ - - /* - * Peel off initial partial hyperslabs until we've got a hyperslab which starts - * at coord[n]==0 for dimensions 1->(ndims-1) (i.e. starting at coordinate - * zero for all dimensions except the slowest changing one - */ - for(i=ndims-1; i>0 && seq_len>=down_size[i]; i--) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* Check if we have a partial hyperslab in this lower dimension */ - if(coords[i]>0) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(i==j) - hslab_size[j]=MIN(seq_len/down_size[i],dset_dims[i]-coords[i]); - else - if(j>i) - hslab_size[j]=dset_dims[j]; - else - hslab_size[j]=1; - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write out the partial hyperslab */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset,coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Increment the buffer offset */ - buf=(const unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=0; - coords[i-1]++; - - /* Carry the coord array correction up the array, if the dimension is finished */ - while(i>0 && coords[i-1]==(hssize_t)dset_dims[i-1]) { - i--; - coords[i]=0; - if(i>0) { - coords[i-1]++; - assert(coords[i-1]<=(hssize_t)dset_dims[i-1]); - } /* end if */ - } /* end while */ - } /* end if */ - } /* end for */ - - /* Check if there is more than just a partial hyperslab to read */ - if(seq_len>=down_size[0]) { - hsize_t tmp_seq_len; /* Temp. size of the sequence in elements */ - hsize_t full_size; /* Size of the full hyperslab in bytes */ - - /* Get the sequence length for computing the hyperslab sizes */ - tmp_seq_len=seq_len; - - /* Reset the size of the hyperslab read in */ - full_size=1; - - /* Compute the hyperslab size from the length given */ - for(i=ndims-1; i>=0; i--) { - /* Check if the hyperslab is wider than the width of the dimension */ - if(tmp_seq_len>dset_dims[i]) { - assert(0==coords[i]); - hslab_size[i]=dset_dims[i]; - } /* end if */ - else - hslab_size[i]=tmp_seq_len; - - /* compute the number of elements read in */ - full_size*=hslab_size[i]; - - /* Fold the length into the length in the next highest dimension */ - tmp_seq_len/=dset_dims[i]; - - /* Make certain the hyperslab sizes don't go less than 1 for dimensions less than 0*/ - assert(tmp_seq_len>=1 || i==0); - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write the full hyperslab in */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Increment the buffer offset */ - buf=(const unsigned char *)buf+(full_size*elmt_size); - - /* Decrement the sequence length left */ - seq_len-=full_size; - - /* Increment coordinate of slowest changing dimension */ - coords[0]+=hslab_size[0]; - - } /* end if */ - - /* - * Peel off final partial hyperslabs until we've finished reading all the data - */ - if(seq_len>0) { - hsize_t partial_size; /* Size of the partial hyperslab in bytes */ - - /* - * Peel off remaining partial hyperslabs, from the next-slowest dimension - * on down to the next-to-fastest changing dimension - */ - for(i=1; i<(ndims-1); i++) { - /* Check if there are enough elements to read in a row in this dimension */ - if(seq_len>=down_size[i]) { - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j<i) - hslab_size[j]=1; - else - if(j==i) - hslab_size[j]=seq_len/down_size[j]; - else - hslab_size[j]=dset_dims[j]; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write out the partial hyperslab */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Increment the buffer offset */ - buf=(const unsigned char *)buf+(partial_size*elmt_size); - - /* Decrement the length of the sequence to read */ - seq_len-=partial_size; - - /* Correct the coords array */ - coords[i]=hslab_size[i]; - } /* end if */ - } /* end for */ - - /* Handle fastest changing dimension if there are any elements left */ - if(seq_len>0) { - assert(seq_len<dset_dims[ndims-1]); - - /* Reset the partial hyperslab size */ - partial_size=1; - - /* Build the partial hyperslab information */ - for(j=0; j<ndims; j++) { - if(j==(ndims-1)) - hslab_size[j]=seq_len; - else - hslab_size[j]=1; - - partial_size*=hslab_size[j]; - } /* end for */ - hslab_size[ndims]=elmt_size; /* basic hyperslab size is the element */ - - /* Write out the final partial hyperslab */ - if (H5F_istore_write(f, dxpl_id, layout, dc_plist, - hslab_size, mem_offset, coords, hslab_size, buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "chunked write failed"); - - /* Double-check the amount read in */ - assert(seq_len==partial_size); - } /* end if */ - } /* end if */ - } - /* Increment offset in buffer */ - real_buf += seq_len_arr[v]; - } /* end for */ - + assert(store); + if((ret_value=H5F_istore_writevv(f, dxpl_id, layout, dc_plist, store->chunk_coords, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + buf))<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "istore write failed"); break; case H5D_COMPACT: - /* Pass along the vector of sequences to write */ - if (H5F_compact_writev(f, layout, nseq, seq_len_arr, dset_offset_arr, dxpl_id, real_buf)<0) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed"); - + if((ret_value=H5F_compact_writevv(f, layout, + dset_max_nseq, dset_curr_seq, dset_len_arr, dset_offset_arr, + mem_max_nseq, mem_curr_seq, mem_len_arr, mem_offset_arr, + dxpl_id, buf))<0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "compact write failed"); break; default: @@ -893,5 +438,4 @@ H5F_seq_writev(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout, done: FUNC_LEAVE_NOAPI(ret_value); -} /* H5F_seq_writev() */ - +} /* H5F_seq_writevv() */ @@ -560,7 +560,7 @@ H5Gget_objtype_by_idx(hid_t group_id, hsize_t idx) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "index out of bound"); /*call private function*/ - ret_value = (H5G_obj_t)H5G_get_objtype_by_idx(group, idx, H5AC_ind_dxpl_id); + ret_value = H5G_get_objtype_by_idx(group, idx, H5AC_ind_dxpl_id); done: FUNC_LEAVE_API(ret_value); diff --git a/src/H5Oefl.c b/src/H5Oefl.c index 898da7f..3c80f95 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -37,6 +37,10 @@ static size_t H5O_efl_size(H5F_t *f, const void *_mesg); static herr_t H5O_efl_reset(void *_mesg); static herr_t H5O_efl_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); +static herr_t H5O_efl_read (const H5O_efl_t *efl, haddr_t addr, size_t size, + uint8_t *buf); +static herr_t H5O_efl_write(const H5O_efl_t *efl, haddr_t addr, size_t size, + const uint8_t *buf); /* This message derives from H5O */ const H5O_class_t H5O_EFL[1] = {{ @@ -422,9 +426,8 @@ done: * The ADDR argument is passed by value. *------------------------------------------------------------------------- */ -herr_t -H5O_efl_read (H5F_t UNUSED *f, const H5O_efl_t *efl, haddr_t addr, - size_t size, uint8_t *buf) +static herr_t +H5O_efl_read (const H5O_efl_t *efl, haddr_t addr, size_t size, uint8_t *buf) { int i, fd=-1; size_t to_read; @@ -510,9 +513,8 @@ done: * The ADDR argument is passed by value. *------------------------------------------------------------------------- */ -herr_t -H5O_efl_write (H5F_t UNUSED *f, const H5O_efl_t *efl, haddr_t addr, - size_t size, const uint8_t *buf) +static herr_t +H5O_efl_write (const H5O_efl_t *efl, haddr_t addr, size_t size, const uint8_t *buf) { int i, fd=-1; size_t to_write; @@ -582,6 +584,164 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_efl_readvv + * + * Purpose: Reads data from an external file list. It is an error to + * read past the logical end of file, but reading past the end + * of any particular member of the external file list results in + * zeros. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, May 7, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +ssize_t +H5O_efl_readvv(const H5O_efl_t *efl, + 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[], + void *_buf) +{ + unsigned char *buf; /* Pointer to buffer to write */ + haddr_t addr; /* Actual address to read */ + size_t size; /* Size of sequence in bytes */ + size_t u; /* Counting variable */ + size_t v; /* Counting variable */ + ssize_t ret_value=0; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_efl_readvv, FAIL); + + /* Check args */ + assert (efl && efl->nused>0); + assert (buf); + + /* Work through all the sequences */ + 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]; + else + size=dset_len_arr[u]; + + /* Compute offset on disk */ + addr=dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (unsigned char *)_buf + mem_offset_arr[v]; + + /* Read data */ + if (H5O_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) + v++; + + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) + u++; + + /* Increment number of bytes copied */ + ret_value+=size; + } /* end for */ + + /* Update current sequence vectors */ + *dset_curr_seq=u; + *mem_curr_seq=v; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_efl_readvv() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_efl_writevv + * + * Purpose: Writes data to an external file list. It is an error to + * write past the logical end of file, but writing past the end + * of any particular member of the external file list just + * extends that file. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, May 2, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +ssize_t +H5O_efl_writevv(const H5O_efl_t *efl, + 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[], + const void *_buf) +{ + const unsigned char *buf; /* Pointer to buffer to write */ + haddr_t addr; /* Actual address to read */ + size_t size; /* Size of sequence in bytes */ + size_t u; /* Counting variable */ + size_t v; /* Counting variable */ + ssize_t ret_value=0; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_efl_writevv, FAIL); + + /* Check args */ + assert (efl && efl->nused>0); + assert (buf); + + /* Work through all the sequences */ + 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]; + else + size=dset_len_arr[u]; + + /* Compute offset on disk */ + addr=dset_offset_arr[u]; + + /* Compute offset in memory */ + buf = (const unsigned char *)_buf + mem_offset_arr[v]; + + /* Write data */ + if (H5O_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) + v++; + + /* Update file information */ + dset_len_arr[u]-=size; + dset_offset_arr[u]+=size; + if(dset_len_arr[u]==0) + u++; + + /* Increment number of bytes copied */ + ret_value+=size; + } /* end for */ + + /* Update current sequence vectors */ + *dset_curr_seq=u; + *mem_curr_seq=v; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5O_efl_writevv() */ + + +/*------------------------------------------------------------------------- * Function: H5O_efl_debug * * Purpose: Prints debugging info for a message. diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 9b40eeb..6f08ca4 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -239,10 +239,14 @@ H5_DLL size_t H5O_layout_meta_size(H5F_t *f, const void *_mesg); /* EFL operators */ H5_DLL hsize_t H5O_efl_total_size(H5O_efl_t *efl); -H5_DLL herr_t H5O_efl_read(H5F_t *f, const H5O_efl_t *efl, haddr_t addr, - size_t size, uint8_t *buf); -H5_DLL herr_t H5O_efl_write(H5F_t *f, const H5O_efl_t *efl, haddr_t addr, - size_t size, const uint8_t *buf); +H5_DLL ssize_t H5O_efl_readvv(const H5O_efl_t *efl, + 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[], + void *buf); +H5_DLL ssize_t H5O_efl_writevv(const H5O_efl_t *efl, + 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[], + const void *buf); /* Fill value operators */ H5_DLL herr_t H5O_fill_convert(void *_fill, H5T_t *type, hid_t dxpl_id); @@ -56,7 +56,7 @@ H5FL_DEFINE(H5S_simple_t); H5FL_DEFINE(H5S_t); /* Declare a free list to manage the array's of hsize_t's */ -H5FL_ARR_DEFINE(hsize_t,H5S_MAX_RANK); +H5FL_ARR_DEFINE(hsize_t,-1); /* Declare a free list to manage the array's of hssize_t's */ H5FL_ARR_DEFINE(hssize_t,H5S_MAX_RANK); @@ -1548,7 +1548,11 @@ done: *------------------------------------------------------------------------- */ H5S_conv_t * -H5S_find (const H5S_t *mem_space, const H5S_t *file_space, unsigned flags) +H5S_find (const H5S_t *mem_space, const H5S_t *file_space, unsigned +#ifndef H5_HAVE_PARALLEL +UNUSED +#endif /* H5_HAVE_PARALLEL */ +flags) { H5S_conv_t *path=NULL; /* Space conversion path */ #ifdef H5_HAVE_PARALLEL @@ -1780,7 +1784,7 @@ H5Screate_simple(int rank, const hsize_t dims[/*rank*/], } /* Create the space and set the extent */ - if(NULL==(space=H5S_create_simple(rank,dims,maxdims))) + if(NULL==(space=H5S_create_simple((unsigned)rank,dims,maxdims))) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace"); /* Atomize */ @@ -1817,7 +1821,7 @@ done: *------------------------------------------------------------------------- */ H5S_t * -H5S_create_simple(int rank, const hsize_t dims[/*rank*/], +H5S_create_simple(unsigned rank, const hsize_t dims[/*rank*/], const hsize_t maxdims[/*rank*/]) { H5S_t *ret_value; /* Return value */ @@ -1825,12 +1829,12 @@ H5S_create_simple(int rank, const hsize_t dims[/*rank*/], FUNC_ENTER_NOAPI(H5S_create_simple, NULL); /* Check arguments */ - assert(rank>=0 && rank <=H5S_MAX_RANK); + assert(rank <=H5S_MAX_RANK); /* Create the space and set the extent */ if(NULL==(ret_value=H5S_create(H5S_SIMPLE))) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace"); - if(H5S_set_extent_simple(ret_value,(unsigned)rank,dims,maxdims)<0) + if(H5S_set_extent_simple(ret_value,rank,dims,maxdims)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, NULL, "can't set dimensions"); done: diff --git a/src/H5Sall.c b/src/H5Sall.c index f5b92b7..08dc8d3 100644 --- a/src/H5Sall.c +++ b/src/H5Sall.c @@ -21,11 +21,11 @@ #define H5S_PACKAGE /*suppress error about including H5Spkg */ -#include "H5private.h" /* Generic Functions */ -#include "H5Eprivate.h" /* Error handling */ -#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 "H5Iprivate.h" /* ID Functions */ +#include "H5Spkg.h" /* Dataspace functions */ +#include "H5Vprivate.h" /* Vector functions */ /* Interface initialization */ #define PABLO_MASK H5Sall_mask @@ -48,7 +48,7 @@ static int interface_initialize_g = 0; *------------------------------------------------------------------------- */ herr_t -H5S_all_iter_init (const H5S_t *space, size_t UNUSED elmt_size, H5S_sel_iter_t *sel_iter) +H5S_all_iter_init (H5S_sel_iter_t *iter, const H5S_t *space, size_t UNUSED elmt_size) { herr_t ret_value=SUCCEED; /* Return value */ @@ -56,13 +56,19 @@ H5S_all_iter_init (const H5S_t *space, size_t UNUSED elmt_size, H5S_sel_iter_t * /* Check args */ assert (space && H5S_SEL_ALL==space->select.type); - assert (sel_iter); + assert (iter); /* Initialize the number of elements to iterate over */ - sel_iter->all.elmt_left=H5S_get_simple_extent_npoints(space); + iter->elmt_left=H5S_get_simple_extent_npoints(space); /* Start at the upper left location */ - sel_iter->all.offset=0; + iter->u.all.offset=0; + + /* Initialize methods for selection iterator */ + iter->iter_coords=H5S_all_iter_coords; + iter->iter_nelmts=H5S_all_iter_nelmts; + iter->iter_next=H5S_all_iter_next; + iter->iter_release=H5S_all_iter_release; done: FUNC_LEAVE_NOAPI(ret_value); @@ -70,6 +76,41 @@ done: /*------------------------------------------------------------------------- + * Function: H5S_all_iter_coords + * + * Purpose: Retrieve the current coordinates of iterator for current + * selection + * + * Return: non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, April 22, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_all_iter_coords (const H5S_sel_iter_t *iter, hssize_t *coords) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_all_iter_coords, FAIL); + + /* Check args */ + assert (iter); + assert (coords); + + /* Calculate the coordinates for the current iterator offset */ + if(H5V_array_calc(iter->u.all.offset,iter->rank,iter->dims,coords)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve coordinates"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_all_iter_coords() */ + + +/*------------------------------------------------------------------------- * Function: H5S_all_iter_nelmts * * Purpose: Return number of elements left to process in iterator @@ -84,17 +125,17 @@ done: *------------------------------------------------------------------------- */ hsize_t -H5S_all_iter_nelmts (const H5S_sel_iter_t *sel_iter) +H5S_all_iter_nelmts (const H5S_sel_iter_t *iter) { hsize_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5S_all_iter_nelmts, 0); /* Check args */ - assert (sel_iter); + assert (iter); /* Set return value */ - ret_value=sel_iter->all.elmt_left; + ret_value=iter->elmt_left; done: FUNC_LEAVE_NOAPI(ret_value); @@ -103,12 +144,49 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_all_iter_next + PURPOSE + Increment selection iterator + USAGE + herr_t H5S_all_iter_next(iter, nelem) + H5S_sel_iter_t *iter; IN: Pointer to selection iterator + size_t nelem; IN: Number of elements to advance by + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Advance selection iterator to the NELEM'th next element in the selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_all_iter_next(H5S_sel_iter_t *iter, size_t nelem) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_all_iter_next, FAIL); + + /* Check args */ + assert (iter); + assert (nelem>0); + + /* Increment the iterator */ + iter->u.all.offset+=nelem; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_all_iter_next() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_all_iter_release PURPOSE Release "all" selection iterator information for a dataspace USAGE - herr_t H5S_all_iter_release(sel_iter) - H5S_sel_iter_t *sel_iter; IN: Pointer to selection iterator + herr_t H5S_all_iter_release(iter) + H5S_sel_iter_t *iter; IN: Pointer to selection iterator RETURNS Non-negative on success/Negative on failure DESCRIPTION @@ -119,14 +197,14 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_all_iter_release (H5S_sel_iter_t UNUSED * sel_iter) +H5S_all_iter_release (H5S_sel_iter_t UNUSED * iter) { herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5S_all_iter_release, FAIL); /* Check args */ - assert (sel_iter); + assert (iter); done: FUNC_LEAVE_NOAPI(ret_value); @@ -542,9 +620,6 @@ H5S_select_all (H5S_t *space, unsigned rel_prev) space->select.get_seq_list=H5S_all_get_seq_list; space->select.get_npoints=H5S_all_npoints; space->select.release=H5S_all_release; - space->select.iter_init=H5S_all_iter_init; - space->select.iter_nelmts=H5S_all_iter_nelmts; - space->select.iter_release=H5S_all_iter_release; space->select.is_valid=H5S_all_is_valid; space->select.serial_size=H5S_all_serial_size; space->select.serialize=H5S_all_serialize; @@ -552,6 +627,7 @@ H5S_select_all (H5S_t *space, unsigned rel_prev) space->select.is_contiguous=H5S_all_is_contiguous; space->select.is_single=H5S_all_is_single; space->select.is_regular=H5S_all_is_regular; + space->select.iter_init=H5S_all_iter_init; done: FUNC_LEAVE_NOAPI(ret_value); @@ -650,13 +726,13 @@ H5S_all_get_seq_list(const H5S_t UNUSED *space, unsigned UNUSED flags, H5S_sel_i assert(len); /* Calculate the number of bytes left in the selection */ - bytes_left=iter->all.elmt_left*elem_size; + bytes_left=iter->elmt_left*elem_size; /* "round" off the maxbytes allowed to a multiple of the element size */ maxbytes=(maxbytes/elem_size)*elem_size; /* Compute the offset in the dataset */ - off[0]=iter->all.offset*elem_size; + off[0]=iter->u.all.offset*elem_size; H5_CHECK_OVERFLOW(bytes_left,hsize_t,size_t); len[0]=MIN(maxbytes,(size_t)bytes_left); @@ -668,8 +744,8 @@ H5S_all_get_seq_list(const H5S_t UNUSED *space, unsigned UNUSED flags, H5S_sel_i /* Update the iterator */ elem_used=len[0]/elem_size; - iter->all.elmt_left-=elem_used; - iter->all.offset+=elem_used; + iter->elmt_left-=elem_used; + iter->u.all.offset+=elem_used; done: FUNC_LEAVE_NOAPI(ret_value); diff --git a/src/H5Shyper.c b/src/H5Shyper.c index 17ea8d3..2fe79aa 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -55,11 +55,12 @@ H5FL_DEFINE_STATIC(H5S_hyper_span_info_t); H5FL_ARR_EXTERN(hssize_t); /* Declare a free list to manage arrays of hsize_t */ -H5FL_ARR_DEFINE_STATIC(hsize_t,-1); +H5FL_ARR_EXTERN(hsize_t); /* Declare a free list to manage arrays of H5S_hyper_dim_t */ H5FL_ARR_DEFINE_STATIC(H5S_hyper_dim_t,H5S_MAX_RANK); +/* #define H5S_HYPER_DEBUG */ #ifdef H5S_HYPER_DEBUG static herr_t H5S_hyper_print_spans_helper(struct H5S_hyper_span_t *span,unsigned depth) @@ -70,9 +71,9 @@ H5S_hyper_print_spans_helper(struct H5S_hyper_span_t *span,unsigned depth) tmp_span=span; while(tmp_span) { - printf("%s: depth=%u, span=%p, (%d, %d), nelem=%u, pstride=%u\n",FUNC,depth,tmp_span,(int)tmp_span->low,(int)tmp_span->high,(unsigned)tmp_span->nelem,(unsigned)tmp_span->pstride); + HDfprintf(stderr,"%s: depth=%u, span=%p, (%d, %d), nelem=%u, pstride=%u\n",FUNC,depth,tmp_span,(int)tmp_span->low,(int)tmp_span->high,(unsigned)tmp_span->nelem,(unsigned)tmp_span->pstride); if(tmp_span->down && tmp_span->down->head) { - printf("%s: spans=%p, count=%u, scratch=%p, head=%p\n",FUNC,tmp_span->down,tmp_span->down->count,tmp_span->down->scratch,tmp_span->down->head); + HDfprintf(stderr,"%s: spans=%p, count=%u, scratch=%p, head=%p\n",FUNC,tmp_span->down,tmp_span->down->count,tmp_span->down->scratch,tmp_span->down->head); H5S_hyper_print_spans_helper(tmp_span->down->head,depth+1); } /* end if */ tmp_span=tmp_span->next; @@ -87,7 +88,7 @@ H5S_hyper_print_spans(const struct H5S_hyper_span_info_t *span_lst) FUNC_ENTER_NOINIT(H5S_hyper_print_spans); if(span_lst!=NULL) { - printf("%s: spans=%p, count=%u, scratch=%p, head=%p\n",FUNC,span_lst,span_lst->count,span_lst->scratch,span_lst->head); + HDfprintf(stderr,"%s: spans=%p, count=%u, scratch=%p, head=%p\n",FUNC,span_lst,span_lst->count,span_lst->scratch,span_lst->head); H5S_hyper_print_spans_helper(span_lst->head,0); } /* end if */ @@ -111,11 +112,11 @@ H5S_hyper_print_spans(const struct H5S_hyper_span_info_t *span_lst) *------------------------------------------------------------------------- */ herr_t -H5S_hyper_iter_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_iter) +H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size) { - unsigned cont_dim; /* Maximum contiguous dimension */ const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */ H5S_hyper_span_info_t *spans; /* Pointer to hyperslab span info node */ + unsigned rank; /* Dataspace's dimension rank */ unsigned u; /* Index variable */ int i; /* Index variable */ herr_t ret_value=SUCCEED; /* Return value */ @@ -124,12 +125,15 @@ H5S_hyper_iter_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_i /* Check args */ assert(space && H5S_SEL_HYPERSLABS==space->select.type); - assert(sel_iter); + assert(iter); assert(space->select.sel_info.hslab.span_lst); /* Initialize the number of points to iterate over */ - sel_iter->hyp.elmt_left=space->select.num_elem; - sel_iter->hyp.iter_rank=0; + iter->elmt_left=space->select.num_elem; + iter->u.hyp.iter_rank=0; + + /* Get the rank of the dataspace */ + rank=space->extent.u.simple.rank; /* Set the temporary pointer to the dimension information */ tdiminfo=space->select.sel_info.hslab.diminfo; @@ -139,6 +143,7 @@ H5S_hyper_iter_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_i /* Initialize the information needed for regular hyperslab I/O */ const hsize_t *mem_size; /* Temporary pointer to dataspace extent's dimension sizes */ hsize_t acc; /* Accumulator for "flattened" dimension's sizes */ + unsigned cont_dim; /* Maximum contiguous dimension */ /* Set the temporary pointer to the dataspace extent's dimension sizes */ mem_size=space->extent.u.simple.size; @@ -151,10 +156,10 @@ H5S_hyper_iter_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_i */ /* Initialize the number of contiguous dimensions to be the same as the dataspace's rank */ - cont_dim=space->extent.u.simple.rank; + cont_dim=rank; /* Check for a "contiguous" block */ - for(u=space->extent.u.simple.rank-1; u>0; u--) { + for(u=rank-1; u>0; u--) { if(tdiminfo[u].count==1 && tdiminfo[u].block==mem_size[u]) cont_dim=u; else @@ -162,114 +167,189 @@ H5S_hyper_iter_init (const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_i } /* end for */ /* Check if the regular selection can be "flattened" */ - if(cont_dim<space->extent.u.simple.rank) { + if(cont_dim<rank) { /* Set the iterator's rank to the contiguous dimensions */ - sel_iter->hyp.iter_rank=cont_dim; + iter->u.hyp.iter_rank=cont_dim; /* Allocate the position & initialize to initial location */ - sel_iter->hyp.off = H5FL_ARR_MALLOC(hsize_t,cont_dim); - assert(sel_iter->hyp.off); - sel_iter->hyp.diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,cont_dim); - assert(sel_iter->hyp.diminfo); - sel_iter->hyp.size = H5FL_ARR_MALLOC(hsize_t,cont_dim); - assert(sel_iter->hyp.size); - sel_iter->hyp.sel_off = H5FL_ARR_MALLOC(hssize_t,cont_dim); - assert(sel_iter->hyp.sel_off); + iter->u.hyp.off = H5FL_ARR_MALLOC(hsize_t,cont_dim); + assert(iter->u.hyp.off); + iter->u.hyp.diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,cont_dim); + assert(iter->u.hyp.diminfo); + iter->u.hyp.size = H5FL_ARR_MALLOC(hsize_t,cont_dim); + assert(iter->u.hyp.size); + iter->u.hyp.sel_off = H5FL_ARR_MALLOC(hssize_t,cont_dim); + assert(iter->u.hyp.sel_off); /* "Flatten" dataspace extent and selection information */ - for(i=space->extent.u.simple.rank-1, acc=1; i>=0; i--) { + for(i=rank-1, acc=1; i>=0; i--) { if(tdiminfo[i].block==mem_size[i] && i>0) { assert(tdiminfo[i].start==0); acc *= mem_size[i]; } /* end if */ else { if((unsigned)i==(cont_dim-1)) { - sel_iter->hyp.diminfo[i].start = tdiminfo[i].start*acc; + iter->u.hyp.diminfo[i].start = tdiminfo[i].start*acc; /* Special case for stride==1 regular selections */ if(tdiminfo[i].stride==1) - sel_iter->hyp.diminfo[i].stride = 1; + iter->u.hyp.diminfo[i].stride = 1; else - sel_iter->hyp.diminfo[i].stride = tdiminfo[i].stride*acc; - sel_iter->hyp.diminfo[i].count = tdiminfo[i].count; - sel_iter->hyp.diminfo[i].block = tdiminfo[i].block*acc; - sel_iter->hyp.size[i] = mem_size[i]*acc; - sel_iter->hyp.sel_off[i] = space->select.offset[i]*acc; + iter->u.hyp.diminfo[i].stride = tdiminfo[i].stride*acc; + iter->u.hyp.diminfo[i].count = tdiminfo[i].count; + iter->u.hyp.diminfo[i].block = tdiminfo[i].block*acc; + iter->u.hyp.size[i] = mem_size[i]*acc; + iter->u.hyp.sel_off[i] = space->select.offset[i]*acc; } /* end if */ else { - sel_iter->hyp.diminfo[i].start = tdiminfo[i].start; - sel_iter->hyp.diminfo[i].stride = tdiminfo[i].stride; - sel_iter->hyp.diminfo[i].count = tdiminfo[i].count; - sel_iter->hyp.diminfo[i].block = tdiminfo[i].block; - sel_iter->hyp.size[i] = mem_size[i]; - sel_iter->hyp.sel_off[i] = space->select.offset[i]; + iter->u.hyp.diminfo[i].start = tdiminfo[i].start; + iter->u.hyp.diminfo[i].stride = tdiminfo[i].stride; + iter->u.hyp.diminfo[i].count = tdiminfo[i].count; + iter->u.hyp.diminfo[i].block = tdiminfo[i].block; + iter->u.hyp.size[i] = mem_size[i]; + iter->u.hyp.sel_off[i] = space->select.offset[i]; } /* end else */ } /* end if */ } /* end for */ /* Initialize "flattened" iterator offset to initial location and dataspace extent and selection information to correct values */ for(u=0; u<cont_dim; u++) - sel_iter->hyp.off[u]=sel_iter->hyp.diminfo[u].start; + iter->u.hyp.off[u]=iter->u.hyp.diminfo[u].start; } /* end if */ else { /* Allocate the position & initialize to initial location */ - sel_iter->hyp.off = H5FL_ARR_MALLOC(hsize_t,space->extent.u.simple.rank); - assert(sel_iter->hyp.off); - for(u=0; u<space->extent.u.simple.rank; u++) - sel_iter->hyp.off[u]=tdiminfo[u].start; + iter->u.hyp.off = H5FL_ARR_MALLOC(hsize_t,rank); + assert(iter->u.hyp.off); + + /* Allocate the storage for the regular selection information */ + iter->u.hyp.diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,rank); + assert(iter->u.hyp.diminfo); + + /* Initialize position to initial location */ + /* Also make local copy of the regular selection information */ + for(u=0; u<rank; u++) { + /* Regular selection information */ + iter->u.hyp.diminfo[u].start = tdiminfo[u].start; + iter->u.hyp.diminfo[u].stride = tdiminfo[u].stride; + iter->u.hyp.diminfo[u].count = tdiminfo[u].count; + iter->u.hyp.diminfo[u].block = tdiminfo[u].block; + + /* Position information */ + iter->u.hyp.off[u]=tdiminfo[u].start; + } /* end if */ /* Initialize other regular region information also (for release) */ - sel_iter->hyp.diminfo = NULL; - sel_iter->hyp.size = NULL; - sel_iter->hyp.sel_off = NULL; + iter->u.hyp.size = NULL; + iter->u.hyp.sel_off = NULL; } /* end else */ /* Initialize irregular region information also (for release) */ - sel_iter->hyp.spans=NULL; - sel_iter->hyp.span=NULL; + iter->u.hyp.spans=NULL; + iter->u.hyp.span=NULL; } /* end if */ else { /* Initialize the information needed for non-regular hyperslab I/O */ /* Make a copy of the span tree to iterate over */ - sel_iter->hyp.spans=H5S_hyper_copy_span(space->select.sel_info.hslab.span_lst); + iter->u.hyp.spans=H5S_hyper_copy_span(space->select.sel_info.hslab.span_lst); /* Set the nelem & pstride values according to the element size */ - H5S_hyper_span_precompute(sel_iter->hyp.spans,elmt_size); + H5S_hyper_span_precompute(iter->u.hyp.spans,elmt_size); /* Allocate the span tree pointers, span pointers and positions */ - sel_iter->hyp.span = H5FL_ARR_MALLOC(H5S_hyper_span_t,space->extent.u.simple.rank); - assert(sel_iter->hyp.span); - sel_iter->hyp.off = H5FL_ARR_MALLOC(hsize_t,space->extent.u.simple.rank); - assert(sel_iter->hyp.off); + iter->u.hyp.span = H5FL_ARR_MALLOC(H5S_hyper_span_t,rank); + assert(iter->u.hyp.span); + iter->u.hyp.off = H5FL_ARR_MALLOC(hsize_t,rank); + assert(iter->u.hyp.off); /* Initialize the starting span_info's and spans */ - spans=sel_iter->hyp.spans; - for(u=0; u<space->extent.u.simple.rank; u++) { + spans=iter->u.hyp.spans; + for(u=0; u<rank; u++) { /* Set the pointers to the initial span in each dimension */ assert(spans); assert(spans->head); /* Set the pointer to the first span in the list for this node */ - sel_iter->hyp.span[u] = spans->head; + iter->u.hyp.span[u] = spans->head; /* Set the initial offset to low bound of span */ - sel_iter->hyp.off[u]=sel_iter->hyp.span[u]->low; + iter->u.hyp.off[u]=iter->u.hyp.span[u]->low; /* Get the pointer to the next level down */ spans=spans->head->down; } /* end for */ /* Initialize regular region information also (for release) */ - sel_iter->hyp.diminfo = NULL; - sel_iter->hyp.size = NULL; - sel_iter->hyp.sel_off = NULL; + iter->u.hyp.diminfo = NULL; + iter->u.hyp.size = NULL; + iter->u.hyp.sel_off = NULL; } /* end else */ + /* Initialize methods for selection iterator */ + iter->iter_coords=H5S_hyper_iter_coords; + iter->iter_nelmts=H5S_hyper_iter_nelmts; + iter->iter_next=H5S_hyper_iter_next; + iter->iter_release=H5S_hyper_iter_release; + done: FUNC_LEAVE_NOAPI(ret_value); } /* H5S_hyper_iter_init() */ /*------------------------------------------------------------------------- + * Function: H5S_hyper_iter_coords + * + * Purpose: Retrieve the current coordinates of iterator for current + * selection + * + * Return: non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, April 22, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_hyper_iter_coords (const H5S_sel_iter_t *iter, hssize_t *coords) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_hyper_iter_coords, FAIL); + + /* Check args */ + assert (iter); + assert (coords); + + /* Copy the offset of the current point */ + + /* Check for a single "regular" hyperslab */ + if(iter->u.hyp.diminfo!=NULL) { + /* 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 */ + + /* Get the rank of the flattened dimension */ + flat_dim=iter->u.hyp.iter_rank-1; + + /* Copy the coordinates up to where things got flattened */ + HDmemcpy(coords,iter->u.hyp.off,sizeof(hssize_t)*flat_dim); + + /* Compute the coordinates for the flattened dimensions */ + H5_CHECK_OVERFLOW(iter->u.hyp.off[flat_dim],hssize_t,hsize_t); + H5V_array_calc((hsize_t)iter->u.hyp.off[flat_dim],iter->rank-flat_dim,&(iter->dims[flat_dim]),&(coords[flat_dim])); + } /* end if */ + else + HDmemcpy(coords,iter->u.hyp.off,sizeof(hssize_t)*iter->rank); + } /* end if */ + else + HDmemcpy(coords,iter->u.hyp.off,sizeof(hssize_t)*iter->rank); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_iter_coords() */ + + +/*------------------------------------------------------------------------- * Function: H5S_hyper_iter_nelmts * * Purpose: Return number of elements left to process in iterator @@ -284,31 +364,248 @@ done: *------------------------------------------------------------------------- */ hsize_t -H5S_hyper_iter_nelmts (const H5S_sel_iter_t *sel_iter) +H5S_hyper_iter_nelmts (const H5S_sel_iter_t *iter) { hsize_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5S_hyper_iter_nelmts, 0); /* Check args */ - assert (sel_iter); + assert (iter); /* Set return value */ - ret_value=sel_iter->hyp.elmt_left; + ret_value=iter->elmt_left; done: FUNC_LEAVE_NOAPI(ret_value); } /* H5S_hyper_iter_nelmts() */ +/*------------------------------------------------------------------------- + * Function: H5S_hyper_iter_next + * + * Purpose: Moves a hyperslab iterator to the beginning of the next sequence + * of elements to read. Handles walking off the end in all dimensions. + * + * Return: Success: non-negative + * Failure: negative + * + * Programmer: Quincey Koziol + * Friday, September 8, 2000 + * + * Modifications: + * Modified for both general and optimized hyperslab I/O + * Quincey Koziol, April 17, 2003 + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem) +{ + unsigned ndims; /* Number of dimensions of dataset */ + int fast_dim; /* Rank of the fastest changing dimension for the dataspace */ + unsigned i; /* Counters */ + + FUNC_ENTER_NOINIT(H5S_hyper_iter_next); + + /* Check for the special case of just one H5Sselect_hyperslab call made */ + /* (i.e. a regular hyperslab selection */ + if(iter->u.hyp.diminfo!=NULL) { + const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */ + hsize_t iter_offset[H5O_LAYOUT_NDIMS]; + hsize_t iter_count[H5O_LAYOUT_NDIMS]; + int temp_dim; /* Temporary rank holder */ + + /* Check if this is a "flattened" regular hyperslab selection */ + if(iter->u.hyp.iter_rank!=0 && iter->u.hyp.iter_rank<iter->rank) { + /* Set the aliases for the dimension rank */ + ndims=iter->u.hyp.iter_rank; + } /* end if */ + else { + /* Set the aliases for the dimension rank */ + ndims=iter->rank; + } /* end else */ + + /* Set the fastest dimension rank */ + fast_dim=ndims-1; + + /* Set the local copy of the diminfo pointer */ + tdiminfo=iter->u.hyp.diminfo; + + /* Calculate the offset and block count for each dimension */ + for(i=0; i<ndims; i++) { + if(tdiminfo[i].stride==1) { + iter_offset[i]=iter->u.hyp.off[i]-tdiminfo[i].start; + iter_count[i]=0; + } /* end if */ + else { + iter_offset[i]=(iter->u.hyp.off[i]-tdiminfo[i].start)%tdiminfo[i].stride; + iter_count[i]=(iter->u.hyp.off[i]-tdiminfo[i].start)/tdiminfo[i].stride; + } /* end else */ + } /* end for */ + + /* Loop through, advancing the offset & counts, until all the nelements are accounted for */ + while(nelem>0) { + /* Start with the fastest changing dimension */ + temp_dim=fast_dim; + while(temp_dim>=0) { + if(temp_dim==fast_dim) { + size_t actual_elem; /* Actual # of elements advanced on each iteration through loop */ + size_t block_elem; /* Number of elements left in a block */ + + /* Compute the number of elements left in block */ + block_elem=tdiminfo[temp_dim].block-iter_offset[temp_dim]; + + /* Compute the number of actual elements to advance */ + actual_elem=MIN(nelem,block_elem); + + /* Move the iterator over as many elements as possible */ + iter_offset[temp_dim]+=actual_elem; + + /* Decrement the number of elements advanced */ + nelem-=actual_elem; + } /* end if */ + else { + /* Move to the next row in the current dimension */ + iter_offset[temp_dim]++; + } /* end else */ + + /* If this block is still in the range of blocks to output for the dimension, break out of loop */ + if(iter_offset[temp_dim]<tdiminfo[temp_dim].block) + break; + else { + /* Move to the next block in the current dimension */ + iter_offset[temp_dim]=0; + iter_count[temp_dim]++; + + /* If this block is still in the range of blocks to output for the dimension, break out of loop */ + if(iter_count[temp_dim]<tdiminfo[temp_dim].count) + break; + else + iter_count[temp_dim]=0; /* reset back to the beginning of the line */ + } /* end else */ + + /* Decrement dimension count */ + temp_dim--; + } /* end while */ + } /* end while */ + + /* Translate current iter_offset and iter_count into iterator position */ + for(i=0; i<ndims; i++) + iter->u.hyp.off[i]=tdiminfo[i].start+(tdiminfo[i].stride*iter_count[i])+iter_offset[i]; + } /* end if */ + /* Must be an irregular hyperslab selection */ + else { + H5S_hyper_span_t *curr_span; /* Current hyperslab span node */ + H5S_hyper_span_t **ispan; /* Iterator's hyperslab span nodes */ + hssize_t *abs_arr; /* Absolute hyperslab span position */ + int curr_dim; /* Temporary rank holder */ + + /* Set the rank of the fastest changing dimension */ + ndims=iter->rank; + fast_dim=(ndims-1); + + /* Get the pointers to the current span info and span nodes */ + abs_arr=iter->u.hyp.off; + ispan=iter->u.hyp.span; + + /* Loop through, advancing the span information, until all the nelements are accounted for */ + while(nelem>0) { + /* Start at the fastest dim */ + curr_dim=fast_dim; + + /* Work back up through the dimensions */ + while(curr_dim>=0) { + /* Reset the current span */ + curr_span=ispan[curr_dim]; + + /* Increment absolute position */ + if(curr_dim==fast_dim) { + size_t actual_elem; /* Actual # of elements advanced on each iteration through loop */ + size_t span_elem; /* Number of elements left in a span */ + + /* Compute the number of elements left in block */ + span_elem=(curr_span->high-abs_arr[curr_dim])+1; + + /* Compute the number of actual elements to advance */ + actual_elem=MIN(nelem,span_elem); + + /* Move the iterator over as many elements as possible */ + abs_arr[curr_dim]+=actual_elem; + + /* Decrement the number of elements advanced */ + nelem-=actual_elem; + } /* end if */ + else { + /* Move to the next row in the current dimension */ + abs_arr[curr_dim]++; + } /* end else */ + + /* Check if we are still within the span */ + if(abs_arr[curr_dim]<=curr_span->high) { + break; + } /* end if */ + /* If we walked off that span, advance to the next span */ + else { + /* Advance span in this dimension */ + curr_span=curr_span->next; + + /* Check if we have a valid span in this dimension still */ + if(curr_span!=NULL) { + /* Reset the span in the current dimension */ + ispan[curr_dim]=curr_span; + + /* Reset absolute position */ + abs_arr[curr_dim]=curr_span->low; + + break; + } /* end if */ + else { + /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */ + curr_dim--; + } /* end else */ + } /* end else */ + } /* end while */ + + /* Check if we are finished with the spans in the tree */ + if(curr_dim>=0) { + /* Walk back down the iterator positions, reseting them */ + while(curr_dim<fast_dim) { + assert(curr_span); + assert(curr_span->down); + assert(curr_span->down->head); + + /* Increment current dimension */ + curr_dim++; + + /* Set the new span_info & span for this dimension */ + ispan[curr_dim]=curr_span->down->head; + + /* Advance span down the tree */ + curr_span=curr_span->down->head; + + /* Reset the absolute offset for the dim */ + abs_arr[curr_dim]=curr_span->low; + } /* end while */ + + /* Verify that the curr_span points to the fastest dim */ + assert(curr_span==ispan[fast_dim]); + } /* end if */ + } /* end while */ + } /* end else */ + + FUNC_LEAVE_NOAPI(SUCCEED); +} /* H5S_hyper_iter_next() */ + + /*-------------------------------------------------------------------------- NAME H5S_hyper_iter_release PURPOSE Release hyperslab selection iterator information for a dataspace USAGE - herr_t H5S_hyper_iter_release(sel_iter) - H5S_sel_iter_t *sel_iter; IN: Pointer to selection iterator + herr_t H5S_hyper_iter_release(iter) + H5S_sel_iter_t *iter; IN: Pointer to selection iterator RETURNS Non-negative on success/Negative on failure DESCRIPTION @@ -319,154 +616,46 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_hyper_iter_release (H5S_sel_iter_t *sel_iter) +H5S_hyper_iter_release (H5S_sel_iter_t *iter) { herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5S_hyper_iter_release, FAIL); /* Check args */ - assert (sel_iter); + assert (iter); /* Release the common array of offsets/positions */ - if(sel_iter->hyp.off!=NULL) - H5FL_ARR_FREE(hsize_t,sel_iter->hyp.off); + if(iter->u.hyp.off!=NULL) + H5FL_ARR_FREE(hsize_t,iter->u.hyp.off); /* Release the information needed for "flattened" regular hyperslab I/O */ /* Free the "flattened" dataspace extent */ - if(sel_iter->hyp.size!=NULL) - H5FL_ARR_FREE(hsize_t,sel_iter->hyp.size); + if(iter->u.hyp.size!=NULL) + H5FL_ARR_FREE(hsize_t,iter->u.hyp.size); /* Free the "flattened" regular hyperslab selection */ - if(sel_iter->hyp.diminfo!=NULL) - H5FL_ARR_FREE(H5S_hyper_dim_t,sel_iter->hyp.diminfo); + if(iter->u.hyp.diminfo!=NULL) + H5FL_ARR_FREE(H5S_hyper_dim_t,iter->u.hyp.diminfo); /* Free the "flattened" selection offset */ - if(sel_iter->hyp.sel_off!=NULL) - H5FL_ARR_FREE(hssize_t,sel_iter->hyp.sel_off); + if(iter->u.hyp.sel_off!=NULL) + H5FL_ARR_FREE(hssize_t,iter->u.hyp.sel_off); /* Release the information needed for non-regular hyperslab I/O */ /* Free the copy of the selections span tree */ - if(sel_iter->hyp.spans!=NULL) - H5S_hyper_free_span_info(sel_iter->hyp.spans); + if(iter->u.hyp.spans!=NULL) + H5S_hyper_free_span_info(iter->u.hyp.spans); /* Release the array of pointers to span nodes */ - if(sel_iter->hyp.span!=NULL) - H5FL_ARR_FREE(H5S_hyper_span_t,sel_iter->hyp.span); + if(iter->u.hyp.span!=NULL) + H5FL_ARR_FREE(H5S_hyper_span_t,iter->u.hyp.span); done: FUNC_LEAVE_NOAPI(ret_value); } /* H5S_hyper_iter_release() */ -/*------------------------------------------------------------------------- - * Function: H5S_hyper_iter_next - * - * Purpose: Moves a hyperslab iterator to the beginning of the next sequence - * of elements to read. Handles walking off the end in all dimensions. - * - * Return: Success: non-negative - * Failure: negative - * - * Programmer: Quincey Koziol - * Friday, September 8, 2000 - * - * Notes: - * Only used for the optimized hyperslab I/O routines - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static int -H5S_hyper_iter_next (const H5S_t *space, H5S_sel_iter_t *iter) -{ - const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */ - hsize_t iter_offset[H5O_LAYOUT_NDIMS]; - hsize_t iter_count[H5O_LAYOUT_NDIMS]; - int fast_dim; /* Rank of the fastest changing dimension for the dataspace */ - int temp_dim; /* Temporary rank holder */ - unsigned i; /* Counters */ - unsigned ndims; /* Number of dimensions of dataset */ - - FUNC_ENTER_NOINIT(H5S_hyper_iter_next); - - /* Check if this is a "flattened" regular hyperslab selection */ - if(iter->hyp.iter_rank!=0 && iter->hyp.iter_rank<space->extent.u.simple.rank) { - /* Set the aliases for a few important dimension ranks */ - ndims=iter->hyp.iter_rank; - fast_dim=ndims-1; - - /* Set the local copy of the diminfo pointer */ - tdiminfo=iter->hyp.diminfo; - } /* end if */ - else { - /* Set the aliases for a few important dimension ranks */ - ndims=space->extent.u.simple.rank; - fast_dim=ndims-1; - - /* Set the local copy of the diminfo pointer */ - tdiminfo=space->select.sel_info.hslab.diminfo; - } /* end else */ - - /* Calculate the offset and block count for each dimension */ - for(i=0; i<ndims; i++) { - if(tdiminfo[i].stride==1) { - iter_offset[i]=iter->hyp.off[i]-tdiminfo[i].start; - iter_count[i]=0; - } /* end if */ - else { - iter_offset[i]=(iter->hyp.off[i]-tdiminfo[i].start)%tdiminfo[i].stride; - iter_count[i]=(iter->hyp.off[i]-tdiminfo[i].start)/tdiminfo[i].stride; - } /* end else */ - } /* end for */ - - /* Start with the fastest changing dimension */ - temp_dim=fast_dim; - while(temp_dim>=0) { - if(temp_dim==fast_dim) { - /* Move to the next block in the current dimension */ - iter_offset[temp_dim]=0; /* reset the offset in the fastest dimension */ - iter_count[temp_dim]++; - - /* If this block is still in the range of blocks to output for the dimension, break out of loop */ - if(iter_count[temp_dim]<tdiminfo[temp_dim].count) - break; - else - iter_count[temp_dim]=0; /* reset back to the beginning of the line */ - } /* end if */ - else { - /* Move to the next row in the curent dimension */ - iter_offset[temp_dim]++; - - /* If this block is still in the range of blocks to output for the dimension, break out of loop */ - if(iter_offset[temp_dim]<tdiminfo[temp_dim].block) - break; - else { - /* Move to the next block in the current dimension */ - iter_offset[temp_dim]=0; - iter_count[temp_dim]++; - - /* If this block is still in the range of blocks to output for the dimension, break out of loop */ - if(iter_count[temp_dim]<tdiminfo[temp_dim].count) - break; - else - iter_count[temp_dim]=0; /* reset back to the beginning of the line */ - } /* end else */ - } /* end else */ - - /* Decrement dimension count */ - temp_dim--; - } /* end while */ - - /* Translate current iter_offset and iter_count into iterator position */ - for(i=0; i<ndims; i++) - iter->hyp.off[i]=tdiminfo[i].start+(tdiminfo[i].stride*iter_count[i])+iter_offset[i]; - - FUNC_LEAVE_NOAPI(SUCCEED); -} /* H5S_hyper_iter_next() */ - - /*-------------------------------------------------------------------------- NAME H5S_hyper_npoints @@ -2592,6 +2781,395 @@ H5S_hyper_recover_span (unsigned *recover, H5S_hyper_span_t **curr_span, H5S_hyp /*-------------------------------------------------------------------------- NAME + H5S_hyper_coord_to_span + PURPOSE + Create a span tree for a single element + USAGE + H5S_hyper_span_t *H5S_hyper_coord_to_span(rank, coords) + unsigned rank; IN: Number of dimensions of coordinate + hssize_t *coords; IN: Location of element + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Create a span tree for a single element + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static H5S_hyper_span_t * +H5S_hyper_coord_to_span(unsigned rank, hssize_t *coords) +{ + H5S_hyper_span_t *new_span; /* Pointer to new span tree for coordinate */ + H5S_hyper_span_info_t *down=NULL; /* Pointer to new span tree for next level down */ + H5S_hyper_span_t *ret_value=NULL; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_hyper_coord_to_span); + + assert(rank>0); + assert(coords); + + /* Search for location to insert new element in tree */ + if(rank>1) { + /* Allocate a span info node */ + if((down = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span"); + + /* Set the reference count */ + down->count=0; + + /* Reset the scratch pad space */ + down->scratch=0; + + /* Build span tree for coordinates below this one */ + if((down->head=H5S_hyper_coord_to_span(rank-1,&coords[1]))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span"); + } /* end if */ + + /* Build span for this coordinate */ + if((new_span = H5S_hyper_new_span(coords[0],coords[0],down,NULL))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span"); + + /* Set return value */ + ret_value=new_span; + +done: + if(ret_value==NULL) { + if(down!=NULL) + H5S_hyper_free_span_info(down); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_coord_to_span() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_add_span_element_helper + PURPOSE + Add a single elment to a span tree + USAGE + herr_t H5S_hyper_add_span_element_helper(prev_span, span_tree, rank, coords) + H5S_hyper_span_info_t *span_tree; IN/OUT: Pointer to span tree to append to + unsigned rank; IN: Number of dimensions of coordinates + hssize_t *coords; IN: Location of element to add to span tree + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Add a single element to an existing span tree. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Assumes that the element is not already covered by the span tree + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_hyper_add_span_element_helper(H5S_hyper_span_info_t *span_tree, unsigned rank, hssize_t *coords) +{ + H5S_hyper_span_info_t *tspan_info; /* Temporary pointer to span info */ + H5S_hyper_span_info_t *prev_span_info; /* Pointer to span info for level above current position */ + H5S_hyper_span_t *tmp_span; /* Temporary pointer to a span */ + H5S_hyper_span_t *tmp2_span; /* Another temporary pointer to a span */ + H5S_hyper_span_t *new_span; /* New span created for element */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_hyper_add_span_element_helper); + + assert(span_tree); + assert(rank>0); + assert(coords); + + /* Get pointer to last span in span tree */ + tspan_info=span_tree; + if(span_tree->scratch) + tmp_span=(H5S_hyper_span_t *)span_tree->scratch; + else { + tmp_span=span_tree->head; + assert(tmp_span); + span_tree->scratch=(H5S_hyper_span_info_t *)tmp_span; + } /* end else */ + + /* Find last span tree which includes a portion of the coordinate */ + prev_span_info=NULL; + while(coords[0]>=tmp_span->low && coords[0]<=tmp_span->high) { + /* Move rank & coordinate offset down a dimension */ + rank--; + coords++; + + /* Remember the span tree we are descending into */ + prev_span_info=tspan_info; + tspan_info=tmp_span->down; + + /* Get the last span in this span's 'down' tree */ + if(tspan_info->scratch) + tmp_span=(H5S_hyper_span_t *)tspan_info->scratch; + else { + tmp_span=tspan_info->head; + assert(tmp_span); + tspan_info->scratch=(H5S_hyper_span_info_t *)tmp_span; + } /* end else */ + } /* end while */ + + /* Check if we made it all the way to the bottom span in the tree */ + if(rank>1) { + /* Before we create another span at this level in the tree, check if + * the last span's "down tree" was equal to any other spans in this + * list of spans in the span tree. + * + * If so, release last span information and make last span merge into + * previous span (if possible), or at least share their "down tree" + * information. + */ + tmp2_span=tspan_info->head; + while(tmp2_span!=tmp_span) { + if(H5S_hyper_cmp_spans(tmp2_span->down,tmp_span->down)==TRUE) { + /* Check for merging into previous span */ + if(tmp2_span->high+1==tmp_span->low) { + /* Release last span created */ + H5S_hyper_free_span(tmp_span); + + /* Increase size of previous span */ + tmp2_span->high++; + + /* Reset the 'tmp_span' for the rest of this block's algorithm */ + tmp_span=tmp2_span; + } /* end if */ + /* Span is disjoint, but has the same "down tree" selection */ + else { + /* Release "down tree" information */ + H5S_hyper_free_span_info(tmp_span->down); + + /* Point at earlier span's "down tree" */ + tmp_span->down=tmp2_span->down; + + /* Increment reference count on shared "down tree" */ + tmp_span->down->count++; + } /* end else */ + + /* Found span to merge into, break out now */ + break; + } /* end if */ + + /* Advance to next span to check */ + tmp2_span=tmp2_span->next; + } /* end while */ + + /* Make span tree for current coordinates */ + if((new_span=H5S_hyper_coord_to_span(rank,coords))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span"); + + /* Add new span tree as span */ + assert(tmp_span); + tmp_span->next=new_span; + + /* Make scratch pointer point to last span in list */ + assert(tspan_info); + tspan_info->scratch=(H5S_hyper_span_info_t *)new_span; + + /* Set the proper 'pstride' for new span */ + new_span->pstride=new_span->low-tmp_span->low; + } /* end if */ + else { + /* Does new node adjoin existing node? */ + if(tmp_span->high+1==coords[0]) { + tmp_span->high++; + + /* Check if this span tree should now be merged with a level higher in the tree */ + if(prev_span_info!=NULL) { + /* Before we create another span at this level in the tree, check if + * the last span's "down tree" was equal to any other spans in this + * list of spans in the span tree. + * + * If so, release last span information and make last span merge into + * previous span (if possible), or at least share their "down tree" + * information. + */ + tmp2_span=prev_span_info->head; + tmp_span=(H5S_hyper_span_t *)prev_span_info->scratch; + while(tmp2_span!=tmp_span) { + if(H5S_hyper_cmp_spans(tmp2_span->down,tmp_span->down)==TRUE) { + /* Check for merging into previous span */ + if(tmp2_span->high+1==tmp_span->low) { + /* Release last span created */ + H5S_hyper_free_span(tmp_span); + + /* Increase size of previous span */ + tmp2_span->high++; + + /* Update pointers */ + tmp2_span->next=NULL; + prev_span_info->scratch=(H5S_hyper_span_info_t *)tmp2_span; + } /* end if */ + /* Span is disjoint, but has the same "down tree" selection */ + else { + /* Release "down tree" information */ + H5S_hyper_free_span_info(tmp_span->down); + + /* Point at earlier span's "down tree" */ + tmp_span->down=tmp2_span->down; + + /* Increment reference count on shared "down tree" */ + tmp_span->down->count++; + } /* end else */ + + /* Found span to merge into, break out now */ + break; + } /* end if */ + + /* Advance to next span to check */ + tmp2_span=tmp2_span->next; + } /* end while */ + } /* end if */ + } /* end if */ + else { + if((new_span = H5S_hyper_new_span(coords[0],coords[0],NULL,NULL))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span"); + + /* Add new span tree as span */ + assert(tmp_span); + tmp_span->next=new_span; + + /* Make scratch pointer point to last span in list */ + tspan_info->scratch=(H5S_hyper_span_info_t *)new_span; + + /* Set the proper 'pstride' for new span */ + new_span->pstride=new_span->low-tmp_span->low; + } /* end else */ + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_add_span_element_helper() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_add_span_element + PURPOSE + Add a single elment to a span tree + USAGE + herr_t H5S_hyper_add_span_element(space, span_tree, rank, coords) + H5S_t *space; IN/OUT: Pointer to dataspace to add coordinate to + unsigned rank; IN: Number of dimensions of coordinates + hssize_t *coords; IN: Location of element to add to span tree + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Add a single element to an existing span tree. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Assumes that the element is not already in the dataspace's selection + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_add_span_element(H5S_t *space, unsigned rank, hssize_t *coords) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_hyper_add_span_element); + + assert(space); + assert(rank>0); + assert(coords); + + /* Check if this is the first element in the selection */ + if(space->select.sel_info.hslab.span_lst==NULL) { + H5S_hyper_span_info_t *head; /* Pointer to new head of span tree */ + + /* Allocate a span info node */ + if((head = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span"); + + /* Set the reference count */ + head->count=0; + + /* Reset the scratch pad space */ + head->scratch=0; + + /* Build span tree for this coordinate */ + if((head->head=H5S_hyper_coord_to_span(rank,coords))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span"); + + /* Set the selection to the new span tree */ + space->select.sel_info.hslab.span_lst=head; + + /* Set selection type */ + space->select.type=H5S_SEL_HYPERSLABS; + + /* Reset "regular" hyperslab fields */ + space->select.sel_info.hslab.diminfo = NULL; + space->select.sel_info.hslab.app_diminfo = NULL; + + /* Set selection methods */ + space->select.get_seq_list=H5S_hyper_get_seq_list; + space->select.get_npoints=H5S_hyper_npoints; + space->select.release=H5S_hyper_release; + space->select.is_valid=H5S_hyper_is_valid; + space->select.serial_size=H5S_hyper_serial_size; + space->select.serialize=H5S_hyper_serialize; + space->select.bounds=H5S_hyper_bounds; + space->select.is_contiguous=H5S_hyper_is_contiguous; + space->select.is_single=H5S_hyper_is_single; + space->select.is_regular=H5S_hyper_is_regular; + space->select.iter_init=H5S_hyper_iter_init; + + /* Set # of elements in selection */ + space->select.num_elem=1; + } /* end if */ + else { + if(H5S_hyper_add_span_element_helper(space->select.sel_info.hslab.span_lst,rank,coords)<0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span"); + + /* Increment # of elements in selection */ + space->select.num_elem++; + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_add_span_element() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_reset_scratch + PURPOSE + Reset the scratch information for span tree + USAGE + herr_t H5S_hyper_reset_scratch(space) + H5S_t *space; IN/OUT: Pointer to dataspace to reset scratch pointers + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Resets the "scratch" pointers used for various tasks in computing hyperslab + spans. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_hyper_reset_scratch(H5S_t *space) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_hyper_reset_scratch); + + assert(space); + + /* Check if there are spans in the span tree */ + if(space->select.sel_info.hslab.span_lst!=NULL) + /* Reset the scratch pointers for the next routine which needs them */ + if(H5S_hyper_span_scratch(space->select.sel_info.hslab.span_lst,NULL)==FAIL) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "can't reset span tree scratch pointers"); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_hyper_reset_scratch() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_hyper_append_span PURPOSE Create a new span and append to span list @@ -4145,9 +4723,6 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, space->select.get_seq_list=H5S_hyper_get_seq_list; space->select.get_npoints=H5S_hyper_npoints; space->select.release=H5S_hyper_release; - space->select.iter_init=H5S_hyper_iter_init; - space->select.iter_nelmts=H5S_hyper_iter_nelmts; - space->select.iter_release=H5S_hyper_iter_release; space->select.is_valid=H5S_hyper_is_valid; space->select.serial_size=H5S_hyper_serial_size; space->select.serialize=H5S_hyper_serialize; @@ -4155,6 +4730,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, space->select.is_contiguous=H5S_hyper_is_contiguous; space->select.is_single=H5S_hyper_is_single; space->select.is_regular=H5S_hyper_is_regular; + space->select.iter_init=H5S_hyper_iter_init; done: if(_stride!=NULL) @@ -4375,18 +4951,17 @@ H5S_operate_hyperslab (H5S_t *result, H5S_hyper_span_info_t *spans1, H5S_seloper result->select.type=H5S_SEL_HYPERSLABS; /* Set selection methods */ - space->select.get_seq_list=H5S_hyper_get_seq_list; - space->select.get_npoints=H5S_hyper_npoints; - space->select.release=H5S_hyper_release; - space->select.iter_init=H5S_hyper_iter_init; - space->select.iter_nelmts=H5S_hyper_iter_nelmts; - space->select.iter_release=H5S_hyper_iter_release; - space->select.is_valid=H5S_hyper_is_valid; - space->select.serial_size=H5S_hyper_serial_size; - space->select.serialize=H5S_hyper_serialize; - space->select.bounds=H5S_hyper_bounds; - space->select.is_contiguous=H5S_hyper_is_contiguous; - space->select.is_single=H5S_hyper_is_single; + result->select.get_seq_list=H5S_hyper_get_seq_list; + result->select.get_npoints=H5S_hyper_npoints; + result->select.release=H5S_hyper_release; + result->select.is_valid=H5S_hyper_is_valid; + result->select.serial_size=H5S_hyper_serial_size; + result->select.serialize=H5S_hyper_serialize; + result->select.bounds=H5S_hyper_bounds; + result->select.is_contiguous=H5S_hyper_is_contiguous; + result->select.is_single=H5S_hyper_is_single; + result->select.is_regular=H5S_hyper_is_regular; + result->select.iter_init=H5S_hyper_iter_init; done: FUNC_LEAVE_NOAPI(ret_value); @@ -4487,8 +5062,8 @@ done: */ herr_t H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, - const hssize_t start, - const hsize_t *stride[], + const hssize_t start[], + const hsize_t *stride, const hsize_t count[], const hsize_t *block) { @@ -4943,7 +5518,7 @@ done: * *------------------------------------------------------------------------- */ -static herr_t +herr_t H5S_select_select (H5S_t *space1, H5S_seloper_t op, H5S_t *space2) { H5S_hyper_span_info_t *tmp_spans=NULL; /* Temporary copy of selection */ @@ -5071,6 +5646,7 @@ H5S_hyper_get_seq_list_gen(const H5S_t *space,H5S_sel_iter_t *iter, hsize_t slab[H5O_LAYOUT_NDIMS]; /* Cumulative size of each dimension in bytes */ hsize_t acc; /* Accumulator for computing cumulative sizes */ hsize_t loc_off; /* Element offset in the dataspace */ + hsize_t last_span_end=0; /* The offset of the end of the last span */ hssize_t *abs_arr; /* Absolute hyperslab span position */ hssize_t *off_arr; /* Offset within the dataspace extent */ size_t span_size=0; /* Number of bytes in current span to actually process */ @@ -5104,14 +5680,14 @@ H5S_hyper_get_seq_list_gen(const H5S_t *space,H5S_sel_iter_t *iter, fast_dim=(ndims-1); /* Get the pointers to the current span info and span nodes */ - curr_span=iter->hyp.span[fast_dim]; - abs_arr=iter->hyp.off; + curr_span=iter->u.hyp.span[fast_dim]; + abs_arr=iter->u.hyp.off; off_arr=space->select.offset; - ispan=iter->hyp.span; + ispan=iter->u.hyp.span; /* Set the amount of elements to perform I/O on, etc. */ - H5_CHECK_OVERFLOW( (iter->hyp.elmt_left*elem_size) ,hsize_t,size_t); - start_io_bytes_left=io_bytes_left=MIN(maxbytes,(size_t)(iter->hyp.elmt_left*elem_size)); + H5_CHECK_OVERFLOW( (iter->elmt_left*elem_size) ,hsize_t,size_t); + start_io_bytes_left=io_bytes_left=MIN(maxbytes,(size_t)(iter->elmt_left*elem_size)); nelem=io_bytes_left/elem_size; /* Compute the cumulative size of dataspace dimensions */ @@ -5126,7 +5702,7 @@ H5S_hyper_get_seq_list_gen(const H5S_t *space,H5S_sel_iter_t *iter, loc_off+=(abs_arr[i]+off_arr[i])*slab[i]; /* Range check against number of elements left in selection */ - assert(io_bytes_left<=(iter->hyp.elmt_left*elem_size)); + assert(io_bytes_left<=(iter->elmt_left*elem_size)); /* Take care of any partial spans leftover from previous I/Os */ if(abs_arr[fast_dim]!=curr_span->low) { @@ -5147,6 +5723,9 @@ H5S_hyper_get_seq_list_gen(const H5S_t *space,H5S_sel_iter_t *iter, /* Increment sequence count */ curr_seq++; + /* Set the location of the last span's end */ + last_span_end=loc_off+span_size; + /* Decrement I/O left to perform */ io_bytes_left-=span_size; @@ -5169,7 +5748,7 @@ H5S_hyper_get_seq_list_gen(const H5S_t *space,H5S_sel_iter_t *iter, /* Check if we are still within the span */ if(abs_arr[fast_dim]<=curr_span->high) { - iter->hyp.span[fast_dim]=curr_span; + iter->u.hyp.span[fast_dim]=curr_span; goto partial_done; /* finished with partial span */ } /* end if */ @@ -5182,7 +5761,7 @@ H5S_hyper_get_seq_list_gen(const H5S_t *space,H5S_sel_iter_t *iter, if(curr_span!=NULL) { /* Reset absolute position */ abs_arr[fast_dim]=curr_span->low; - iter->hyp.span[fast_dim]=curr_span; + iter->u.hyp.span[fast_dim]=curr_span; goto partial_done; /* finished with partial span */ } /* end if */ @@ -5199,7 +5778,7 @@ H5S_hyper_get_seq_list_gen(const H5S_t *space,H5S_sel_iter_t *iter, /* Work back up through the dimensions */ while(curr_dim>=0) { /* Reset the current span */ - curr_span=iter->hyp.span[curr_dim]; + curr_span=iter->u.hyp.span[curr_dim]; /* Increment absolute position */ abs_arr[curr_dim]++; @@ -5248,7 +5827,7 @@ H5S_hyper_get_seq_list_gen(const H5S_t *space,H5S_sel_iter_t *iter, curr_dim++; /* Set the new span_info & span for this dimension */ - iter->hyp.span[curr_dim]=curr_span->down->head; + iter->u.hyp.span[curr_dim]=curr_span->down->head; /* Advance span down the tree */ curr_span=curr_span->down->head; @@ -5258,7 +5837,7 @@ H5S_hyper_get_seq_list_gen(const H5S_t *space,H5S_sel_iter_t *iter, } /* end while */ /* Verify that the curr_span points to the fastest dim */ - assert(curr_span==iter->hyp.span[fast_dim]); + assert(curr_span==iter->u.hyp.span[fast_dim]); } /* end else */ /* Reset the buffer offset */ @@ -5290,11 +5869,20 @@ partial_done: /* Yes, goto's are evil, so sue me... :-) */ /* COMMON */ /* Store the I/O information for the span */ - off[curr_seq]=loc_off; - len[curr_seq]=span_size; - - /* Increment the number of sequences in arrays */ - curr_seq++; + + /* Check if this is appending onto previous sequence */ + if(curr_seq>0 && last_span_end==loc_off) + len[curr_seq-1]+=span_size; + else { + off[curr_seq]=loc_off; + len[curr_seq]=span_size; + + /* Increment the number of sequences in arrays */ + curr_seq++; + } /* end else */ + + /* Set the location of the last span's end */ + last_span_end=loc_off+span_size; /* If the sequence & offset arrays are full, do what? */ if(curr_seq>=maxseq) { @@ -5313,11 +5901,20 @@ partial_done: /* Yes, goto's are evil, so sue me... :-) */ /* COMMON */ /* Store the I/O information for the span */ - off[curr_seq]=loc_off; - len[curr_seq]=span_size; - - /* Increment the number of sequences in arrays */ - curr_seq++; + + /* Check if this is appending onto previous sequence */ + if(curr_seq>0 && last_span_end==loc_off) + len[curr_seq-1]+=span_size; + else { + off[curr_seq]=loc_off; + len[curr_seq]=span_size; + + /* Increment the number of sequences in arrays */ + curr_seq++; + } /* end else */ + + /* Set the location of the last span's end */ + last_span_end=loc_off+span_size; /* If the sequence & offset arrays are full, do what? */ if(curr_seq>=maxseq) { @@ -5337,7 +5934,7 @@ partial_done: /* Yes, goto's are evil, so sue me... :-) */ /* Check if we are still within the span */ if(abs_arr[fast_dim]<=curr_span->high) { - iter->hyp.span[fast_dim]=curr_span; + iter->u.hyp.span[fast_dim]=curr_span; break; } /* end if */ /* If we walked off that span, advance to the next span */ @@ -5349,7 +5946,7 @@ partial_done: /* Yes, goto's are evil, so sue me... :-) */ if(curr_span!=NULL) { /* Reset absolute position */ abs_arr[fast_dim]=curr_span->low; - iter->hyp.span[fast_dim]=curr_span; + iter->u.hyp.span[fast_dim]=curr_span; break; } /* end if */ } /* end else */ @@ -5363,7 +5960,7 @@ partial_done: /* Yes, goto's are evil, so sue me... :-) */ /* Work back up through the dimensions */ while(curr_dim>=0) { /* Reset the current span */ - curr_span=iter->hyp.span[curr_dim]; + curr_span=iter->u.hyp.span[curr_dim]; /* Increment absolute position */ abs_arr[curr_dim]++; @@ -5411,7 +6008,7 @@ partial_done: /* Yes, goto's are evil, so sue me... :-) */ curr_dim++; /* Set the new span for the next dimension down */ - iter->hyp.span[curr_dim]=curr_span->down->head; + iter->u.hyp.span[curr_dim]=curr_span->down->head; /* Advance span down the tree */ curr_span=curr_span->down->head; @@ -5421,7 +6018,7 @@ partial_done: /* Yes, goto's are evil, so sue me... :-) */ } /* end while */ /* Verify that the curr_span points to the fastest dim */ - assert(curr_span==iter->hyp.span[fast_dim]); + assert(curr_span==iter->u.hyp.span[fast_dim]); } /* end else */ /* Reset the buffer offset */ @@ -5430,7 +6027,7 @@ partial_done: /* Yes, goto's are evil, so sue me... :-) */ } /* end while */ /* Decrement number of elements left in iterator */ - iter->hyp.elmt_left-=(nelem-(io_bytes_left/elem_size)); + iter->elmt_left-=(nelem-(io_bytes_left/elem_size)); /* Set the number of sequences generated */ *nseq=curr_seq; @@ -5526,29 +6123,26 @@ H5S_hyper_get_seq_list_opt(const H5S_t *space,H5S_sel_iter_t *iter, assert(off); assert(len); + /* Set the local copy of the diminfo pointer */ + tdiminfo=iter->u.hyp.diminfo; + /* Check if this is a "flattened" regular hyperslab selection */ - if(iter->hyp.iter_rank!=0 && iter->hyp.iter_rank<space->extent.u.simple.rank) { + if(iter->u.hyp.iter_rank!=0 && iter->u.hyp.iter_rank<space->extent.u.simple.rank) { /* Set the aliases for a few important dimension ranks */ - ndims=iter->hyp.iter_rank; + ndims=iter->u.hyp.iter_rank; fast_dim=ndims-1; - /* Set the local copy of the diminfo pointer */ - tdiminfo=iter->hyp.diminfo; - /* Set the local copy of the selection offset */ - sel_off=iter->hyp.sel_off; + sel_off=iter->u.hyp.sel_off; /* Set up the size of the memory space */ - HDmemcpy(mem_size, iter->hyp.size, ndims*sizeof(hsize_t)); + HDmemcpy(mem_size, iter->u.hyp.size, ndims*sizeof(hsize_t)); } /* end if */ else { /* Set the aliases for a few important dimension ranks */ ndims=space->extent.u.simple.rank; fast_dim=ndims-1; - /* Set the local copy of the diminfo pointer */ - tdiminfo=space->select.sel_info.hslab.diminfo; - /* Set the local copy of the selection offset */ sel_off=space->select.offset; @@ -5564,22 +6158,22 @@ H5S_hyper_get_seq_list_opt(const H5S_t *space,H5S_sel_iter_t *iter, } /* end for */ /* Get the number of elements left in the selection */ - H5_ASSIGN_OVERFLOW(io_left,iter->hyp.elmt_left,hsize_t,size_t); + H5_ASSIGN_OVERFLOW(io_left,iter->elmt_left,hsize_t,size_t); /* Calculate the number of elements to sequence through */ start_io_left=io_left=MIN(io_left,(maxbytes/elmt_size)); /* Check if we stopped in the middle of a sequence of elements */ - if((iter->hyp.off[fast_dim]-tdiminfo[fast_dim].start)%tdiminfo[fast_dim].stride!=0 || - ((iter->hyp.off[fast_dim]!=tdiminfo[fast_dim].start) && tdiminfo[fast_dim].stride==1)) { + if((iter->u.hyp.off[fast_dim]-tdiminfo[fast_dim].start)%tdiminfo[fast_dim].stride!=0 || + ((iter->u.hyp.off[fast_dim]!=tdiminfo[fast_dim].start) && tdiminfo[fast_dim].stride==1)) { size_t leftover; /* The number of elements left over from the last sequence */ /* Calculate the number of elements left in the sequence */ if(tdiminfo[fast_dim].stride==1) { - H5_ASSIGN_OVERFLOW(leftover, tdiminfo[fast_dim].block-(iter->hyp.off[fast_dim]-tdiminfo[fast_dim].start) ,hsize_t,size_t); + H5_ASSIGN_OVERFLOW(leftover, tdiminfo[fast_dim].block-(iter->u.hyp.off[fast_dim]-tdiminfo[fast_dim].start) ,hsize_t,size_t); } /* end if */ else { - H5_ASSIGN_OVERFLOW(leftover, tdiminfo[fast_dim].block-((iter->hyp.off[fast_dim]-tdiminfo[fast_dim].start)%tdiminfo[fast_dim].stride) ,hsize_t,size_t); + H5_ASSIGN_OVERFLOW(leftover, tdiminfo[fast_dim].block-((iter->u.hyp.off[fast_dim]-tdiminfo[fast_dim].start)%tdiminfo[fast_dim].stride) ,hsize_t,size_t); } /* end else */ /* Make certain that we don't write too many */ @@ -5587,7 +6181,7 @@ H5S_hyper_get_seq_list_opt(const H5S_t *space,H5S_sel_iter_t *iter, /* Compute the initial buffer offset */ for(i=0,loc=0; i<ndims; i++) - loc+=(iter->hyp.off[i]+sel_off[i])*slab[i]; + loc+=(iter->u.hyp.off[i]+sel_off[i])*slab[i]; /* Add a new sequence */ off[curr_seq]=loc; @@ -5600,22 +6194,10 @@ H5S_hyper_get_seq_list_opt(const H5S_t *space,H5S_sel_iter_t *iter, io_left -= actual_elem; /* Advance the hyperslab iterator */ - - /* If we had enough room to count the rest of the sequence - * in the fastest changing dimension, move the iterator offset to - * the beginning of the next block to write. Otherwise, just advance - * the iterator in the fastest changing dimension. - */ - if(actual_elem==leftover) { - /* Move iterator offset to beginning of next sequence in the fastest changing dimension */ - H5S_hyper_iter_next(space,iter); - } /* end if */ - else { - iter->hyp.off[fast_dim]+=actual_elem; /* whole sequence not written out, just advance fastest dimension offset */ - } /* end else */ + H5S_hyper_iter_next(iter,actual_elem); /* Decrement the number of elements left in selection */ - iter->hyp.elmt_left-=actual_elem; + iter->elmt_left-=actual_elem; } /* end if */ /* Now that we've cleared the "remainder" of the previous fastest dimension @@ -5629,7 +6211,7 @@ H5S_hyper_get_seq_list_opt(const H5S_t *space,H5S_sel_iter_t *iter, /* Compute the arrays to perform I/O on */ /* Copy the location of the point to get */ - HDmemcpy(offset, iter->hyp.off,ndims*sizeof(hssize_t)); + HDmemcpy(offset, iter->u.hyp.off,ndims*sizeof(hssize_t)); /* Add in the selection offset */ for(i=0; i<ndims; i++) @@ -5639,11 +6221,11 @@ H5S_hyper_get_seq_list_opt(const H5S_t *space,H5S_sel_iter_t *iter, for(i=0; i<ndims; i++) { if(tdiminfo[i].stride==1) { tmp_count[i] = 0; - tmp_block[i] = iter->hyp.off[i]-tdiminfo[i].start; + tmp_block[i] = iter->u.hyp.off[i]-tdiminfo[i].start; } /* end if */ else { - tmp_count[i] = (iter->hyp.off[i]-tdiminfo[i].start)/tdiminfo[i].stride; - tmp_block[i] = (iter->hyp.off[i]-tdiminfo[i].start)%tdiminfo[i].stride; + tmp_count[i] = (iter->u.hyp.off[i]-tdiminfo[i].start)/tdiminfo[i].stride; + tmp_block[i] = (iter->u.hyp.off[i]-tdiminfo[i].start)%tdiminfo[i].stride; } /* end else */ } /* end for */ @@ -5983,7 +6565,6 @@ H5S_hyper_get_seq_list_opt(const H5S_t *space,H5S_sel_iter_t *iter, assert(io_left==0 || curr_seq==maxseq); } /* end if */ - /* Update the iterator */ /* Subtract out the selection offset */ @@ -5991,10 +6572,10 @@ H5S_hyper_get_seq_list_opt(const H5S_t *space,H5S_sel_iter_t *iter, offset[i] -= sel_off[i]; /* Update the iterator with the location we stopped */ - HDmemcpy(iter->hyp.off, offset, ndims*sizeof(hssize_t)); + HDmemcpy(iter->u.hyp.off, offset, ndims*sizeof(hssize_t)); /* Decrement the number of elements left in selection */ - iter->hyp.elmt_left-=(nelmts-io_left); + iter->elmt_left-=(nelmts-io_left); } /* end if */ /* Set the number of sequences generated */ diff --git a/src/H5Snone.c b/src/H5Snone.c index 20f03be..a1d6127 100644 --- a/src/H5Snone.c +++ b/src/H5Snone.c @@ -49,7 +49,7 @@ static int interface_initialize_g = 0; *------------------------------------------------------------------------- */ herr_t -H5S_none_iter_init (const H5S_t UNUSED *space, size_t UNUSED elmt_size, H5S_sel_iter_t UNUSED *sel_iter) +H5S_none_iter_init (H5S_sel_iter_t *iter, const H5S_t UNUSED *space, size_t UNUSED elmt_size) { herr_t ret_value=SUCCEED; /* Return value */ @@ -57,7 +57,13 @@ H5S_none_iter_init (const H5S_t UNUSED *space, size_t UNUSED elmt_size, H5S_sel_ /* Check args */ assert (space && H5S_SEL_NONE==space->select.type); - assert (sel_iter); + assert (iter); + + /* Initialize methods for selection iterator */ + iter->iter_coords=H5S_none_iter_coords; + iter->iter_nelmts=H5S_none_iter_nelmts; + iter->iter_next=H5S_none_iter_next; + iter->iter_release=H5S_none_iter_release; done: FUNC_LEAVE_NOAPI(ret_value); @@ -65,6 +71,37 @@ done: /*------------------------------------------------------------------------- + * Function: H5S_none_iter_coords + * + * Purpose: Retrieve the current coordinates of iterator for current + * selection + * + * Return: non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, April 22, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_none_iter_coords (const H5S_sel_iter_t UNUSED *iter, hssize_t UNUSED *coords) +{ + herr_t ret_value=FAIL; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_none_iter_coords, FAIL); + + /* Check args */ + assert (iter); + assert (coords); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_none_iter_coords() */ + + +/*------------------------------------------------------------------------- * Function: H5S_none_iter_nelmts * * Purpose: Return number of elements left to process in iterator @@ -79,14 +116,14 @@ done: *------------------------------------------------------------------------- */ hsize_t -H5S_none_iter_nelmts (const H5S_sel_iter_t UNUSED *sel_iter) +H5S_none_iter_nelmts (const H5S_sel_iter_t UNUSED *iter) { hsize_t ret_value=0; /* Return value */ FUNC_ENTER_NOAPI(H5S_none_iter_nelmts, 0); /* Check args */ - assert (sel_iter); + assert (iter); done: FUNC_LEAVE_NOAPI(ret_value); @@ -95,12 +132,46 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_none_iter_next + PURPOSE + Increment selection iterator + USAGE + herr_t H5S_none_iter_next(iter, nelem) + H5S_sel_iter_t *iter; IN: Pointer to selection iterator + size_t nelem; IN: Number of elements to advance by + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Advance selection iterator to the NELEM'th next element in the selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_none_iter_next(H5S_sel_iter_t UNUSED *iter, size_t UNUSED nelem) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_none_iter_next, FAIL); + + /* Check args */ + assert (iter); + assert (nelem>0); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_none_iter_next() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_none_iter_release PURPOSE Release "none" selection iterator information for a dataspace USAGE - herr_t H5S_none_iter_release(sel_iter) - H5S_sel_iter_t *sel_iter; IN: Pointer to selection iterator + herr_t H5S_none_iter_release(iter) + H5S_sel_iter_t *iter; IN: Pointer to selection iterator RETURNS Non-negative on success/Negative on failure DESCRIPTION @@ -111,14 +182,14 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_none_iter_release (H5S_sel_iter_t UNUSED * sel_iter) +H5S_none_iter_release (H5S_sel_iter_t UNUSED * iter) { herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5S_none_iter_release, FAIL); /* Check args */ - assert (sel_iter); + assert (iter); done: FUNC_LEAVE_NOAPI(ret_value); @@ -515,9 +586,6 @@ herr_t H5S_select_none (H5S_t *space) space->select.get_seq_list=H5S_none_get_seq_list; space->select.get_npoints=H5S_none_npoints; space->select.release=H5S_none_release; - space->select.iter_init=H5S_none_iter_init; - space->select.iter_nelmts=H5S_none_iter_nelmts; - space->select.iter_release=H5S_none_iter_release; space->select.is_valid=H5S_none_is_valid; space->select.serial_size=H5S_none_serial_size; space->select.serialize=H5S_none_serialize; @@ -525,6 +593,7 @@ herr_t H5S_select_none (H5S_t *space) space->select.is_contiguous=H5S_none_is_contiguous; space->select.is_single=H5S_none_is_single; space->select.is_regular=H5S_none_is_regular; + space->select.iter_init=H5S_none_iter_init; done: FUNC_LEAVE_NOAPI(ret_value); diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 8079d77..7844d14 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -79,7 +79,12 @@ struct H5S_hyper_span_t { /* Information about a list of hyperslab spans */ struct H5S_hyper_span_info_t { unsigned count; /* Ref. count of number of spans which share this span */ - struct H5S_hyper_span_info_t *scratch; /* Scratch pointer (used during copies & as mark during precomputes for I/O) */ + struct H5S_hyper_span_info_t *scratch; /* Scratch pointer + * (used during copies, as mark + * during precomputes for I/O & + * to point to the last span in a + * list during single element adds) + */ struct H5S_hyper_span_t *head; /* Pointer to list of spans in next dimension down */ }; @@ -117,12 +122,6 @@ typedef herr_t (*H5S_sel_get_seq_list_func_t)(const H5S_t *space, unsigned flags typedef hsize_t (*H5S_sel_get_npoints_func_t)(const H5S_t *space); /* Method to release current selection */ typedef herr_t (*H5S_sel_release_func_t)(H5S_t *space); -/* Method to initialize iterator for current selection */ -typedef herr_t (*H5S_sel_iter_init_func_t)(const H5S_t *space, size_t elmt_size, H5S_sel_iter_t *sel_iter); -/* Method to determine number of elements left in iterator for current selection */ -typedef hsize_t (*H5S_sel_iter_nelmts_func_t)(const H5S_sel_iter_t *iter); -/* Method to release iterator for current selection */ -typedef herr_t (*H5S_sel_iter_release_func_t)(H5S_sel_iter_t *iter); /* Method to determine if current selection is valid for dataspace */ typedef htri_t (*H5S_sel_is_valid_func_t)(const H5S_t *space); /* Method to determine number of bytes required to store current selection */ @@ -137,6 +136,8 @@ typedef htri_t (*H5S_sel_is_contiguous_func_t)(const H5S_t *space); 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 initialize iterator for current selection */ +typedef herr_t (*H5S_sel_iter_init_func_t)(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_size); /* Selection information object */ typedef struct { @@ -151,9 +152,6 @@ typedef struct { H5S_sel_get_seq_list_func_t get_seq_list; /* Method to retrieve a list of offset/length sequences for selection */ H5S_sel_get_npoints_func_t get_npoints; /* Method to compute number of elements in current selection */ H5S_sel_release_func_t release; /* Method to release current selection */ - H5S_sel_iter_init_func_t iter_init; /* Method to initialize iterator for current selection */ - H5S_sel_iter_nelmts_func_t iter_nelmts; /* Method to determine number of elements left in iterator for current selection */ - H5S_sel_iter_release_func_t iter_release; /* Method to release iterator for current selection */ H5S_sel_is_valid_func_t is_valid; /* Method to determine if current selection is valid for dataspace */ H5S_sel_serial_size_func_t serial_size; /* Method to determine number of bytes required to store current selection */ H5S_sel_serialize_func_t serialize; /* Method to store current selection in "serialized" form (a byte sequence suitable for storing on disk) */ @@ -161,6 +159,7 @@ typedef struct { 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_iter_init_func_t iter_init; /* Method to initialize iterator for current selection */ } H5S_select_t; /* Main dataspace structure (typedef'd in H5Sprivate.h) */ @@ -174,11 +173,14 @@ H5_DLL herr_t H5S_close_simple(H5S_simple_t *simple); H5_DLL herr_t H5S_release_simple(H5S_simple_t *simple); H5_DLL herr_t H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src); -/* Point select functions */ -H5_DLL herr_t H5S_point_iter_init (const H5S_t *space, size_t elmt_size, - H5S_sel_iter_t *iter); -H5_DLL hsize_t H5S_point_iter_nelmts (const H5S_sel_iter_t *iter); +/* Point selection iterator functions */ +H5_DLL herr_t H5S_point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size); +H5_DLL herr_t H5S_point_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords); +H5_DLL hsize_t H5S_point_iter_nelmts(const H5S_sel_iter_t *iter); +H5_DLL herr_t H5S_point_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); H5_DLL herr_t H5S_point_iter_release(H5S_sel_iter_t *sel_iter); + +/* Point selection functions */ H5_DLL herr_t H5S_point_release(H5S_t *space); H5_DLL hsize_t H5S_point_npoints(const H5S_t *space); H5_DLL herr_t H5S_point_copy(H5S_t *dst, const H5S_t *src); @@ -194,11 +196,14 @@ H5_DLL herr_t H5S_point_get_seq_list(const H5S_t *space, unsigned flags, H5S_sel_iter_t *iter, size_t elem_size, size_t maxseq, size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len); -/* "All" select functions */ -H5_DLL herr_t H5S_all_iter_init (const H5S_t *space, size_t elmt_size, - H5S_sel_iter_t *iter); -H5_DLL hsize_t H5S_all_iter_nelmts (const H5S_sel_iter_t *iter); +/* "All" selection iterator functions */ +H5_DLL herr_t H5S_all_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size); +H5_DLL herr_t H5S_all_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords); +H5_DLL hsize_t H5S_all_iter_nelmts(const H5S_sel_iter_t *iter); +H5_DLL herr_t H5S_all_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); H5_DLL herr_t H5S_all_iter_release(H5S_sel_iter_t *sel_iter); + +/* "All" selection functions */ H5_DLL herr_t H5S_all_release(H5S_t *space); H5_DLL hsize_t H5S_all_npoints(const H5S_t *space); H5_DLL htri_t H5S_all_is_valid(const H5S_t *space); @@ -213,11 +218,14 @@ H5_DLL herr_t H5S_all_get_seq_list(const H5S_t *space, unsigned flags, H5S_sel_iter_t *iter, size_t elem_size, size_t maxseq, size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len); -/* Hyperslab selection functions */ -H5_DLL herr_t H5S_hyper_iter_init (const H5S_t *space, size_t elmt_size, - H5S_sel_iter_t *iter); -H5_DLL hsize_t H5S_hyper_iter_nelmts (const H5S_sel_iter_t *iter); +/* Hyperslab selection iterator functions */ +H5_DLL herr_t H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size); +H5_DLL herr_t H5S_hyper_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords); +H5_DLL hsize_t H5S_hyper_iter_nelmts(const H5S_sel_iter_t *iter); +H5_DLL herr_t H5S_hyper_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); H5_DLL herr_t H5S_hyper_iter_release(H5S_sel_iter_t *sel_iter); + +/* Hyperslab selection functions */ H5_DLL herr_t H5S_hyper_release(H5S_t *space); H5_DLL hsize_t H5S_hyper_npoints(const H5S_t *space); H5_DLL herr_t H5S_hyper_copy(H5S_t *dst, const H5S_t *src); @@ -233,11 +241,14 @@ H5_DLL herr_t H5S_hyper_get_seq_list(const H5S_t *space, unsigned flags, H5S_sel_iter_t *iter, size_t elem_size, size_t maxseq, size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len); -/* "None" selection functions */ -H5_DLL herr_t H5S_none_iter_init (const H5S_t *space, size_t elmt_size, - H5S_sel_iter_t *iter); -H5_DLL hsize_t H5S_none_iter_nelmts (const H5S_sel_iter_t *iter); +/* "None" selection iterator functions */ +H5_DLL herr_t H5S_none_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size); +H5_DLL herr_t H5S_none_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords); +H5_DLL hsize_t H5S_none_iter_nelmts(const H5S_sel_iter_t *iter); +H5_DLL herr_t H5S_none_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); H5_DLL herr_t H5S_none_iter_release(H5S_sel_iter_t *sel_iter); + +/* "None" selection functions */ H5_DLL herr_t H5S_none_release(H5S_t *space); H5_DLL hsize_t H5S_none_npoints(const H5S_t *space); H5_DLL htri_t H5S_none_is_valid(const H5S_t *space); @@ -252,6 +263,8 @@ H5_DLL herr_t H5S_none_get_seq_list(const H5S_t *space, unsigned flags, H5S_sel_iter_t *iter, size_t elem_size, size_t maxseq, size_t maxbytes, size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len); /* Needed for use in hyperslab code (H5Shyper.c) */ -H5_DLL herr_t H5S_select_none(H5S_t *space); +#ifdef NEW_HYPERSLAB_API +H5_DLL herr_t H5S_select_select (H5S_t *space1, H5S_seloper_t op, H5S_t *space2); +#endif /*NEW_HYPERSLAB_API*/ -#endif +#endif /*_H5Spkg_H*/ diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 18b81b5..eefd599 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -56,7 +56,7 @@ H5FL_DEFINE_STATIC(H5S_pnt_list_t); *------------------------------------------------------------------------- */ herr_t -H5S_point_iter_init(const H5S_t *space, size_t UNUSED elmt_size, H5S_sel_iter_t *sel_iter) +H5S_point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t UNUSED elmt_size) { herr_t ret_value=SUCCEED; /* Return value */ @@ -64,20 +64,60 @@ H5S_point_iter_init(const H5S_t *space, size_t UNUSED elmt_size, H5S_sel_iter_t /* Check args */ assert (space && H5S_SEL_POINTS==space->select.type); - assert (sel_iter); + assert (iter); /* Initialize the number of points to iterate over */ - sel_iter->pnt.elmt_left=space->select.num_elem; + iter->elmt_left=space->select.num_elem; /* Start at the head of the list of points */ - sel_iter->pnt.curr=space->select.sel_info.pnt_lst->head; + iter->u.pnt.curr=space->select.sel_info.pnt_lst->head; + /* Initialize methods for selection iterator */ + iter->iter_coords=H5S_point_iter_coords; + iter->iter_nelmts=H5S_point_iter_nelmts; + iter->iter_next=H5S_point_iter_next; + iter->iter_release=H5S_point_iter_release; + done: FUNC_LEAVE_NOAPI(ret_value); } /* H5S_point_iter_init() */ /*------------------------------------------------------------------------- + * Function: H5S_point_iter_coords + * + * Purpose: Retrieve the current coordinates of iterator for current + * selection + * + * Return: non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, April 22, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5S_point_iter_coords (const H5S_sel_iter_t *iter, hssize_t *coords) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_point_iter_coords, FAIL); + + /* Check args */ + assert (iter); + assert (coords); + + /* Copy the offset of the current point */ + HDmemcpy(coords,iter->u.pnt.curr->pnt,sizeof(hssize_t)*iter->rank); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_point_iter_coords() */ + + +/*------------------------------------------------------------------------- * Function: H5S_point_iter_nelmts * * Purpose: Return number of elements left to process in iterator @@ -92,17 +132,17 @@ done: *------------------------------------------------------------------------- */ hsize_t -H5S_point_iter_nelmts (const H5S_sel_iter_t *sel_iter) +H5S_point_iter_nelmts (const H5S_sel_iter_t *iter) { hsize_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5S_point_iter_nelmts, 0); /* Check args */ - assert (sel_iter); + assert (iter); /* Set return value */ - ret_value=sel_iter->pnt.elmt_left; + ret_value=iter->elmt_left; done: FUNC_LEAVE_NOAPI(ret_value); @@ -111,12 +151,52 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_point_iter_next + PURPOSE + Increment selection iterator + USAGE + herr_t H5S_point_iter_next(iter, nelem) + H5S_sel_iter_t *iter; IN: Pointer to selection iterator + size_t nelem; IN: Number of elements to advance by + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Advance selection iterator to the NELEM'th next element in the selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_point_iter_next(H5S_sel_iter_t *iter, size_t nelem) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_point_iter_next, FAIL); + + /* Check args */ + assert (iter); + assert (nelem>0); + + /* Increment the iterator */ + while(nelem>0) { + iter->u.pnt.curr=iter->u.pnt.curr->next; + nelem--; + } /* end while */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_point_iter_next() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_point_iter_release PURPOSE Release point selection iterator information for a dataspace USAGE - herr_t H5S_point_iter_release(sel_iter) - H5S_sel_iter_t *sel_iter; IN: Pointer to selection iterator + herr_t H5S_point_iter_release(iter) + H5S_sel_iter_t *iter; IN: Pointer to selection iterator RETURNS Non-negative on success/Negative on failure DESCRIPTION @@ -127,14 +207,14 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_point_iter_release (H5S_sel_iter_t UNUSED * sel_iter) +H5S_point_iter_release (H5S_sel_iter_t UNUSED * iter) { herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5S_point_iter_release, FAIL); /* Check args */ - assert (sel_iter); + assert (iter); done: FUNC_LEAVE_NOAPI(ret_value); @@ -339,7 +419,7 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -static herr_t +herr_t H5S_select_elements (H5S_t *space, H5S_seloper_t op, size_t num_elem, const hssize_t **coord) { @@ -376,9 +456,6 @@ H5S_select_elements (H5S_t *space, H5S_seloper_t op, size_t num_elem, space->select.get_seq_list=H5S_point_get_seq_list; space->select.get_npoints=H5S_point_npoints; space->select.release=H5S_point_release; - space->select.iter_init=H5S_point_iter_init; - space->select.iter_nelmts=H5S_point_iter_nelmts; - space->select.iter_release=H5S_point_iter_release; space->select.is_valid=H5S_point_is_valid; space->select.serial_size=H5S_point_serial_size; space->select.serialize=H5S_point_serialize; @@ -386,6 +463,7 @@ H5S_select_elements (H5S_t *space, H5S_seloper_t op, size_t num_elem, space->select.is_contiguous=H5S_point_is_contiguous; space->select.is_single=H5S_point_is_single; space->select.is_regular=H5S_point_is_regular; + space->select.iter_init=H5S_point_iter_init; done: FUNC_LEAVE_NOAPI(ret_value); @@ -811,7 +889,7 @@ H5S_get_select_elem_pointlist(H5S_t *space, hsize_t startpoint, hsize_t numpoint /* Iterate through the node, copying each hyperslab's information */ while(node!=NULL && numpoints>0) { - HDmemcpy(buf,node->pnt,sizeof(hsize_t)*rank); + HDmemcpy(buf,node->pnt,sizeof(hssize_t)*rank); buf+=rank; numpoints--; node=node->next; @@ -1183,7 +1261,7 @@ H5S_point_get_seq_list(const H5S_t *space, unsigned flags, H5S_sel_iter_t *iter, maxbytes=(maxbytes/elem_size)*elem_size; /* Choose the minimum number of bytes to sequence through */ - start_bytes_left=bytes_left=MIN(iter->pnt.elmt_left*elem_size,maxbytes); + start_bytes_left=bytes_left=MIN(iter->elmt_left*elem_size,maxbytes); /* Get the dataspace dimensions */ if ((ndims=H5S_get_simple_extent_dims (space, dims, NULL))<0) @@ -1191,7 +1269,7 @@ H5S_point_get_seq_list(const H5S_t *space, unsigned flags, H5S_sel_iter_t *iter, /* Walk through the points in the selection, starting at the current */ /* location in the iterator */ - node=iter->pnt.curr; + node=iter->u.pnt.curr; curr_seq=0; while(node!=NULL) { /* Compute the offset of each selected point in the buffer */ @@ -1234,8 +1312,8 @@ H5S_point_get_seq_list(const H5S_t *space, unsigned flags, H5S_sel_iter_t *iter, bytes_left-=elem_size; /* Move the iterator */ - iter->pnt.curr=node->next; - iter->pnt.elmt_left--; + iter->u.pnt.curr=node->next; + iter->elmt_left--; /* Check if we're finished with all sequences */ if(curr_seq==maxseq) diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index e6619a4..6ca9802 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -51,17 +51,16 @@ typedef struct H5S_pnt_node_t H5S_pnt_node_t; typedef struct H5S_hyper_span_t H5S_hyper_span_t; typedef struct H5S_hyper_span_info_t H5S_hyper_span_info_t; typedef struct H5S_hyper_dim_t H5S_hyper_dim_t; +union H5D_storage_t; /* Point selection iteration container */ typedef struct { - hsize_t elmt_left; /* Number of elements left to iterate over */ H5S_pnt_node_t *curr; /* Pointer to next node to output */ } H5S_point_iter_t; -/* New Hyperslab selection iteration container */ +/* Hyperslab selection iteration container */ typedef struct { /* Common fields for all hyperslab selections */ - hsize_t elmt_left; /* Number of elements left to iterate over */ hssize_t *off; /* Offset in span node (used as position for regular hyperslabs) */ unsigned iter_rank; /* Rank of iterator information */ /* (This should always be the same as the dataspace @@ -82,16 +81,40 @@ typedef struct { /* "All" selection iteration container */ typedef struct { - hsize_t elmt_left; /* Number of elements left to iterate over */ hsize_t offset; /* Next element to output */ } H5S_all_iter_t; +typedef struct H5S_sel_iter_t H5S_sel_iter_t; + +/* Method to retrieve the current coordinates of iterator for current selection */ +typedef herr_t (*H5S_sel_iter_coords_func_t)(const H5S_sel_iter_t *iter, hssize_t *coords); +/* Method to determine number of elements left in iterator for current selection */ +typedef hsize_t (*H5S_sel_iter_nelmts_func_t)(const H5S_sel_iter_t *iter); +/* Method to move selection iterator to the next element in the selection */ +typedef herr_t (*H5S_sel_iter_next_func_t)(H5S_sel_iter_t *iter, size_t nelem); +/* Method to release iterator for current selection */ +typedef herr_t (*H5S_sel_iter_release_func_t)(H5S_sel_iter_t *iter); + /* Selection iteration container */ -typedef union { - H5S_point_iter_t pnt; /* Point selection iteration information */ - H5S_hyper_iter_t hyp; /* New Hyperslab selection iteration information */ - H5S_all_iter_t all; /* "All" selection iteration information */ -} H5S_sel_iter_t; +struct H5S_sel_iter_t { + /* Information common to all iterators */ + unsigned rank; /* Rank of dataspace the selection iterator is operating on */ + hsize_t *dims; /* Dimensions of dataspace the selection is operating on */ + hsize_t elmt_left; /* Number of elements left to iterate over */ + + /* Information specific to each type of iterator */ + union { + H5S_point_iter_t pnt; /* Point selection iteration information */ + H5S_hyper_iter_t hyp; /* New Hyperslab selection iteration information */ + H5S_all_iter_t all; /* "All" selection iteration information */ + } u; + + /* Methods on selections */ + H5S_sel_iter_coords_func_t iter_coords; /* Method to retrieve the current coordinates of iterator for current selection */ + H5S_sel_iter_nelmts_func_t iter_nelmts; /* Method to determine number of elements left in iterator for current selection */ + H5S_sel_iter_next_func_t iter_next; /* Method to move selection iterator to the next element in the selection */ + H5S_sel_iter_release_func_t iter_release; /* Method to release iterator for current selection */ +}; typedef struct H5S_conv_t { H5S_sel_type ftype; @@ -105,14 +128,14 @@ typedef struct H5S_conv_t { /* Read from file to application w/o intermediate scratch buffer */ herr_t (*read)(H5F_t *f, const struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, + H5P_genplist_t *dc_plist, const union H5D_storage_t *store, size_t elmt_size, const H5S_t *file_space, const H5S_t *mem_space, hid_t dxpl_id, void *buf/*out*/); /* Write directly from app buffer to file */ herr_t (*write)(H5F_t *f, struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, + H5P_genplist_t *dc_plist, const union H5D_storage_t *store, size_t elmt_size, const H5S_t *file_space, const H5S_t *mem_space, hid_t dxpl_id, const void *buf); @@ -161,7 +184,7 @@ H5_DLL htri_t H5S_is_simple(const H5S_t *sdim); H5_DLL herr_t H5S_extent_release(H5S_t *space); H5_DLL int H5S_extend(H5S_t *space, const hsize_t *size); H5_DLL int H5S_set_extent(H5S_t *space, const hsize_t *size); -H5_DLL H5S_t *H5S_create_simple(int rank, const hsize_t dims[/*rank*/], +H5_DLL H5S_t *H5S_create_simple(unsigned rank, const hsize_t dims[/*rank*/], const hsize_t maxdims[/*rank*/]); H5_DLL herr_t H5S_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *stream, int indent, int fwidth); @@ -169,17 +192,18 @@ H5_DLL herr_t H5S_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE *stream /* Operations on selections */ H5_DLL herr_t H5S_select_copy(H5S_t *dst, const H5S_t *src); H5_DLL herr_t H5S_select_deserialize(H5S_t *space, const uint8_t *buf); +H5_DLL H5S_sel_type H5S_get_select_type(const H5S_t *space); H5_DLL htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2); -H5_DLL herr_t H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, +H5_DLL herr_t H5S_select_iterate(void *buf, hid_t type_id, const H5S_t *space, H5D_operator_t op, void *operator_data); H5_DLL herr_t H5S_select_fill(void *fill, size_t fill_size, const H5S_t *space, void *buf); H5_DLL herr_t H5S_select_fscat (H5F_t *f, struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, + H5P_genplist_t *dc_plist, const union H5D_storage_t *store, size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, hsize_t nelmts, hid_t dxpl_id, const void *_buf); H5_DLL hsize_t H5S_select_fgath (H5F_t *f, const struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, + H5P_genplist_t *dc_plist, const union H5D_storage_t *store, size_t elmt_size, const H5S_t *file_space, H5S_sel_iter_t *file_iter, hsize_t nelmts, hid_t dxpl_id, void *buf); H5_DLL herr_t H5S_select_mscat (const void *_tscat_buf, size_t elmt_size, @@ -189,19 +213,35 @@ H5_DLL hsize_t H5S_select_mgath (const void *_buf, size_t elmt_size, const H5S_t *space, H5S_sel_iter_t *iter, hsize_t nelmts, hid_t dxpl_id, void *_tgath_buf/*out*/); H5_DLL herr_t H5S_select_read(H5F_t *f, const struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, + H5P_genplist_t *dc_plist, const union H5D_storage_t *store, size_t elmt_size, const H5S_t *file_space, const H5S_t *mem_space, hid_t dxpl_id, void *buf/*out*/); H5_DLL herr_t H5S_select_write(H5F_t *f, struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, + H5P_genplist_t *dc_plist, const union H5D_storage_t *store, size_t elmt_size, const H5S_t *file_space, const H5S_t *mem_space, hid_t dxpl_id, const void *buf/*out*/); - -/* Needed for internal use of selections in H5Fistore code */ +H5_DLL herr_t H5S_select_elements (H5S_t *space, H5S_seloper_t op, + size_t num_elem, const hssize_t **coord); +#ifdef NEW_HYPERSLAB_API +H5_DLL herr_t H5S_select_select (H5S_t *space1, H5S_seloper_t op, H5S_t *space2); +#endif /*NEW_HYPERSLAB_API */ +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_select_all(H5S_t *space, unsigned rel_prev); +H5_DLL herr_t H5S_select_none(H5S_t *space); H5_DLL herr_t H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, const hssize_t start[], const hsize_t *stride, const hsize_t count[], const hsize_t *block); +H5_DLL herr_t H5S_hyper_add_span_element(H5S_t *space, unsigned rank, + hssize_t *coords); +H5_DLL herr_t H5S_hyper_reset_scratch(H5S_t *space); + +/* Operations on selection iterators */ +H5_DLL herr_t H5S_select_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size); +H5_DLL herr_t H5S_select_iter_coords(const H5S_sel_iter_t *sel_iter, hssize_t *coords); +H5_DLL hsize_t H5S_select_iter_nelmts(const H5S_sel_iter_t *sel_iter); +H5_DLL herr_t H5S_select_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); +H5_DLL herr_t H5S_select_iter_release(H5S_sel_iter_t *sel_iter); #ifdef H5_HAVE_PARALLEL /* MPI-IO function to read directly from app buffer to file rky980813 */ diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 5d921d8..5551412 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -40,7 +40,7 @@ H5FL_ARR_EXTERN(hssize_t); H5FL_ARR_DEFINE_STATIC(size_t,-1); /* Declare a free list to manage arrays of hsize_t */ -H5FL_ARR_DEFINE_STATIC(hsize_t,-1); +H5FL_ARR_EXTERN(hsize_t); /* Declare a free list to manage blocks of single datatype element data */ H5FL_BLK_EXTERN(type_elem); @@ -182,7 +182,7 @@ done: hssize_t H5Sget_select_npoints(dsid) hid_t dsid; IN: Dataspace ID of selection to query RETURNS - The number of elements in selection on success, 0 on failure + Non-negative on success/Negative on failure DESCRIPTION Returns the number of elements in current selection for dataspace. GLOBAL VARIABLES @@ -196,14 +196,14 @@ H5Sget_select_npoints(hid_t spaceid) H5S_t *space = NULL; /* Dataspace to modify selection of */ hssize_t ret_value; /* return value */ - FUNC_ENTER_API(H5Sget_select_npoints, 0); + 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, 0, "not a data space"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space"); - ret_value = (*space->select.get_npoints)(space); + ret_value = H5S_get_select_npoints(space); done: FUNC_LEAVE_API(ret_value); @@ -212,6 +212,40 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_get_select_npoints + PURPOSE + Get the number of elements in current selection + USAGE + hssize_t H5Sget_select_npoints(space) + H5S_t *space; IN: Dataspace of selection to query + RETURNS + The number of elements in selection on success, 0 on failure + DESCRIPTION + Returns the number of elements in current selection for dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hssize_t +H5S_get_select_npoints(const H5S_t *space) +{ + hssize_t ret_value; /* return value */ + + FUNC_ENTER_NOAPI(H5S_get_select_npoints, 0); + + /* Check args */ + assert(space); + + ret_value = (*space->select.get_npoints)(space); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_get_select_npoints() */ + + +/*-------------------------------------------------------------------------- + NAME H5Sselect_valid PURPOSE Check whether the selection fits within the extent, with the current @@ -243,7 +277,7 @@ H5Sselect_valid(hid_t spaceid) if (NULL == (space=H5I_object_verify(spaceid, H5I_DATASPACE))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not a data space"); - ret_value = (*space->select.is_valid)(space); + ret_value = H5S_select_valid(space); done: FUNC_LEAVE_API(ret_value); @@ -252,6 +286,42 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_select_valid + PURPOSE + Check whether the selection fits within the extent, with the current + offset defined. + USAGE + htri_t H5S_select_void(space) + H5S_t *space; IN: Dataspace to query + RETURNS + TRUE if the selection fits within the extent, FALSE if it does not and + Negative on an error. + DESCRIPTION + Determines if the current selection at the current offet fits within the + extent for the dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +htri_t +H5S_select_valid(const H5S_t *space) +{ + htri_t ret_value; /* return value */ + + FUNC_ENTER_NOAPI(H5S_select_valid, 0); + + assert(space); + + ret_value = (*space->select.is_valid)(space); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_select_valid() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_select_deserialize PURPOSE Deserialize the current selection from a user-provided buffer into a real @@ -362,6 +432,207 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_select_iter_init + PURPOSE + Initializes iteration information for a selection. + USAGE + herr_t H5S_select_iter_init(sel_iter, space, elmt_size) + H5S_sel_iter_t *sel_iter; OUT: Selection iterator to initialize. + H5S_t *space; IN: Dataspace object containing selection to + iterate over + size_t elmt_size; IN: Size of elements in the selection + RETURNS + Non-negative on success, negative on failure. + DESCRIPTION + Initialize the selection iterator object to point to the first element + in the dataspace's selection. +--------------------------------------------------------------------------*/ +herr_t +H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_size) +{ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_select_iter_init, FAIL); + + /* Check args */ + assert(sel_iter); + assert(space); + assert(elmt_size>0); + + /* Initialize common information */ + + /* Save the dataspace's rank */ + sel_iter->rank=space->extent.u.simple.rank; + + /* Allocate room for the dataspace dimensions */ + sel_iter->dims = H5FL_ARR_MALLOC(hsize_t,sel_iter->rank); + assert(sel_iter->dims); + + /* Keep a copy of the dataspace dimensions */ + HDmemcpy(sel_iter->dims,space->extent.u.simple.size,sel_iter->rank*sizeof(hsize_t)); + + /* Call initialization routine for selection type */ + ret_value= (*space->select.iter_init)(sel_iter, space, elmt_size); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_select_iter_init() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_select_iter_coords + PURPOSE + Get the coordinates of the current iterator position + USAGE + herr_t H5S_select_iter_coords(sel_iter,coords) + H5S_sel_iter_t *sel_iter; IN: Selection iterator to query + hssize_t *coords; OUT: Array to place iterator coordinates in + RETURNS + Non-negative on success, negative on failure. + DESCRIPTION + The current location of the iterator within the selection is placed in + the COORDS array. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_iter_coords (const H5S_sel_iter_t *sel_iter, hssize_t *coords) +{ + herr_t ret_value; /* return value */ + + FUNC_ENTER_NOAPI(H5S_select_iter_coords, FAIL); + + /* Check args */ + assert(sel_iter); + assert(coords); + + /* Call iter_coords routine for selection type */ + ret_value = (*sel_iter->iter_coords)(sel_iter,coords); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_select_iter_coords() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_select_iter_nelmts + PURPOSE + Get the number of elements left to iterate over in selection + USAGE + hssize_t H5S_select_iter_nelmts(sel_iter) + H5S_sel_iter_t *sel_iter; IN: Selection iterator to query + RETURNS + The number of elements in selection on success, 0 on failure + DESCRIPTION + Returns the number of elements in current selection for dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +hsize_t +H5S_select_iter_nelmts (const H5S_sel_iter_t *sel_iter) +{ + hsize_t ret_value; /* return value */ + + FUNC_ENTER_NOAPI(H5S_select_iter_nelmts, 0); + + /* Check args */ + assert(sel_iter); + + /* Call iter_nelmts routine for selection type */ + ret_value = (*sel_iter->iter_nelmts)(sel_iter); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_select_iter_nelmts() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_select_iter_next + PURPOSE + Advance seletion iterator + USAGE + herr_t H5S_select_iter_next(iter, nelem) + H5S_sel_iter_t *iter; IN/OUT: Selection iterator to change + size_t nelem; IN: Number of elements to advance by + RETURNS + Non-negative on success, negative on failure. + DESCRIPTION + Move the current element for the selection iterator to the NELEM'th next + element in the selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_iter_next(H5S_sel_iter_t *iter, size_t nelem) +{ + herr_t ret_value; /* return value */ + + FUNC_ENTER_NOAPI(H5S_select_iter_next, FAIL); + + /* Check args */ + assert(iter); + assert(nelem>0); + + /* Call iter_coords routine for selection type */ + ret_value = (*iter->iter_next)(iter,nelem); + + /* Decrement the number of elements left in selection */ + iter->elmt_left-=nelem; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_select_iter_next() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_select_iter_release + PURPOSE + Release a selection iterator's resources. + USAGE + hssize_t H5S_select_iter_release(sel_iter) + H5S_sel_iter_t *sel_iter; IN: Selection iterator to query + RETURNS + The number of elements in selection on success, 0 on failure + DESCRIPTION + Returns the number of elements in current selection for dataspace. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5S_select_iter_release(H5S_sel_iter_t *sel_iter) +{ + herr_t ret_value; /* return value */ + + FUNC_ENTER_NOAPI(H5S_select_iter_release, FAIL); + + /* Check args */ + assert(sel_iter); + + /* Release the array of dimensions common to all iterators */ + H5FL_ARR_FREE(hsize_t,sel_iter->dims); + + /* Call selection type-specific release routine */ + ret_value = (*sel_iter->iter_release)(sel_iter); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* H5S_select_iter_release() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_select_iterate PURPOSE Iterate over the selected elements in a memory buffer. @@ -389,7 +660,7 @@ done: the selection is not modified. --------------------------------------------------------------------------*/ herr_t -H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, +H5S_select_iterate(void *buf, hid_t type_id, const H5S_t *space, H5D_operator_t op, void *operator_data) { H5T_t *dt; /* Datatype structure */ @@ -441,7 +712,7 @@ H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, HGOTO_ERROR(H5E_DATATYPE, H5E_BADSIZE, FAIL, "datatype size invalid"); /* Initialize iterator */ - if ((*space->select.iter_init)(space, elmt_size, &iter)<0) + 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 */ @@ -509,7 +780,7 @@ H5S_select_iterate(void *buf, hid_t type_id, H5S_t *space, H5D_operator_t op, done: /* Release selection iterator */ if(iter_init) { - if ((*space->select.iter_release)(&iter)<0) + if (H5S_select_iter_release(&iter)<0) HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ @@ -530,7 +801,7 @@ done: Retrieve the type of selection in a dataspace USAGE H5S_sel_type H5Sget_select_type(space_id) - hid_t space_id; IN: Dataspace object to reset + hid_t space_id; IN: Dataspace object to query RETURNS Non-negative on success/Negative on failure. Return value is from the set of values in the H5S_sel_type enumerated type. @@ -552,7 +823,7 @@ H5Sget_select_type(hid_t space_id) HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, H5S_SEL_ERROR, "not a data space"); /* Set return value */ - ret_value=space->select.type; + ret_value=H5S_get_select_type(space); done: FUNC_LEAVE_API(ret_value); @@ -561,6 +832,39 @@ done: /*-------------------------------------------------------------------------- NAME + H5S_get_select_type + PURPOSE + Retrieve the type of selection in a dataspace + USAGE + H5S_sel_type H5Sget_select_type(space) + const H5S_t *space; IN: Dataspace object to query + RETURNS + Non-negative on success/Negative on failure. Return value is from the + set of values in the H5S_sel_type enumerated type. + DESCRIPTION + This function retrieves the type of selection currently defined for + a dataspace. +--------------------------------------------------------------------------*/ +H5S_sel_type +H5S_get_select_type(const H5S_t *space) +{ + H5S_sel_type ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_get_select_type, H5S_SEL_ERROR); + + /* Check args */ + assert(space); + + /* Set return value */ + ret_value=space->select.type; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5S_get_select_type() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_select_shape_same PURPOSE Check if two selections are the same shape @@ -745,7 +1049,7 @@ H5S_select_fill(void *_fill, size_t fill_size, const H5S_t *space, void *_buf) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); /* Initialize iterator */ - if ((*space->select.iter_init)(space, fill_size, &iter)<0) + if (H5S_select_iter_init(&iter, space, fill_size)<0) HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); iter_init=1; /* Selection iteration info has been initialized */ @@ -780,7 +1084,7 @@ H5S_select_fill(void *_fill, size_t fill_size, const H5S_t *space, void *_buf) done: /* Release selection iterator */ if(iter_init) { - if ((*space->select.iter_release)(&iter)<0) + if (H5S_select_iter_release(&iter)<0) HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ @@ -818,13 +1122,17 @@ done: */ herr_t H5S_select_fscat (H5F_t *f, struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, - const H5S_t *space, H5S_sel_iter_t *iter, hsize_t nelmts, - hid_t dxpl_id, const void *_buf) + H5P_genplist_t *dc_plist, const H5D_storage_t *store, + size_t elmt_size, const H5S_t *space, H5S_sel_iter_t *iter, + hsize_t nelmts, hid_t dxpl_id, const void *_buf) { const uint8_t *buf=_buf; /* Alias for pointer arithmetic */ hsize_t *off=NULL; /* Array to store 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=NULL; /* Array to store sequence lengths */ + size_t mem_len; /* Length of sequence in memory */ ssize_t vector_size; /* Value for vector size */ size_t maxbytes; /* Number of bytes in the buffer */ size_t nseq; /* Number of sequences generated */ @@ -837,7 +1145,7 @@ H5S_select_fscat (H5F_t *f, struct H5O_layout_t *layout, assert (f); assert (layout); assert (elmt_size>0); - assert (efl); + assert (store); assert (space); assert (iter); assert (nelmts>0); @@ -863,8 +1171,13 @@ H5S_select_fscat (H5F_t *f, struct H5O_layout_t *layout, if((*space->select.get_seq_list)(space,H5S_GET_SEQ_LIST_SORTED,iter,elmt_size,(size_t)vector_size,maxbytes,&nseq,&nbytes,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; + mem_len=nbytes; + mem_off=0; + /* Write sequence list out */ - if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, efl, space, elmt_size, nseq, len, off, buf)<0) + if (H5F_seq_writevv(f, dxpl_id, layout, dc_plist, store, nseq, &dset_curr_seq, len, off, 1, &mem_curr_seq, &mem_len, &mem_off, buf)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error"); /* Update buffer */ @@ -909,13 +1222,17 @@ done: */ hsize_t H5S_select_fgath (H5F_t *f, const struct H5O_layout_t *layout, - H5P_genplist_t *dc_plist, const H5O_efl_t *efl, size_t elmt_size, - const H5S_t *space, H5S_sel_iter_t *iter, hsize_t nelmts, - hid_t dxpl_id, void *_buf/*out*/) + H5P_genplist_t *dc_plist, const H5D_storage_t *store, + size_t elmt_size, const H5S_t *space, H5S_sel_iter_t *iter, + hsize_t nelmts, hid_t dxpl_id, void *_buf/*out*/) { uint8_t *buf=_buf; /* Alias for pointer arithmetic */ hsize_t *off=NULL; /* Array to store 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=NULL; /* Array to store sequence lengths */ + size_t mem_len; /* Length of sequence in memory */ ssize_t vector_size; /* Value for vector size */ size_t maxbytes; /* Number of bytes in the buffer */ size_t nseq; /* Number of sequences generated */ @@ -928,7 +1245,7 @@ H5S_select_fgath (H5F_t *f, const struct H5O_layout_t *layout, assert (f); assert (layout); assert (elmt_size>0); - assert (efl); + assert (store); assert (space); assert (iter); assert (nelmts>0); @@ -953,8 +1270,13 @@ H5S_select_fgath (H5F_t *f, const struct H5O_layout_t *layout, if((*space->select.get_seq_list)(space,H5S_GET_SEQ_LIST_SORTED,iter,elmt_size,(size_t)vector_size,maxbytes,&nseq,&nbytes,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; + mem_len=nbytes; + mem_off=0; + /* Read sequence list in */ - if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, efl, space, elmt_size, nseq, len, off, buf)<0) + if (H5F_seq_readvv(f, dxpl_id, layout, dc_plist, store, nseq, &dset_curr_seq, len, off, 1, &mem_curr_seq, &mem_len, &mem_off, buf)<0) HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, 0, "read error"); /* Update buffer */ @@ -1166,14 +1488,13 @@ done: */ herr_t H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, - const H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space, - const H5S_t *mem_space, hid_t dxpl_id, void *_buf/*out*/) + const H5D_storage_t *store, size_t elmt_size, const H5S_t *file_space, + const H5S_t *mem_space, hid_t dxpl_id, void *buf/*out*/) { 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 */ - uint8_t *buf=NULL; /* Local buffer pointer, for address arithmetic */ hsize_t *mem_off=NULL; /* Array to store sequence offsets in memory */ hsize_t *file_off=NULL; /* Array to store sequence offsets in the file */ ssize_t vector_size; /* Value for vector size */ @@ -1186,20 +1507,26 @@ H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, size_t file_nbytes; /* Number of bytes 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 */ - size_t tmp_file_len; /* Temporary number of bytes in file sequence */ - unsigned partial_file; /* Whether a partial file sequence was accessed */ - size_t orig_file_len=0; /* Original file sequence length for partial file access */ - size_t orig_file_seq; /* Original file sequence to operate on */ - size_t tot_file_seq; /* Number of file sequences to access */ + ssize_t tmp_file_len; /* Temporary number of bytes in file sequence */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5S_select_read, FAIL); /* Check args */ assert(f); - assert(efl); - assert(_buf); + assert(store); + assert(buf); assert(TRUE==H5P_isa_class(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 */ /* Get the hyperslab vector size */ if((vector_size=H5S_get_vector_size(dxpl_id))<0) @@ -1215,16 +1542,6 @@ H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, if((file_off = H5FL_ARR_MALLOC(hsize_t,(size_t)vector_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); - /* Initialize file iterator */ - if ((*file_space->select.iter_init)(file_space, elmt_size, &file_iter)<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 ((*mem_space->select.iter_init)(mem_space, elmt_size, &mem_iter)<0) - HGOTO_ERROR (H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator"); - mem_iter_init=1; /* Memory selection iteration info has been initialized */ - /* Get number of bytes in selection */ #ifndef NDEBUG { @@ -1259,115 +1576,29 @@ H5S_select_read(H5F_t *f, const H5O_layout_t *layout, H5P_genplist_t *dc_plist, /* Start at the beginning of the sequences again */ curr_mem_seq=0; - - /* Set the buffer pointer using the first sequence */ - H5_CHECK_OVERFLOW(mem_off[0],hsize_t,size_t); - buf=(uint8_t *)_buf+(size_t)mem_off[0]; } /* end if */ - /* Check if current file sequence will fit into current memory sequence */ - if(mem_len[curr_mem_seq]>=file_len[curr_file_seq]) { - /* Save the current number file sequence */ - orig_file_seq=curr_file_seq; - - /* Determine how many file sequences will fit into current memory sequence */ - tmp_file_len=0; - tot_file_seq=0; - while( curr_file_seq<file_nseq && (tmp_file_len+file_len[curr_file_seq])<=mem_len[curr_mem_seq] ) { - tmp_file_len+=file_len[curr_file_seq]; - curr_file_seq++; - tot_file_seq++; - } /* end while */ - - /* Check for partial file sequence */ - if(tmp_file_len<mem_len[curr_mem_seq] && curr_file_seq<file_nseq) { - /* Get the original file sequence length */ - orig_file_len=file_len[curr_file_seq]; - - /* Make the last file sequence a partial access */ - file_len[curr_file_seq]=mem_len[curr_mem_seq]-tmp_file_len; - - /* Increase the number of bytes to access */ - tmp_file_len=mem_len[curr_mem_seq]; - - /* Indicate that there is an extra sequence to include in the file access */ - tot_file_seq++; - - /* Indicate a partial file sequence */ - partial_file=1; - } /* end if */ - else - partial_file=0; - - /* Read file sequences into current memory sequence */ - if (H5F_seq_readv(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, tot_file_seq, &file_len[orig_file_seq], &file_off[orig_file_seq], buf)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error"); - - /* Update last file sequence, if it was partially accessed */ - if(partial_file) { - file_off[curr_file_seq]+=orig_file_len-file_len[curr_file_seq]; - file_len[curr_file_seq]=orig_file_len-file_len[curr_file_seq]; - } /* end if */ - - /* Check if the current memory sequence was only partially accessed */ - if(tmp_file_len<mem_len[curr_mem_seq]) { - /* Adjust current memory sequence */ - mem_off[curr_mem_seq]+=tmp_file_len; - mem_len[curr_mem_seq]-=tmp_file_len; - - /* Adjust memory buffer pointer */ - buf+=tmp_file_len; - } /* end if */ - else { - /* Must have used entire memory sequence, advance to next one */ - curr_mem_seq++; - - /* Check if it is valid to adjust buffer pointer */ - if(curr_mem_seq<mem_nseq) { - H5_CHECK_OVERFLOW(mem_off[curr_mem_seq],hsize_t,size_t); - buf=(uint8_t *)_buf+(size_t)mem_off[curr_mem_seq]; - } /* end if */ - } /* end else */ + /* Read file sequences into current memory sequence */ + if ((tmp_file_len=H5F_seq_readvv(f, dxpl_id, layout, dc_plist, store, + file_nseq, &curr_file_seq, file_len, file_off, + mem_nseq, &curr_mem_seq, mem_len, mem_off, + buf))<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error"); - /* Decrement number of bytes left to process */ - maxbytes-=tmp_file_len; - } /* end if */ - else { - /* Save number of bytes to access */ - tmp_file_len=mem_len[curr_mem_seq]; - - /* Read part of current file sequence into current memory sequence */ - if (H5F_seq_read(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, tmp_file_len, file_off[curr_file_seq], buf)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_READERROR, FAIL, "read error"); - - /* Update current file sequence information */ - file_off[curr_file_seq]+=tmp_file_len; - file_len[curr_file_seq]-=tmp_file_len; - - /* Increment memory sequence */ - curr_mem_seq++; - - /* Check if it is valid to adjust buffer pointer */ - if(curr_mem_seq<mem_nseq) { - H5_CHECK_OVERFLOW(mem_off[curr_mem_seq],hsize_t,size_t); - buf=(uint8_t *)_buf+(size_t)mem_off[curr_mem_seq]; - } /* end if */ - - /* Decrement number of bytes left to process */ - maxbytes-=tmp_file_len; - } /* end else */ + /* Decrement number of bytes left to process */ + maxbytes-=tmp_file_len; } /* end while */ done: /* Release file selection iterator */ if(file_iter_init) { - if ((*file_space->select.iter_release)(&file_iter)<0) + 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 ((*mem_space->select.iter_release)(&mem_iter)<0) + if (H5S_select_iter_release(&mem_iter)<0) HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ @@ -1400,14 +1631,13 @@ done: */ herr_t H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, - const H5O_efl_t *efl, size_t elmt_size, const H5S_t *file_space, - const H5S_t *mem_space, hid_t dxpl_id, const void *_buf/*out*/) + const H5D_storage_t *store, size_t elmt_size, const H5S_t *file_space, + const H5S_t *mem_space, hid_t dxpl_id, const void *buf/*out*/) { 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 */ - const uint8_t *buf=NULL; /* Local buffer pointer, for address arithmetic */ hsize_t *mem_off=NULL; /* Array to store sequence offsets in memory */ hsize_t *file_off=NULL; /* Array to store sequence offsets in the file */ ssize_t vector_size; /* Value for vector size */ @@ -1420,21 +1650,17 @@ H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, size_t file_nbytes; /* Number of bytes 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 */ - size_t tmp_file_len; /* Temporary number of bytes in file sequence */ - unsigned partial_file; /* Whether a partial file sequence was accessed */ - size_t orig_file_len=0; /* Original file sequence length for partial file access */ - size_t orig_file_seq; /* Original file sequence to operate on */ - size_t tot_file_seq; /* Number of file sequences to access */ + ssize_t tmp_file_len; /* Temporary number of bytes in file sequence */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5S_select_write, FAIL); /* Check args */ assert(f); - assert(efl); - assert(_buf); + assert(store); + assert(buf); assert(TRUE==H5P_isa_class(dxpl_id,H5P_DATASET_XFER)); - + /* Get the hyperslab vector size */ if((vector_size=H5S_get_vector_size(dxpl_id))<0) HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get I/O vector size"); @@ -1450,15 +1676,15 @@ H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate I/O offset vector array"); /* Initialize file iterator */ - if ((*file_space->select.iter_init)(file_space, elmt_size, &file_iter)<0) + 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 ((*mem_space->select.iter_init)(mem_space, elmt_size, &mem_iter)<0) + 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 */ - + /* Get number of bytes in selection */ #ifndef NDEBUG { @@ -1493,115 +1719,29 @@ H5S_select_write(H5F_t *f, H5O_layout_t *layout, H5P_genplist_t *dc_plist, /* Start at the beginning of the sequences again */ curr_mem_seq=0; - - /* Set the buffer pointer using the first sequence */ - H5_CHECK_OVERFLOW(mem_off[0],hsize_t,size_t); - buf=(const uint8_t *)_buf+(size_t)mem_off[0]; } /* end if */ - /* Check if current file sequence will fit into current memory sequence */ - if(mem_len[curr_mem_seq]>=file_len[curr_file_seq]) { - /* Save the current number file sequence */ - orig_file_seq=curr_file_seq; - - /* Determine how many file sequences will fit into current memory sequence */ - tmp_file_len=0; - tot_file_seq=0; - while( curr_file_seq<file_nseq && (tmp_file_len+file_len[curr_file_seq])<=mem_len[curr_mem_seq] ) { - tmp_file_len+=file_len[curr_file_seq]; - curr_file_seq++; - tot_file_seq++; - } /* end while */ - - /* Check for partial file sequence */ - if(tmp_file_len<mem_len[curr_mem_seq] && curr_file_seq<file_nseq) { - /* Get the original file sequence length */ - orig_file_len=file_len[curr_file_seq]; - - /* Make the last file sequence a partial access */ - file_len[curr_file_seq]=mem_len[curr_mem_seq]-tmp_file_len; - - /* Increase the number of bytes to access */ - tmp_file_len=mem_len[curr_mem_seq]; - - /* Indicate that there is an extra sequence to include in the file access */ - tot_file_seq++; - - /* Indicate a partial file sequence */ - partial_file=1; - } /* end if */ - else - partial_file=0; - - /* Write current memory sequence into file sequences */ - if (H5F_seq_writev(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, tot_file_seq, &file_len[orig_file_seq], &file_off[orig_file_seq], buf)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error"); - - /* Update last file sequence, if it was partially accessed */ - if(partial_file) { - file_off[curr_file_seq]+=orig_file_len-file_len[curr_file_seq]; - file_len[curr_file_seq]=orig_file_len-file_len[curr_file_seq]; - } /* end if */ - - /* Check if the current memory sequence was only partially accessed */ - if(tmp_file_len<mem_len[curr_mem_seq]) { - /* Adjust current memory sequence */ - mem_off[curr_mem_seq]+=tmp_file_len; - mem_len[curr_mem_seq]-=tmp_file_len; - - /* Adjust memory buffer pointer */ - buf+=tmp_file_len; - } /* end if */ - else { - /* Must have used entire memory sequence, advance to next one */ - curr_mem_seq++; - - /* Check if it is valid to adjust buffer pointer */ - if(curr_mem_seq<mem_nseq) { - H5_CHECK_OVERFLOW(mem_off[curr_mem_seq],hsize_t,size_t); - buf=(const uint8_t *)_buf+(size_t)mem_off[curr_mem_seq]; - } /* end if */ - } /* end else */ + /* Write memory sequences into file sequences */ + if ((tmp_file_len=H5F_seq_writevv(f, dxpl_id, layout, dc_plist, store, + file_nseq, &curr_file_seq, file_len, file_off, + mem_nseq, &curr_mem_seq, mem_len, mem_off, + buf))<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error"); - /* Decrement number of bytes left to process */ - maxbytes-=tmp_file_len; - } /* end if */ - else { - /* Save number of bytes to access */ - tmp_file_len=mem_len[curr_mem_seq]; - - /* Write part of current memory sequence to current file sequence */ - if (H5F_seq_write(f, dxpl_id, layout, dc_plist, efl, file_space, elmt_size, tmp_file_len, file_off[curr_file_seq], buf)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_WRITEERROR, FAIL, "write error"); - - /* Update current file sequence information */ - file_off[curr_file_seq]+=tmp_file_len; - file_len[curr_file_seq]-=tmp_file_len; - - /* Increment memory sequence */ - curr_mem_seq++; - - /* Check if it is valid to adjust buffer pointer */ - if(curr_mem_seq<mem_nseq) { - H5_CHECK_OVERFLOW(mem_off[curr_mem_seq],hsize_t,size_t); - buf=(const uint8_t *)_buf+(size_t)mem_off[curr_mem_seq]; - } /* end if */ - - /* Decrement number of bytes left to process */ - maxbytes-=tmp_file_len; - } /* end else */ + /* Decrement number of bytes left to process */ + maxbytes-=tmp_file_len; } /* end while */ done: /* Release file selection iterator */ if(file_iter_init) { - if ((*file_space->select.iter_release)(&file_iter)<0) + 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 ((*mem_space->select.iter_release)(&mem_iter)<0) + if (H5S_select_iter_release(&mem_iter)<0) HDONE_ERROR (H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator"); } /* end if */ @@ -959,7 +959,49 @@ done: /*------------------------------------------------------------------------- - * Function: H5V_array_offset + * Function: H5V_array_down + * + * Purpose: Given a set of dimension sizes, calculate the size of each + * "down" slice. This is the size of the dimensions for all the + * dimensions below the current one, which is used for indexing + * offsets in this dimension. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, April 28, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5V_array_down(unsigned n, const hsize_t *total_size, hsize_t *down) +{ + hsize_t acc; /*accumulator */ + int i; /*counter */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5V_array_down, FAIL); + + assert(n <= H5V_HYPER_NDIMS); + assert(total_size); + assert(down); + + /* Build the sizes of each dimension in the array */ + /* (From fastest to slowest) */ + for(i=n-1,acc=1; i>=0; i--) { + down[i]=acc; + acc *= total_size[i]; + } /* end for */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5V_array_down() */ + + +/*------------------------------------------------------------------------- + * Function: H5V_array_offset_pre * * Purpose: Given a coordinate description of a location in an array, this * function returns the byte offset of the coordinate. @@ -975,33 +1017,293 @@ done: * Tuesday, June 22, 1999 * * Modifications: + * Use precomputed accumulator array + * Quincey Koziol + * Saturday, April 26, 2003 * *------------------------------------------------------------------------- */ hsize_t -H5V_array_offset(unsigned n, const hsize_t *total_size, const hssize_t *offset) +H5V_array_offset_pre(unsigned n, const hsize_t *total_size, const hsize_t *acc, const hssize_t *offset) { hsize_t skip; /*starting point byte offset */ - hsize_t acc; /*accumulator */ - int i; /*counter */ + int i; /*counter */ hsize_t ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5V_array_offset, (HDabort(), 0)); + FUNC_ENTER_NOAPI(H5V_array_offset_pre, (HDabort(), 0)); assert(n <= H5V_HYPER_NDIMS); assert(total_size); + assert(acc); assert(offset); - /* others */ - for (i=(int)(n-1), acc=1, skip=0; i>=0; --i) { - skip += acc * offset[i]; - acc *= total_size[i]; - } /* end for */ + /* Compute offset in array */ + for (i=(int)(n-1), skip=0; i>=0; --i) + skip += acc[i] * offset[i]; /* Set return value */ ret_value=skip; done: FUNC_LEAVE_NOAPI(ret_value); +} /* end H5V_array_offset_pre() */ + + +/*------------------------------------------------------------------------- + * Function: H5V_array_offset + * + * Purpose: Given a coordinate description of a location in an array, this + * function returns the byte offset of the coordinate. + * + * The dimensionality of the whole array, and the offset is N. + * The whole array dimensions are TOTAL_SIZE and the coordinate + * is at offset OFFSET. + * + * Return: Success: Byte offset from beginning of array to element offset + * Failure: abort() -- should never fail + * + * Programmer: Quincey Koziol + * Tuesday, June 22, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hsize_t +H5V_array_offset(unsigned n, const hsize_t *total_size, const hssize_t *offset) +{ + hsize_t acc_arr[H5V_HYPER_NDIMS]; /* Accumulated size of down dimensions */ + hsize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5V_array_offset, (HDabort(), 0)); + + assert(n <= H5V_HYPER_NDIMS); + assert(total_size); + assert(offset); + + /* Build the sizes of each dimension in the array */ + if(H5V_array_down(n,total_size,acc_arr)<0) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADVALUE, UFAIL, "can't compute down sizes"); + + /* Set return value */ + ret_value=H5V_array_offset_pre(n,total_size,acc_arr,offset); + +done: + FUNC_LEAVE_NOAPI(ret_value); } /* end H5V_array_offset() */ + +/*------------------------------------------------------------------------- + * Function: H5V_array_calc + * + * Purpose: Given a linear offset in an array and the dimensions of that + * array, this function computes the coordinates of that offset + * in the array. + * + * The dimensionality of the whole array, and the coordinates is N. + * The array dimensions are TOTAL_SIZE and the coordinates + * are returned in COORD. The linear offset is in OFFSET. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Wednesday, April 16, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5V_array_calc(hsize_t offset, unsigned n, const hsize_t *total_size, hssize_t *coords) +{ + hsize_t idx[H5V_HYPER_NDIMS]; /* Size of each dimension in bytes */ + hsize_t acc; /* Size accumulator */ + unsigned u; /* Local index variable */ + int i; /* Local index variable */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5V_array_calc, FAIL); + + /* Sanity check */ + assert(n <= H5V_HYPER_NDIMS); + assert(total_size); + assert(coords); + + /* Build the sizes of each dimension in the array */ + /* (From fastest to slowest) */ + for(i=n-1,acc=1; i>=0; i--) { + idx[i]=acc; + acc *= total_size[i]; + } /* end for */ + + /* Compute the coordinates from the offset */ + for(u=0; u<n; u++) { + coords[u]=offset/idx[u]; + offset %= idx[u]; + } /* end for */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5V_array_calc() */ + + +/*------------------------------------------------------------------------- + * Function: H5V_chunk_index + * + * Purpose: Given a coordinate offset (COORD), the size of each chunk + * (CHUNK), the number of chunks in each dimension (NCHUNKS) + * and the number of dimensions of all of these (NDIMS), calculate + * a "chunk index" for the chunk that the coordinate offset is + * located in. + * + * The chunk index starts at 0 and increases according to the + * fastest changing dimension, then the next fastest, etc. + * + * For example, with a 3x5 chunk size and 6 chunks in the fastest + * changing dimension and 3 chunks in the slowest changing + * dimension, the chunk indices are as follows: + * + * +-----+-----+-----+-----+-----+-----+ + * | | | | | | | + * | 0 | 1 | 2 | 3 | 4 | 5 | + * | | | | | | | + * +-----+-----+-----+-----+-----+-----+ + * | | | | | | | + * | 6 | 7 | 8 | 9 | 10 | 11 | + * | | | | | | | + * +-----+-----+-----+-----+-----+-----+ + * | | | | | | | + * | 12 | 13 | 14 | 15 | 16 | 17 | + * | | | | | | | + * +-----+-----+-----+-----+-----+-----+ + * + * The chunk index is placed in the CHUNK_IDX location for return + * from this function + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Monday, April 21, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5V_chunk_index(unsigned ndims, const hssize_t *coord, const hsize_t *chunk, + const hsize_t *nchunks, const hsize_t *down_nchunks, hsize_t *chunk_idx) +{ + hssize_t scaled_coord[H5V_HYPER_NDIMS]; /* Scaled, coordinates, in terms of chunks */ + unsigned u; /* Local index variable */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5V_chunk_index, FAIL); + + /* Sanity check */ + assert(ndims <= H5V_HYPER_NDIMS); + assert(coord); + assert(chunk); + assert(nchunks); + assert(chunk_idx); + + /* Compute the scaled coordinates for actual coordinates */ + for(u=0; u<ndims; u++) + scaled_coord[u]=coord[u]/chunk[u]; + + /* Compute the chunk index */ + *chunk_idx=H5V_array_offset_pre(ndims,nchunks,down_nchunks,scaled_coord); + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5V_chunk_index() */ + + +/*------------------------------------------------------------------------- + * Function: H5V_memcpyvv + * + * Purpose: Given source and destination buffers in memory (SRC & DST) + * copy sequences of from the source buffer into the destination + * buffer. Each set of sequnces has an array of lengths, an + * array of offsets, the maximum number of sequences and the + * current sequence to start at in the sequence. + * + * There may be different numbers of bytes in the source and + * destination sequences, data copying stops when either the + * source or destination buffer runs out of sequence information. + * + * Return: Non-negative # of bytes copied on success/Negative on failure + * + * Programmer: Quincey Koziol + * Friday, May 2, 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +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, + size_t src_max_nseq, size_t *src_curr_seq, size_t src_len_arr[], hsize_t src_off_arr[]) +{ + unsigned char *dst; /* Destination buffer pointer */ + const unsigned char *src; /* Source buffer pointer */ + size_t size; /* Size of sequence in bytes */ + size_t u,v; /* Local index variables */ + ssize_t ret_value=0; /* Return value */ + + FUNC_ENTER_NOAPI(H5V_memcpyvv, FAIL); + + /* Sanity check */ + assert(_dst); + assert(dst_curr_seq); + assert(*dst_curr_seq<dst_max_nseq); + assert(dst_len_arr); + assert(dst_off_arr); + assert(_src); + assert(src_curr_seq); + assert(*src_curr_seq<src_max_nseq); + assert(src_len_arr); + assert(src_off_arr); + + /* Work through all the sequences */ + for(u=*dst_curr_seq, v=*src_curr_seq; u<dst_max_nseq && v<src_max_nseq; ) { + /* Choose smallest buffer to write */ + if(src_len_arr[v]<dst_len_arr[u]) + size=src_len_arr[v]; + else + size=dst_len_arr[u]; + + /* Compute offset on disk */ + dst=(unsigned char *)_dst+dst_off_arr[u]; + + /* Compute offset in memory */ + src=(const unsigned char *)_src+src_off_arr[v]; + + /* Copy data */ + HDmemcpy(dst,src,size); + + /* Update source information */ + src_len_arr[v]-=size; + src_off_arr[v]+=size; + if(src_len_arr[v]==0) + v++; + + /* Update destination information */ + dst_len_arr[u]-=size; + dst_off_arr[u]+=size; + if(dst_len_arr[u]==0) + u++; + + /* Increment number of bytes copied */ + ret_value+=size; + } /* end for */ + + /* Update current sequence vectors */ + *dst_curr_seq=u; + *src_curr_seq=v; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5V_memcpyvv() */ + diff --git a/src/H5Vprivate.h b/src/H5Vprivate.h index a6f67ba..3840075 100644 --- a/src/H5Vprivate.h +++ b/src/H5Vprivate.h @@ -83,8 +83,21 @@ H5_DLL herr_t H5V_stride_optimize2(unsigned *np, hsize_t *elmt_size, hssize_t *stride2); H5_DLL herr_t H5V_array_fill(void *_dst, const void *src, size_t size, size_t count); +H5_DLL herr_t H5V_array_down(unsigned n, const hsize_t *total_size, + hsize_t *down); +H5_DLL hsize_t H5V_array_offset_pre(unsigned n, const hsize_t *total_size, + const hsize_t *acc, const hssize_t *offset); H5_DLL hsize_t H5V_array_offset(unsigned n, const hsize_t *total_size, - const hssize_t *offset); + const hssize_t *offset); +H5_DLL herr_t H5V_array_calc(hsize_t offset, unsigned n, + const hsize_t *total_size, hssize_t *coords); +H5_DLL herr_t H5V_chunk_index(unsigned ndims, const hssize_t *coord, + const hsize_t *chunk, const hsize_t *nchunks, 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, + size_t src_max_nseq, size_t *src_curr_seq, size_t src_len_arr[], hsize_t src_off_arr[]); /*------------------------------------------------------------------------- @@ -529,7 +529,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.nfilters > 0) { - int chunk_ndims; /* # of chunk dimensions */ + unsigned chunk_ndims; /* # of chunk dimensions */ hsize_t chunk_size[H5O_LAYOUT_NDIMS]; /* Size of chunk dimensions */ H5S_t *space; /* Dataspace describing chunk */ hid_t space_id; /* ID for dataspace describing chunk */ diff --git a/src/Makefile.in b/src/Makefile.in index 03f4cf8..b0e43e7 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -28,21 +28,21 @@ LIB=libhdf5.la CLEAN=libhdf5.settings ## Source and object files for the library (lexicographically)... -LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5D.c H5E.c H5F.c H5Farray.c H5Fcontig.c \ - H5Fcompact.c H5Fistore.c H5Fseq.c H5FD.c H5FDcore.c H5FDfamily.c \ - H5FDfphdf5.c H5FDgass.c H5FDlog.c H5FDmpio.c H5FDmpiposix.c \ - H5FDmulti.c H5FDsec2.c H5FDsrb.c H5FDstdio.c H5FDstream.c H5FL.c \ - H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c H5G.c H5Gent.c \ - H5Gnode.c H5Gstab.c H5HG.c H5HL.c H5HP.c H5I.c H5MF.c H5MM.c H5O.c \ - H5Oattr.c H5Obogus.c H5Ocont.c H5Odtype.c H5Oefl.c H5Ofill.c \ - H5Olayout.c H5Omtime.c H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c \ - H5Oshared.c H5Ostab.c H5P.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c \ - H5R.c H5RS.c H5S.c H5Sall.c H5Shyper.c H5Smpio.c H5Snone.c \ - H5Spoint.c H5Sselect.c H5ST.c H5T.c H5Tarray.c H5Tbit.c H5Tcommit.c \ - H5Tcompound.c H5Tconv.c H5Tcset.c H5Tenum.c H5Tfields.c H5Tfixed.c \ - H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Topaque.c H5Torder.c \ - H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvlen.c H5TB.c H5TS.c H5V.c H5Z.c \ - H5Zdeflate.c H5Zfletcher32.c H5Zshuffle.c H5Zszip.c +LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5D.c H5Dio.c H5E.c H5F.c H5Fcontig.c \ + H5Fcompact.c H5Fistore.c H5Fseq.c H5FD.c H5FDcore.c \ + H5FDfamily.c H5FDfphdf5.c H5FDgass.c H5FDlog.c H5FDmpio.c \ + H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDsrb.c H5FDstdio.c \ + H5FDstream.c H5FL.c H5FO.c H5FP.c H5FPclient.c H5FPserver.c H5FS.c \ + H5G.c H5Gent.c H5Gnode.c H5Gstab.c H5HG.c H5HL.c H5HP.c H5I.c H5MF.c \ + H5MM.c H5O.c H5Oattr.c H5Obogus.c H5Ocont.c H5Odtype.c H5Oefl.c \ + H5Ofill.c H5Olayout.c H5Omtime.c H5Oname.c H5Onull.c H5Opline.c \ + H5Osdspace.c H5Oshared.c H5Ostab.c H5P.c H5Pdcpl.c H5Pdxpl.c \ + H5Pfapl.c H5Pfcpl.c H5R.c H5RS.c H5S.c H5Sall.c H5Shyper.c H5Smpio.c \ + H5Snone.c H5Spoint.c H5Sselect.c H5ST.c H5T.c H5Tarray.c H5Tbit.c \ + H5Tcommit.c H5Tcompound.c H5Tconv.c H5Tcset.c H5Tenum.c H5Tfields.c \ + H5Tfixed.c H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Topaque.c \ + H5Torder.c H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvlen.c H5TB.c H5TS.c \ + H5V.c H5Z.c H5Zdeflate.c H5Zfletcher32.c H5Zshuffle.c H5Zszip.c LIB_OBJ=$(LIB_SRC:.c=.lo) @@ -64,7 +64,7 @@ PRIVATE_HDR=H5private.h H5Aprivate.h H5Apkg.h H5ACprivate.h H5Bprivate.h \ H5FOprivate.h H5FPprivate.h H5FSprivate.h H5Gprivate.h H5Gpkg.h \ H5HGprivate.h H5HLprivate.h H5HPprivate.h H5Iprivate.h H5MFprivate.h \ H5MMprivate.h H5Oprivate.h H5Opkg.h H5Pprivate.h H5Ppkg.h \ - H5Rprivate.h H5RSprivate.h H5Sprivate.h H5STprivate.h \ + H5Rprivate.h H5RSprivate.h H5Sprivate.h H5STprivate.h \ H5Tprivate.h H5TBprivate.h H5Tpkg.h H5TSprivate.h H5Vprivate.h \ H5Zprivate.h H5Zpkg.h H5config.h |