1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
 void *
 ss_blob_read(ss_blob_t *blob,                   /* The blob from which data should be read. This is the blob's top scope for
                                                  * tasks that are participating for collectivity and are members of the blob's
                                                  * file communicator but not the blob's scope communicator. */
              hid_t iospace,                     /* This is an optional hyperslab describing the part of the blob that is to
                                                  * be read. The extent and selection are relative to the portion of the
                                                  * dataset owned by the blob and described in some previous call to
                                                  * ss_blob_bind_f() (perhaps in an earlier execution). If not specified then
                                                  * all of the blob's data is read. Such a selection is generally constructed
                                                  * by calling ss_blob_space() and applying the selection. */
              unsigned flags,                    /* Various bit flags commonly passed to this function. */
              ss_prop_t UNUSED *props            /* See [Blob Properties]. (Unused at this time.) */
              )
 {
     SS_ENTER(ss_blob_read, voidP);
     ss_scope_t          topscope=SS_SCOPE_NULL; /* The top scope for BLOB */
     ss_gblob_t          *gblob=NULL;            /* Global blob record for the file */
     size_t              d_idx=SS_NOSIZE;        /* Index into gblob->d table */
     void                *buffer=NULL;           /* Result buffer */
     hid_t               iom=-1, iof=-1;         /* Data spaces for memory and file -- extent and selections */
     hid_t               dxpl=-1;                /* Dataset transfer property list -- not copied here so do not close */
     hid_t               mtype=-1;               /* Memory datatype saved after unbind */
     herr_t              status;                 /* Return status of called functions */
     size_t              tsize=SS_NOSIZE;        /* Datatype size in bytes */
     hssize_t            nelmts;                 /* Number of elements in the I/O operation */

     if (!ss_mpi_extras((ss_pers_t**)&blob, &topscope)) SS_ERROR(FAILED);
     gblob = SS_GFILE_LINK(&topscope)->gblob;

     if (blob) {
         /* Verify data space consistency to the extent possible without actually calling H5Dread(). This also generates the
          * dataset-dimension data spaces for memory and file. We have to do this before unbinding the memory but we still want
          * to unbind it if necessary. So the error return is delayed until after the unbinding. */
         if ((status = ss_blob_ckspaces(blob, iospace, &iom, &iof))<0) SS_SAVE;

         /* Get a buffer for the result and unbind memory if so requested. If not bound to memory we'll allocate a buffer after
          * we've checked that we're bound to a dataset. */
         if ((buffer = SS_BLOB(blob)->m.mem)) {
             if (flags & SS_BLOB_UNBIND) {
                 SS_BLOB(blob)->m.mem = NULL;
                 mtype = SS_BLOB(blob)->m.mtype; /*will be closed at end*/
                 SS_BLOB(blob)->m.mtype = 0;
                 if (H5Sclose(SS_BLOB(blob)->m.mspace)<0) SS_ERROR(HDF5);
                 SS_BLOB(blob)->m.mspace = 0;
             } else {
                 if ((mtype = H5Tcopy(SS_BLOB(blob)->m.mtype))<0) SS_ERROR(HDF5);
             }
         }

         /* Now that we've had an opportunity to unbind, raise the ss_blob_ckspaces() error if there was one. */
         if (status<0) {
             SS_REFAIL;
             SS_ERROR(FAILED);
         }

         /* Make sure the blob is bound to a dataset */
         if (!SS_BLOB(blob)->dsetaddr) SS_ERROR_FMT(USAGE, ("blob is not bound to a dataset"));
         if (SS_NOSIZE==(d_idx=ss_blob_didx(blob))) SS_ERROR(FAILED);
         SS_ASSERT(SS_BLOB(blob)->dsetaddr==*((haddr_t*)(&gblob->d[d_idx].stat.objno)[0]));
         SS_ASSERT(gblob->d[d_idx].dset>0);

         /* Allocate a buffer if we don't have one by now. */
         if (!buffer) {
             SS_ASSERT(mtype<0);
             if ((mtype = H5Tget_native_type(gblob->d[d_idx].dtype, H5T_DIR_DEFAULT))<0) SS_ERROR(HDF5);
             if (0==(tsize=H5Tget_size(mtype))) SS_ERROR(HDF5);
             if ((nelmts = H5Sget_select_npoints(iom))<0) SS_ERROR(HDF5);
             if (NULL==(buffer=malloc(MAX((size_t)1, (size_t)(nelmts*tsize))))) SS_ERROR(RESOURCE);
         }

         /* Get the dataset transfer property list. We do not allow this to be specified by the caller because SSlib does too
          * many things under the covers to make that reliable. */
         dxpl = flags & SS_BLOB_COLLECTIVE ? SS_GFILE_LINK(&topscope)->dxpl_collective : SS_GFILE_LINK(&topscope)->dxpl_independent;

         /* Read the data */
         /* ISSUE: The two-phase I/O optimization for reads is not implemented. */
         if (H5Dread(gblob->d[d_idx].dset, mtype, iom, iof, dxpl, buffer)<0) SS_ERROR(HDF5);

         /* Cleanup */
         if (H5Sclose(iom)<0) SS_ERROR(HDF5);
         iom = -1;
         if (H5Sclose(iof)<0) SS_ERROR(HDF5);
         iof = -1;
         if (H5Tclose(mtype)<0) SS_ERROR(HDF5);
         mtype = -1;
     }

  SS_CLEANUP:
     if (iom>0) H5Sclose(iom);
     if (iof>0) H5Sclose(iof);
     if (mtype>0) H5Tclose(mtype);

     SS_LEAVE(buffer);
 }