MOAB: Mesh Oriented datABase  (version 5.4.1)
BitTag.cpp
Go to the documentation of this file.
00001 #include "BitTag.hpp"
00002 #include "BitPage.hpp"
00003 #include "moab/Range.hpp"
00004 #include "TagCompare.hpp"
00005 #include "SequenceManager.hpp"
00006 #include "moab/Error.hpp"
00007 #include "moab/ErrorHandler.hpp"
00008 #include <cstdlib>
00009 #include <cstring>
00010 
00011 namespace moab
00012 {
00013 
00014 BitTag::~BitTag()
00015 {
00016     release_all_data( 0, 0, true );
00017 }
00018 
00019 TagType BitTag::get_storage_type() const
00020 {
00021     return MB_TAG_BIT;
00022 }
00023 
00024 BitTag* BitTag::create_tag( const char* name, int size, const void* default_value )
00025 {
00026     BitTag* result = new BitTag( name, size, default_value );
00027     if( MB_SUCCESS != result->reserve( size ) )
00028     {
00029         delete result;
00030         result = NULL;
00031     }
00032 
00033     return result;
00034 }
00035 
00036 ErrorCode BitTag::reserve( unsigned bits )
00037 {
00038     if( bits > 8 ) return MB_FAILURE;
00039 
00040     requestedBitsPerEntity = bits;
00041     // Store smallest power of two greater than or
00042     // equal to the number of bits
00043     storedBitsPerEntity    = 1;
00044     unsigned ln2storedbits = 0;
00045     while( storedBitsPerEntity < bits )
00046     {
00047         storedBitsPerEntity *= 2;
00048         ++ln2storedbits;
00049     }
00050 
00051     // pageShift = log2(ents_per_page())
00052     //           = log2(8 * pageSize / storedBitsPerEntity )
00053     //           = log2(8) + log2(pageSize) - log2(storedBitsPerEntity)
00054     //           = 3 + Ln2PageSize - ln2storedbits;
00055     pageShift = 3 + Ln2PageSize - ln2storedbits;
00056 
00057     return MB_SUCCESS;
00058 }
00059 
00060 ErrorCode BitTag::release_all_data( SequenceManager*, Error*, bool )
00061 {
00062     for( EntityType t = (EntityType)0; t != MBMAXTYPE; ++t )
00063     {
00064         for( size_t i = 0; i < pageList[t].size(); ++i )
00065             delete pageList[t][i];
00066         pageList[t].clear();
00067     }
00068 
00069     return MB_SUCCESS;
00070 }
00071 
00072 ErrorCode BitTag::get_data( const SequenceManager*,
00073                             Error*,
00074                             const EntityHandle* handles,
00075                             size_t num_handles,
00076                             void* gen_data ) const
00077 {
00078     EntityType type;
00079     size_t page;
00080     int offset;
00081     unsigned char def   = default_val();
00082     unsigned char* data = reinterpret_cast< unsigned char* >( gen_data );
00083     for( size_t i = 0; i < num_handles; ++i )
00084     {
00085         unpack( handles[i], type, page, offset );
00086         if( pageList[type].size() <= page || !pageList[type][page] )
00087             data[i] = def;
00088         else
00089             data[i] = pageList[type][page]->get_bits( offset, storedBitsPerEntity );
00090     }
00091 
00092     return MB_SUCCESS;
00093 }
00094 
00095 ErrorCode BitTag::set_data( SequenceManager* seqman,
00096                             Error* /* error */,
00097                             const EntityHandle* handles,
00098                             size_t num_handles,
00099                             const void* gen_data )
00100 {
00101     ErrorCode rval = seqman->check_valid_entities( NULL, handles, num_handles, true );MB_CHK_ERR( rval );
00102 
00103     EntityType type;
00104     size_t page;
00105     int offset;
00106     const unsigned char* data = reinterpret_cast< const unsigned char* >( gen_data );
00107     for( size_t i = 0; i < num_handles; ++i )
00108     {
00109         unpack( handles[i], type, page, offset );
00110         if( pageList[type].size() <= page ) pageList[type].resize( page + 1, 0 );
00111         if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
00112         pageList[type][page]->set_bits( offset, storedBitsPerEntity, data[i] );
00113     }
00114 
00115     return MB_SUCCESS;
00116 }
00117 
00118 ErrorCode BitTag::clear_data( SequenceManager* seqman,
00119                               Error* /* error */,
00120                               const EntityHandle* handles,
00121                               size_t num_handles,
00122                               const void* value_ptr,
00123                               int value_len )
00124 {
00125     if( value_len ) return MB_INVALID_SIZE;
00126 
00127     ErrorCode rval = seqman->check_valid_entities( NULL, handles, num_handles, true );MB_CHK_ERR( rval );
00128 
00129     EntityType type;
00130     size_t page;
00131     int offset;
00132     const unsigned char value = *reinterpret_cast< const unsigned char* >( value_ptr );
00133     for( size_t i = 0; i < num_handles; ++i )
00134     {
00135         unpack( handles[i], type, page, offset );
00136         if( pageList[type].size() <= page ) pageList[type].resize( page + 1, 0 );
00137         if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
00138         pageList[type][page]->set_bits( offset, storedBitsPerEntity, value );
00139     }
00140 
00141     return MB_SUCCESS;
00142 }
00143 
00144 ErrorCode BitTag::remove_data( SequenceManager*, Error*, const EntityHandle* handles, size_t num_handles )
00145 {
00146     EntityType type;
00147     size_t page;
00148     int offset;
00149     const unsigned char val = default_val();
00150     for( size_t i = 0; i < num_handles; ++i )
00151     {
00152         unpack( handles[i], type, page, offset );
00153         if( pageList[type].size() > page && pageList[type][page] )
00154             pageList[type][page]->set_bits( offset, storedBitsPerEntity, val );
00155     }
00156 
00157     return MB_SUCCESS;
00158 }
00159 
00160 ErrorCode BitTag::get_data( const SequenceManager*, Error*, const Range& handles, void* gen_data ) const
00161 {
00162     EntityType type;
00163     EntityID count;
00164     size_t page;
00165     int offset, per_page = ents_per_page();
00166     unsigned char def   = default_val();
00167     unsigned char* data = reinterpret_cast< unsigned char* >( gen_data );
00168     Range::const_pair_iterator i;
00169     for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00170     {
00171         unpack( i->first, type, page, offset );
00172         assert( TYPE_FROM_HANDLE( i->second ) == type );  // Should be true because id of zero is never used
00173         count = i->second - i->first + 1;
00174         if( page >= pageList[type].size() )
00175         {
00176             memset( data, def, count );
00177             data += count;
00178             continue;
00179         }
00180 
00181         while( count )
00182         {
00183             size_t pcount = std::min( (EntityID)( per_page - offset ), count );
00184             if( pageList[type][page] )
00185                 pageList[type][page]->get_bits( offset, pcount, storedBitsPerEntity, data );
00186             else
00187                 memset( data, def, pcount );
00188             data += pcount;
00189             count -= pcount;
00190             offset = 0;
00191             ++page;
00192         }
00193     }
00194 
00195     return MB_SUCCESS;
00196 }
00197 
00198 ErrorCode BitTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& handles, const void* gen_data )
00199 {
00200     ErrorCode rval = seqman->check_valid_entities( NULL, handles );MB_CHK_ERR( rval );
00201 
00202     EntityType type;
00203     EntityID count;
00204     size_t page;
00205     int offset, per_page = ents_per_page();
00206     unsigned char def         = default_val();
00207     const unsigned char* data = reinterpret_cast< const unsigned char* >( gen_data );
00208     Range::const_pair_iterator i;
00209     for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00210     {
00211         unpack( i->first, type, page, offset );
00212         assert( TYPE_FROM_HANDLE( i->second ) == type );  // Should be true because id of zero is never used
00213         count = i->second - i->first + 1;
00214 
00215         while( count )
00216         {
00217             if( page >= pageList[type].size() ) pageList[type].resize( page + 1, 0 );
00218             if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, def );
00219 
00220             size_t pcount = std::min( (EntityID)( per_page - offset ), count );
00221             pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, data );
00222             data += pcount;
00223             count -= pcount;
00224             offset = 0;
00225             ++page;
00226         }
00227     }
00228 
00229     return MB_SUCCESS;
00230 }
00231 
00232 ErrorCode BitTag::clear_data( SequenceManager* seqman,
00233                               Error* /* error */,
00234                               const Range& handles,
00235                               const void* value_ptr,
00236                               int value_len )
00237 {
00238     if( value_len ) return MB_INVALID_SIZE;
00239 
00240     ErrorCode rval = seqman->check_valid_entities( NULL, handles );MB_CHK_ERR( rval );
00241 
00242     EntityType type;
00243     EntityID count;
00244     size_t page;
00245     int offset, per_page = ents_per_page();
00246     const unsigned char value = *reinterpret_cast< const unsigned char* >( value_ptr );
00247     Range::const_pair_iterator i;
00248     for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00249     {
00250         unpack( i->first, type, page, offset );
00251         assert( TYPE_FROM_HANDLE( i->second ) == type );  // Should be true because id of zero is never used
00252         count = i->second - i->first + 1;
00253 
00254         while( count )
00255         {
00256             if( page >= pageList[type].size() ) pageList[type].resize( page + 1, 0 );
00257             if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
00258 
00259             size_t pcount = std::min( (EntityID)( per_page - offset ), count );
00260             pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, value );
00261             count -= pcount;
00262             offset = 0;
00263             ++page;
00264         }
00265     }
00266 
00267     return MB_SUCCESS;
00268 }
00269 
00270 ErrorCode BitTag::remove_data( SequenceManager*, Error*, const Range& handles )
00271 {
00272     EntityType type;
00273     EntityID count;
00274     size_t page;
00275     int offset, per_page = ents_per_page();
00276     unsigned char val = default_val();
00277     Range::const_pair_iterator i;
00278     for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00279     {
00280         unpack( i->first, type, page, offset );
00281         assert( TYPE_FROM_HANDLE( i->second ) == type );  // Should be true because id of zero is never used
00282         count = i->second - i->first + 1;
00283 
00284         while( count )
00285         {
00286             size_t pcount = std::min( (EntityID)( per_page - offset ), count );
00287             if( page < pageList[type].size() && pageList[type][page] )
00288                 pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, val );
00289             count -= pcount;
00290             offset = 0;
00291             ++page;
00292         }
00293     }
00294 
00295     return MB_SUCCESS;
00296 }
00297 
00298 ErrorCode BitTag::get_data( const SequenceManager*,
00299                             Error* /* error */,
00300                             const EntityHandle*,
00301                             size_t,
00302                             const void**,
00303                             int* ) const
00304 {
00305     MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation get_data not supported for bit tags" );
00306 }
00307 
00308 ErrorCode BitTag::get_data( const SequenceManager*, Error* /* error */, const Range&, const void**, int* ) const
00309 {
00310     MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation get_data not supported for bit tags" );
00311 }
00312 
00313 ErrorCode BitTag::set_data( SequenceManager*,
00314                             Error* /* error */,
00315                             const EntityHandle*,
00316                             size_t,
00317                             void const* const*,
00318                             const int* )
00319 {
00320     MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation set_data not supported for bit tags" );
00321 }
00322 
00323 ErrorCode BitTag::set_data( SequenceManager*, Error* /* error */, const Range&, void const* const*, const int* )
00324 {
00325     MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation set_data not supported for bit tags" );
00326 }
00327 
00328 ErrorCode BitTag::tag_iterate( SequenceManager*,
00329                                Error* /* error */,
00330                                Range::iterator&,
00331                                const Range::iterator&,
00332                                void*&,
00333                                bool )
00334 {
00335     MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation tag_iterate not supported for bit tags" );
00336 }
00337 
00338 template < class Container >
00339 inline void BitTag::get_tagged( EntityType type, Container& entities ) const
00340 {
00341     std::pair< EntityType, EntityType > r = type_range( type );
00342     typename Container::iterator hint     = entities.begin();
00343     const int per_page                    = ents_per_page();
00344     for( EntityType t = r.first; t != r.second; ++t )
00345     {
00346         for( size_t i = 0; i < pageList[t].size(); ++i )
00347         {
00348             if( pageList[t][i] )
00349             {
00350                 EntityID id       = i * per_page;
00351                 EntityHandle h    = CREATE_HANDLE( t, id );
00352                 EntityHandle last = h + per_page - 1;
00353                 // Never zero ID
00354                 if( 0 == id ) ++h;
00355                 hint = entities.insert( hint, h, last );
00356             }
00357         }
00358     }
00359 }
00360 
00361 template < class Container >
00362 inline void BitTag::get_tagged( Range::const_iterator begin, Range::const_iterator end, Container& entities ) const
00363 {
00364     EntityType type;
00365     EntityID count;
00366     size_t page;
00367     int offset, per_page = ents_per_page();
00368     typename Container::iterator hint = entities.begin();
00369     EntityHandle h;
00370     Range::const_iterator i = begin;
00371     while( i != end )
00372     {
00373         h = *i;
00374         unpack( h, type, page, offset );
00375 
00376         i     = i.end_of_block();
00377         count = *i - h + 1;
00378         ++i;
00379         while( count > 0 )
00380         {
00381             EntityID pcount = std::min( count, (EntityID)( per_page - offset ) );
00382             if( page < pageList[type].size() && pageList[type][page] )
00383                 hint = entities.insert( hint, h, h + pcount - 1 );
00384 
00385             count -= pcount;
00386             h += pcount;
00387             assert( TYPE_FROM_HANDLE( h ) == type );
00388             offset = 0;
00389             ++page;
00390         }
00391     }
00392 }
00393 
00394 template < class Container >
00395 inline void BitTag::get_tagged( Container& entities, EntityType type, const Range* intersect ) const
00396 
00397 {
00398     if( !intersect )
00399         get_tagged< Container >( type, entities );
00400     else if( MBMAXTYPE == type )
00401         get_tagged< Container >( intersect->begin(), intersect->end(), entities );
00402     else
00403     {
00404         std::pair< Range::iterator, Range::iterator > r = intersect->equal_range( type );
00405         get_tagged< Container >( r.first, r.second, entities );
00406     }
00407 }
00408 
00409 ErrorCode BitTag::get_tagged_entities( const SequenceManager*,
00410                                        Range& entities,
00411                                        EntityType type,
00412                                        const Range* intersect ) const
00413 {
00414     get_tagged< Range >( entities, type, intersect );
00415     return MB_SUCCESS;
00416 }
00417 
00418 ErrorCode BitTag::num_tagged_entities( const SequenceManager*,
00419                                        size_t& count,
00420                                        EntityType type,
00421                                        const Range* intersect ) const
00422 {
00423     InsertCount counter( count );
00424     get_tagged< InsertCount >( counter, type, intersect );
00425     count = counter.end();
00426     return MB_SUCCESS;
00427 }
00428 
00429 ErrorCode BitTag::find_entities_with_value( const SequenceManager*,
00430                                             Error* /* error */,
00431                                             Range& output_entities,
00432                                             const void* value,
00433                                             int value_bytes,
00434                                             EntityType type,
00435                                             const Range* intersect_entities ) const
00436 {
00437     if( value_bytes && value_bytes != 1 )
00438     {
00439         MB_SET_ERR( MB_INVALID_SIZE, "Invalid tag size for bit tag: " << value_bytes << " bytes" );
00440     }
00441 
00442     const signed char bits = *reinterpret_cast< const unsigned char* >( value );
00443     if( intersect_entities )
00444         return get_entities_with_bits( *intersect_entities, type, output_entities, bits );
00445     else
00446         return get_entities_with_bits( type, output_entities, bits );
00447 }
00448 
00449 ErrorCode BitTag::get_entities_with_bits( EntityType type, Range& entities, unsigned char bits ) const
00450 {
00451     std::pair< EntityType, EntityType > r = type_range( type );
00452     const int per_page                    = ents_per_page();
00453     for( EntityType t = r.first; t != r.second; ++t )
00454     {
00455         for( size_t i = 0; i < pageList[t].size(); ++i )
00456         {
00457             if( pageList[t][i] )
00458             {
00459                 EntityID id    = i * per_page;
00460                 EntityHandle h = CREATE_HANDLE( t, id );
00461                 int off        = !i;  // Never zero ID
00462                 pageList[t][i]->search( bits, off, per_page - off, storedBitsPerEntity, entities, h + off );
00463             }
00464         }
00465     }
00466 
00467     return MB_SUCCESS;
00468 }
00469 
00470 ErrorCode BitTag::get_entities_with_bits( const Range& range,
00471                                           EntityType in_type,
00472                                           Range& entities,
00473                                           unsigned char bits ) const
00474 {
00475     if( MBMAXTYPE == in_type )
00476     {
00477         ErrorCode rval;
00478         for( --in_type; in_type >= MBVERTEX; --in_type )
00479         {
00480             rval = get_entities_with_bits( range, in_type, entities, bits );MB_CHK_ERR( rval );
00481         }
00482         return MB_SUCCESS;
00483     }
00484 
00485     EntityType type;
00486     EntityID count;
00487     size_t page;
00488     int offset, per_page = ents_per_page();
00489     Range::const_iterator i, end;
00490     std::pair< Range::iterator, Range::iterator > r = range.equal_range( in_type );
00491     i                                               = r.first;
00492     end                                             = r.second;
00493     EntityHandle h;
00494     while( i != end )
00495     {
00496         h = *i;
00497         unpack( h, type, page, offset );
00498         assert( MBMAXTYPE == in_type || type == in_type );
00499 
00500         i     = i.end_of_block();
00501         count = *i - h + 1;
00502         ++i;
00503         while( count > 0 )
00504         {
00505             EntityID pcount = std::min( count, (EntityID)( per_page - offset ) );
00506             if( page < pageList[type].size() && pageList[type][page] )
00507                 pageList[type][page]->search( bits, offset, pcount, storedBitsPerEntity, entities, h );
00508 
00509             count -= pcount;
00510             h += pcount;
00511             assert( TYPE_FROM_HANDLE( h ) == type );
00512             offset = 0;
00513             ++page;
00514         }
00515     }
00516 
00517     return MB_SUCCESS;
00518 }
00519 
00520 ErrorCode BitTag::get_memory_use( const SequenceManager*, unsigned long& total, unsigned long& per_entity ) const
00521 {
00522     per_entity = ( storedBitsPerEntity > 4 );  // Cannot return fraction of bytes, so round
00523     total      = 0;
00524     for( EntityType t = (EntityType)0; t < MBMAXTYPE; ++t )
00525     {
00526         total += pageList[t].capacity() * sizeof( BitPage* );
00527         for( size_t i = 0; i < pageList[t].size(); ++i )
00528             if( pageList[t][i] ) total += sizeof( BitPage );
00529     }
00530 
00531     return MB_SUCCESS;
00532 }
00533 
00534 bool BitTag::is_tagged( const SequenceManager*, EntityHandle h ) const
00535 {
00536     EntityType type;
00537     size_t page;
00538     int offset;
00539     unpack( h, type, page, offset );
00540     return page < pageList[type].size() && pageList[type][page];
00541 }
00542 
00543 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines