LCOV - code coverage report
Current view: top level - src/io - ReadHDF5VarLen.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 78 120 65.0 %
Date: 2020-12-16 07:07:30 Functions: 3 3 100.0 %
Branches: 112 312 35.9 %

           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

Generated by: LCOV version 1.11