Bdb packages | Design docs | Source docs | Guidelines | Recent releases

Search | Site Map .

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

/BdbCondRemote/BdbCondRInfoImpl.cc

Go to the documentation of this file.
00001 //--------------------------------------------------------------------------
00002 // File and Version Information:
00003 //      $Id: BdbCondRInfoImpl.cc,v 1.10 2002/08/07 21:49:14 gapon Exp $
00004 //
00005 // Description:
00006 //      This is the class implementing the corresponding IDL interface.
00007 //
00008 // Environment:
00009 //      Software developed for the BaBar Detector at the SLAC B-Factory.
00010 //
00011 // Author List
00012 //      Igor Gaponenko          Original Author
00013 //
00014 // Copyright Information:
00015 //      Copyright (C) 2000      Lawrence Berkeley Laboratory
00016 //
00017 //------------------------------------------------------------------------
00018 
00019 // -------------------------
00020 // -- This Class's Header --
00021 // -------------------------
00022 
00023 #include "BdbCondRemote/BdbCondRInfoImpl.hh"
00024 #include "BbrStdUtils/Tokenize.hh" 
00025 using namespace babar::String; 
00026 
00027 // -------------------
00028 // -- C/C++ Headers --
00029 // -------------------
00030 
00031 #include <time.h>
00032 
00033 extern "C" {
00034 #include <stdlib.h>
00035 #include <errno.h>
00036 }
00037 
00038 #include "fstream.h"
00039 
00040 // -----------------------
00041 // -- The CORBA headers --
00042 // -----------------------
00043 
00044 #include "tao/corba.h"
00045 
00046 // ---------------------------------
00047 // -- Collaborating Class Headers --
00048 // ---------------------------------
00049 
00050 #include "BdbApplication/BdbDebug.hh"
00051 #include "BdbTime/BdbTime.hh"
00052 #include "BdbCond/BdbConditions.hh"
00053 #include "BdbCond/BdbIntervalItr.hh"
00054 #include "BdbCond/BdbObsoleteDatabase.hh"
00055 #include "BdbCond/BdbCondContainerLink.hh"
00056 #include "BdbCondRemote/BdbCondRInfoCache.hh"
00057 #include "BdbCondRemote/BdbCondRInfoFederation.hh"
00058 #include "BdbCondRemote/BdbCondRInfoSnapshot.hh"
00059 #include "BdbCondRemote/BdbCondRInfoDetector.hh"
00060 #include "BdbCondRemote/BdbCondRInfoOrigin.hh"
00061 #include "BdbCondRemote/BdbCondRInfoContainer.hh"
00062 #include "BdbCondRemote/BdbCondRInfoLoader.hh"
00063 #include "BdbCondRemote/BdbCondRInfoJob.hh"
00064 #include "BdbCondRemote/BdbCondRInfoConversionFactory.hh"
00065 #include "TaoTools/TaoServer.hh"
00066 
00067 #include <rw/tvsrtvec.h>
00068 #include <rw/ctoken.h>
00069 
00070 // --------------------------------------------------------------------------
00071 // -- Local Macros, Typedefs, Structures, Unions, and Forward Declarations --
00072 // --------------------------------------------------------------------------
00073 
00074 static const char  rcsid[] = "$Id: BdbCondRInfoImpl.cc,v 1.10 2002/08/07 21:49:14 gapon Exp $";
00075 
00076 static const char* DEFAULT_SNAPSHOT_NAME = "<LIVE>";
00077 
00078 // ------------------
00079 // -- Constructors --
00080 // ------------------
00081 
00082 BdbCondRInfoImpl::BdbCondRInfoImpl( bool       verbose,
00083                                     ooContext* cxtPtr,
00084                                     bool       bload ) :
00085     POA_BdbCondRemote::Info( ),
00086     _verbose(verbose),
00087     _bload(bload),
00088     _myCxtPtr(cxtPtr),
00089     _isInitialized(false)
00090 {
00091     const char* infoString = "BdbCondRInfoImpl::BdbCondRInfoImpl()";
00092 
00093     if( _verbose )
00094         cout << "[ " << BdbTime( ) << " ] " << infoString << " Start serving federation: " << BdbConditions::instance( )->bootName( ) << endl;
00095 
00096   // This mutex provides the exclusive access to the Objectivity
00097   // context from the transactions.
00098 
00099     pthread_mutex_init( &_myCxtMutex, 0 );
00100 
00101   // Create the cache itself. This thing has to be created first before
00102   // any other activities which are using it.
00103 
00104     _cache = new BdbCondRInfoCache( );
00105 
00106   // Create the persistent data loader to be used for synchronoious loading
00107   // operations directly from the serving method(s).
00108 
00109     _myLoader = new BdbCondRInfoLoader( verbose,
00110                                         _cache,
00111                                         _myCxtPtr,
00112                                         &_myCxtMutex );
00113 
00114   // Create a jobs queue and a pool of loaders to be fed via
00115   // this queue.
00116   //
00117   // NOTE: In the current implementation there is only one loader
00118   //       due to limitations of the single-threaded BDB stuff.
00119 
00120     _myJobsQueue = new BdbCondRQueue<BdbCondRInfoJob>( );
00121 
00122     _myLoadres.push_back( new BdbCondRInfoLoader( verbose,
00123                                                _cache,
00124                                                _myCxtPtr,
00125                                                &_myCxtMutex,
00126                                                _myJobsQueue ));
00127 
00128   // Create the persistent data loader to be used by the "Background Loader" thread
00129   // and then start the thread itself if required.
00130   //
00131   // NOTE: The sequence is very important, because the thread may attempt
00132   //       to use the loader when it is not yet existing.
00133   //
00134   // NOTE: We also construct a loader without passing a jobs queue
00135   //       to its constructor since we are not going to run the loader
00136   //       in a separate thread, but just call directly (and synchroniously) its
00137   //       loading facility.
00138 
00139     if( _bload ) {
00140         _bloadLoader = new BdbCondRInfoLoader( verbose,
00141                                                _cache,
00142                                                _myCxtPtr,
00143                                                &_myCxtMutex );
00144         startBloadThread( );
00145     }
00146 }
00147 
00148 // ----------------
00149 // -- Destructor --
00150 // ----------------
00151 
00152 BdbCondRInfoImpl::~BdbCondRInfoImpl( )
00153 {
00154     const char* infoString = "BdbCondRInfoImpl::~BdbCondRInfoImpl()";
00155 
00156     if( _verbose )
00157         cout << "[ " << BdbTime( ) << " ] " << infoString << " Stop serving federation: " << BdbConditions::instance( )->bootName( ) << endl;
00158 
00159   // Stop the "Background Loader" thread if required and then delete
00160   // its loader.
00161   //
00162   // NOTE: The same reasoning for the sequence of these operations as in case when
00163   //       the loader was being created and the thread was being started.
00164 
00165     if( _bload ) {
00166         stopBloadThread( );
00167         delete _bloadLoader;
00168     }
00169 
00170   // Stop and destroy the loaders. Then delete the jobs queue.
00171   //
00172   // NOTE: The same considerations for the sequence of these operations.
00173   //       The queue should be deleted _after_ the loaders using this queue
00174   //       are destroyed
00175 
00176     int entries = _myLoadres.size( );
00177     for( int i = 0; i < entries; i++ ) {
00178         delete _myLoadres[i];
00179     }
00180     delete _myJobsQueue;
00181 
00182   // Delete the dircet loader.
00183 
00184     delete _myLoader;
00185 
00186   // This is the very last thing we delete.
00187 
00188     delete _cache;
00189 }
00190 
00191 // ----------------
00192 // -- Operations --
00193 // ----------------
00194 
00195 BdbCondRemote::Info::StrSequenceType*
00196 BdbCondRInfoImpl::getFederations( CORBA_Environment& theEnvironment )
00197 {
00198     const char* infoString = "BdbCondRInfoImpl::getFederations()";
00199 
00200     BdbCondRemote::Info::StrSequenceType* result = new BdbCondRemote::Info::StrSequenceType( );
00201 
00202     if( _verbose )
00203         cout << "[ " << BdbTime( ) << " ] " << infoString << endl;
00204 
00205     if( ! initialize( )) return result;
00206 
00207     cacheLockBeginRead( _cache );
00208 
00209     do {
00210 
00211       // Load a list of federations from the cache.
00212 
00213         vector<string> theListOfFederations;
00214         _cache->keys( theListOfFederations );
00215 
00216         int num = theListOfFederations.size( );
00217 
00218         result->length( num );
00219         for( int i = 0; i < num; i++ ) {
00220             (*result)[i] = theListOfFederations[i].c_str();
00221         }
00222 
00223     } while( false );
00224 
00225     cacheLockEndRead( _cache );
00226 
00227     return result;
00228 }
00229 
00230 BdbCondRemote::Info::StrSequenceType*
00231 BdbCondRInfoImpl::getSnapshots( const char*        theFederationName,
00232                                 CORBA_Environment& theEnvironment )
00233 {
00234     const char* infoString  = "BdbCondRInfoImpl::getSnapshots()";
00235     const char* errorString = "BdbCondRInfoImpl::getSnapshots() - ERROR.";
00236 
00237     BdbCondRemote::Info::StrSequenceType* result = new BdbCondRemote::Info::StrSequenceType( );
00238 
00239     if( _verbose )
00240         cout << "[ " << BdbTime( ) << " ] " << infoString << endl
00241              << "    FEDERATION: " << theFederationName << endl;
00242 
00243     if( ! initialize( )) return result;
00244 
00245     cacheLockBeginRead( _cache );
00246 
00247     do {
00248 
00249       // Find the corresponding federation descriptor in the cache.
00250 
00251         BdbCondRInfoFederation* theFederation = _cache->findFederation( theFederationName );
00252         if( 0 == theFederation ) {
00253 
00254             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
00255                  << "    No such federation in the cache." << endl
00256                  << "        FEDERATION: " << theFederationName << endl;
00257             break;
00258         }
00259 
00260       // Load a list of snapshots from the cache.
00261 
00262         vector<string> theListOfSnapshots;
00263         theFederation->keys( theListOfSnapshots );
00264 
00265         int num = theListOfSnapshots.size( );
00266 
00267         result->length( num );
00268         for( int i = 0; i < num; i++ ) {
00269             (*result)[i] = theListOfSnapshots[i].c_str();
00270         }
00271 
00272     } while( false );
00273 
00274     cacheLockEndRead( _cache );
00275 
00276     return result;
00277 }
00278 
00279 BdbCondRemote::Info::StrSequenceType*
00280 BdbCondRInfoImpl::getDetectors( const char*        theFederationName,
00281                                 const char*        theSnapshotName,
00282                                 CORBA_Environment& theEnvironment )
00283 {
00284     const char* infoString  = "BdbCondRInfoImpl::getDetectors()";
00285     const char* errorString = "BdbCondRInfoImpl::getDetectors() - ERROR.";
00286 
00287     BdbCondRemote::Info::StrSequenceType* result = new BdbCondRemote::Info::StrSequenceType( );
00288 
00289     if( _verbose )
00290         cout << "[ " << BdbTime( ) << " ] " << infoString << endl
00291              << "    FEDERATION: " << theFederationName << endl
00292              << "    SNAPSHOT:   " << theSnapshotName << endl;
00293 
00294     if( ! initialize( )) return result;
00295 
00296     cacheLockBeginRead( _cache );
00297 
00298     do {
00299 
00300       // Find the corresponding snapshot descriptor in the cache.
00301 
00302         BdbCondRInfoSnapshot* theSnapshot = _cache->findSnapshot( theFederationName,
00303                                                                   theSnapshotName );
00304         if( 0 == theSnapshot ) {
00305 
00306             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
00307                  << "    No such snapshot in the cache." << endl
00308                  << "        FEDERATION: " << theFederationName << endl
00309                  << "        SNAPSHOT:   " << theSnapshotName << endl;
00310             break;
00311         }
00312 
00313       // Load a list of detectors from the cache.
00314 
00315         vector<string> theListOfDetectors;
00316         theSnapshot->keys( theListOfDetectors );
00317 
00318         int num = theListOfDetectors.size( );
00319 
00320         result->length( num );
00321         for( int i = 0; i < num; i++ ) {
00322             (*result)[i] = theListOfDetectors[i].c_str();
00323         }
00324 
00325     } while( false );
00326 
00327     cacheLockEndRead( _cache );
00328 
00329     return result;
00330 }
00331 
00332 BdbCondRemote::Info::StrSequenceType*
00333 BdbCondRInfoImpl::getOrigins( const char*        theFederationName,
00334                               const char*        theSnapshotName,
00335                               const char*        theDetectorName,
00336                               CORBA_Environment& theEnvironment )
00337 {
00338     const char* infoString  = "BdbCondRInfoImpl::getOrigins()";
00339     const char* errorString = "BdbCondRInfoImpl::getOrigins() - ERROR.";
00340 
00341     BdbCondRemote::Info::StrSequenceType* result = new BdbCondRemote::Info::StrSequenceType( );
00342 
00343     if( _verbose )
00344         cout << "[ " << BdbTime( ) << " ] " << infoString << endl
00345              << "    FEDERATION: " << theFederationName << endl
00346              << "    SNAPSHOT:   " << theSnapshotName << endl
00347              << "    DETECTOR:   " << theDetectorName << endl;
00348 
00349     if( ! initialize( )) return result;
00350 
00351     cacheLockBeginRead( _cache );
00352 
00353     do {
00354 
00355       // Find the corresponding detector descriptor in the cache.
00356 
00357         BdbCondRInfoDetector* theDetector = _cache->findDetector( theFederationName,
00358                                                                   theSnapshotName,
00359                                                                   theDetectorName );
00360         if( 0 == theDetector ) {
00361 
00362             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
00363                  << "    No such detector in the cache." << endl
00364                  << "        FEDERATION: " << theFederationName << endl
00365                  << "        SNAPSHOT:   " << theSnapshotName << endl
00366                  << "        DETECTOR:   " << theDetectorName << endl;
00367             break;
00368         }
00369 
00370       // Load a list of origins from the cache.
00371 
00372         vector<string> theListOfOrigins;
00373         theDetector->keys( theListOfOrigins );
00374 
00375         int num = theListOfOrigins.size( );
00376 
00377         result->length( num );
00378         for( int i = 0; i < num; i++ ) {
00379             (*result)[i] = theListOfOrigins[i].c_str();
00380         }
00381 
00382     } while( false );
00383 
00384     cacheLockEndRead( _cache );
00385 
00386     return result;
00387 }
00388 
00389 BdbCondRemote::Info::StrSequenceType*
00390 BdbCondRInfoImpl::getContainers( const char*        theFederationName,
00391                                  const char*        theSnapshotName,
00392                                  const char*        theDetectorName,
00393                                  const char*        theOriginName,
00394                                  CORBA_Environment& theEnvironment )
00395 {
00396     const char* infoString  = "BdbCondRInfoImpl::getContainers()";
00397     const char* errorString = "BdbCondRInfoImpl::getContainers() - ERROR.";
00398 
00399     BdbCondRemote::Info::StrSequenceType* result = new BdbCondRemote::Info::StrSequenceType( );
00400 
00401     if( _verbose )
00402         cout << "[ " << BdbTime( ) << " ] " << infoString << endl
00403              << "    FEDERATION: " << theFederationName << endl
00404              << "    SNAPSHOT:   " << theSnapshotName << endl
00405              << "    DETECTOR:   " << theDetectorName << endl
00406              << "    ORIGIN:     " << theOriginName << endl;
00407 
00408     if( ! initialize( )) return result;
00409 
00410     cacheLockBeginRead( _cache );
00411 
00412     do {
00413 
00414       // Find the corresponding origin descriptor in the cache.
00415 
00416         BdbCondRInfoOrigin* theOrigin = _cache->findOrigin( theFederationName,
00417                                                             theSnapshotName,
00418                                                             theDetectorName,
00419                                                             theOriginName );
00420         if( 0 == theOrigin ) {
00421 
00422             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
00423                  << "    No such origin in the cache." << endl
00424                  << "        FEDERATION: " << theFederationName << endl
00425                  << "        SNAPSHOT:   " << theSnapshotName << endl
00426                  << "        DETECTOR:   " << theDetectorName << endl
00427                  << "        ORIGIN:     " << theOriginName << endl;
00428             break;
00429         }
00430 
00431       // Load a list of containers from the cache.
00432 
00433         vector<string> theListOfContainers;
00434         theOrigin->keys( theListOfContainers );
00435 
00436         int num = theListOfContainers.size( );
00437 
00438         result->length( num );
00439         for( int i = 0; i < num; i++ ) {
00440             (*result)[i] = theListOfContainers[i].c_str();
00441         }
00442 
00443     } while( false );
00444 
00445     cacheLockEndRead( _cache );
00446 
00447     return result;
00448 }
00449 
00450 BdbCondRemote::Info::StrSequenceType*
00451 BdbCondRInfoImpl::getGenealogy( const char*        theFederationName,
00452                                 const char*        theSnapshotName,
00453                                 const char*        theDetectorName,
00454                                 const char*        theOriginName,
00455                                 const char*        theContainerName,
00456                                 CORBA_Environment& theEnvironment )
00457 {
00458     const char* infoString       = "BdbCondRInfoImpl::getGenealogy()";
00459     const char* fatalErrorString = "BdbCondRInfoImpl::getGenealogy() - FATAL ERROR.";
00460     const char* errorString      = "BdbCondRInfoImpl::getGenealogy() - ERROR.";
00461 
00462     BdbCondRemote::Info::StrSequenceType* result = new BdbCondRemote::Info::StrSequenceType( );
00463 
00464     if( _verbose )
00465         cout << "[ " << BdbTime( ) << " ] " << infoString << endl
00466              << "    FEDERATION: " << theFederationName << endl
00467              << "    SNAPSHOT:   " << theSnapshotName << endl
00468              << "    DETECTOR:   " << theDetectorName << endl
00469              << "    ORIGIN:     " << theOriginName << endl
00470              << "    CONTAINER:  " << theContainerName << endl;
00471 
00472     if( ! initialize( )) return result;
00473 
00474     cacheLockBeginRead( _cache );
00475 
00476     do {
00477 
00478       // Find the corresponding container descriptor in the cache.
00479 
00480         BdbCondRInfoContainer* theContainer = _cache->findContainer( theFederationName,
00481                                                                      theSnapshotName,
00482                                                                      theDetectorName,
00483                                                                      theOriginName,
00484                                                                      theContainerName );
00485         if( 0 == theContainer ) {
00486 
00487             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
00488                  << "    No such container in the cache." << endl
00489                  << "        FEDERATION: " << theFederationName << endl
00490                  << "        SNAPSHOT:   " << theSnapshotName << endl
00491                  << "        DETECTOR:   " << theDetectorName << endl
00492                  << "        ORIGIN:     " << theOriginName << endl
00493                  << "        CONTAINER:  " << theContainerName << endl;
00494             break;
00495         }
00496 
00497       // The following operations are executed withing an infinitive
00498       // loop until the stable state of the container is found.
00499       //
00500       // NOTE: We are not keeping any type of locks while checking the container
00501       //       state until we really need reliable access to the container's data
00502       //       structures.
00503       //
00504       //       Also when we establish the proper lock then we check the container
00505       //       state again because another thread might change it at this time.
00506 
00507         while( true ) {
00508 
00509             if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
00510 
00511                 containerLockBeginRead( theContainer );
00512 
00513                 if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
00514 
00515                   // Just copy Genealogy from the container cache into
00516                   // the resulting sequence.
00517 
00518                     vector<string>& theGenealogyList = theContainer->getGenealogyList( );
00519                     int num = theGenealogyList.size( );
00520 
00521                     result->length( num );
00522                     for( int i = 0; i < num; i++ ) {
00523                         (*result)[i] = theGenealogyList[i].c_str();
00524                     }
00525 
00526                   // Release the lock and break the infinite loop becase
00527                   // we're done with this container.
00528 
00529                     containerLockEndRead( theContainer );
00530 
00531                     break;
00532                 }
00533 
00534                 containerLockEndRead( theContainer );
00535 
00536             } else if(( BdbCondRInfoContainer::IS_EMPTY     == theContainer->getState( )) ||
00537                       ( BdbCondRInfoContainer::IS_SCHEDULED == theContainer->getState( )) ||
00538                       ( BdbCondRInfoContainer::IS_LOADING   == theContainer->getState( ))) {
00539 
00540               // Obtain the WRITER lock for the container and load the container
00541               // if it's still in the same state (except the "IS_LOADING" state, which
00542               // is not possible under the protection of the WRITER lock. See the subsequent
00543               // check and fatal error reporting.).
00544               //
00545               //  NOTE: The trick we use here is that even if the container remains in
00546               //        the "IS_SCHEDULED" state when we get the WRITER lock on the container
00547               //        then we still are able to load the container and to upgrade its
00548               //        state to the "IS_LOADED" (or "IS_UNAVAILABLE" in case of a error).
00549               //        Later this will be discovered by another loader when it will
00550               //        get an exclusive WRITER access over this container.
00551               //
00552               // Then we continue in the current loop for the next try to get the genealogy
00553               // from the loaded state or report a problem if the container is not
00554               // available at all. Here we rely on the change of container status done
00555               // by the loader.
00556 
00557                 containerLockBeginWrite( theContainer );
00558 
00559                 if(( BdbCondRInfoContainer::IS_EMPTY     == theContainer->getState( )) ||
00560                    ( BdbCondRInfoContainer::IS_SCHEDULED == theContainer->getState( ))) {
00561 
00562                   // Directly call the loader to load the container (assuming that the new state of
00563                   // the container has already been set by this procedure).
00564 
00565                     BdbCondRInfoJob* theJobPtr = new BdbCondRInfoJob( theContainer,
00566                                                                       theFederationName,
00567                                                                       theSnapshotName,
00568                                                                       theDetectorName,
00569                                                                       theOriginName,
00570                                                                       theContainerName );
00571 
00572                     _myLoader->load( theJobPtr );
00573 
00574                     delete theJobPtr;
00575 
00576                 } else if( BdbCondRInfoContainer::IS_LOADING == theContainer->getState( )) {
00577 
00578                     cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
00579                          << "    Unexpected container state was discovered under protcetion of the WRITER lock." << endl
00580                          << "    This is a fatal internal bug." << endl;
00581                     exit( 1 );
00582                 }
00583 
00584                 containerLockEndWrite( theContainer );
00585 
00586             } else if( BdbCondRInfoContainer::IS_UNAVAILABLE == theContainer->getState( )) {
00587 
00588               // Just break the current loop to return the empty genealogy since the container
00589               // can not be loaded under any circumstances.
00590 
00591                 break;
00592 
00593             } else {
00594 
00595                 cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
00596                      << "    Unknown container state. This is a fatal internal bug." << endl;
00597                 exit( 1 );
00598             }
00599         }
00600 
00601     } while( false );
00602 
00603     cacheLockEndRead( _cache );
00604 
00605     return result;
00606 }
00607 
00608 BdbCondRemote::Info::StrSequenceType*
00609 BdbCondRInfoImpl::tryGetGenealogy( const char*                                  theFederationName,
00610                                    const char*                                  theSnapshotName,
00611                                    const char*                                  theDetectorName,
00612                                    const char*                                  theOriginName,
00613                                    const char*                                  theContainerName,
00614                                    BdbCondRemote::Info::ContainerStatusType_out theStatus,
00615                                    CORBA_Environment&                           theEnvironment )
00616 {
00617     const char* infoString       = "BdbCondRInfoImpl::tryGetGenealogy()";
00618     const char* fatalErrorString = "BdbCondRInfoImpl::tryGetGenealogy() - FATAL ERROR.";
00619     const char* errorString      = "BdbCondRInfoImpl::tryGetGenealogy() - ERROR.";
00620 
00621     BdbCondRemote::Info::StrSequenceType* result = new BdbCondRemote::Info::StrSequenceType( );
00622 
00623     theStatus.state  = BdbCondRemote::Info::IS_UNAVAILABLE;
00624     theStatus.loaded = 0;
00625     theStatus.total  = 0;
00626 
00627     if( _verbose )
00628         cout << "[ " << BdbTime( ) << " ] " << infoString << endl
00629              << "    FEDERATION: " << theFederationName << endl
00630              << "    SNAPSHOT:   " << theSnapshotName << endl
00631              << "    DETECTOR:   " << theDetectorName << endl
00632              << "    ORIGIN:     " << theOriginName << endl
00633              << "    CONTAINER:  " << theContainerName << endl;
00634 
00635     if( ! initialize( )) return result;
00636 
00637     cacheLockBeginRead( _cache );
00638 
00639     do {
00640 
00641       // Find the corresponding container descriptor in the cache.
00642 
00643         BdbCondRInfoContainer* theContainer = _cache->findContainer( theFederationName,
00644                                                                      theSnapshotName,
00645                                                                      theDetectorName,
00646                                                                      theOriginName,
00647                                                                      theContainerName );
00648         if( 0 == theContainer ) {
00649 
00650             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
00651                  << "    No such container in the cache." << endl
00652                  << "        FEDERATION: " << theFederationName << endl
00653                  << "        SNAPSHOT:   " << theSnapshotName << endl
00654                  << "        DETECTOR:   " << theDetectorName << endl
00655                  << "        ORIGIN:     " << theOriginName << endl
00656                  << "        CONTAINER:  " << theContainerName << endl;
00657             break;
00658         }
00659 
00660       // The following operations are executed withing an infinitive
00661       // loop until the stable state of the container is found.
00662       //
00663       // NOTE: We are not keeping any type of locks while checking the container
00664       //       state until we really need reliable access to the container's data
00665       //       structures.
00666       //
00667       //       Also when we establish the proper lock then we check the container
00668       //       state again because another thread might change it at this time.
00669 
00670         while( true ) {
00671 
00672             if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
00673 
00674                 containerLockBeginRead( theContainer );
00675 
00676                 if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
00677 
00678                   // Just copy Genealogy from the container cache into
00679                   // the resulting sequence.
00680 
00681                     vector<string>& theGenealogyList = theContainer->getGenealogyList( );
00682                     int num = theGenealogyList.size( );
00683 
00684                     result->length( num );
00685                     for( int i = 0; i < num; i++ ) {
00686                         (*result)[i] = theGenealogyList[i].c_str();
00687                     }
00688 
00689                   // Release the lock and break the infinite loop becase
00690                   // we're done with this container.
00691 
00692                     containerLockEndRead( theContainer );
00693 
00694                   // Set the proper status.
00695 
00696                     theStatus.state = BdbCondRemote::Info::IS_LOADED;
00697 
00698                     break;
00699                 }
00700 
00701                 containerLockEndRead( theContainer );
00702 
00703             } else if( BdbCondRInfoContainer::IS_EMPTY == theContainer->getState( )) {
00704 
00705               // Obtain the WRITER lock for the container and submit the container
00706               // for loading if it's still in the same state.
00707 
00708                 containerLockBeginWrite( theContainer );
00709 
00710                 if( BdbCondRInfoContainer::IS_EMPTY == theContainer->getState( )) {
00711 
00712                   // Change the container state and put into the jobs queue
00713                   // for the loading.
00714 
00715                     theContainer->setState( BdbCondRInfoContainer::IS_SCHEDULED );
00716 
00717                     BdbCondRInfoJob* theJobPtr = new BdbCondRInfoJob( theContainer,
00718                                                                       theFederationName,
00719                                                                       theSnapshotName,
00720                                                                       theDetectorName,
00721                                                                       theOriginName,
00722                                                                       theContainerName );
00723 
00724                     _myJobsQueue->insert( theJobPtr );
00725                 }
00726 
00727                 containerLockEndWrite( theContainer );
00728 
00729             } else if( BdbCondRInfoContainer::IS_SCHEDULED == theContainer->getState( )) {
00730 
00731               // Set the proper status.
00732 
00733                 theStatus.state = BdbCondRemote::Info::IS_SCHEDULED;
00734 
00735                 break;
00736 
00737             } else if( BdbCondRInfoContainer::IS_LOADING == theContainer->getState( )) {
00738 
00739               // Set the proper status.
00740 
00741                 theStatus.state  = BdbCondRemote::Info::IS_LOADING;
00742                 theStatus.loaded = theContainer->getNumLoaded( );
00743                 theStatus.total  = theContainer->getNumTotal( );
00744 
00745                 break;
00746 
00747             } else if( BdbCondRInfoContainer::IS_UNAVAILABLE == theContainer->getState( )) {
00748 
00749               // Set the proper status.
00750 
00751                 theStatus.state = BdbCondRemote::Info::IS_UNAVAILABLE;
00752 
00753                 break;
00754 
00755             } else {
00756 
00757                 cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
00758                      << "    Unknown container state. This is a fatal internal bug." << endl;
00759                 exit( 1 );
00760             }
00761         }
00762 
00763     } while( false );
00764 
00765     cacheLockEndRead( _cache );
00766 
00767     return result;
00768 }
00769 
00770 BdbCondRemote::Info::RevisionsSequenceType*
00771 BdbCondRInfoImpl::getRevisions( const char*        theFederationName,
00772                                 const char*        theSnapshotName,
00773                                 const char*        theDetectorName,
00774                                 const char*        theOriginName,
00775                                 const char*        theContainerName,
00776                                 CORBA_Environment& theEnvironment )
00777 {
00778     const char* infoString       = "BdbCondRInfoImpl::getRevisions()";
00779     const char* fatalErrorString = "BdbCondRInfoImpl::getRevisions() - FATAL ERROR.";
00780     const char* errorString      = "BdbCondRInfoImpl::getRevisions() - ERROR.";
00781 
00782     BdbCondRemote::Info::RevisionsSequenceType* result = new BdbCondRemote::Info::RevisionsSequenceType( );
00783 
00784     if( _verbose )
00785         cout << "[ " << BdbTime( ) << " ] " << infoString << endl
00786              << "    FEDERATION: " << theFederationName << endl
00787              << "    SNAPSHOT:   " << theSnapshotName << endl
00788              << "    DETECTOR:   " << theDetectorName << endl
00789              << "    ORIGIN:     " << theOriginName << endl
00790              << "    CONTAINER:  " << theContainerName << endl;
00791 
00792     if( ! initialize( )) return result;
00793 
00794     cacheLockBeginRead( _cache );
00795 
00796     do {
00797 
00798       // Find the corresponding container descriptor in the cache.
00799 
00800         BdbCondRInfoContainer* theContainer = _cache->findContainer( theFederationName,
00801                                                                      theSnapshotName,
00802                                                                      theDetectorName,
00803                                                                      theOriginName,
00804                                                                      theContainerName );
00805         if( 0 == theContainer ) {
00806             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
00807                  << "    No such container in the cache." << endl
00808                  << "        FEDERATION: " << theFederationName << endl
00809                  << "        SNAPSHOT:   " << theSnapshotName << endl
00810                  << "        DETECTOR:   " << theDetectorName << endl
00811                  << "        ORIGIN:     " << theOriginName << endl
00812                  << "        CONTAINER:  " << theContainerName << endl;
00813             break;
00814         }
00815 
00816       // The following operations are executed withing an infinitive
00817       // loop until the stable state of the container is found.
00818       //
00819       // NOTE: We are not keeping any type of locks while checking the container
00820       //       state until we really need reliable access to the container's data
00821       //       structures.
00822       //
00823       //       Also when we establish the proper lock then we check the container
00824       //       state again because another thread might change it at this time.
00825 
00826         while( true ) {
00827 
00828             if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
00829 
00830                 containerLockBeginRead( theContainer );
00831 
00832                 if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
00833 
00834                   // Convert and copy the revision information from the container cache into
00835                   // the resulting sequence.
00836 
00837                     vector<BdbCondTRevision*>& theRevisionsList = theContainer->getRevisionsList( );
00838                     int num = theRevisionsList.size( );
00839 
00840                     result->length( num );
00841                     for( int i = 0; i < num; i++ ) {
00842 
00843                       // We expect that resulting sequence will make a deep copy of
00844                       // the data. This is why we are deleting the converted abject afterwards.
00845 
00846                         BdbCondRemote::Info::RevisionType* revisionPtr = BdbCondRInfoConversionFactory::convert( theRevisionsList[i] );
00847 
00848                         (*result)[i] = *revisionPtr;
00849 
00850                         delete revisionPtr;
00851                     }
00852 
00853                   // Release the lock and break the infinite loop becase
00854                   // we're done with this container.
00855 
00856                     containerLockEndRead( theContainer );
00857 
00858                     break;
00859                 }
00860 
00861                 containerLockEndRead( theContainer );
00862 
00863             } else if(( BdbCondRInfoContainer::IS_EMPTY     == theContainer->getState( )) ||
00864                       ( BdbCondRInfoContainer::IS_SCHEDULED == theContainer->getState( )) ||
00865                       ( BdbCondRInfoContainer::IS_LOADING   == theContainer->getState( ))) {
00866 
00867               // Obtain the WRITER lock for the container and load the container
00868               // if it's still in the same state (except the "IS_LOADING" state, which
00869               // is not possible under the protection of the WRITER lock. See the subsequent
00870               // check and fatal error reporting.).
00871               //
00872               //  NOTE: The trick we use here is that even if the container remains in
00873               //        the "IS_SCHEDULED" state when we get the WRITER lock on the container
00874               //        then we still are able to load the container and to upgrade its
00875               //        state to the "IS_LOADED" (or "IS_UNAVAILABLE" in case of a error).
00876               //        Later this will be discovered by another loader when it will
00877               //        get an exclusive WRITER access over this container.
00878               //
00879               // Then we continue in the current loop for the next try to get the genealogy
00880               // from the loaded state or report a problem if the container is not
00881               // available at all. Here we rely on the change of container status done
00882               // by the loader.
00883 
00884                 containerLockBeginWrite( theContainer );
00885 
00886                 if(( BdbCondRInfoContainer::IS_EMPTY     == theContainer->getState( )) ||
00887                    ( BdbCondRInfoContainer::IS_SCHEDULED == theContainer->getState( ))) {
00888 
00889                   // Directly call the loader to load the container (assuming that the new state of
00890                   // the container has already been set by this procedure).
00891 
00892                     BdbCondRInfoJob* theJobPtr = new BdbCondRInfoJob( theContainer,
00893                                                                       theFederationName,
00894                                                                       theSnapshotName,
00895                                                                       theDetectorName,
00896                                                                       theOriginName,
00897                                                                       theContainerName );
00898 
00899                     _myLoader->load( theJobPtr );
00900 
00901                     delete theJobPtr;
00902 
00903                 } else if( BdbCondRInfoContainer::IS_LOADING == theContainer->getState( )) {
00904 
00905                     cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
00906                          << "    Unexpected container state was discovered under protcetion of the WRITER lock." << endl
00907                          << "    This is a fatal internal bug." << endl;
00908 
00909                     exit( 1 );
00910                 }
00911 
00912                 containerLockEndWrite( theContainer );
00913 
00914             } else if( BdbCondRInfoContainer::IS_UNAVAILABLE == theContainer->getState( )) {
00915 
00916               // Just break the current loop to return the empty genealogy since the container
00917               // can not be loaded under any circumstances.
00918 
00919                 break;
00920 
00921             } else {
00922 
00923                 cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
00924                      << "    Unknown container state. This is a fatal internal bug." << endl;
00925 
00926                 exit( 1 );
00927             }
00928         }
00929 
00930     } while( false );
00931 
00932     cacheLockEndRead( _cache );
00933 
00934     return result;
00935 }
00936 
00937 BdbCondRemote::Info::RevisionsSequenceType*
00938 BdbCondRInfoImpl::tryGetRevisions( const char*                                  theFederationName,
00939                                    const char*                                  theSnapshotName,
00940                                    const char*                                  theDetectorName,
00941                                    const char*                                  theOriginName,
00942                                    const char*                                  theContainerName,
00943                                    BdbCondRemote::Info::ContainerStatusType_out theStatus,
00944                                    CORBA_Environment&                           theEnvironment )
00945 {
00946     const char* infoString       = "BdbCondRInfoImpl::tryGetRevisions()";
00947     const char* fatalErrorString = "BdbCondRInfoImpl::tryGetRevisions() - FATAL ERROR.";
00948     const char* errorString      = "BdbCondRInfoImpl::tryGetRevisions() - ERROR.";
00949 
00950     BdbCondRemote::Info::RevisionsSequenceType* result = new BdbCondRemote::Info::RevisionsSequenceType( );
00951 
00952     theStatus.state  = BdbCondRemote::Info::IS_UNAVAILABLE;
00953     theStatus.loaded = 0;
00954     theStatus.total  = 0;
00955 
00956     if( _verbose )
00957         cout << "[ " << BdbTime( ) << " ] " << infoString << endl
00958              << "    FEDERATION: " << theFederationName << endl
00959              << "    SNAPSHOT:   " << theSnapshotName << endl
00960              << "    DETECTOR:   " << theDetectorName << endl
00961              << "    ORIGIN:     " << theOriginName << endl
00962              << "    CONTAINER:  " << theContainerName << endl;
00963 
00964     if( ! initialize( )) return result;
00965 
00966     cacheLockBeginRead( _cache );
00967 
00968     do {
00969 
00970       // Find the corresponding container descriptor in the cache.
00971 
00972         BdbCondRInfoContainer* theContainer = _cache->findContainer( theFederationName,
00973                                                                      theSnapshotName,
00974                                                                      theDetectorName,
00975                                                                      theOriginName,
00976                                                                      theContainerName );
00977         if( 0 == theContainer ) {
00978 
00979             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
00980                  << "    No such container in the cache." << endl
00981                  << "        FEDERATION: " << theFederationName << endl
00982                  << "        SNAPSHOT:   " << theSnapshotName << endl
00983                  << "        DETECTOR:   " << theDetectorName << endl
00984                  << "        ORIGIN:     " << theOriginName << endl
00985                  << "        CONTAINER:  " << theContainerName << endl;
00986             break;
00987         }
00988 
00989       // The following operations are executed withing an infinitive
00990       // loop until the stable state of the container is found.
00991       //
00992       // NOTE: We are not keeping any type of locks while checking the container
00993       //       state until we really need reliable access to the container's data
00994       //       structures.
00995       //
00996       //       Also when we establish the proper lock then we check the container
00997       //       state again because another thread might change it at this time.
00998 
00999         while( true ) {
01000 
01001             if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
01002 
01003                 containerLockBeginRead( theContainer );
01004 
01005                 if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
01006 
01007                   // Convert and copy the revision information from the container cache into
01008                   // the resulting sequence.
01009 
01010                     vector<BdbCondTRevision*>& theRevisionsList = theContainer->getRevisionsList( );
01011                     int num = theRevisionsList.size( );
01012 
01013                     result->length( num );
01014                     for( int i = 0; i < num; i++ ) {
01015 
01016                       // We expect that resulting sequence will make a deep copy of
01017                       // the data. This is why we are deleting the converted abject afterwards.
01018 
01019                         BdbCondRemote::Info::RevisionType* revisionPtr = BdbCondRInfoConversionFactory::convert( theRevisionsList[i] );
01020 
01021                         (*result)[i] = *revisionPtr;
01022 
01023                         delete revisionPtr;
01024                     }
01025 
01026                   // Release the lock and break the infinite loop becase
01027                   // we're done with this container.
01028 
01029                     containerLockEndRead( theContainer );
01030 
01031                   // Set the proper status.
01032 
01033                     theStatus.state = BdbCondRemote::Info::IS_LOADED;
01034 
01035                     break;
01036                 }
01037 
01038                 containerLockEndRead( theContainer );
01039 
01040             } else if( BdbCondRInfoContainer::IS_EMPTY == theContainer->getState( )) {
01041 
01042               // Obtain the WRITER lock for the container and submit the container
01043               // for loading if it's still in the same state.
01044 
01045                 containerLockBeginWrite( theContainer );
01046 
01047                 if( BdbCondRInfoContainer::IS_EMPTY == theContainer->getState( )) {
01048 
01049                   // Change the container state and put into the jobs queue
01050                   // for the loading.
01051 
01052                     theContainer->setState( BdbCondRInfoContainer::IS_SCHEDULED );
01053 
01054                     BdbCondRInfoJob* theJobPtr = new BdbCondRInfoJob( theContainer,
01055                                                                       theFederationName,
01056                                                                       theSnapshotName,
01057                                                                       theDetectorName,
01058                                                                       theOriginName,
01059                                                                       theContainerName );
01060 
01061                     _myJobsQueue->insert( theJobPtr );
01062                 }
01063 
01064                 containerLockEndWrite( theContainer );
01065 
01066             } else if( BdbCondRInfoContainer::IS_SCHEDULED == theContainer->getState( )) {
01067 
01068               // Set the proper status.
01069 
01070                 theStatus.state = BdbCondRemote::Info::IS_SCHEDULED;
01071 
01072                 break;
01073 
01074             } else if( BdbCondRInfoContainer::IS_LOADING == theContainer->getState( )) {
01075 
01076               // Set the proper status.
01077 
01078                 theStatus.state  = BdbCondRemote::Info::IS_LOADING;
01079                 theStatus.loaded = theContainer->getNumLoaded( );
01080                 theStatus.total  = theContainer->getNumTotal( );
01081 
01082                 break;
01083 
01084             } else if( BdbCondRInfoContainer::IS_UNAVAILABLE == theContainer->getState( )) {
01085 
01086               // Set the proper status.
01087 
01088                 theStatus.state = BdbCondRemote::Info::IS_UNAVAILABLE;
01089 
01090                 break;
01091 
01092             } else {
01093 
01094                 cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01095                      << "    Unknown container state. This is a fatal internal bug." << endl;
01096                 exit( 1 );
01097             }
01098         }
01099 
01100     } while( false );
01101 
01102     cacheLockEndRead( _cache );
01103 
01104     return result;
01105 }
01106 
01107 BdbCondRemote::Info::HistRecordSequenceType*
01108 BdbCondRInfoImpl::getHistory( const char*        theFederationName,
01109                               const char*        theSnapshotName,
01110                               const char*        theDetectorName,
01111                               const char*        theOriginName,
01112                               const char*        theContainerName,
01113                               CORBA_Environment& theEnvironment )
01114 {
01115     const char* infoString       = "BdbCondRInfoImpl::getHistory()";
01116     const char* fatalErrorString = "BdbCondRInfoImpl::getHistory() - FATAL ERROR.";
01117     const char* errorString      = "BdbCondRInfoImpl::getHistory() - ERROR.";
01118 
01119     BdbCondRemote::Info::HistRecordSequenceType* result = new BdbCondRemote::Info::HistRecordSequenceType( );
01120 
01121     if( _verbose )
01122         cout << "[ " << BdbTime( ) << " ] " << infoString << endl
01123              << "    FEDERATION: " << theFederationName << endl
01124              << "    SNAPSHOT:   " << theSnapshotName << endl
01125              << "    DETECTOR:   " << theDetectorName << endl
01126              << "    ORIGIN:     " << theOriginName << endl
01127              << "    CONTAINER:  " << theContainerName << endl;
01128 
01129     if( ! initialize( )) return result;
01130 
01131     cacheLockBeginRead( _cache );
01132 
01133     do {
01134 
01135       // Find the corresponding container descriptor in the cache.
01136 
01137         BdbCondRInfoContainer* theContainer = _cache->findContainer( theFederationName,
01138                                                                      theSnapshotName,
01139                                                                      theDetectorName,
01140                                                                      theOriginName,
01141                                                                      theContainerName );
01142         if( 0 == theContainer ) {
01143 
01144             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
01145                  << "    No such container in the cache." << endl
01146                  << "        FEDERATION: " << theFederationName << endl
01147                  << "        SNAPSHOT:   " << theSnapshotName << endl
01148                  << "        DETECTOR:   " << theDetectorName << endl
01149                  << "        ORIGIN:     " << theOriginName << endl
01150                  << "        CONTAINER:  " << theContainerName << endl;
01151             break;
01152         }
01153 
01154       // The following operations are executed withing an infinitive
01155       // loop until the stable state of the container is found.
01156       //
01157       // NOTE: We are not keeping any type of locks while checking the container
01158       //       state until we really need reliable access to the container's data
01159       //       structures.
01160       //
01161       //       Also when we establish the proper lock then we check the container
01162       //       state again because another thread might change it at this time.
01163 
01164         while( true ) {
01165 
01166             if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
01167 
01168                 containerLockBeginRead( theContainer );
01169 
01170                 if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
01171 
01172                   // Convert and copy the history information from the container cache into
01173                   // the resulting sequence.
01174 
01175                     vector<BdbCondTHistoryRecord*>& theHistoryList = theContainer->getHistoryList( );
01176                     int num = theHistoryList.size( );
01177 
01178                     result->length( num );
01179                     for( int i = 0; i < num; i++ ) {
01180 
01181                       // We expect that resulting sequence will make a deep copy of
01182                       // the data. This is why we are deleting the converted abject afterwards.
01183 
01184                         BdbCondRemote::Info::HistRecordType* recordPtr = BdbCondRInfoConversionFactory::convert( theHistoryList[i] );
01185 
01186                         (*result)[i] = *recordPtr;
01187 
01188                         delete recordPtr;
01189                     }
01190 
01191                   // Release the lock and break the infinite loop becase
01192                   // we're done with this container.
01193 
01194                     containerLockEndRead( theContainer );
01195 
01196                     break;
01197                 }
01198 
01199                 containerLockEndRead( theContainer );
01200 
01201             } else if(( BdbCondRInfoContainer::IS_EMPTY     == theContainer->getState( )) ||
01202                       ( BdbCondRInfoContainer::IS_SCHEDULED == theContainer->getState( )) ||
01203                       ( BdbCondRInfoContainer::IS_LOADING   == theContainer->getState( ))) {
01204 
01205               // Obtain the WRITER lock for the container and load the container
01206               // if it's still in the same state (except the "IS_LOADING" state, which
01207               // is not possible under the protection of the WRITER lock. See the subsequent
01208               // check and fatal error reporting.).
01209               //
01210               //  NOTE: The trick we use here is that even if the container remains in
01211               //        the "IS_SCHEDULED" state when we get the WRITER lock on the container
01212               //        then we still are able to load the container and to upgrade its
01213               //        state to the "IS_LOADED" (or "IS_UNAVAILABLE" in case of a error).
01214               //        Later this will be discovered by another loader when it will
01215               //        get an exclusive WRITER access over this container.
01216               //
01217               // Then we continue in the current loop for the next try to get the genealogy
01218               // from the loaded state or report a problem if the container is not
01219               // available at all. Here we rely on the change of container status done
01220               // by the loader.
01221 
01222                 containerLockBeginWrite( theContainer );
01223 
01224                 if(( BdbCondRInfoContainer::IS_EMPTY     == theContainer->getState( )) ||
01225                    ( BdbCondRInfoContainer::IS_SCHEDULED == theContainer->getState( ))) {
01226 
01227                   // Directly call the loader to load the container (assuming that the new state of
01228                   // the container has already been set by this procedure).
01229 
01230                     BdbCondRInfoJob* theJobPtr = new BdbCondRInfoJob( theContainer,
01231                                                                       theFederationName,
01232                                                                       theSnapshotName,
01233                                                                       theDetectorName,
01234                                                                       theOriginName,
01235                                                                       theContainerName );
01236 
01237                     _myLoader->load( theJobPtr );
01238 
01239                     delete theJobPtr;
01240 
01241                 } else if( BdbCondRInfoContainer::IS_LOADING == theContainer->getState( )) {
01242 
01243                     cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01244                          << "    Unexpected container state was discovered under protcetion of the WRITER lock." << endl
01245                          << "    This is a fatal internal bug." << endl;
01246                     exit( 1 );
01247                 }
01248 
01249                 containerLockEndWrite( theContainer );
01250 
01251             } else if( BdbCondRInfoContainer::IS_UNAVAILABLE == theContainer->getState( )) {
01252 
01253               // Just break the current loop to return the empty genealogy since the container
01254               // can not be loaded under any circumstances.
01255 
01256                 break;
01257 
01258             } else {
01259 
01260                 cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01261                      << "    Unknown container state. This is a fatal internal bug." << endl;
01262                 exit( 1 );
01263             }
01264         }
01265 
01266     } while( false );
01267 
01268     cacheLockEndRead( _cache );
01269 
01270     return result;
01271 }
01272 
01273 BdbCondRemote::Info::HistRecordSequenceType*
01274 BdbCondRInfoImpl::tryGetHistory( const char*                                  theFederationName,
01275                                  const char*                                  theSnapshotName,
01276                                  const char*                                  theDetectorName,
01277                                  const char*                                  theOriginName,
01278                                  const char*                                  theContainerName,
01279                                  BdbCondRemote::Info::ContainerStatusType_out theStatus,
01280                                  CORBA_Environment&                           theEnvironment )
01281 {
01282     const char* infoString       = "BdbCondRInfoImpl::tryGetHistory()";
01283     const char* fatalErrorString = "BdbCondRInfoImpl::tryGetHistory() - FATAL ERROR.";
01284     const char* errorString      = "BdbCondRInfoImpl::tryGetHistory() - ERROR.";
01285 
01286     BdbCondRemote::Info::HistRecordSequenceType* result = new BdbCondRemote::Info::HistRecordSequenceType( );
01287 
01288     theStatus.state  = BdbCondRemote::Info::IS_UNAVAILABLE;
01289     theStatus.loaded = 0;
01290     theStatus.total  = 0;
01291 
01292     if( _verbose )
01293         cout << "[ " << BdbTime( ) << " ] " << infoString << endl
01294              << "    FEDERATION: " << theFederationName << endl
01295              << "    SNAPSHOT:   " << theSnapshotName << endl
01296              << "    DETECTOR:   " << theDetectorName << endl
01297              << "    ORIGIN:     " << theOriginName << endl
01298              << "    CONTAINER:  " << theContainerName << endl;
01299 
01300     if( ! initialize( )) return result;
01301 
01302     cacheLockBeginRead( _cache );
01303 
01304     do {
01305 
01306       // Find the corresponding container descriptor in the cache.
01307 
01308         BdbCondRInfoContainer* theContainer = _cache->findContainer( theFederationName,
01309                                                                      theSnapshotName,
01310                                                                      theDetectorName,
01311                                                                      theOriginName,
01312                                                                      theContainerName );
01313         if( 0 == theContainer ) {
01314 
01315             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
01316                  << "    No such container in the cache." << endl
01317                  << "        FEDERATION: " << theFederationName << endl
01318                  << "        SNAPSHOT:   " << theSnapshotName << endl
01319                  << "        DETECTOR:   " << theDetectorName << endl
01320                  << "        ORIGIN:     " << theOriginName << endl
01321                  << "        CONTAINER:  " << theContainerName << endl;
01322             break;
01323         }
01324 
01325       // The following operations are executed withing an infinitive
01326       // loop until the stable state of the container is found.
01327       //
01328       // NOTE: We are not keeping any type of locks while checking the container
01329       //       state until we really need reliable access to the container's data
01330       //       structures.
01331       //
01332       //       Also when we establish the proper lock then we check the container
01333       //       state again because another thread might change it at this time.
01334 
01335         while( true ) {
01336 
01337             if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
01338 
01339                 containerLockBeginRead( theContainer );
01340 
01341                 if( BdbCondRInfoContainer::IS_LOADED == theContainer->getState( )) {
01342 
01343                   // Convert and copy the history information from the container cache into
01344                   // the resulting sequence.
01345 
01346                     vector<BdbCondTHistoryRecord*>& theHistoryList = theContainer->getHistoryList( );
01347                     int num = theHistoryList.size( );
01348 
01349                     result->length( num );
01350                     for( int i = 0; i < num; i++ ) {
01351 
01352                       // We expect that resulting sequence will make a deep copy of
01353                       // the data. This is why we are deleting the converted abject afterwards.
01354 
01355                         BdbCondRemote::Info::HistRecordType* recordPtr = BdbCondRInfoConversionFactory::convert( theHistoryList[i] );
01356 
01357                         (*result)[i] = *recordPtr;
01358 
01359                         delete recordPtr;
01360                     }
01361 
01362                   // Release the lock and break the infinite loop becase
01363                   // we're done with this container.
01364 
01365                     containerLockEndRead( theContainer );
01366 
01367                   // Set the proper status.
01368 
01369                     theStatus.state = BdbCondRemote::Info::IS_LOADED;
01370 
01371                     break;
01372                 }
01373 
01374                 containerLockEndRead( theContainer );
01375 
01376             } else if( BdbCondRInfoContainer::IS_EMPTY == theContainer->getState( )) {
01377 
01378               // Obtain the WRITER lock for the container and submit the container
01379               // for loading if it's still in the same state.
01380 
01381                 containerLockBeginWrite( theContainer );
01382 
01383                 if( BdbCondRInfoContainer::IS_EMPTY == theContainer->getState( )) {
01384 
01385                   // Change the container state and put into the jobs queue
01386                   // for the loading.
01387 
01388                     theContainer->setState( BdbCondRInfoContainer::IS_SCHEDULED );
01389 
01390                     BdbCondRInfoJob* theJobPtr = new BdbCondRInfoJob( theContainer,
01391                                                                       theFederationName,
01392                                                                       theSnapshotName,
01393                                                                       theDetectorName,
01394                                                                       theOriginName,
01395                                                                       theContainerName );
01396 
01397                     _myJobsQueue->insert( theJobPtr );
01398                 }
01399 
01400                 containerLockEndWrite( theContainer );
01401 
01402             } else if( BdbCondRInfoContainer::IS_SCHEDULED == theContainer->getState( )) {
01403 
01404               // Set the proper status.
01405 
01406                 theStatus.state = BdbCondRemote::Info::IS_SCHEDULED;
01407 
01408                 break;
01409 
01410             } else if( BdbCondRInfoContainer::IS_LOADING == theContainer->getState( )) {
01411 
01412               // Set the proper status.
01413 
01414                 theStatus.state  = BdbCondRemote::Info::IS_LOADING;
01415                 theStatus.loaded = theContainer->getNumLoaded( );
01416                 theStatus.total  = theContainer->getNumTotal( );
01417 
01418                 break;
01419 
01420             } else if( BdbCondRInfoContainer::IS_UNAVAILABLE == theContainer->getState( )) {
01421 
01422               // Set the proper status.
01423 
01424                 theStatus.state = BdbCondRemote::Info::IS_UNAVAILABLE;
01425 
01426                 break;
01427 
01428             } else {
01429 
01430                 cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01431                      << "    Unknown container state. This is a fatal internal bug." << endl;
01432                 exit( 1 );
01433             }
01434         }
01435 
01436     } while( false );
01437 
01438     cacheLockEndRead( _cache );
01439 
01440     return result;
01441 }
01442 
01443 CORBA::Boolean
01444 BdbCondRInfoImpl::resetContainer( const char*        theFederationName,
01445                                   const char*        theSnapshotName,
01446                                   const char*        theDetectorName,
01447                                   const char*        theOriginName,
01448                                   const char*        theContainerName,
01449                                   CORBA_Environment& theEnvironment )
01450 {
01451     const char* infoString  = "BdbCondRInfoImpl::resetContainer()";
01452     const char* errorString = "BdbCondRInfoImpl::resetContainer() - ERROR.";
01453 
01454 
01455     CORBA::Boolean result = 0;
01456 
01457     if( _verbose )
01458         cout << "[ " << BdbTime( ) << " ] " << infoString << endl
01459              << "    FEDERATION: " << theFederationName << endl
01460              << "    SNAPSHOT:   " << theSnapshotName << endl
01461              << "    DETECTOR:   " << theDetectorName << endl
01462              << "    ORIGIN:     " << theOriginName << endl
01463              << "    CONTAINER:  " << theContainerName << endl;
01464 
01465     if( ! initialize( )) return result;
01466 
01467     cacheLockBeginRead( _cache );
01468 
01469     do {
01470 
01471       // Find the corresponding container descriptor in the cache.
01472 
01473         BdbCondRInfoContainer* theContainer = _cache->findContainer( theFederationName,
01474                                                                      theSnapshotName,
01475                                                                      theDetectorName,
01476                                                                      theOriginName,
01477                                                                      theContainerName );
01478         if( 0 == theContainer ) {
01479 
01480             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
01481                  << "    No such container in the cache." << endl
01482                  << "        FEDERATION: " << theFederationName << endl
01483                  << "        SNAPSHOT:   " << theSnapshotName << endl
01484                  << "        DETECTOR:   " << theDetectorName << endl
01485                  << "        ORIGIN:     " << theOriginName << endl
01486                  << "        CONTAINER:  " << theContainerName << endl;
01487             break;
01488         }
01489 
01490       // We are only care about the following states:
01491       //
01492       //    IS_LOADED
01493       //    IS_UNAVAILABLE
01494       //
01495       // If this is a case then we will reset a container.
01496       //
01497       // NOTE: Resetting container from the "UNAVAILABLE" state would allow
01498       //       us another attempt to load it from the persistent store if something
01499       //       has happened since the previous un-successfull attempt.
01500       //
01501       // NOTE: We're ignoring IS_SCHEDULED and IS_LOADING states because the container
01502       //       is still not loaded or is just about to be loaded, which is sufficient
01503       //       for us.
01504 
01505         result = 1;
01506 
01507         if(( BdbCondRInfoContainer::IS_LOADED      == theContainer->getState( )) ||
01508            ( BdbCondRInfoContainer::IS_UNAVAILABLE == theContainer->getState( ))) {
01509 
01510           // Set proper container contents under protection of the WRITER lock.
01511 
01512             containerLockBeginWrite( theContainer );
01513 
01514             if(( BdbCondRInfoContainer::IS_LOADED      == theContainer->getState( )) ||
01515                ( BdbCondRInfoContainer::IS_UNAVAILABLE == theContainer->getState( ))) {
01516                 theContainer->setState( BdbCondRInfoContainer::IS_EMPTY );
01517             }
01518 
01519             containerLockEndWrite( theContainer );
01520         }
01521 
01522     } while( false );
01523 
01524     cacheLockEndRead( _cache );
01525 
01526     return result;
01527 }
01528 
01529 CORBA::Boolean
01530 BdbCondRInfoImpl::getVerboseMode( CORBA_Environment& theEnvironment )
01531 {
01532     const char* infoString = "BdbCondRInfoImpl::getVerboseMode()";
01533 
01534     if( _verbose )
01535         cout << "[ " << BdbTime( ) << " ] " << infoString << " Get current verbose mode: " << _verbose << endl;
01536 
01537   // Return the current mode.
01538 
01539     return _verbose;
01540 }
01541 
01542 CORBA::Boolean
01543 BdbCondRInfoImpl::setVerboseMode( CORBA::Boolean     theVerboseMode,
01544                                   CORBA_Environment& theEnvironment )
01545 {
01546     const char* infoString = "BdbCondRInfoImpl::setVerboseMode()";
01547 
01548     if( _verbose )
01549         cout << "[ " << BdbTime( ) << " ] " << infoString << " Set verbose mode: " << theVerboseMode << endl;
01550 
01551   // Remember the current state. Then set the new one.
01552 
01553     CORBA::Boolean theOldVerboseMode = _verbose;
01554     _verbose = theVerboseMode;
01555 
01556   // Return the old mode.
01557 
01558     return theOldVerboseMode;
01559 }
01560 
01561 void
01562 BdbCondRInfoImpl::shutdownServer( CORBA_Environment& theEnvironment )
01563 {
01564     const char* infoString = "BdbCondRInfoImpl::shutdownServer()";
01565 
01566     if( _verbose )
01567         cout << "[ " << BdbTime( ) << " ] " << infoString << " Shutting the server down..." << endl;
01568 
01569   // Do it.
01570 
01571     TaoServer::shutdownAfterThisCall( 1 );
01572 }
01573 
01574 // -------------
01575 // -- Helpers --
01576 // -------------
01577 
01578 bool
01579 BdbCondRInfoImpl::initialize( )
01580 {
01581     cacheLockBeginRead( _cache );
01582 
01583     if( ! _isInitialized ) {
01584 
01585         cacheLockUpgrade( _cache );
01586 
01587       // Check the status again because the situation could change
01588       // while we were upgrading the lock level.
01589 
01590         if( ! _isInitialized ) {
01591 
01592           // Load the initial cache contents. Use the result of the reloading
01593           // operation as a new state of the object's context.
01594 
01595             _isInitialized = reloadCache( );
01596         }
01597 
01598         cacheLockDowngrade( _cache );
01599     }
01600 
01601     cacheLockEndRead( _cache );
01602 
01603     return _isInitialized;
01604 }
01605 
01606 bool
01607 BdbCondRInfoImpl::reloadCache( bool forceReloadFlag )
01608 {
01609     const char* errorString = "BdbCondRInfoImpl::reloadCache() - ERROR.";
01610 
01611     bool result = true;     // Unless somebody in this method has another opinion.
01612 
01613   // NOTE: We are assuming that the cache has been properly locked for
01614   //       WRITE operations.
01615 
01616     do {
01617 
01618         if( forceReloadFlag || ( ! _cache->isValid( ))) {
01619 
01620           // Clear the contents of the cache object itself.
01621 
01622             _cache->clear( );
01623 
01624           // Load the federation name.
01625           //
01626           // NOTE: We are deleting the old federation description, if the one with
01627           //       similar name already exist.
01628 
01629             BdbCondRInfoFederation* theFederation = new BdbCondRInfoFederation( );
01630             BdbCondRInfoFederation* theOldFederation = _cache->add( BdbConditions::instance( )->bootName( ),
01631                                                                     theFederation );
01632             delete theOldFederation;
01633 
01634           // Load the list of snapshots for the federation.
01635 
01636             BdbCondRInfoSnapshot* theSnapshot = new BdbCondRInfoSnapshot( );
01637             BdbCondRInfoSnapshot* theOldSnapshot = theFederation->add( DEFAULT_SNAPSHOT_NAME,
01638                                                                        theSnapshot );
01639             delete theOldSnapshot;
01640 
01641           // Load a list of detectors.
01642 
01643             vector<string> theListOfDetectors;
01644             if( ! getListOfDetectors( theListOfDetectors )) {
01645 
01646                 cout << "[ " << BdbTime( ) << " ] " << errorString << endl
01647                      << "    Failed to obtain a list of detectors." << endl;
01648 
01649                 result = false;
01650                 break;
01651             }
01652 
01653             string detectorName;
01654             int       numDetectors = theListOfDetectors.size( );
01655 
01656             for( int det = 0; det < numDetectors; det++ ) {
01657 
01658                 detectorName = theListOfDetectors[det];
01659 
01660               // Load a detector into the cache.
01661 
01662                 BdbCondRInfoDetector* theDetector = new BdbCondRInfoDetector( );
01663                 BdbCondRInfoDetector* theOldDetector = theSnapshot->add( detectorName.c_str(),
01664                                                                          theDetector );
01665                 delete theOldDetector;
01666 
01667               // Load a list of origins into the cache.
01668 
01669                 vector<string> theListOfOrigins;
01670                 if( ! getListOfOrigins( detectorName.c_str(), theListOfOrigins )) {
01671 
01672                     cout << "[ " << BdbTime( ) << " ] " << errorString << endl
01673                          << "    Failed to obtain a list of origins." << endl;
01674 
01675                     result = false;
01676                     break;
01677                 }
01678 
01679                 string originName;
01680                 int       numOrigins = theListOfOrigins.size( );
01681 
01682                 for( int ori = 0; ori < numOrigins; ori++ ) {
01683 
01684                     originName = theListOfOrigins[ori];
01685 
01686                   // Load an origin into the cache.
01687 
01688                     BdbCondRInfoOrigin* theOrigin = new BdbCondRInfoOrigin( );
01689                     BdbCondRInfoOrigin* theOldOrigin = theDetector->add( originName.c_str(),
01690                                                                          theOrigin );
01691                     delete theOldOrigin;
01692 
01693                   // Load a list of containers into the cache.
01694 
01695                     vector<string> theListOfContainers;
01696                     if( ! getListOfContainers( detectorName.c_str(), originName.c_str(), theListOfContainers )) {
01697 
01698                         cout << "[ " << BdbTime( ) << " ] " << errorString << endl
01699                              << "    Failed to obtain a list of containers." << endl;
01700 
01701                         result = false;
01702                         break;
01703                     }
01704 
01705                     string containerName;
01706                     int       numContainers = theListOfContainers.size( );
01707 
01708                     for( int con = 0; con < numContainers; con++ ) {
01709 
01710                         containerName = theListOfContainers[con];
01711 
01712                       // Load a container descriptor into the cache.
01713 
01714                         BdbCondRInfoContainer* theContainer = new BdbCondRInfoContainer( );
01715                         BdbCondRInfoContainer* theOldContainer = theOrigin->add( containerName.c_str(),
01716                                                                                  theContainer );
01717                         delete theOldContainer;
01718                     }
01719                 }
01720                 if( ! result ) break;
01721             }
01722             if( ! result ) break;
01723 
01724           // Set the cache as "valid".
01725           //
01726           // NOTE: This only happens in case of successfull completion of
01727           //       the previous code.
01728 
01729             _cache->setValid( true );
01730         }
01731 
01732     } while( false );
01733 
01734     return result;
01735 }
01736 
01737 // --------------------------------------
01738 // -- Lock management helpers (static) --
01739 // --------------------------------------
01740 
01741 void
01742 BdbCondRInfoImpl::cacheLockBeginRead( BdbCondRInfoCache* theCache )
01743 {
01744     const char* fatalErrorString = "BdbCondRInfoImpl::cacheLockBeginRead() - FATAL ERROR.";
01745 
01746 
01747     if( ! theCache->getLock().beginRead( )) {
01748 
01749         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01750              << "    Failed to obtain access to the cache as a READER." << endl;
01751         exit( 1 );
01752     }
01753 }
01754 
01755 void
01756 BdbCondRInfoImpl::cacheLockUpgrade( BdbCondRInfoCache* theCache )
01757 {
01758     const char* fatalErrorString = "BdbCondRInfoImpl::cacheLockUpgrade() - FATAL ERROR.";
01759 
01760     if( ! theCache->getLock().endRead( )) {
01761 
01762         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01763              << "    Failed to release access to the cache as a READER." << endl;
01764         exit( 1 );
01765     }
01766 
01767     if( ! theCache->getLock().beginWrite( )) {
01768 
01769         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01770              << "    Failed to obtain access to the cache as a WRITER." << endl;
01771         exit( 1 );
01772     }
01773 }
01774 
01775 void
01776 BdbCondRInfoImpl::cacheLockDowngrade( BdbCondRInfoCache* theCache )
01777 {
01778     const char* fatalErrorString = "BdbCondRInfoImpl::cacheLockDowngrade() - FATAL ERROR.";
01779 
01780     if( ! theCache->getLock( ).downgrade( )) {
01781 
01782         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01783              << "    Failed to downgrade access to the cache from WRITER to READER level." << endl;
01784         exit( 1 );
01785     }
01786 }
01787 
01788 void
01789 BdbCondRInfoImpl::cacheLockEndRead( BdbCondRInfoCache* theCache )
01790 {
01791     const char* fatalErrorString = "BdbCondRInfoImpl::cacheLockEndRead() - FATAL ERROR.";
01792 
01793     if( ! theCache->getLock().endRead( )) {
01794 
01795         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01796              << "    Failed to release access to the cache as a READER." << endl;
01797         exit( 1 );
01798     }
01799 }
01800 
01801 void
01802 BdbCondRInfoImpl::containerLockBeginRead( BdbCondRInfoContainer* theContainer )
01803 {
01804     const char* fatalErrorString = "BdbCondRInfoImpl::containerLockBeginRead() - FATAL ERROR.";
01805 
01806     if( ! theContainer->getLock( ).beginRead( )) {
01807 
01808         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01809              << "    Failed to obtain access to the container genealogy as a READER." << endl;
01810         exit( 1 );
01811     }
01812 }
01813 
01814 void
01815 BdbCondRInfoImpl::containerLockEndRead( BdbCondRInfoContainer* theContainer )
01816 {
01817     const char* fatalErrorString = "BdbCondRInfoImpl::containerLockEndRead() - FATAL ERROR.";
01818 
01819     if( ! theContainer->getLock( ).endRead( )) {
01820 
01821         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01822              << "    Failed to release access to the container genealogy as a READER." << endl;
01823         exit( 1 );
01824     }
01825 }
01826 
01827 void
01828 BdbCondRInfoImpl::containerLockBeginWrite( BdbCondRInfoContainer* theContainer )
01829 {
01830     const char* fatalErrorString = "BdbCondRInfoImpl::containerLockBeginWrite() - FATAL ERROR.";
01831 
01832     if( ! theContainer->getLock( ).beginWrite( )) {
01833 
01834         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01835              << "    Failed to obtain access to the container genealogy as a WRITER." << endl;
01836         exit( 1 );
01837     }
01838 }
01839 
01840 void
01841 BdbCondRInfoImpl::containerLockEndWrite( BdbCondRInfoContainer* theContainer )
01842 {
01843     const char* fatalErrorString = "BdbCondRInfoImpl::containerLockEndWrite() - FATAL ERROR.";
01844 
01845     if( ! theContainer->getLock( ).endWrite( )) {
01846 
01847         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
01848              << "    Failed to release access to the container genealogy as a WRITER." << endl;
01849         exit( 1 );
01850     }
01851 }
01852 
01853 void
01854 BdbCondRInfoImpl::startProtectedTransaction( )
01855 {
01856   // Make sure that the current thread is the only one who is using
01857   // the Objectivity context for database operations.
01858 
01859     if( 0 != _myCxtPtr ) {
01860 
01861         pthread_mutex_lock( &_myCxtMutex );
01862 
01863         ooInitThread( 0 );
01864         ooContext::setCurrent( _myCxtPtr );
01865     }
01866 
01867   // Then start the transaction in the current context.
01868 
01869     BdbConditions::instance( )->startRead( );
01870 }
01871 
01872 void
01873 BdbCondRInfoImpl::commitProtectedTransaction( )
01874 {
01875   // Commit current transaction in the current context.
01876 
01877     BdbConditions::instance( )->commit( );
01878 
01879   // Release the current context. Now it will be available to any
01880   // other thread willing to perfrom database operations.
01881 
01882     if( 0 != _myCxtPtr ) {
01883 
01884         ooContext::setCurrent( 0 );
01885         ooTermThread( );
01886 
01887         pthread_mutex_unlock( &_myCxtMutex );
01888 
01889     }
01890 }
01891 
01892 bool
01893 BdbCondRInfoImpl::getListOfDetectors( vector<string>& theList )
01894 {
01895     const char* errorString = "BdbCondRInfoImpl::getListOfDetectors() - ERROR.";
01896 
01897   // The list is always cleared even when the operation fails.
01898 
01899     theList.clear( );
01900 
01901   // Dump the list of "Link" database names into a temporary file.
01902   // The name of this file should be unique because the current number of seconds
01903   // is used to build this name.
01904 
01905     char    seconds[11];
01906     BdbTime theCurrentTime;
01907 
01908     printSeconds( theCurrentTime.getGmtSec( ), seconds );
01909 
01910     string fileName = string( "/tmp/oodumpcatalog_" ) + string( seconds ) + string( ".tmp" );
01911     string commandName;
01912 
01913     commandName = string( "oodumpcatalog -notitle | grep \"DB Name\" | grep con_ | grep _Link > " ) + fileName;
01914     if( -1 == system( commandName.c_str() )) {
01915 
01916         cout << "[ " << BdbTime( ) << " ] " << errorString << endl
01917              << "    Failed to execute the command via system() call." << endl
01918              << "        COMMAND: " << commandName << endl
01919              << "        ERRNO:   " << errno << endl;
01920         return false;
01921     }
01922 
01923   // Open the temporary file and to grep its contents
01924   // on order to find out all "xxx"-s from the following database names:
01925   //
01926   //    "con_xxx_Link"
01927 
01928     int databaseNameLength = strlen( "con_xxx_Link" );
01929 
01930     ifstream  tmp( fileName.c_str() );
01931     string theLine;
01932 
01933     while( getline(tmp,theLine),!tmp.eof() ) {
01934 
01935       // Parse the string of the following format:
01936       //
01937       //    "DB Name   = con_xxx_Link"
01938 
01939         Tokenize theTokenizer( theLine );
01940         string    theToken;
01941 
01942         for( int i = 0; i < 4; i++ ) {
01943             if(( theToken = theTokenizer( )).empty( )) {
01944 
01945                 cout << "[ " << BdbTime( ) << " ] " << errorString << endl
01946                      << "    Unexpected format of the input file." << endl
01947                      << "        FILE:  " << fileName << endl
01948                      << "        ERRNO: " << errno << endl;
01949                 return false;
01950             }
01951         }
01952 
01953       // We are interested in last parsed token (which is supposed to be
01954       // a database name) only if it has a proper length.
01955 
01956         if( strlen( theToken.c_str() ) == databaseNameLength ) {
01957             string theDetector = theToken.substr( 4, 3 );   // Take "xxx" into a substring.
01958             theList.push_back( theDetector );
01959         }
01960     }
01961 
01962   // Remove the temporary file from to prevent collecting the garbage.
01963 
01964     commandName = string( "rm " ) + fileName;
01965     if( -1 == system( commandName.c_str() )) {
01966 
01967         cout << "[ " << BdbTime( ) << " ] " << errorString << endl
01968              << "    Failed to execute the command via system() call." << endl
01969              << "        COMMAND: " << commandName << endl
01970              << "        ERRNO:   " << errno << endl;
01971         return false;
01972     }
01973 
01974     return true;
01975 }
01976 
01977 bool
01978 BdbCondRInfoImpl::getListOfOrigins( const char*                     theDetectorName,
01979                                     vector<string>& theList )
01980 {
01981     const char* errorString = "BdbCondRInfoImpl::getListOfOrigins() - ERROR.";
01982 
01983     theList.clear( );
01984 
01985   // +++ TRANSACTION ZONE +++
01986 
01987     startProtectedTransaction( );
01988 
01989   // Execute the request in a exception-like loop to be able to commit
01990   // the open transaction.
01991 
01992     bool result = true;     // At least for now. Until something bad happens.
01993 
01994     do {
01995 
01996       // Get a list of links.
01997 
01998         BdbObsoleteDatabase                   theDb( theDetectorName );
01999         vector<string> theListOfLinks;
02000 
02001         if( BdbcSuccess != theDb.listAllClasses( theListOfLinks )) {
02002 
02003             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
02004                  << "    Failed to get a list of all container links for specified detector." << endl
02005                  << "        Detector: " << theDetectorName << endl;
02006 
02007             result = false;
02008             break;
02009         }
02010 
02011       // Get the origin name for every found link and register it in the output
02012       // vector if required.
02013       //
02014       // NOTE: We are using here a very trivial algorithm since we don't expect
02015       //       more origins then just a few of them. As a result we can't benefit
02016       //       from using hash dictionaries.
02017 
02018         BdbCondContainerLink theLink;
02019 
02020         string theLinkName;
02021         string theOriginName;
02022 
02023         int numLinks = theListOfLinks.size( );
02024 
02025         for( int link = 0; link < numLinks; link++ ) {
02026 
02027             theLinkName = theListOfLinks[link];
02028 
02029             if(( BdbcSuccess != theDb.findContainerLink( theLink, theLinkName.c_str() )) ||
02030                ( ! theLink.isValid( ))) {
02031 
02032                 cout << "[ " << BdbTime( ) << " ] " << errorString << endl
02033                      << "    Failed to get a symbolic link for a container." << endl
02034                      << "        Detector:  " << theDetectorName << endl
02035                      << "        Container: " << theLinkName << endl;
02036 
02037                 result = false;
02038                 break;
02039             }
02040 
02041           // Check if the origin is already in the output list.
02042 
02043             theOriginName = theLink.getOrigin( );
02044 
02045             bool wasFound   = false;
02046             int  numOrigins = theList.size( );
02047 
02048             for( int origin = 0; origin < numOrigins; origin++ ) {
02049                 if( 0 == strcmp( theList[origin].c_str(), theOriginName.c_str() )) {
02050                     wasFound = true;
02051                     break;
02052                 }
02053             }
02054             if( ! wasFound ) {
02055                 theList.push_back( theOriginName );
02056             }
02057         }
02058 
02059     } while( false );
02060 
02061     commitProtectedTransaction( );
02062 
02063   // --- TRANSACTION ZONE ---
02064 
02065     return result;
02066 }
02067 
02068 bool
02069 BdbCondRInfoImpl::getListOfContainers( const char*                     theDetectorName,
02070                                        const char*                     theOriginName,
02071                                        vector<string>& theList )
02072 {
02073     const char* errorString = "BdbCondRInfoImpl::getListOfContainers() - ERROR.";
02074 
02075 
02076   // The list is always cleared even when the operation fails.
02077 
02078     theList.clear( );
02079 
02080   // +++ TRANSACTION ZONE +++
02081 
02082     startProtectedTransaction( );
02083 
02084   // Execute the request in a exception-like loop to be able to commit
02085   // the open transaction.
02086 
02087     bool result = true;     // At least for now. Until something bad happens.
02088 
02089     do {
02090 
02091       // Get a list of links.
02092 
02093         BdbObsoleteDatabase                   theDb( theDetectorName );
02094         vector<string> theListOfLinks;
02095 
02096         if( BdbcSuccess != theDb.listAllClasses( theListOfLinks )) {
02097 
02098             cout << "[ " << BdbTime( ) << " ] " << errorString << endl
02099                  << "    Failed to get a list of all container links for specified detector." << endl
02100                  << "        Detector: " << theDetectorName << endl;
02101 
02102             result = false;
02103             break;
02104         }
02105 
02106       // Include into the containers which have required origin.
02107 
02108         BdbCondContainerLink theLink;
02109 
02110         string theLinkName;
02111 
02112         int numLinks = theListOfLinks.size( );
02113 
02114         for( int link = 0; link < numLinks; link++ ) {
02115 
02116             theLinkName = theListOfLinks[link];
02117 
02118             if(( BdbcSuccess != theDb.findContainerLink( theLink, theLinkName.c_str() )) ||
02119                ( ! theLink.isValid( ))) {
02120 
02121                 cout << "[ " << BdbTime( ) << " ] " << errorString << endl
02122                      << "    Failed to get a symbolic link for a container." << endl
02123                      << "        Detector:  " << theDetectorName << endl
02124                      << "        Container: " << theLinkName << endl;
02125 
02126                 result = false;
02127                 break;
02128             }
02129 
02130           // Check if the link has required origin.
02131 
02132             if( 0 == strcmp( theOriginName, theLink.getOrigin( ).c_str())) {
02133                 theList.push_back( theLinkName );
02134             }
02135         }
02136 
02137     } while( false );
02138 
02139     commitProtectedTransaction( );
02140 
02141   // --- TRANSACTION ZONE ---
02142 
02143     return result;
02144 }
02145 
02146 void
02147 BdbCondRInfoImpl::bload( )
02148 {
02149     const char* infoString = "BdbCondRInfoImpl::bload()";
02150 
02151     if( _verbose )
02152         cout << "[ " << BdbTime( ) << " ] " << infoString << " Background loading of the cache was requested." << endl;
02153 
02154     if( ! initialize( )) return;
02155 
02156   // Find the next candidate container for the loading.
02157   //
02158   // IMPORTANT: If the subsequent operation succeeds then both the READER lock for
02159   //            the cache itself and the WRITER lock for the found container will be
02160   //            inherited from the called method.
02161 
02162     string theFederationName;
02163     string theSnapshotName;
02164     string theDetectorName;
02165     string theOriginName;
02166     string theContainerName;
02167 
02168     BdbCondRInfoContainer* theContainer = bloadNextWriteLockedContainer( theFederationName,
02169                                                                          theSnapshotName,
02170                                                                          theDetectorName,
02171                                                                          theOriginName,
02172                                                                          theContainerName );
02173     if( 0 != theContainer ) {
02174 
02175       // Directly call the loader to load the container (assuming that the new state of
02176       // the container has already been set by this procedure).
02177 
02178         BdbCondRInfoJob* theJobPtr = new BdbCondRInfoJob( theContainer,
02179                                                           theFederationName,
02180                                                           theSnapshotName,
02181                                                           theDetectorName,
02182                                                           theOriginName,
02183                                                           theContainerName );
02184 
02185         _bloadLoader->load( theJobPtr );
02186 
02187         delete theJobPtr;
02188 
02189       // Release locks captured when the container was found.
02190 
02191         containerLockEndWrite( theContainer );
02192         cacheLockEndRead( _cache );
02193     }
02194 }
02195 
02196 BdbCondRInfoContainer*
02197 BdbCondRInfoImpl::bloadNextWriteLockedContainer( string& theFederationName,
02198                                                  string& theSnapshotName,
02199                                                  string& theDetectorName,
02200                                                  string& theOriginName,
02201                                                  string& theContainerName )
02202 {
02203     const char* fatalErrorString = "BdbCondRInfoImpl::bloadNextWriteLockedContainer() - FATAL ERROR.";
02204 
02205     BdbCondRInfoFederation* theFederation;
02206     BdbCondRInfoSnapshot*   theSnapshot;
02207     BdbCondRInfoDetector*   theDetector;
02208     BdbCondRInfoOrigin*     theOrigin;
02209     BdbCondRInfoContainer*  theContainer;
02210 
02211     cacheLockBeginRead( _cache );
02212 
02213     do {
02214 
02215       // Search a proper container in the cache.
02216 
02217         vector<string> theListOfFederations;
02218         _cache->keys( theListOfFederations );
02219 
02220         int numFederations = theListOfFederations.size( );
02221         for( int fed = 0; fed < numFederations; fed++ ) {
02222 
02223             theFederationName = theListOfFederations[fed];
02224 
02225             if( 0 == ( theFederation = _cache->find( theFederationName.c_str() ))) {
02226 
02227                 cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
02228                      << "    The cache element was not found. The cache is inconsistent." << endl
02229                      << "        FEDERATION: " << theFederationName << endl;
02230                 exit( 1 );
02231             }
02232 
02233             vector<string> theListOfSnapshots;
02234             theFederation->keys( theListOfSnapshots );
02235 
02236             int numSnapshots = theListOfSnapshots.size( );
02237             for( int sna = 0; sna < numSnapshots; sna++ ) {
02238 
02239                 theSnapshotName = theListOfSnapshots[sna];
02240 
02241                 if( 0 == ( theSnapshot = theFederation->find( theSnapshotName.c_str() ))) {
02242 
02243                     cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
02244                          << "    The cache element was not found. The cache is inconsistent." << endl
02245                          << "        FEDERATION: " << theFederationName << endl
02246                          << "        SNAPSHOT:   " << theSnapshotName << endl;
02247                     exit( 1 );
02248                 }
02249 
02250                 vector<string> theListOfDetectors;
02251                 theSnapshot->keys( theListOfDetectors );
02252 
02253                 int numDetectors = theListOfDetectors.size( );
02254                 for( int det = 0; det < numDetectors; det++ ) {
02255 
02256                     theDetectorName = theListOfDetectors[det];
02257 
02258                     if( 0 == ( theDetector = theSnapshot->find( theDetectorName.c_str() ))) {
02259 
02260                         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
02261                              << "    The cache element was not found. The cache is inconsistent." << endl
02262                              << "        FEDERATION: " << theFederationName << endl
02263                              << "        SNAPSHOT:   " << theSnapshotName << endl
02264                              << "        DETECTOR:   " << theDetectorName << endl;
02265                         exit( 1 );
02266                     }
02267 
02268                     vector<string> theListOfOrigins;
02269                     theDetector->keys( theListOfOrigins );
02270 
02271                     int numOrigins = theListOfOrigins.size( );
02272                     for( int ori = 0; ori < numOrigins; ori++ ) {
02273 
02274                         theOriginName = theListOfOrigins[ori];
02275 
02276                         if( 0 == ( theOrigin = theDetector->find( theOriginName.c_str() ))) {
02277 
02278                             cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
02279                                  << "    The cache element was not found. The cache is inconsistent." << endl
02280                                  << "        FEDERATION: " << theFederationName << endl
02281                                  << "        SNAPSHOT:   " << theSnapshotName << endl
02282                                  << "        DETECTOR:   " << theDetectorName << endl
02283                                  << "        ORIGIN:     " << theOriginName << endl;
02284                             exit( 1 );
02285                         }
02286 
02287                         vector<string> theListOfContainers;
02288                         theOrigin->keys( theListOfContainers );
02289 
02290                         int numContainers = theListOfContainers.size( );
02291                         for( int con = 0; con < numContainers; con++ ) {
02292 
02293                             theContainerName = theListOfContainers[con];
02294 
02295                             if( 0 == ( theContainer = theOrigin->find( theContainerName.c_str() ))) {
02296 
02297                                 cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
02298                                      << "    The cache element was not found. The cache is inconsistent." << endl
02299                                      << "        FEDERATION: " << theFederationName << endl
02300                                      << "        SNAPSHOT:   " << theSnapshotName << endl
02301                                      << "        DETECTOR:   " << theDetectorName << endl
02302                                      << "        ORIGIN:     " << theOriginName << endl
02303                                      << "        CONTAINER:  " << theContainerName << endl;
02304                                 exit( 1 );
02305                             }
02306 
02307                             if( BdbCondRInfoContainer::IS_EMPTY == theContainer->getState( )) {
02308                                 
02309                                 containerLockBeginWrite( theContainer );
02310 
02311                               // Check the status again because the candidate container may change
02312                               // their state whuile we were gaining the proper lock.
02313 
02314                                 if( BdbCondRInfoContainer::IS_EMPTY == theContainer->getState( )) {
02315 
02316                                   // NOTE: This will return the WRITER locked container in the READER locked cache.
02317                                   // It's up to the caller to release this locks in a proper way.
02318 
02319                                     return theContainer;
02320                                 }
02321 
02322                                 containerLockEndWrite( theContainer );
02323                             }
02324                         }
02325                     }
02326                 }
02327             }
02328         }
02329 
02330     } while( false );
02331 
02332     cacheLockEndRead( _cache );
02333 
02334     return 0;
02335 }
02336 
02337 void
02338 BdbCondRInfoImpl::startBloadThread( )
02339 {
02340     const char* infoString       = "BdbCondRInfoImpl::startBloadThread()";
02341     const char* fatalErrorString = "BdbCondRInfoImpl::startBloadThread() - FATAL ERROR.";
02342 
02343   // Try running the thread.
02344   // Pass the pointer to the current object as a parameter.
02345 
02346     if( 0 != pthread_create( &_bloadThread, 0, bloadMgr, this )) {
02347 
02348         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
02349              << "    Failed to create a new thread."<< endl;
02350         exit( 1 );
02351     }
02352 
02353     if( _verbose )
02354         cout << "[ " << BdbTime( ) << " ] " << infoString << " Background loading thread started."<< endl;
02355 }
02356 
02357 void
02358 BdbCondRInfoImpl::stopBloadThread( )
02359 {
02360     const char* infoString       = "BdbCondRInfoImpl::stopBloadThread()";
02361     const char* fatalErrorString = "BdbCondRInfoImpl::stopBloadThread() - FATAL ERROR.";
02362 
02363   // Stop the thread if there are no clients in the table.
02364 
02365     if( 0 != pthread_cancel( _bloadThread )) {
02366 
02367         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
02368              << "    Failed to cancel existing thread."<< endl;
02369         exit( 1 );
02370     }
02371 
02372     if( _verbose )
02373         cout << "[ " << BdbTime( ) << " ] " << infoString << " Background loading thread stopped."<< endl;
02374 }
02375 
02376 // --------------------
02377 // -- Static methods --
02378 // --------------------
02379 
02380 void*
02381 BdbCondRInfoImpl::bloadMgr( void* arg )
02382 {
02383     const char* fatalErrorString = "BdbCondRInfoImpl::bloadMgr() - FATAL ERROR.";
02384 
02385     BdbCondRInfoImpl* myClientPtr = (BdbCondRInfoImpl*) arg;
02386     if( 0 == myClientPtr ) {
02387 
02388         cout << "[ " << BdbTime( ) << " ] " << fatalErrorString << endl
02389              << "    A null client pointer was passed to the Background Loader thread." << endl;
02390         exit( 1 );
02391     }
02392 
02393   // Activate the client's loading procedure on a periodic basics.
02394 
02395     while( true ) {
02396         sleep( BLOAD_PERIOD );
02397         myClientPtr->bload( );
02398     }
02399 
02400     return 0;
02401 }
02402 
02403 void
02404 BdbCondRInfoImpl::printSeconds( d_ULong sec,
02405                                 char*   str )
02406 {
02407     if( BdbTimeConst::minusInfinity == sec ) {
02408         strcpy( str, "-Infinity-" );
02409     } else if( BdbTimeConst::plusInfinity == sec ) {
02410         strcpy( str, "+Infinity+" );
02411     } else {
02412         sprintf( str, "%10.10u", (unsigned int) sec );
02413     }
02414 }
02415 
02416 /////////////////
02417 // End Of File //
02418 /////////////////

 


BaBar Public Site | SLAC | News | Links | Who's Who | Contact Us

Page Owner: Jacek Becla
Last Update: October 04, 2002