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

CdbBdb2RooPayloadConversionFwk.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbBdb2RooPayloadConversionFwk.cc,v 1.12 2005/11/11 02:07:41 gapon Exp $
00003 
00004 /// The implementation of the CdbBdb2RooPayloadConversionFwk class.
00005 /**
00006   * @see CdbBdb2RooPayloadConversionFwk
00007   */
00008 #include "BaBar/BaBar.hh"
00009 
00010 #include "CdbRooConversionFwk/CdbBdb2RooPayloadConversionFwk.hh"
00011 
00012 #include "CdbBase/CdbId.hh"
00013 #include "CdbBase/CdbDatabase.hh"
00014 #include "CdbBase/CdbOrigin.hh"
00015 #include "CdbBase/CdbPartition.hh"
00016 #include "CdbBase/CdbCondition.hh"
00017 #include "CdbBase/CdbTransaction.hh"
00018 #include "CdbBase/CdbStringUtils.hh"
00019 
00020 #include "BdbCond/BdbObject.hh"
00021 
00022 #include "CdbBdb/CdbBdbSchemaUtils.hh"
00023 
00024 #include "CdbBdbShared/CdbBdbShared.hh"
00025 
00026 #include "CdbRoo/CdbRooObjectR.hh"
00027 #include "CdbRoo/CdbRooObjectHasMovedR.hh"
00028 
00029 #include "CdbRooReadonly/CdbRooReadonly.hh"
00030 #include "CdbRooReadonly/CdbRooRoFileUtils.hh"
00031 #include "CdbRooReadonly/CdbRooRoMetaDataR.hh"
00032 #include "CdbRooReadonly/CdbRooRoOiCollectionR.hh"
00033 #include "CdbRooReadonly/CdbRooRoObjectIdR.hh"
00034 
00035 #include "CdbRooConversionFwk/CdbRooConverterBase.hh"
00036 #include "CdbRooConversionFwk/CdbBdb2RooPayloadConvertersDict.hh"
00037 #include "CdbRooConversionFwk/CdbRooConverterDict.hh"
00038 
00039 #include <stdio.h>  // sscanf(), sprintf()
00040 
00041 #include <TDirectory.h>
00042 #include <TTree.h>
00043 #include <TBranch.h>
00044 
00045 #include <string>
00046 #include <vector>
00047 #include <map>
00048 #include <iostream>
00049 using std::cin;
00050 using std::cout;
00051 using std::cerr;
00052 using std::endl;
00053 
00054 #include <fstream>
00055 using std::ifstream;
00056 
00057 #include <sstream>
00058 using std::ostringstream;
00059 
00060 #include "BbrStdUtils/Tokenize.hh"
00061 #include "BbrStdUtils/String.hh"
00062 using namespace babar::String;
00063 
00064 namespace {
00065 
00066   /// Convert a vector into a string
00067   /**
00068     * USE & PARAMETERS:
00069     *
00070     *     1. The converted values will be separated by a single space in an output string
00071     *
00072     *     2. The "<<" operator is expected to be available for the elements of the vector.
00073     */
00074     template< class T >
00075     std::string
00076     vector2string( const std::vector<T>& theVector )
00077     {
00078         ostringstream result;
00079         for( typename std::vector<T>::const_iterator itr =  theVector.begin( );
00080                                                      itr != theVector.end( );
00081                                                    ++itr ) {
00082             result << (*itr) << " ";
00083         }
00084         return result.str( );
00085     }
00086 
00087   // A helper function
00088 
00089     bool translate_OID( ooRef(ooObj)&      theRef,
00090                         const std::string& theString )
00091     {
00092         assert( !theString.empty( ));
00093 
00094         ooId id;
00095         {
00096             int db;
00097             int cont;
00098             int page;
00099             int slot;
00100 
00101             if( 4 != sscanf( theString.c_str( ), "#%d-%d-%d-%d", &db, &cont, &page, &slot )) {
00102                 if( 4 != sscanf( theString.c_str( ), "%d-%d-%d-%d", &db, &cont, &page, &slot )) {
00103                     return false;
00104                 }
00105             }
00106 
00107             id.set_DB  ( db );
00108             id.set_OC  ( cont );
00109             id.set_page( page );
00110             id.set_slot( slot );
00111         }
00112         theRef = id;
00113 
00114         return true;
00115     }
00116 
00117   /// A supplementary helper class storing parameters of a MetaData
00118 
00119     struct CdbBdb2RooPayloadMetaDataDescriptor {
00120 
00121       /// Constructor for regular conversion
00122 
00123         CdbBdb2RooPayloadMetaDataDescriptor( UShort_t theOriginId,
00124                                              UShort_t theConditionId,
00125                                              bool     isPartitionableFlag,
00126                                              UShort_t thePartitionId,
00127                                              UShort_t theClusterId,
00128                                              UShort_t theIncrementId ) :
00129             originId       (theOriginId),
00130             conditionId    (1, theConditionId),
00131             isPartitionable(isPartitionableFlag),
00132             partitionId    (thePartitionId),
00133             clusterId      (theClusterId),
00134             incrementId    (theIncrementId)
00135         { }
00136 
00137       /// Constructor for merging conversion
00138 
00139         CdbBdb2RooPayloadMetaDataDescriptor( UShort_t                       theOriginId,
00140                                              const std::vector< UShort_t >& theConditionId,
00141                                              bool                           isPartitionableFlag,
00142                                              UShort_t                       thePartitionId,
00143                                              UShort_t                       theClusterId,
00144                                              UShort_t                       theIncrementId ) :
00145             originId       (theOriginId),
00146             conditionId    (theConditionId),
00147             isPartitionable(isPartitionableFlag),
00148             partitionId    (thePartitionId),
00149             clusterId      (theClusterId),
00150             incrementId    (theIncrementId)
00151         { }
00152 
00153         std::string toString( ) const
00154         {
00155             ostringstream result;
00156             result << originId << "::" << conditionId[0] << " [" << partitionId << "," << clusterId << "," << incrementId << "] ";
00157             return result.str( );
00158         }
00159 
00160         UShort_t                originId;
00161         std::vector< UShort_t > conditionId;
00162         bool                    isPartitionable;
00163         UShort_t                partitionId;
00164         UShort_t                clusterId;
00165         UShort_t                incrementId;
00166     };
00167 
00168   // A helper function
00169 
00170     void printMetDataParameters( UShort_t theOriginId,
00171                                  UShort_t theConditionId,
00172                                  bool     isPartitionableFlag,
00173                                  UShort_t thePartitionId,
00174                                  UShort_t theClusterId,
00175                                  UShort_t theIncrementId )
00176     {
00177         cout << "         Origin identifier : "   << theOriginId << endl
00178              << "      Condition identifier : "   << theConditionId << endl
00179              << "          Is partitionable : "   << ( isPartitionableFlag ? "Yes" : "No" ) << endl
00180              << "      Partition identifier : "   << thePartitionId << endl
00181              << "        Cluster identifier : "   << theClusterId << endl
00182              << "          Increment number : "   << theIncrementId << endl;
00183     }
00184 
00185   // Supplementary helper classes storing the context of a "payload" container (TTree/TBranch)
00186 
00187     struct CdbBdb2RooPayloadContainerContext {
00188 
00189         CdbBdb2RooPayloadContainerContext( const std::string&                             theTreeName,
00190                                            const std::string&                             theTreeDescription,
00191                                            const CdbCPtr<CdbRooConverterBase>& theConverterPtr ) :
00192             tree( theTreeName.c_str( ),
00193                   theTreeDescription.c_str( )),
00194             converterPtr(theConverterPtr)
00195         { }
00196 
00197         void add( const BdbRef(BdbObject)& theInputLegacyObjectRef,
00198                   const CdbRooRoObjectIdR& theOutputObjectId )
00199         {
00200              inObjects.push_back( theInputLegacyObjectRef );
00201             outObjects.push_back( theOutputObjectId );
00202         }
00203 
00204       // Data members
00205 
00206         TTree tree;
00207 
00208         CdbCPtr<CdbRooConverterBase> converterPtr;
00209 
00210         std::vector< BdbRef(BdbObject) >  inObjects;
00211         std::vector< CdbRooRoObjectIdR > outObjects;
00212     };
00213 
00214     struct CdbBdb2RooPayloadMainContainerContext {
00215 
00216         CdbBdb2RooPayloadMainContainerContext( const std::string&                             theTreeName,
00217                                                const std::string&                             theTreeDescription,
00218                                                const CdbCPtr<CdbRooConverterBase>& theConverterPtr ) :
00219             tree( theTreeName.c_str( ),
00220                   theTreeDescription.c_str( )),
00221             converterPtr(theConverterPtr)
00222         { }
00223 
00224             void add( const std::vector< BdbRef(BdbObject) >& theInputLegacyObjectRef,
00225                       const CdbRooRoObjectIdR&                theOutputObjectId )
00226         {
00227              inObjects.push_back( theInputLegacyObjectRef );
00228             outObjects.push_back( theOutputObjectId );
00229         }
00230 
00231       // Data members
00232 
00233         TTree tree;
00234 
00235         CdbCPtr<CdbRooConverterBase> converterPtr;
00236 
00237         std::vector< std::vector< BdbRef(BdbObject) > >  inObjects;
00238         std::vector< CdbRooRoObjectIdR >                 outObjects;
00239     };
00240     struct CdbBdb2RooPayloadExtraContainerContext {
00241 
00242         CdbBdb2RooPayloadExtraContainerContext( const std::string&                             theTreeName,
00243                                                 const std::string&                             theTreeDescription,
00244                                                 const CdbCPtr<CdbRooConverterBase>& theConverterPtr ) :
00245             tree( theTreeName.c_str( ),
00246                   theTreeDescription.c_str( )),
00247             converterPtr(theConverterPtr)
00248         { }
00249 
00250         void add( const BdbRef(BdbObject)& theInputLegacyObjectRef,
00251                   const CdbRooRoObjectIdR& theOutputObjectId,
00252                   const CdbRooRoObjectIdR& theMainObjectId )
00253         {
00254               inObjects.push_back( theInputLegacyObjectRef );
00255              outObjects.push_back( theOutputObjectId );
00256             mainObjects.push_back( theMainObjectId );
00257         }
00258 
00259       // Data members
00260 
00261         TTree tree;
00262 
00263         CdbCPtr<CdbRooConverterBase> converterPtr;
00264 
00265         std::vector< BdbRef(BdbObject) >   inObjects;
00266         std::vector< CdbRooRoObjectIdR >  outObjects;
00267         std::vector< CdbRooRoObjectIdR > mainObjects;
00268     };
00269 
00270     bool translateNextLine( const std::string&    theLine,
00271                             const CdbDatabasePtr& theDatabasePtr,
00272                             UShort_t&             theOriginId,
00273                             UShort_t&             theConditionId,
00274                             bool&                 isPartitionableFlag,
00275                             UShort_t&             thePartitionId,
00276                             UShort_t&             theClusterId,
00277                             UShort_t&             theIncrementId,
00278                             std::string&          theInputClassName )
00279     {
00280         const char* errorStr = "CdbBdb2RooPayloadConversionFwk::<anonymous>::translateNextLine() - ERROR.";
00281 
00282         Tokenize tokenize( theLine );
00283 
00284         std::string  physicalConditionId = tokenize( );
00285         std::string        placementInfo = tokenize( );
00286         std::string spaceFilledSeparator = tokenize( "\"" );
00287         std::string       inputClassName = tokenize( "\"" );
00288 
00289         if(  physicalConditionId.empty( ) ||
00290                    placementInfo.empty( ) ||
00291             spaceFilledSeparator.empty( ) ||
00292                   inputClassName.empty( )) {
00293 
00294             cerr << errorStr << endl
00295                  << "    The line read from the definition file has an illegal format." << endl
00296                  << "\"" << theLine << "\"" << endl;
00297             return false;
00298         }
00299 
00300         UShort_t originId    = 0;
00301         UShort_t conditionId = 0;
00302         {
00303             unsigned origin;
00304             unsigned local;
00305 
00306             if( 2 != sscanf( physicalConditionId.c_str( ), "%u::%u", &origin, &local )) {
00307                 cerr << errorStr << endl
00308                      << "    Failed to translate the physical identifier of the condition found" << endl
00309                      << "    at the following line of the definition file." << endl
00310                      << "\"" << theLine << "\"" << endl;
00311                 return false;
00312             }
00313             if(( origin > 0xFFFF ) || ( local > 0xFFFF )) {
00314                 cerr << errorStr << endl
00315                      << "    The translated physical identifier of the condition has illegal format." << endl
00316                      << "    The identifier was found at the following line of the definition file." << endl
00317                      << "\"" << theLine << "\"" << endl;
00318                 return false;
00319             }
00320             originId    = (UShort_t)origin;
00321             conditionId = (UShort_t)local;
00322         }
00323 
00324         bool isPartitionable = false;
00325         {
00326             CdbId physicalId( originId,
00327                               conditionId );
00328 
00329             CdbConditionPtr cPtr;
00330             if( CdbStatus::Success != CdbCondition::instance( cPtr,
00331                                                               physicalId )) {
00332                 cerr << errorStr << endl
00333                      << "    Failed to find the condition with the condition physical identifier " << physicalId << endl
00334                      << "    in the input federation." << endl;
00335                 return false;
00336             }
00337             isPartitionable = cPtr->isPartitionable( );
00338         }
00339 
00340         UShort_t partitionId = 0;
00341         UShort_t clusterId   = 0;
00342         UShort_t incrementId = 0;
00343         {
00344             unsigned partition;
00345             unsigned cluster;
00346             unsigned increment;
00347 
00348             if( 3 != sscanf( placementInfo.c_str( ), "[%u,%u,%u]", &partition, &cluster, &increment )) {
00349                 cerr << errorStr << endl
00350                      << "    Failed to translate the condition placement parameters found" << endl
00351                      << "    at the following line of the definition file." << endl
00352                      << "\"" << theLine << "\"" << endl;
00353                 return false;
00354             }
00355             if(( partition > 0xFFFF ) || ( cluster > 0xFFFF ) || ( increment > 0xFFFF )) {
00356                 cerr << errorStr << endl
00357                      << "    The translated condition placement parameters have illegal format." << endl
00358                      << "    They were found at the following line of the definition file." << endl
00359                      << "\"" << theLine << "\"" << endl;
00360                 return false;
00361             }
00362             partitionId = (UShort_t)partition;
00363             clusterId   = (UShort_t)cluster;
00364             incrementId = (UShort_t)increment;
00365         }
00366 
00367       // Derive a correct owner origin identifier in case if this is a PARTITIONABLE
00368       // condition. We need this correction in order to locate the correct MetaData.
00369       //
00370       //    NOTE: The MetaData of partitionable conditions belong to owners of partitions,
00371       //           not to a formal owner
00372 
00373         if( isPartitionable ) {
00374 
00375             CdbPartitionPtr partitionPtr;
00376             if( CdbStatus::Success != theDatabasePtr->findPartition( partitionPtr,
00377                                                                      partitionId )) {
00378                 cerr << errorStr << endl
00379                      << "    Failed to obtain a pointer onto the CDB API object for the partition " <<  partitionId << endl;
00380                 return false;
00381             }
00382             originId = partitionPtr->ownerId( );
00383         }
00384 
00385       // Done. Fill resulting variables
00386 
00387         theOriginId         = originId;
00388         theConditionId      = conditionId;
00389         isPartitionableFlag = isPartitionable;
00390         thePartitionId      = partitionId;
00391         theClusterId        = clusterId;
00392         theIncrementId      = incrementId;
00393         theInputClassName   = inputClassName;
00394 
00395         return true;
00396     }
00397 }
00398 
00399 ////////////////////////////
00400 // Static class's members //
00401 ////////////////////////////
00402 
00403 bool CdbBdb2RooPayloadConversionFwk::verboseModeFlag       = true;
00404 bool CdbBdb2RooPayloadConversionFwk::debugModeFlag         = false;
00405 bool CdbBdb2RooPayloadConversionFwk::doNotCompressModeFlag = false;
00406 
00407 /////////////////////
00408 // Class's methods //
00409 /////////////////////
00410 
00411 bool
00412 CdbBdb2RooPayloadConversionFwk::setVerbose( bool newModeFlag )
00413 {
00414     bool previousFlag = verboseModeFlag;
00415     verboseModeFlag = newModeFlag;
00416     return previousFlag;
00417 }
00418 
00419 bool
00420 CdbBdb2RooPayloadConversionFwk::setDebug( bool newModeFlag )
00421 {
00422     bool previousFlag = debugModeFlag;
00423     debugModeFlag = newModeFlag;
00424     return previousFlag;
00425 }
00426 
00427 bool
00428 CdbBdb2RooPayloadConversionFwk::setDoNotCompress( bool newModeFlag )
00429 {
00430     bool previousFlag = doNotCompressModeFlag;
00431     doNotCompressModeFlag = newModeFlag;
00432     return previousFlag;
00433 }
00434 
00435 CdbStatus
00436 CdbBdb2RooPayloadConversionFwk::registerConverter( const CdbCPtr< CdbRooConverterBase >& thePtr )
00437 {
00438     if( thePtr.isNull( )) return CdbStatus::IllegalParameters;
00439 
00440   // Choose the right dictionary to register the converter.
00441   //
00442   // IMPLEMENTATION NOTE:
00443   //
00444   //   We're using two dictionary to allow the same input class be used in two
00445   //   different modes. Note, that dictionaries are keying converters based on
00446   //   the input class only.
00447 
00448     if( thePtr->mergingConverter( )) return mergingConvertersDict( )->add( thePtr );
00449     return regularConvertersDict( )->add( thePtr );
00450 }
00451 
00452 CdbStatus
00453 CdbBdb2RooPayloadConversionFwk::registerConverters(const std::vector< CdbCPtr < CdbRooConverterDict > >& theDicts)
00454 {
00455   vector< CdbCPtr< CdbRooConverterDict > >::const_iterator iter = theDicts.begin();
00456 
00457   while (iter != theDicts.end()) {
00458 
00459     vector< CdbCPtr< CdbRooConverterBase > > vect = (*iter)->converters();
00460     vector< CdbCPtr< CdbRooConverterBase > >::iterator converterIter = vect.begin();
00461 
00462     while (converterIter != vect.end()) {
00463       CdbStatus result = registerConverter(*converterIter);
00464       if (result != CdbStatus::Success) return result;
00465       converterIter++;
00466     }
00467 
00468     iter++;
00469   }
00470 
00471   return CdbStatus::Success;
00472 }
00473 
00474 CdbStatus
00475 CdbBdb2RooPayloadConversionFwk::testConversion( UShort_t theOriginId,
00476                                                 UShort_t theConditionId,
00477                                                 bool     isPartitionableFlag,
00478                                                 UShort_t thePartitionId,
00479                                                 UShort_t theClusterId,
00480                                                 UShort_t theIncrementId )
00481 {
00482     const char* infoStr = "CdbBdb2RooPayloadConversionFwk::testConversion(regular) - INFO.";
00483 
00484     cout << infoStr << endl
00485          << "    Just for the record, you've entered the following parameters:" << endl
00486          << endl
00487          << "         Origin identifier : "   << theOriginId << endl
00488          << "      Condition identifier : "   << theConditionId << endl
00489          << "          Is partitionable : "   << ( isPartitionableFlag ? "Yes" : "No" ) << endl
00490          << "      Partition identifier : "   << thePartitionId << endl
00491          << "        Cluster identifier : "   << theClusterId << endl
00492          << "          Increment number : "   << theIncrementId << endl
00493          << endl;
00494 
00495   // Initialize the context of the Objectivity/DB based CDB
00496 
00497     CdbBdbShared::forceLoad( );
00498 
00499     CdbTransaction bdbReadOnlyTransactionStartsHere( CdbBdbShared::technology( ),
00500                                                      CdbBdbShared::implementation( ));
00501 
00502   // Initialize the context of the ROOT I/O based CDB
00503 
00504     CdbRooReadonly::forceLoad( );
00505 
00506     CdbTransaction rooReadOnlyTransactionStartsHere( CdbRooReadonly::technology( ),
00507                                                      CdbRooReadonly::implementation( ));
00508 
00509   // Proceed to the actual conversion
00510 
00511     return convertMetadata( theOriginId,
00512                             theConditionId,
00513                             isPartitionableFlag,
00514                             thePartitionId,
00515                             theClusterId,
00516                             theIncrementId );
00517 }
00518 
00519 CdbStatus
00520 CdbBdb2RooPayloadConversionFwk::testConversion( UShort_t                     theOriginId,
00521                                                 const std::vector<UShort_t>& theConditionId,
00522                                                 bool                         isPartitionableFlag,
00523                                                 UShort_t                     thePartitionId,
00524                                                 UShort_t                     theClusterId,
00525                                                 UShort_t                     theIncrementId )
00526 {
00527     const char* infoStr = "CdbBdb2RooPayloadConversionFwk::testConversion(merging) - INFO.";
00528 
00529     cout << infoStr << endl
00530          << "    Just for the record, you've entered the following parameters:" << endl
00531          << endl
00532          << "          Origin identifier : " << theOriginId << endl
00533          << "      Condition identifiers : " << ::vector2string( theConditionId ) << endl
00534          << "           Is partitionable : " << ( isPartitionableFlag ? "Yes" : "No" ) << endl
00535          << "       Partition identifier : " << thePartitionId << endl
00536          << "         Cluster identifier : " << theClusterId << endl
00537          << "           Increment number : " << theIncrementId << endl
00538          << endl;
00539 
00540   // Initialize the context of the Objectivity/DB based CDB
00541 
00542     CdbBdbShared::forceLoad( );
00543 
00544     CdbTransaction bdbReadOnlyTransactionStartsHere( CdbBdbShared::technology( ),
00545                                                      CdbBdbShared::implementation( ));
00546 
00547   // Initialize the context of the ROOT I/O based CDB
00548 
00549     CdbRooReadonly::forceLoad( );
00550 
00551     CdbTransaction rooReadOnlyTransactionStartsHere( CdbRooReadonly::technology( ),
00552                                                      CdbRooReadonly::implementation( ));
00553 
00554   // Proceed to the actual conversion
00555 
00556     return convertMetadata( theOriginId,
00557                             theConditionId,
00558                             isPartitionableFlag,
00559                             thePartitionId,
00560                             theClusterId,
00561                             theIncrementId );
00562 }
00563 
00564 CdbStatus
00565 CdbBdb2RooPayloadConversionFwk::doConversion( const char* theDefinitionFile )
00566 {
00567     const char* errorStr = "CdbBdb2RooPayloadConversionFwk::doConversion() - ERROR.";
00568 
00569     CdbStatus result = CdbStatus::Error;
00570 
00571     assert( 0 != theDefinitionFile );
00572 
00573   // Initialize the context of the Objectivity/DB based CDB
00574 
00575     CdbBdbShared::forceLoad( );
00576 
00577     CdbTransaction bdbReadOnlyTransactionStartsHere( CdbBdbShared::technology( ),
00578                                                      CdbBdbShared::implementation( ));
00579 
00580   // Initialize the context of the ROOT I/O based CDB
00581 
00582     CdbRooReadonly::forceLoad( );
00583 
00584     CdbTransaction rooReadOnlyTransactionStartsHere( CdbRooReadonly::technology( ),
00585                                                      CdbRooReadonly::implementation( ));
00586 
00587   // Find the API object for the Database. We'll need it wor two reasons:
00588   //
00589   // - to check if we're running against the MASTER CDB, which would be desired
00590   //   to have a complete database contents;
00591   //
00592   // - to retrieve owner identifiers of partitions, which is needed to derive
00593   //   correct parameters of MetaData objects.
00594 
00595     CdbDatabasePtr databasePtr;
00596     if( CdbStatus::Success != ( result = CdbDatabase::instance( databasePtr ))) {
00597         cerr << errorStr << endl
00598              << "    Failed to obtain a pointer onto the CDB API object for the Database." << endl;
00599         return result;
00600     }
00601     if( !databasePtr->localOrigin( )->isMaster( )) {
00602         cerr << errorStr << endl
00603              << "    The input CDB is not of the MASTER type. The converter can only be run" << endl
00604              << "    against a MASTER type CDB. Make sure that you have set the correct" << endl
00605              << "    value for the OO_FD_BOOT environment variable." << endl;
00606         return CdbStatus::Error;
00607     }
00608 
00609   // Read the definition file into the memory. Collect only those conditioons whose classes
00610   // are known to the converter.
00611 
00612     typedef std::map< std::string, std::vector< CdbBdb2RooPayloadMetaDataDescriptor > > DescriptorsOfAcceptedMetaData;
00613 
00614     DescriptorsOfAcceptedMetaData regularMetaDataDescr;
00615     DescriptorsOfAcceptedMetaData  mergedMetaDataDescr;
00616 
00617     UShort_t                mergedOriginId        = 0;
00618     std::vector< UShort_t > mergedConditionId    ( 0 );
00619     bool                    mergedIsPartitionable = false;
00620     UShort_t                mergedPartitionId     = 0;
00621     UShort_t                mergedClusterId       = 0;
00622     UShort_t                mergedIncrementId     = 0;
00623     std::string             mergedInputClassName  = "";
00624 
00625     unsigned int currentLineNumber = 0;
00626     std::string  currentLine       = "";
00627 
00628     enum {
00629         PARSER_IDLE,
00630         PARSER_REGULAR,
00631         PARSER_MERGING_BEGIN,
00632         PARSER_MERGING,
00633         PARSER_FAILED
00634     } parserState = PARSER_IDLE;
00635 
00636     ifstream definitionFileStream( theDefinitionFile );
00637 
00638     const int bufSize = 64 * 1024;
00639     char      buf[bufSize];
00640 
00641     while( definitionFileStream.getline( buf,
00642                                          bufSize, '\n' )) {
00643 
00644         ++currentLineNumber;
00645         currentLine = std::string( buf );
00646 
00647       // Translate the next line read from the input file.
00648 
00649         if( verboseModeFlag ) {
00650             cout << "translating line: \"" << currentLine << "\"" << endl;
00651         }
00652         if( "#REGULAR" == currentLine ) {
00653 
00654             if(( PARSER_IDLE == parserState ) || ( PARSER_REGULAR == parserState ) || ( PARSER_MERGING_BEGIN == parserState )) {
00655 
00656                 parserState = PARSER_REGULAR;
00657 
00658             } else if( PARSER_MERGING == parserState ) {
00659 
00660               // Finalize a block of the currently merged conditions before switching
00661               // to a regular one.
00662               //
00663               // IMPLEMENTATION NOTES:
00664               //
00665               //    That's the "cut-and-paste" of the same code implemented
00666               //    below when switching from one block merged conditions to
00667               //    another one.
00668               //
00669               //    The code needs to be refactored to be more robust.
00670 
00671                 if( mergedConditionId.size( ) > 1 ) {
00672 
00673                   // Check if the Dictionary of Merging Converters has an entry for the input
00674                   // persistent class. If not then just skip the whole block MetaData entries.
00675 
00676                     CdbCPtr<CdbRooConverterBase> converterPtr =
00677                         mergingConvertersDict( )->findByInputClassName( mergedInputClassName );
00678 
00679                     if( converterPtr.isNull( )) {
00680 
00681                         if( verboseModeFlag ) {
00682                             cout << "skipping merged block of MetaData for main class: " << mergedInputClassName << endl;
00683                         }
00684 
00685                     } else {
00686 
00687                         if( mergedMetaDataDescr.find( mergedInputClassName ) == mergedMetaDataDescr.end( )) {
00688                             std::vector< CdbBdb2RooPayloadMetaDataDescriptor > emptyVector;
00689                             mergedMetaDataDescr[ mergedInputClassName ] = emptyVector;
00690                         }
00691                         mergedMetaDataDescr[ mergedInputClassName ].push_back( CdbBdb2RooPayloadMetaDataDescriptor( mergedOriginId,
00692                                                                                                                     mergedConditionId,
00693                                                                                                                     mergedIsPartitionable,
00694                                                                                                                     mergedPartitionId,
00695                                                                                                                     mergedClusterId,
00696                                                                                                                     mergedIncrementId ));
00697                     }
00698 
00699                 } else {
00700 
00701                     cerr << errorStr << endl
00702                          << "    Too few MetaData-s in a block of merged ones." << endl
00703                          << "    There must be at least 2 of them." << endl;
00704 
00705                     parserState = PARSER_FAILED;
00706 
00707                     break;
00708                 }
00709                 
00710                 parserState = PARSER_REGULAR;
00711 
00712             } else {
00713 
00714                 parserState = PARSER_FAILED;
00715 
00716                 break;
00717             }
00718 
00719         } else if( "#MERGE" == currentLine ) {
00720 
00721             if(( PARSER_IDLE == parserState ) || ( PARSER_REGULAR == parserState ) || ( PARSER_MERGING_BEGIN == parserState )) {
00722 
00723                 parserState = PARSER_MERGING_BEGIN;
00724 
00725             } else if( PARSER_MERGING == parserState ) {
00726 
00727               // Finalize a block of the currently merged conditions before switching
00728               // to the next merged one.
00729               //
00730               // IMPLEMENTATION NOTES:
00731               //
00732               //    That's the "cut-and-paste" of the same code implemented
00733               //    above when switching from merged to regular conditions.
00734               //
00735               //    The code needs to be refactored to be more robust.
00736 
00737                 if( mergedConditionId.size( ) > 1 ) {
00738 
00739                   // Check if the Dictionary of Merging Converters has an entry for the input
00740                   // persistent class. If not then just skip the whole block MetaData entries.
00741 
00742                     CdbCPtr<CdbRooConverterBase> converterPtr =
00743                         mergingConvertersDict( )->findByInputClassName( mergedInputClassName );
00744 
00745                     if( converterPtr.isNull( )) {
00746 
00747                         if( verboseModeFlag ) {
00748                             cout << "skipping merged block of MetaData for main class: " << mergedInputClassName << endl;
00749                         }
00750 
00751                     } else {
00752 
00753                         if( mergedMetaDataDescr.find( mergedInputClassName ) == mergedMetaDataDescr.end( )) {
00754                             std::vector< CdbBdb2RooPayloadMetaDataDescriptor > emptyVector;
00755                             mergedMetaDataDescr[ mergedInputClassName ] = emptyVector;
00756                         }
00757                         mergedMetaDataDescr[ mergedInputClassName ].push_back( CdbBdb2RooPayloadMetaDataDescriptor( mergedOriginId,
00758                                                                                                                     mergedConditionId,
00759                                                                                                                     mergedIsPartitionable,
00760                                                                                                                     mergedPartitionId,
00761                                                                                                                     mergedClusterId,
00762                                                                                                                     mergedIncrementId ));
00763                     }
00764 
00765                 } else {
00766 
00767                     cerr << errorStr << endl
00768                          << "    Too few MetaData-s in a block of merged ones." << endl
00769                          << "    There must be at least 2 of them." << endl;
00770 
00771                     parserState = PARSER_FAILED;
00772 
00773                     break;
00774                 }
00775                 
00776                 parserState = PARSER_MERGING_BEGIN;
00777 
00778             } else {
00779 
00780                 parserState = PARSER_FAILED;
00781 
00782                 break;
00783             }
00784 
00785         } else if( "#END" == currentLine ) {
00786 
00787             if( PARSER_MERGING == parserState ) {
00788 
00789               // Finalize a block of the currently merged conditions before switching
00790               // to the next merged one.
00791               //
00792               // IMPLEMENTATION NOTES:
00793               //
00794               //    That's the "cut-and-paste" of the same code implemented
00795               //    above when switching from merged to regular conditions
00796               //    as well as when switching from one block merged conditions to
00797               //    another one.
00798               //
00799               //    The code needs to be refactored to be more robust.
00800 
00801                 if( mergedConditionId.size( ) > 1 ) {
00802 
00803                   // Check if the Dictionary of Merging Converters has an entry for the input
00804                   // persistent class. If not then just skip the whole block MetaData entries.
00805 
00806                     CdbCPtr<CdbRooConverterBase> converterPtr =
00807                         mergingConvertersDict( )->findByInputClassName( mergedInputClassName );
00808 
00809                     if( converterPtr.isNull( )) {
00810 
00811                         if( verboseModeFlag ) {
00812                             cout << "skipping merged block of MetaData for main class: " << mergedInputClassName << endl;
00813                         }
00814 
00815                     } else {
00816 
00817                         if( mergedMetaDataDescr.find( mergedInputClassName ) == mergedMetaDataDescr.end( )) {
00818                             std::vector< CdbBdb2RooPayloadMetaDataDescriptor > emptyVector;
00819                             mergedMetaDataDescr[ mergedInputClassName ] = emptyVector;
00820                         }
00821                         mergedMetaDataDescr[ mergedInputClassName ].push_back( CdbBdb2RooPayloadMetaDataDescriptor( mergedOriginId,
00822                                                                                                                     mergedConditionId,
00823                                                                                                                     mergedIsPartitionable,
00824                                                                                                                     mergedPartitionId,
00825                                                                                                                     mergedClusterId,
00826                                                                                                                     mergedIncrementId ));
00827                     }
00828 
00829                 } else {
00830 
00831                     cerr << errorStr << endl
00832                          << "    Too few MetaData-s in a block of merged ones." << endl
00833                          << "    There must be at least 2 of them." << endl;
00834 
00835                     parserState = PARSER_FAILED;
00836 
00837                     break;
00838                 }
00839             }
00840 
00841             parserState = PARSER_IDLE;
00842 
00843             break;
00844 
00845         } else {
00846 
00847           // It must be the MetaData line then?
00848 
00849             UShort_t    originId        = 0;
00850             UShort_t    conditionId     = 0;
00851             bool        isPartitionable = false;
00852             UShort_t    partitionId     = 0;
00853             UShort_t    clusterId       = 0;
00854             UShort_t    incrementId     = 0;
00855             std::string inputClassName  = "";
00856 
00857             if( !::translateNextLine( currentLine,
00858                                       databasePtr,
00859                                       originId,
00860                                       conditionId,
00861                                       isPartitionable,
00862                                       partitionId,
00863                                       clusterId,
00864                                       incrementId,
00865                                       inputClassName )) {
00866 
00867                 parserState = PARSER_FAILED;
00868 
00869                 break;
00870             }
00871 
00872             if( PARSER_REGULAR == parserState ) {
00873 
00874               // Check if the Dictionary of Regular Converters has an entry for the input
00875               // persistent class. If not then just skip the MetaData entry.
00876 
00877                 CdbCPtr<CdbRooConverterBase> converterPtr =
00878                     regularConvertersDict( )->findByInputClassName( inputClassName );
00879 
00880                 if( converterPtr.isNull( )) {
00881 
00882                     if( verboseModeFlag ) {
00883                         cout << "no converter found for the input class \"" << inputClassName << "\", skipping line " << currentLine<< endl;
00884                     }
00885 
00886                 } else {
00887 
00888                     if( regularMetaDataDescr.find( inputClassName ) == regularMetaDataDescr.end( )) {
00889                         std::vector< CdbBdb2RooPayloadMetaDataDescriptor > emptyVector;
00890                         regularMetaDataDescr[ inputClassName ] = emptyVector;
00891                     }
00892                     regularMetaDataDescr[ inputClassName ].push_back( CdbBdb2RooPayloadMetaDataDescriptor( originId,
00893                                                                                                            conditionId,
00894                                                                                                            isPartitionable,
00895                                                                                                            partitionId,
00896                                                                                                            clusterId,
00897                                                                                                            incrementId ));
00898                 }
00899 
00900             } else if( PARSER_MERGING_BEGIN == parserState ) {
00901 
00902               // That's the very first MetaData in a block.
00903               // Set up the main context.
00904 
00905                 mergedOriginId        = originId;
00906 
00907                 mergedConditionId.resize( 0 );
00908                 mergedConditionId.push_back( conditionId );
00909 
00910                 mergedIsPartitionable = isPartitionable;
00911                 mergedPartitionId     = partitionId;
00912                 mergedClusterId       = clusterId;
00913                 mergedIncrementId     = incrementId;
00914                 mergedInputClassName  = inputClassName;
00915 
00916                 parserState = PARSER_MERGING;
00917 
00918             } else if( PARSER_MERGING == parserState ) {
00919 
00920               // That's the next MetaData in a block.
00921               // Verify if its parameters are consistent with the current context.
00922 
00923                 if(( mergedOriginId        != originId        ) ||
00924                    ( mergedIsPartitionable != isPartitionable ) ||
00925                    ( mergedPartitionId     != partitionId     ) ||
00926                    ( mergedClusterId       != clusterId       ) ||
00927                    ( mergedIncrementId     != incrementId     )) {
00928 
00929                     cerr << errorStr << endl
00930                          << "    Inconsistent MetaData in a block of merged ones." << endl;
00931 
00932                     parserState = PARSER_FAILED;
00933 
00934                     break;
00935                 }
00936 
00937                 mergedConditionId.push_back( conditionId );
00938 
00939             } else {
00940 
00941                 parserState = PARSER_FAILED;
00942 
00943                 break;
00944             }
00945         }
00946     }
00947     if( PARSER_IDLE != parserState ) {
00948 
00949         if( PARSER_FAILED == parserState ) {
00950 
00951             cerr << errorStr << endl
00952                  << "    Incorrect syntax of the definition file:" << endl
00953                  << "        \"" << theDefinitionFile << "\"" << endl
00954                  << "    at line #" << currentLineNumber << " containing:" << endl
00955                  << "        \"" << currentLine << "\"" << endl
00956                  << endl;
00957 
00958         } else {
00959 
00960             cerr << errorStr << endl
00961                  << "    Incorrect syntax at the end of the definition file:" << endl
00962                  << "        \"" << theDefinitionFile << "\"" << endl
00963                  << "    after line #" << currentLineNumber << " containing:" << endl
00964                  << "        \"" << currentLine << "\"" << endl
00965                  << "    Perhaps the #END command line is missing?" << endl
00966                  << endl;
00967         }
00968         return CdbStatus::Error;
00969     }
00970 
00971   // Process accepted regular MetaData objects.
00972 
00973     for( DescriptorsOfAcceptedMetaData::const_iterator itr = regularMetaDataDescr.begin( );
00974                                                        itr != regularMetaDataDescr.end( );
00975                                                      ++itr ) {
00976 
00977         if( verboseModeFlag )
00978             cout << "processing regular InputClass \"" << (*itr).first << "\"" << endl;
00979 
00980         std::vector< CdbBdb2RooPayloadMetaDataDescriptor > vectorOfDescriptors = (*itr).second;
00981 
00982         unsigned int num = vectorOfDescriptors.size( );
00983         assert( 0 != num );
00984 
00985         for( unsigned int i = 0; i < num; ++i ) {
00986 
00987             CdbBdb2RooPayloadMetaDataDescriptor descriptor = vectorOfDescriptors[i];
00988 
00989             if( verboseModeFlag )
00990                 cout << "  processing regular MetaData " << descriptor.toString( ) << endl;
00991 
00992             if( CdbStatus::Success != ( result = convertMetadata( descriptor.originId,
00993                                                                   descriptor.conditionId[0],    // Main object only
00994                                                                   descriptor.isPartitionable,
00995                                                                   descriptor.partitionId,
00996                                                                   descriptor.clusterId,
00997                                                                   descriptor.incrementId ))) {
00998                 cerr << errorStr << endl
00999                      << "    Failed when regular processing MetaData " << descriptor.toString( ) << endl;
01000                 return result;
01001             }
01002         }
01003     }
01004 
01005   // Process accepted merged MetaData objects.
01006 
01007     for( DescriptorsOfAcceptedMetaData::const_iterator itr = mergedMetaDataDescr.begin( );
01008                                                        itr != mergedMetaDataDescr.end( );
01009                                                      ++itr ) {
01010 
01011         if( verboseModeFlag )
01012             cout << "processing merged InputClass \"" << (*itr).first << "\"" << endl;
01013 
01014         std::vector< CdbBdb2RooPayloadMetaDataDescriptor > vectorOfDescriptors = (*itr).second;
01015 
01016         unsigned int num = vectorOfDescriptors.size( );
01017         assert( 0 != num );
01018 
01019         for( unsigned int i = 0; i < num; ++i ) {
01020 
01021             CdbBdb2RooPayloadMetaDataDescriptor descriptor = vectorOfDescriptors[i];
01022 
01023             if( verboseModeFlag )
01024                 cout << "  processing merged MetaData " << descriptor.toString( ) << endl;
01025 
01026             if( CdbStatus::Success != ( result = convertMetadata( descriptor.originId,
01027                                                                   descriptor.conditionId,   // Main + extra objects
01028                                                                   descriptor.isPartitionable,
01029                                                                   descriptor.partitionId,
01030                                                                   descriptor.clusterId,
01031                                                                   descriptor.incrementId ))) {
01032                 cerr << errorStr << endl
01033                      << "    Failed when processing merged MetaData " << descriptor.toString( ) << endl;
01034                 return result;
01035             }
01036         }
01037     }
01038     return CdbStatus::Success;
01039 }
01040 
01041 CdbStatus
01042 CdbBdb2RooPayloadConversionFwk::convertMetadata( UShort_t theOriginId,
01043                                                  UShort_t theConditionId,
01044                                                  bool     isPartitionableFlag,
01045                                                  UShort_t thePartitionId,
01046                                                  UShort_t theClusterId,
01047                                                  UShort_t theIncrementId )
01048 {
01049     const char* errorStr = "CdbBdb2RooPayloadConversionFwk::::convertMetadata(regular) - ERROR.";
01050 
01051     if( verboseModeFlag ) {
01052         cout << "CdbBdb2RooPayloadConversionFwk::convertMetadata(regular) : PARAMETERS OF THE METHOD {" << endl
01053              << "    theOriginId         = " << theOriginId << endl
01054              << "    theConditionId      = " << theConditionId << endl
01055              << "    isPartitionableFlag = " << isPartitionableFlag << endl
01056              << "    thePartitionId      = " << thePartitionId << endl
01057              << "    theClusterId        = " << theClusterId << endl
01058              << "    theIncrementId      = " << theIncrementId << endl
01059              << "}" << endl;
01060     }
01061 
01062     CdbStatus result = CdbStatus::Error;
01063 
01064   // Find the output collection of original intervals to be processed
01065 
01066     CdbCPtr< CdbRooRoMetaDataR > mdPtr;
01067     if( CdbStatus::Success != ( result = CdbRooRoFileUtils::instance( ).findMetaData( mdPtr,
01068                                                                                       theConditionId,
01069                                                                                       isPartitionableFlag,
01070                                                                                       thePartitionId,
01071                                                                                       theClusterId,
01072                                                                                       theIncrementId,
01073                                                                                       theOriginId ))) {
01074         cerr << errorStr << endl
01075              << "    Failed to locate the input MetaData object." << endl;
01076         return result;
01077     }
01078     CdbCPtr< CdbRooRoOiCollectionR> oiCollectionPtr = mdPtr->originalIntervalsCollection( );
01079 
01080     if( debugModeFlag ) {
01081         cout << "CdbBdb2RooPayloadConversionFwk::convertMetadata(regular) : DUMP OF THE ORIGINAL COLLECTION {" << endl;
01082         oiCollectionPtr->dump( cout );
01083     }
01084 
01085   // Find and open the output file for updating
01086 
01087     CdbCPtr< TFile > databasePtr;
01088     if( CdbStatus::Success != ( result = CdbRooRoFileUtils::instance( ).findObjectsDatabase( databasePtr,
01089                                                                                              isPartitionableFlag,
01090                                                                                              thePartitionId,
01091                                                                                              theClusterId,
01092                                                                                              theIncrementId,
01093                                                                                              theOriginId,
01094                                                                                              "update" ))) {
01095         cerr << errorStr << endl
01096              << "    Failed to locate the file for output objects." << endl;
01097         return result;
01098     }
01099     if( doNotCompressModeFlag ) databasePtr->SetCompressionLevel( 0 );
01100 
01101   // Build a base name for container trees where with branches where we're going
01102   // to put converted objects.
01103   //
01104   // NOTE: In ROOT I/O the tree will be create in the last open/activated file. Hence we're
01105   //       assuming that it's been done by the previous operation.
01106 
01107     const std::string treeNameBase =
01108         CdbRooRoFileUtils::nameOfObjectsContainer( theConditionId,
01109                                                    isPartitionableFlag,
01110                                                    thePartitionId,
01111                                                    theClusterId,
01112                                                    theIncrementId,
01113                                                    theOriginId ) + ".";
01114 
01115   // Prepare a map with an executin plan for the conversion
01116 
01117     std::map< UShort_t, CdbBdb2RooPayloadContainerContext* > executionPlan;
01118 
01119   // Create a map of object which are processes to avoid double processing
01120 
01121     std::map< std::string, bool > mapOfProcessedObjects;
01122 
01123   // Process each interval found in the collection
01124 
01125     if( debugModeFlag )
01126         cout << endl
01127              << "Conversion pass  I: preparing an execution plan..." << endl
01128              << endl;
01129 
01130     UInt_t nIntervals = oiCollectionPtr->size( );
01131     assert( nIntervals > 0 );
01132 
01133     for( UInt_t idx = 1; idx < nIntervals; ++idx ) {
01134 
01135         CdbRooRoOiR oi;
01136 
01137         BdbTime beginOfDuration;    // not used by the current algorithm
01138         BdbTime   endOfDuration;    // not used by the current algorithm
01139 
01140         if( CdbStatus::Success != ( result = oiCollectionPtr->find( idx,
01141                                                                     oi,
01142                                                                     beginOfDuration,
01143                                                                     endOfDuration ))) {
01144             cerr << errorStr << endl
01145                  << "    Failed to find an 'origina' interval with index = " << idx << endl;
01146             return result;
01147         }
01148 
01149         if( debugModeFlag )
01150             cout << "  " << oi.object( ) << " <-- " << oi.legacyObjectAddress( ) << endl;
01151 
01152       // Check if the OID of the output object matches the current location of the "MetaData.<id>"
01153       // and "Objects.<id>" containers.
01154 
01155         if( ( oi.object( ).origin   ( ) != theOriginId    ) ||
01156             ( oi.object( ).condition( ) != theConditionId ) ||
01157             ( oi.object( ).cluster  ( ) != theClusterId   ) ||
01158             ( oi.object( ).partition( ) != thePartitionId ) ||
01159             ( oi.object( ).increment( ) != theIncrementId )) {
01160 
01161                 cerr << errorStr << endl
01162                      << "    The output object address " << oi.object( ) << " doesn't match" << endl
01163                      << "    the location of the output container." << endl;
01164                 return CdbStatus::Error;
01165         }
01166 
01167       // Skip the object if it's already been processed
01168 
01169         if( mapOfProcessedObjects.find( oi.object( ).toString( )) != mapOfProcessedObjects.end( )) continue;
01170 
01171         mapOfProcessedObjects[oi.object( ).toString( )] = true;
01172 
01173       // Get the input persistent object first and verify it exists
01174 
01175         BdbRef(BdbObject) legacyObjectRef;
01176 
01177         if( !translate_OID( legacyObjectRef,
01178                             oi.legacyObjectAddress( ))) {
01179             cerr << errorStr << endl
01180                  << "    Failed to translate the OID of the legacy object: " << oi.legacyObjectAddress( ) << endl;
01181             return CdbStatus::Error;
01182         }
01183 
01184       // Get the final class of that persistent object and verify if it derives
01185       // from the BdbObject class.
01186 
01187         const std::string legacyObjectTypeName = legacyObjectRef.typeName( );
01188         {
01189             if( !CdbBdbSchemaUtils::instance( ).isA( legacyObjectRef.typeN( ),
01190                                                      ooTypeN( BdbObject ))) {
01191                 cerr << errorStr << endl
01192                      << "    The legacy object doesn't derive from BdbObject: " << oi.legacyObjectAddress( ) << endl;
01193                 return CdbStatus::Error;
01194             }
01195         }
01196 
01197       // Create new container context if it doesn't exist yet, then put the found
01198       // original interval into this context.
01199       //
01200       // NOTE: the order of original intervals is important to match ROID-s
01201       //       generated during the metadata conversion phase.
01202 
01203         if( executionPlan.find( oi.object( ).container( )) == executionPlan.end( )) {
01204 
01205           // Build the name of the tree representing this container
01206 
01207             const std::string treeName = treeNameBase + CdbStringUtils::toString( oi.object( ).container( ));
01208 
01209           // Check if the corresponding converter is available
01210 
01211             CdbCPtr< CdbRooConverterBase > converterPtr = regularConvertersDict( )->findByInputClassName( legacyObjectTypeName );
01212             if( converterPtr.isNull( )) {
01213                 cerr << errorStr << endl
01214                      << "    No converter avaialble for the legacy class: " << legacyObjectTypeName << endl;
01215                 return CdbStatus::Error;
01216             }
01217 
01218           //
01219           // VERY IMPORTANT NOTE: Due to a way this "xyz!@#$^%" ROOT I/O works one should always
01220           //                      be sure that the proper "current file" is set before creating new
01221           //                      TTree-s which is what is going to happen below.
01222  
01223 // cout << "gDirectory->GetName( ) = \"" << gDirectory->GetName( ) << "\"" << endl;
01224 // cout << "gFile->GetName( )      = \"" << gFile->GetName( )      << "\"" << endl;
01225 
01226             databasePtr->Cd( "" );
01227             gDirectory->Cd( databasePtr->GetPath( ));
01228 
01229 // cout << "gDirectory->GetName( ) = \"" << gDirectory->GetName( ) << "\"" << endl;
01230 // cout << "gFile->GetName( )      = \"" << gFile->GetName( )      << "\"" << endl;
01231 
01232             executionPlan[oi.object( ).container( )] = new CdbBdb2RooPayloadContainerContext( treeName,
01233                                                                                               "A tree for 'payload' objects" ,
01234                                                                                               converterPtr );
01235         }
01236         executionPlan[oi.object( ).container( )]->add( legacyObjectRef,
01237                                                        oi.object( ));
01238     }
01239 
01240     if( debugModeFlag )
01241         cout << endl
01242              << "Conversion pass II: performing the actual conversion..." << endl
01243              << endl;
01244 
01245     for( std::map< UShort_t, CdbBdb2RooPayloadContainerContext* >::iterator itr = executionPlan.begin( );
01246                                                                             itr != executionPlan.end( );
01247                                                                           ++itr ) {
01248 
01249         CdbBdb2RooPayloadContainerContext* containerContext = (*itr).second;
01250 
01251       // Get the corresponding TBranch for that class
01252       //
01253       // DESIGN NOTE: A transient pointer passed to the constructor will be managed
01254       //              internally by the converter. See more details on how this
01255       //              converter is used insede an intervals conversion loop below.
01256 
01257         const char* branchName = "0";   // always use this branch name
01258 
01259         TBranch* branch = containerContext->converterPtr->branchConstructor( containerContext->tree,
01260                                                                              branchName );
01261 
01262         UInt_t nIntervals = containerContext->inObjects.size( );
01263         assert( nIntervals > 0 );
01264 
01265         for( UInt_t idx = 0; idx < nIntervals; ++idx ) {
01266 
01267             BdbRef(BdbObject)& legacyObjectRef = containerContext->inObjects [idx];
01268             CdbRooRoObjectIdR& outputObjectId  = containerContext->outObjects[idx];
01269 
01270             if( debugModeFlag )
01271                 cout << "  " << outputObjectId << " <-- " << legacyObjectRef.sprint( ) << " : \"" << containerContext->converterPtr->inputClassName( ) << "\"" << endl;
01272 
01273           // Use the converter
01274           //
01275           // DESIGN NOTE:
01276           //
01277           //   1. The actual object will be created and stored at a location known to
01278           //   above constructed TBranch inside the converter. We just need to make sure
01279           //   that the object is saved (see TTree::Fill()) operation in the current TTree,
01280           //
01281           //   2. Remember that the converter manages the lifetime of the created transient objects.
01282 
01283             {
01284                 std::vector< BdbRef(BdbObject) > extraObjects( 0 ); // no extra objects for now
01285 
01286                 if( CdbStatus::Success != ( result = containerContext->converterPtr->conversion( legacyObjectRef,
01287                                                                                                  extraObjects ))) {
01288                     cerr << errorStr << endl
01289                          << "    Failed to convert the legacy object " << legacyObjectRef.sprint( ) << endl;
01290                     return result;
01291                 }
01292 
01293               // Store the object in the Tree/Branch
01294 
01295                 containerContext->tree.Fill( );
01296 
01297               // Make sure that the next available index in the branch matches the object index
01298               // in its OID.
01299 
01300                 if( debugModeFlag )
01301                     cout << "  tree->GetNbranches( ) = " << containerContext->tree.GetNbranches( ) << endl
01302                          << "  tree->GetEntries  ( ) = " << containerContext->tree.GetEntries( ) << endl
01303                          << "branch->GetEntries  ( ) = " << branch->GetEntries( ) << endl;
01304 
01305                 Long64_t objectIndexInBranch = branch->GetEntries( ) - 1;
01306 
01307                 if(( objectIndexInBranch < 0 ) ||
01308                    ( objectIndexInBranch >= 0xFFFF ) ||
01309                    ( objectIndexInBranch != outputObjectId.index( ))) {
01310 
01311                     cerr << errorStr << endl
01312                          << "    The just converted object " << outputObjectId << " produced from the legacy object " << legacyObjectRef.sprint( ) << endl
01313                          << "    was writtent into a branch with a noon-valid index " << objectIndexInBranch << endl;
01314 
01315                     return CdbStatus::Error;
01316                 }
01317             }
01318         }
01319 
01320       // Save the tree in the file
01321 
01322         databasePtr->Cd( "" );
01323         gDirectory->Cd( databasePtr->GetPath( ));
01324 
01325         Int_t numBytesWritten = databasePtr->WriteObject( &containerContext->tree,
01326                                                           containerContext->tree.GetName( ));
01327         if( numBytesWritten <= 0 ) {
01328             cerr << errorStr << endl
01329                  << "    Failed to save the tree \"" << containerContext->tree.GetName( ) << "\" in the file: " << databasePtr->GetName( ) << endl;
01330             return CdbStatus::Error;
01331         }
01332         if( debugModeFlag )
01333             cout << endl
01334                  << "Total of " << nIntervals << " converted and stored into the tree \"" << containerContext->tree.GetName( ) << "\"." << endl
01335                  << endl;
01336 
01337       // Destroy the context
01338 
01339         delete containerContext;
01340     }
01341     return CdbStatus::Success;
01342 }
01343 
01344 CdbStatus
01345 CdbBdb2RooPayloadConversionFwk::convertMetadata( UShort_t                     theOriginId,
01346                                                  const std::vector<UShort_t>& theConditionId,
01347                                                  bool                         isPartitionableFlag,
01348                                                  UShort_t                     thePartitionId,
01349                                                  UShort_t                     theClusterId,
01350                                                  UShort_t                     theIncrementId )
01351 {
01352     const char* infoStr  = "CdbBdb2RooPayloadConversionFwk::::convertMetadata(merging) - INFO.";
01353     const char* errorStr = "CdbBdb2RooPayloadConversionFwk::::convertMetadata(merging) - ERROR.";
01354 
01355     CdbStatus result = CdbStatus::Error;
01356 
01357     if( debugModeFlag ) {
01358         cout << infoStr << endl
01359              << "    Converting and merging the following conditions:" << endl
01360              << endl
01361              << "          Origin identifier : " << theOriginId << endl
01362              << "      Condition identifiers : " << ::vector2string( theConditionId ) << endl
01363              << "           Is partitionable : " << ( isPartitionableFlag ? "Yes" : "No" ) << endl
01364              << "       Partition identifier : " << thePartitionId << endl
01365              << "         Cluster identifier : " << theClusterId   << endl
01366              << "           Increment number : " << theIncrementId << endl
01367              << endl;
01368     }
01369 
01370   // Verify parameters
01371 
01372     const unsigned int nConditions = theConditionId.size( );
01373     if( nConditions < 2 ) {
01374         cerr << errorStr << endl
01375              << "    The total number of conditions to be merged is less than 2." << endl;
01376         return CdbStatus::IllegalParameters;
01377     }
01378 
01379   // Find and verify the output collections of original intervals to be processed
01380   //
01381   // NOTE: By "verify" we mean that all collections should have the same number
01382   //       of intervals. That's essential for the merging algorithm!
01383 
01384     std::vector< CdbCPtr< CdbRooRoOiCollectionR> > oiCollectionPtr( nConditions );
01385 
01386     for( unsigned int conditionIdx = 0; conditionIdx < nConditions; ++conditionIdx ) {
01387 
01388         CdbCPtr< CdbRooRoMetaDataR > mdPtr;
01389         if( CdbStatus::Success != ( result = CdbRooRoFileUtils::instance( ).findMetaData( mdPtr,
01390                                                                                           theConditionId[conditionIdx],
01391                                                                                           isPartitionableFlag,
01392                                                                                           thePartitionId,
01393                                                                                           theClusterId,
01394                                                                                           theIncrementId,
01395                                                                                           theOriginId ))) {
01396             cerr << errorStr << endl
01397                  << "    Failed to locate the input MetaData object for:" << endl;
01398 
01399             ::printMetDataParameters( theOriginId,
01400                                       theConditionId[conditionIdx],
01401                                       isPartitionableFlag,
01402                                       thePartitionId,
01403                                       theClusterId,
01404                                       theIncrementId );
01405             return result;
01406         }
01407         oiCollectionPtr[conditionIdx] = mdPtr->originalIntervalsCollection( );
01408     }
01409 
01410     for( unsigned int conditionIdx = 1; conditionIdx < nConditions; ++conditionIdx ) {
01411         if( oiCollectionPtr[0]->size( ) != oiCollectionPtr[conditionIdx]->size( )) {
01412             cerr << errorStr << endl
01413                  << "    MetData objects passed to the current procedure do not have the same" << endl
01414                  << "    number of original intervals. Merging is not possible for these conditions." << endl;
01415             return CdbStatus::Error;
01416         }
01417     }
01418 
01419   // Find and open the output file for updating
01420   //
01421   // IMPLEMENTATION NOTE: 
01422 
01423     CdbCPtr< TFile > databasePtr;
01424     if( CdbStatus::Success != ( result = CdbRooRoFileUtils::instance( ).findObjectsDatabase( databasePtr,
01425                                                                                              isPartitionableFlag,
01426                                                                                              thePartitionId,
01427                                                                                              theClusterId,
01428                                                                                              theIncrementId,
01429                                                                                              theOriginId,
01430                                                                                              "update" ))) {
01431         cerr << errorStr << endl
01432              << "    Failed to create/reopen a file for output objects." << endl;
01433         return result;
01434     }
01435     if( doNotCompressModeFlag ) databasePtr->SetCompressionLevel( 0 );
01436 
01437   // Build a base name for container trees where with branches where we're going
01438   // to put converted objects.
01439   //
01440   // NOTE: In ROOT I/O the tree will be create in the last open/activated file. Hence we're
01441   //       assuming that it's been done by the previous operation.
01442 
01443     std::vector< std::string > treeNameBase( nConditions );
01444     for( unsigned int conditionIdx = 0; conditionIdx < nConditions; ++conditionIdx ) {
01445 
01446         treeNameBase[conditionIdx] =
01447             CdbRooRoFileUtils::nameOfObjectsContainer( theConditionId[conditionIdx],
01448                                                        isPartitionableFlag,
01449                                                        thePartitionId,
01450                                                        theClusterId,
01451                                                        theIncrementId,
01452                                                        theOriginId ) + ".";
01453     }
01454 
01455   // Prepare two maps with executin plans for the conversion.
01456   //
01457   // NOTE: the element with index [0] is not used in the second plan. It's there just
01458   //       for the simplicity.
01459 
01460     std::map< UShort_t, CdbBdb2RooPayloadMainContainerContext* > mainExecutionPlan;
01461 
01462     std::vector< std::map< UShort_t, CdbBdb2RooPayloadExtraContainerContext* > > executionPlan( nConditions );
01463 
01464   // Create a map of object which are processes
01465   //
01466   // NOTE: When merging objects this map is used to track those cases when the same object
01467   //       is seen more then once and abort the procedure. Merging seems to be a non
01468   //       trivial thing in this case because the original identity of objects is going to be
01469   //       violated.
01470 
01471     std::map< std::string, bool > mapOfProcessedObjects;
01472 
01473   // Process each interval found in the collection
01474 
01475     if( debugModeFlag )
01476         cout << endl
01477              << "Conversion pass  I: preparing an execution plan..." << endl
01478              << endl;
01479 
01480     const UInt_t nIntervals = oiCollectionPtr[0]->size( );  // note, that this number also includes the interval
01481                                                             // with 0 index, which is used for special purposes
01482     assert( nIntervals > 0 );
01483 
01484     if( debugModeFlag )
01485         cout << "There are " << nIntervals - 1 << " intervals to be converted and merged." << endl;
01486 
01487     for( UInt_t idx = 1; idx < nIntervals; ++idx ) {
01488 
01489       // The validity intervals of found objects must also be synchronious. The corresponding
01490       // check will be done after the end of the evaluation loop.
01491       //
01492       // NOTE: This doesn't apply to the "duration" intervals as this parameter
01493       //       is meant to reflect when objects were actually stored in the database.
01494       //       CDB can't guarantee that two objects were stored at the same moment
01495       //       of time.
01496 
01497         std::vector< CdbRooRoOiR > oi( nConditions );
01498 
01499       // This is a vector of all objects to be merged.
01500 
01501         std::vector< BdbRef(BdbObject) > legacyObjectRef( nConditions );
01502 
01503       // Evaluate objects from all conditions
01504       //
01505       // IMPORTANT NOTE:
01506       //
01507       //   Note that extra objects are being processed first before the main one
01508       //   in the loop below. Otherwise the vector of the legacy objects defined
01509       //   above won't be usable. See details inseide the loop.
01510 
01511         for( int conditionIdx = nConditions - 1; conditionIdx >= 0; --conditionIdx ) {
01512 
01513             BdbTime beginOfDuration;    // not used by the current algorithm
01514             BdbTime   endOfDuration;    // not used by the current algorithm
01515 
01516             if( CdbStatus::Success != ( result = oiCollectionPtr[conditionIdx]->find( idx,
01517                                                                                       oi[conditionIdx],
01518                                                                                       beginOfDuration,
01519                                                                                       endOfDuration ))) {
01520                 cerr << errorStr << endl
01521                      << "    Failed to find an 'origina' interval with index = " << idx << endl;
01522                 return result;
01523             }
01524 
01525             if( debugModeFlag )
01526                 cout << "[" << conditionIdx << "]" << "  " << oi[conditionIdx].object( ) << " <-- " << oi[conditionIdx].legacyObjectAddress( ) << endl;
01527 
01528           // Check if the OID of the output object matches the current location of the "MetaData.<id>"
01529           // and "Objects.<id>" containers.
01530 
01531             if( ( oi[conditionIdx].object( ).origin   ( ) != theOriginId                  ) ||
01532                 ( oi[conditionIdx].object( ).condition( ) != theConditionId[conditionIdx] ) ||
01533                 ( oi[conditionIdx].object( ).cluster  ( ) != theClusterId                 ) ||
01534                 ( oi[conditionIdx].object( ).partition( ) != thePartitionId               ) ||
01535                 ( oi[conditionIdx].object( ).increment( ) != theIncrementId               )) {
01536 
01537                     cerr << errorStr << endl
01538                          << "    The output object address " << oi[conditionIdx].object( ) << " doesn't match" << endl
01539                          << "    the location of the output container." << endl;
01540                     return CdbStatus::Error;
01541             }
01542 
01543           // Abort if the main object has already been processed. And we don't care about
01544           // extra conditions.
01545 
01546             if( 0 == conditionIdx ) {
01547 
01548                 if( mapOfProcessedObjects.find( oi[conditionIdx].object( ).toString( )) != mapOfProcessedObjects.end( )) {
01549 
01550                     cerr << errorStr << endl
01551                          << "    An attempt to merge conditions with duplicate objects in the main" << endl
01552                          << "    condition has been detected. Aborting the operation." << endl;
01553 
01554                     ::printMetDataParameters( theOriginId,
01555                                               theConditionId[conditionIdx],
01556                                               isPartitionableFlag,
01557                                               thePartitionId,
01558                                               theClusterId,
01559                                               theIncrementId );
01560 
01561                     return CdbStatus::Error;
01562                 }
01563             }
01564             mapOfProcessedObjects[oi[conditionIdx].object( ).toString( )] = true;
01565 
01566           // Get the input persistent object first and verify if it exists
01567 
01568             if( !translate_OID( legacyObjectRef[conditionIdx],
01569                                 oi[conditionIdx].legacyObjectAddress( ))) {
01570                 cerr << errorStr << endl
01571                      << "    Failed to translate the OID of the legacy object: " << oi[conditionIdx].legacyObjectAddress( ) << endl;
01572                 return CdbStatus::Error;
01573             }
01574 
01575           // Get the final class of that persistent object and verify if it derives
01576           // from the BdbObject class.
01577 
01578             const std::string legacyObjectTypeName = legacyObjectRef[conditionIdx].typeName( );
01579             {
01580                 if( !CdbBdbSchemaUtils::instance( ).isA( legacyObjectRef[conditionIdx].typeN( ),
01581                                                          ooTypeN( BdbObject ))) {
01582                     cerr << errorStr << endl
01583                          << "    The legacy object doesn't derive from BdbObject: " << oi[conditionIdx].legacyObjectAddress( ) << endl;
01584                     return CdbStatus::Error;
01585                 }
01586             }
01587 
01588           // Create new container context if it doesn't exist yet, then put the found
01589           // original interval into this context.
01590           //
01591           // NOTES:
01592           //
01593           //   1. The order of original intervals is important to match ROID-s
01594           //      generated during the metadata conversion phase.
01595           //
01596           //   2. Also note that different execiton plans are used for the main and extra
01597           //      conditions.
01598 
01599             if( 0 == conditionIdx ) {
01600 
01601                 if( mainExecutionPlan.find( oi[conditionIdx].object( ).container( )) == mainExecutionPlan.end( )) {
01602 
01603                   // Build the name of the tree representing this container
01604 
01605                     const std::string treeName = treeNameBase[conditionIdx] + CdbStringUtils::toString( oi[conditionIdx].object( ).container( ));
01606 
01607                   // Check if the corresponding converter is available
01608 
01609                     CdbCPtr< CdbRooConverterBase > converterPtr = mergingConvertersDict( )->findByInputClassName( legacyObjectTypeName );
01610                     if( converterPtr.isNull( )) {
01611                         cerr << errorStr << endl
01612                              << "    No MERGING converter avaialble for the legacy class: " << legacyObjectTypeName << endl;
01613                         return CdbStatus::Error;
01614                     }
01615 
01616                   //
01617                   // VERY IMPORTANT NOTE: Due to a way this "xyz!@#$^%" ROOT I/O works one should always
01618                   //                      be sure that the proper "current file" is set before creating new
01619                   //                      TTree-s which is what is going to happen below.
01620 
01621 // cout << "gDirectory->GetName( ) = \"" << gDirectory->GetName( ) << "\"" << endl;
01622 // cout << "gFile->GetName( )      = \"" << gFile->GetName( )      << "\"" << endl;
01623 
01624                     databasePtr->Cd( "" );
01625                     gDirectory->Cd( databasePtr->GetPath( ));
01626 
01627 // cout << "gDirectory->GetName( ) = \"" << gDirectory->GetName( ) << "\"" << endl;
01628 // cout << "gFile->GetName( )      = \"" << gFile->GetName( )      << "\"" << endl;
01629 
01630                     mainExecutionPlan[oi[conditionIdx].object( ).container( )] = new CdbBdb2RooPayloadMainContainerContext( treeName,
01631                                                                                                                            "A tree for 'payload' objects" ,
01632                                                                                                                            converterPtr );
01633                 }
01634 
01635               // IMPORTANT NOTES:
01636               //
01637               //   1. When we're calling the "add" method below then we're relying on a fact that
01638               //   the main object is being processed after all extra objects have already been found.
01639               //   Otherwise the array with list of legacy objects won't be complete!!!
01640               //
01641               //   2. We're also "add"-ing records to the previously discovered containers for
01642               //   extra objects. We do it here since these extra objects should know where (a main object)
01643               //   their original contents is going to be moved to.
01644 
01645                 mainExecutionPlan[oi[conditionIdx].object( ).container( )]->add( legacyObjectRef,
01646                                                                                  oi[conditionIdx].object( ));
01647 
01648                 for( unsigned int extraConditionIdx = 1; extraConditionIdx < nConditions; ++extraConditionIdx ) {
01649 
01650                     const unsigned int containerId = oi[extraConditionIdx].object( ).container( );
01651 
01652                     executionPlan[extraConditionIdx][containerId]->add( legacyObjectRef[extraConditionIdx],
01653                                                                         oi[extraConditionIdx].object( ),
01654                                                                         oi[conditionIdx].object( ));
01655                 }
01656 
01657             } else {
01658 
01659               // Precreate the execution plan, but do _NOT_ add the found object to it. Thsi will
01660               // be done after the main object will be found. That's because extra objects will be replaced
01661               // with the "ObjectHasMoved" entries reffering back to the new home for the extra objects'
01662               // original contents.
01663 
01664                 if( executionPlan[conditionIdx].find( oi[conditionIdx].object( ).container( )) == executionPlan[conditionIdx].end( )) {
01665 
01666                   // Build the name of the tree representing this container
01667 
01668                     const std::string treeName = treeNameBase[conditionIdx] + CdbStringUtils::toString( oi[conditionIdx].object( ).container( ));
01669 
01670                   // No converter for extra objects because a special class known to the current
01671                   // application will be used to put dummy object into the extra conditions.
01672 
01673                     CdbCPtr< CdbRooConverterBase > converterPtr;
01674 
01675                   //
01676                   // VERY IMPORTANT NOTE: Due to a way this "xyz!@#$^%" ROOT I/O works one should always
01677                   //                      be sure that the proper "current file" is set before creating new
01678                   //                      TTree-s which is what is going to happen below.
01679 
01680 // cout << "gDirectory->GetName( ) = \"" << gDirectory->GetName( ) << "\"" << endl;
01681 // cout << "gFile->GetName( )      = \"" << gFile->GetName( )      << "\"" << endl;
01682 
01683                     databasePtr->Cd( "" );
01684                     gDirectory->Cd( databasePtr->GetPath( ));
01685 
01686 // cout << "gDirectory->GetName( ) = \"" << gDirectory->GetName( ) << "\"" << endl;
01687 // cout << "gFile->GetName( )      = \"" << gFile->GetName( )      << "\"" << endl;
01688 
01689                     executionPlan[conditionIdx][oi[conditionIdx].object( ).container( )] = new CdbBdb2RooPayloadExtraContainerContext( treeName,
01690                                                                                                                                        "A tree for 'payload' objects" ,
01691                                                                                                                                        converterPtr );
01692                 }
01693 
01694 // This operation has moved up to the same place when the main object is added
01695 // to its execution plan.
01696 //
01697 //                executionPlan[conditionIdx][oi[conditionIdx].object( ).container( )]->add( legacyObjectRef[conditionIdx],
01698 //                                                                                           oi[conditionIdx].object( ));
01699             }
01700         }
01701 
01702       // Check if conditions are synchronious
01703 
01704         for( unsigned int conditionIdx = 1; conditionIdx < nConditions; ++conditionIdx ) {
01705 
01706           // The validity intervals must be equal
01707 
01708             if( oi[0].begin( ) != oi[conditionIdx].begin( )) {
01709                 cerr << errorStr << endl
01710                      << "    Checked the begin validity time of objects in merged conditions and found" << endl
01711                      << "    that an attempt to merge asynchronious conditions is taking place." << endl;
01712                 return CdbStatus::Error;
01713             }
01714             if( oi[0].end( ) != oi[conditionIdx].end( )) {
01715                 cerr << errorStr << endl
01716                      << "    Checked the begin validity time of objects in merged conditions and found" << endl
01717                      << "    that an attempt to merge asynchronious conditions is taking place." << endl;
01718                 return CdbStatus::Error;
01719             }
01720         }
01721     }
01722 
01723     if( debugModeFlag )
01724         cout << endl
01725              << "Conversion pass II: performing the actual conversion..." << endl
01726              << endl;
01727 
01728   // Process the main condition first
01729 
01730     for( std::map< UShort_t, CdbBdb2RooPayloadMainContainerContext* >::iterator itr = mainExecutionPlan.begin( );
01731                                                                                 itr != mainExecutionPlan.end( );
01732                                                                               ++itr ) {
01733 
01734         CdbBdb2RooPayloadMainContainerContext* containerContext = (*itr).second;
01735 
01736       // Get the corresponding TBranch for that class
01737       //
01738       // DESIGN NOTE: A transient pointer passed to the constructor will be managed
01739       //              internally by the converter. See more details on how this
01740       //              converter is used insede an intervals conversion loop below.
01741 
01742         const char* branchName = "0";   // always use this branch name
01743 
01744         TBranch* branch = containerContext->converterPtr->branchConstructor( containerContext->tree,
01745                                                                              branchName );
01746 
01747         UInt_t nIntervals = containerContext->inObjects.size( );
01748         assert( nIntervals > 0 );
01749 
01750         for( UInt_t idx = 0; idx < nIntervals; ++idx ) {
01751 
01752             BdbRef(BdbObject) mainLegacyObjectRef = containerContext->inObjects[idx][0];
01753 
01754           // A vector of "extra" objects will have all but "main" ones. Teh main object is
01755           // supposed to be the first one in the input list, so we have to skip it.
01756 
01757             std::vector< BdbRef(BdbObject) >::iterator beginItr = containerContext->inObjects[idx].begin( );
01758             ++beginItr;
01759             std::vector< BdbRef(BdbObject) >::iterator   endItr = containerContext->inObjects[idx].end( );
01760 
01761             std::vector< BdbRef(BdbObject) > extraLegacyObjectRef( beginItr, endItr);
01762 
01763             CdbRooRoObjectIdR outputObjectId  = containerContext->outObjects[idx];
01764 
01765             if( debugModeFlag )
01766                 cout << "  " << outputObjectId << " <-- " << mainLegacyObjectRef.sprint( ) << " : \"" << containerContext->converterPtr->inputClassName( ) << "\"" << endl;
01767 
01768           // Use the converter
01769           //
01770           // DESIGN NOTE:
01771           //
01772           //   1. The actual object will be created and stored at a location known to
01773           //   above constructed TBranch inside the converter. We just need to make sure
01774           //   that the object is saved (see TTree::Fill()) operation in the current TTree,
01775           //
01776           //   2. Remember that the converter manages the lifetime of the created transient objects.
01777 
01778             {
01779                 if( CdbStatus::Success != ( result = containerContext->converterPtr->conversion( mainLegacyObjectRef,
01780                                                                                                  extraLegacyObjectRef ))) {
01781                     cerr << errorStr << endl
01782                          << "    Failed to convert the main legacy object " << mainLegacyObjectRef.sprint( ) << endl;
01783                     return result;
01784                 }
01785 
01786               // Store the object in the Tree/Branch
01787 
01788                 containerContext->tree.Fill( );
01789 
01790               // Make sure that the next available index in the branch matches the object index
01791               // in its OID.
01792 
01793                 if( debugModeFlag )
01794                     cout << "  tree->GetNbranches( ) = " << containerContext->tree.GetNbranches( ) << endl
01795                          << "  tree->GetEntries  ( ) = " << containerContext->tree.GetEntries( ) << endl
01796                          << "branch->GetEntries  ( ) = " << branch->GetEntries( ) << endl;
01797 
01798                 Long64_t objectIndexInBranch = branch->GetEntries( ) - 1;
01799 
01800                 if(( objectIndexInBranch < 0 ) ||
01801                    ( objectIndexInBranch >= 0xFFFF ) ||
01802                    ( objectIndexInBranch != outputObjectId.index( ))) {
01803 
01804                     cerr << errorStr << endl
01805                          << "    The just converted object " << outputObjectId << " produced from the legacy object " << mainLegacyObjectRef.sprint( ) << endl
01806                          << "    was writtent into a branch with a noon-valid index " << objectIndexInBranch << endl;
01807 
01808                     return CdbStatus::Error;
01809                 }
01810             }
01811         }
01812 
01813       // Save the tree in the file
01814 
01815         databasePtr->Cd( "" );
01816         gDirectory->Cd( databasePtr->GetPath( ));
01817 
01818         Int_t numBytesWritten = databasePtr->WriteObject( &containerContext->tree,
01819                                                           containerContext->tree.GetName( ));
01820         if( numBytesWritten <= 0 ) {
01821             cerr << errorStr << endl
01822                  << "    Failed to save the tree \"" << containerContext->tree.GetName( ) << "\" in the file: " << databasePtr->GetName( ) << endl;
01823             return CdbStatus::Error;
01824         }
01825         if( debugModeFlag )
01826             cout << endl
01827                  << "Total of " << nIntervals << " converted and stored into the tree \"" << containerContext->tree.GetName( ) << "\"." << endl
01828                  << endl;
01829 
01830       // Destroy the context
01831 
01832         delete containerContext;
01833     }
01834 
01835   // Process the extra conditions
01836 
01837     for( unsigned int conditionIdx = 1; conditionIdx < nConditions; ++conditionIdx ) {
01838 
01839         for( std::map< UShort_t, CdbBdb2RooPayloadExtraContainerContext* >::iterator itr = executionPlan[conditionIdx].begin( );
01840                                                                                      itr != executionPlan[conditionIdx].end( );
01841                                                                                    ++itr ) {
01842 
01843             CdbBdb2RooPayloadExtraContainerContext* containerContext = (*itr).second;
01844 
01845           // Get the corresponding TBranch for that class
01846 
01847             const char* branchName = "0";   // always use this branch name
01848 
01849             CdbRooObjectHasMovedR* dummyObjectPtr = 0;
01850 
01851             TBranch* branch = containerContext->tree.Branch( branchName,
01852                                                              "CdbRooObjectHasMovedR",
01853                                                              &dummyObjectPtr );
01854 
01855             UInt_t nIntervals = containerContext->inObjects.size( );
01856             assert( nIntervals > 0 );
01857 
01858             for( UInt_t idx = 0; idx < nIntervals; ++idx ) {
01859 
01860                 BdbRef(BdbObject)& legacyObjectRef = containerContext->inObjects[idx];
01861                 CdbRooRoObjectIdR& outputObjectId  = containerContext->outObjects[idx];
01862                 CdbRooRoObjectIdR&   mainObjectId  = containerContext->mainObjects[idx];
01863 
01864                 if( debugModeFlag )
01865                     cout << "  " << mainObjectId << " <== " << outputObjectId << " <-- " << legacyObjectRef.sprint( ) << " : \"" << legacyObjectRef.typeName( ) << "\"" << endl;
01866 
01867               // Store the same dummy object
01868               //
01869               // NOTE: We're not using any converters since we already have the final
01870               //       persistent class in the current framework.
01871 
01872                 {
01873                     if( 0 != dummyObjectPtr ) delete dummyObjectPtr;
01874                     dummyObjectPtr = new CdbRooObjectHasMovedR( mainObjectId.toString( ));
01875 
01876                   // Store the object in the Tree/Branch and get rif of a temporary transient object
01877 
01878                     containerContext->tree.Fill( );
01879 
01880                     if( 0 != dummyObjectPtr ) delete dummyObjectPtr;
01881                     dummyObjectPtr = 0;
01882 
01883                   // Make sure that the next available index in the branch matches the object index
01884                   // in its OID.
01885 
01886                     if( debugModeFlag )
01887                         cout << "  tree->GetNbranches( ) = " << containerContext->tree.GetNbranches( ) << endl
01888                              << "  tree->GetEntries  ( ) = " << containerContext->tree.GetEntries( ) << endl
01889                              << "branch->GetEntries  ( ) = " << branch->GetEntries( ) << endl;
01890 
01891                     Long64_t objectIndexInBranch = branch->GetEntries( ) - 1;
01892 
01893                     if(( objectIndexInBranch < 0 ) ||
01894                        ( objectIndexInBranch >= 0xFFFF ) ||
01895                        ( objectIndexInBranch != outputObjectId.index( ))) {
01896 
01897                         cerr << errorStr << endl
01898                              << "    The just converted object " << outputObjectId << " produced from the legacy object " << legacyObjectRef.sprint( ) << endl
01899                              << "    was writtent into a branch with a noon-valid index " << objectIndexInBranch << endl;
01900 
01901                         return CdbStatus::Error;
01902                     }
01903                 }
01904             }
01905             if( 0 != dummyObjectPtr ) delete dummyObjectPtr;
01906             dummyObjectPtr = 0;
01907 
01908           // Save the tree in the file
01909 
01910             databasePtr->Cd( "" );
01911             gDirectory->Cd( databasePtr->GetPath( ));
01912 
01913             Int_t numBytesWritten = databasePtr->WriteObject( &containerContext->tree,
01914                                                               containerContext->tree.GetName( ));
01915             if( numBytesWritten <= 0 ) {
01916                 cerr << errorStr << endl
01917                      << "    Failed to save the tree \"" << containerContext->tree.GetName( ) << "\" in the file: " << databasePtr->GetName( ) << endl;
01918                 return CdbStatus::Error;
01919             }
01920             if( debugModeFlag )
01921                 cout << endl
01922                      << "Total of " << nIntervals << " converted and stored into the tree \"" << containerContext->tree.GetName( ) << "\"." << endl
01923                      << endl;
01924 
01925           // Destroy the context
01926 
01927             delete containerContext;
01928         }
01929     }
01930     return CdbStatus::Success;
01931 }
01932 
01933 CdbBdb2RooPayloadConvertersDict*
01934 CdbBdb2RooPayloadConversionFwk::regularConvertersDict( )
01935 {
01936     static CdbBdb2RooPayloadConvertersDict myDict;
01937     return &myDict;
01938 }
01939 
01940 CdbBdb2RooPayloadConvertersDict*
01941 CdbBdb2RooPayloadConversionFwk::mergingConvertersDict( )
01942 {
01943     static CdbBdb2RooPayloadConvertersDict myDict;
01944     return &myDict;
01945 }
01946 
01947 /////////////////
01948 // End Of File //
01949 /////////////////

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