Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #include "TypeSequenceManager.hpp" 00002 #include "SequenceData.hpp" 00003 #include "moab/Error.hpp" 00004 #include <cassert> 00005 #include <limits> 00006 00007 namespace moab 00008 { 00009 00010 TypeSequenceManager::~TypeSequenceManager() 00011 { 00012 // We assume that for there to be multiple sequences referencing 00013 // the same SequenceData, there must be some portion of the 00014 // SequenceData that is unused. Otherwise the sequences should 00015 // have been merged. Given that assumption, it is the case that 00016 // either a) a SequenceData is in availableList or b) the 00017 // SequenceData is referenced by exactly one sequence. 00018 00019 // Delete every entity sequence 00020 for( iterator i = begin(); i != end(); ++i ) 00021 { 00022 EntitySequence* seq = *i; 00023 // Check for case b) above 00024 if( seq->using_entire_data() ) 00025 { 00026 // Delete sequence before data, because sequence 00027 // has a pointer to data and may try to dereference 00028 // that pointer during its destruction. 00029 SequenceData* data = seq->data(); 00030 delete seq; 00031 delete data; 00032 } 00033 else 00034 { 00035 delete seq; 00036 } 00037 } 00038 sequenceSet.clear(); 00039 00040 // Case a) above 00041 for( data_iterator i = availableList.begin(); i != availableList.end(); ++i ) 00042 delete *i; 00043 availableList.clear(); 00044 } 00045 00046 ErrorCode TypeSequenceManager::merge_internal( iterator i, iterator j ) 00047 { 00048 EntitySequence* dead = *j; 00049 sequenceSet.erase( j ); 00050 ErrorCode rval = ( *i )->merge( *dead ); 00051 if( MB_SUCCESS != rval ) 00052 { 00053 sequenceSet.insert( dead ); 00054 return rval; 00055 } 00056 00057 if( lastReferenced == dead ) lastReferenced = *i; 00058 delete dead; 00059 00060 // If merging results in no unused portions of the SequenceData, 00061 // remove it from the available list. 00062 if( ( *i )->using_entire_data() ) availableList.erase( ( *i )->data() ); 00063 00064 return MB_SUCCESS; 00065 } 00066 00067 ErrorCode TypeSequenceManager::check_merge_next( iterator i ) 00068 { 00069 iterator j = i; 00070 ++j; 00071 if( j == end() || ( *j )->data() != ( *i )->data() || ( *j )->start_handle() > ( *i )->end_handle() + 1 ) 00072 return MB_SUCCESS; 00073 00074 assert( ( *i )->end_handle() + 1 == ( *j )->start_handle() ); 00075 return merge_internal( i, j ); 00076 } 00077 00078 ErrorCode TypeSequenceManager::check_merge_prev( iterator i ) 00079 { 00080 if( i == begin() ) return MB_SUCCESS; 00081 00082 iterator j = i; 00083 --j; 00084 if( ( *j )->data() != ( *i )->data() || ( *j )->end_handle() + 1 < ( *i )->start_handle() ) return MB_SUCCESS; 00085 00086 assert( ( *j )->end_handle() + 1 == ( *i )->start_handle() ); 00087 return merge_internal( i, j ); 00088 } 00089 00090 ErrorCode TypeSequenceManager::insert_sequence( EntitySequence* seq_ptr ) 00091 { 00092 if( !seq_ptr->data() ) return MB_FAILURE; 00093 00094 if( seq_ptr->data()->start_handle() > seq_ptr->start_handle() || 00095 seq_ptr->data()->end_handle() < seq_ptr->end_handle() || seq_ptr->end_handle() < seq_ptr->start_handle() ) 00096 return MB_FAILURE; 00097 00098 iterator i = lower_bound( seq_ptr->start_handle() ); 00099 if( i != end() ) 00100 { 00101 if( ( *i )->start_handle() <= seq_ptr->end_handle() ) return MB_ALREADY_ALLOCATED; 00102 if( seq_ptr->data() != ( *i )->data() && ( *i )->data()->start_handle() <= seq_ptr->data()->end_handle() ) 00103 return MB_ALREADY_ALLOCATED; 00104 } 00105 00106 if( i != begin() ) 00107 { 00108 iterator j = i; 00109 --j; 00110 if( seq_ptr->data() != ( *j )->data() && ( *j )->data()->end_handle() >= seq_ptr->data()->start_handle() ) 00111 return MB_ALREADY_ALLOCATED; 00112 } 00113 00114 i = sequenceSet.insert( i, seq_ptr ); 00115 00116 // Merge with previous sequence ? 00117 if( seq_ptr->start_handle() > seq_ptr->data()->start_handle() && i != begin() ) 00118 { 00119 if( MB_SUCCESS != check_merge_prev( i ) ) 00120 { 00121 sequenceSet.erase( i ); 00122 return MB_FAILURE; 00123 } 00124 } 00125 00126 // Merge with next sequence ? 00127 if( ( *i )->end_handle() < ( *i )->data()->end_handle() ) 00128 { 00129 if( MB_SUCCESS != check_merge_next( i ) ) 00130 { 00131 sequenceSet.erase( i ); 00132 return MB_FAILURE; 00133 } 00134 } 00135 00136 // We merged adjacent sequences sharing a SequenceData, so 00137 // we can safely assume that unless this EntitySequence is 00138 // using the entire SequenceData, there are unused portions. 00139 if( !seq_ptr->using_entire_data() ) availableList.insert( seq_ptr->data() ); 00140 00141 // lastReferenced is only allowed to be NULL if there are 00142 // no sequences (avoids unnecessary if's in fast path). 00143 if( !lastReferenced ) lastReferenced = seq_ptr; 00144 00145 // Each SequenceData has a pointer to the first EntitySequence 00146 // referencing it. Update that pointer if the new sequence is 00147 // the first one. 00148 if( ( *i )->start_handle() == ( *i )->data()->start_handle() || lower_bound( ( *i )->data()->start_handle() ) == i ) 00149 ( *i )->data()->seqManData.firstSequence = i; 00150 00151 assert( check_valid_data( seq_ptr ) ); 00152 return MB_SUCCESS; 00153 } 00154 00155 ErrorCode TypeSequenceManager::replace_subsequence( EntitySequence* seq_ptr, const int* tag_sizes, int num_tag_sizes ) 00156 { 00157 // Find the sequence of interest 00158 iterator i = lower_bound( seq_ptr->start_handle() ); 00159 if( i == end() || ( *i )->data() == seq_ptr->data() ) return MB_FAILURE; 00160 // New sequence must be a subset of an existing one 00161 if( seq_ptr->start_handle() < ( *i )->start_handle() || seq_ptr->end_handle() > ( *i )->end_handle() ) 00162 return MB_FAILURE; 00163 // New sequence's data must be new also, and cannot intersect 00164 // any existing sequence (just require that the data range 00165 // matches the sequence range for now) 00166 if( !seq_ptr->using_entire_data() ) return MB_FAILURE; 00167 // Copy tag data (move ownership of var-len data) 00168 SequenceData* const dead_data = ( *i )->data(); 00169 dead_data->move_tag_data( seq_ptr->data(), tag_sizes, num_tag_sizes ); 00170 00171 // Split sequences sharing old data into two groups: 00172 // p->i : first sequence to i 00173 // i->n : i to one past last sequence 00174 iterator p, n = i; 00175 p = ( *i )->data()->seqManData.firstSequence; 00176 for( ++n; n != end() && ( *n )->data() == ( *i )->data(); ++n ) 00177 ; 00178 00179 // First subdivide EntitySequence as necessary 00180 // Move i to be the first sequence past the insertion point 00181 // such that the new order will be: 00182 // [p,i-1] seq_ptr [i,n] 00183 // where p == i if no previous sequence 00184 00185 // Four possible cases: 00186 // 0. All entities in sequence are in new sequence 00187 // 1. Old entities in sequence before and after new sequence, 00188 // requiring sequence to be split. 00189 // 2. Old entities after new sequence 00190 // 3. Old entities before new sequence 00191 const bool some_before = ( ( *i )->start_handle() < seq_ptr->start_handle() ); 00192 const bool some_after = ( ( *i )->end_handle() > seq_ptr->end_handle() ); 00193 // Case 0 00194 if( !( some_before || some_after ) ) 00195 { 00196 // Remove dead sequence from internal lists 00197 EntitySequence* seq = *i; 00198 iterator dead = i; 00199 ++i; 00200 if( p == dead ) p = i; 00201 sequenceSet.erase( dead ); 00202 00203 // Delete old sequence 00204 delete seq; 00205 // Make sure lastReferenced isn't stale 00206 if( lastReferenced == seq ) lastReferenced = seq_ptr; 00207 } 00208 // Case 1 00209 else if( some_before && some_after ) 00210 { 00211 i = split_sequence( i, seq_ptr->start_handle() ); 00212 ( *i )->pop_front( seq_ptr->size() ); 00213 } 00214 // Case 2 00215 else if( some_after ) 00216 { 00217 ( *i )->pop_front( seq_ptr->size() ); 00218 } 00219 // Case 3 00220 else 00221 { // some_before 00222 ( *i )->pop_back( seq_ptr->size() ); 00223 ++i; 00224 } 00225 00226 // Now subdivide the underlying sequence data as necessary 00227 availableList.erase( dead_data ); 00228 if( p != i ) 00229 { 00230 iterator last = i; 00231 --last; 00232 SequenceData* new_data = ( *p )->create_data_subset( ( *p )->start_handle(), ( *last )->end_handle() ); 00233 new_data->seqManData.firstSequence = p; 00234 00235 for( ; p != i; ++p ) 00236 ( *p )->data( new_data ); 00237 // Copy tag data (move ownership of var-len data) 00238 dead_data->move_tag_data( new_data, tag_sizes, num_tag_sizes ); 00239 if( !( *new_data->seqManData.firstSequence )->using_entire_data() ) availableList.insert( new_data ); 00240 } 00241 if( i != n ) 00242 { 00243 iterator last = n; 00244 --last; 00245 SequenceData* new_data = ( *i )->create_data_subset( ( *i )->start_handle(), ( *last )->end_handle() ); 00246 new_data->seqManData.firstSequence = i; 00247 for( ; i != n; ++i ) 00248 ( *i )->data( new_data ); 00249 // Copy tag data (move ownership of var-len data) 00250 dead_data->move_tag_data( new_data, tag_sizes, num_tag_sizes ); 00251 if( !( *new_data->seqManData.firstSequence )->using_entire_data() ) availableList.insert( new_data ); 00252 } 00253 delete dead_data; 00254 00255 // Put new sequence in lists 00256 return insert_sequence( seq_ptr ); 00257 } 00258 00259 TypeSequenceManager::iterator TypeSequenceManager::erase( iterator i ) 00260 { 00261 EntitySequence* seq = *i; 00262 SequenceData* data = seq->data(); 00263 iterator j; 00264 00265 // Check if we need to delete the referenced SequenceData also 00266 bool delete_data; 00267 if( seq->using_entire_data() ) // Only sequence 00268 delete_data = true; 00269 else if( data->seqManData.firstSequence != i ) 00270 { // Earlier sequence? 00271 delete_data = false; 00272 availableList.insert( data ); 00273 } 00274 else 00275 { // Later sequence ? 00276 j = i; 00277 ++j; 00278 delete_data = ( j == end() || ( *j )->data() != data ); 00279 if( delete_data ) 00280 availableList.erase( data ); 00281 else 00282 { 00283 availableList.insert( data ); 00284 data->seqManData.firstSequence = j; 00285 } 00286 } 00287 00288 // Remove sequence, updating i to be next sequence 00289 j = i++; 00290 sequenceSet.erase( j ); 00291 00292 // Make sure lastReferenced isn't stale. It can only be NULL if 00293 // no sequences. 00294 if( lastReferenced == seq ) lastReferenced = sequenceSet.empty() ? 0 : *sequenceSet.begin(); 00295 00296 // Always delete sequence before the SequenceData it references. 00297 assert( 0 == find( seq->start_handle() ) ); 00298 delete seq; 00299 if( delete_data ) 00300 delete data; 00301 else 00302 { 00303 assert( check_valid_data( *data->seqManData.firstSequence ) ); 00304 assert( lastReferenced != seq ); 00305 } 00306 return i; 00307 } 00308 00309 ErrorCode TypeSequenceManager::remove_sequence( const EntitySequence* seq_ptr, bool& unreferenced_data ) 00310 { 00311 // Remove sequence from set 00312 iterator i = lower_bound( seq_ptr->start_handle() ); 00313 if( i == end() || *i != seq_ptr ) return MB_ENTITY_NOT_FOUND; 00314 sequenceSet.erase( i ); 00315 00316 // Check if this is the only sequence referencing its data 00317 if( seq_ptr->using_entire_data() ) 00318 unreferenced_data = true; 00319 else 00320 { 00321 i = lower_bound( seq_ptr->data()->start_handle() ); 00322 unreferenced_data = i == end() || ( *i )->data() != seq_ptr->data(); 00323 if( unreferenced_data ) 00324 availableList.erase( seq_ptr->data() ); 00325 else 00326 seq_ptr->data()->seqManData.firstSequence = i; // Might be 'i' already 00327 } 00328 00329 if( lastReferenced == seq_ptr ) lastReferenced = sequenceSet.empty() ? 0 : *sequenceSet.begin(); 00330 00331 return MB_SUCCESS; 00332 } 00333 00334 TypeSequenceManager::iterator TypeSequenceManager::find_free_handle( EntityHandle min_start_handle, 00335 EntityHandle max_end_handle, 00336 bool& append_out, 00337 int values_per_ent ) 00338 { 00339 for( data_iterator i = availableList.begin(); i != availableList.end(); ++i ) 00340 { 00341 if( ( *( *i )->seqManData.firstSequence )->values_per_entity() != values_per_ent ) continue; 00342 00343 if( ( *i )->start_handle() > max_end_handle || ( *i )->end_handle() < min_start_handle ) continue; 00344 00345 for( iterator j = ( *i )->seqManData.firstSequence; 00346 j != end() && ( *j )->start_handle() <= ( max_end_handle + 1 ) && ( *j )->data() == *i; ++j ) 00347 { 00348 if( ( *j )->end_handle() + 1 < min_start_handle ) continue; 00349 if( ( *j )->start_handle() > ( *i )->start_handle() && ( *j )->start_handle() > min_start_handle ) 00350 { 00351 append_out = false; 00352 return j; 00353 } 00354 if( ( *j )->end_handle() < ( *i )->end_handle() && ( *j )->end_handle() < max_end_handle ) 00355 { 00356 append_out = true; 00357 return j; 00358 } 00359 } 00360 } 00361 00362 return end(); 00363 } 00364 00365 bool TypeSequenceManager::is_free_sequence( EntityHandle start, 00366 EntityID num_entities, 00367 SequenceData*& data_out, 00368 int values_per_ent ) 00369 { 00370 data_out = 0; 00371 if( empty() ) return true; 00372 00373 const_iterator i = lower_bound( start ); 00374 if( i == end() ) 00375 { 00376 --i; // Safe because already tested empty() 00377 // If we don't overlap the last data object... 00378 if( ( *i )->data()->end_handle() < start ) return true; 00379 data_out = ( *i )->data(); 00380 if( ( *i )->values_per_entity() != values_per_ent ) return false; 00381 // If we overlap a data object, we must be entirely inside of it 00382 return start + num_entities - 1 <= ( *i )->data()->end_handle(); 00383 } 00384 00385 #ifndef NDEBUG 00386 if( i != begin() ) 00387 { 00388 const_iterator j = i; 00389 --j; 00390 assert( ( *j )->end_handle() < start ); 00391 } 00392 #endif 00393 00394 // Check if we fit in the block of free handles 00395 if( start + num_entities > ( *i )->start_handle() ) // start + num + 1 >= i->start 00396 return false; 00397 00398 // Check if we overlap the data for the next sequence 00399 if( start + num_entities > ( *i )->data()->start_handle() ) 00400 { 00401 data_out = ( *i )->data(); 00402 if( ( *i )->values_per_entity() != values_per_ent ) return false; 00403 // If overlap, must be entirely contained 00404 return start >= data_out->start_handle() && start + num_entities - 1 <= data_out->end_handle(); 00405 } 00406 00407 // Check if we overlap the data for the previous sequence 00408 if( i != begin() ) 00409 { 00410 --i; 00411 if( ( *i )->data()->end_handle() >= start ) 00412 { 00413 data_out = ( *i )->data(); 00414 if( ( *i )->values_per_entity() != values_per_ent ) return false; 00415 return start + num_entities - 1 <= ( *i )->data()->end_handle(); 00416 } 00417 } 00418 00419 // Unused handle block that overlaps no SequenceData 00420 return true; 00421 } 00422 00423 EntityHandle TypeSequenceManager::find_free_block( EntityID num_entities, 00424 EntityHandle min_start_handle, 00425 EntityHandle max_end_handle ) 00426 { 00427 const_iterator i = lower_bound( min_start_handle ); 00428 if( i == end() ) return min_start_handle; 00429 00430 if( ( *i )->start_handle() < min_start_handle + num_entities ) return min_start_handle; 00431 00432 EntityHandle prev_end = ( *i )->end_handle(); 00433 ++i; 00434 for( ; i != end(); prev_end = ( *i )->end_handle(), ++i ) 00435 { 00436 EntityID len = ( *i )->start_handle() - prev_end - 1; 00437 if( len >= num_entities ) break; 00438 } 00439 00440 if( prev_end + num_entities > max_end_handle ) 00441 return 0; 00442 else 00443 return prev_end + 1; 00444 } 00445 00446 struct range_data 00447 { 00448 EntityID num_entities; 00449 EntityHandle min_start_handle, max_end_handle; 00450 EntityHandle first, last; 00451 }; 00452 00453 static bool check_range( const range_data& d, bool prefer_end, EntityHandle& result ) 00454 { 00455 EntityHandle first = std::max( d.min_start_handle, d.first ); 00456 EntityHandle last = std::min( d.max_end_handle, d.last ); 00457 if( last < first + d.num_entities - 1 ) 00458 { 00459 result = 0; 00460 return false; 00461 } 00462 00463 result = prefer_end ? last + 1 - d.num_entities : first; 00464 return true; 00465 } 00466 00467 EntityHandle TypeSequenceManager::find_free_sequence( EntityID num_entities, 00468 EntityHandle min_start_handle, 00469 EntityHandle max_end_handle, 00470 SequenceData*& data_out, 00471 EntityID& data_size, 00472 int num_verts ) 00473 { 00474 if( max_end_handle < min_start_handle + num_entities - 1 ) return 0; 00475 00476 EntityHandle result; 00477 iterator p, i = lower_bound( min_start_handle ); 00478 range_data d = { num_entities, min_start_handle, max_end_handle, 0, 0 }; 00479 00480 if( i == end() ) 00481 { 00482 data_out = 0; 00483 return min_start_handle; 00484 } 00485 else if( i == begin() ) 00486 { 00487 if( ( *i )->values_per_entity() == num_verts ) 00488 { 00489 d.first = ( *i )->data()->start_handle(); 00490 d.last = ( *i )->start_handle() - 1; 00491 if( check_range( d, true, result ) ) 00492 { 00493 data_out = ( *i )->data(); 00494 return result; 00495 } 00496 } 00497 d.first = min_start_handle; 00498 d.last = ( *i )->data()->start_handle() - 1; 00499 if( check_range( d, true, result ) ) 00500 { 00501 data_out = 0; 00502 // This will back up against the end of the seq data, so 00503 // size the data that way 00504 data_size = num_entities; 00505 return result; 00506 } 00507 p = i++; 00508 } 00509 else 00510 { 00511 p = i; 00512 --p; 00513 } 00514 00515 for( ; i != end() && ( *i )->start_handle() < max_end_handle; p = i++ ) 00516 { 00517 if( ( *p )->data() == ( *i )->data() ) 00518 { 00519 if( ( *p )->values_per_entity() == num_verts ) 00520 { 00521 d.first = ( *p )->end_handle() + 1; 00522 d.last = ( *i )->start_handle() - 1; 00523 if( check_range( d, false, result ) ) 00524 { 00525 data_out = ( *p )->data(); 00526 return result; 00527 } 00528 } 00529 } 00530 else 00531 { 00532 if( ( *p )->values_per_entity() == num_verts ) 00533 { 00534 d.first = ( *p )->end_handle() + 1; 00535 d.last = ( *p )->data()->end_handle(); 00536 if( check_range( d, false, result ) ) 00537 { 00538 data_out = ( *p )->data(); 00539 return result; 00540 } 00541 } 00542 if( ( *i )->values_per_entity() == num_verts ) 00543 { 00544 d.first = ( *i )->data()->start_handle(); 00545 d.last = ( *i )->start_handle() - 1; 00546 if( check_range( d, true, result ) ) 00547 { 00548 data_out = ( *i )->data(); 00549 return result; 00550 } 00551 } 00552 d.first = ( *p )->data()->end_handle() + 1; 00553 d.last = ( *i )->data()->start_handle() - 1; 00554 if( check_range( d, false, result ) ) 00555 { 00556 data_out = 0; 00557 data_size = d.last - d.first + 1; 00558 return result; 00559 } 00560 } 00561 } 00562 00563 if( ( *p )->values_per_entity() == num_verts ) 00564 { 00565 d.first = ( *p )->end_handle() + 1; 00566 d.last = ( *p )->data()->end_handle(); 00567 if( check_range( d, false, result ) ) 00568 { 00569 data_out = ( *p )->data(); 00570 return result; 00571 } 00572 } 00573 00574 d.first = ( *p )->data()->end_handle() + 1; 00575 d.last = max_end_handle; 00576 if( check_range( d, false, result ) ) 00577 { 00578 data_out = 0; 00579 return result; 00580 } 00581 00582 data_out = 0; 00583 return 0; 00584 } 00585 00586 EntityHandle TypeSequenceManager::last_free_handle( EntityHandle after_this ) const 00587 { 00588 int junk; 00589 const_iterator it = lower_bound( after_this ); 00590 if( it == end() ) 00591 return CREATE_HANDLE( TYPE_FROM_HANDLE( after_this ), MB_END_ID, junk ); 00592 else if( ( *it )->start_handle() > after_this ) 00593 { 00594 // Need to check against the sequence data first 00595 EntityHandle rhandle = ( *it )->data()->start_handle(); 00596 return rhandle - 1; 00597 } 00598 else 00599 return 0; 00600 } 00601 00602 ErrorCode TypeSequenceManager::check_valid_handles( Error* /* error_handler */, 00603 EntityHandle first, 00604 EntityHandle last ) const 00605 { 00606 const_iterator i = lower_bound( first ); 00607 if( i == end() || ( *i )->start_handle() > first ) 00608 { 00609 #if 0 00610 // MB_ENTITY_NOT_FOUND could be a non-error condition, do not call 00611 // MB_SET_ERR on it 00612 fprintf( 00613 stderr, 00614 "[Warning]: Invalid entity handle: 0x%lx\n", (unsigned long)first 00615 ); 00616 #endif 00617 return MB_ENTITY_NOT_FOUND; 00618 } 00619 00620 while( ( *i )->end_handle() < last ) 00621 { 00622 EntityHandle prev_end = ( *i )->end_handle(); 00623 ++i; 00624 if( i == end() || prev_end + 1 != ( *i )->start_handle() ) return MB_ENTITY_NOT_FOUND; 00625 } 00626 00627 return MB_SUCCESS; 00628 } 00629 00630 ErrorCode TypeSequenceManager::erase( Error* /* error_handler */, EntityHandle h ) 00631 { 00632 EntitySequence* seq = find( h ); 00633 if( !seq ) 00634 { 00635 #if 0 00636 // MB_ENTITY_NOT_FOUND could be a non-error condition, do not call 00637 // MB_SET_ERR on it 00638 fprintf( 00639 stderr, 00640 "[Warning]: Invalid entity handle: 0x%lx\n", (unsigned long)h 00641 ); 00642 #endif 00643 return MB_ENTITY_NOT_FOUND; 00644 } 00645 00646 if( seq->start_handle() == h ) 00647 { 00648 if( seq->end_handle() != h ) 00649 { 00650 if( seq->using_entire_data() ) availableList.insert( seq->data() ); 00651 seq->pop_front( 1 ); 00652 return MB_SUCCESS; 00653 } 00654 SequenceData* data = seq->data(); 00655 bool delete_data; 00656 ErrorCode rval = remove_sequence( seq, delete_data ); 00657 if( MB_SUCCESS != rval ) return rval; 00658 delete seq; 00659 if( delete_data ) delete data; 00660 } 00661 else if( seq->end_handle() == h ) 00662 { 00663 if( seq->using_entire_data() ) availableList.insert( seq->data() ); 00664 seq->pop_back( 1 ); 00665 } 00666 else 00667 { 00668 iterator i = lower_bound( h ); 00669 if( ( *i )->using_entire_data() ) availableList.insert( ( *i )->data() ); 00670 i = split_sequence( i, h ); 00671 seq = *i; 00672 assert( seq->start_handle() == h ); 00673 seq->pop_front( 1 ); 00674 } 00675 00676 return MB_SUCCESS; 00677 } 00678 00679 ErrorCode TypeSequenceManager::erase( Error* /* error */, EntityHandle first, EntityHandle last ) 00680 { 00681 // First check that all entities in range are valid 00682 00683 ErrorCode rval = check_valid_handles( NULL, first, last ); 00684 if( MB_SUCCESS != rval ) return rval; 00685 00686 // Now remove entities 00687 00688 // Get first sequence intersecting range 00689 iterator i = lower_bound( first ); 00690 if( i == end() ) // Shouldn't be possible given check_valid_handles call above. 00691 return MB_ENTITY_NOT_FOUND; 00692 00693 // If range is entirely in interior of sequence, need to split sequence. 00694 if( ( *i )->start_handle() < first && ( *i )->end_handle() > last ) 00695 { 00696 if( ( *i )->using_entire_data() ) availableList.insert( ( *i )->data() ); 00697 i = split_sequence( i, first ); 00698 ( *i )->pop_front( last - first + 1 ); 00699 assert( check_valid_data( *i ) ); 00700 return MB_SUCCESS; 00701 } 00702 00703 // If range doesn't entirely contain first sequence, remove some 00704 // handles from the end of the sequence and advance to the next 00705 // sequence. 00706 if( ( *i )->start_handle() < first ) 00707 { 00708 if( ( *i )->using_entire_data() ) availableList.insert( ( *i )->data() ); 00709 ( *i )->pop_back( ( *i )->end_handle() - first + 1 ); 00710 ++i; 00711 } 00712 00713 // Destroy all sequences contained entirely within the range 00714 while( i != end() && ( *i )->end_handle() <= last ) 00715 i = erase( i ); 00716 00717 // If necessary, remove entities from the beginning of the 00718 // last sequence. 00719 if( i != end() && ( *i )->start_handle() <= last ) 00720 { 00721 if( ( *i )->using_entire_data() ) availableList.insert( ( *i )->data() ); 00722 ( *i )->pop_front( last - ( *i )->start_handle() + 1 ); 00723 assert( check_valid_data( *i ) ); 00724 } 00725 00726 return MB_SUCCESS; 00727 } 00728 00729 TypeSequenceManager::iterator TypeSequenceManager::split_sequence( iterator i, EntityHandle h ) 00730 { 00731 EntitySequence* seq = ( *i )->split( h ); 00732 if( !seq ) return end(); 00733 00734 i = sequenceSet.insert( i, seq ); 00735 assert( check_valid_data( *i ) ); 00736 00737 return i; 00738 } 00739 00740 ErrorCode TypeSequenceManager::is_free_handle( EntityHandle handle, 00741 iterator& seq_iter_out, 00742 SequenceData*& data_ptr_out, 00743 EntityHandle& block_start, 00744 EntityHandle& block_end, 00745 int values_per_ent ) 00746 { 00747 int junk; 00748 block_start = CREATE_HANDLE( TYPE_FROM_HANDLE( handle ), MB_START_ID, junk ); 00749 block_end = CREATE_HANDLE( TYPE_FROM_HANDLE( handle ), MB_END_ID, junk ); 00750 00751 iterator i = lower_bound( handle ); 00752 if( i != end() ) 00753 { 00754 block_end = ( *i )->start_handle() - 1; 00755 00756 // If sequence contains handle, then already allocated 00757 if( ( *i )->start_handle() <= handle ) return MB_ALREADY_ALLOCATED; 00758 00759 // Handle is not within an existing sequence, but is 00760 // within an existing SequenceData... 00761 if( ( *i )->data()->start_handle() <= handle ) 00762 { 00763 // If values_per_entity don't match, can't put new entity 00764 // in existing SequenceData 00765 if( ( *i )->values_per_entity() != values_per_ent ) return MB_ALREADY_ALLOCATED; 00766 00767 data_ptr_out = ( *i )->data(); 00768 if( block_end == handle ) 00769 { 00770 // Prepend to existing sequence 00771 seq_iter_out = i; 00772 block_start = handle; 00773 } 00774 else 00775 { 00776 // Add new sequence to existing SequenceData 00777 seq_iter_out = end(); 00778 if( i == begin() || ( *--i )->data() != data_ptr_out ) 00779 block_start = data_ptr_out->start_handle(); 00780 else 00781 block_start = ( *i )->end_handle() + 1; 00782 } 00783 return MB_SUCCESS; 00784 } 00785 } 00786 00787 if( i != begin() ) 00788 { 00789 --i; 00790 block_start = ( *i )->end_handle() + 1; 00791 00792 // Handle is within previous sequence data... 00793 if( ( *i )->data()->end_handle() >= handle ) 00794 { 00795 // If values_per_entity don't match, can't put new entity 00796 // in existing SequenceData 00797 if( ( *i )->values_per_entity() != values_per_ent ) return MB_ALREADY_ALLOCATED; 00798 00799 data_ptr_out = ( *i )->data(); 00800 if( block_start == handle ) 00801 { 00802 // Append to existing sequence 00803 seq_iter_out = i; 00804 block_end = handle; 00805 } 00806 else 00807 { 00808 // Add new sequence to existing SequenceData 00809 seq_iter_out = end(); 00810 if( ++i == end() || ( *i )->data() != data_ptr_out ) 00811 block_end = data_ptr_out->end_handle(); 00812 else 00813 block_end = ( *i )->start_handle() - 1; 00814 } 00815 return MB_SUCCESS; 00816 } 00817 } 00818 00819 seq_iter_out = end(); 00820 data_ptr_out = 0; 00821 00822 return MB_SUCCESS; 00823 } 00824 00825 ErrorCode TypeSequenceManager::notify_appended( iterator seq ) 00826 { 00827 ErrorCode rval = check_merge_next( seq ); 00828 if( ( *seq )->using_entire_data() ) availableList.erase( ( *seq )->data() ); 00829 00830 return rval; 00831 } 00832 00833 ErrorCode TypeSequenceManager::notify_prepended( iterator seq ) 00834 { 00835 ErrorCode rval = check_merge_prev( seq ); 00836 if( ( *seq )->using_entire_data() ) availableList.erase( ( *seq )->data() ); 00837 00838 return rval; 00839 } 00840 00841 void TypeSequenceManager::get_memory_use( unsigned long long& entity_storage, unsigned long long& total_storage ) const 00842 { 00843 entity_storage = total_storage = 0; 00844 if( empty() ) return; 00845 00846 EntityType mytype = TYPE_FROM_HANDLE( lastReferenced->start_handle() ); 00847 int junk; 00848 get_memory_use( CREATE_HANDLE( mytype, MB_START_ID, junk ), CREATE_HANDLE( mytype, MB_END_ID, junk ), 00849 entity_storage, total_storage ); 00850 } 00851 00852 void TypeSequenceManager::append_memory_use( EntityHandle first, 00853 EntityHandle last, 00854 const SequenceData* data, 00855 unsigned long long& entity_storage, 00856 unsigned long long& total_storage ) const 00857 { 00858 const unsigned long allocated_count = data->size(); 00859 00860 unsigned long bytes_per_ent, seq_size; 00861 const_iterator i = data->seqManData.firstSequence; 00862 ( *i )->get_const_memory_use( bytes_per_ent, seq_size ); 00863 00864 unsigned long other_ent_mem = 0; 00865 unsigned long occupied_count = 0, entity_count = 0, sequence_count = 0; 00866 for( ; i != end() && ( *i )->data() == data; ++i ) 00867 { 00868 occupied_count += ( *i )->size(); 00869 ++sequence_count; 00870 00871 EntityHandle start = std::max( first, ( *i )->start_handle() ); 00872 EntityHandle stop = std::min( last, ( *i )->end_handle() ); 00873 if( stop < start ) continue; 00874 00875 entity_count += stop - start + 1; 00876 other_ent_mem += ( *i )->get_per_entity_memory_use( start, stop ); 00877 } 00878 00879 unsigned long sum = sequence_count * seq_size + allocated_count * bytes_per_ent; 00880 00881 // Watch for overflow 00882 assert( entity_count > 0 && occupied_count > 0 && allocated_count > 0 ); 00883 if( std::numeric_limits< unsigned long >::max() / entity_count <= sum ) 00884 { 00885 total_storage += sum * ( entity_count / occupied_count ) + other_ent_mem; 00886 entity_storage += sum * ( entity_count / allocated_count ) + other_ent_mem; 00887 } 00888 else 00889 { 00890 total_storage += sum * entity_count / occupied_count + other_ent_mem; 00891 entity_storage += sum * entity_count / allocated_count + other_ent_mem; 00892 } 00893 } 00894 00895 void TypeSequenceManager::get_memory_use( EntityHandle first, 00896 EntityHandle last, 00897 unsigned long long& entity_storage, 00898 unsigned long long& total_storage ) const 00899 { 00900 entity_storage = total_storage = 0; 00901 00902 while( first <= last ) 00903 { 00904 const_iterator i = lower_bound( first ); 00905 if( i == end() ) return; 00906 00907 SequenceData* data = ( *i )->data(); 00908 if( first < data->end_handle() ) 00909 { 00910 append_memory_use( first, last, data, entity_storage, total_storage ); 00911 } 00912 first = data->end_handle() + 1; 00913 } 00914 } 00915 00916 EntityID TypeSequenceManager::get_occupied_size( const SequenceData* data ) const 00917 { 00918 EntityID result = 0; 00919 for( const_iterator i = data->seqManData.firstSequence; i != end() && ( *i )->data() == data; ++i ) 00920 result += ( *i )->size(); 00921 00922 return result; 00923 } 00924 00925 #ifndef NDEBUG 00926 bool TypeSequenceManager::check_valid_data( const EntitySequence* seq ) const 00927 { 00928 // Caller passed a sequence that should be contained, so cannot be empty 00929 if( empty() ) return false; 00930 00931 // Make sure lastReferenced points to something 00932 if( !lastReferenced ) return false; 00933 00934 const_iterator seqi = sequenceSet.lower_bound( lastReferenced ); 00935 if( seqi == sequenceSet.end() || *seqi != lastReferenced ) return false; 00936 00937 // Make sure passed sequence is in list 00938 const EntitySequence* seq2 = find( seq->start_handle() ); 00939 if( seq2 != seq ) return false; 00940 00941 // Check all sequences referencing the same SequenceData 00942 const SequenceData* data = seq->data(); 00943 const_iterator i = lower_bound( data->start_handle() ); 00944 if( i != data->seqManData.firstSequence ) return false; 00945 00946 if( i != begin() ) 00947 { 00948 const_iterator j = i; 00949 --j; 00950 if( ( *j )->end_handle() >= data->start_handle() ) return false; 00951 if( ( *j )->data()->end_handle() >= data->start_handle() ) return false; 00952 } 00953 00954 for( ;; ) 00955 { 00956 seq2 = *i; 00957 ++i; 00958 if( i == end() ) return true; 00959 if( ( *i )->data() != data ) break; 00960 00961 if( seq2->end_handle() >= ( *i )->start_handle() ) return false; 00962 } 00963 00964 if( ( *i )->start_handle() <= data->end_handle() ) return false; 00965 if( ( *i )->data()->start_handle() <= data->end_handle() ) return false; 00966 00967 return true; 00968 } 00969 00970 #endif 00971 00972 } // namespace moab