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
 herr_t
 ss_blob_extend(ss_blob_t *blob,                 /* Blob which is possibly to be extended. */
                const hsize_t *size,             /* New size of the blob on each calling task per dataset dimension */
                unsigned flags,                  /* Bit flags such as SS_ALLSAME. */
                ss_prop_t UNUSED *props          /* Optional property list (none defined yet). */
                )
 {
     SS_ENTER(ss_blob_extend, herr_t);
     ss_scope_t          topscope=SS_SCOPE_NULL; /* Top scope for BLOB */
     ss_scope_t          blobscope=SS_SCOPE_NULL;
     hsize_t             newsize[SS_MAXDIMS], dsize[SS_MAXDIMS];
     ss_gblob_t          *gblob=NULL;
     size_t              d_idx=SS_NOSIZE;
     hid_t               dspace=-1;
     int                 i, ndims;
     MPI_Comm            blobcomm=SS_COMM_NULL;

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

     /* The blob must be 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);
     if ((ndims=H5Sget_simple_extent_ndims(gblob->d[d_idx].dspace))<0) SS_ERROR(HDF5);

     if (blob) {
         /* MAX-Reduce the size in each dimension */
         if (flags & SS_ALLSAME) {
             for (i=0; i<ndims; i++) newsize[i] = size[i];
         } else {
             if (NULL==ss_pers_scope((ss_pers_t*)blob, &blobscope)) SS_ERROR(FAILED);
             if (ss_scope_comm(&blobscope, &blobcomm, NULL, NULL)<0) SS_ERROR(FAILED);
 #ifdef HAVE_PARALLEL
             {
                 unsigned long lsize[SS_MAXDIMS], lsize2[SS_MAXDIMS];
                 for (i=0; i<ndims; i++) lsize[i] = size[i];
                 if (MPI_Allreduce(lsize, lsize2, ndims, MPI_UNSIGNED_LONG, MPI_MAX, blobcomm)) SS_ERROR(MPI);
                 for (i=0; i<ndims; i++) newsize[i] = lsize2[i];
             }
 #else
             for (i=0; i<ndims; i++) newsize[i] = size[i];
 #endif
         }

         /* Make sure that the dataset is extendible or already large enough. We could actually delay this and let
          * ss_blob_bind_f() check it, but then we might unbind the blob if it fails.  */
         ss_blob_ckspace(gblob->d[d_idx].dspace, ndims, dsize, NULL, NULL, NULL);
         if (gblob->d[d_idx].is_extendible) {
             for (i=0; i<ndims; i++) {
                 dsize[i] = MAX(dsize[i], SS_BLOB(blob)->start[i]+newsize[i]);
             }
         } else {
             for (i=0; i<ndims; i++) {
                 if (SS_BLOB(blob)->start[i]+newsize[i]>dsize[i]) {
                     SS_ERROR_FMT(OVERFLOW,
                                  ("blob(start=%lu,count=%lu) extends past end of non-extendible dataset(%lu) in dimension %d",
                                   (unsigned long)(SS_BLOB(blob)->start[i]), (unsigned long)newsize[i],
                                   (unsigned long)(dsize[i]), i));
                 }
             }
         }

         /* Create a new data space for the rebind operation */
         if ((dspace=H5Screate_simple(ndims, dsize, ss_blob_unlim_g))<0) SS_ERROR(HDF5);
         if (H5Sselect_slab(dspace, H5S_SELECT_SET, (hsize_t)0, SS_BLOB(blob)->start, newsize)<0) SS_ERROR(HDF5);
     }

     /* All tasks rebind the blob to a dataset. The `dspace' argument is ignored on the non-blob tasks */
     if (ss_blob_bind_f(blob?blob:(ss_blob_t*)&topscope, gblob->d[d_idx].dset, dspace, SS_BLOB_EXTEND)<0) SS_ERROR(FAILED);

     /* Successful cleanup */
     if (dspace>0 && H5Sclose(dspace)<0) SS_ERROR(HDF5);
     dspace = -1;

 SS_CLEANUP:
     if (dspace>0) H5Sclose(dspace);
     SS_LEAVE(0);
 }