diff options
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 |