Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

CdbRooRoRevCollectionR.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbRooRoRevCollectionR.cc,v 1.7 2005/11/11 01:41:28 gapon Exp $
00003 
00004 /// Implementation file for the CdbRooRoRevCollectionR class
00005 /**
00006   * @see CdbRooRoRevCollectionR
00007   */
00008 
00009 #include "BaBar/BaBar.hh"
00010 
00011 #include "CdbRooReadonly/CdbRooRoRevCollectionR.hh"
00012 #include "CdbRooReadonly/CdbRooRoCollectionAddressR.hh"
00013 
00014 #include "CdbBase/CdbVectorAdapterItr.hh"
00015 #include "CdbBase/CdbSimpleVectorAdapterItr.hh"
00016 #include "CdbBase/CdbTimeUtils.hh"
00017 
00018 #include "ErrLogger/ErrLog.hh"
00019 
00020 #include <assert.h>
00021 
00022 #include <iostream>
00023 using std::cout;
00024 using std::endl;
00025 
00026 namespace {
00027 
00028   /////////////////////////////////
00029   // Class: RevisionNameIterator //
00030   /////////////////////////////////
00031 
00032     class RevisionNameIterator : public CdbVectorAdapterItr< const char*, std::string > {
00033 
00034     private:
00035 
00036       /// Default constructor (IS NOT IMPLEMENTED)
00037 
00038         RevisionNameIterator( );
00039 
00040     protected:
00041 
00042       /// Copy constructor
00043 
00044         RevisionNameIterator( const RevisionNameIterator& theOther ) :
00045             CdbVectorAdapterItr< const char*, std::string >( theOther )
00046         { }
00047 
00048     public:
00049 
00050       /// The normal constructor
00051       /**
00052         * @see CdbVectorAdapterItr::CdbVectorAdapterItr()
00053         */
00054         RevisionNameIterator( const std::vector< std::string >& theList ) :
00055             CdbVectorAdapterItr< const char*, std::string >( theList )
00056         { }
00057 
00058        /// Make a clone of itself
00059       /**
00060         * @see CdbIItr::clone()
00061         */
00062         virtual CdbVectorAdapterItr< const char*, std::string >::InterfaceType* clone( ) const
00063         {
00064             return new RevisionNameIterator( *this );
00065         }
00066 
00067     protected:
00068 
00069       /// User defined translation for the currently refered value
00070       /**
00071         * @see CdbVectorAdapterItr::CdbVectorAdapterItr()
00072         */
00073         virtual const char* toValue( const std::string& theValue ) const
00074         {
00075             return theValue.c_str( );
00076         }
00077     };
00078 }
00079 
00080 //////////////////////////////////
00081 // Class: CdbRooRoRevCollectionR //
00082 //////////////////////////////////
00083 
00084 CdbRooRoRevCollectionR::CdbRooRoRevCollectionR( ) :
00085     CdbRooRoPersistentCollectionR( ),
00086     _revisions         (1),
00087     _useTopmostRevision(false)
00088 { }
00089 
00090 UInt_t
00091 CdbRooRoRevCollectionR::size( ) const
00092 {
00093   // IMPLEMENTATION NOTE:
00094   //
00095   //   The number returned doesn't include the very first element with the special 0 index.
00096   //   This internal index is internally used for the "no-information" signalling mechanizm.
00097 
00098     return _revisions.size( ) - 1 + ( _useTopmostRevision ? 1 : 0 );
00099 }
00100 
00101 CdbStatus
00102 CdbRooRoRevCollectionR::insert( const CdbRooRoRevisionR& theRevision )
00103 {
00104     const char* errorMsg = "CdbRooRoRevCollectionR::insert() -- ERROR";
00105 
00106     CdbStatus result = CdbStatus::Error;
00107 
00108     if( isStored( )) return CdbStatus::Error;
00109 
00110   // Verify parameters.
00111 
00112     BdbTime     id   = theRevision.id( );
00113     std::string name = theRevision.name( );
00114 
00115     if( BdbTime::minusInfinity == id )  {
00116         cout << errorMsg << endl
00117              << "    Passed persistent revision object has invalid identifier. " << endl;
00118         return CdbStatus::IllegalParameters;
00119     }
00120 
00121   // Check if it's the 'topmost' revision. If so then it has to be handled separatedly
00122   // through dedicated data structures.
00123 
00124     if( BdbTime::plusInfinity == id )  {
00125 
00126         if( _useTopmostRevision ) {
00127             cout << errorMsg << endl
00128                  << "    Sorry, the 'topmost' revision is already stored in the collection. " << endl;
00129             return CdbStatus::Error;
00130         }
00131         _useTopmostRevision = true;
00132         _topmostRevision    = theRevision;
00133 
00134         return CdbStatus::Success;
00135     }
00136 
00137   // Put the revision into the vector of ones. Capture its index in vectore as we're
00138   // going to use it as an internal identifier in indexes.
00139 
00140     UInt_t numBeforeInsert = _revisions.size( );
00141 
00142     if( CdbStatus::Success != _revisions.addElement( theRevision )) {
00143         ErrMsg(error)
00144             << errorMsg << endl
00145             << "    Failed to add a revision into the internal storage."
00146             << endmsg;
00147         return CdbStatus::Error;
00148     }
00149 
00150     UInt_t idx = numBeforeInsert;
00151     assert( 0 != idx );
00152 
00153   // Follow up with revision registration in the map and the TimeLine
00154   //
00155   // NOTE: The registration sequence is only important from the recovery point
00156   //       of view just in case this (recovery) would be required. Removing an element
00157   //       from the map is much easier than from the TimeLine
00158 
00159     if( CdbStatus::Success != ( result = insertIntoMap( theRevision,
00160                                                         idx ))) {
00161 
00162         if( CdbStatus::Success != _revisions.resize( numBeforeInsert )) {
00163             ErrMsg(error)
00164                 << errorMsg << endl
00165                 << "    Failed to resize the internal storage after failing to insert" << endl
00166                 << "    a new revision into the map."
00167                 << endmsg;
00168         }
00169         return result;
00170     }
00171     if( CdbStatus::Success != ( result = insertIntoTimeLine( theRevision,
00172                                                              idx )))  {
00173 
00174       // To maintain consistency of the collection's context.
00175 
00176         removeFromMap( theRevision.name( ));
00177 
00178         if( CdbStatus::Success != _revisions.resize( numBeforeInsert )) {
00179             ErrMsg(error)
00180                 << errorMsg << endl
00181                 << "    Failed to resize the internal storage after failing to insert" << endl
00182                 << "    a new revision into the timeline."
00183                 << endmsg;
00184         }
00185         return result;
00186     }
00187     return CdbStatus::Success;
00188 }
00189 
00190 CdbStatus
00191 CdbRooRoRevCollectionR::find( const BdbTime&     theId,
00192                               CdbRooRoRevisionR& theRevision ) const
00193 {
00194     const char* errorMsg = "CdbRooRoRevCollectionR::find(id) -- ERROR";
00195 
00196   // Verify the parameters
00197 
00198     if( BdbTime::minusInfinity == theId )  {
00199         cout << errorMsg << endl
00200              << "    Passed revision identifier is not valid in this context." << endl
00201              << "        ID: " << CdbTimeUtils::time2string( theId ) << " : " << theId << endl;
00202         return CdbStatus::Error;
00203     }
00204 
00205   // Check if the 'topmost' revision is requested. If so then it has to be handled separatedly
00206   // through dedicated data structures.
00207 
00208     if( BdbTime::plusInfinity == theId )  {
00209 
00210         if( !_useTopmostRevision ) return CdbStatus::NotFound;
00211 
00212         theRevision = _topmostRevision;
00213 
00214         return CdbStatus::Success;
00215     }
00216 
00217   // This method uses "exact match" search in the B-tree to locate specified
00218   // revision object.
00219 
00220     Interval dInterval;
00221     if(( !_indexById.findAtBegin( dInterval, theId )) || ( 0 == dInterval.value( ))) {
00222         return CdbStatus::NotFound;
00223     }
00224     if( CdbStatus::Success != _revisions.elementAt( dInterval.value( ),
00225                                                     theRevision )) {
00226         ErrMsg(error)
00227             << errorMsg << endl
00228             << "    Failed to find a revision in the internal storage."
00229             << endmsg;
00230         return CdbStatus::Error;
00231     }
00232     return CdbStatus::Success;
00233 }
00234 
00235 CdbStatus
00236 CdbRooRoRevCollectionR::find( const char*        theName,
00237                               CdbRooRoRevisionR& theRevision ) const
00238 {
00239     const char* errorMsg = "CdbRooRoRevCollectionR::find(name) -- ERROR";
00240 
00241   // Verify the parameters
00242 
00243     if( 0 == theName )  {
00244         cout << errorMsg << endl
00245              << "    Passed revision name can't be 0 in this context." << endl;
00246         return CdbStatus::Error;
00247     }
00248 
00249   // Check if the 'topmost' revision is requested. If so then it has to be handled separatedly
00250   // through dedicated data structures.
00251 
00252     if( std::string( "<topmost>" ) == theName )  {
00253 
00254         if( !_useTopmostRevision ) return CdbStatus::NotFound;
00255 
00256         theRevision = _topmostRevision;
00257 
00258         return CdbStatus::Success;
00259     }
00260 
00261   // Look up the object in the map.
00262   //
00263   // NOTE: If the object is not found then we let a client to interpret
00264   //       the result of this search.
00265 
00266     std::map< std::string, UInt_t >::const_iterator itr = _indexByName.find( theName );
00267     if( itr == _indexByName.end( )) {
00268         return CdbStatus::NotFound;
00269     }
00270     UInt_t idx = (*itr).second;
00271     assert( 0 != idx );
00272 
00273     if( CdbStatus::Success != _revisions.elementAt( idx,
00274                                                     theRevision )) {
00275         ErrMsg(error)
00276             << errorMsg << endl
00277             << "    Failed to find a revision in the internal storage."
00278             << endmsg;
00279         return CdbStatus::Error;
00280     }
00281     return CdbStatus::Success;
00282 }
00283 
00284 CdbStatus
00285 CdbRooRoRevCollectionR::last( BdbTime& theId ) const
00286 {
00287   // Check if the 'topmost' revision is present.
00288 
00289     if( _useTopmostRevision ) {
00290         theId = BdbTime::plusInfinity;
00291         return CdbStatus::Success;
00292     }
00293 
00294   // If not, then proceed with normal revisions
00295 
00296     Interval dInterval;
00297 
00298     CdbStatus result = _indexById.last( dInterval );
00299     if( CdbStatus::Success == result ) {
00300 
00301         if( 0 != dInterval.value( )) {
00302             theId = dInterval.begin( );
00303         } else {
00304             result = CdbStatus::NotFound;
00305         }
00306     }
00307     return result;
00308 }
00309 
00310 CdbItr<BdbTime>
00311 CdbRooRoRevCollectionR::iterator_identifiers( ) const
00312 {
00313     const char* fatalMsg = "CdbRooRoRevCollectionR::iterator_identifiers() -- FATAL ERROR";
00314 
00315   // Build a vector of identifiers
00316 
00317     std::vector<BdbTime> vectorOfIdentifiers;
00318     {
00319       // Browse the normal revisions first
00320 
00321         CdbRooRoTimeLineR< UInt_t >::IteratorOfIntervals itr = _indexById.iterator( );
00322         while( itr.next( )) {
00323 
00324             UInt_t idx = itr.value( ).value( );
00325 
00326             if( 0 == idx ) continue;    // Skip this index as it's reserved
00327                                         // for special purposes.
00328 
00329             CdbRooRoRevisionR revision;
00330             if( CdbStatus::Success != _revisions.elementAt( idx,
00331                                                             revision )) {
00332                 ErrMsg(fatal)
00333                     << fatalMsg << endl
00334                     << "    Failed to find a revision in the internal storage."
00335                     << endmsg;
00336                 break;
00337             }
00338             vectorOfIdentifiers.push_back( revision.id( ));
00339         }
00340 
00341       // Add the 'topmost' revision if present
00342 
00343         if( _useTopmostRevision ) vectorOfIdentifiers.push_back( BdbTime::plusInfinity );
00344     }
00345 
00346   // Build the resulting iterator
00347 
00348     CdbItr<BdbTime> itr( new CdbSimpleVectorAdapterItr<BdbTime>( vectorOfIdentifiers ));
00349 
00350     return itr;
00351 }
00352 
00353 CdbItr<const char*>
00354 CdbRooRoRevCollectionR::iterator_names( ) const
00355 {
00356     const char* fatalMsg = "CdbRooRoRevCollectionR::iterator_names() -- FATAL ERROR";
00357 
00358   // Build a vector of identifiers
00359 
00360     std::vector<std::string> vectorOfNames;
00361     {
00362       // Browse the normal revisions first
00363 
00364         CdbRooRoTimeLineR< UInt_t >::IteratorOfIntervals itr = _indexById.iterator( );
00365         while( itr.next( )) {
00366 
00367             UInt_t idx = itr.value( ).value( );
00368 
00369             if( 0 == idx ) continue;    // Skip this index as it's reserved
00370                                         // for special purposes.
00371 
00372             CdbRooRoRevisionR revision;
00373             if( CdbStatus::Success != _revisions.elementAt( idx,
00374                                                             revision )) {
00375                 ErrMsg(fatal)
00376                     << fatalMsg << endl
00377                     << "    Failed to find a revision in the internal storage."
00378                     << endmsg;
00379                 break;
00380             }
00381             vectorOfNames.push_back( revision.name( ));
00382         }
00383 
00384       // Add the 'topmost' revision if present
00385 
00386         if( _useTopmostRevision ) vectorOfNames.push_back( std::string( "<topmost>" ));
00387     }
00388 
00389   // Build the resulting iterator
00390 
00391     CdbItr<const char*> itr( new RevisionNameIterator( vectorOfNames ));
00392 
00393     return itr;
00394 }
00395 
00396 void
00397 CdbRooRoRevCollectionR::dump( std::ostream& o ) const
00398 {
00399     const char* fatalMsg = "CdbRooRoRevCollectionR::dump() -- FATAL ERROR";
00400 
00401     do {
00402 
00403       // Do the dump
00404 
00405         o << "** COLLECTION OF REVISIONS **" << endl
00406           << endl;
00407 
00408         CdbRooRoTimeLineR< UInt_t >::IteratorOfIntervals itr = _indexById.iterator( );
00409 
00410         while( itr.next( )) {
00411 
00412             Interval dInterval = itr.value( );
00413             UInt_t   idx       = dInterval.value( );
00414 
00415             if( 0 == idx ) {
00416 
00417                 o << "  <IS EMPTY>" << endl
00418                   << endl;
00419 
00420             } else {
00421 
00422               // NOTE: Keep an eye on the 'tiopmost' revision, which is managed through
00423               //       a separate storage.
00424 
00425                 BdbTime     rId   = BdbTime::plusInfinity;
00426                 std::string rName = "<topmost>";
00427 
00428                 if( !_useTopmostRevision ) {
00429 
00430                     CdbRooRoRevisionR revision;
00431                     if( CdbStatus::Success != _revisions.elementAt( idx,
00432                                                                     revision )) {
00433                         ErrMsg(fatal)
00434                             << fatalMsg << endl
00435                             << "    Failed to find a revision in the internal storage."
00436                             << endmsg;
00437                         break;
00438                     }
00439                     rId   = revision.id( );
00440                     rName = revision.name( );
00441                 }
00442 
00443                 o << "  ID       : "   << CdbTimeUtils::time2string( rId ) << " : " << rId << endl
00444                   << "  NAME     : \"" << rName << "\"" << endl
00445                   << "  DURATION : "   << "[ " << CdbTimeUtils::time2string( dInterval.begin( ), true ) << " , "
00446                   <<                              CdbTimeUtils::time2string( dInterval.end( ),   true ) << " )" << endl
00447                   << endl;
00448             }
00449         }
00450 
00451         o << "** END OF THE COLLECTION **" << endl;
00452 
00453     } while( false );
00454 }
00455 
00456 CdbStatus
00457 CdbRooRoRevCollectionR::storeSubCollectionsAt( const CdbRooRoCollectionAddressR& theCollectionAddress,
00458                                                const CdbCPtr<TFile>&             theFilePtr,
00459                                                Int_t&                            theNumBytesStored )
00460 {
00461     const char* errorStr = "CdbRooRoRevCollectionR::storeSubCollectionsAt() -- ERROR";
00462 
00463     Int_t numBytesStored = 0;
00464 
00465   // Store the embedded colletions.
00466 
00467     Int_t numBytes = 0;
00468 
00469     const CdbRooRoCollectionAddressR subCollectionAddress =
00470         CdbRooRoCollectionAddressR::createSubCollection( theCollectionAddress,
00471                                                          ".Revisions" );
00472 
00473     CdbStatus status = _revisions.storeAsEmbeddedAt( subCollectionAddress,
00474                                                      theFilePtr,
00475                                                      numBytes );
00476     if( CdbStatus::Success != status ) {
00477 
00478         ErrMsg(error) << errorStr << endl
00479                       << "   Failed to store an embedded sub-collection of revisions." << endl
00480                       << "       File Name              : " << theFilePtr->GetName( )  << endl
00481                       << "       Sub.Collection Address : " << subCollectionAddress    << endl
00482                       << "       Error Status           : " << status
00483                       << endmsg;
00484         return status;
00485     }
00486     numBytesStored += numBytes;
00487 
00488   // Done
00489 
00490     theNumBytesStored = numBytesStored;
00491 
00492     return CdbStatus::Success;
00493 }
00494 
00495 CdbStatus
00496 CdbRooRoRevCollectionR::insertIntoMap( const CdbRooRoRevisionR& theRevision,
00497                                        UInt_t                   theIdx )
00498 {
00499     const char* errorMsg = "CdbRooRoRevCollectionR::insertIntoMap() -- ERROR";
00500 
00501     assert( 0 != theIdx );
00502 
00503     CdbStatus result = CdbStatus::Error;
00504     do {
00505 
00506       // Verify if the map does not contain any revision with such name.
00507 
00508         std::string name = theRevision.name( );
00509 
00510         std::map< std::string, UInt_t >::const_iterator itr = _indexByName.find( name );
00511         if( itr != _indexByName.end( )) {
00512             cout << errorMsg << endl
00513                  << "    There is already a revision with such name." << endl
00514                  << "        Passed revision name: \"" << name << "\"" << endl;
00515             break;
00516         }
00517 
00518       // Now just add the revision.
00519 
00520         _indexByName[name] = theIdx;
00521 
00522       // Done.
00523 
00524         result = CdbStatus::Success;
00525 
00526     } while( false );
00527 
00528     return result;
00529 }
00530 
00531 void
00532 CdbRooRoRevCollectionR::removeFromMap( const std::string& theName )
00533 {
00534     std::map< std::string, UInt_t >::iterator itr = _indexByName.find( theName );
00535     if( itr != _indexByName.end( )) _indexByName.erase( itr );
00536 }
00537 
00538 CdbStatus
00539 CdbRooRoRevCollectionR::insertIntoTimeLine( const CdbRooRoRevisionR& theRevision,
00540                                             UInt_t                   theIdx )
00541 {
00542     const char* errorMsg = "CdbRooRoRevCollectionR::insertIntoTimeLine() -- ERROR";
00543 
00544     assert( 0 != theIdx );
00545 
00546     CdbStatus result = CdbStatus::Error;
00547     do {
00548 
00549       // Verify the value of the revisin identifier. It must not be older
00550       // (less or equal) than the most recently known revision.
00551 
00552         BdbTime id = theRevision.id( );
00553 
00554         Interval lastInterval;
00555         if( CdbStatus::Success != _indexById.last( lastInterval )) {
00556             cout << errorMsg << endl
00557                  << "    Failed to obtain the last interval from the TimeLine." << endl;
00558             break;
00559         }
00560         if( id <= lastInterval.begin( )) {
00561             cout << errorMsg << endl
00562                  << "    Passed revision object has incorrect identifier time, which" << endl
00563                  << "    should never be less or equal than the one of the last known revision." << endl
00564                  << "        Passed revision     ID: " << CdbTimeUtils::time2string( id )                   << " : " << id << endl
00565                  << "        Last known revision ID: " << CdbTimeUtils::time2string( lastInterval.begin( )) << " : " << lastInterval.begin( ) << endl;
00566             break;
00567         }
00568 
00569       // Append the "revision duration" interval by the end of the TimeLine.
00570       // This operation will cut existing "last" interval at the specified
00571       // insertion time point.
00572       //
00573       // NOTE: Intervals have the following semantics: [begin,end)
00574 
00575         if( CdbStatus::Success != _indexById.insert( id,
00576                                                      BdbTime::plusInfinity,
00577                                                      theIdx )) {
00578             cout << errorMsg << endl
00579                  << "    Failed to insert new interval into the TimeLine." << endl;
00580             break;
00581         }
00582 
00583       // Done.
00584 
00585         result = CdbStatus::Success;
00586 
00587     } while( false );
00588 
00589     return result;
00590 }
00591 
00592 /////////////////
00593 // End Of File //
00594 /////////////////

Generated on Mon Dec 5 18:22:11 2005 for CDB by doxygen1.3-rc3