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

CdbBdbObjectVisitorUserAction.cc

Go to the documentation of this file.
00001 // File and Version Information:
00002 //      $Id: CdbBdbObjectVisitorUserAction.cc,v 1.5 2004/08/06 05:54:18 bartoldu Exp $
00003 
00004 /// The implementation of the CdbBdbObjectVisitorUserAction.
00005 /**
00006   * @see CdbBdbObjectVisitorUserAction
00007   */
00008 
00009 #include "BaBar/BaBar.hh"
00010 
00011 #include "CdbBdb/CdbBdbObjectVisitorUserAction.hh"
00012 #include "CdbBdb/CdbBdbObjectVisitorContext.hh"
00013 
00014 #include "BbrStdUtils/Tokenize.hh"
00015 #include "BbrStdUtils/String.hh"
00016 using namespace babar::String;
00017 
00018 #include "ErrLogger/ErrLog.hh"
00019 
00020 #include <fstream>
00021 #include <iostream>
00022 #include <iomanip>
00023 
00024 #include <stdio.h>
00025 #include <assert.h>
00026 using std::cout;
00027 using std::endl;
00028 using std::fstream;
00029 using std::ifstream;
00030 using std::setfill;
00031 using std::setw;
00032 
00033 namespace {
00034 
00035   ////////////////////////////////
00036   // Internal utility functions //
00037   ////////////////////////////////
00038 
00039   /// Try to match specified pattern with the current context
00040   /**
00041     * Note the following semantical differences between the context and teh pattern
00042     * (they both use the same class):
00043     *
00044     *   - a context is a current path of the visitor
00045     *   - a pattern is a class of paths.
00046     *   - the fields in patterns may represent a spectrum of possible values. Here are
00047     *     the conventions:
00048     *
00049     *     -- text:  "*" means any value
00050     *     -- index: 0xFFFFFFFF means any number
00051     *     -- ooRef: 0xFFFF-0xFFFF-0xFFFF-0xFFFF means any reference
00052     *
00053     * The matching algorithm would try to match the whole pattern starting
00054     * from the end of the context. The definition of success is when the whole
00055     * pattern fits into the end of context.
00056     */
00057     bool match_pattern( const CdbBdbObjectVisitorContext* theContext,
00058                         const CdbBdbObjectVisitorContext* thePattern );
00059 
00060   /// Print A context onto the standard output
00061   /**
00062     * More info...
00063     */
00064     void print_context(            const ooHandle(ooObj)& theInputH,
00065                         const CdbBdbObjectVisitorContext* theContext );
00066 
00067   /// Print a pattern onto the standard output
00068   /**
00069     * The pattern is printed in a waywhich is compatible with pattern translator.
00070     * So that these printed patterns could be loaded back and used for filtering.
00071     */
00072     void print_pattern( const CdbBdbObjectVisitorContext* theContext );
00073 
00074   /// Load patterns from the input file
00075   /**
00076     * The patterns have the same format the output of the above defined
00077     * method 'print_context' looks alike.
00078     */
00079     bool load_patterns( std::vector<CdbBdbObjectVisitorContext*>& theRepository,
00080                                                       const char* theFileName,
00081                                                              bool verboseMode,
00082                                                              bool debugMode );
00083 
00084   /// Extract a pair of a key and its value only from a string
00085   /**
00086     * The procedure gurantees (if successful) that only  avalid pair of key/value
00087     * is found in the stream.
00088     */
00089     bool extract_pair( const std::string& theExpectedKey,
00090                              std::string& theValue,
00091                                 ifstream& theStream,
00092                                      bool verboseMode,
00093                                      bool debugMode );
00094 
00095     /// Extract a pair of a key and its value or a pattern delimiter from a string
00096 
00097     bool extract_pair_or_delimiter( const std::string& theExpectedKey,
00098                                           std::string& theValue,
00099                                                  bool& isEndOfFile,
00100                                                  bool& isBegin,
00101                                                  bool& isEnd,
00102                                              ifstream& theStream,
00103                                                   bool verboseMode,
00104                                                   bool debugMode );
00105 
00106   /// Extract the value of an index
00107   /**
00108     * This procedure is used when reading and translating patterns from
00109     * an input file. Normally indeces are treated as plain numbers of 'size_t'
00110     * type unless the input string has '*' meaning "don't care about a concrete value".
00111     * In this case 0xFFFFFFFF is returned as an index's value.
00112     */
00113     bool extract_index(            size_t& theIndex,
00114                         const std::string& theStr,
00115                                       bool verboseMode,
00116                                       bool debugMode );
00117 
00118   /// Translate an OID string into an object of ooId class
00119   /**
00120     * Depending on a value of the last ('useHash'_ parameter the function
00121     * may also be tolerant to the '#' symbol preceeding OID-s.
00122     */
00123     bool translate_OID(       ooId& theId,
00124                         const char* theString,
00125                        bool useHash = false );
00126 
00127 };
00128 
00129 CdbBdbObjectVisitorUserAction::CdbBdbObjectVisitorUserAction(                const char* theSupressFile,
00130                                                               const std::list<d_UShort>* theDatabasesToIgnore,
00131                                                                                     bool verboseMode,
00132                                                                                     bool debugMode ) :
00133     _verboseMode   (verboseMode),
00134     _debugMode     (debugMode),
00135     _totalObjects  (0),
00136     _invalidObjects(0)
00137 {
00138     if( _debugMode ) _verboseMode = true;
00139 
00140   // Trunslate the list of patterns to be supressed (if any)
00141 
00142     if( 0 != theSupressFile ) {
00143 
00144         if( !load_patterns( _patternsToIgnore,
00145                             theSupressFile,
00146                             _verboseMode,
00147                             _debugMode )) {
00148 
00149             ErrMsg(fatal) << "failed to translate patterns to be ignored from the input file \"" << theSupressFile << "\"." << endmsg;
00150         }
00151         if( _verboseMode ) {
00152 
00153             cout << "PATTERNS TO BE IGNORED:" << endl;
00154 
00155             size_t num = _patternsToIgnore.size( );
00156             for( size_t i = 0; i < num; ++i )
00157                 print_pattern( _patternsToIgnore[i] );
00158 
00159             cout << "END OF PATTERNS." << endl;
00160         }
00161     }
00162 
00163   // Load a list of databases (by DBID-s) not to touch
00164 
00165     for( size_t db = 0; db <= MAX_DATABASE; ++db )
00166         _databasesToIgnore[db] = false;
00167 
00168     if( 0 != theDatabasesToIgnore ) {
00169         std::list<d_UShort>::const_iterator itr = theDatabasesToIgnore->begin( );
00170         while( theDatabasesToIgnore->end( ) != itr ) {
00171             _databasesToIgnore[*itr] = true;
00172             ++itr;
00173         }
00174     }
00175 
00176   // Clear statistics
00177 
00178     for( size_t db = 0; db <= MAX_DATABASE; ++db ) {
00179         _missingDatabase         [db] = 0;
00180         _clientsOfMissingDatabase[db] = 0;
00181         _dbidToName              [db] = "";
00182     }
00183 }
00184 
00185 CdbBdbObjectVisitorUserAction::~CdbBdbObjectVisitorUserAction( )
00186 {
00187     size_t num = _patternsToIgnore.size( );
00188     for( size_t i = 0; i < num; ++i ) delete _patternsToIgnore[i];
00189     _patternsToIgnore.clear( );
00190 
00191     for( size_t db = 0; db <= MAX_DATABASE; ++db )
00192         if( _missingDatabase[db] ) delete _clientsOfMissingDatabase[db];
00193 }
00194 
00195 CdbBdbObjectVisitorUserAction::ActionType
00196 CdbBdbObjectVisitorUserAction::action(            const ooHandle(ooObj)& theInputH,
00197                                        const CdbBdbObjectVisitorContext* theContext )
00198 {
00199     ooId     id = theInputH;
00200     d_UShort db = id.get_DB( );
00201 
00202   // FILTER #1 STEP
00203 
00204   // Skip the known databases
00205 
00206     if( _databasesToIgnore[db] ) {
00207 
00208 //////////////////////////////////////////////////////////////////////////////////////////
00209 if( _debugMode ) {
00210     cout << "STOPPING AT THE OBJECT (ITS DATABASE IS IN \"TO BE IGNORED\" LIST)." << endl;
00211     print_context( theInputH,
00212                    theContext );
00213 }
00214 //////////////////////////////////////////////////////////////////////////////////////////
00215 
00216             return ACTION_STOP;
00217     }
00218 
00219   // EVALUATION STEP : propagate the further decision to a user supplied
00220   //                   method if the passed object is valid.
00221 
00222     ++_totalObjects;
00223 
00224     if( theInputH.isValid( )) return userAction( theInputH,
00225                                                  theContext );
00226     ++_invalidObjects;
00227 
00228   // FILTER #2 STEP
00229 
00230   // Try known patterns to see if they could match the current context.
00231   // Note that matched cases do not contribute into the "missing/corrupted"
00232   // statistics.
00233 
00234     size_t num = _patternsToIgnore.size( );
00235     for( size_t i = 0; i < num; ++i ) {
00236         if( match_pattern( theContext, _patternsToIgnore[i] )) {
00237 
00238 ////////////////////////////////////////////////////////////////////////////////
00239 if( _debugMode ) {
00240     cout << "STOPPING AT THE OBJECT (MATCHED the PATTERN #" << i << ")" << endl;
00241     print_context( theInputH,
00242                    theContext );
00243 }
00244 ////////////////////////////////////////////////////////////////////////////////
00245 
00246             return ACTION_STOP;
00247         }
00248     }
00249 
00250   // STATISTICS STEP
00251 
00252   // For now just assume that object is not valid due to missing database.
00253   // In reality an existing database may also be corrupted. Therefore they
00254   // should be reported into a separate list.
00255 
00256     _missingDatabase[db]++;
00257     if( !update_missing_database_clients_list( _clientsOfMissingDatabase[db],
00258                                                theContext )) return ACTION_ERROR;
00259 
00260   // Simply print the current contex and report the problem upstream
00261 
00262     if( _verboseMode )
00263         print_context( theInputH,
00264                        theContext );
00265 
00266     return ACTION_STOP;
00267 }
00268 
00269 void
00270 CdbBdbObjectVisitorUserAction::print_statistics( ) const
00271 {
00272     cout << endl
00273          << "  *** VISITED OBJECTS REPORT ***" << endl
00274          << endl
00275          << "  ------------------------+-----------------------" << endl
00276          << "    TOTAL OBJECTS VISITED : INVALID OBJECTS FOUND " << endl
00277          << "  ------------------------+-----------------------" << endl
00278          << endl
00279          << "    "
00280          << setw( 21 ) << setfill( ' ' ) << _totalObjects
00281          << " : "
00282          << setw( 21 ) << setfill( ' ' ) << _invalidObjects << endl
00283          << endl
00284          << "  *** MISSING DATABASES REPORT ***" << endl
00285          << endl
00286          << "  ----------+------------+------" << endl
00287          << "   DATABASE : REFERENCES : FROM " << endl
00288          << "  ----------+------------+------" << endl;
00289 
00290     for( size_t db = 0; db <= MAX_DATABASE; ++db ) {
00291         if( _missingDatabase[db] ) {
00292 
00293             cout << "   "
00294                  << setw( 8 ) << setfill( ' ' ) << db
00295                  << " : "
00296                  << setw( 10 ) << setfill( ' ' ) << _missingDatabase[db]
00297                  << " : ";
00298 
00299             std::map<d_UShort,std::string>::iterator itr =  _clientsOfMissingDatabase[db]->begin( );
00300             while( itr != _clientsOfMissingDatabase[db]->end( )) {
00301                 cout << (*itr).second.c_str( ) << " ";
00302                 ++itr;
00303             }
00304             cout << endl;
00305         }
00306     }
00307     cout << "  ----------+------------+------" << endl;
00308 }
00309 
00310 unsigned int
00311 CdbBdbObjectVisitorUserAction::missedCounters( d_UShort theDatabaseId ) const
00312 {
00313     if( theDatabaseId > MAX_DATABASE )
00314         ErrMsg(fatal) << "an out-of-range database number " << theDatabaseId << " passed" << endl
00315                       << "into the method. The allowed range is between 0 and " << MAX_DATABASE << endl;
00316 
00317     return _missingDatabase[theDatabaseId];
00318 }
00319 
00320 const std::map<d_UShort,std::string>*
00321 CdbBdbObjectVisitorUserAction::missedDatabaseClients( d_UShort theDatabaseId ) const
00322 {
00323     if( theDatabaseId > MAX_DATABASE )  
00324         ErrMsg(fatal) << "an out-of-range database number " << theDatabaseId << " passed" << endl
00325                       << "into the method. The allowed range is between 0 and " << MAX_DATABASE << endl;
00326 
00327     return _clientsOfMissingDatabase[theDatabaseId];
00328 }
00329 
00330 CdbBdbObjectVisitorUserAction::ActionType
00331 CdbBdbObjectVisitorUserAction::userAction(            const ooHandle(ooObj)& theInputH,
00332                                            const CdbBdbObjectVisitorContext* theContext )
00333 {
00334     return ACTION_PROCEED;
00335 }
00336 
00337 bool
00338 CdbBdbObjectVisitorUserAction::update_missing_database_clients_list(  std::map<d_UShort,std::string>*& theClients,
00339                                                                      const CdbBdbObjectVisitorContext* theContext )
00340 {
00341     if( 0 == theClients ) theClients = new std::map<d_UShort,std::string>( );
00342 
00343   // Find the direct client of the missing database by browsing
00344   // the current context from its last element.
00345 
00346   // Note, 'signed int' rather than 'unsigned int' should always be used
00347   // in decrement loops to prevent going through 0 to the upper numbers.
00348 
00349     size_t contextSize = theContext->size( );
00350     for( int i = contextSize - 1; i >= 0; --i ) {
00351 
00352         const CdbBdbObjectVisitorContext::Element& context = (*theContext)[i];
00353 
00354         if( CdbBdbObjectVisitorContext::Element::OBJECT == context.type( )) {
00355 
00356             const ooId     id = context.ref( );
00357             const d_UShort db = id.get_DB( );
00358 
00359           // Proceed with obtaining the database name only if this database identifier
00360           // is not in the list of clients yet.
00361 
00362             if( theClients->end( ) == theClients->find( db )) {
00363                 if( "" == _dbidToName[db] )
00364                     _dbidToName[db] = context.ref( ).containedIn( ).containedIn( ).name( );
00365 
00366                 (*theClients)[db] = _dbidToName[db];
00367             }
00368             return true;
00369         }
00370     }
00371 
00372  // The failure to find an object is considered a error.
00373 
00374     ErrMsg(error) << "failed to find the cleint object." << endmsg;
00375 
00376     return false;
00377 }
00378 
00379 //////////////////////////////////////////////////
00380 // Implementation of internal utility functions //
00381 //////////////////////////////////////////////////
00382 
00383 namespace {
00384 
00385 bool
00386 match_pattern( const CdbBdbObjectVisitorContext* theContext,
00387                const CdbBdbObjectVisitorContext* thePattern )
00388 {
00389     ooId anyId;
00390     anyId.set_DB  ( 0xFFFF );
00391     anyId.set_OC  ( 0xFFFF );
00392     anyId.set_page( 0xFFFF );
00393     anyId.set_slot( 0xFFFF );
00394 
00395     const  std::string anyName  = "*";
00396     const       size_t anyIndex = 0xFFFFFFFF;
00397     const ooRef(ooObj) anyRef   = anyId;
00398 
00399     size_t contextSize = theContext->size( );
00400     size_t patternSize = thePattern->size( );
00401 
00402   // The context should be at least of the same length...
00403 
00404     if( patternSize > contextSize ) return false;
00405 
00406   // Note, 'signed int' rather than 'unsigned int' should always be used
00407   // in decrement loops to prevent going through 0 to the upper numbers.
00408 
00409     for( int i = patternSize - 1; i >= 0; --i ) {
00410 
00411         const CdbBdbObjectVisitorContext::Element& context = (*theContext)[ i + contextSize - patternSize ];
00412         const CdbBdbObjectVisitorContext::Element& pattern = (*thePattern)[ i ];
00413 
00414         if( pattern.type( ) != context.type( )) return false;
00415 
00416         switch( pattern.type( )) {
00417 
00418         case CdbBdbObjectVisitorContext::Element::OBJECT :
00419 
00420             if(     pattern.ref( ) != anyRef )
00421                 if( pattern.ref( ) != context.ref( )) return false;
00422 
00423             if(     pattern.name( ) != anyName )
00424                 if( pattern.name( ) != context.name( )) return false;
00425 
00426             break;
00427 
00428         case CdbBdbObjectVisitorContext::Element::EMBEDDED_OBJECT :
00429 
00430             if(     pattern.name( ) != anyName )
00431                 if( pattern.name( ) != context.name( )) return false;
00432 
00433             if(     pattern.name_2( ) != anyName )
00434                 if( pattern.name_2( ) != context.name_2( )) return false;
00435 
00436             if(     pattern.index( ) != anyIndex )
00437                 if( pattern.index( ) != context.index( )) return false;
00438 
00439             break;
00440 
00441 
00442         case CdbBdbObjectVisitorContext::Element::REFERENCE :
00443 
00444             if(     pattern.name( ) != anyName )
00445                 if( pattern.name( ) != context.name( )) return false;
00446 
00447             if(     pattern.index( ) != anyIndex )
00448                 if( pattern.index( ) != context.index( )) return false;
00449 
00450             break;
00451 
00452         case CdbBdbObjectVisitorContext::Element::BASE_CLASS :
00453         case CdbBdbObjectVisitorContext::Element::MAP_ELEMENT :
00454         case CdbBdbObjectVisitorContext::Element::MANY_RELATIONSHIP :
00455         case CdbBdbObjectVisitorContext::Element::ONE_RELATIONSHIP :
00456 
00457             if(     pattern.name( ) != anyName )
00458                 if( pattern.name( ) != context.name( )) return false;
00459 
00460             break;
00461 
00462         default:
00463 
00464             return false;
00465         }
00466     }
00467     return true;
00468 }
00469 
00470 void
00471 print_context(            const ooHandle(ooObj)& theInputH,
00472                const CdbBdbObjectVisitorContext* theContext )
00473 {
00474     cout << "VISITOR CONTEXT FOR " << theInputH.sprint( ) << " IS" << endl;
00475     print_pattern( theContext );
00476 }
00477 
00478 void
00479 print_pattern( const CdbBdbObjectVisitorContext* theContext )
00480 {
00481     cout << "{" << endl;
00482 
00483     size_t num = theContext->size( );
00484     for( size_t i = 0; i < num; ++i ) {
00485 
00486         if( i > 0 )
00487             cout << endl;
00488 
00489         switch((*theContext)[i].type( )) {
00490 
00491         case CdbBdbObjectVisitorContext::Element::OBJECT :
00492 
00493             cout << "  TYPE       : <OBJECT>" << endl
00494                  << "  OID        : " << (*theContext)[i].ref( ).sprint( ) << endl
00495                  << "  CLASS_NAME : " << (*theContext)[i].name( ).c_str( ) << endl;
00496             break;
00497 
00498         case CdbBdbObjectVisitorContext::Element::BASE_CLASS :
00499 
00500             cout << "  TYPE       : <BASE_CLASS>" << endl
00501                  << "  CLASS_NAME : " << (*theContext)[i].name( ).c_str( ) << endl;
00502             break;
00503 
00504         case CdbBdbObjectVisitorContext::Element::EMBEDDED_OBJECT :
00505 
00506             cout << "  TYPE       : <EMBEDDED_OBJECT>" << endl
00507                  << "  CLASS_NAME : " << (*theContext)[i].name( ).c_str( ) << endl
00508                  << "  NAME       : " << (*theContext)[i].name_2( ).c_str( ) << endl
00509                  << "  INDEX      : " << (*theContext)[i].index( ) << endl;
00510             break;
00511 
00512         case CdbBdbObjectVisitorContext::Element::MAP_ELEMENT :
00513 
00514             cout << "  TYPE       : <MAP_ELEMENT>" << endl
00515                  << "  KEY        : " << (*theContext)[i].name( ).c_str( ) << endl;
00516             break;
00517 
00518         case CdbBdbObjectVisitorContext::Element::REFERENCE :
00519 
00520             cout << "  TYPE       : <REFERENCE>" << endl
00521                  << "  NAME       : " << (*theContext)[i].name( ).c_str( ) << endl
00522                  << "  INDEX      : " << (*theContext)[i].index( ) << endl;
00523             break;
00524 
00525         case CdbBdbObjectVisitorContext::Element::MANY_RELATIONSHIP :
00526 
00527             cout << "  TYPE       : <MANY_RELATIONSHIP>" << endl
00528                  << "  NAME       : " << (*theContext)[i].name( ).c_str( ) << endl;
00529             break;
00530 
00531         case CdbBdbObjectVisitorContext::Element::ONE_RELATIONSHIP :
00532 
00533             cout << "  TYPE       : <ONE_RELATIONSHIP>" << endl
00534                  << "  NAME       : " << (*theContext)[i].name( ).c_str( ) << endl;
00535             break;
00536 
00537         default:
00538 
00539             cout << "  TYPE       : <unknown>" << endl;
00540             break;
00541         }
00542     }
00543     cout << "}" << endl;
00544 }
00545 
00546 bool
00547 load_patterns( std::vector<CdbBdbObjectVisitorContext*>& theRepository,
00548                                              const char* theFileName,
00549                                                     bool verboseMode,
00550                                                     bool debugMode )
00551 {
00552     assert( 0 != theFileName );  // a fatal error in the class's implementation
00553 
00554   // Clear the repository
00555 
00556     theRepository.clear( );
00557 
00558   // Open a file with a list of patterns
00559 
00560     ifstream inFile( theFileName );
00561     if( !inFile.good( )) {
00562         ErrMsg(error) << "failed to open specified input file." << endmsg;
00563         return false;
00564     }
00565 
00566   // Read patterns, translate them and put them into the repository
00567 
00568     CdbBdbObjectVisitorContext* currentPattern = 0;
00569     do {
00570         std::string type;
00571         bool        isEndOfFile = false;
00572         bool        isBegin     = false;
00573         bool        isEnd       = false;
00574         if( !extract_pair_or_delimiter( "TYPE",
00575                                         type,
00576                                         isEndOfFile,
00577                                         isBegin,
00578                                         isEnd,
00579                                         inFile,
00580                                         verboseMode,
00581                                         debugMode )) return false;
00582         if( isEndOfFile ) break;
00583         if( isBegin ) {
00584 
00585           // Check if we're not ie middle of a previous pattern
00586 
00587             if( 0 != currentPattern ) {
00588                 ErrMsg(error) << "wrong format of the input file. The previous pattern was not properly closed." << endmsg;
00589                 return false;
00590             }
00591 
00592           // Begin a new one
00593 
00594             currentPattern = new CdbBdbObjectVisitorContext( );
00595 
00596         } else if( isEnd ) {
00597 
00598           // Make sure that we're already processing a pattern
00599 
00600             if( 0 == currentPattern ) {
00601                 ErrMsg(error) << "wrong format of the input file. A stray closing paranthesis not related to any pattern found."<< endmsg;
00602                 return false;
00603             }
00604 
00605           // Put a new pattern into a list and get ready to scan the next pattern
00606 
00607             theRepository.push_back( currentPattern );
00608             currentPattern = 0;
00609 
00610         } else {
00611 
00612           // We're processing next node in the current pattern. The whole node is expected
00613           // to be processed in the current block.
00614 
00615             if( "<OBJECT>" == type ) {
00616 
00617                 std::string oid;
00618                 std::string className;
00619                 if( !extract_pair( "OID",        oid,       inFile, verboseMode, debugMode )) return false;
00620                 if( !extract_pair( "CLASS_NAME", className, inFile, verboseMode, debugMode )) return false;
00621 
00622               // Note, when translating OID-s from patterns we should also take into
00623               // account that there will be the '#' symbol preceeding the actual OID.
00624 
00625                 ooId id;
00626                 if( !translate_OID( id, oid.c_str( ), true )) return false;
00627                 ooRef(ooObj) ref = id;
00628 
00629                 currentPattern->push( CdbBdbObjectVisitorContext::Element::createObject( ref,
00630                                                                                          className.c_str( )));
00631 
00632             } else if( "<BASE_CLASS>" == type ) {
00633 
00634                 std::string className;
00635                 if( !extract_pair( "CLASS_NAME", className, inFile, verboseMode, debugMode )) return false;
00636 
00637                 currentPattern->push( CdbBdbObjectVisitorContext::Element::createBaseClass( className.c_str( )));
00638 
00639             } else if( "<EMBEDDED_OBJECT>" == type ) {
00640 
00641                 std::string className;
00642                 std::string name;
00643                 std::string indexStr;
00644                 if( !extract_pair( "CLASS_NAME", className, inFile, verboseMode, debugMode )) return false;
00645                 if( !extract_pair( "NAME",       name,      inFile, verboseMode, debugMode )) return false;
00646                 if( !extract_pair( "INDEX",      indexStr,  inFile, verboseMode, debugMode )) return false;
00647 
00648                 size_t index;
00649                 if( !extract_index( index, indexStr, verboseMode, debugMode )) return false;
00650 
00651                 currentPattern->push( CdbBdbObjectVisitorContext::Element::createEmbeddedObject( className.c_str( ),
00652                                                                                                  name.c_str( ),
00653                                                                                                  index ));
00654 
00655             } else if( "<MAP_ELEMENT>" == type ) {
00656 
00657                 std::string key;
00658                 if( !extract_pair( "KEY", key, inFile, verboseMode, debugMode )) return false;
00659 
00660                 currentPattern->push( CdbBdbObjectVisitorContext::Element::createMapElement( key.c_str( )));
00661 
00662             } else if( "<REFERENCE>" == type ) {
00663 
00664                 std::string name;
00665                 std::string indexStr;
00666                 if( !extract_pair( "NAME",  name,     inFile, verboseMode, debugMode )) return false;
00667                 if( !extract_pair( "INDEX", indexStr, inFile, verboseMode, debugMode )) return false;
00668 
00669                 size_t index;
00670                 if( !extract_index( index, indexStr, verboseMode, debugMode )) return false;
00671 
00672                 currentPattern->push( CdbBdbObjectVisitorContext::Element::createReference( name.c_str( ),
00673                                                                                             index ));
00674 
00675             } else if( "<MANY_RELATIONSHIP>" == type ) {
00676 
00677                 std::string name;
00678                 if( !extract_pair( "NAME", name, inFile, verboseMode, debugMode )) return false;
00679 
00680                 currentPattern->push( CdbBdbObjectVisitorContext::Element::createManyRelationship( name.c_str( )));
00681 
00682             } else if( "<ONE_RELATIONSHIP>" == type ) {
00683 
00684                 std::string name;
00685                 if( !extract_pair( "NAME", name, inFile, verboseMode, debugMode )) return false;
00686 
00687                 currentPattern->push( CdbBdbObjectVisitorContext::Element::createOneRelationship( name.c_str( )));
00688 
00689             } else {
00690                 ErrMsg(error) << "unknown type: \"" << type << "\"." << endmsg;
00691                 return false;
00692             }
00693         }
00694 
00695     } while( true );
00696 
00697     return true;
00698 }
00699 
00700 bool extract_pair( const std::string& theExpectedKey,
00701                          std::string& theValue,
00702                             ifstream& theStream,
00703                                  bool verboseMode,
00704                                  bool debugMode )
00705 {
00706     bool isEndOfFile = false;
00707     bool isBegin     = false;
00708     bool isEnd       = false;
00709 
00710   // Firstly, the translation must succeed
00711 
00712     if( !extract_pair_or_delimiter( theExpectedKey,
00713                                     theValue,
00714                                     isEndOfFile,
00715                                     isBegin,
00716                                     isEnd,
00717                                     theStream,
00718                                     verboseMode,
00719                                     debugMode )) return false;
00720 
00721   // Secondly, it should not be a special case
00722 
00723     return ! ( isEndOfFile || isBegin || isEnd );
00724 }
00725 
00726 bool
00727 extract_pair_or_delimiter( const std::string& theExpectedKey,
00728                                  std::string& theValue,
00729                                         bool& isEndOfFile,
00730                                         bool& isBegin,
00731                                         bool& isEnd,
00732                                     ifstream& theStream,
00733                                          bool verboseMode,
00734                                          bool debugMode )
00735 {
00736     isEndOfFile = false;
00737     isBegin     = false;
00738     isEnd       = false;
00739 
00740   // Read until either end of file or reconized contents is met
00741 
00742     char buf[1024];
00743     while( theStream.getline( buf, 1024, '\n' )) {
00744 
00745 //////////////////////////////////////////////////////////
00746 if( debugMode ) {
00747 cout << "READ FROM INPUT FILE: \"" << buf << "\"" << endl;
00748 }
00749 //////////////////////////////////////////////////////////
00750 
00751       // Skip empty lines
00752 
00753         if( 0 == strlen( buf )) continue;
00754 
00755       // Check if it's either begin or end paranthesis
00756 
00757         if( 0 == strcmp( "{" , buf )) {
00758             isBegin = true;
00759             return true;
00760         }
00761         if( 0 == strcmp( "}" , buf )) {
00762             isEnd = true;
00763             return true;
00764         }
00765 
00766       // Break the line into tokens
00767 
00768         std::string str( buf );
00769         Tokenize tokenize( str );
00770 
00771         std::string       key = tokenize( );
00772         std::string separator = tokenize( );
00773                      theValue = tokenize( );
00774 
00775         if( key.empty( ) || separator.empty( ) || ( ":" != separator ) || theValue.empty( )) {
00776 
00777             ErrMsg(error) << "illegal syntax of the input file. Pairs of keys and values separated by ':' were expected." << endl
00778                           << "found at line \"" << buf << "\"." << endmsg;
00779             return false;
00780         }
00781 
00782       // Check if the keys is correct
00783 
00784         if( theExpectedKey != key ) {
00785             ErrMsg(error) << "unexpected key found in the input file." << endl
00786                  << "    EXPECTED KEY: \"" << theExpectedKey.c_str( ) << "\"" << endl
00787                  << "    FOUND    KEY: \"" <<            key.c_str( ) << "\"" << endl
00788                  << "found at line \"" << buf << "\"" << endmsg;
00789             return false;
00790         }
00791         return true;
00792     }
00793 
00794   // The only condition we can gete here is when EOF has reeched.
00795 
00796     isEndOfFile = true;
00797 
00798     return true;
00799 }
00800 
00801 bool
00802 extract_index(            size_t& theIndex,
00803                const std::string& theStr,
00804                              bool verboseMode,
00805                              bool debugMode )
00806 {
00807     if( "*" == theStr ) {
00808         theIndex = 0xFFFFFFFF;
00809     } else {
00810         if( 1 != sscanf( theStr.c_str( ), "%ud", &theIndex )) {
00811             ErrMsg(error) << "failed to translate gather an index value from specified string." << endl
00812                           << "The string was \"" << theStr.c_str( ) << "\"." << endmsg;
00813             return false;
00814         }
00815     }
00816     return true;
00817 }
00818 
00819 bool
00820 translate_OID(       ooId& theId,
00821                const char* theString,
00822                bool useHash )
00823 {
00824     bool result = false;
00825 
00826     do {
00827         if( 0 == theString ) {
00828             ErrMsg(error) << "empty string passed where an OID was expeted." << endmsg;
00829             break;
00830         }
00831 
00832         int db;
00833         int cont;
00834         int page;
00835         int slot;
00836 
00837         const char* format = ( useHash ? "#%d-%d-%d-%d" : "%d-%d-%d-%d" );
00838         if( 4 != sscanf( theString, format, &db, &cont, &page, &slot )) {
00839             ErrMsg(error) << "illegal format of the OID string \"" << theString << "\"." << endmsg;
00840             break;
00841         }
00842         theId.set_DB  ( db );
00843         theId.set_OC  ( cont );
00844         theId.set_page( page );
00845         theId.set_slot( slot );
00846 
00847         result = true;
00848 
00849     } while( false );
00850 
00851     return true;
00852 }
00853 };
00854 
00855 /////////////////
00856 // End Of File //
00857 /////////////////

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