MOAB: Mesh Oriented datABase  (version 5.2.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*, Error*, const EntityHandle* handles, size_t num_handles,
00073                             void* gen_data ) const
00074 {
00075     EntityType type;
00076     size_t page;
00077     int offset;
00078     unsigned char def   = default_val();
00079     unsigned char* data = reinterpret_cast< unsigned char* >( gen_data );
00080     for( size_t i = 0; i < num_handles; ++i )
00081     {
00082         unpack( handles[i], type, page, offset );
00083         if( pageList[type].size() <= page || !pageList[type][page] )
00084             data[i] = def;
00085         else
00086             data[i] = pageList[type][page]->get_bits( offset, storedBitsPerEntity );
00087     }
00088 
00089     return MB_SUCCESS;
00090 }
00091 
00092 ErrorCode BitTag::set_data( SequenceManager* seqman, Error* /* error */, const EntityHandle* handles,
00093                             size_t num_handles, const void* gen_data )
00094 {
00095     ErrorCode rval = seqman->check_valid_entities( NULL, handles, num_handles, true );MB_CHK_ERR( rval );
00096 
00097     EntityType type;
00098     size_t page;
00099     int offset;
00100     const unsigned char* data = reinterpret_cast< const unsigned char* >( gen_data );
00101     for( size_t i = 0; i < num_handles; ++i )
00102     {
00103         unpack( handles[i], type, page, offset );
00104         if( pageList[type].size() <= page ) pageList[type].resize( page + 1, 0 );
00105         if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
00106         pageList[type][page]->set_bits( offset, storedBitsPerEntity, data[i] );
00107     }
00108 
00109     return MB_SUCCESS;
00110 }
00111 
00112 ErrorCode BitTag::clear_data( SequenceManager* seqman, Error* /* error */, const EntityHandle* handles,
00113                               size_t num_handles, const void* value_ptr, int value_len )
00114 {
00115     if( value_len ) return MB_INVALID_SIZE;
00116 
00117     ErrorCode rval = seqman->check_valid_entities( NULL, handles, num_handles, true );MB_CHK_ERR( rval );
00118 
00119     EntityType type;
00120     size_t page;
00121     int offset;
00122     const unsigned char value = *reinterpret_cast< const unsigned char* >( value_ptr );
00123     for( size_t i = 0; i < num_handles; ++i )
00124     {
00125         unpack( handles[i], type, page, offset );
00126         if( pageList[type].size() <= page ) pageList[type].resize( page + 1, 0 );
00127         if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
00128         pageList[type][page]->set_bits( offset, storedBitsPerEntity, value );
00129     }
00130 
00131     return MB_SUCCESS;
00132 }
00133 
00134 ErrorCode BitTag::remove_data( SequenceManager*, Error*, const EntityHandle* handles, size_t num_handles )
00135 {
00136     EntityType type;
00137     size_t page;
00138     int offset;
00139     const unsigned char val = default_val();
00140     for( size_t i = 0; i < num_handles; ++i )
00141     {
00142         unpack( handles[i], type, page, offset );
00143         if( pageList[type].size() > page && pageList[type][page] )
00144             pageList[type][page]->set_bits( offset, storedBitsPerEntity, val );
00145     }
00146 
00147     return MB_SUCCESS;
00148 }
00149 
00150 ErrorCode BitTag::get_data( const SequenceManager*, Error*, const Range& handles, void* gen_data ) const
00151 {
00152     EntityType type;
00153     EntityID count;
00154     size_t page;
00155     int offset, per_page = ents_per_page();
00156     unsigned char def   = default_val();
00157     unsigned char* data = reinterpret_cast< unsigned char* >( gen_data );
00158     Range::const_pair_iterator i;
00159     for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00160     {
00161         unpack( i->first, type, page, offset );
00162         assert( TYPE_FROM_HANDLE( i->second ) == type );  // Should be true because id of zero is never used
00163         count = i->second - i->first + 1;
00164         if( page >= pageList[type].size() )
00165         {
00166             memset( data, def, count );
00167             data += count;
00168             continue;
00169         }
00170 
00171         while( count )
00172         {
00173             size_t pcount = std::min( ( EntityID )( per_page - offset ), count );
00174             if( pageList[type][page] )
00175                 pageList[type][page]->get_bits( offset, pcount, storedBitsPerEntity, data );
00176             else
00177                 memset( data, def, pcount );
00178             data += pcount;
00179             count -= pcount;
00180             offset = 0;
00181             ++page;
00182         }
00183     }
00184 
00185     return MB_SUCCESS;
00186 }
00187 
00188 ErrorCode BitTag::set_data( SequenceManager* seqman, Error* /* error */, const Range& handles, const void* gen_data )
00189 {
00190     ErrorCode rval = seqman->check_valid_entities( NULL, handles );MB_CHK_ERR( rval );
00191 
00192     EntityType type;
00193     EntityID count;
00194     size_t page;
00195     int offset, per_page = ents_per_page();
00196     unsigned char def         = default_val();
00197     const unsigned char* data = reinterpret_cast< const unsigned char* >( gen_data );
00198     Range::const_pair_iterator i;
00199     for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00200     {
00201         unpack( i->first, type, page, offset );
00202         assert( TYPE_FROM_HANDLE( i->second ) == type );  // Should be true because id of zero is never used
00203         count = i->second - i->first + 1;
00204 
00205         while( count )
00206         {
00207             if( page >= pageList[type].size() ) pageList[type].resize( page + 1, 0 );
00208             if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, def );
00209 
00210             size_t pcount = std::min( ( EntityID )( per_page - offset ), count );
00211             pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, data );
00212             data += pcount;
00213             count -= pcount;
00214             offset = 0;
00215             ++page;
00216         }
00217     }
00218 
00219     return MB_SUCCESS;
00220 }
00221 
00222 ErrorCode BitTag::clear_data( SequenceManager* seqman, Error* /* error */, const Range& handles, const void* value_ptr,
00223                               int value_len )
00224 {
00225     if( value_len ) return MB_INVALID_SIZE;
00226 
00227     ErrorCode rval = seqman->check_valid_entities( NULL, handles );MB_CHK_ERR( rval );
00228 
00229     EntityType type;
00230     EntityID count;
00231     size_t page;
00232     int offset, per_page = ents_per_page();
00233     const unsigned char value = *reinterpret_cast< const unsigned char* >( value_ptr );
00234     Range::const_pair_iterator i;
00235     for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00236     {
00237         unpack( i->first, type, page, offset );
00238         assert( TYPE_FROM_HANDLE( i->second ) == type );  // Should be true because id of zero is never used
00239         count = i->second - i->first + 1;
00240 
00241         while( count )
00242         {
00243             if( page >= pageList[type].size() ) pageList[type].resize( page + 1, 0 );
00244             if( !pageList[type][page] ) pageList[type][page] = new BitPage( storedBitsPerEntity, default_val() );
00245 
00246             size_t pcount = std::min( ( EntityID )( per_page - offset ), count );
00247             pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, value );
00248             count -= pcount;
00249             offset = 0;
00250             ++page;
00251         }
00252     }
00253 
00254     return MB_SUCCESS;
00255 }
00256 
00257 ErrorCode BitTag::remove_data( SequenceManager*, Error*, const Range& handles )
00258 {
00259     EntityType type;
00260     EntityID count;
00261     size_t page;
00262     int offset, per_page = ents_per_page();
00263     unsigned char val = default_val();
00264     Range::const_pair_iterator i;
00265     for( i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i )
00266     {
00267         unpack( i->first, type, page, offset );
00268         assert( TYPE_FROM_HANDLE( i->second ) == type );  // Should be true because id of zero is never used
00269         count = i->second - i->first + 1;
00270 
00271         while( count )
00272         {
00273             size_t pcount = std::min( ( EntityID )( per_page - offset ), count );
00274             if( page < pageList[type].size() && pageList[type][page] )
00275                 pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, val );
00276             count -= pcount;
00277             offset = 0;
00278             ++page;
00279         }
00280     }
00281 
00282     return MB_SUCCESS;
00283 }
00284 
00285 ErrorCode BitTag::get_data( const SequenceManager*, Error* /* error */, const EntityHandle*, size_t, const void**,
00286                             int* ) const
00287 {
00288     MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation get_data not supported for bit tags" );
00289 }
00290 
00291 ErrorCode BitTag::get_data( const SequenceManager*, Error* /* error */, const Range&, const void**, int* ) const
00292 {
00293     MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation get_data not supported for bit tags" );
00294 }
00295 
00296 ErrorCode BitTag::set_data( SequenceManager*, Error* /* error */, const EntityHandle*, size_t, void const* const*,
00297                             const int* )
00298 {
00299     MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation set_data not supported for bit tags" );
00300 }
00301 
00302 ErrorCode BitTag::set_data( SequenceManager*, Error* /* error */, const Range&, void const* const*, const int* )
00303 {
00304     MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation set_data not supported for bit tags" );
00305 }
00306 
00307 ErrorCode BitTag::tag_iterate( SequenceManager*, Error* /* error */, Range::iterator&, const Range::iterator&, void*&,
00308                                bool )
00309 {
00310     MB_SET_ERR( MB_TYPE_OUT_OF_RANGE, "Operation tag_iterate not supported for bit tags" );
00311 }
00312 
00313 template < class Container >
00314 inline void BitTag::get_tagged( EntityType type, Container& entities ) const
00315 {
00316     std::pair< EntityType, EntityType > r = type_range( type );
00317     typename Container::iterator hint     = entities.begin();
00318     const int per_page                    = ents_per_page();
00319     for( EntityType t = r.first; t != r.second; ++t )
00320     {
00321         for( size_t i = 0; i < pageList[t].size(); ++i )
00322         {
00323             if( pageList[t][i] )
00324             {
00325                 EntityID id       = i * per_page;
00326                 EntityHandle h    = CREATE_HANDLE( t, id );
00327                 EntityHandle last = h + per_page - 1;
00328                 // Never zero ID
00329                 if( 0 == id ) ++h;
00330                 hint = entities.insert( hint, h, last );
00331             }
00332         }
00333     }
00334 }
00335 
00336 template < class Container >
00337 inline void BitTag::get_tagged( Range::const_iterator begin, Range::const_iterator end, Container& entities ) const
00338 {
00339     EntityType type;
00340     EntityID count;
00341     size_t page;
00342     int offset, per_page = ents_per_page();
00343     typename Container::iterator hint = entities.begin();
00344     EntityHandle h;
00345     Range::const_iterator i = begin;
00346     while( i != end )
00347     {
00348         h = *i;
00349         unpack( h, type, page, offset );
00350 
00351         i     = i.end_of_block();
00352         count = *i - h + 1;
00353         ++i;
00354         while( count > 0 )
00355         {
00356             EntityID pcount = std::min( count, ( EntityID )( per_page - offset ) );
00357             if( page < pageList[type].size() && pageList[type][page] )
00358                 hint = entities.insert( hint, h, h + pcount - 1 );
00359 
00360             count -= pcount;
00361             h += pcount;
00362             assert( TYPE_FROM_HANDLE( h ) == type );
00363             offset = 0;
00364             ++page;
00365         }
00366     }
00367 }
00368 
00369 template < class Container >
00370 inline void BitTag::get_tagged( Container& entities, EntityType type, const Range* intersect ) const
00371 
00372 {
00373     if( !intersect )
00374         get_tagged< Container >( type, entities );
00375     else if( MBMAXTYPE == type )
00376         get_tagged< Container >( intersect->begin(), intersect->end(), entities );
00377     else
00378     {
00379         std::pair< Range::iterator, Range::iterator > r = intersect->equal_range( type );
00380         get_tagged< Container >( r.first, r.second, entities );
00381     }
00382 }
00383 
00384 ErrorCode BitTag::get_tagged_entities( const SequenceManager*, Range& entities, EntityType type,
00385                                        const Range* intersect ) const
00386 {
00387     get_tagged< Range >( entities, type, intersect );
00388     return MB_SUCCESS;
00389 }
00390 
00391 ErrorCode BitTag::num_tagged_entities( const SequenceManager*, size_t& count, EntityType type,
00392                                        const Range* intersect ) const
00393 {
00394     InsertCount counter( count );
00395     get_tagged< InsertCount >( counter, type, intersect );
00396     count = counter.end();
00397     return MB_SUCCESS;
00398 }
00399 
00400 ErrorCode BitTag::find_entities_with_value( const SequenceManager*, Error* /* error */, Range& output_entities,
00401                                             const void* value, int value_bytes, EntityType type,
00402                                             const Range* intersect_entities ) const
00403 {
00404     if( value_bytes && value_bytes != 1 )
00405     { MB_SET_ERR( MB_INVALID_SIZE, "Invalid tag size for bit tag: " << value_bytes << " bytes" ); }
00406 
00407     const signed char bits = *reinterpret_cast< const unsigned char* >( value );
00408     if( intersect_entities )
00409         return get_entities_with_bits( *intersect_entities, type, output_entities, bits );
00410     else
00411         return get_entities_with_bits( type, output_entities, bits );
00412 }
00413 
00414 ErrorCode BitTag::get_entities_with_bits( EntityType type, Range& entities, unsigned char bits ) const
00415 {
00416     std::pair< EntityType, EntityType > r = type_range( type );
00417     const int per_page                    = ents_per_page();
00418     for( EntityType t = r.first; t != r.second; ++t )
00419     {
00420         for( size_t i = 0; i < pageList[t].size(); ++i )
00421         {
00422             if( pageList[t][i] )
00423             {
00424                 EntityID id    = i * per_page;
00425                 EntityHandle h = CREATE_HANDLE( t, id );
00426                 int off        = !i;  // Never zero ID
00427                 pageList[t][i]->search( bits, off, per_page - off, storedBitsPerEntity, entities, h + off );
00428             }
00429         }
00430     }
00431 
00432     return MB_SUCCESS;
00433 }
00434 
00435 ErrorCode BitTag::get_entities_with_bits( const Range& range, EntityType in_type, Range& entities,
00436                                           unsigned char bits ) const
00437 {
00438     if( MBMAXTYPE == in_type )
00439     {
00440         ErrorCode rval;
00441         for( --in_type; in_type >= MBVERTEX; --in_type )
00442         {
00443             rval = get_entities_with_bits( range, in_type, entities, bits );MB_CHK_ERR( rval );
00444         }
00445         return MB_SUCCESS;
00446     }
00447 
00448     EntityType type;
00449     EntityID count;
00450     size_t page;
00451     int offset, per_page = ents_per_page();
00452     Range::const_iterator i, end;
00453     std::pair< Range::iterator, Range::iterator > r = range.equal_range( in_type );
00454     i                                               = r.first;
00455     end                                             = r.second;
00456     EntityHandle h;
00457     while( i != end )
00458     {
00459         h = *i;
00460         unpack( h, type, page, offset );
00461         assert( MBMAXTYPE == in_type || type == in_type );
00462 
00463         i     = i.end_of_block();
00464         count = *i - h + 1;
00465         ++i;
00466         while( count > 0 )
00467         {
00468             EntityID pcount = std::min( count, ( EntityID )( per_page - offset ) );
00469             if( page < pageList[type].size() && pageList[type][page] )
00470                 pageList[type][page]->search( bits, offset, pcount, storedBitsPerEntity, entities, h );
00471 
00472             count -= pcount;
00473             h += pcount;
00474             assert( TYPE_FROM_HANDLE( h ) == type );
00475             offset = 0;
00476             ++page;
00477         }
00478     }
00479 
00480     return MB_SUCCESS;
00481 }
00482 
00483 ErrorCode BitTag::get_memory_use( const SequenceManager*, unsigned long& total, unsigned long& per_entity ) const
00484 {
00485     per_entity = ( storedBitsPerEntity > 4 );  // Cannot return fraction of bytes, so round
00486     total      = 0;
00487     for( EntityType t = (EntityType)0; t < MBMAXTYPE; ++t )
00488     {
00489         total += pageList[t].capacity() * sizeof( BitPage* );
00490         for( size_t i = 0; i < pageList[t].size(); ++i )
00491             if( pageList[t][i] ) total += sizeof( BitPage );
00492     }
00493 
00494     return MB_SUCCESS;
00495 }
00496 
00497 bool BitTag::is_tagged( const SequenceManager*, EntityHandle h ) const
00498 {
00499     EntityType type;
00500     size_t page;
00501     int offset;
00502     unpack( h, type, page, offset );
00503     return page < pageList[type].size() && pageList[type][page];
00504 }
00505 
00506 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines