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);
}