![]() |
|
|
Bdb packages | Design docs | Source docs | Guidelines | Recent releases |
|
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