Branch data Line data Source code
1 : : /** \file ReadHDF5VarLen.cpp
2 : : * \author Jason Kraftcheck
3 : : * \date 2010-09-04
4 : : */
5 : :
6 : : #include "ReadHDF5VarLen.hpp"
7 : : #include "ReadHDF5Dataset.hpp"
8 : : #include "H5Tpublic.h"
9 : : #include <assert.h>
10 : :
11 : : namespace moab
12 : : {
13 : :
14 : 661 : bool ReadHDF5VarLen::is_ranged( EntityHandle file_id, Range::const_iterator& ranged_iter,
15 : : Range::const_iterator range_end )
16 : : {
17 [ + - ]: 661 : if( ranged_iter == range_end ) return false;
18 : :
19 [ # # ]: 0 : assert( file_id <= *ranged_iter );
20 [ # # ]: 0 : if( *ranged_iter != file_id ) return false;
21 : :
22 : 0 : ++ranged_iter;
23 : 0 : return true;
24 : : }
25 : :
26 : 73 : ErrorCode ReadHDF5VarLen::read_data( ReadHDF5Dataset& data_set, const Range& offsets, EntityHandle start_offset,
27 : : hid_t data_type, const Range& file_ids,
28 : : const std::vector< unsigned >& vals_per_ent, const Range& ranged_file_ids )
29 : : {
30 : : ErrorCode rval;
31 [ + - ]: 73 : const size_t value_size = H5Tget_size( data_type );
32 : 73 : const size_t buffer_size = bufferSize / value_size;
33 : 73 : unsigned char* const data_buffer = reinterpret_cast< unsigned char* >( dataBuffer );
34 [ + - ]: 73 : std::vector< unsigned char > partial; // for when we read only part of the contents of a set/entity
35 [ + - ]: 73 : Range::const_iterator fileid_iter = file_ids.begin();
36 [ + - ]: 73 : Range::const_iterator ranged_iter = ranged_file_ids.begin();
37 : 73 : std::vector< unsigned >::const_iterator count_iter = vals_per_ent.begin();
38 : : size_t count, offset;
39 : : bool ranged;
40 : 73 : int nn = 0;
41 : :
42 [ + - ][ - + ]: 73 : assert( file_ids.size() == vals_per_ent.size() );
43 : :
44 : : try
45 : : {
46 [ + - ]: 73 : data_set.set_file_ids( offsets, start_offset, buffer_size, data_type );
47 : : }
48 [ # # ]: 0 : catch( ReadHDF5Dataset::Exception& )
49 : : {
50 : 0 : return MB_FAILURE;
51 : : }
52 : :
53 [ + - ][ + - ]: 73 : dbgOut.printf( 3, "Reading %s in %lu chunks\n", data_set.get_debug_desc(), data_set.get_read_count() );
[ + - ]
54 : :
55 [ + - ][ + + ]: 146 : while( !data_set.done() )
56 : : {
57 [ + - ][ + - ]: 73 : dbgOut.printf( 3, "Reading chunk %d of %s\n", ++nn, data_set.get_debug_desc() );
58 : : try
59 : : {
60 [ + - ]: 73 : data_set.read( data_buffer, count );
61 : : }
62 : 0 : catch( ReadHDF5Dataset::Exception& )
63 : : {
64 : 0 : return MB_FAILURE;
65 : : }
66 : :
67 [ + - ][ + - ]: 73 : assert( 0 == count || fileid_iter != file_ids.end() );
[ + - ][ - + ]
[ + - ][ # # ]
68 : :
69 : : // Handle 'special' case where we read some, but not all
70 : : // of the data for an entity during the last iteration.
71 : 73 : offset = 0;
72 [ - + ]: 73 : if( !partial.empty() )
73 : : { // didn't read all of previous entity
74 [ # # ][ # # ]: 0 : assert( fileid_iter != file_ids.end() );
[ # # ]
75 [ # # ]: 0 : assert( 0 == ( partial.size() % value_size ) );
76 : 0 : size_t num_prev = partial.size() / value_size;
77 [ # # ]: 0 : offset = *count_iter - num_prev;
78 [ # # ]: 0 : if( offset > count )
79 : : { // still don't have all
80 [ # # ]: 0 : partial.insert( partial.end(), data_buffer, data_buffer + count * value_size );
81 : 0 : continue;
82 : : }
83 : :
84 [ # # ]: 0 : partial.insert( partial.end(), data_buffer, data_buffer + offset * value_size );
85 : :
86 [ # # ][ # # ]: 0 : ranged = is_ranged( *fileid_iter, ranged_iter, ranged_file_ids.end() );
[ # # ]
87 [ # # ][ # # ]: 0 : assert( partial.size() == *count_iter * value_size );
88 [ # # ][ # # ]: 0 : rval = store_data( *fileid_iter, &partial[0], *count_iter, ranged );
[ # # ][ # # ]
89 [ # # ]: 0 : if( MB_SUCCESS != rval ) return rval;
90 : :
91 [ # # ]: 0 : ++count_iter;
92 [ # # ]: 0 : ++fileid_iter;
93 : 0 : partial.clear();
94 : : }
95 : :
96 : : // Process contents for all entities for which we
97 : : // have read the complete list
98 [ + - ][ + + ]: 734 : while( count_iter != vals_per_ent.end() && offset + *count_iter <= count )
[ + - ][ + - ]
[ + - ]
[ + + # # ]
99 : : {
100 [ + - ][ + - ]: 661 : assert( fileid_iter != file_ids.end() );
[ - + ]
101 [ + - ][ + - ]: 661 : ranged = is_ranged( *fileid_iter, ranged_iter, ranged_file_ids.end() );
[ + - ]
102 [ + - ][ + - ]: 661 : rval = store_data( *fileid_iter, data_buffer + offset * value_size, *count_iter, ranged );
[ + - ]
103 [ - + ]: 661 : if( MB_SUCCESS != rval ) return rval;
104 : :
105 [ + - ]: 661 : offset += *count_iter;
106 [ + - ]: 661 : ++count_iter;
107 [ + - ]: 661 : ++fileid_iter;
108 : : }
109 : :
110 : : // If we did not read all of the final entity,
111 : : // store what we did read to be processed in the
112 : : // next iteration
113 [ - + ]: 73 : if( offset < count )
114 : : {
115 [ # # ]: 0 : assert( partial.empty() );
116 [ # # ]: 0 : partial.insert( partial.end(), data_buffer + offset * value_size, data_buffer + count * value_size );
117 : : }
118 : : }
119 : : // NOTE: If the last set is empty, we will not process it here
120 : : // assert(fileid_iter == file_ids.end());
121 : : #ifndef NDEBUG
122 [ # # ][ + - ]: 73 : for( ; fileid_iter != file_ids.end(); ++fileid_iter )
[ + - ][ - + ]
123 : : {
124 [ # # ][ # # ]: 0 : assert( 0 == *count_iter );
125 [ # # ]: 0 : ++count_iter;
126 : : }
127 : : #endif
128 [ # # ]: 73 : return MB_SUCCESS;
129 : : }
130 : : /*
131 : : ErrorCode ReadHDF5VarLen::read_offsets( ReadHDF5Dataset& data_set,
132 : : const Range& file_ids,
133 : : EntityHandle start_file_id,
134 : : unsigned num_columns,
135 : : const unsigned indices[],
136 : : EntityHandle nudge,
137 : : Range offsets_out[],
138 : : std::vector<unsigned> counts_out[],
139 : : Range* ranged_file_ids = 0 )
140 : : {
141 : : const int local_index = 1;
142 : :
143 : : // sanity check
144 : : const unsigned max_cols = ranged_file_ids ? data_set.columns() - 1 : data_set.columns()
145 : : for (unsigned i = 0; i < num_columns; ++i) {
146 : : assert(indices[i] >= max_cols);
147 : : if (indices[i] >= max_cols)
148 : : return MB_FAILURE;
149 : : }
150 : :
151 : : // Use hints to make sure insertion into ranges is O(1)
152 : : std::vector<Range::iterator> hints;
153 : : if (ranged_file_ids) {
154 : : hints.resize( num_colums + 1 );
155 : : hints.back() = ranged_file_ids->begin();
156 : : }
157 : : else {
158 : : hints.resize( num_columns );
159 : : }
160 : : for (unsigned i = 0; i < num_columns; ++i)
161 : : offsets_out[i].clear();
162 : : counts_out[i].clear();
163 : : counts_out[i].reserve( file_ids.size() );
164 : : hints[i] = offsets_out[i].begin();
165 : : }
166 : :
167 : : // If we only need one column from a multi-column data set,
168 : : // then read only that column.
169 : : if (num_columns == 1 && data_set.columns() > 1 && !ranged_file_ids) {
170 : : data_set.set_column( indices[0] );
171 : : indices = &local_index;
172 : : }
173 : : else if (ranged_file_ids && data_set.columns() > 1 && 0 == num_columns) {
174 : : data_set.set_column( data_set.columns() - 1 );
175 : : }
176 : : // NOTE: do not move this above the previous block.
177 : : // The previous block changes the results of data_set.columns()!
178 : : const size_t table_columns = data_set.columns();
179 : :
180 : : // Calculate which rows we need to read from the offsets table
181 : : Range rows;
182 : : Range::iterator hint = rows.begin();
183 : : Range::const_pair_iterator pair = file_ids.const_pair_begin();
184 : : // special case if reading first entity in dataset, because
185 : : // there is no previous end value.
186 : : if (pair != file_ids.const_pair_end() && pair->first == start_file_id)
187 : : hint = rows.insert( nudge, pair->second - start_file_id + nudge );
188 : : while (pair != file_ids.const_pair_end()) {
189 : : hint = rows.insert( hint,
190 : : pair->first + nudge - 1 - start_file_id,
191 : : pair->second + nudge - start_file_id );
192 : : ++pair;
193 : : }
194 : :
195 : : // set up read of offsets dataset
196 : : hsize_t buffer_size = bufferSize / (sizeof(hssize_t) * data_set.columns());
197 : : hssize_t* buffer = reinterpret_cast<hssize_t*>(dataBuffer);
198 : : data_set.set_file_ids( rows, nudge, buffer_size, H5T_NATIVE_HSSIZE );
199 : : std::vector<hssize_t> prev_end;
200 : : // If we're reading the first row of the table, then the
201 : : // previous end is implicitly -1.
202 : : if (!file_ids.empty() && file_ids.front() == start_file_id)
203 : : prev_end.resize(num_columns,-1);
204 : :
205 : : // read offset table
206 : : size_t count, offset;
207 : : Range::const_iterator fiter = file_ids.begin();
208 : : while (!data_set.done()) {
209 : : try {
210 : : data_set.read( buffer, count );
211 : : }
212 : : catch (ReadHDF5Dataset::Exception e) {
213 : : return MB_FAILURE;
214 : : }
215 : : if (!count) // might have been NULL read for collective IO
216 : : continue;
217 : :
218 : : // If the previous end values were read in the previous iteration,
219 : : // then they're stored in prev_end.
220 : : size_t offset = 0;
221 : : if (!prev_end.empty()) {
222 : : for (unsigned i = 0; i < num_columns; ++i) {
223 : : counts_out[i].push_back( buffer[indices[i]] - prev_end[i] );
224 : : hints[i] = offsets_out[i].insert( hints[i],
225 : : prev_end[i] + 1 + nudge,
226 : : buffer[indices[i]] + nudge );
227 : : }
228 : : if (ranged_file_ids && (buffer[table_columns-1] & mhdf_SET_RANGE_BIT))
229 : : hints.back() = ranged_file_ids->insert( hints.back(), *fiter );
230 : : ++fiter;
231 : : offset = 1;
232 : : prev_end.clear();
233 : : }
234 : :
235 : : while (offset < count) {
236 : : assert(fiter != file_ids.end());
237 : : // whenever we get to a gap between blocks we need to
238 : : // advance one step because we read an extra end id
239 : : // preceding teah block
240 : : if (fiter == fiter.start_of_block()) {
241 : : if (offset == count-1)
242 : : break;
243 : : ++offset;
244 : : }
245 : :
246 : : for (unsigned i = 0; i < num_columns; ++i) {
247 : : size_t s = buffer[(offset-1)*table_columns+indices[i]] + 1;
248 : : size_t e = buffer[ offset *table_columns+indices[i]];
249 : : counts_out.push_back( e - s + 1 );
250 : : hints[i] = offsets_out.insert( hints[i], s, e );
251 : : }
252 : : if (ranged_file_ids && (buffer[offset*table_columns+table_columns-1] & mhdf_SET_RANGE_BIT))
253 : : hints.back() = ranged_file_ids->insert( hints.back(), *fiter );
254 : :
255 : : ++fiter;
256 : : ++offset;
257 : : }
258 : :
259 : : // If we did not end on the boundary between two blocks,
260 : : // then we need to save the end indices for the final entry
261 : : // for use in the next iteration. Similarly, if we ended
262 : : // with extra values that were read with the express intention
263 : : // of getting the previous end values for a block, we need to
264 : : // save them. This case only arises if we hit the break in
265 : : // the above loop.
266 : : if (fiter != fiter.start_of_block() || offset < count) {
267 : : assert(prev_end.empty());
268 : : if (offset == count) {
269 : : --offset;
270 : : assert(fiter != fiter.start_of_block());
271 : : }
272 : : else {
273 : : assert(offset+1 == count);
274 : : assert(fiter == fiter.start_of_block());
275 : : }
276 : : for (unsigned i = 0; i < num_columns; ++i)
277 : : prev_end.push_back(buffer[offset*table_columns+indices[i]]);
278 : : }
279 : : }
280 : : assert(prev_end.empty());
281 : : assert(fiter == file_ids.end());
282 : :
283 : : return MB_SUCCESS;
284 : : }
285 : : */
286 : 73 : ErrorCode ReadHDF5VarLen::read_offsets( ReadHDF5Dataset& data_set, const Range& file_ids, EntityHandle start_file_id,
287 : : EntityHandle nudge, Range& offsets_out, std::vector< unsigned >& counts_out )
288 : : {
289 : :
290 : : // Use hints to make sure insertion into ranges is O(1)
291 [ + - ]: 73 : offsets_out.clear();
292 : 73 : counts_out.clear();
293 [ + - ][ + - ]: 73 : counts_out.reserve( file_ids.size() );
294 [ + - ]: 73 : Range::iterator hint;
295 : :
296 : : // Calculate which rows we need to read from the offsets table
297 [ + - ]: 73 : Range rows;
298 [ + - ]: 73 : hint = rows.begin();
299 [ + - ]: 73 : Range::const_pair_iterator pair = file_ids.const_pair_begin();
300 : : // special case if reading first entity in dataset, because
301 : : // there is no previous end value.
302 [ + - ][ + - ]: 73 : if( pair != file_ids.const_pair_end() && pair->first == start_file_id )
[ + - ][ + - ]
[ + - ][ + - ]
[ + - # # ]
303 : : {
304 [ + - ][ + - ]: 73 : hint = rows.insert( nudge, pair->second - start_file_id + nudge );
305 [ + - ]: 73 : ++pair;
306 : : }
307 [ + - ][ + - ]: 73 : while( pair != file_ids.const_pair_end() )
[ - + # # ]
308 : : {
309 [ # # ][ # # ]: 0 : hint = rows.insert( hint, pair->first - start_file_id + nudge - 1, pair->second - start_file_id + nudge );
[ # # ]
310 [ # # ]: 0 : ++pair;
311 : : }
312 : :
313 : : // set up read of offsets dataset
314 : 73 : hsize_t buffer_size = bufferSize / sizeof( hssize_t );
315 : 73 : hssize_t* buffer = reinterpret_cast< hssize_t* >( dataBuffer );
316 [ + - ][ + - ]: 73 : data_set.set_file_ids( rows, nudge, buffer_size, H5T_NATIVE_HSSIZE );
317 : : hssize_t prev_end;
318 : 73 : bool have_prev_end = false;
319 : : // If we're reading the first row of the table, then the
320 : : // previous end is implicitly -1.
321 [ + - ][ + - ]: 73 : if( !file_ids.empty() && file_ids.front() == start_file_id )
[ + - ][ + - ]
[ + - ]
322 : : {
323 : 73 : prev_end = -1;
324 : 73 : have_prev_end = true;
325 : : }
326 : :
327 [ + - ][ + - ]: 73 : dbgOut.printf( 3, "Reading %s in %lu chunks\n", data_set.get_debug_desc(), data_set.get_read_count() );
[ + - ]
328 : :
329 : : // read offset table
330 : : size_t count, offset;
331 [ + - ]: 73 : Range::const_iterator fiter = file_ids.begin();
332 [ + - ]: 73 : hint = offsets_out.begin();
333 : 73 : int nn = 0;
334 [ + - ][ + + ]: 146 : while( !data_set.done() )
335 : : {
336 [ + - ][ + - ]: 73 : dbgOut.printf( 3, "Reading chunk %d of %s\n", ++nn, data_set.get_debug_desc() );
337 : : try
338 : : {
339 [ + - ]: 73 : data_set.read( buffer, count );
340 : : }
341 : 0 : catch( ReadHDF5Dataset::Exception& )
342 : : {
343 : 0 : return MB_FAILURE;
344 : : }
345 [ - + ]: 73 : if( !count ) // might have been NULL read for collective IO
346 : 0 : continue;
347 : :
348 : : // If the previous end values were read in the previous iteration,
349 : : // then they're stored in prev_end.
350 : 73 : offset = 0;
351 [ + - ]: 73 : if( have_prev_end )
352 : : {
353 [ + - ]: 73 : counts_out.push_back( buffer[0] - prev_end );
354 [ + - ]: 73 : hint = offsets_out.insert( hint, prev_end + 1 + nudge, buffer[0] + nudge );
355 [ + - ]: 73 : ++fiter;
356 : 73 : offset = 1;
357 : 73 : have_prev_end = false;
358 : : }
359 : :
360 [ + + ]: 661 : while( offset < count )
361 : : {
362 [ + - ][ + - ]: 588 : assert( fiter != file_ids.end() );
[ - + ]
363 : : // whenever we get to a gap between blocks we need to
364 : : // advance one step because we read an extra end id
365 : : // preceding teah block
366 [ + - ][ + - ]: 588 : if( fiter == fiter.start_of_block() )
[ - + ]
367 : : {
368 [ # # ]: 0 : if( offset == count - 1 ) break;
369 : 0 : ++offset;
370 : : }
371 : :
372 : 588 : size_t s = buffer[offset - 1] + 1;
373 : 588 : size_t e = buffer[offset];
374 [ + - ]: 588 : counts_out.push_back( e - s + 1 );
375 [ + - ]: 588 : hint = offsets_out.insert( hint, s + nudge, e + nudge );
376 : :
377 [ + - ]: 588 : ++fiter;
378 : 588 : ++offset;
379 : : }
380 : :
381 : : // If we did not end on the boundary between two blocks,
382 : : // then we need to save the end indices for the final entry
383 : : // for use in the next iteration. Similarly, if we ended
384 : : // with extra values that were read with the express intention
385 : : // of getting the previous end values for a block, we need to
386 : : // save them. This case only arises if we hit the break in
387 : : // the above loop.
388 [ + - ][ + - ]: 73 : if( fiter != fiter.start_of_block() || offset < count )
[ + - ][ - + ]
[ + - ]
[ - + # # ]
389 : : {
390 [ # # ]: 0 : assert( !have_prev_end );
391 [ # # ]: 0 : if( offset == count )
392 : : {
393 : 0 : --offset;
394 [ # # ][ # # ]: 0 : assert( fiter != fiter.start_of_block() );
[ # # ]
395 : : }
396 : : else
397 : : {
398 [ # # ]: 0 : assert( offset + 1 == count );
399 [ # # ][ # # ]: 0 : assert( fiter == fiter.start_of_block() );
[ # # ]
400 : : }
401 : 0 : have_prev_end = true;
402 : 0 : prev_end = buffer[offset];
403 : : }
404 : : }
405 [ - + ]: 73 : assert( !have_prev_end );
406 [ + - ][ + - ]: 73 : assert( fiter == file_ids.end() );
[ - + ]
407 : :
408 : 73 : return MB_SUCCESS;
409 : : }
410 : :
411 : : } // namespace moab
|