MOAB: Mesh Oriented datABase
(version 5.2.1)
|
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