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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121 | int
saf_read_subset_relation(SAF_ParMode pmode, /* The parallel mode. */
SAF_Rel *rel, /* The relation whose data is to be read. */
SAF_RelTarget *target, /* Relation targeting information. */
void **abuf, /* The data representing those members in the range collection (on the superset)
* that are related to the members in the domain collection (on the subset). */
void **bbuf /* Optional data for boundary subsets indicating which local piece of boundary
* each member in the domain collection represents in each member of the
* range collection (see saf_declare_subset_relation()) */
)
{
SAF_ENTER(saf_read_subset_relation, SAF_PRECONDITION_ERROR);
double timer_start=0; /* Timer for accumulating time spent reading data. */
ss_set_t sub,sup; /* Relation's subset and superset */
ss_collection_t sub_coll, sup_coll; /* Relation's sub and super collections */
size_t width; /* Number of elements in a collection `members' array */
ss_pers_t val; /* Element from a collection `members' array; link to a set hopefully. */
hsize_t size; /* Number of elements in a blob */
hid_t ftype=-1; /* File datatype for a blob */
hid_t mtype=-1; /* Memory datatype corresponding to `ftype' */
int i;
SAF_REQUIRE(_saf_valid_pmode(pmode), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("PMODE must be valid"));
if (!_saf_is_participating_proc(pmode)) SAF_RETURN(-1);
SAF_REQUIRE(SS_REL(rel), SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("REL must be a valid relation handle"));
SAF_REQUIRE(abuf, SAF_LOW_CHK_COST, SAF_PRECONDITION_ERROR,
_saf_errmsg("ABUF cannot be null for all participating processes"));
SAF_ASSERT(!target, SAF_LOW_CHK_COST, SAF_NOTIMPL_ERROR,
_saf_errmsg("Relation targeting is not implemented"));
/* Start timer */
if (_SAF_GLOBALS.p.TraceTimes)
timer_start = _saf_wall_clock(false);
/* Cache some stuff */
sub = SS_REL(rel)->sub;
if (NULL==_saf_getCollection_set(&sub, SS_REL_P(rel,sub_cat), &sub_coll))
SAF_ERROR(SAF_FILE_ERROR, _saf_errmsg("required subset collection was not available"));
sup = SS_REL(rel)->sup;
/* Just as in the write case, we need to do something special for the case in which the domain collection contains just 1
* member AND is a decomposition of its containing set. */
if (SS_COLLECTION(&sub_coll)->count<=1 &&
SS_COLLECTION(&sub_coll)->cell_type==SAF_CELLTYPE_SET &&
SS_COLLECTION(&sub_coll)->is_decomp) {
if (NULL==_saf_getCollection_set(&sup, SS_REL_P(rel,sup_cat), &sup_coll))
SAF_ERROR(SAF_FILE_ERROR, _saf_errmsg("attempt to read non-existent collection members"));
if (0==(width=ss_array_nelmts(SS_COLLECTION_P(&sup_coll,members))))
SAF_ERROR(SAF_FILE_ERROR,_saf_errmsg("attempt to read non-existent collection members"));
if (SS_COLLECTION(&sup_coll)->count!=(int)width)
SAF_ERROR(SAF_FILE_ERROR, _saf_errmsg("apparent attempt to read members array before it's been completey filled"));
/* Scan list of members for the one pointing to the subset and return a link to it in the array */
for (i=0; i<SS_COLLECTION(&sup_coll)->count; i++) {
ss_array_get(SS_COLLECTION_P(&sup_coll,members), ss_pers_tm, (size_t)i, 1, &val);
if (SS_PERS_EQ(&val,SS_REL_P(rel,sub))) {
if (!*abuf && NULL==(*abuf=malloc(sizeof(size_t))))
SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("unable to allocate space to return collection members"));
*(size_t*)(*abuf) = i;
break;
}
}
if (i>=SS_COLLECTION(&sup_coll)->count)
SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("unable to find subset in the superset collection's member list"));
} else {
/* First, read the abuf (range) data; it is *always* present either indirectly or in a blob. */
if (ss_array_nelmts(SS_REL_P(rel,indirect_rels))>0) {
*abuf = ss_array_get(SS_REL_P(rel,indirect_rels), ss_pers_tm, (size_t)0, SS_NOSIZE, *abuf);
if (!*abuf) SAF_ERROR(SAF_FILE_ERROR, _saf_errmsg("problems reading indirect relation pointers"));
mtype = H5I_INVALID_HID;
} else if (!SS_PERS_ISNULL(SS_REL_P(rel,r_blob))) {
/* obtain the data set type. Note, it will be same for bbuf too, needed below. */
ss_blob_bound_f1(SS_REL_P(rel,r_blob), NULL, NULL, &size, &ftype);
mtype = H5Tget_native_type(ftype, H5T_DIR_DEFAULT);
H5Tclose(ftype); ftype=-1;
/* allocate space for the abuf data or check size */
if (!*abuf && NULL==(*abuf = malloc((size_t)size*H5Tget_size(mtype))))
SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("unable to allocate space to read abuf of relation"));
/* read the data */
ss_blob_bind_m1(SS_REL_P(rel,r_blob), *abuf, mtype, size);
ss_blob_read1(SS_REL_P(rel,r_blob), (hsize_t)0, size, SS_BLOB_UNBIND, NULL);
} else {
SAF_ERROR(SAF_FILE_ERROR, _saf_errmsg("attempt to read non-existent range data"));
}
/* Read the bbuf (domain) data */
if (bbuf) {
/* Issue: If the client requests BBUF but none was written, is that an error? Unfortunately, the only answer that
* works in all cases is to declare this an error. This is so because it is not possible to notify the client
* that none was written except by returning *BBUF==NULL and that is *not* possible in the case that the client
* has pre-allocated BBUF (except if we opt to free the pre-allocated BBUF, and then set it to NULL which I
* don't think would be a good idea). We limit returning error to *only* this case. The other case returns
* BBUF==NULL */
if (SS_PERS_ISNULL(SS_REL_P(rel,d_blob))) {
if (*bbuf)
SAF_ERROR(SAF_FILE_ERROR, _saf_errmsg("attempt to read non-existent bbuf blob into pre-allocated memory"));
} else {
/* allocate space for the bbuf data or check size */
ss_blob_bound_f1(SS_REL_P(rel,d_blob), NULL, NULL, &size, NULL);
if (!*bbuf && NULL==(*bbuf=malloc((size_t)size*H5Tget_size(mtype))))
SAF_ERROR(SAF_MEMORY_ERROR, _saf_errmsg("unable to allocate space to read bbuf of relation"));
/* read the data */
ss_blob_bind_m1(SS_REL_P(rel,d_blob), *bbuf, mtype, size);
ss_blob_read1(SS_REL_P(rel,d_blob), (hsize_t)0, size, SS_BLOB_UNBIND, NULL);
}
}
}
if (mtype>0) H5Tclose(mtype);
if (_SAF_GLOBALS.p.TraceTimes)
_SAF_GLOBALS.CummReadTime += _saf_wall_clock(FALSE) - timer_start;
SAF_LEAVE(SAF_SUCCESS);
}
|