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

CdbBdb2RooConversionTool.cc

Go to the documentation of this file.
00001 // A conversion tool to convert the contents of an Objectivity/DD base
00002 // CDB installation into the ROOT I/O based one.
00003 
00004 #include "BaBar/BaBar.hh"
00005 #include "BdbUtil/Bdb.hh"
00006 
00007 #include "CdbBase/CdbPathName.hh"
00008 #include "CdbBase/CdbTimeUtils.hh"
00009 #include "CdbBase/CdbTransaction.hh"
00010 
00011 #include "CdbBdbShared/CdbBdbShared.hh"
00012 #include "CdbBdbShared/CdbBdbSRegistryP.hh"
00013 #include "CdbBdbShared/CdbBdbSOriginCollectionP.hh"
00014 #include "CdbBdbShared/CdbBdbSOriginP.hh"
00015 #include "CdbBdbShared/CdbBdbSConditionCollectionP.hh"
00016 #include "CdbBdbShared/CdbBdbSConditionP.hh"
00017 #include "CdbBdbShared/CdbBdbSViewCollectionP.hh"
00018 #include "CdbBdbShared/CdbBdbSViewP.hh"
00019 #include "CdbBdbShared/CdbBdbSConfigCollectionP.hh"
00020 #include "CdbBdbShared/CdbBdbSConfigInterval.hh"
00021 #include "CdbBdbShared/CdbBdbSClusterCollectionP.hh"
00022 #include "CdbBdbShared/CdbBdbSClusterP.hh"
00023 #include "CdbBdbShared/CdbBdbSSimpleClusterP.hh"
00024 #include "CdbBdbShared/CdbBdbSIncrement.hh"
00025 #include "CdbBdbShared/CdbBdbSPartitionsLayoutP.hh"
00026 #include "CdbBdbShared/CdbBdbSPartitionP.hh"
00027 #include "CdbBdbShared/CdbBdbSMetaDataP.hh"
00028 #include "CdbBdbShared/CdbBdbSUtils.hh"
00029 #include "CdbBdbShared/CdbBdbSOiCollectionP.hh"
00030 #include "CdbBdbShared/CdbBdbSRevisionP.hh"
00031 #include "CdbBdbShared/CdbBdbSViCollectionP.hh"
00032 
00033 #include "CdbRooReadonly/CdbRooRoFileUtils.hh"
00034 #include "CdbRooReadonly/CdbRooRoIdR.hh"
00035 #include "CdbRooReadonly/CdbRooRoRegistryDescriptorR.hh"
00036 #include "CdbRooReadonly/CdbRooRoConditionCollectionR.hh"
00037 #include "CdbRooReadonly/CdbRooRoConditionR.hh"
00038 #include "CdbRooReadonly/CdbRooRoViewCollectionR.hh"
00039 #include "CdbRooReadonly/CdbRooRoViewR.hh"
00040 #include "CdbRooReadonly/CdbRooRoConfigCollectionR.hh"
00041 #include "CdbRooReadonly/CdbRooRoConfigElementR.hh"
00042 #include "CdbRooReadonly/CdbRooRoConfigInterval.hh"
00043 #include "CdbRooReadonly/CdbRooRoRClusterCollectionR.hh"
00044 #include "CdbRooReadonly/CdbRooRoRClusterR.hh"
00045 #include "CdbRooReadonly/CdbRooRoIncrementR.hh"
00046 #include "CdbRooReadonly/CdbRooRoOriginCollectionR.hh"
00047 #include "CdbRooReadonly/CdbRooRoOriginR.hh"
00048 #include "CdbRooReadonly/CdbRooRoClusterCollectionR.hh"
00049 #include "CdbRooReadonly/CdbRooRoClusterR.hh"
00050 #include "CdbRooReadonly/CdbRooRoPartitionsLayoutR.hh"
00051 #include "CdbRooReadonly/CdbRooRoPartitionR.hh"
00052 #include "CdbRooReadonly/CdbRooRoOiCollectionR.hh"
00053 #include "CdbRooReadonly/CdbRooRoRevisionR.hh"
00054 #include "CdbRooReadonly/CdbRooRoRevCollectionR.hh"
00055 #include "CdbRooReadonly/CdbRooRoMetaDataR.hh"
00056 #include "CdbRooReadonly/CdbRooRoViCollectionR.hh"
00057 #include "CdbRooReadonly/CdbRooRoBootRecordR.hh"
00058 
00059 #include <TFile.h>
00060 #include <TTree.h>
00061 #include <TDirectory.h>
00062 
00063 #include <iostream>
00064 #include <fstream>
00065 #include <string>
00066 using std::cin;
00067 using std::cout;
00068 using std::cerr;
00069 using std::endl;
00070 #include <sstream>
00071 using std::ostringstream;
00072 
00073 namespace {
00074 
00075     bool verboseModeFlag          = false;
00076     bool excludeRegularFlag       = false;
00077     bool excludePartitionableFlag = false;
00078     bool doNotCompressFlag        = false;
00079 
00080     enum ClusteringMode {
00081         CLUSTERING_MODE_STANDARD,
00082         CLUSTERING_MODE_ALLIN3,
00083         CLUSTERING_MODE_1PLUS2PERORIGIN
00084     } clusteringMode = CLUSTERING_MODE_STANDARD;
00085 
00086   // Helper functions forming database names depending on a selected clustering option
00087   // They'll also register an entry in a special map to be saved in a boot file.
00088   //
00089   // We also have the cache and teh opening helper and open the corresponding databases.
00090   //
00091   // IMPORTANT: The same databases should be open just once! Otherwise objects may get
00092   //            lost! In other words, for the same file "file.root" there shouldn't be
00093   //            two (or more) simultaneous file opening operations:
00094   //
00095   //              TFile f("file.root")
00096   //
00097   //            within an application. Thsi problem is solved by mean of caching
00098   //            open files in the special cache: database2fileMap and using and polutating
00099   //            the cache as needed. See below.
00100 
00101     std::map<std::string,std::string> database2LocationMap;
00102 
00103     std::map<std::string, CdbCPtr<TFile> > database2fileMap;
00104 
00105     CdbCPtr<TFile>
00106     openDatabase( const std::string& theDatabaseLocation )
00107     {
00108       // Check if we have the database in the cache. If so then return the cached value.
00109       // We're also doing "Cd" into the top-level directory of the file.
00110 
00111         std::map<std::string, CdbCPtr<TFile> >::const_iterator itr = database2fileMap.find( theDatabaseLocation );
00112         if( itr != database2fileMap.end( )) {
00113             itr->second->Cd( "" );
00114             gDirectory->Cd( itr->second->GetPath( ));
00115             return itr->second;
00116         }
00117 
00118       // Try to open the database, and if we succeed - then populate the cache.
00119 
00120         int compressionLevel = 1;                       // "..minimal compression level but fast.."
00121         if( doNotCompressFlag ) compressionLevel = 0;   // "..objects written to this file will not be compressed.."
00122 
00123         CdbCPtr<TFile> databasePtr = new TFile( theDatabaseLocation.c_str( ),
00124                                                 "recreate",
00125                                                 "CDB file",
00126                                                 compressionLevel );
00127         if( databasePtr->IsZombie( )) {
00128             cerr << "error: failed to (re-)create the database: '" << theDatabaseLocation << "'." << endl;
00129             return false;
00130         }
00131         database2fileMap[theDatabaseLocation] = databasePtr;
00132 
00133       // "Cd" into the database before returning it to a caller.
00134 
00135         databasePtr->Cd( "" );
00136         gDirectory->Cd( databasePtr->GetPath( ));
00137 
00138         return databasePtr;
00139     }
00140 
00141     CdbCPtr<TFile>
00142     openRegistryDatabase( const unsigned short theOriginId )
00143     {
00144       // Build a 'system' name of the database
00145 
00146         std::string systemName = "";
00147         {
00148             ostringstream s;
00149             s << "cdb_o" << theOriginId << "_registry.root";
00150             systemName = s.str( );
00151         }
00152 
00153       // Build a 'location' name according to the current clustering mode
00154 
00155         std::string locationName = "";
00156         {
00157             ostringstream s;
00158 
00159             switch( clusteringMode ) {
00160 
00161             case CLUSTERING_MODE_STANDARD:
00162 
00163                 s << systemName;
00164                 break;
00165 
00166             case CLUSTERING_MODE_ALLIN3:
00167 
00168                 s << "cdb_metadata.root";
00169                 break;
00170 
00171             case CLUSTERING_MODE_1PLUS2PERORIGIN:
00172 
00173                 s << "cdb_o" << theOriginId << "_metadata.root";
00174                 break;
00175 
00176             default:
00177                 assert( 0 );
00178                 return 0;
00179             }
00180             locationName = s.str( );
00181         }
00182 
00183       // Register a pair of names in the map
00184 
00185         database2LocationMap[systemName] = locationName;
00186 
00187       // Propagate the operation down to open/create the database (now we're going to populate/use
00188       // the cache). Any errors (if any) should already be reported by the called function, therefore
00189       // we just return the error status.
00190 
00191         return openDatabase( locationName );
00192     }
00193 
00194     CdbCPtr<TFile>
00195     openMetadataDatabase( const unsigned short theOriginId,
00196                           const unsigned short theClusterId,
00197                           const unsigned short thePartitionId,
00198                           const unsigned short theIncrementId,
00199                           const bool           isPartitionableFlag )
00200     {
00201       // Build a 'system' name of both metadata and objects databases
00202 
00203         std::string metadataSystemName = "";
00204         std::string objectsSystemName  = "";
00205         {
00206             ostringstream s;
00207             s << "cdb_o" << theOriginId << "_c" << theClusterId;
00208             if( isPartitionableFlag ) s << "_p" << thePartitionId;
00209             s << "_i" << theIncrementId;
00210             metadataSystemName =  s.str( );
00211             metadataSystemName += ".root";
00212             objectsSystemName  =  s.str( );
00213             objectsSystemName  += "_objects.root";
00214         }
00215 
00216       // Build 'location' names for both databases according to the current clustering mode
00217 
00218         std::string metadataLocation = "";
00219         std::string objectsLocation  = "";
00220         {
00221             ostringstream metadataStream;
00222             ostringstream objectsStream;
00223 
00224             switch( clusteringMode ) {
00225 
00226             case CLUSTERING_MODE_STANDARD:
00227 
00228                 metadataStream << metadataSystemName;
00229                 objectsStream  << objectsSystemName;
00230 
00231                 break;
00232 
00233             case CLUSTERING_MODE_ALLIN3:
00234 
00235                 metadataStream << "cdb_metadata.root";
00236                 objectsStream  << "cdb_objects.root";
00237 
00238                 break;
00239 
00240             case CLUSTERING_MODE_1PLUS2PERORIGIN:
00241 
00242                 metadataStream << "cdb_o" << theOriginId << "_metadata.root";
00243                 objectsStream  << "cdb_o" << theOriginId << "_objects.root";
00244 
00245                 break;
00246 
00247             default:
00248                 assert( 0 );
00249                 return 0;
00250             }
00251             metadataLocation = metadataStream.str( );
00252             objectsLocation  = objectsStream.str( );
00253         }
00254 
00255       // Register both databases in the map
00256 
00257         database2LocationMap[metadataSystemName] = metadataLocation;
00258         database2LocationMap[objectsSystemName]  = objectsLocation;
00259 
00260       // Propagate the operation down to open/create the database (now we're going to populate/use
00261       // the cache). Any errors (if any) should already be reported by the called function, therefore
00262       // we just return the error status.
00263 
00264         return openDatabase( metadataLocation );
00265     }
00266 
00267   // Operations
00268 
00269     CdbStatus convertConfigCollection( CdbRooRoConfigCollectionR*&             theOutputConfigPtr,
00270                                        const BdbRef(CdbBdbSConfigCollectionP)& theInputConfigCollectionRef );
00271 
00272     CdbStatus convertFoldersAndConditions( CdbRooRoViewR&                     theOutView,
00273                                            const BdbHandle(CdbBdbSFolderP)&   theInFolderH,
00274                                            const CdbPathName&                 theCurrentPathName );
00275 
00276     CdbStatus convertPhysicalConditions( const CdbCPtr<TFile>&              theFilePtr,
00277                                          const BdbHandle(CdbBdbSRegistryP)& theMasterRegistryH,
00278                                          const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
00279                                          const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor );
00280 
00281     CdbStatus convertViews( const CdbCPtr<TFile>&              theFilePtr,
00282                             const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
00283                             const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor );
00284 
00285     CdbStatus convertRegularClusters( const CdbCPtr<TFile>&              theFilePtr,
00286                                       const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
00287                                       const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor );
00288 
00289     CdbStatus convertPartitionsLayout( const CdbCPtr<TFile>&              theFilePtr,
00290                                        const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
00291                                        const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor );
00292 
00293     CdbStatus convertOrigins( const CdbCPtr<TFile>&              theFilePtr,
00294                               const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
00295                               const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor );
00296 
00297     CdbStatus convertPartitionableClusters( const CdbCPtr<TFile>&              theFilePtr,
00298                                             const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
00299                                             const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor );
00300 
00301     CdbStatus testMetaDataConversion( );
00302 
00303     CdbStatus convertMetaDataOfRegularCondition( const BdbHandle(CdbBdbSConditionP)& theConditionH,
00304                                                  const BdbHandle(CdbBdbSRegistryP)&  theMasterRegistryH,
00305                                                  d_UShort                            theOwnerOriginId,
00306                                                  const CdbRooRoRegistryDescriptorR&  theOutRegistryDescriptor );
00307 
00308     CdbStatus convertMetaDataOfPartitionableCondition( const BdbHandle(CdbBdbSConditionP)& theConditionH,
00309                                                        const BdbHandle(CdbBdbSRegistryP)&  theMasterRegistryH,
00310                                                        const CdbRooRoRegistryDescriptorR&  theOutRegistryDescriptor );
00311 
00312     CdbStatus convertMetaData( const CdbCPtr<TFile>&              theFilePtr,
00313                                const BdbHandle(CdbBdbSMetaDataP)& theInMetaDataH,
00314                                UShort_t                           theOriginId,
00315                                UShort_t                           theConditionId,
00316                                UShort_t                           theClusterId,
00317                                bool                               isPartitionableFlag,
00318                                UShort_t                           thePartitionId,
00319                                UShort_t                           theIncrementId,
00320                                const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor );
00321 
00322     CdbStatus translateOriginalCollection( CdbRooRoOiCollectionR&                 theOutCollection,
00323                                            const BdbHandle(CdbBdbSOiCollectionP)& theInCollectionH,
00324                                            UShort_t                               theOriginId,
00325                                            UShort_t                               theConditionId,
00326                                            UShort_t                               theClusterId,
00327                                            bool                                   isPartitionableFlag,
00328                                            UShort_t                               thePartitionId,
00329                                            UShort_t                               theIncrementId );
00330 
00331     CdbStatus translateRevision( CdbRooRoRevisionR&                 theOutRevision,
00332                                  const BdbHandle(CdbBdbSRevisionP)& theInRevisionH );
00333 
00334     CdbStatus printPersistentClasses( );
00335 
00336     CdbStatus printPersistentConditions( );
00337 
00338     void usage( )
00339     {
00340         cout << "Usage: <command> [<options>]\n"
00341             << "  help\n"
00342             << "  conversion [<options>] [-clustering { STANDARD | ALLIN3 | 1PLUS2PERORIGIN }] [-do_not_compress]\n"
00343             << "  testing    [<options>]\n"
00344             << "  classes    [<options>]\n"
00345             << "  conditions [<options>]\n"
00346             << "Options common for all commands:\n"
00347             << "  [-noregular] [-nopartitionable] [-verbose]" << endl;
00348     }
00349 }
00350 
00351 int
00352 main( int argc, char* argv[] )
00353 {
00354   // Get the command name
00355 
00356     enum CommandType {
00357         CMD_CONVERSION = 0,
00358         CMD_TESTING,
00359         CMD_CLASSES,
00360         CMD_CONDITIONS
00361     };
00362     CommandType command = CMD_CONVERSION;
00363 
00364     int numArgs = argc - 1;
00365     int nextArg = 1;
00366 
00367     if( 0 == numArgs ) {
00368         usage( );
00369         return 1;
00370     }
00371     if( numArgs > 0 ) {
00372 
00373         const std::string commandName = argv[nextArg];
00374 
00375         if( commandName == "help" ) {
00376 
00377             usage( );
00378 
00379             return 1;
00380 
00381         } else if( commandName == "conversion" ) {
00382 
00383             command = CMD_CONVERSION;
00384 
00385             numArgs--;
00386             nextArg++;
00387 
00388             if( numArgs >= 2 ) {
00389                 const std::string option = argv[nextArg];
00390                 if( option == "-clustering" ) {
00391                     const std::string value = argv[nextArg+1];
00392                     if     ( value == "STANDARD"        ) clusteringMode = CLUSTERING_MODE_STANDARD;
00393                     else if( value == "ALLIN3"          ) clusteringMode = CLUSTERING_MODE_ALLIN3;
00394                     else if( value == "1PLUS2PERORIGIN" ) clusteringMode = CLUSTERING_MODE_1PLUS2PERORIGIN;
00395                     else {
00396                         cerr << "error: unrecognized value '" << value << "' of the option '" << option << "'." << endl;
00397                         usage( );
00398                         return 1;
00399                     }
00400                     numArgs -= 2;
00401                     nextArg += 2;
00402                 } else {
00403                     cerr << "error: unrecognized option '" << option << "'." << endl;
00404                     usage( );
00405                     return 1;
00406                 }
00407             }
00408             if( numArgs >= 1 ) {
00409                 const std::string option = argv[nextArg];
00410                 if( option == "-do_not_compress" ) {
00411                     doNotCompressFlag = true;
00412                     numArgs -= 1;
00413                     nextArg += 1;
00414                 }
00415             }
00416 
00417         } else if( commandName == "testing" ) {
00418 
00419             command = CMD_TESTING;
00420 
00421             numArgs--;
00422             nextArg++;
00423 
00424         } else if( commandName == "classes" ) {
00425 
00426             command = CMD_CLASSES;
00427 
00428             numArgs--;
00429             nextArg++;
00430 
00431         } else if( commandName == "conditions" ) {
00432 
00433             command = CMD_CONDITIONS;
00434 
00435             numArgs--;
00436             nextArg++;
00437 
00438         } else {
00439 
00440             cerr << "unknown command: \"" << commandName << "\"." << endl;
00441             usage( );
00442             return 1;
00443         }
00444     }
00445     if( numArgs > 0 ) {
00446         if( argv[nextArg] == std::string( "-noregular" )) {
00447 
00448             excludeRegularFlag = true;
00449 
00450             numArgs --;
00451             nextArg ++;
00452         }
00453     }
00454     if( numArgs > 0 ) {
00455         if( argv[nextArg] == std::string( "-nopartitionable" )) {
00456 
00457             excludePartitionableFlag = true;
00458 
00459             numArgs --;
00460             nextArg ++;
00461         }
00462     }
00463     if( numArgs > 0 ) {
00464         if( std::string( "-verbose" ) == argv[nextArg] ) {
00465 
00466             verboseModeFlag = true;
00467 
00468             numArgs --;
00469             nextArg ++;
00470 
00471         } else {
00472             cerr << "unknown command option or parameter: \"" << argv[nextArg] << "\"." << endl;
00473             usage( );
00474             return 1;
00475         }
00476     }
00477 
00478    // Initialize Ojectivity/DB base CDB API context
00479 
00480     CdbBdbShared::forceLoad( );
00481 
00482     CdbTransaction readOnlyTransaction( CdbBdbShared::technology( ),
00483                                         CdbBdbShared::implementation( ));
00484 
00485  // Proceed directly to the simple tests if required.
00486 
00487     switch( command ) {
00488     case CMD_TESTING   : return ( CdbStatus::Success == ::testMetaDataConversion   ( ) ? 0 : 1 );
00489     case CMD_CLASSES   : return ( CdbStatus::Success == ::printPersistentClasses   ( ) ? 0 : 1 );
00490     case CMD_CONDITIONS: return ( CdbStatus::Success == ::printPersistentConditions( ) ? 0 : 1 );
00491     default:
00492         break;
00493     }
00494 
00495   // Get the MASTER registry and the collection of origins, which we'll
00496   // be using for a few things below.
00497 
00498     BdbHandle(CdbBdbSRegistryP) masterRegistryH;
00499     CdbStatus result = CdbBdbSRegistryP::findMaster( masterRegistryH );
00500     if( CdbStatus::Success != result ) {
00501         cerr << "failed to find the MASTER registry." << endl;
00502         return 1;
00503     }
00504     assert( masterRegistryH->isMaster( ));
00505 
00506     BdbHandle(CdbBdbSOriginCollectionP) originCollectionH = masterRegistryH->originCollection( );
00507     assert( !BdbIsNull(originCollectionH));
00508 
00509   // Iterate over known registries and convert them one-by-one if the corresponding origins
00510   // are instantiated in the input database.
00511 
00512     CdbBdbSOriginCollectionP::IteratorOfIdentifiers itr = originCollectionH->iterator_identifiers( );
00513     while( itr.next( )) {
00514 
00515       // Get the persistent registry object
00516 
00517         d_UShort originId = itr.value( );
00518 
00519 //cout << "CdbBdb2RooConversionTool::main() - DEBUG" << endl;
00520 //if( 0 != originId ) break;
00521 
00522         BdbHandle(CdbBdbSOriginP) originH;
00523         {
00524             BdbRef(CdbBdbSOriginP) originRef;
00525             if( CdbStatus::Success != originCollectionH->find( originId,
00526                                                                originRef )) {
00527 
00528                 cerr << "failed to find an origin with ID = " << originId << "." << endl
00529                      << "The input database may not be properly initialized." << endl;
00530                 return 1;
00531             }
00532             originH = originRef;
00533         }
00534 
00535       // Try to get the corresponding registry. If it doesn't exist (not instantiated) then we
00536       // will _NOT_ create the output data structures for that registry.
00537 
00538         BdbHandle(CdbBdbSRegistryP) registryH;
00539         {
00540             CdbStatus result = CdbBdbSRegistryP::findByOrigin( registryH,
00541                                                                originId );
00542             if( CdbStatus::Success != result ) {
00543                 if( CdbStatus::NotFound == result ) {
00544 
00545                   // The origin is not currently instantiated in the input database. This may happen
00546                   // when the origin's data are yet to be imported.
00547 
00548                     continue;
00549 
00550                 } else {
00551                     cerr << "failed to find a registry for origin ID = " << originId << "." << endl;
00552                     return 1;
00553                 }
00554             }
00555         }
00556 
00557       // Open the output file for the registry & related collections
00558 
00559         const CdbCPtr<TFile> databaseFilePtr = openRegistryDatabase( originId );
00560         if( databaseFilePtr.isNull( )) return 1;
00561 
00562       // Create a registry descriptor of the corresponding type
00563 
00564         CdbRooRoRegistryDescriptorR registryDescriptor;
00565 
00566         switch( originH->type( )) {
00567 
00568         case CdbBdbSOriginP::MASTER:
00569 
00570             registryDescriptor = CdbRooRoRegistryDescriptorR( originH->id( ),
00571                                                               originH->name( ).head( ),
00572                                                               registryH->description( ).head( ),
00573                                                               registryH->created( ),
00574                                                               registryH->id( ),
00575                                                               true,                         // hasLocalCollections
00576                                                               true,                         // isMaster
00577                                                               false,                        // isSlave
00578                                                               false );                      // isTest
00579             break;
00580 
00581         case CdbBdbSOriginP::SLAVE:
00582 
00583             registryDescriptor = CdbRooRoRegistryDescriptorR( originH->id( ),
00584                                                               originH->name( ).head( ),
00585                                                               registryH->description( ).head( ),
00586                                                               registryH->created( ),
00587                                                               registryH->id( ),
00588                                                               true,                         // hasLocalCollections
00589                                                               false,                        // isMaster
00590                                                               true,                         // isSlave
00591                                                               false );                      // isTest
00592             break;
00593 
00594         case CdbBdbSOriginP::REPLICA:
00595 
00596             cerr << "an obsolete and unsupprted (to the current algorithm) origin type: " << originH->type( ) << " found" << endl
00597                  << "for an origin with ID = " << originH->id( ) << " and NAME = \"" << originH->name( ) << "\"." << endl;
00598             return 1;
00599 
00600         case CdbBdbSOriginP::TEST:
00601 
00602             registryDescriptor = CdbRooRoRegistryDescriptorR( originH->id( ),
00603                                                               originH->name( ).head( ),
00604                                                               registryH->description( ).head( ),
00605                                                               registryH->created( ),
00606                                                               registryH->id( ),
00607                                                               true,                         // hasLocalCollections
00608                                                               false,                        // isMaster
00609                                                               false,                        // isSlave
00610                                                               true );                       // isTest
00611             break;
00612 
00613         default:
00614 
00615             cerr << "unknown (to the current algorithm) origin type: " << originH->type( ) << " found" << endl
00616                  << "for an origin with ID = " << originH->id( ) << " and NAME = \"" << originH->name( ) << "\"." << endl;
00617             return 1;
00618         }
00619 
00620       // Store the descriptor in the output file
00621 
00622         {
00623             const std::string persistentObjectName =
00624                 CdbRooRoFileUtils::nameOfSystemContainer( registryDescriptor.originId( ),
00625                                                           "Registry" );
00626 
00627             databaseFilePtr->Cd( "" );
00628             gDirectory->Cd( databaseFilePtr->GetPath( ));
00629 
00630             Int_t bytesWritten = databaseFilePtr->WriteObject( &registryDescriptor,
00631                                                                persistentObjectName.c_str( ));
00632             if( !bytesWritten ) {
00633                 cerr << "New object couldn't be written. Perhaps it's not" << endl
00634                      << "been properly instrumented for streaming." << endl;
00635                 return 1;
00636             }
00637             cout << databaseFilePtr->GetName( ) << "::" << registryDescriptor.originName( ) << "::" << persistentObjectName << " ** " << bytesWritten << " bytes written **" << endl;
00638         }
00639 
00640       // Convert and store local collections
00641 
00642         if( registryDescriptor.hasLocalCollections( )) {
00643 
00644             if( CdbStatus::Success != ( result = ::convertPhysicalConditions( databaseFilePtr,
00645                                                                               masterRegistryH,
00646                                                                               registryH,
00647                                                                               registryDescriptor ))) {
00648 
00649                 cerr << "Failed to convert a collection of 'physical' conditions." << endl
00650                      << "for origin ID = " << registryDescriptor.originId( ) << endl;
00651                 return 1;
00652             }
00653             if( CdbStatus::Success != ( result = ::convertViews( databaseFilePtr,
00654                                                                  registryH,
00655                                                                  registryDescriptor ))) {
00656 
00657                 cerr << "Failed to convert a collection of views." << endl
00658                      << "for origin ID = " << registryDescriptor.originId( ) << endl;
00659                 return 1;
00660             }
00661             if( CdbStatus::Success != ( result = ::convertRegularClusters( databaseFilePtr,
00662                                                                            registryH,
00663                                                                            registryDescriptor ))) {
00664 
00665                 cerr << "Failed to convert a collection of 'regular' clusters." << endl
00666                      << "for origin ID = " << registryDescriptor.originId( ) << endl;
00667                 return 1;
00668             }
00669         }
00670 
00671       // MASTER & SLAVE collections only
00672 
00673         if( registryDescriptor.isMaster( ) || registryDescriptor.isSlave( )) {
00674 
00675             if( CdbStatus::Success != ( result = ::convertPartitionsLayout( databaseFilePtr,
00676                                                                             registryH,
00677                                                                             registryDescriptor ))) {
00678 
00679                 cerr << "Failed to convert Partitions Layout." << endl
00680                      << "for origin ID = " << registryDescriptor.originId( ) << endl;
00681                 return 1;
00682             }
00683         }
00684 
00685       // MASTER collections only
00686 
00687         if( registryDescriptor.isMaster( )) {
00688 
00689             if( CdbStatus::Success != ( result = ::convertOrigins( databaseFilePtr,
00690                                                                    registryH,
00691                                                                    registryDescriptor ))) {
00692 
00693                 cerr << "Failed to convert a collection of origins." << endl
00694                      << "for origin ID = " << registryDescriptor.originId( ) << endl;
00695                 return 1;
00696             }
00697             if( CdbStatus::Success != ( result = ::convertPartitionableClusters( databaseFilePtr,
00698                                                                                  registryH,
00699                                                                                  registryDescriptor ))) {
00700 
00701                 cerr << "Failed to convert a collection of 'partitionable' clusters." << endl
00702                      << "for origin ID = " << registryDescriptor.originId( ) << endl;
00703                 return 1;
00704             }
00705         }
00706      }
00707 
00708   // Create the boot file
00709 
00710     {
00711       // Get the local registry and its origin
00712 
00713         BdbHandle(CdbBdbSRegistryP) localRegistryH;
00714         CdbStatus result = CdbBdbSRegistryP::findLocal( localRegistryH );
00715         if( CdbStatus::Success != result ) {
00716             cerr << "failed to find the local registry." << endl;
00717             return 1;
00718         }
00719 
00720         BdbHandle(CdbBdbSOriginP) originH;
00721         {
00722             BdbRef(CdbBdbSOriginP) originRef;
00723             if( CdbStatus::Success != originCollectionH->find( localRegistryH->originId( ),
00724                                                                originRef )) {
00725 
00726                 cerr << "failed to find the local origin with ID = " << localRegistryH->originId( ) << "." << endl
00727                      << "The input database may not be properly initialized." << endl;
00728                 return 1;
00729             }
00730             originH = originRef;
00731         }
00732 
00733       // Create the boorfile record
00734 
00735         const std::string bootFileName = "cdb_boot.root";
00736         TFile boofFileDatabaseFile( bootFileName.c_str( ), "recreate" );
00737         if( boofFileDatabaseFile.IsZombie( )) {
00738             cerr << "Failed to (re-)create the file: \"" << boofFileDatabaseFile.GetName( ) << "\"." << endl;
00739             return 1;
00740         }
00741         const std::map<std::string,std::string> object2DatabaseMap;     // This special mapping is not implemented
00742                                                                         // in the current version of the conversion procedure.
00743         CdbRooRoBootRecordR bootRecord( originH->name( ).head( ),
00744                                         originH->id( ),
00745                                         "<local>::<recent>",
00746                                         database2LocationMap,
00747                                         object2DatabaseMap );
00748         const Int_t numBytes = boofFileDatabaseFile.WriteObject( &bootRecord,
00749                                                                  CdbRooRoBootRecordR::PersistentObjectName( ));
00750         if( numBytes <= 0 ) {
00751             cerr << "failed to save the boot record '" << CdbRooRoBootRecordR::PersistentObjectName( ) << "' in the file: " << boofFileDatabaseFile.GetName( ) << endl;
00752             return 1;
00753         }
00754 
00755     }
00756 
00757    // Done.
00758 
00759     return 0;
00760 }
00761 
00762 /////////////
00763 // Helpers //
00764 /////////////
00765 
00766 namespace {
00767 
00768     CdbStatus
00769     convertConfigCollection( CdbRooRoConfigCollectionR*&             theOutputConfigPtr,
00770                              const BdbRef(CdbBdbSConfigCollectionP)& theInputConfigCollectionRef )
00771     {
00772         const char* errorStr = "::convertConfigCollection() - ERROR.";
00773 
00774         CdbStatus result = CdbStatus::Error;
00775 
00776         if( BdbIsNull(theInputConfigCollectionRef)) {
00777             theOutputConfigPtr = 0;
00778             return CdbStatus::Success;
00779         }
00780         theOutputConfigPtr = new CdbRooRoConfigCollectionR( );
00781 
00782         CdbBdbSConfigCollectionP::IteratorOfIntervals itr = theInputConfigCollectionRef->iterator( );
00783         while( itr.next( )) {
00784 
00785             CdbBdbSConfigInterval iVal = itr.value( );
00786 
00787             CdbRooRoConfigElementR element( iVal.value.revision,
00788                                             iVal.value.partition,
00789                                             iVal.value.useRevision );
00790 
00791             CdbRooRoConfigInterval interval( element,
00792                                              iVal.begin,
00793                                              iVal.end );
00794 
00795             if( CdbStatus::Success != ( result = theOutputConfigPtr->insert( interval ))) {
00796                 cerr << errorStr << endl
00797                      << "    Failed to isert the interval into the output collection." << endl
00798                      << "        INTERVAL: " << interval << endl;
00799                 return result;
00800             }
00801         }
00802         return CdbStatus::Success;
00803     }
00804 
00805     CdbStatus
00806     convertFoldersAndConditions( CdbRooRoViewR&                   theView,
00807                                  const BdbHandle(CdbBdbSFolderP)& theFolderH,
00808                                  const CdbPathName&               theCurrentPathName )
00809     {
00810         const char* errorStr = "::convertFoldersAndConditions() - ERROR.";
00811 
00812         assert( !BdbIsNull(theFolderH));
00813 
00814         CdbStatus result = CdbStatus::Error;
00815 
00816         // Browse conditions in the input folder and copy them
00817 
00818         {
00819             CdbItr< const char* > itr;
00820             if( CdbStatus::Success != ( result = theFolderH->conditionIterator( itr ))) {
00821                 cerr << errorStr << endl
00822                      << "    Failed to obtain an iterator of condition names." << endl
00823                      << "        CURRENT FOLDER: \"" << theCurrentPathName << "\"" << endl;
00824                 return result;
00825             }
00826             while( itr.next( )) {
00827 
00828               // Find the input condition objct
00829 
00830                 BdbHandle(CdbBdbSConditionAtFolderP) conditionH;
00831                 {
00832                     BdbRef(CdbBdbSConditionAtFolderP) conditionRef;
00833                     if( CdbStatus::Success != ( result = theFolderH->findCondition( CdbPathName( itr.value( )),
00834                                                                                     conditionRef ))) {
00835                         cerr << errorStr << endl
00836                              << "    Failed to find the condition in the current folder." << endl
00837                              << "        CURRENT FOLDER: \"" << theCurrentPathName << "\"" << endl
00838                              << "        CONDITION:      \"" << itr.value( ) << "\"" << endl;
00839                         return result;
00840                     }
00841                     conditionH = conditionRef;
00842                 }
00843                 assert( !BdbIsNull(conditionH));
00844 
00845               // Convert the configuration collection (if any)
00846               //
00847               // NOTE: The null input collection is considered a normal result since some conditions
00848               //       may be used through a default collection of their parent view.
00849 
00850                 CdbRooRoConfigCollectionR* configPtr = 0;
00851 
00852                 if( CdbStatus::Success != ( result = ::convertConfigCollection( configPtr,
00853                                                                                 conditionH->config( )))) {
00854                     cerr << errorStr << endl
00855                          << "    Failed to convert the configuration collection of the condition in the current folder." << endl
00856                          << "        CURRENT FOLDER: \"" << theCurrentPathName << "\"" << endl
00857                          << "        CONDITION:      \"" << itr.value( ) << "\"" << endl;
00858                     return result;
00859                 }
00860 
00861               // Create a new condition by its full path in the output view
00862 
00863                 if( CdbStatus::Success != ( result = theView.createCondition( theCurrentPathName.toString( ),
00864                                                                               conditionH->name( ).head( ),
00865                                                                               conditionH->description( ).head( ),
00866                                                                               conditionH->created( ),
00867                                                                               CdbRooRoIdR( conditionH->id( ).origin,
00868                                                                                            conditionH->id( ).local ),
00869                                                                               configPtr ))) {
00870                     cerr << errorStr << endl
00871                          << "    Failed to create the condition in the output view." << endl
00872                          << "        CURRENT FOLDER: \"" << theCurrentPathName << "\"" << endl
00873                          << "        CONDITION:      \"" << itr.value( ) << "\"" << endl;
00874                     return result;
00875                 }
00876             }
00877         }
00878 
00879         // Browse folders in the input folder and copy them
00880 
00881         {
00882             CdbItr< const char* > itr;
00883             if( CdbStatus::Success != ( result = theFolderH->folderIterator( itr ))) {
00884                 cerr << errorStr << endl
00885                      << "    Failed to obtain an iterator of folder names." << endl
00886                      << "        CURRENT FOLDER: \"" << theCurrentPathName << "\"" << endl;
00887                 return result;
00888             }
00889             while( itr.next( )) {
00890 
00891               // Find the input folder objct
00892 
00893                 BdbHandle(CdbBdbSFolderP) folderH;
00894                 {
00895                     BdbRef(CdbBdbSFolderP) folderRef;
00896                     if( CdbStatus::Success != ( result = theFolderH->findFolder( CdbPathName( itr.value( )),
00897                                                                                  folderRef ))) {
00898                         cerr << errorStr << endl
00899                              << "    Failed to find the folder in the current folder." << endl
00900                              << "        CURRENT FOLDER: \"" << theCurrentPathName << "\"" << endl
00901                              << "        FOLDER:         \"" << itr.value( ) << "\"" << endl;
00902                         return result;
00903                     }
00904                     folderH = folderRef;
00905                 }
00906                 assert( !BdbIsNull(folderH));
00907 
00908               // Create a new folder by its full path in the output view
00909 
00910                 CdbPathName folderFullPathName = theCurrentPathName + itr.value( );
00911 
00912                 if( CdbStatus::Success != ( result = theView.createFolder( folderFullPathName.toString( ),
00913                                                                            folderH->description( ).head( ),
00914                                                                            folderH->created( )))) {
00915                     cerr << errorStr << endl
00916                          << "    Failed to create the folder in the output view." << endl
00917                          << "        CURRENT FOLDER: \"" << theCurrentPathName << "\"" << endl
00918                          << "        FOLDER:         \"" << itr.value( ) << "\"" << endl;
00919                     return result;
00920                 }
00921 
00922               // Proceed down to the found folder
00923 
00924                 if( CdbStatus::Success != ( result = ::convertFoldersAndConditions( theView,
00925                                                                                     folderH,
00926                                                                                     folderFullPathName ))) {
00927                     cerr << errorStr << endl
00928                          << "    Failed to convert folders starting from the found one." << endl
00929                          << "        CURRENT FOLDER: \"" << theCurrentPathName << "\"" << endl
00930                          << "        FOLDER:         \"" << itr.value( ) << "\"" << endl;
00931                     return result;
00932                 }
00933             }
00934         }
00935         return CdbStatus::Success;
00936     }
00937 
00938     CdbStatus
00939     convertPhysicalConditions( const CdbCPtr<TFile>&              theFilePtr,
00940                                const BdbHandle(CdbBdbSRegistryP)& theMasterRegistryH,
00941                                const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
00942                                const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor )
00943     {
00944         const char* errorStr = "::convertPhysicalConditions() - ERROR.";
00945 
00946         assert( !BdbIsNull(theInRegistryH));
00947 
00948         CdbStatus result = CdbStatus::Error;
00949 
00950         CdbRooRoConditionCollectionR conditionCollection;
00951 
00952         BdbHandle(CdbBdbSConditionCollectionP) conditionCollectionH = theInRegistryH->conditionCollection( );
00953 
00954         CdbBdbSConditionCollectionP::IteratorOfIdentifiers itr = conditionCollectionH->iterator_identifiers( );
00955         while( itr.next( )) {
00956 
00957           // Get the input condition
00958 
00959             d_UShort conditionId = itr.value( );
00960 
00961             BdbHandle(CdbBdbSConditionP) conditionH;
00962             {
00963                 BdbRef(CdbBdbSConditionP) conditionRef;
00964                 if( CdbStatus::Success != ( result = conditionCollectionH->find( conditionId,
00965                                                                                  conditionRef ))) {
00966                     cerr << errorStr << endl
00967                          << "    A condition with ID = " << conditionId << " was not found." << endl;
00968                     return result;
00969                 }
00970                 conditionH = conditionRef;
00971             }
00972 
00973           // See if we need to exclude it
00974 
00975             if( conditionH->isPartitionable( )) {
00976                 if( excludePartitionableFlag ) continue;
00977             } else {
00978                 if( excludeRegularFlag ) continue;
00979             }
00980 
00981           // Create the output one and put into the collection
00982 
00983             CdbRooRoConditionR condition( conditionH->name( ).head( ),
00984                                           conditionH->id( ),
00985                                           conditionH->isPartitionable( ),
00986                                           conditionH->cluster( )->id( ),
00987                                           conditionH->created( ),
00988                                           conditionH->description( ).head( ));
00989 
00990             if( CdbStatus::Success != ( result = conditionCollection.add( condition ))) {
00991                 cerr << errorStr << endl
00992                      << "    Failed to add a condition with ID = " << conditionId << " to a collection." << endl;
00993                 return result;
00994             }
00995             if( verboseModeFlag ) {
00996                 condition.dump( cout );
00997                 cout << endl;
00998             }
00999 
01000           // Find all relevant MetaData objects and convert them too
01001 
01002             if( !conditionH->isPartitionable( )) {
01003 
01004                 if( CdbStatus::Success != ( result = ::convertMetaDataOfRegularCondition( conditionH,
01005                                                                                           theMasterRegistryH,
01006                                                                                           theInRegistryH->originId( ),
01007                                                                                           theOutRegistryDescriptor ))) {
01008                     cerr << errorStr << endl
01009                          << "    Failed to convert MetaDaa of a 'regular' condition with ID = " << conditionId << "." << endl;
01010                     return result;
01011                 }
01012 
01013             } else {
01014 
01015                 if( CdbStatus::Success != ( result = ::convertMetaDataOfPartitionableCondition( conditionH,
01016                                                                                                 theMasterRegistryH,
01017                                                                                                 theOutRegistryDescriptor ))) {
01018                     cerr << errorStr << endl
01019                          << "    Failed to convert MetaDaa of a 'partitionable' condition with ID = " << conditionId << "." << endl;
01020                     return result;
01021                 }
01022             }
01023         }
01024 
01025       // Save the output collection of 'physical' conditions
01026 
01027         const std::string persistentObjectName =
01028             CdbRooRoFileUtils::nameOfSystemContainer( theOutRegistryDescriptor.originId( ),
01029                                                       "ConditionCollection" );
01030 
01031         Int_t bytesWritten = 0;
01032 
01033         theFilePtr->Cd( "" );
01034         gDirectory->Cd( theFilePtr->GetPath( ));
01035 
01036         if( CdbStatus::Success != conditionCollection.storeAt( CdbRooRoCollectionAddressR::createRegistry( persistentObjectName,
01037                                                                                                            theOutRegistryDescriptor.originId( )),
01038                                                                theFilePtr,
01039                                                                bytesWritten )) {
01040             cerr << errorStr << endl
01041                  << "    New object couldn't be written." << endl
01042                  << "    Perhaps it's not been properly instrumented for the streaming." << endl;
01043             return CdbStatus::Error;
01044         }
01045         cout << theFilePtr->GetName( ) << "::" << theOutRegistryDescriptor.originName( ) << "::" << persistentObjectName << " ** " << bytesWritten << " bytes written **" << endl;
01046 
01047         return CdbStatus::Success;
01048     }
01049 
01050     CdbStatus
01051     convertViews( const CdbCPtr<TFile>&              theFilePtr,
01052                   const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
01053                   const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor )
01054     {
01055         const char* errorStr = "::convertViews() - ERROR.";
01056 
01057         assert( !BdbIsNull(theInRegistryH));
01058 
01059         CdbStatus result = CdbStatus::Error;
01060 
01061         CdbRooRoViewCollectionR viewCollection;
01062 
01063         BdbHandle(CdbBdbSViewCollectionP) viewCollectionH = theInRegistryH->viewCollection( );
01064         assert( !BdbIsNull(viewCollectionH));
01065 
01066         CdbBdbSViewCollectionP::IteratorOfIdentifiers itr = viewCollectionH->iterator_identifiers( );
01067         while( itr.next( )) {
01068 
01069           // Get the input condition
01070 
01071             d_UShort viewId = itr.value( );
01072 
01073             BdbHandle(CdbBdbSViewP) viewH;
01074             {
01075                 BdbRef(CdbBdbSViewP) viewRef;
01076                 if( CdbStatus::Success != ( result = viewCollectionH->find( viewId,
01077                                                                             viewRef ))) {
01078                     cerr << errorStr << endl
01079                          << "    A view with ID = " << viewId << " was not found." << endl;
01080                     return result;
01081                 }
01082                 viewH = viewRef;
01083             }
01084 
01085           // Convert the configuration collection (if any)
01086           //
01087           // NOTE: The null input collection is considered a normal result since conditions
01088           //       normally have their own conditions.
01089 
01090             CdbRooRoConfigCollectionR* configPtr = 0;
01091 
01092             if( CdbStatus::Success != ( result = ::convertConfigCollection( configPtr,
01093                                                                             viewH->defaultConfig( )))) {
01094                 cerr << errorStr << endl
01095                      << "    Failed to convert the default configuration collection of a view with ID = " << viewId << endl;
01096                 return result;
01097             }
01098 
01099           // Create the output view
01100 
01101             CdbRooRoViewR view( viewH->name( ).head( ),
01102                                 viewH->id( ),
01103                                 viewH->description( ).head( ),
01104                                 viewH->created( ),
01105                                 viewH->minValidity( ),
01106                                 viewH->maxValidity( ),
01107                                 configPtr );
01108 
01109           // Proceed down to folders
01110           //
01111           // NOTES:
01112           //
01113           //   (1) The "/" folder must already exist in the output collection as it's created
01114           //       automatically at the same time the view gets created.
01115           //
01116           //   (2) The path name would be automatically extended as the recursive copying
01117           //       procedure of folders and conditions will keep going.
01118 
01119             BdbHandle(CdbBdbSFolderP) rootFolderH = viewH->rootFolder( );
01120             assert( !BdbIsNull(rootFolderH));
01121 
01122             if( CdbStatus::Success != ( result = ::convertFoldersAndConditions( view,
01123                                                                                 rootFolderH,
01124                                                                                 CdbPathName( rootFolderH->name( ).head( ))))) {
01125                 cerr << errorStr << endl
01126                      << "    Failed to convert folders starting from \"/\"" << endl
01127                      << "    when copying view \"" << view.name( ) << "\"" << endl;
01128                 return result;
01129             }
01130                                                         
01131           // Finally, store the whole graph in the collection
01132 
01133             if( CdbStatus::Success != ( result = viewCollection.add( view ))) {
01134                 cerr << errorStr << endl
01135                      << "    Failed to add a view to a collection" << endl;
01136                 return result;
01137             }
01138             if( verboseModeFlag ) {
01139                 view.dump( cout );
01140                 cout << endl;
01141             }
01142         }
01143 
01144       // Save the output collection
01145 
01146         const std::string persistentObjectName =
01147             CdbRooRoFileUtils::nameOfSystemContainer( theOutRegistryDescriptor.originId( ),
01148                                                       "ViewCollection" );
01149 
01150         Int_t bytesWritten = 0;
01151 
01152         theFilePtr->Cd( "" );
01153         gDirectory->Cd( theFilePtr->GetPath( ));
01154 
01155         if( CdbStatus::Success != viewCollection.storeAt( CdbRooRoCollectionAddressR::createRegistry( persistentObjectName,
01156                                                                                                       theOutRegistryDescriptor.originId( )),
01157                                                           theFilePtr,
01158                                                           bytesWritten )) {
01159             cerr << errorStr << endl
01160                  << "    New object couldn't be written. Perhaps it's not" << endl
01161                  << "    been properly instrumented for streaming." << endl;
01162             return CdbStatus::Error;
01163         }
01164         cout << theFilePtr->GetName( ) << "::" << theOutRegistryDescriptor.originName( ) << "::" << persistentObjectName << " ** " << bytesWritten << " bytes written **" << endl;
01165 
01166         return CdbStatus::Success;
01167     }
01168 
01169     CdbStatus
01170     convertRegularClusters( const CdbCPtr<TFile>&              theFilePtr,
01171                             const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
01172                             const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor )
01173     {
01174         const char* errorStr = "::convertRegularClusters() - ERROR.";
01175 
01176         assert( !BdbIsNull(theInRegistryH));
01177 
01178         CdbStatus result = CdbStatus::Error;
01179 
01180         CdbRooRoRClusterCollectionR clusterCollection;
01181 
01182         BdbHandle(CdbBdbSClusterCollectionP) clusterCollectionH = theInRegistryH->clusterCollection( );
01183         assert( !BdbIsNull(clusterCollectionH));
01184 
01185         CdbBdbSClusterCollectionP::IteratorOfIdentifiers itr = clusterCollectionH->iterator_identifiers( );
01186         while( itr.next( )) {
01187 
01188           // Get the input condition
01189 
01190             d_UShort clusterId = itr.value( );
01191 
01192             BdbHandle(CdbBdbSSimpleClusterP) clusterH;
01193             {
01194                 BdbRef(CdbBdbSSimpleClusterP) clusterRef;
01195                 if( CdbStatus::Success != ( result = clusterCollectionH->find( clusterId,
01196                                                                                clusterRef ))) {
01197                     cerr << errorStr << endl
01198                          << "    A 'regular' cluster with ID = " << clusterId << " was not found." << endl;
01199                     return result;
01200                 }
01201                 clusterH = clusterRef;
01202             }
01203 
01204           // Prepare a vector with increments converted from the input cluster
01205 
01206             std::vector<CdbRooRoIncrementR> vectorOfIncrements;
01207             {
01208                 d_UShort numIncrements = clusterH->numIncrements( );
01209                 for( d_UShort i = 0; i < numIncrements; ++i ) {
01210 
01211                     CdbBdbSIncrement inputIncrement;
01212 
01213                     if( CdbStatus::Success != ( result = clusterH->increment( i,
01214                                                                               inputIncrement ))) {
01215                         cerr << errorStr << endl
01216                              << "    An increment with ID = " << i << " was not found in a cluster with ID = " << clusterId << endl;
01217                         return result;
01218                     }
01219 
01220                     CdbRooRoIncrementR outputIncrement( inputIncrement.begin,
01221                                                         inputIncrement.end );
01222 
01223                     vectorOfIncrements.push_back( outputIncrement );
01224                 }
01225             }
01226 
01227           // Create the output cluster and store it in the collection
01228 
01229             CdbRooRoRClusterR cluster( clusterH->id( ),
01230                                        clusterH->name( ).head( ),
01231                                        clusterH->created( ),
01232                                        clusterH->description( ).head( ),
01233                                        vectorOfIncrements );
01234 
01235             if( CdbStatus::Success != ( result = clusterCollection.add( cluster ))) {
01236                 cerr << errorStr << endl
01237                      << "    Failed to add a 'regular' cluster to a collection" << endl;
01238                 return result;
01239             }
01240             if( verboseModeFlag ) {
01241                 cluster.dump( cout );
01242                 cout << endl;
01243             }
01244         }
01245 
01246       // Save the output collection
01247 
01248         const std::string persistentObjectName =
01249             CdbRooRoFileUtils::nameOfSystemContainer( theOutRegistryDescriptor.originId( ),
01250                                                       "RegularClusterCollection" );
01251 
01252         Int_t bytesWritten = 0;
01253 
01254         theFilePtr->Cd( "" );
01255         gDirectory->Cd( theFilePtr->GetPath( ));
01256 
01257         if( CdbStatus::Success != clusterCollection.storeAt( CdbRooRoCollectionAddressR::createRegistry( persistentObjectName,
01258                                                                                                          theOutRegistryDescriptor.originId( )),
01259                                                              theFilePtr,
01260                                                              bytesWritten )) {
01261             cerr << errorStr << endl
01262                  << "    New object couldn't be written. Perhaps it's not" << endl
01263                  << "    been properly instrumented for streaming." << endl;
01264             return CdbStatus::Error;
01265         }
01266         cout << theFilePtr->GetName( ) << "::" << theOutRegistryDescriptor.originName( ) << "::" << persistentObjectName << " ** " << bytesWritten << " bytes written **" << endl;
01267 
01268         return CdbStatus::Success;
01269     }
01270 
01271     CdbStatus
01272     convertPartitionsLayout( const CdbCPtr<TFile>&              theFilePtr,
01273                              const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
01274                              const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor )
01275     {
01276         const char* errorStr = "::convertPartitionsLayout() - ERROR.";
01277 
01278         assert( !BdbIsNull(theInRegistryH));
01279 
01280         CdbStatus result = CdbStatus::Error;
01281 
01282         std::vector<CdbRooRoPartitionR> vectorOfPartitions;
01283 
01284         BdbHandle(CdbBdbSPartitionsLayoutP) partitionsLayoutH = theInRegistryH->partitionsLayout( );
01285         assert( !BdbIsNull(partitionsLayoutH));
01286 
01287         CdbItr<d_UShort> itr = partitionsLayoutH->iterator( );
01288         while( itr.next( )) {
01289 
01290             d_UShort partitionId = itr.value( );
01291 
01292           // Get the input partition
01293 
01294             BdbHandle(CdbBdbSPartitionP) partitionH;
01295             {
01296                 BdbRef(CdbBdbSPartitionP) partitionRef;
01297                 if( CdbStatus::Success != ( result = partitionsLayoutH->find( partitionId,
01298                                                                               partitionRef ))) {
01299                     cerr << errorStr << endl
01300                          << "    A partition with ID = " << partitionId << " was not found." << endl;
01301                     return result;
01302                 }
01303                 partitionH = partitionRef;
01304             }
01305 
01306           // Prepare a vector with increments converted from the input cluster
01307 
01308             std::vector<CdbRooRoIncrementR> vectorOfIncrements;
01309             {
01310                 d_UShort numIncrements = partitionH->numIncrements( );
01311                 for( d_UShort i = 0; i < numIncrements; ++i ) {
01312 
01313                     CdbBdbSIncrement inputIncrement;
01314 
01315                     if( CdbStatus::Success != ( result = partitionH->increment( i,
01316                                                                                 inputIncrement ))) {
01317                         cerr << errorStr << endl
01318                              << "    An increment with ID = " << i << " was not found in a partition with ID = " << partitionId << endl;
01319                         return result;
01320                     }
01321 
01322                     CdbRooRoIncrementR outputIncrement( inputIncrement.begin,
01323                                                         inputIncrement.end );
01324 
01325                     vectorOfIncrements.push_back( outputIncrement );
01326                 }
01327             }
01328 
01329           // Create the output cluster and store it in the collection
01330 
01331             CdbRooRoPartitionR partition( vectorOfIncrements,
01332                                           partitionH->id( ),
01333                                           partitionH->originId( ),
01334                                           partitionH->isInstantiated( ),
01335                                           partitionH->isClosed( ),
01336                                           partitionH->created( ),
01337                                           partitionH->modified( ),
01338                                           partitionH->cell( ).beginValidity,
01339                                           partitionH->cell( ).endValidity,
01340                                           partitionH->cell( ).beginInsertion,
01341                                           partitionH->cell( ).endInsertion,
01342                                           partitionH->description( ).head( ));
01343 
01344             vectorOfPartitions.push_back( partition );
01345 
01346             if( verboseModeFlag ) {
01347                 partition.dump( cout );
01348                 cout << endl;
01349             }
01350         }
01351 
01352       // Finally, create the output layout using the prepared vector of partitions
01353 
01354         CdbRooRoPartitionsLayoutR partitionsLayout( vectorOfPartitions );
01355 
01356       // Save the output collection
01357 
01358         const std::string persistentObjectName =
01359             CdbRooRoFileUtils::nameOfSystemContainer( theOutRegistryDescriptor.originId( ),
01360                                                       "PartitionsLayout" );
01361 
01362         Int_t bytesWritten = 0;
01363 
01364         theFilePtr->Cd( "" );
01365         gDirectory->Cd( theFilePtr->GetPath( ));
01366 
01367         if( CdbStatus::Success != partitionsLayout.storeAt( CdbRooRoCollectionAddressR::createRegistry( persistentObjectName,
01368                                                                                                         theOutRegistryDescriptor.originId( )),
01369                                                             theFilePtr,
01370                                                             bytesWritten )) {
01371             cerr << errorStr << endl
01372                  << "    New object couldn't be written. Perhaps it's not" << endl
01373                  << "    been properly instrumented for streaming." << endl;
01374             return CdbStatus::Error;
01375         }
01376         cout << theFilePtr->GetName( ) << "::" << theOutRegistryDescriptor.originName( ) << "::" << persistentObjectName << " ** " << bytesWritten << " bytes written **" << endl;
01377 
01378         return CdbStatus::Success;
01379     }
01380 
01381     CdbStatus
01382     convertOrigins( const CdbCPtr<TFile>&              theFilePtr,
01383                     const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
01384                     const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor )
01385     {
01386         const char* errorStr = "::convertOrigins() - ERROR.";
01387 
01388         assert( !BdbIsNull(theInRegistryH));
01389 
01390         CdbStatus result = CdbStatus::Error;
01391 
01392         CdbRooRoOriginCollectionR originCollection;
01393 
01394         BdbHandle(CdbBdbSOriginCollectionP) originCollectionH = theInRegistryH->originCollection( );
01395         assert( !BdbIsNull(originCollectionH));
01396 
01397         CdbBdbSOriginCollectionP::IteratorOfIdentifiers itr = originCollectionH->iterator_identifiers( );
01398         while( itr.next( )) {
01399 
01400           // Get the input condition
01401 
01402             d_UShort originId = itr.value( );
01403 
01404             BdbHandle(CdbBdbSOriginP) originH;
01405             {
01406                 BdbRef(CdbBdbSOriginP) originRef;
01407                 if( CdbStatus::Success != ( result = originCollectionH->find( originId,
01408                                                                               originRef ))) {
01409                     cerr << errorStr << endl
01410                          << "    An origin with ID = " << originId << " was not found." << endl;
01411                     return result;
01412                 }
01413                 originH = originRef;
01414             }
01415 
01416           // Remap the origin type
01417 
01418             CdbRooRoOriginR::OriginType originType = CdbRooRoOriginR::FIRST;
01419 
01420             switch( originH->type( )) {
01421 
01422             case CdbBdbSOriginP::MASTER  : originType = CdbRooRoOriginR::MASTER;  break;
01423             case CdbBdbSOriginP::SLAVE   : originType = CdbRooRoOriginR::SLAVE;   break;
01424             case CdbBdbSOriginP::REPLICA : originType = CdbRooRoOriginR::REPLICA; break;
01425             case CdbBdbSOriginP::TEST    : originType = CdbRooRoOriginR::TEST;    break;
01426 
01427             default:
01428 
01429                 cerr << errorStr << endl
01430                      << "    An unknown (to the current algorithm) origin type: " << originH->type( ) << endl;
01431                 return CdbStatus::Error;
01432             }
01433 
01434           // Create the output one and put into the collection
01435 
01436             CdbRooRoOriginR origin( originH->name( ).head( ),
01437                                     originH->id( ),
01438                                     originType,
01439                                     originH->created( ),
01440                                     originH->description( ).head( ));
01441 
01442             if( CdbStatus::Success != ( result = originCollection.add( origin ))) {
01443                 cerr << errorStr << endl
01444                      << "    Failed to add an origin to a collection" << endl;
01445                 return result;
01446             }
01447             if( verboseModeFlag ) {
01448                 origin.dump( cout );
01449                 cout << endl;
01450             }
01451         }
01452 
01453       // Save the output collection
01454 
01455         const std::string persistentObjectName =
01456             CdbRooRoFileUtils::nameOfSystemContainer( theOutRegistryDescriptor.originId( ),
01457                                                       "OriginCollection" );
01458 
01459         Int_t bytesWritten = 0;
01460 
01461         theFilePtr->Cd( "" );
01462         gDirectory->Cd( theFilePtr->GetPath( ));
01463 
01464         if( CdbStatus::Success != originCollection.storeAt( CdbRooRoCollectionAddressR::createRegistry( persistentObjectName,
01465                                                                                                         theOutRegistryDescriptor.originId( )),
01466                                                             theFilePtr,
01467                                                             bytesWritten )) {
01468             cerr << errorStr << endl
01469                  << "    New object couldn't be written. Perhaps it's not" << endl
01470                  << "    been properly instrumented for streaming." << endl;
01471             return CdbStatus::Error;
01472         }
01473         cout << theFilePtr->GetName( ) << "::" << theOutRegistryDescriptor.originName( ) << "::" << persistentObjectName << "  ** " << bytesWritten << " bytes written **" << endl;
01474 
01475         return CdbStatus::Success;
01476     }
01477 
01478     CdbStatus
01479     convertPartitionableClusters( const CdbCPtr<TFile>&              theFilePtr,
01480                                   const BdbHandle(CdbBdbSRegistryP)& theInRegistryH,
01481                                   const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor )
01482     {
01483         const char* errorStr = "::convertPartitionableClusters() - ERROR.";
01484 
01485         assert( !BdbIsNull(theInRegistryH));
01486 
01487         CdbStatus result = CdbStatus::Error;
01488 
01489         CdbRooRoClusterCollectionR clusterCollection;
01490 
01491         BdbHandle(CdbBdbSClusterCollectionP) clusterCollectionH = theInRegistryH->pClusterCollection( );
01492         assert( !BdbIsNull(clusterCollectionH));
01493 
01494         CdbBdbSClusterCollectionP::IteratorOfIdentifiers itr = clusterCollectionH->iterator_identifiers( );
01495         while( itr.next( )) {
01496 
01497           // Get the input condition
01498 
01499             d_UShort clusterId = itr.value( );
01500 
01501             BdbHandle(CdbBdbSClusterP) clusterH;
01502             {
01503                 BdbRef(CdbBdbSClusterP) clusterRef;
01504                 if( CdbStatus::Success != ( result = clusterCollectionH->find( clusterId,
01505                                                                                clusterRef ))) {
01506                     cerr << errorStr << endl
01507                          << "    A 'partitionable' cluster with ID = " << clusterId << " was not found." << endl;
01508                     return result;
01509                 }
01510                 clusterH = clusterRef;
01511             }
01512 
01513           // Create the output cluster and store it in the collection
01514 
01515             CdbRooRoClusterR cluster( clusterH->id( ),
01516                                       clusterH->name( ).head( ),
01517                                       clusterH->created( ),
01518                                       clusterH->description( ).head( ));
01519 
01520             if( CdbStatus::Success != ( result = clusterCollection.add( cluster ))) {
01521                 cerr << errorStr << endl
01522                      << "    Failed to add a 'partitionable' cluster to a collection" << endl;
01523                 return result;
01524             }
01525             if( verboseModeFlag ) {
01526                 cluster.dump( cout );
01527                 cout << endl;
01528             }
01529         }
01530 
01531       // Save the output collection
01532 
01533         const std::string persistentObjectName =
01534             CdbRooRoFileUtils::nameOfSystemContainer( theOutRegistryDescriptor.originId( ),
01535                                                       "PartitionableClusterCollection" );
01536 
01537         Int_t bytesWritten = 0;
01538 
01539         theFilePtr->Cd( "" );
01540         gDirectory->Cd( theFilePtr->GetPath( ));
01541 
01542         if( CdbStatus::Success != clusterCollection.storeAt( CdbRooRoCollectionAddressR::createRegistry( persistentObjectName,
01543                                                                                                          theOutRegistryDescriptor.originId( )),
01544                                                              theFilePtr,
01545                                                              bytesWritten )) {
01546             cerr << errorStr << endl
01547                  << "    New object couldn't be written. Perhaps it's not" << endl
01548                  << "    been properly instrumented for streaming." << endl;
01549             return CdbStatus::Error;
01550         }
01551         cout << theFilePtr->GetName( ) << "::" << theOutRegistryDescriptor.originName( ) << "::" << persistentObjectName << " ** " << bytesWritten << " bytes written **" << endl;
01552 
01553         return CdbStatus::Success;
01554     }
01555 
01556     CdbStatus
01557     testMetaDataConversion( )
01558     {
01559         const char* errorStr = "::testMetaDataConversion() - ERROR.";
01560 
01561         CdbStatus result = CdbStatus::Error;
01562 
01563       // Ask a user which collection to convert
01564 
01565         d_UShort originId = 0;
01566 
01567         cout << endl
01568              << "Please, enter the parameters of a condition." << endl
01569              << endl;
01570 
01571         d_UShort conditionId = 0xFFFF;
01572         {
01573             cout << "  Condition identifier : "; cin >> conditionId;
01574         }
01575         bool isPartitionableFlag = false;
01576         {
01577             int yesOrNo;
01578             cout << "Is partitionable [0/1] : "; cin >> yesOrNo;
01579             isPartitionableFlag = ( 0 != yesOrNo );
01580         }
01581         d_UShort partitionId = 0xFFFF;
01582         {
01583             cout << "  Partition identifier : "; cin >> partitionId;
01584         }
01585         d_UShort clusterId = 0xFFFF;
01586         {
01587             cout << "    Cluster identifier : "; cin >> clusterId;
01588         }
01589         d_UShort incrementNumber = 0xFFFF;
01590         {
01591             cout << "      Increment number : "; cin >> incrementNumber;
01592         }
01593         std::string dbIdRange = "";
01594         {
01595             cout << "       DBID Range Name : "; cin >> dbIdRange;
01596         }
01597         cout << endl
01598              << "Just for the record, you've entered the following parameters:" << endl
01599              << endl
01600              << "  Condition identifier : "   << conditionId << endl
01601              << "      Is partitionable : "   << ( isPartitionableFlag ? "Yes" : "No" ) << endl
01602              << "  Partition identifier : "   << partitionId << endl
01603              << "    Cluster identifier : "   << clusterId << endl
01604              << "      Increment number : "   << incrementNumber << endl
01605              << "       DBID Range Name : \"" << dbIdRange << "\"" << endl
01606              << endl;
01607 
01608       // Find the input metadata collection 
01609 
01610         BdbHandle(CdbBdbSMetaDataP) mdH;
01611         {
01612             BdbRef(CdbBdbSMetaDataP) mdRef;
01613             if( CdbStatus::Success != ( result = CdbBdbSUtils::findMetaData( mdRef,
01614                                                                              conditionId,
01615                                                                              isPartitionableFlag,
01616                                                                              partitionId,
01617                                                                              clusterId,
01618                                                                              incrementNumber,
01619                                                                              dbIdRange ))) {
01620                 cerr << errorStr << endl
01621                      << "    Failed to locate the input MetaData object." << endl;
01622                 return result;
01623             }
01624             mdH = mdRef;
01625         }
01626 
01627       // Create the output file
01628 
01629         const CdbCPtr<TFile> databaseFilePtr = new TFile( "cdb_test.root",
01630                                                           "recreate" );
01631         if( databaseFilePtr->IsZombie( )) {
01632             cerr << errorStr << endl
01633                  << "    Failed to (re-)create the file: '" << databaseFilePtr->GetName( ) << "'." << endl;
01634             return CdbStatus::Error;
01635         }
01636 
01637       // Create a fake descriptor
01638 
01639         CdbRooRoRegistryDescriptorR registryDescriptor;
01640 
01641       // Proceed to the converion of the found MetaData object
01642 
01643         return ::convertMetaData( databaseFilePtr,
01644                                   mdH,
01645                                   originId,
01646                                   conditionId,
01647                                   clusterId,
01648                                   isPartitionableFlag,
01649                                   partitionId,
01650                                   incrementNumber,
01651                                   registryDescriptor );
01652     }
01653 
01654     CdbStatus
01655     convertMetaDataOfRegularCondition( const BdbHandle(CdbBdbSConditionP)& theConditionH,
01656                                        const BdbHandle(CdbBdbSRegistryP)&  theMasterRegistryH,
01657                                        d_UShort                            theOwnerOriginId,
01658                                        const CdbRooRoRegistryDescriptorR&  theOutRegistryDescriptor )
01659     {
01660         const char* errorStr = "::convertMetaDataOfRegularCondition() - ERROR.";
01661 
01662         assert( !BdbIsNull(theConditionH));
01663         assert( !theConditionH->isPartitionable( ));
01664         assert( !BdbIsNull(theMasterRegistryH));
01665 
01666         CdbStatus result = CdbStatus::Error;
01667 
01668       // Get the DBID range of the condition's origin.
01669 
01670         std::string dbidRangeName;
01671         {
01672             BdbRef(CdbBdbSOriginP) originRef;
01673             if( CdbStatus::Success != ( result = theMasterRegistryH->originCollection( )->find( theOwnerOriginId,
01674                                                                                                 originRef ))) {
01675                 cerr << errorStr << endl
01676                      << "    An origin with ID=" << theOwnerOriginId << " was not found." << endl;
01677                 return result;
01678             }
01679             dbidRangeName = originRef->dbidrange( ).head( );
01680         }
01681 
01682       // Browse through increments of a cluster the condition is a member of. Select only
01683       // those increments the condition is participating in.
01684       //
01685       // NOTE: The condition might be creaed after certain increments were already
01686       //       closed. That's why we shoul skip those ones closed before.
01687 
01688         BdbHandle(CdbBdbSSimpleClusterP) clusterH = (const BdbRef(CdbBdbSSimpleClusterP)&)theConditionH->cluster( );
01689 
01690         d_ULong numIncrements = clusterH->numIncrements( );
01691         for( d_ULong i = 0; i < numIncrements; ++i ) {
01692 
01693             if( verboseModeFlag ) {
01694                 cout << "increment=" << i << endl;
01695             }
01696 
01697             CdbBdbSIncrement increment;
01698             if( CdbStatus::Success != ( result = clusterH->increment( i,
01699                                                                       increment ))) {
01700                 cerr << errorStr << endl
01701                      << "    Failed to get increment " << i << " from cluster " << clusterH->id( ) << endl
01702                      << "    of condition \"" << theConditionH->name( ) << "\"" << endl;
01703                 return result;
01704             }
01705 
01706           // Skip increments closed at or before the condition creation time.
01707           // These increments are not supposed to know about this condition.
01708 
01709             if( increment.end <= theConditionH->created( )) {
01710                 if( verboseModeFlag ) {
01711                     cout << "skipping the increment=" << i << " since it was" << endl
01712                          << "    ended before the condition was created." << endl
01713                          << "    CONDITION CREATED: " << theConditionH->created( ) << endl
01714                          << "    PARTITION CLOSED : " << increment.end << endl;
01715                 }
01716                 continue;
01717             }
01718 
01719           // Find out the input "MetaData" object
01720 
01721             BdbHandle(CdbBdbSMetaDataP) mdH;
01722             {
01723                 BdbRef(CdbBdbSMetaDataP) mdRef;
01724                 if( CdbStatus::Success != ( result = CdbBdbSUtils::findMetaData( mdRef,
01725                                                                                  theConditionH->id( ),
01726                                                                                  theConditionH->isPartitionable( ),
01727                                                                                  0,
01728                                                                                  clusterH->id( ),
01729                                                                                  i,
01730                                                                                  dbidRangeName.c_str( )))) {
01731                     cerr << errorStr << endl
01732                          << "    Failed to find the metadata object for condition \"" << theConditionH->name( ) << "\"." << endl
01733                          << "    See details above." << endl;
01734                     return result;
01735                 }
01736                 mdH = mdRef;
01737             }
01738 
01739           // Open the output database name for that <condition_owner_origin>-<cluster>-<increment>.
01740           //
01741           // NOTE: The database file is open in the "update" mode, not "recreate". Otherwise
01742           //       we would destroy its previous contents.
01743 
01744             const CdbCPtr<TFile> databaseFilePtr = openMetadataDatabase( theOwnerOriginId,
01745                                                                          clusterH->id( ),
01746                                                                          0,
01747                                                                          i,
01748                                                                          theConditionH->isPartitionable( ));
01749             if( databaseFilePtr.isNull( )) return CdbStatus::Error;
01750 
01751           // Convert the object
01752 
01753             if( CdbStatus::Success != ( result = ::convertMetaData( databaseFilePtr,
01754                                                                     mdH,
01755                                                                     theOwnerOriginId,
01756                                                                     theConditionH->id( ),
01757                                                                     clusterH->id( ),
01758                                                                     theConditionH->isPartitionable( ),
01759                                                                     0,
01760                                                                     i,
01761                                                                     theOutRegistryDescriptor ))) {
01762                 cerr << errorStr << endl
01763                      << "    Failed to translate the metadata object for condition \"" << theConditionH->name( ) << "\"." << endl
01764                      << "    See details above." << endl;
01765                 return result;
01766             }
01767         }
01768         return CdbStatus::Success;
01769     }
01770 
01771     CdbStatus
01772     convertMetaDataOfPartitionableCondition( const BdbHandle(CdbBdbSConditionP)& theConditionH,
01773                                              const BdbHandle(CdbBdbSRegistryP)&  theMasterRegistryH,
01774                                              const CdbRooRoRegistryDescriptorR&  theOutRegistryDescriptor )
01775     {
01776         const char* errorStr = "::convertMetaDataOfPartitionableCondition() : ";
01777 
01778         assert( !BdbIsNull(theConditionH));
01779         assert( theConditionH->isPartitionable( ));
01780         assert( !BdbIsNull(theMasterRegistryH));
01781 
01782         CdbStatus result = CdbStatus::Error;
01783 
01784       // Get to the cluster.
01785 
01786         BdbHandle(CdbBdbSSimpleClusterP) clusterH = (const BdbRef(CdbBdbSSimpleClusterP)&)theConditionH->cluster( );
01787 
01788       // Get to the PartitinLayout at MASTER's Registry and iterate over
01789       // _instantiated_ partitions only.
01790 
01791         BdbHandle(CdbBdbSPartitionsLayoutP) pLayoutH = theMasterRegistryH->partitionsLayout( );
01792 
01793         CdbItr< d_UShort > pItr = pLayoutH->iterator( );
01794         while( pItr.next( )) {
01795 
01796             d_UShort partitionId = pItr.value( );
01797 
01798             if( verboseModeFlag ) {
01799                 cout << "partition ID=" << partitionId << endl;
01800             }
01801 
01802             BdbHandle( CdbBdbSPartitionP ) partitionH;
01803             {
01804                 BdbRef( CdbBdbSPartitionP ) partitionRef;
01805                 if( CdbStatus::Success != ( result = pLayoutH->find( partitionId,
01806                                                                      partitionRef ))) {
01807                     cerr << errorStr << endl
01808                          << "   Failed to find the partition corresponding to ID=" << partitionId << endl;
01809                     return result;
01810                 }
01811                 partitionH = partitionRef;
01812             }
01813 
01814           // Skip this partition if it's not instantiated yet or if it's closed at the time
01815           // of before the current condition was created.
01816 
01817             if( !partitionH->isInstantiated( )) {
01818                 if( verboseModeFlag ) {
01819                     cout << "skipping non-instantiated partition ID=" << partitionId << endl;
01820                 }
01821                 continue;
01822             }
01823             if( partitionH->isClosed( ) && ( partitionH->cell( ).endInsertion <= theConditionH->created( ))) {
01824                 if( verboseModeFlag ) {
01825                     cout << "skipping closed partition ID=" << partitionId << " since it was" << endl
01826                          << "    closed before the condition was created." << endl
01827                          << "    CONDITION CREATED: " << theConditionH->created( ) << endl
01828                          << "    PARTITION CLOSED : " << partitionH->cell( ).endInsertion << endl;
01829                 }
01830                 continue;
01831             }
01832 
01833           // Get the DBID range of the partition's orgin.
01834 
01835             std::string dbidRangeName;
01836             {
01837                 d_UShort originId = partitionH->originId( );
01838 
01839                 BdbRef(CdbBdbSOriginP) originRef;
01840                 if( CdbStatus::Success != ( result = theMasterRegistryH->originCollection( )->find( originId,
01841                                                                                                     originRef ))) {
01842                     cerr << errorStr << endl
01843                          << "    An origin with ID=" << originId << " was not found." << endl;
01844                     return result;
01845                 }
01846                 dbidRangeName = originRef->dbidrange( ).head( );
01847             }
01848 
01849           //  Browse through increments
01850 
01851             d_ULong numIncrements = partitionH->numIncrements( );
01852             for( d_ULong i = 0; i < numIncrements; ++i ) {
01853 
01854                 if( verboseModeFlag ) {
01855                     cout << "increment=" << i << endl;
01856                 }
01857 
01858                 CdbBdbSIncrement increment;
01859                 if( CdbStatus::Success != ( result = partitionH->increment( i,
01860                                                                             increment ))) {
01861                     cerr << errorStr << endl
01862                          << "    Failed to get increment " << i << " from partition " << partitionId << endl
01863                          << "    of condition \"" << theConditionH->name( ) << "\"" << endl;
01864                     return result;
01865                 }
01866 
01867               // Skip increments closed at or before the condition creation time.
01868               // These increments are not supposed to know about this condition.
01869 
01870                 if( increment.end <= theConditionH->created( )) {
01871                     if( verboseModeFlag ) {
01872                         cout << "skipping the increment=" << i << " since it was" << endl
01873                          << "    ended before the condition was created." << endl
01874                          << "    CONDITION CREATED: " << theConditionH->created( ) << endl
01875                          << "    PARTITION CLOSED : " << increment.end << endl;
01876                     }
01877                     continue;
01878                 }
01879 
01880               // Find out the input "MetaData" object
01881 
01882                 BdbHandle(CdbBdbSMetaDataP) mdH;
01883                 {
01884                     BdbRef(CdbBdbSMetaDataP) mdRef;
01885                     if( CdbStatus::Success != ( result = CdbBdbSUtils::findMetaData( mdRef,
01886                                                                                      theConditionH->id( ),
01887                                                                                      theConditionH->isPartitionable( ),
01888                                                                                      partitionId,
01889                                                                                      clusterH->id( ),
01890                                                                                      i,
01891                                                                                      dbidRangeName ))) {
01892                         cerr << errorStr << endl
01893                              << "    Failed to find the metadata object for condition \"" << theConditionH->name( ) << "\"." << endl
01894                              << "    See details above." << endl;
01895                         return result;
01896                     }
01897                     mdH = mdRef;
01898                 }
01899 
01900               // Open the output database name for that <partition_owner_origin>-<cluster>-<partition>-<increment>.
01901               //
01902               // NOTE: The database file is open in the "update" mode, not "recreate". Otherwise
01903               //       we would destroy its previous contents.
01904 
01905                 const CdbCPtr<TFile> databaseFilePtr = openMetadataDatabase( partitionH->originId( ),
01906                                                                              clusterH->id( ),
01907                                                                              partitionH->id( ),
01908                                                                              i,
01909                                                                              theConditionH->isPartitionable( ));
01910                 if( databaseFilePtr.isNull( )) return CdbStatus::Error;
01911 
01912               // Convert the object
01913 
01914                 if( CdbStatus::Success != ( result = ::convertMetaData( databaseFilePtr,
01915                                                                         mdH,
01916                                                                         partitionH->originId( ),
01917                                                                         theConditionH->id( ),
01918                                                                         clusterH->id( ),
01919                                                                         theConditionH->isPartitionable( ),
01920                                                                         partitionId,
01921                                                                         i,
01922                                                                         theOutRegistryDescriptor ))) {
01923                     cerr << errorStr << endl
01924                          << "    Failed to translate the metadata object for condition \"" << theConditionH->name( ) << "\"." << endl
01925                          << "    See details above." << endl;
01926                     return result;
01927                 }
01928             }
01929         }
01930         return CdbStatus::Success;
01931     }
01932 
01933     CdbStatus
01934     convertMetaData( const CdbCPtr<TFile>&              theFilePtr,
01935                      const BdbHandle(CdbBdbSMetaDataP)& theInMetaDataH,
01936                      UShort_t                           theOriginId,
01937                      UShort_t                           theConditionId,
01938                      UShort_t                           theClusterId,
01939                      bool                               isPartitionableFlag,
01940                      UShort_t                           thePartitionId,
01941                      UShort_t                           theIncrementId,
01942                      const CdbRooRoRegistryDescriptorR& theOutRegistryDescriptor )
01943     {
01944         const char* errorStr = "::convertMetaData() - ERROR.";
01945 
01946         assert( !BdbIsNull(theInMetaDataH));
01947 
01948         CdbStatus result = CdbStatus::Error;
01949 
01950       // Translate the collection of 'original intervals
01951 
01952         CdbRooRoOiCollectionR originalCollection;
01953         if( CdbStatus::Success != ( result = ::translateOriginalCollection( originalCollection,
01954                                                                             theInMetaDataH->originaIntervalsCollection( ),
01955                                                                             theOriginId,
01956                                                                             theConditionId,
01957                                                                             theClusterId,
01958                                                                             isPartitionableFlag,
01959                                                                             thePartitionId,
01960                                                                             theIncrementId ))) {
01961             cerr << errorStr << endl
01962                  << "    Failed to translate a collection of the 'original' intervals." << endl;
01963             return result;
01964         }
01965 
01966       // Iterate over known revisions and translate them into a collection of revisions
01967 
01968         CdbRooRoRevCollectionR revisionCollection;
01969         {
01970             CdbItr<BdbTime> itr;
01971             if( CdbStatus::Success != ( result = theInMetaDataH->revisionIdIterator( itr ))) {
01972                 cerr << errorStr << endl
01973                      << "    Failed to set up an iterator of revision identifiers." << endl;
01974                 return result;
01975             }
01976             while( itr.next( )) {
01977 
01978                 BdbTime revisionId = itr.value( );
01979 
01980               // Find the input revision
01981 
01982                 BdbHandle(CdbBdbSRevisionP) theInRevisionH;
01983                 {
01984                     BdbRef(CdbBdbSRevisionP) revisionRef;
01985                     if( CdbStatus::Success != ( result = theInMetaDataH->findRevision( revisionId,
01986                                                                                        revisionRef ))) {
01987                         cerr << errorStr << endl
01988                             << "    Failed to find a revision with ID = " << CdbTimeUtils::time2string( revisionId ) << endl;
01989                         return result;
01990                     }
01991                     theInRevisionH = revisionRef;
01992                 }
01993 
01994               // Translate the revision
01995 
01996                 CdbRooRoRevisionR revision;
01997                 if( CdbStatus::Success != ( result = ::translateRevision( revision,
01998                                                                           theInRevisionH ))) {
01999                     cerr << errorStr << endl
02000                          << "    Failed to translate a revision with ID = " << CdbTimeUtils::time2string( revisionId ) << endl;
02001                     return result;
02002                 }
02003 
02004               // Put it into the output collection of revisions
02005 
02006                 if( CdbStatus::Success != ( result = revisionCollection.insert( revision ))) {
02007                     cerr << errorStr << endl
02008                          << "    Failed to insert a revision with ID = " << CdbTimeUtils::time2string( revisionId ) << endl
02009                          << "    into the output collection." << endl;
02010                     return result;
02011                 }
02012             }
02013         }
02014 
02015       // Create the output MetaData object
02016 
02017         CdbRooRoMetaDataR metadata( theInMetaDataH->minValidity( ),
02018                                     theInMetaDataH->maxValidity( ),
02019                                     theInMetaDataH->minInsertion( ),
02020                                     theInMetaDataH->maxInsertion( ),
02021                                     theInMetaDataH->modified( ),
02022                                     originalCollection,
02023                                     revisionCollection );
02024 
02025         if( verboseModeFlag ) {
02026             cout << endl;
02027             metadata.dump( cout );
02028             cout << endl;
02029         }
02030 
02031       // Build the name of a persistent object for the "MetaData" and store it
02032 
02033         {
02034             const std::string persistentObjectName =
02035                 CdbRooRoFileUtils::nameOfMetaDataContainer( theConditionId,
02036                                                             isPartitionableFlag,
02037                                                             thePartitionId,
02038                                                             theClusterId,
02039                                                             theIncrementId,
02040                                                             theOriginId );
02041 
02042             Int_t bytesWritten = 0;
02043 
02044             theFilePtr->Cd( "" );
02045             gDirectory->Cd( theFilePtr->GetPath( ));
02046 
02047             CdbRooRoCollectionAddressR collectionAddress;
02048             {
02049                 if( isPartitionableFlag ) {
02050                     collectionAddress = CdbRooRoCollectionAddressR::createPartitionable( persistentObjectName,
02051                                                                                          theOriginId,
02052                                                                                          theClusterId,
02053                                                                                          thePartitionId,
02054                                                                                          theIncrementId );
02055                 } else {
02056                     collectionAddress = CdbRooRoCollectionAddressR::createRegular( persistentObjectName,
02057                                                                                    theOriginId,
02058                                                                                    theClusterId,
02059                                                                                    theIncrementId );
02060                 }
02061             }
02062             if( CdbStatus::Success != metadata.storeAt( collectionAddress,
02063                                                         theFilePtr,
02064                                                         bytesWritten )) {
02065                 cerr << errorStr << endl
02066                      << "    New object couldn't be written." << endl
02067                      << "    Perhaps it's not been properly instrumented for the streaming." << endl;
02068                 return CdbStatus::Error;
02069             }
02070             cout << theFilePtr->GetName( ) << "::" << theOutRegistryDescriptor.originName( ) << "::" << persistentObjectName << " ** " << bytesWritten << " bytes written **" << endl;
02071         }
02072         return CdbStatus::Success;
02073     }
02074 
02075   // A generator of locations of ID-s for user-defined "payload".
02076   //
02077   // The corresponding objects will be produced during the second path of the conversion
02078   // run by users.
02079   //
02080   // GENERATOR DESCRIPTION:
02081   //
02082   //   1. Containers may only have objects of the same (final) persistent type.
02083   //
02084   //      1.1 It's assumed that there is one-to-one correspondance between Objectivity/DB
02085   //          and ROOT I/O persistent classes.
02086   //
02087   //      1.2 The object index varies from 0 up to 0xFFFE.
02088   //
02089   //   2. When a container is full then a new one gets allocated.
02090   //
02091   //   3. There is a variable with an ID of the "next available (for allocation) container"
02092   //      It gets incremented every time a new container is allocated.
02093   //
02094   //   4. There is a map with the current mapping from an input class name onto a pair
02095   //      of the currently allocated (for the class) container and the last index used
02096   //      of an output "payload" object "stored" (the one which would be actually stored
02097   //      during the second phase of the conversion).
02098   //
02099   //      4.1 The object index varies from 0 up to 0xFFFE.
02100   //
02101   //   5. When no more containers is available then the current function will
02102   //      exit with the error status.
02103   //
02104   // The class defined below assists in producing the location information for
02105   // objects given their class names as keys. The class is implemented as an iterator
02106   // with an internal state to be used in the right context.
02107   //
02108   // Here is how it should be used:
02109   //
02110   //    LocationGenerator generator;
02111   //
02112   //    if( !generator.tryNextFor( )) {
02113   //        cerr << "error: an overflow in the current conditions. Not able to store" << endl
02114   //             << "       more than 2^32 objects." << endl;
02115   //        ...
02116   //    }
02117   //    UShort_t currentContainer   = generator.container( );
02118   //    UShort_t currentObjectIndex = generator.index    ( );
02119   //    ..
02120   //
02121   // USAGE NOTES:
02122   //
02123   //    1. If no single call to the "LocationGenerator::tryNextFor()" method is made
02124   //       then the current context would be invalid.
02125   //
02126   //    2. Each successfull call to the "LocationGenerator::tryNextFor()" would setup
02127   //       proper context for the specified value of the key. Obviously, this value
02128   //       can't be used for other purposes.
02129   //
02130   //    3. If the "LocationGenerator::tryNextFor()" returns "false" then the current
02131   //       context of the generator object gets invalid.
02132   //
02133 
02134     struct Location {
02135 
02136         Location( UShort_t theCurrentContainerId = 0xFFFF,
02137                   UShort_t theCurrentObjectIndex = 0xFFFF) :
02138             container(theCurrentContainerId),
02139             index    (theCurrentObjectIndex)
02140         { }
02141 
02142         UShort_t container;
02143         UShort_t index;
02144     };
02145 
02146     class LocationGenerator {
02147 
02148     public:
02149 
02150         LocationGenerator( ) :
02151             _nextContainerId (0),
02152             _currentContainer(0xFFFF),
02153             _currentIndex    (0xFFFF)
02154         { }
02155 
02156         bool tryNextFor( const std::string& theKey )
02157         {
02158             std::map< std::string, ::Location >::iterator itr = _locations.find( theKey );
02159             if( itr == _locations.end( )) {
02160 
02161               // New key passed
02162 
02163                 _currentContainer = _nextContainerId;
02164                 _currentIndex     = 0;
02165 
02166                 if( _currentContainer == 0xFFFF ) {
02167                     _currentIndex = 0xFFFF;
02168                     return false;
02169                 }
02170                 _locations[theKey] = ::Location( _currentContainer,
02171                                                  _currentIndex );
02172 
02173               // Give up one more container from the pool of spare ones. We're going to check
02174               // it on the next invocation of the current method if we've run out of containers.
02175 
02176                 ++_nextContainerId;
02177 
02178             } else {
02179 
02180               // This key is already known
02181 
02182                 ::Location location = (*itr).second;    // reuse the found value to save one lookup operation with map
02183 
02184                 _currentContainer = location.container;
02185                 _currentIndex     = ++location.index;
02186 
02187                 if( location.index == 0xFFFF ) {
02188 
02189                   // Remove the key from the map and do all over again as if the key
02190                   // never existed (which would be absolutelly correct since a particular
02191                   // value of the key is associated with a container.
02192 
02193                     _locations.erase( theKey );
02194 
02195                     return tryNextFor( theKey );
02196                 }
02197 
02198               // Update the map
02199 
02200                 _locations[theKey] = location;
02201 
02202             }
02203             return true;
02204         }
02205 
02206         UShort_t container( ) const { return _currentContainer; }
02207         UShort_t index    ( ) const { return _currentIndex;     }
02208 
02209     private:
02210 
02211         UShort_t _nextContainerId;      // next available container identifier
02212 
02213         std::map< std::string, ::Location > _locations;     // the current mapping for recently used keys
02214 
02215         UShort_t _currentContainer;     // a cached value for the recently used key
02216         UShort_t _currentIndex;         // a cached value for the recently used key
02217     };
02218 
02219     CdbStatus
02220     translateOriginalCollection( CdbRooRoOiCollectionR&                 theOutCollection,
02221                                  const BdbHandle(CdbBdbSOiCollectionP)& theInCollectionH,
02222                                  UShort_t                               theOriginId,
02223                                  UShort_t                               theConditionId,
02224                                  UShort_t                               theClusterId,
02225                                  bool                                   isPartitionableFlag,
02226                                  UShort_t                               thePartitionId,
02227                                  UShort_t                               theIncrementId )
02228     {
02229         const char* errorStr = "::translateOriginalCollection() - ERROR.";
02230 
02231         assert( !BdbIsNull(theInCollectionH));
02232 
02233         CdbStatus result = CdbStatus::Error;
02234 
02235       // Prepare a generator of output object ID-s for user-defined "payload".
02236 
02237         ::LocationGenerator objectLocationGenerator;
02238 
02239       // Scan the input collection and fill a vector of intervals to be used
02240       // to initialize the output collection.
02241 
02242         std::vector< CdbRooRoOiR > vectorOfIntervals;
02243         {
02244             d_ULong numOriginalElements = theInCollectionH->size( );
02245 
02246             for( d_ULong idx = 1; idx < numOriginalElements; ++ idx ) {
02247 
02248                 CdbBdbSOi oi;
02249 
02250                 BdbTime beginDuration;  // will be filled by the call, but we're not going to use it
02251                 BdbTime endDuration;    // -//-
02252 
02253                 if( CdbStatus::Success != ( result = theInCollectionH->find( idx,
02254                                                                              oi,
02255                                                                              beginDuration,
02256                                                                              endDuration ))) {
02257                     cerr << errorStr << endl
02258                          << "    Failed to obtain an 'original' interval with IDX = " << idx << " from the collection." << endl;
02259                     return result;
02260                 }
02261 
02262               // Create an output "original" object initialized with a preallocated ID of
02263               // a "payload" object. The corresponding object will be produced and stored
02264               // in the suggested (by ID) location during the second phase of the conversion.
02265 
02266                 if( !objectLocationGenerator.tryNextFor( oi.object.typeName( ))) {
02267 
02268                     cerr << errorStr << endl
02269                          << "   An overflow in the current condition. The current implementation of" << endl
02270                          << "   the conversion procedure doesn't allo storing more than 2^32 'original'" << endl
02271                          << "   objects per MetaData." << endl
02272                          << "       ORIGIN ID        : " << theOriginId << endl
02273                          << "       CONDITION ID     : " << theConditionId << endl
02274                          << "       CLUSTER ID       : " << theClusterId << endl
02275                          << "       IS PARTITIONABLE : " << ( isPartitionableFlag ? "Yes" : "No" ) << endl
02276                          << "       PARTITION        : " << thePartitionId << endl
02277                          << "       INCREMENT        : " << theIncrementId << endl;
02278 
02279                     return CdbStatus::Error;
02280                 }
02281 
02282                 CdbRooRoObjectIdR outputPersistentObjectId;
02283                 if( isPartitionableFlag ) {
02284                     outputPersistentObjectId = CdbRooRoObjectIdR::createPartitionable( theOriginId,
02285                                                                                        theConditionId,
02286                                                                                        theClusterId,
02287                                                                                        thePartitionId,
02288                                                                                        theIncrementId,
02289                                                                                        objectLocationGenerator.container( ),
02290                                                                                        objectLocationGenerator.index    ( ));
02291                 } else {
02292                     outputPersistentObjectId = CdbRooRoObjectIdR::createRegular( theOriginId,
02293                                                                                  theConditionId,
02294                                                                                  theClusterId,
02295                                                                                  theIncrementId,
02296                                                                                  objectLocationGenerator.container( ),
02297                                                                                  objectLocationGenerator.index    ( ));
02298                 }
02299                 vectorOfIntervals.push_back( CdbRooRoOiR( oi.begin,
02300                                                           oi.end,
02301                                                           oi.inserted,
02302                                                           outputPersistentObjectId,
02303                                                           oi.object.sprint( )));
02304             }
02305         }
02306 
02307       // Create the output collection object
02308 
02309         theOutCollection = CdbRooRoOiCollectionR( vectorOfIntervals );
02310 
02311         if( verboseModeFlag ) {
02312             cout << endl;
02313             theOutCollection.dump( cout );
02314             cout << endl;
02315         }
02316         return CdbStatus::Success;
02317     }
02318 
02319     CdbStatus
02320     translateRevision( CdbRooRoRevisionR&                 theOutRevision,
02321                        const BdbHandle(CdbBdbSRevisionP)& theInRevisionH )
02322     {
02323         const char* errorStr = "::translateRevision() - ERROR.";
02324 
02325         assert( !BdbIsNull(theInRevisionH));
02326 
02327         CdbStatus result = CdbStatus::Error;
02328 
02329       // Get the collection of 'visible' intervals
02330 
02331         BdbHandle(CdbBdbSViCollectionP) viCollectionH = theInRevisionH->collection( );
02332         assert( !BdbIsNull(viCollectionH));
02333 
02334       // Scan the input collection and fill an output collection of 'visible' intervals
02335       // to be used to initialize the output revision.
02336 
02337         CdbRooRoViCollectionR viCollection;
02338         {
02339             CdbBdbSViCollectionP::IteratorOfIntervals itr = viCollectionH->iterator( );
02340             while( itr.next( )) {
02341 
02342                 CdbBdbSVi iVal = itr.value( );
02343 
02344                 if( CdbStatus::Success != ( result = viCollection.insert( CdbRooRoViR( iVal.value,
02345                                                                                        iVal.begin,
02346                                                                                        iVal.end )))) {
02347                     cerr << errorStr << endl
02348                          << "    Failed to insert an interval into the collection." << endl;
02349                     return result;
02350                 }
02351             }
02352         }
02353 
02354       // Create the output revision object
02355 
02356         theOutRevision = CdbRooRoRevisionR( theInRevisionH->id( ),
02357                                             theInRevisionH->name( ).head( ),
02358                                             viCollection,
02359                                             theInRevisionH->created( ),
02360                                             theInRevisionH->description( ).head( ));
02361         if( verboseModeFlag ) {
02362             cout << endl;
02363             theOutRevision.dump( cout );
02364             cout << endl;
02365         }
02366         return CdbStatus::Success;
02367     }
02368 
02369     CdbStatus
02370     printPersistentClasses( )
02371     {
02372         const char* errorStr = "::printPersistentClasses() - ERROR.";
02373 
02374         CdbStatus result = CdbStatus::Error;
02375 
02376       // Get the MASTER registry.
02377 
02378         BdbHandle(CdbBdbSRegistryP) masterRegistryH;
02379         if( CdbStatus::Success != ( result = CdbBdbSRegistryP::findMaster( masterRegistryH ))) {
02380             cerr << errorStr << endl
02381                  << "    Failed to find the MASTER registry." << endl;
02382             return result;
02383         }
02384 
02385       // Iterate over known registries and analyses them one-by-one if the corresponding origins
02386       // are instantiated in the input database.
02387 
02388         BdbHandle(CdbBdbSOriginCollectionP) originCollectionH = masterRegistryH->originCollection( );
02389 
02390         CdbBdbSOriginCollectionP::IteratorOfIdentifiers itr = originCollectionH->iterator_identifiers( );
02391         while( itr.next( )) {
02392 
02393           // Get the persistent registry object
02394 
02395             d_UShort conditionOwnerOriginId = itr.value( );
02396 
02397             BdbHandle(CdbBdbSOriginP) originH;
02398             {
02399                 BdbRef(CdbBdbSOriginP) originRef;
02400                 if( CdbStatus::Success != ( result = originCollectionH->find( conditionOwnerOriginId,
02401                                                                               originRef ))) {
02402 
02403                     cerr << errorStr << endl
02404                          << "    Failed to find an origin with ID = " << conditionOwnerOriginId << "." << endl
02405                          << "    The input database may not be properly initialized." << endl;
02406                     return result;
02407                 }
02408                 originH = originRef;
02409             }
02410 
02411           // Try to get the corresponding registry. If it doesn't exist (not instantiated)
02412           // then we will skip that registry.
02413 
02414             BdbHandle(CdbBdbSRegistryP) registryH;
02415             {
02416                 if( CdbStatus::Success != ( result = CdbBdbSRegistryP::findByOrigin( registryH,
02417                                                                                      conditionOwnerOriginId ))) {
02418                     if( CdbStatus::NotFound == result ) {
02419 
02420                       // The origin is not currently instantiated in the input database. This may happen
02421                       // when the origin's data are yet to be imported.
02422 
02423                         continue;
02424 
02425                     } else {
02426                         cerr << errorStr << endl
02427                              << "    Failed to find a registry for origin ID = " << conditionOwnerOriginId << "." << endl;
02428                         return result;
02429                     }
02430                 }
02431             }
02432 
02433           // Proceed to 'physical' conditions of the collection
02434 
02435             if( registryH->hasLocalCollections( )) {
02436 
02437                 BdbHandle(CdbBdbSConditionCollectionP) conditionCollectionH = registryH->conditionCollection( );
02438 
02439                 CdbBdbSConditionCollectionP::IteratorOfIdentifiers itr = conditionCollectionH->iterator_identifiers( );
02440                 while( itr.next( )) {
02441 
02442                   // Get the input condition
02443 
02444                     d_UShort conditionId = itr.value( );
02445 
02446                     BdbHandle(CdbBdbSConditionP) conditionH;
02447                     {
02448                         BdbRef(CdbBdbSConditionP) conditionRef;
02449                         if( CdbStatus::Success != ( result = conditionCollectionH->find( conditionId,
02450                                                                                          conditionRef ))) {
02451                             cerr << errorStr << endl
02452                                  << "    A condition with ID = " << conditionId << " was not found." << endl;
02453                             return result;
02454                         }
02455                         conditionH = conditionRef;
02456                     }
02457 
02458                   // Find all relevant MetaData objects
02459 
02460                     if( conditionH->isPartitionable( )) {
02461 
02462                       // ** PARTITIONABLE **
02463 
02464                         if( excludePartitionableFlag ) continue;
02465 
02466                         BdbHandle(CdbBdbSSimpleClusterP) clusterH = (const BdbRef(CdbBdbSSimpleClusterP)&)conditionH->cluster( );
02467 
02468                       // Get to the PartitinLayout at MASTER's Registry and iterate over
02469                       // _instantiated_ partitions only.
02470 
02471                         BdbHandle(CdbBdbSPartitionsLayoutP) pLayoutH = masterRegistryH->partitionsLayout( );
02472 
02473                         CdbItr< d_UShort > pItr = pLayoutH->iterator( );
02474                         while( pItr.next( )) {
02475 
02476                             d_UShort partitionId = pItr.value( );
02477 
02478                             BdbHandle( CdbBdbSPartitionP ) partitionH;
02479                             {
02480                                 BdbRef( CdbBdbSPartitionP ) partitionRef;
02481                                 if( CdbStatus::Success != ( result = pLayoutH->find( partitionId,
02482                                                                                      partitionRef ))) {
02483                                     cerr << errorStr << endl
02484                                          << "   Failed to find the partition corresponding to ID=" << partitionId << endl;
02485                                     return result;
02486                                 }
02487                                 partitionH = partitionRef;
02488                             }
02489 
02490                           // Skip this partition if it's not instantiated yet or if it's closed at the time
02491                           // of before the current condition was created.
02492 
02493                             if( !partitionH->isInstantiated( )) continue;
02494                             if( partitionH->isClosed( ) && ( partitionH->cell( ).endInsertion <= conditionH->created( ))) continue;
02495 
02496                           // Get the DBID range of the partition's orgin.
02497 
02498                             std::string dbidRangeName;
02499                             {
02500                                 BdbRef(CdbBdbSOriginP) originRef;
02501                                 if( CdbStatus::Success != ( result = masterRegistryH->originCollection( )->find( partitionH->originId( ),
02502                                                                                                                  originRef ))) {
02503                                     cerr << errorStr << endl
02504                                          << "    An origin with ID=" << partitionH->originId( ) << " was not found." << endl;
02505                                     return result;
02506                                 }
02507                                 dbidRangeName = originRef->dbidrange( ).head( );
02508                             }
02509 
02510                           //  Browse through increments
02511 
02512                             d_ULong numIncrements = partitionH->numIncrements( );
02513                             for( d_ULong i = 0; i < numIncrements; ++i ) {
02514 
02515                                 CdbBdbSIncrement increment;
02516                                 if( CdbStatus::Success != ( result = partitionH->increment( i,
02517                                                                                             increment ))) {
02518                                     cerr << errorStr << endl
02519                                          << "    Failed to get increment " << i << " from partition " << partitionId << endl
02520                                          << "    of condition \"" << conditionH->name( ) << "\"" << endl;
02521                                     return result;
02522                                 }
02523 
02524                               // Skip increments closed at or before the condition creation time.
02525                               // These increments are not supposed to know about this condition.
02526 
02527                                 if( increment.end <= conditionH->created( )) continue;
02528 
02529                               // Find out the input "MetaData" object
02530 
02531                                 BdbHandle(CdbBdbSMetaDataP) mdH;
02532                                 {
02533                                     BdbRef(CdbBdbSMetaDataP) mdRef;
02534                                     if( CdbStatus::Success != ( result = CdbBdbSUtils::findMetaData( mdRef,
02535                                                                                                      conditionH->id( ),
02536                                                                                                      conditionH->isPartitionable( ),
02537                                                                                                      partitionId,
02538                                                                                                      clusterH->id( ),
02539                                                                                                      i,
02540                                                                                                      dbidRangeName ))) {
02541                                         cerr << errorStr << endl
02542                                              << "    Failed to find the metadata object for condition \"" << conditionH->name( ) << "\"." << endl
02543                                              << "    See details above." << endl;
02544                                         return result;
02545                                     }
02546                                     mdH = mdRef;
02547                                 }
02548 
02549                               // Browse the 'original' collection
02550 
02551                                 std::map<std::string,unsigned int> counters;
02552 
02553                                 const BdbHandle(CdbBdbSOiCollectionP) collectionH = mdH->originaIntervalsCollection( );
02554 
02555                                 d_ULong numOriginalElements = collectionH->size( );
02556 
02557                                 for( d_ULong idx = 1; idx < numOriginalElements; ++idx ) {
02558 
02559                                     CdbBdbSOi oi;
02560 
02561                                     BdbTime beginDuration;  // will be filled by the call, but we're not going to use it
02562                                     BdbTime endDuration;    // -//-
02563 
02564                                     if( CdbStatus::Success != ( result = collectionH->find( idx,
02565                                                                                             oi,
02566                                                                                             beginDuration,
02567                                                                                             endDuration ))) {
02568                                         cerr << errorStr << endl
02569                                              << "    Failed to obtain an 'original' interval with IDX = " << idx << " from the collection." << endl;
02570                                         return result;
02571                                     }
02572 
02573                                     std::string typeName = oi.object.typeName( );
02574 
02575                                     unsigned int nObjectsOfThisClass = 0;
02576                                     if( 0 != counters.count( typeName )) nObjectsOfThisClass = counters[ typeName ];
02577                                     counters[ typeName ] = ++nObjectsOfThisClass;
02578                                 }
02579 
02580                               // Print results
02581 
02582                                 for( std::map<std::string,unsigned int>::const_iterator itr = counters.begin( );
02583                                                                                         itr != counters.end( );
02584                                                                                       ++itr ) {
02585                                     std::string typeName = (*itr).first;
02586                                     unsigned int nObjectsOfThisClass = (*itr).second;
02587                                     cout << conditionOwnerOriginId << "::" << conditionH->id( ) << " [" << partitionH->id( ) << "," << clusterH->id( ) << "," << i << "] \"" << typeName << "\" " << nObjectsOfThisClass << endl;
02588                                 }
02589                             }
02590                         }
02591 
02592                     } else {
02593 
02594                       // ** REGULAR **
02595 
02596                         if( excludeRegularFlag ) continue;
02597 
02598                       // Get the DBID range of the condition's origin.
02599 
02600                         std::string dbidRangeName;
02601                         {
02602                             BdbRef(CdbBdbSOriginP) originRef;
02603                             if( CdbStatus::Success != ( result = masterRegistryH->originCollection( )->find( conditionOwnerOriginId,
02604                                                                                                              originRef ))) {
02605                                 cerr << errorStr << endl
02606                                      << "    An origin with ID=" << conditionOwnerOriginId << " was not found." << endl;
02607                                 return result;
02608                             }
02609                             dbidRangeName = originRef->dbidrange( ).head( );
02610                         }
02611 
02612                       // Browse through increments of a cluster the condition is a member of. Select only
02613                       // those increments the condition is participating in.
02614                       //
02615                       // NOTE: The condition might be creaed after certain increments were already
02616                       //       closed. That's why we shoul skip those ones closed before.
02617 
02618                         BdbHandle(CdbBdbSSimpleClusterP) clusterH = (const BdbRef(CdbBdbSSimpleClusterP)&)conditionH->cluster( );
02619 
02620                         d_ULong numIncrements = clusterH->numIncrements( );
02621                         for( d_ULong i = 0; i < numIncrements; ++i ) {
02622 
02623                             CdbBdbSIncrement increment;
02624                             if( CdbStatus::Success != ( result = clusterH->increment( i,
02625                                                                                       increment ))) {
02626                                 cerr << errorStr << endl
02627                                      << "    Failed to get increment " << i << " from cluster " << clusterH->id( ) << endl
02628                                      << "    of condition \"" << conditionH->name( ) << "\"" << endl;
02629                                 return result;
02630                             }
02631 
02632                           // Skip increments closed at or before the condition creation time.
02633                           // These increments are not supposed to know about this condition.
02634 
02635                             if( increment.end <= conditionH->created( )) continue;
02636 
02637                           // Find out the input "MetaData" object
02638 
02639                             BdbHandle(CdbBdbSMetaDataP) mdH;
02640                             {
02641                                 BdbRef(CdbBdbSMetaDataP) mdRef;
02642                                 if( CdbStatus::Success != ( result = CdbBdbSUtils::findMetaData( mdRef,
02643                                                                                                  conditionH->id( ),
02644                                                                                                  conditionH->isPartitionable( ),
02645                                                                                                  0,
02646                                                                                                  clusterH->id( ),
02647                                                                                                  i,
02648                                                                                                  dbidRangeName.c_str( )))) {
02649                                     cerr << errorStr << endl
02650                                          << "    Failed to find the metadata object for condition \"" << conditionH->name( ) << "\"." << endl
02651                                          << "    See details above." << endl;
02652                                     return result;
02653                                 }
02654                                 mdH = mdRef;
02655                             }
02656 
02657                           // Browse the 'original' collection
02658 
02659                             std::map<std::string,unsigned int> counters;
02660 
02661                             const BdbHandle(CdbBdbSOiCollectionP) collectionH = mdH->originaIntervalsCollection( );
02662 
02663                             d_ULong numOriginalElements = collectionH->size( );
02664 
02665                             for( d_ULong idx = 1; idx < numOriginalElements; ++idx ) {
02666 
02667                                 CdbBdbSOi oi;
02668 
02669                                 BdbTime beginDuration;  // will be filled by the call, but we're not going to use it
02670                                 BdbTime endDuration;    // -//-
02671 
02672                                 if( CdbStatus::Success != ( result = collectionH->find( idx,
02673                                                                                         oi,
02674                                                                                         beginDuration,
02675                                                                                         endDuration ))) {
02676                                     cerr << errorStr << endl
02677                                          << "    Failed to obtain an 'original' interval with IDX = " << idx << " from the collection." << endl;
02678                                     return result;
02679                                 }
02680 
02681                                 std::string typeName = oi.object.typeName( );
02682 
02683                                 unsigned int nObjectsOfThisClass = 0;
02684                                 if( 0 != counters.count( typeName )) nObjectsOfThisClass = counters[ typeName ];
02685                                 counters[ typeName ] = ++nObjectsOfThisClass;
02686                             }
02687 
02688                           // Print results
02689 
02690                             for( std::map<std::string,unsigned int>::const_iterator itr = counters.begin( );
02691                                                                                     itr != counters.end( );
02692                                                                                   ++itr ) {
02693                                 std::string typeName = (*itr).first;
02694                                 unsigned int nObjectsOfThisClass = (*itr).second;
02695                                 cout << conditionOwnerOriginId << "::" << conditionH->id( ) << " [" << 0 << "," << clusterH->id( ) << "," << i << "] \"" << typeName << "\" " << nObjectsOfThisClass << endl;
02696                             }
02697                         }
02698                     }
02699                 }
02700             }
02701         }
02702         return CdbStatus::Success;
02703     }
02704 
02705     CdbStatus
02706     browseConditionsInFolder( d_UShort                      theOriginId,
02707                               d_UShort                      theViewId,
02708                               const CdbPathName&            theParentFolderPath,
02709                               const BdbRef(CdbBdbSFolderP)& theParentFolderRef  )
02710     {
02711         const char* errorStr = "::browseConditionsInFolder() - ERROR.";
02712 
02713         assert( theParentFolderPath.isAbsolute( ));
02714         assert( !BdbIsNull(theParentFolderRef));
02715 
02716         const BdbHandle(CdbBdbSFolderP) parentFolderH = theParentFolderRef;
02717 
02718         CdbStatus result = CdbStatus::Error;
02719 
02720       // Find all conditions directly attached to the parent folder
02721 
02722         {
02723             CdbItr< const char* > itr;
02724             if( CdbStatus::Success != ( result = parentFolderH->conditionIterator( itr ))) {
02725                 cerr << errorStr << endl
02726                      << "    Failed to set up an iterator of conditions for folder \"" << theParentFolderPath.toString( ) << "\"." << endl;
02727                 return result;
02728             }
02729             while( itr.next( )) {
02730 
02731                 CdbPathName conditionPath( itr.value( ));
02732 
02733                 BdbRef(CdbBdbSConditionAtFolderP) conditionRef;
02734                 if( CdbStatus::Success != ( result = parentFolderH->findCondition( conditionPath,
02735                                                                                    conditionRef ))) {
02736                     cerr << errorStr << endl
02737                          << "    Failed to find the condition \"" <<  conditionPath.toString( ) << "\"" << endl
02738                          << "    in folder \"" << theParentFolderPath.toString( ) << "\"." << endl;
02739                     return result;
02740                 }
02741 
02742                 CdbBdbSId   id                = conditionRef->id( );
02743                 CdbPathName conditionFullPath = theParentFolderPath + conditionPath;
02744 
02745                 cout << theOriginId << "::" << theViewId << " " << id.origin << "::" << id.local << " \"" << conditionFullPath.toString( ) << "\"" << endl;
02746             }
02747         }
02748 
02749       // Find all sub-folders directly attached to the parent folder and proceed to them
02750 
02751         {
02752             CdbItr< const char* > itr;
02753             if( CdbStatus::Success != ( result = parentFolderH->folderIterator( itr ))) {
02754                 cerr << errorStr << endl
02755                      << "    Failed to set up an iterator of sub-folders for folder \"" << theParentFolderPath.toString( ) << "\"." << endl;
02756                 return result;
02757             }
02758             while( itr.next( )) {
02759 
02760                 CdbPathName folderPath( itr.value( ));
02761 
02762                 BdbRef(CdbBdbSFolderP) folderRef;
02763                 if( CdbStatus::Success != ( result = parentFolderH->findFolder( folderPath,
02764                                                                                 folderRef ))) {
02765                     cerr << errorStr << endl
02766                          << "    Failed to find the sub-folder \"" <<  folderPath.toString( ) << "\"" << endl
02767                          << "    in folder \"" << theParentFolderPath.toString( ) << "\"." << endl;
02768                     return result;
02769                 }
02770 
02771                 CdbPathName folderFullPath = theParentFolderPath + folderPath;
02772 
02773                 if( CdbStatus::Success != ( result = ::browseConditionsInFolder( theOriginId,
02774                                                                                  theViewId,
02775                                                                                  folderFullPath,
02776                                                                                  folderRef ))) {
02777                     cerr << errorStr << endl
02778                          << "    Failed to browse conditions in the sub-folder \"" <<  folderPath.toString( ) << "\"" << endl
02779                          << "    of folder \"" << theParentFolderPath.toString( ) << "\"." << endl;
02780                     return result;
02781                 }
02782             }
02783         }
02784         return CdbStatus::Success;
02785     }
02786 
02787     CdbStatus
02788     printPersistentConditions( )
02789     {
02790         const char* errorStr = "::printPersistentConditions() - ERROR.";
02791 
02792         CdbStatus result = CdbStatus::Error;
02793 
02794       // Get the MASTER registry.
02795 
02796         BdbHandle(CdbBdbSRegistryP) masterRegistryH;
02797         if( CdbStatus::Success != ( result = CdbBdbSRegistryP::findMaster( masterRegistryH ))) {
02798             cerr << errorStr << endl
02799                  << "    Failed to find the MASTER registry." << endl;
02800             return result;
02801         }
02802 
02803       // Iterate over known registries and analyses them one-by-one if the corresponding origins
02804       // are instantiated in the input database.
02805 
02806         BdbHandle(CdbBdbSOriginCollectionP) originCollectionH = masterRegistryH->originCollection( );
02807 
02808         CdbBdbSOriginCollectionP::IteratorOfIdentifiers itr = originCollectionH->iterator_identifiers( );
02809         while( itr.next( )) {
02810 
02811           // Get the persistent registry object
02812 
02813             d_UShort viewOwnerOriginId = itr.value( );
02814 
02815             BdbHandle(CdbBdbSOriginP) originH;
02816             {
02817                 BdbRef(CdbBdbSOriginP) originRef;
02818                 if( CdbStatus::Success != ( result = originCollectionH->find( viewOwnerOriginId,
02819                                                                               originRef ))) {
02820 
02821                     cerr << errorStr << endl
02822                          << "    Failed to find an origin with ID = " << viewOwnerOriginId << "." << endl
02823                          << "    The input database may not be properly initialized." << endl;
02824                     return result;
02825                 }
02826                 originH = originRef;
02827             }
02828 
02829           // Try to get the corresponding registry. If it doesn't exist (not instantiated)
02830           // then we will skip that registry.
02831 
02832             BdbHandle(CdbBdbSRegistryP) registryH;
02833             {
02834                 if( CdbStatus::Success != ( result = CdbBdbSRegistryP::findByOrigin( registryH,
02835                                                                                      viewOwnerOriginId ))) {
02836                     if( CdbStatus::NotFound == result ) {
02837 
02838                       // The origin is not currently instantiated in the input database. This may happen
02839                       // when the origin's data are yet to be imported.
02840 
02841                         continue;
02842 
02843                     } else {
02844                         cerr << errorStr << endl
02845                              << "    Failed to find a registry for origin ID = " << viewOwnerOriginId << "." << endl;
02846                         return result;
02847                     }
02848                 }
02849             }
02850 
02851           // Proceed to 'views' of this registry
02852 
02853             if( registryH->hasLocalCollections( )) {
02854 
02855                 BdbHandle(CdbBdbSViewCollectionP) viewCollectionH = registryH->viewCollection( );
02856 
02857                 CdbBdbSViewCollectionP::IteratorOfIdentifiers itr = viewCollectionH->iterator_identifiers( );
02858                 while( itr.next( )) {
02859 
02860                   // Get the view
02861 
02862                     d_UShort viewId = itr.value( );
02863 
02864                     BdbHandle(CdbBdbSViewP) viewH;
02865                     {
02866                         BdbRef(CdbBdbSViewP) viewRef;
02867                         if( CdbStatus::Success != ( result = viewCollectionH->find( viewId,
02868                                                                                     viewRef ))) {
02869                             cerr << errorStr << endl
02870                                  << "    A view with ID = " << viewId << " was not found." << endl;
02871                             return result;
02872                         }
02873                         viewH = viewRef;
02874                     }
02875 
02876                   // Skip the "main" view as it's not supposed to have any valueable information
02877 
02878                     if( std::string( "main" ) == viewH->name( )) continue;
02879 
02880                   // Browse the view
02881 
02882                     if( CdbStatus::Success != ( result = ::browseConditionsInFolder( viewOwnerOriginId,
02883                                                                                      viewId,
02884                                                                                      CdbPathName( viewH->rootFolder( )->name( ).head( )),
02885                                                                                      viewH->rootFolder( )))) {
02886                         cerr << errorStr << endl
02887                              << "    Failed to browse conditions in the 'root' folder of a view with ID = " << viewId << "." << endl;
02888                         return result;
02889                     }
02890                 }
02891             }
02892         }
02893         return CdbStatus::Success;
02894     }
02895 }
02896 
02897 /////////////////
02898 // End Of File //
02899 /////////////////

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