00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "BaBar/BaBar.hh"
00010
00011 #if !defined(OO_DDL_TRANSLATION)
00012 #include "CdbBdbShared/CdbBdbSTimeLineP.hh"
00013 #endif // OO_DDL_TRANSLATION
00014
00015 #include "CdbBdbShared/CdbBdbSTimeLineNodeItr.hh"
00016 using std::cout;
00017 using std::endl;
00018 using std::ostream;
00019
00020 template< class V >
00021 CdbBdbSTimeLineP<V>::CdbBdbSTimeLineP( )
00022 {
00023
00024
00025
00026 initialize( V( ));
00027 }
00028
00029 template< class V >
00030 CdbBdbSTimeLineP<V>::CdbBdbSTimeLineP( const V& theInitialValue )
00031 {
00032
00033
00034 initialize( theInitialValue );
00035 }
00036
00037 template< class V >
00038 CdbBdbSTimeLineP<V>::~CdbBdbSTimeLineP( )
00039 {
00040 BdbDelete( _indexRef );
00041 BdbDelete( _bufRef );
00042 }
00043
00044 template< class V >
00045 CdbStatus
00046 CdbBdbSTimeLineP<V>::insert( const BdbTime& theBeginTime,
00047 const BdbTime& theEndTime,
00048 const V& theValue )
00049 {
00050 const char* errorMsg = "CdbBdbSTimeLineP<V>::insert() -- ERROR";
00051
00052 ooUpdate( );
00053
00054 CdbStatus result = CdbStatus::Error;
00055 do {
00056
00057
00058
00059 if( theBeginTime >= theEndTime ) {
00060 cout << errorMsg << endl << " Illegal interval passed to the procedure." << endl;
00061 break;
00062 }
00063
00064
00065
00066
00067
00068
00069 d_ULong begin = 0;
00070 {
00071 BTreeEntry e;
00072 if( _indexRef->fuzzySearch( BTreeEntry( theBeginTime ), e )) begin = e.value;
00073 }
00074 d_ULong end = 0;
00075 {
00076 BTreeEntry e;
00077 if( _indexRef->fuzzySearch( BTreeEntry( theEndTime ), e )) end = e.value;
00078 if( 0 == end ) end = _last;
00079 }
00080 if(( 0 == begin ) || ( 0 == end )) {
00081 cout << errorMsg << endl << " Failed to find existing interval in the B-tree index." << endl;
00082 break;
00083 }
00084
00085
00086
00087
00088
00089
00090 if( begin == end ) {
00091
00092 insertAndRemoveOne( begin,
00093 theBeginTime,
00094 theEndTime,
00095 theValue );
00096 } else {
00097
00098 insertAndRemoveMany( begin,
00099 end,
00100 theBeginTime,
00101 theEndTime,
00102 theValue );
00103 }
00104
00105
00106
00107 result = CdbStatus::Success;
00108
00109 } while( false );
00110
00111 return result;
00112 }
00113
00114 template< class V >
00115 CdbStatus
00116 CdbBdbSTimeLineP<V>::insert( const CdbBdbSTimeLineInterval< V >& theInterval )
00117 {
00118 return insert( theInterval.begin,
00119 theInterval.end,
00120 theInterval.value );
00121 }
00122
00123 template< class V >
00124 bool
00125 CdbBdbSTimeLineP<V>::findAtBegin( CdbBdbSTimeLineInterval< V >& theInterval,
00126 const BdbTime& theTime ) const
00127 {
00128 BTreeEntry e;
00129
00130 if( _indexRef->search( BTreeEntry( theTime ), e )) {
00131 theInterval = (_bufRef->elementAt( e.value )).interval( );
00132 return true;
00133 }
00134 return false;
00135 }
00136
00137 template< class V >
00138 bool
00139 CdbBdbSTimeLineP<V>::find( CdbBdbSTimeLineInterval< V >& theInterval,
00140 const BdbTime& theTime ) const
00141 {
00142 BTreeEntry e;
00143
00144 if( _indexRef->fuzzySearch( BTreeEntry( theTime ), e )) {
00145 theInterval = (_bufRef->elementAt( e.value )).interval( );
00146 return true;
00147 }
00148 return false;
00149 }
00150
00151 template< class V >
00152 CdbStatus
00153 CdbBdbSTimeLineP<V>::first( CdbBdbSTimeLineInterval< V >& theInterval ) const
00154 {
00155 theInterval = (_bufRef->elementAt( _first )).interval( );
00156 return CdbStatus::Success;
00157 }
00158
00159 template< class V >
00160 CdbStatus
00161 CdbBdbSTimeLineP<V>::last( CdbBdbSTimeLineInterval< V >& theInterval ) const
00162 {
00163 theInterval = (_bufRef->elementAt( _last )).interval( );
00164 return CdbStatus::Success;
00165 }
00166
00167 template< class V >
00168 typename CdbBdbSTimeLineP<V>::IteratorOfIntervals
00169 CdbBdbSTimeLineP<V>::iterator( const BdbTime& theBeginTime ) const
00170 {
00171
00172
00173 d_ULong firstIndex = _first;
00174 if( theBeginTime > BdbTime::minusInfinity ) {
00175
00176
00177
00178
00179 firstIndex = 0;
00180 if( theBeginTime < BdbTime::plusInfinity ) {
00181
00182 BTreeEntry e;
00183 if( _indexRef->fuzzySearch( BTreeEntry( theBeginTime ), e )) {
00184 firstIndex = e.value;
00185 }
00186 }
00187 }
00188
00189
00190
00191
00192 return IteratorOfIntervals( new CdbBdbSTimeLineNodeItr<V>( _bufRef, firstIndex ));
00193 }
00194
00195 template< class V >
00196 void
00197 CdbBdbSTimeLineP<V>::dump( ostream& o,
00198 const BdbTime& theBeginTime,
00199 const BdbTime& theEndTime )
00200 {
00201 const char* errorMsg = "CdbBdbSTimeLineP<V>::dump() -- ERROR";
00202
00203 do {
00204
00205
00206
00207 if( theBeginTime >= theEndTime ) {
00208 cout << errorMsg << endl << " Illegal interval passed to the procedure." << endl;
00209 break;
00210 }
00211
00212
00213
00214
00215
00216
00217 d_ULong begin = 0;
00218 {
00219 BTreeEntry e;
00220 if( _indexRef->fuzzySearch( BTreeEntry( theBeginTime ), e )) begin = e.value;
00221 }
00222 d_ULong end = 0;
00223 {
00224 BTreeEntry e;
00225 if( _indexRef->fuzzySearch( BTreeEntry( theEndTime ), e )) end = e.value;
00226 if( 0 == end ) end = _last;
00227 }
00228 if(( 0 == begin ) || ( 0 == end )) {
00229 cout << errorMsg << endl << " Failed to find an interval in the B-tree index." << endl;
00230 break;
00231 }
00232
00233
00234
00235 d_ULong next = begin;
00236 do {
00237
00238 Node n = _bufRef->elementAt( next );
00239
00240 o << next << " : [ " << n.begin.getGmtSec( ) << "." << n.begin.getGmtNsec( ) << " , "
00241 << n.end.getGmtSec( ) << "." << n.end.getGmtNsec( ) << " ) "
00242 << n.prev << "< >" << n.next << " : " << n.value << endl;
00243
00244 if( next == end ) break;
00245 else next = n.next;
00246
00247 } while( 0 != next );
00248
00249 } while( false );
00250 }
00251
00252 template< class V >
00253 CdbStatus
00254 CdbBdbSTimeLineP<V>::clone( BdbRef(CdbBdbSTimeLineP<V>)& theRef,
00255 const BdbRefAny& theHint ) const
00256 {
00257 const char* errorMsg = "CdbBdbSTimeLineP<V>::clone() -- ERROR";
00258
00259
00260
00261 BdbRefAny hint = theHint;
00262 if( BdbIsNull(hint)) hint = ooThis( );
00263
00264
00265
00266 theRef = new( hint ) CdbBdbSTimeLineP<V>( );
00267
00268
00269
00270
00271 d_ULong next = _first;
00272 do {
00273 Node n = _bufRef->elementAt( next );
00274
00275 CdbStatus status = theRef->insert( n.begin,
00276 n.end,
00277 n.value );
00278 if( CdbStatus::Success != status ) {
00279 cout << errorMsg << endl
00280 << " Failed to insert new interval: " << n.interval( ) << endl
00281 << " from input object into the output one." << endl;
00282 return status;
00283 }
00284 next = n.next;
00285
00286 } while( 0 != next );
00287
00288 return CdbStatus::Success;
00289 }
00290
00291 template< class V >
00292 void
00293 CdbBdbSTimeLineP<V>::initialize( const V& theInitialValue )
00294 {
00295
00296
00297 _bufRef = new( ooThis( )) CdbBdbSPagedVarrayP< Node >( 1 );
00298 _indexRef = new( ooThis( )) CdbBdbSBtreeP< BTreeEntry, BTreeEntryFCP >( );
00299
00300
00301
00302
00303 _free = 0;
00304
00305
00306
00307
00308 _first = allocate( );
00309 {
00310 BdbTime beginTime = BdbTime::minusInfinity;
00311 BdbTime endTime = BdbTime::plusInfinity;
00312
00313 _bufRef->setElementAt( _first, Node( theInitialValue, beginTime, endTime ));
00314 _indexRef->insert( BTreeEntry( beginTime, endTime, _first ));
00315 }
00316 _last = _first;
00317 }
00318
00319 template< class V >
00320 void
00321 CdbBdbSTimeLineP<V>::insertAndRemoveOne( d_ULong begin,
00322 const BdbTime& beginTime,
00323 const BdbTime& endTime,
00324 const V& value )
00325 {
00326
00327
00328
00329
00330
00331
00332
00333 Node beginN = _bufRef->elementAt( begin );
00334
00335 if(( beginTime == beginN.begin ) && ( endTime == beginN.end )) {
00336
00337
00338
00339 beginN.value = value;
00340 _bufRef->setElementAt( begin, beginN );
00341
00342 } else {
00343
00344
00345
00346
00347
00348
00349
00350 _indexRef->remove( BTreeEntry( beginN.begin ));
00351 release( begin );
00352
00353 if( beginTime == beginN.begin ) {
00354
00355
00356
00357 d_ULong first = allocate( );
00358 d_ULong second = allocate( );
00359
00360 Node firstN( value,
00361 beginTime,
00362 endTime,
00363 beginN.prev,
00364 second );
00365 _bufRef->setElementAt( first, firstN );
00366
00367 Node secondN( beginN.value,
00368 endTime,
00369 beginN.end,
00370 first,
00371 beginN.next );
00372 _bufRef->setElementAt( second, secondN );
00373
00374
00375
00376 if( 0 == firstN.prev ) {
00377 _first = first;
00378 } else {
00379 Node prevN = _bufRef->elementAt( firstN.prev );
00380 { prevN.next = first; }
00381 _bufRef->setElementAt( firstN.prev, prevN );
00382 }
00383 if( 0 == secondN.next ) {
00384 _last = second;
00385 } else {
00386 Node nextN = _bufRef->elementAt( secondN.next );
00387 { nextN.prev = second; }
00388 _bufRef->setElementAt( secondN.next, nextN );
00389 }
00390
00391
00392
00393 _indexRef->insert( BTreeEntry( firstN.begin,
00394 firstN.end,
00395 first ));
00396 _indexRef->insert( BTreeEntry( secondN.begin,
00397 secondN.end,
00398 second ));
00399
00400 } else if( endTime == beginN.end ) {
00401
00402
00403
00404 d_ULong first = allocate( );
00405 d_ULong second = allocate( );
00406
00407 Node firstN( beginN.value,
00408 beginN.begin,
00409 beginTime,
00410 beginN.prev,
00411 second );
00412 _bufRef->setElementAt( first, firstN );
00413
00414 Node secondN( value,
00415 beginTime,
00416 endTime,
00417 first,
00418 beginN.next );
00419 _bufRef->setElementAt( second, secondN );
00420
00421
00422
00423 if( 0 == firstN.prev ) {
00424 _first = first;
00425 } else {
00426 Node prevN = _bufRef->elementAt( firstN.prev );
00427 { prevN.next = first; }
00428 _bufRef->setElementAt( firstN.prev, prevN );
00429 }
00430 if( 0 == secondN.next ) {
00431 _last = second;
00432 } else {
00433 Node nextN = _bufRef->elementAt( secondN.next );
00434 { nextN.prev = second; }
00435 _bufRef->setElementAt( secondN.next, nextN );
00436 }
00437
00438
00439
00440 _indexRef->insert( BTreeEntry( firstN.begin,
00441 firstN.end,
00442 first ));
00443 _indexRef->insert( BTreeEntry( secondN.begin,
00444 secondN.end,
00445 second ));
00446 } else {
00447
00448
00449
00450 d_ULong first = allocate( );
00451 d_ULong second = allocate( );
00452 d_ULong third = allocate( );
00453
00454 Node firstN( beginN.value,
00455 beginN.begin,
00456 beginTime,
00457 beginN.prev,
00458 second );
00459 _bufRef->setElementAt( first, firstN );
00460
00461 Node secondN( value,
00462 beginTime,
00463 endTime,
00464 first,
00465 third );
00466 _bufRef->setElementAt( second, secondN );
00467
00468 Node thirdN( beginN.value,
00469 endTime,
00470 beginN.end,
00471 second,
00472 beginN.next );
00473 _bufRef->setElementAt( third, thirdN );
00474
00475
00476
00477 if( 0 == firstN.prev ) {
00478 _first = first;
00479 } else {
00480 Node prevN = _bufRef->elementAt( firstN.prev );
00481 { prevN.next = first; }
00482 _bufRef->setElementAt( firstN.prev, prevN );
00483 }
00484 if( 0 == thirdN.next ) {
00485 _last = third;
00486 } else {
00487 Node nextN = _bufRef->elementAt( thirdN.next );
00488 { nextN.prev = third; }
00489 _bufRef->setElementAt( thirdN.next, nextN );
00490 }
00491
00492
00493
00494 _indexRef->insert( BTreeEntry( firstN.begin,
00495 firstN.end,
00496 first ));
00497 _indexRef->insert( BTreeEntry( secondN.begin,
00498 secondN.end,
00499 second ));
00500 _indexRef->insert( BTreeEntry( thirdN.begin,
00501 thirdN.end,
00502 third ));
00503 }
00504 }
00505 }
00506
00507 template< class V >
00508 void
00509 CdbBdbSTimeLineP<V>::insertAndRemoveMany( d_ULong begin,
00510 d_ULong end,
00511 const BdbTime& beginTime,
00512 const BdbTime& endTime,
00513 const V& value )
00514 {
00515
00516
00517
00518
00519
00520
00521
00522 Node beginN = _bufRef->elementAt( begin );
00523 Node endN = _bufRef->elementAt( end );
00524
00525
00526
00527 if( beginN.next != end ) {
00528
00529 d_ULong next = beginN.next;
00530 while(( 0 != next ) && ( next != end )) {
00531 Node nextN = _bufRef->elementAt( next );
00532 _indexRef->remove( BTreeEntry( nextN.begin ));
00533 release( next );
00534 next = nextN.next;
00535 }
00536 }
00537
00538
00539
00540 _indexRef->remove( BTreeEntry( beginN.begin ));
00541 release( begin );
00542
00543 _indexRef->remove( BTreeEntry( endN.begin ));
00544 release( end );
00545
00546 if(( beginTime == beginN.begin ) && ( endTime == endN.end )) {
00547
00548
00549
00550 d_ULong first = allocate( );
00551
00552 Node firstN( value,
00553 beginTime,
00554 endTime,
00555 beginN.prev,
00556 endN.next );
00557 _bufRef->setElementAt( first, firstN );
00558
00559
00560
00561 if( 0 == firstN.prev ) {
00562 _first = first;
00563 } else {
00564 Node prevN = _bufRef->elementAt( firstN.prev );
00565 { prevN.next = first; }
00566 _bufRef->setElementAt( firstN.prev, prevN );
00567 }
00568 if( 0 == firstN.next ) {
00569 _last = first;
00570 } else {
00571 Node nextN = _bufRef->elementAt( firstN.next );
00572 { nextN.prev = first; }
00573 _bufRef->setElementAt( firstN.next, nextN );
00574 }
00575
00576
00577
00578 _indexRef->insert( BTreeEntry( firstN.begin,
00579 firstN.end,
00580 first ));
00581 } else if( beginTime == beginN.begin ) {
00582
00583
00584
00585
00586 d_ULong first = allocate( );
00587 d_ULong second = allocate( );
00588
00589 Node firstN( value,
00590 beginTime,
00591 endTime,
00592 beginN.prev,
00593 second );
00594 _bufRef->setElementAt( first, firstN );
00595
00596 Node secondN( endN.value,
00597 endTime,
00598 endN.end,
00599 first,
00600 endN.next );
00601 _bufRef->setElementAt( second, secondN );
00602
00603
00604
00605 if( 0 == firstN.prev ) {
00606 _first = first;
00607 } else {
00608 Node prevN = _bufRef->elementAt( firstN.prev );
00609 { prevN.next = first; }
00610 _bufRef->setElementAt( firstN.prev, prevN );
00611 }
00612 if( 0 == secondN.next ) {
00613 _last = second;
00614 } else {
00615 Node nextN = _bufRef->elementAt( secondN.next );
00616 { nextN.prev = second; }
00617 _bufRef->setElementAt( secondN.next, nextN );
00618 }
00619
00620
00621
00622 _indexRef->insert( BTreeEntry( firstN.begin,
00623 firstN.end,
00624 first ));
00625 _indexRef->insert( BTreeEntry( secondN.begin,
00626 secondN.end,
00627 second ));
00628
00629 } else if( endTime == endN.end ) {
00630
00631
00632
00633
00634 d_ULong first = allocate( );
00635 d_ULong second = allocate( );
00636
00637 Node firstN( beginN.value,
00638 beginN.begin,
00639 beginTime,
00640 beginN.prev,
00641 second );
00642 _bufRef->setElementAt( first, firstN );
00643
00644 Node secondN( value,
00645 beginTime,
00646 endTime,
00647 first,
00648 endN.next );
00649 _bufRef->setElementAt( second, secondN );
00650
00651
00652
00653 if( 0 == firstN.prev ) {
00654 _first = first;
00655 } else {
00656 Node prevN = _bufRef->elementAt( firstN.prev );
00657 { prevN.next = first; }
00658 _bufRef->setElementAt( firstN.prev, prevN );
00659 }
00660 if( 0 == secondN.next ) {
00661 _last = second;
00662 } else {
00663 Node nextN = _bufRef->elementAt( secondN.next );
00664 { nextN.prev = second; }
00665 _bufRef->setElementAt( secondN.next, nextN );
00666 }
00667
00668
00669
00670 _indexRef->insert( BTreeEntry( firstN.begin,
00671 firstN.end,
00672 first ));
00673 _indexRef->insert( BTreeEntry( secondN.begin,
00674 secondN.end,
00675 second ));
00676
00677 } else {
00678
00679
00680
00681
00682 d_ULong first = allocate( );
00683 d_ULong second = allocate( );
00684 d_ULong third = allocate( );
00685
00686 Node firstN( beginN.value,
00687 beginN.begin,
00688 beginTime,
00689 beginN.prev,
00690 second );
00691 _bufRef->setElementAt( first, firstN );
00692
00693 Node secondN( value,
00694 beginTime,
00695 endTime,
00696 first,
00697 third );
00698 _bufRef->setElementAt( second, secondN );
00699
00700 Node thirdN( endN.value,
00701 endTime,
00702 endN.end,
00703 second,
00704 endN.next );
00705 _bufRef->setElementAt( third, thirdN );
00706
00707
00708
00709 if( 0 == firstN.prev ) {
00710 _first = first;
00711 } else {
00712 Node prevN = _bufRef->elementAt( firstN.prev );
00713 { prevN.next = first; }
00714 _bufRef->setElementAt( firstN.prev, prevN );
00715 }
00716 if( 0 == thirdN.next ) {
00717 _last = third;
00718 } else {
00719 Node nextN = _bufRef->elementAt( thirdN.next );
00720 { nextN.prev = third; }
00721 _bufRef->setElementAt( thirdN.next, nextN );
00722 }
00723
00724
00725
00726 _indexRef->insert( BTreeEntry( firstN.begin,
00727 firstN.end,
00728 first ));
00729 _indexRef->insert( BTreeEntry( secondN.begin,
00730 secondN.end,
00731 second ));
00732 _indexRef->insert( BTreeEntry( thirdN.begin,
00733 thirdN.end,
00734 third ));
00735 }
00736 }
00737
00738 template< class V >
00739 d_ULong
00740 CdbBdbSTimeLineP<V>::allocate( d_ULong next )
00741 {
00742 if( _free == 0 ) extend_free_list( );
00743
00744 d_ULong result = _free;
00745 {
00746 _free = _bufRef->elementAt( result ).next;
00747 }
00748 return result;
00749 }
00750
00751 template< class V >
00752 void
00753 CdbBdbSTimeLineP<V>::release( d_ULong element )
00754 {
00755 if( element ) {
00756
00757 Node n = _bufRef->elementAt( element );
00758 { n.next = _free; }
00759 _bufRef->setElementAt( element, n );
00760
00761 _free = element;
00762 }
00763 }
00764
00765 template< class V >
00766 void
00767 CdbBdbSTimeLineP<V>::extend_free_list( )
00768 {
00769 if( _free == 0 ) {
00770
00771 const d_ULong sizeIncrement = 1000;
00772
00773 _free = _bufRef->size( );
00774 _bufRef->resize( _free + sizeIncrement );
00775
00776 for( d_ULong element = _free + 1; element < _free + sizeIncrement; ++element ) {
00777
00778
00779
00780 Node endN = _bufRef->elementAt( element );
00781 { endN.next = 0; }
00782 _bufRef->setElementAt( element, endN );
00783
00784
00785
00786 Node previousN = _bufRef->elementAt( element - 1 );
00787 { previousN.next = element; }
00788 _bufRef->setElementAt( element - 1, previousN );
00789 }
00790 }
00791 }
00792
00793
00794
00795