Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

DbmModule.cxx

Go to the documentation of this file.
00001 
00002 // Dbm                                                                //
00003 //                                                                    //
00004 // package: Dbm (Database Maintenance).                               //
00005 //                                                                    //
00006 // Driver module.                                                     //
00007 //                                                                    //
00008 // N. West  08/2001                                                   //
00010 
00011 #include <algorithm>
00012 #include <fstream>
00013 #include <memory>
00014 using std::auto_ptr;
00015 #include <sstream>
00016 
00017 #include "Conventions/Detector.h"
00018 #include "Conventions/SimFlag.h"
00019 
00020 #include "DatabaseInterface/Dbi.h"
00021 #include "DatabaseInterface/DbiExceptionLog.h"
00022 #include "DatabaseInterface/DbiDBProxy.h"
00023 #include "DatabaseInterface/DbiCascader.h"
00024 #include "DatabaseInterface/DbiConfigSet.h"
00025 #include "DatabaseInterface/DbiResultKey.h"
00026 #include "DatabaseInterface/DbiResultPtr.h"
00027 #include "DatabaseInterface/DbiSqlValPacket.h"
00028 #include "DatabaseInterface/DbiStatement.h"
00029 #include "DatabaseInterface/DbiTableProxyRegistry.h"
00030 #include "DatabaseInterface/DbiTimerManager.h"
00031 #include "DatabaseInterface/DbiValidityRec.h"
00032 #include "DatabaseInterface/DbiValRecSet.h"
00033 #include "DatabaseInterface/DbiTableProxy.h"
00034 #include "DatabaseInterface/DbiTableProxyRegistry.h"
00035 #include "DatabaseInterface/DbiWriter.h"
00036 
00037 #include "DatabaseMaintenance/DbmCmdOptions.h"
00038 #include "DatabaseMaintenance/DbmLogFile.h"
00039 #include "DatabaseMaintenance/DbmModule.h"
00040 #include "DatabaseMaintenance/DbmNameFilter.h"
00041 
00042 #include "LeakChecker/LeaLeakChecker.h"
00043 #include "JobControl/JobCModuleRegistry.h" 
00044 #include "JobControl/JobCommand.h" 
00045 
00046 #include "MessageService/MsgService.h"     
00047 
00048 #include "TSQLStatement.h"
00049 
00050 #include "Util/MsgUtil.h"
00051 #include "Validity/VldContext.h"
00052 #include "Validity/VldTimeStamp.h"
00053 
00054 
00055 using namespace std;
00056 
00057 ClassImp(DbmModule)
00058 
00059 CVSID("$Id: DbmModule.cxx,v 1.63 2007/11/11 07:41:21 rhatcher Exp $");
00060 
00061 JOBMODULE(DbmModule,"DbmModule","Database Maintenance");
00062 
00063 //.....................................................................
00064 
00065 DbmModule::DbmModule() :
00066 fCascader(DbiTableProxyRegistry::Instance().GetCascader()),
00067 fValRecSet(0)
00068 {
00069 //
00070 //
00071 //  Purpose:  Default constructor
00072 //
00073 //  Arguments:  None.
00074 //
00075 //  Return:    n/a
00076 //
00077 //  Contact:   N. West
00078 //
00079 //  Specification:-
00080 //  =============
00081 //
00082 //  o  Create a DbmModule.
00083 
00084 
00085 //  Program Notes:-
00086 //  =============
00087 
00088 //  None.
00089 
00090   LEA_CTOR    //Leak Checker
00091 
00092     //  MsgService::Instance()->GetStream("Dbi")->SetLogLevel(Msg::kVerbose);
00093     //  MsgService::Instance()->GetStream("Dbm")->SetLogLevel(Msg::kDebug);
00094   MSG("Dbm", Msg::kVerbose) << "Creating DbmModule" << endl;
00095   
00096 }
00097 
00098 //.....................................................................
00099 
00100 DbmModule::~DbmModule() {
00101 //
00102 //
00103 //  Purpose: Destructor
00104 //
00105 //  Arguments: 
00106 //    None.
00107 //
00108 //  Return:    n/a
00109 //
00110 //  Contact:   N. West
00111 //
00112 //  Specification:-
00113 //  =============
00114 //
00115 //  o  Destroy DbmModule.
00116 
00117 
00118 //  Program Notes:-
00119 //  =============
00120 
00121 //  None.
00122 
00123   LEA_DTOR    //Leak Checker
00124 
00125   MSG("Dbm", Msg::kVerbose) << "Destroying DbmModule" << endl;
00126 
00127   ClearCache();
00128 
00129 }
00130 
00131 //.....................................................................
00132 
00133 Bool_t DbmModule::ApplySQLFixup(UInt_t dbNo,
00134                                 ifstream& in, 
00135                                 DbmLogFile& logFile,
00136                                 Bool_t enabled) {
00137 //
00138 //
00139 //  Purpose:  Apply any SQL fixups at the start of update file in and log
00140 //
00141 //               SQL fixup lines start: SQL:
00142 //
00143 //            Return true if no errors detected.
00144 
00145   auto_ptr<DbiStatement> stmtDb(DbiTableProxyRegistry::Instance()
00146                               .GetCascader()
00147                               .CreateStatement(dbNo) );
00148   if ( ! stmtDb.get() ) {
00149     MSG("Dbm",Msg::kWarning) 
00150       << "Attempting to write to non-existant cascade entry " << dbNo
00151       << endl;
00152    return kFALSE;
00153   }
00154 
00155   // Use peek to look one character ahead without disturbing input;
00156   // we must not read the start of the first update record.
00157 
00158   while ( in.peek() == 'S' ) {
00159     string line;
00160     getline(in,line);
00161     if ( line.substr(0,4) != "SQL:" ) {
00162       MSG("Dbm",Msg::kError) 
00163         << "SQL Fixup line does not start: SQL: " << line
00164         << endl;
00165      return kFALSE;
00166     }
00167 
00168     //Remove anything after last ';'
00169     string::size_type locSemiColon = line.rfind(';');
00170     if ( locSemiColon == string::npos )  {
00171       MSG("Dbm",Msg::kError) 
00172         << "SQL Fixup line does not end with semicolon: " << line
00173         << endl;
00174      return kFALSE;
00175     }
00176     line.erase(locSemiColon+1);
00177 
00178     if ( enabled ) {
00179       //some hackery to make sure data gets deleted before VLD entry
00180       std::string::size_type p;
00181       if((line.find("delete from ")!=std::string::npos) &&
00182          ((p=line.find("VLD"))!=std::string::npos)){
00183         std::string noVLD=line.substr(0,p);
00184         noVLD+=line.substr(p+3);
00185         stmtDb->ExecuteUpdate(noVLD.substr(4).c_str());
00186         logFile.LogMsg(line,kFALSE);
00187         if ( stmtDb->PrintExceptions() ) logFile.LogMsg("   - above command failed.",kFALSE);
00188       }
00189       stmtDb->ExecuteUpdate(line.substr(4).c_str());
00190       logFile.LogMsg(line,kFALSE);
00191       if ( stmtDb->PrintExceptions() ) logFile.LogMsg("   - above command failed.",kFALSE);
00192     }
00193     else {
00194       string msg("SQL fixup disabled. Ignoring :");
00195       msg += line;
00196       logFile.LogMsg(msg,kFALSE);
00197     }
00198 
00199   }
00200   return kTRUE;
00201 
00202 }
00203 
00204 //.....................................................................
00205 
00206 Bool_t DbmModule::BuildValRecSet(const string& tableName,UInt_t dbNo) {
00207 //
00208 //
00209 //  Purpose:  If necessary, rebuild DbiValidityRec for selected table.
00210 //
00211 //  Arguments: 
00212 //    tableName    in    Name of selected table.
00213 //    dbNo         in    Cascade number of Database to be used.
00214 //
00215 //  Return:    kTRUE if table successfully built (or already exists)
00216 //
00217 //  Contact:   N. West
00218 //
00219 //  Specification:-
00220 //  =============
00221 //
00222 //  o If fValRecSet does not point at DbiValidityRec of requested
00223 //    table then rebuild it.
00224 
00225 //  Program Notes:-
00226 //  =============
00227 
00228 //  fValRecSet is just a cache to reduce the number of builds
00229 //  of a DbiValRecSet for a given table.  For example the Export
00230 //  method requires it but calls the GlobaliseSeqNo method which
00231 //  also requires it.
00232 
00233   if (    fValRecSet 
00234        && (    fValRecSet->GetTableName() != (tableName+"VLD") 
00235             || fValRecSet->GetDbNo()      != dbNo ) ) {
00236     MSG("Dbm", Msg::kDebug) << "(Dropping Table "
00237                            << fValRecSet->GetTableName() << ")" << endl;
00238     ClearCache();
00239   }
00240 
00241   if ( ! fValRecSet ) {
00242     MSG("Dbm", Msg::kDebug) << "Reading Table " << tableName
00243                            << "..." << endl;
00244     
00245     fValRecSet = new DbiValRecSet(tableName,dbNo);
00246   }
00247 
00248   int numRows = fValRecSet->GetNumRows();
00249   if ( numRows ) {
00250     MSG("Dbm", Msg::kInfo) << "Table " << tableName
00251                            << " contains " << numRows
00252                            << " sequence numbers" << endl;
00253   }
00254   else {
00255     MSG("Dbm", Msg::kDebug) << "Table " << tableName
00256                            << " missing or empty!" << endl;
00257   }
00258 
00259   return numRows > 0;
00260 
00261 }
00262 
00263 //.....................................................................
00264 
00265 Bool_t DbmModule::CheckMemory(JobCommand *cmd) {
00266 //
00267 //
00268 //  Purpose:  Check memory
00269 //
00270 //    cmd          in    Command parameters. Optional, default = 0;       
00271 //  Arguments: None.
00272 //
00273 //  Return:    kTRUE.
00274 //
00275 //  Contact:   N. West
00276 //
00277 //  Specification:-
00278 //  =============
00279 //
00280 //  o Check memory.
00281 
00282 //  Program Notes:-
00283 //  =============
00284 
00285 //  None.
00286 
00287 
00288 // Check command options, if supplied.
00289 
00290   if ( cmd ) {
00291     DbmCmdOptions opts("",cmd);
00292     if ( ! opts.IsValid() ) return kFALSE;
00293   }
00294 
00295 // Clear out local cache to make any leak easier to spot.
00296 
00297   ClearCache();
00298 
00299   LeaLeakChecker* lea = LeaLeakChecker::Instance();
00300   MSG("Dbm",Msg::kInfo) << lea << endl;
00301   DbiTableProxyRegistry::Instance().ShowStatistics();
00302 
00303   return kTRUE;
00304 
00305 }
00306 
00307 //.....................................................................
00308 
00309 void DbmModule::ClearCache() {
00310 //
00311 //
00312 //  Purpose:  Clear out cached  DbiValidityRec.
00313 //
00314 //  Arguments: None.
00315 
00316 //
00317 //  Return:    n/a
00318 //
00319 //  Contact:   N. West
00320 //
00321 //  Specification:-
00322 //  =============
00323 //
00324 //  o Clear out cached  DbiValidityRec.
00325 //
00326 //  Program Notes:-
00327 //  =============
00328 
00329 //  None.
00330 
00331   delete fValRecSet;
00332   fValRecSet = 0;
00333 
00334 }
00335 //.....................................................................
00336 
00337 Bool_t DbmModule::ExportTable(const string& tableName,
00338                               ofstream* out,
00339                               DbmLogFile& logFile,
00340                               list<int>seqnos) {
00341 //
00342 //
00343 //  Purpose:  Export the contents of the specified table to an ostream.
00344 //
00345 //  Arguments: 
00346 //    tableName    in    The table to operate on.
00347 //    out          in    The output stream.
00348 //    logFile      in    Log file to record I/O,
00349 //    seqnos       in    List of selected sequence numbers.
00350 //                       If empty, export all.
00351 //
00352 //  Return:    kTRUE if output successful.
00353 //
00354 //  Contact:   N. West
00355 //
00356 //  Specification:-
00357 //  =============
00358 //
00359 //  o Ensure that all exported entries have global SeqNos.
00360 //
00361 //  o Loop over all entries in the auxillary validity range table and
00362 //    export each to a file.
00363 //  
00364 //  o For any entry whose insertion date is the far future
00365 //    (year >= 2030), set it back a few minutes before the current date.
00366 //
00367 //  o For first entry add SQl to create table.
00368 
00369 //  Program Notes:-
00370 //  =============
00371 
00372 //  The DbiConfigSet table row is used as a generic row to export all
00373 //  types of tables.
00374 
00375 //  The reseting of far future insertion dates allows people to add
00376 //  data into the database with dummy insertion date and have it
00377 //  exported as if the insertion date were correct.
00378 
00379 // Check that all have global SeqNos (will also ensure that fValRecSet
00380 // will contain all DbiValidityRecs for table).
00381 
00382 
00383   MSG("Dbm", Msg::kInfo) << "\nExporting table " 
00384                          << tableName << "..." << endl;
00385 
00386   if ( ! BuildValRecSet(tableName,0) ) return kFALSE;
00387 
00388   int numVRecs    = fValRecSet->GetNumRows();
00389   int numVRecsOut = 0;
00390   Int_t numModified = 0;
00391 
00392   if ( numVRecs == 0 ) {
00393     MSG("Dbm", Msg::kInfo) << "Nothing to do: table " 
00394                            << tableName << " is empty!" << endl;
00395     return kTRUE; 
00396   }
00397 
00398   VldTimeStamp farFuture(2030,1,1,0,0,0);
00399 // Now is actually 5 mins ago otherwise next Export will
00400 // pick it up again.
00401   VldTimeStamp now(VldTimeStamp().GetSec() - 5*60, 0);
00402   
00403   const DbiDBProxy& proxy = GetDBProxy(tableName);
00404 
00405   Int_t numDataRows = 0;
00406   Bool_t writeMeta  = kTRUE;
00407 
00408   for ( int jvrec = 0; jvrec < numVRecs; ++jvrec ) {
00409 
00410     // Create an inner scope to limit the lifetime of packet
00411     {
00412 
00413       // Skip if unwanted.
00414       const DbiValidityRec* vrec = fValRecSet->GetTableRow(jvrec);
00415       int seqNo   = vrec->GetSeqNo();
00416       bool isWanted = true;
00417       if ( seqnos.size() > 0 ) {
00418         isWanted = false;
00419         int seqNoMin = 999999999;
00420         list<int>::iterator  itr(seqnos.begin()), itrEnd(seqnos.end());
00421         for ( ; itr != itrEnd; ++itr ) {
00422           int seqNoMax = *itr;
00423           if ( seqNoMax < 0 ) {
00424             seqNoMax = - seqNoMax;
00425             if ( seqNo >= seqNoMin && seqNo <= seqNoMax ) isWanted = true;
00426           }
00427           else {
00428             if ( seqNo == seqNoMax ) isWanted = true; 
00429           }
00430           seqNoMin = seqNoMax;
00431         }
00432       }
00433       if ( ! isWanted ) continue;
00434       DbiSqlValPacket packet(*vrec);
00435 
00436       // Deal with far future insert dates.
00437       if ( vrec->GetInsertDate() > farFuture ) { 
00438           vrec->GetTableProxy()
00439                  ->GetDBProxy()
00440                 .ReplaceInsertDate(now,seqNo,vrec->GetDbNo());
00441       }
00442 
00443       // Renumber local SEQNOs.
00444       if ( seqNo <= Dbi::kMAXLOCALSEQNO ) {
00445         Int_t globalSeqNo = fCascader.AllocateSeqNo(tableName,1);
00446         if ( globalSeqNo < Dbi::kMAXLOCALSEQNO ) {
00447           MSG("Dbi",Msg::kError) << "Failed (cascader returned " <<globalSeqNo
00448                                  << ") to get replacement for " 
00449                                  << seqNo << endl;
00450           continue;
00451         }
00452   
00453         MSG("Dbi",Msg::kInfo) << "    Renumbering " << seqNo 
00454                               <<  " -> " << globalSeqNo << endl;
00455         if ( ! proxy.ReplaceSeqNo(seqNo,globalSeqNo,0) ) continue;
00456         else ++numModified;
00457         seqNo = globalSeqNo;
00458         packet.SetSeqNo(seqNo);
00459       }
00460 
00461       Int_t  numRows = packet.GetNumSqlStmts()-1;
00462 
00463       MSG("Dbm", Msg::kInfo)
00464         << "Exporting sequence number " << seqNo
00465         << " with " << numRows << " rows of data" << endl;
00466 
00467       packet.Write(*out,writeMeta);
00468       writeMeta = kFALSE;
00469       logFile.LogRec(vrec);
00470       numDataRows += numRows;
00471       ++numVRecsOut;
00472 
00473     }
00474   
00475 //  Packet will have been destroyed so can now purge caches, 
00476 //  the data won't be needed again.
00477     DbiTableProxyRegistry::Instance().PurgeCaches();
00478   }
00479 
00480   // If any sequence number has been modified flush the cache.
00481   if ( numModified ) ClearCache();
00482 
00483   MSG("Dbm", Msg::kInfo)
00484     << "A total of " << numVRecsOut << " validity entries and "
00485     << numDataRows << " data rows written to file" << endl;
00486   // Flush out last record.
00487   logFile.LogRec();
00488 
00489 
00490   return kTRUE;
00491 
00492 }
00493 //.....................................................................
00494 
00495 Bool_t DbmModule::ExportTables(JobCommand *cmd) {
00496 //
00497 //
00498 //  Purpose:  Export tables..
00499 //
00500 //  Arguments: 
00501 //    cmd          in    Command parameters.          
00502 //
00503 //  Return:    kTRUE if output successful.
00504 //
00505 //  Contact:   N. West
00506 //
00507 //  Specification:-
00508 //  =============
00509 //
00510 //  o Process command parameters.
00511 //
00512 //  o Loop over all selected tables exporting them.
00513 
00514 //  Program Notes:-
00515 //  =============
00516 
00517 // None.
00518 
00519 // Process all options.
00520 
00521   MSG("Dbm",Msg::kInfo) << "\n\nProcessing EXPORT command...\n" << endl;
00522 
00523   DbmCmdOptions opts("--File:--LogFile:--SeqNo:--Since:--Table", cmd);
00524   if ( ! opts.IsValid() ) return kFALSE;
00525 
00526 
00527 //  Deal with --LogFile but always create a logfile even
00528 //  if its dummy.  That way it can be put on the stack.
00529 
00530   string logName;
00531   if ( opts.TestOpt("--LogFile") ) {
00532     logName = opts.GetOptString("--LogFile");
00533   }
00534   DbmLogFile logFile(logName);
00535 
00536 //  Deal with --SeqNo.
00537 
00538   list<int> seqnos;
00539   if ( opts.TestOpt("--SeqNo" ) ) opts.GetOptIntList("--SeqNo",seqnos);
00540 
00541 //  Deal with --Since.
00542   string insertDateCondition;
00543   if ( opts.TestOpt("--Since" ) ) {
00544     string opt = opts.GetOptString("--Since");
00545 //  Have to add leading and trailing double quotes for SQL
00546     insertDateCondition =   insertDateCondition + "InsertDate >'" 
00547                             + opt + "'";
00548     MSG("Dbm",Msg::kInfo) << "Applying condition: " 
00549                           << insertDateCondition  << endl;
00550   }
00551 
00552 // Deal with --File and --Table.
00553   if ( ! opts.TestOpt("--Table" ) ) {
00554     MSG("Dbm",Msg::kWarning) << "Table names  not specified." << endl;
00555     return kFALSE;
00556   }
00557   if ( ! opts.TestOpt("--File" ) ) {
00558     MSG("Dbm",Msg::kWarning) << "File name  not specified." << endl;
00559     return kFALSE;
00560   }
00561  
00562   DbmNameFilter nameFilter(opts.GetOptString("--Table"));
00563   MSG("Dbm",Msg::kInfo) << " Export table name mask set to: " 
00564                         << opts.GetOptString("--Table") <<  endl;
00565   string fileName = opts.GetOptString("--File");
00566 
00567 
00568 //  Open export file.
00569   ofstream exportFile(fileName.c_str(),ios_base::app);
00570   if ( ! exportFile ) {
00571     MSG("Dbm", Msg::kInfo) << "Unable to open " << fileName << endl;
00572     return kFALSE; 
00573   }
00574 
00575 
00576   //Collect list of table names to be processed before proceesing
00577   // because TSQLResultSet only valid until next query.
00578     list<string> tableNames;
00579     this->ListTables(nameFilter,0,tableNames);
00580 
00581   // If a start date is to be applied clear out any cached 
00582   // DbiValidityRecs before applying.
00583   if ( insertDateCondition != "" ) {
00584     ClearCache();
00585     DbiTableProxyRegistry::Instance()
00586                            .SetSqlCondition(insertDateCondition);
00587   }
00588 
00589   // Now process all tables.
00590 
00591   logFile.LogCmd("export",opts);
00592 
00593   for ( list<string>::const_iterator itr = tableNames.begin();
00594         itr != tableNames.end();
00595         ++itr ) {
00596     DbiTableProxyRegistry::Instance()
00597                            .SetSqlCondition(insertDateCondition);
00598     ExportTable(*itr,&exportFile,logFile,seqnos);
00599     DbiTableProxyRegistry::Instance().SetSqlCondition("");
00600   }
00601 
00602   // Undo any SQL conditions.
00603   if ( insertDateCondition != "" ) {
00604     ClearCache();
00605     DbiTableProxyRegistry::Instance().SetSqlCondition();
00606   }
00607 
00608 //  Close export file (even though it will as it goes out of scope).
00609   exportFile.close();
00610 
00611   return kTRUE;
00612 
00613 }
00614 
00615 //.....................................................................
00616 const DbiDBProxy& DbmModule::GetDBProxy(const string& tableName) const {
00617 //
00618 //
00619 //  Purpose:  Return a DBProxy for specified table.
00620 //
00621 //  Arguments: 
00622 //    tableName    in   Name of table.
00623 //
00624 //  Return:    
00625 //
00626 //  Contact:   N. West
00627 //
00628 //  Specification:-
00629 //  =============
00630 //
00631 //  o Return a DBProxy for specified table.
00632 
00633 //  Program Notes:-
00634 //  =============
00635 
00636 //  For all tables Dbm uses DbiConfigSet as a generic table row.
00637 
00638   DbiConfigSet pet;
00639   return  DbiTableProxyRegistry::Instance()
00640             .GetTableProxy(tableName,&pet)
00641                .GetDBProxy(); 
00642 
00643 }
00644 
00645 //.....................................................................
00646 
00647 Bool_t DbmModule::GlobaliseSeqNo(JobCommand *cmd) {
00648 //
00649 //
00650 //  Purpose:  Convert to global any local sequence numbers in supplied
00651 //            table name.
00652 //
00653 //  Arguments: 
00654 //    cmd          in    Command parameters.          
00655 //
00656 //  Return:    kTRUE if all sequence numbers are now global.
00657 //
00658 //  Contact:   N. West
00659 //
00660 //  Specification:-
00661 //  =============
00662 //
00663 //  o Ensure that there is an authorising database is the cascade.
00664 //
00665 //  o Load all entries in the auxillary validity range table and
00666 //    look for local sequence numbers ( <= Dbi::kMAXLOCALSEQNO)
00667 //    and for each convert to global in both this and the main table.
00668 //
00669 
00670 //  Program Notes:-
00671 //  =============
00672 
00673 // None.
00674 
00675 // Process all options.
00676 
00677   string tableName;
00678 
00679   DbmCmdOptions opts("--Table", cmd);
00680   if ( ! opts.IsValid() ) return kFALSE;
00681 
00682   if ( ! opts.TestOpt("--Table" ) ) {
00683     MSG("Dbm",Msg::kWarning) << "Table name  not specified." << endl;
00684     return kFALSE;
00685   }
00686 
00687   tableName = opts.GetOptString("--Table");
00688 
00689   return GlobaliseSeqNo(tableName);
00690 
00691 }
00692 
00693 //.....................................................................
00694 
00695 Bool_t DbmModule::GlobaliseSeqNo(const string& tableName) {
00696 //
00697 //
00698 //  Purpose:  Convert to global any local sequence numbers in supplied
00699 //            table name.
00700 //
00701 //  Arguments: 
00702 //    tableName    in    The table to be globalised.
00703 //
00704 //  Return:    kTRUE if all sequence numbers are now global.
00705 //
00706 //  Contact:   N. West
00707 //
00708 //  Specification:-
00709 //  =============
00710 //
00711 //  o Ensure that there is an authorising database is the cascade.
00712 //
00713 //  o Load all entries in the auxillary validity range table and
00714 //    look for local sequence numbers ( <= Dbi::kMAXLOCALSEQNO)
00715 //    and for each convert to global in both this and the main table.
00716 //
00717 
00718 //  Program Notes:-
00719 //  =============
00720 
00721 //  As a by product this sets up fValRecSet.
00722 
00723   Bool_t ok         = kTRUE;
00724   Int_t numModified = 0;
00725 
00726   // Collect up all DbiValityRecs.
00727   if ( ! BuildValRecSet(tableName,0) ) return kFALSE;
00728 
00729   // Make sure that there is an authorising database.
00730   if ( fCascader.GetAuthorisingDbNo() < 0 ) {
00731     MSG("Dbi",Msg::kError) << "No authorising DB in cascade" << endl;
00732     return kFALSE;
00733   }
00734 
00735   // Loop over all DbiValidityRecs checking for and converting local SeqNos
00736 
00737   const DbiDBProxy& proxy = GetDBProxy(tableName);
00738 
00739   MSG("Dbm", Msg::kInfo) << "Scanning for local sequence numbers..." << endl;
00740   int numRows = fValRecSet->GetNumRows();
00741 
00742   for ( int irow = 0; irow < numRows; ++ irow ) {
00743     const DbiValidityRec* vrec = fValRecSet->GetTableRow(irow);
00744     int seqNo = vrec->GetSeqNo();
00745     if ( seqNo <= Dbi::kMAXLOCALSEQNO ) {
00746       Int_t globalSeqNo = fCascader.AllocateSeqNo(tableName,1);
00747       if ( globalSeqNo < Dbi::kMAXLOCALSEQNO ) {
00748         MSG("Dbi",Msg::kError) << "Failed to get replacement for " 
00749                                << seqNo << endl;
00750         ok = kFALSE;
00751         break;
00752       }
00753 
00754       MSG("Dbi",Msg::kInfo) << "    Renumbering " << seqNo 
00755                             <<  " -> " << globalSeqNo << endl;
00756       if ( ! proxy.ReplaceSeqNo(seqNo,globalSeqNo,0) ) ok = kFALSE;
00757       else ++numModified;
00758       
00759     }
00760   }
00761 
00762   MSG("Dbi",Msg::kInfo) << "A total of " << numRows
00763                           << " were scanned" << endl;
00764 
00765   // If any sequence number has been modified flush the cache.
00766   if ( numModified ) {
00767     MSG("Dbi",Msg::kInfo) << "A total of " << numModified
00768                           << " were renumbered" << endl;
00769     ClearCache();
00770     BuildValRecSet(tableName,0);
00771   }
00772   else MSG("Dbi",Msg::kInfo) << "No local SeqNos found" << endl;
00773   return ok;
00774 
00775 }
00776 
00777 //.....................................................................
00778 
00779 void DbmModule::HandleCommand(JobCommand *cmd) {
00780 //
00781 //
00782 //  Purpose:  Command Processor
00783 //
00784 //  Arguments: 
00785 //    cmd          in    JobCommand holding command to be processed.
00786 //
00787 //  Return:    n/a
00788 //
00789 //  Contact:   N. West
00790 //
00791 //  Specification:-
00792 //  =============
00793 //
00794 //  o Execute supplied database maintenance command.
00795 
00796 //  Program Notes:-
00797 //  =============
00798 
00799 //  None.
00800 
00801 // Clear cache in case previous command modified
00802 // the table is was caching.
00803 
00804   this->ClearCache();
00805 
00806   const char* c = cmd->PopCmd();
00807 
00808   if (c) {
00809     TString sc(c);
00810     sc.ToLower();
00811     if      (sc == "checkmemory" )    CheckMemory(cmd);
00812     else if (sc == "export" )         ExportTables(cmd);
00813     else if (sc == "globaliseseqno" ) GlobaliseSeqNo(cmd);
00814     else if (sc == "import" )         Import(cmd);
00815     else if (sc == "logentry" )       LogEntry(cmd);
00816     else if (sc == "help" )           Help();
00817     else if (sc == "query" )          Query(cmd);
00818     else if (sc == "setloglevel" )    SetLogLevel(cmd);
00819     else if (sc == "settimer" )       SetTimer(cmd);
00820 
00821     else {
00822       MSG("Dbm",Msg::kWarning) << "Unknown command " << sc <<endl
00823            << "Type Help for valid commands." << endl;
00824 
00825     }
00826   }
00827 
00828 }
00829 //.....................................................................
00830 
00831 void DbmModule::Help() {
00832 //
00833 //
00834 //  Purpose:  Print help.
00835 //
00836 //  Arguments: None.
00837 //
00838 //  Return:  none.  
00839 //
00840 //  Contact:   N. West
00841 //
00842 //  Specification:-
00843 //  =============
00844 //
00845 //  o  Print help.
00846 
00847 //  Program Notes:-
00848 //  =============
00849 
00850 //  None.
00851 
00852   string helpFileName 
00853      = fFileLocater.Find("DatabaseMaintenance/doc/Help.txt");
00854     ifstream helpFile(helpFileName.c_str());
00855 
00856   if ( ! helpFile.is_open() ) {
00857     MSG("Dbm",Msg::kInfo) << "Sorry, I cannot help you!" << endl;
00858   }
00859   else {
00860     string line;
00861     while ( ! helpFile.eof() ) {
00862       getline(helpFile,line);
00863       MSG("Dbm",Msg::kInfo) << line << endl;
00864     }
00865   }
00866 
00867 
00868 }
00869 //.....................................................................
00870 
00871 Bool_t DbmModule::Import(JobCommand *cmd) {
00872 //
00873 //
00874 //  Purpose:  Import the contents of the specified file into database.
00875 //
00876 //  Arguments: 
00877 //    cmd          in    Command parameters.          
00878 //
00879 //  Return:    kTRUE if import successful.
00880 //
00881 //  Contact:   N. West
00882 //
00883 //  Specification:-
00884 //  =============
00885 //
00886 //  o Process input file, skipping any local or duplicate SeqNos 
00887 //    and ignoring excluded tables.
00888 //
00889 //  o If table does not exist, get DbiSqlvalPacket to create them
00890 //    usin the create table SQL.
00891 
00892 
00893 //  Program Notes:-
00894 //  =============
00895 
00896 
00897   MSG("Dbm",Msg::kInfo) << "\n\nProcessing IMPORT command...\n" << endl;
00898 
00899 // Process all options.
00900   DbmCmdOptions opts("--Batch:"
00901                      "--DiscardConflicts:"
00902                      "--DatabaseNumber:"
00903                      "--EnableSQL:"
00904                      "--File:"
00905                      "--LogFile:"
00906                      "--Table:"
00907                      "--Test",
00908                      cmd);
00909   if ( ! opts.IsValid() ) return kFALSE;
00910 
00911 //  Deal with --DatabaseNumber
00912   UInt_t dbNo = 0;
00913   if ( opts.TestOpt("--DatabaseNumber" ) ) {
00914     dbNo = opts.GetOptInt("--DatabaseNumber");
00915     MSG("Dbm",Msg::kInfo) << " using database number " << dbNo
00916                           << "  " << opts.GetOptString("--DatabaseNumber")
00917                         << " for import" <<  endl;
00918   }
00919 
00920 //  Deal with --Batch
00921    Bool_t batch = opts.TestOpt("--Batch");
00922    if ( batch ) MSG("Dbm",Msg::kInfo) 
00923        << " Batch mode: Errors will force exit at end of command." <<  endl;
00924 
00925 //  Deal with --DiscardConflicts
00926    Bool_t discardConflicts = opts.TestOpt("--DiscardConflicts");
00927    if ( discardConflicts ) MSG("Dbm",Msg::kInfo) 
00928        << " Conflicts will be discarded." <<  endl;
00929    else MSG("Dbm",Msg::kInfo) 
00930        << " Conflicts will be imported." <<  endl;
00931 
00932 //  Deal with --EnableSQL
00933    Bool_t enableSQL = opts.TestOpt("--EnableSQL");
00934    if ( enableSQL ) MSG("Dbm",Msg::kInfo) 
00935        << " SQL fixups are enabled." <<  endl;
00936    else MSG("Dbm",Msg::kInfo) 
00937        << " SQL fixups are disabled." <<  endl;
00938 
00939 //  Deal with --File
00940   if ( ! opts.TestOpt("--File" ) ) {
00941     MSG("Dbm",Msg::kWarning) << "File name  not specified." << endl;
00942     if ( batch ) this->Quit();
00943     return kFALSE;
00944   }
00945   string fileName = opts.GetOptString("--File");
00946 
00947 //  Deal with --LogFile but always create a logfile even
00948 //  if its dummy.  That way it can be put on the stack.
00949   string logName;
00950   if ( opts.TestOpt("--LogFile") ) {
00951     logName = opts.GetOptString("--LogFile");
00952   }
00953   DbmLogFile logFile(logName,dbNo);
00954 
00955 
00956 //  Deal with optional --Table
00957   string tableMask = "*";
00958   if ( opts.TestOpt("--Table") ) tableMask = opts.GetOptString("--Table");
00959   DbmNameFilter nameFilter(tableMask);
00960   MSG("Dbm",Msg::kInfo) << " Import table name mask set to: " << tableMask <<  endl;
00961 
00962 //  Deal with --Test
00963   Bool_t test = opts.TestOpt("--Test");
00964   if ( test ) MSG("Dbm",Msg::kInfo) << " Testing only, database will "
00965                                      << " not be updated." <<  endl;  
00966 
00967 //  Open import file.
00968   ifstream import(fileName.c_str());
00969   if ( ! import ) {
00970     MSG("Dbm", Msg::kError) << "Unable to open " << fileName << endl;
00971     if ( batch ) this->Quit();
00972     return kFALSE; 
00973   }
00974 
00975   MSG("Dbm", Msg::kInfo) << "\n\nProcessing file " << fileName 
00976                          << " ..." << endl;
00977 
00978   Int_t numNewTables = 0;
00979   Int_t numImported  = 0;
00980   Int_t numImpConfl  = 0;
00981   Int_t numImpUpdate = 0;
00982   Int_t numDuplicate = 0;
00983   Int_t numOutOfDate = 0;
00984   Int_t numConflict  = 0;
00985   Int_t numLocal     = 0;
00986   Int_t numFailed    = 0;
00987   Int_t numTest      = 0;
00988 
00989   string currentTableName;
00990 
00991   logFile.LogCmd("import",opts);
00992 
00993 //  Apply any SQL fixups before starting the import loop.
00994 
00995   if ( ! this->ApplySQLFixup(dbNo, import, logFile, enableSQL) ) {
00996     MSG("Dbm", Msg::kError) << "Fixup failed " << endl;
00997     if ( batch ) this->Quit();
00998     return kFALSE; 
00999   }
01000 
01001 // Loop repeatedly filling a DbiSqlValPacket and storing it.
01002 
01003   DbiSqlValPacket packetFile(import);
01004 
01005   Bool_t skipTable = kFALSE;
01006 
01007   for (;  packetFile.CanBeStored(); packetFile.Fill(import) ) {
01008 
01009     //  Check for table change.
01010     if ( currentTableName != packetFile.GetTableName() ) {
01011       currentTableName = packetFile.GetTableName();
01012 
01013       // Skip table if not in name filter.
01014       skipTable =  ! nameFilter.Test(currentTableName);
01015       if ( skipTable ) {
01016         if ( ! batch ) MSG("Dbm", Msg::kInfo) << "\nSkipping table " 
01017                              << currentTableName << "...\n" << endl;
01018         continue;
01019       }
01020       if ( ! batch ) MSG("Dbm", Msg::kInfo) << "\nUpdating table " 
01021                              << currentTableName << "...\n" << endl;
01022 
01023       // If it doesn't exist, try to create it.
01024       auto_ptr<DbiStatement> stmtDb(fCascader.CreateStatement(dbNo));
01025       string sql = "select * from  ";
01026       sql += currentTableName + " where 1=0;";
01027       TSQLStatement* res = stmtDb->ExecuteQuery(sql.c_str());
01028 
01029       if ( ! res ) {
01030         if ( packetFile.CreateTable(dbNo) ) {
01031           MSG("Dbm", Msg::kInfo) << "   Created table: "
01032                                  << currentTableName << endl;
01033           ++numNewTables;
01034         }
01035         else {
01036           MSG("Dbm", Msg::kError) << "   failed to create table: "
01037                                  << currentTableName << endl;
01038         }
01039       }
01040     }
01041 
01042     // Ignore if table to be skipped.
01043     if ( skipTable ) continue;
01044 
01045     Int_t seqNo = packetFile.GetSeqNo();
01046 
01047     // Decide if record is to be imported.
01048     bool tryImport = false;
01049     bool replace   = false;
01050 
01051     // Check for duplicates.
01052 
01053     DbiValRecSet vrecSet(currentTableName,dbNo,seqNo);
01054     const DbiValidityRec* vrec = vrecSet.GetTableRowBySeqNo(seqNo);
01055 
01056     if ( vrec ) {
01057 //       DbiSqlValPacket packetDb(*vrec);
01058 //       DbiSqlValPacket::CompResult_t comp
01059 //      = packetDb.Compare(packetFile,kTRUE,"Database","Import  ");
01060 
01061       DbiSqlValPacket::CompResult_t comp = DbiSqlValPacket::kIdentical;
01062       if ( packetFile.GetCreationDate() > vrec->GetCreationDate() 
01063          )  comp = DbiSqlValPacket::kUpdate;
01064       if ( packetFile.GetCreationDate() < vrec->GetCreationDate() 
01065          )  comp = DbiSqlValPacket::kOutOfDate;
01066 
01067       switch ( comp ) {
01068 
01069       case DbiSqlValPacket::kIdentical :
01070         if ( ! batch ) MSG("Dbm", Msg::kInfo) << "   " << seqNo 
01071                                       << " skipped (duplicate)" << endl;
01072         ++numDuplicate;
01073         break;
01074 
01075       case DbiSqlValPacket::kUpdate :
01076         ++numImpUpdate;
01077         tryImport = true;
01078         replace   = true;
01079         break;
01080 
01081       case DbiSqlValPacket::kOutOfDate :
01082         if ( ! batch ) MSG("Dbm", Msg::kInfo) << "   " << seqNo 
01083                                     << " skipped (out of date)" << endl;
01084         ++numOutOfDate;
01085         break;
01086 
01087       // Everything else is a conflict!
01088       default :
01089         if ( discardConflicts ) {
01090           MSG("Dbm", Msg::kError) << "   " << seqNo 
01091                                       << " skipped (conflict!)" << endl;
01092           ++numConflict;
01093         }
01094         else {
01095           MSG("Dbm", Msg::kError) << "   " << seqNo 
01096                                       << " accepting conflict!" << endl;
01097           ++numImpConfl;
01098           tryImport = true;
01099           replace   = true;
01100         }
01101       }
01102     }
01103     else {
01104       if ( Dbi::NotGlobalSeqNo(seqNo) )  {
01105         ++numLocal;
01106         if ( ! batch ) MSG("Dbm", Msg::kInfo) << "   " << seqNo 
01107                                    << " skipped (local sSeqNo)" << endl;
01108       }
01109 
01110       else {
01111         tryImport = true;
01112       }
01113     }
01114 
01115 //  Purge caches, used when getting DbiSqlValPackets from database;
01116 //  the data won't be needed again.
01117     if ( vrec )  DbiTableProxyRegistry::Instance().PurgeCaches();
01118 
01119     // Try to import unless already rejected.
01120     if ( tryImport ) {
01121 
01122       // Skip importing if testing.
01123       if ( test ) {
01124         ++numTest;
01125         if ( ! batch ) MSG("Dbm", Msg::kInfo) << "   " << seqNo 
01126                                               << " tested" << endl;
01127       }
01128       else {
01129 
01130         if ( packetFile.Store(dbNo,replace) )  {
01131           ++numImported;
01132           if ( ! batch ) MSG("Dbm", Msg::kInfo) << "   " << seqNo 
01133                                                 << " imported" << endl;
01134           logFile.LogRec(currentTableName,seqNo);
01135         }
01136         else {
01137         ++numFailed;
01138          MSG("Dbm", Msg::kError) << "   " << seqNo
01139                                           << " failed" << endl;
01140          // Attempt to delete failed SEQNO;
01141          DbiConfigSet pet;
01142          DbiTableProxyRegistry::Instance()
01143            .GetTableProxy(currentTableName,&pet)
01144              .GetDBProxy().RemoveSeqNo(seqNo,dbNo);
01145         }
01146       }
01147     }
01148   }
01149 
01150   //  Check for read errors
01151   if ( packetFile.GetNumErrors() > 0 ) {
01152     ++numFailed;
01153      MSG("Dbm", Msg::kError) << "   input error on"
01154                              << fileName.c_str() << endl;
01155     }
01156 
01157   //Flush last table entry in log file.
01158   logFile.LogRec();
01159 
01160 
01161   MSG("Dbm", Msg::kInfo)
01162     << "Summary of processing of packets (validity rec + data):-" <<endl
01163     << "  Packets skipped (local seqNo): " << numLocal << endl
01164     << "  Packets skipped (duplicate):   " << numDuplicate << endl
01165     << "  Packets skipped (out of date): " << numOutOfDate << endl
01166     << "  Packets skipped (conflict):    " << numConflict  << endl
01167     << "  Packets failed :               " << numFailed    << endl
01168     << "  Packets tested (not imported): " << numTest      << endl
01169     << "  Packets imported :             " << numImported  << endl
01170     << "    including conflicts :        " << numImpConfl  << endl
01171     << "              updates :          " << numImpUpdate << endl;
01172   if ( numNewTables ) MSG("Dbm", Msg::kInfo) << endl
01173     << "  Tables Created :               " << numNewTables << endl;
01174 
01175   
01176   ofstream* log = logFile.GetStream();
01177   if ( log ) { 
01178     *log
01179       << "      Summary of processing of packets (validity rec + data):-" <<endl;
01180     if ( numLocal ) *log << "        Packets skipped (local seqNo): " 
01181                          << numLocal << endl;
01182     if ( numDuplicate ) *log << "        Packets skipped (duplicate):   " 
01183                  << numDuplicate << endl;
01184     if ( numOutOfDate ) *log << "        Packets skipped (out of date): " 
01185                  << numOutOfDate << endl;
01186     if ( numConflict ) *log << "        Packets skipped (conflict):    " 
01187                  << numConflict  << endl;
01188     if ( numFailed ) *log << "        Packets failed :               " 
01189                  << numFailed    << endl;
01190     if ( numTest ) *log << "        Packets tested (not imported): " 
01191                  << numTest      << endl;
01192     if ( numImported ) *log << "        Packets imported :             " 
01193                  << numImported  << endl;
01194     if ( numImpConfl) *log << "          including conflicts :        " 
01195                  << numImpConfl  << endl;
01196     if ( numImpUpdate ) *log << "                    updates :          " 
01197                    << numImpUpdate << endl;
01198     if ( numNewTables ) *log << endl
01199       << "        Tables Created :               " << numNewTables << endl;
01200     if ( numConflict + numFailed > 0 ) {
01201       *log << "      Import failed!!"  << endl;
01202     }
01203     else {
01204       *log << "      Import O.K."  << endl;
01205     }
01206   }
01207 
01208 //  Close import file (even though it will as it goes out of scope).
01209   import.close();
01210     
01211 
01212 // Exit if in Batch mode and errors have occurred.
01213   if (      batch
01214             && ( numConflict +  numFailed ) > 0  ) this->Quit();
01215   return packetFile.GetNumErrors() ? kFALSE : kTRUE;
01216 
01217 }
01218 //.....................................................................
01219 
01220 Bool_t DbmModule::LogEntry(JobCommand *cmd) {
01221 //
01222 //
01223 //  Purpose: Write log entry.
01224 //
01225 //  Arguments: 
01226 //    cmd          in    Command parameters.          
01227 //
01228 //  Return:    kTRUE if output successful.
01229 //
01230 //  Contact:   N. West
01231 //
01232 //  Specification:-
01233 //  =============
01234 //
01235 //  o Write database log entry using information supplied.
01236 
01237 //  Program Notes:-
01238 //  =============
01239 
01240 // None.
01241 
01242 // Process all options.
01243 
01244   std::list<std::string> defaultOpts;
01245   defaultOpts.push_back("--Table");
01246   defaultOpts.push_back("--Reason");
01247   defaultOpts.push_back("--SeqNoMin");
01248   defaultOpts.push_back("--Detector");
01249   defaultOpts.push_back("--SimFlag");
01250 
01251   DbmCmdOptions opts("--Table:"
01252                      "--Reason:"
01253                      "--SeqNoMin:"
01254                      "--Detector:"
01255                      "--SimFlag:"
01256                      "--SeqNoMax:"
01257                      "--NumSeqNo:"
01258                      "--Task:"
01259                      "--UpdateTime:"
01260                      "--DatabaseNumber",
01261                      cmd, &defaultOpts);
01262   if ( ! opts.IsValid() ) return kFALSE;
01263 
01264 
01265 //  Deal with compulsory "options" (please excuse the contradition).
01266 
01267   if ( ! opts.TestOpt("--Table" ) ) {
01268     MSG("Dbm",Msg::kWarning) << "Table name not specified." << endl;
01269     return kFALSE;
01270   }
01271   string tableName = opts.GetOptString("--Table");
01272 
01273   if ( ! opts.TestOpt("--Reason" ) ) {
01274     MSG("Dbm",Msg::kWarning) << "Reason not specified." << endl;
01275     return kFALSE;
01276   }
01277   string reason = opts.GetOptString("--Reason");
01278 
01279   if ( ! opts.TestOpt("--SeqNoMin" ) ) {
01280     MSG("Dbm",Msg::kWarning) << "SeqNoMin not specified." << endl;
01281     return kFALSE;
01282   }
01283   Int_t logSeqNoMin = opts.GetOptInt("--SeqNoMin");
01284 
01285 // Deal with optional options.
01286 
01287   UInt_t dbNo = 0;
01288   if ( opts.TestOpt("--DatabaseNumber") ) dbNo = opts.GetOptInt("--DatabaseNumber");
01289 
01290 // Have a quick check to see if table exists.
01291   int dbNoFound =   DbiTableProxyRegistry::Instance().GetCascader().GetTableDbNo(tableName);
01292   if ( dbNoFound < 0 || dbNoFound != (int) dbNo ) {
01293     MSG("Dbm",Msg::kWarning) << "Sorry, cannot find table " << tableName << endl;
01294     return kFALSE;
01295   }
01296 
01297 // If the data is already in the database, retrieve detMask, simMask and task
01298 // and use as defaults.
01299 
01300   Int_t detMask  = 2;
01301   Int_t simMask  = 1;
01302   Dbi::Task task = 0;
01303  
01304   DbiResultPtr<DbiConfigSet> dataPtr(tableName,logSeqNoMin,dbNo);
01305   const DbiValidityRec* vrec = dataPtr.GetValidityRec();
01306   if ( dataPtr.GetNumRows() > 0 && vrec ) {
01307     MSG("Dbi",Msg::kInfo) << "Found " << tableName << " " << logSeqNoMin << endl;
01308     const VldRange& vrng = vrec->GetVldRange();
01309     detMask  = vrng.GetDetectorMask();
01310     simMask  = vrng.GetSimMask();
01311     task     = vrec->GetTask();  
01312   }
01313 
01314   if ( opts.TestOpt("--Detector") ) detMask = opts.GetOptInt("--Detector");
01315 
01316   if ( opts.TestOpt("--SimFlag") ) simMask = opts.GetOptInt("--SimFlag");
01317 
01318   Int_t logSeqNoMax = logSeqNoMin;
01319   if ( opts.TestOpt("--SeqNoMax") ) logSeqNoMax = opts.GetOptInt("--SeqNoMax");
01320 
01321   Int_t logNumSeqNo = logSeqNoMax - logSeqNoMin + 1;
01322   if ( opts.TestOpt("--NumSeqNo") ) logNumSeqNo = opts.GetOptInt("--NumSeqNo");
01323 
01324   if ( opts.TestOpt("--Task") ) task = opts.GetOptInt("--Task");
01325 
01326   VldTimeStamp updateTime;
01327   if ( opts.TestOpt("--UpdateTime") 
01328      ) updateTime = Dbi::MakeTimeStamp(opts.GetOptString("--UpdateTime"));
01329 
01330 // Create a DbiLogEntry, ask for confirmation and write it out.
01331   DbiLogEntry logEntry(tableName,reason,detMask,simMask,task,
01332                        logSeqNoMin,logSeqNoMax,logNumSeqNo);
01333   logEntry.SetUpdateTime(updateTime);
01334   MSG("Dbi",Msg::kInfo) << "Created:-\n " 
01335                         <<  logEntry << endl;
01336   char ans = '?';
01337   while ( ans != 'y' && ans != 'n' ) {
01338     cout << "O.K. to output ? Ans y or n: ";
01339     cin  >> ans;
01340   }
01341 
01342   if ( ans == 'y' ) {
01343     bool ioResult = logEntry.Write(dbNo);
01344     if ( ioResult ) MSG("Dbi",Msg::kInfo) << "Successfully wrote entry"
01345                                           << endl;
01346     return ioResult;
01347   }
01348   MSG("Dbi",Msg::kInfo) << "Entry not written" << endl;
01349   return kFALSE;
01350 
01351 }
01352 
01353 //.....................................................................
01354 
01355 void DbmModule::ListTables(const DbmNameFilter& nameFilter,
01356                            UInt_t dbNo,
01357                            std::list<string>& tableNames) const {
01358 //
01359 //
01360 //  Purpose:  Assemble list of tables matching filter
01361 //
01362 //  Arguments: 
01363 //    
01364 //    nameFilter   in      Filter string
01365 //    dbNo         in      Cascade number of Database to be used.
01366 //    tableNames   in/out  List to hold matching names (not cleared)
01367 //
01368 //  Contact:   N. West
01369 //
01370 
01371  //  Loop over all candidate tables (that have a corresponding
01372  // *Validity table).
01373   auto_ptr<DbiStatement> stmtDb(fCascader.CreateStatement(dbNo));
01374   if ( ! stmtDb.get() ) {
01375     MSG("Dbm", Msg::kInfo) << "Cascade entry " << dbNo
01376             << " empty! " << endl;
01377     return; 
01378   }
01379   TSQLStatement* stmt = stmtDb->ExecuteQuery("show tables");
01380   if ( ! stmt ) {
01381     MSG("Dbm", Msg::kInfo) << "Cannot find any tables! " << endl;
01382     return; 
01383   }
01384 
01385   while ( kTRUE ) {
01386     TString name;
01387     if ( ! stmt->NextResultRow() ) break;
01388     name = stmt->GetString(0);
01389     string tableName = name.Data();
01390     MSG("Dbm", Msg::kDebug )<< "examining table " << tableName << endl;
01391 
01392     if (    tableName.size() > 3
01393          && tableName.substr(tableName.size()-3) == "VLD" ) {
01394       tableName.erase(tableName.size()-3);
01395       if ( nameFilter.Test(tableName) ){
01396         tableNames.push_back(tableName);
01397         MSG("Dbm", Msg::kInfo) << "preparing to export: " << tableName << endl;
01398       }
01399     }
01400   }
01401   delete stmt;
01402 
01403   if(tableNames.size()==0)
01404         MSG("Dbm", Msg::kInfo) << "error no tables found! " << endl;
01405 }
01406 
01407 //.....................................................................
01408 
01409 Bool_t DbmModule::Query(JobCommand *cmd) {
01410 //
01411 //
01412 //  Purpose:  Simulate a validity query and display summary of results.
01413 //
01414 //  Arguments: 
01415 //    cmd          in    Command parameters.          
01416 //
01417 //  Return: kTRUE if query satisfied.
01418 //
01419 //  Contact:   N. West
01420 //
01421 
01422   Bool_t satisfied = kFALSE;
01423 
01424   // Establish defaults.
01425   string pattern           = "*";
01426   Detector::Detector_t det = Detector::kFar;
01427   SimFlag::SimFlag_t   sim = SimFlag::kData;
01428   VldTimeStamp date;
01429   Dbi::Task task = 0;
01430 
01431   // Replace as required with supplied parameters.
01432 
01433   DbmCmdOptions opts("--Table:--Detector:--Date:--SimFlag:--Task", cmd);
01434   if ( ! opts.IsValid() ) return kFALSE;
01435    
01436   if ( opts.TestOpt("--Table") ) pattern = opts.GetOptString("--Table");
01437   if ( opts.TestOpt("--Detector") ) {
01438     string detstr = opts.GetOptString("--Detector");
01439     if ( detstr == "Unknown"   ) det = Detector::kUnknown;
01440     if ( detstr == "Near"      ) det = Detector::kNear;
01441     if ( detstr == "Far"       ) det = Detector::kFar;
01442     if ( detstr == "CalDet"    ) det = Detector::kCalDet;
01443     if ( detstr == "Calib"     ) det = Detector::kCalib;
01444     if ( detstr == "TestStand" ) det = Detector::kTestStand;
01445     if ( detstr == "Mapper"    ) det = Detector::kMapper;
01446   }
01447   if ( opts.TestOpt("--SimFlag") ) {
01448     string simstr = opts.GetOptString("--SimFlag");
01449     if ( simstr == "Unknown"     ) sim = SimFlag::kUnknown;
01450     if ( simstr == "Data"        ) sim = SimFlag::kData;
01451     if ( simstr == "DaqFakeData" ) sim = SimFlag::kDaqFakeData;
01452     if ( simstr == "MC"          ) sim = SimFlag::kMC;
01453     if ( simstr == "Reroot"      ) sim = SimFlag::kReroot;
01454   }
01455   if ( opts.TestOpt("--Date") ) {
01456     string datestr = opts.GetOptString("--Date");
01457     date = Dbi::MakeTimeStamp(datestr);
01458   }
01459 
01460   if ( opts.TestOpt("--Task") ) {
01461    task = opts.GetOptInt("--Task");
01462   }
01463 
01464   //  Create context for query.
01465   VldContext vc(det,sim,date);
01466   
01467   //  Establish list of names.
01468   list<string> tableNames;
01469   this->ListTables(pattern,0,tableNames);
01470 
01471   //  Loop over all tables applying query.
01472 
01473   for ( list<string>::const_iterator itr = tableNames.begin();
01474         itr != tableNames.end();
01475         ++itr ) {
01476     DbiResultPtr<DbiConfigSet> rptr(*itr,vc,task);
01477     MSG("Dbm", Msg::kInfo) << "Query for table: " << *itr ;
01478     if ( ! rptr.GetNumRows() ) MSG("Dbm",Msg::kInfo) << " failed\n";  
01479     else {
01480       MSG("Dbm",Msg::kInfo) << " succeeded. " 
01481               << rptr.GetNumRows() << " rows"
01482               << "\n  ResultKey: " << *rptr.GetKey();
01483       satisfied = kTRUE;
01484     }  
01485     MSG("Dbm", Msg::kInfo) << "  ValidityRec: " << *rptr.GetValidityRec() << endl;
01486     
01487   }
01488 
01489   return satisfied;  // but not smug!
01490 
01491 
01492 }
01493 
01494 //.....................................................................
01495 
01496 void DbmModule::Quit() const {
01497     MSG("Dbm", Msg::kInfo)  << "Exit forced due to above errors" << endl;
01498     exit(1);
01499 }
01500 
01501 //.....................................................................
01502 
01503 void DbmModule::SetLogLevel(JobCommand *cmd) const {
01504 //
01505 //
01506 //  Purpose:  Set Log Level
01507 //
01508 //  Arguments: 
01509 //    cmd          in    Command parameters.          
01510 //
01511 
01512   const char* stream = cmd->PopOpt();
01513   const char* level  = cmd->PopOpt();
01514   if ( ! stream or ! level ) {
01515      MSG("Dbm",Msg::kWarning) 
01516        << "Please supply both a stream and a level to the SetLogLevel command\n" << endl;
01517      return;
01518   }
01519 
01520   bool set_ok = Util::MsgLevel(stream,level);
01521   MSG("Dbm",Msg::kInfo) << "Setting MessageService level on stream " << stream
01522                   << " to level " << level
01523                   << ( set_ok ? " succeeded" : " failed" ) << endl;
01524   
01525 }
01526 //.....................................................................
01527 
01528 void DbmModule::SetTimer(JobCommand *cmd) const {
01529 //
01530 //
01531 //  Purpose:  Set Timer on/off
01532 //
01533 //  Arguments: 
01534 //    cmd          in    Command parameters.          
01535 //
01536 
01537   bool enableTimer = true;
01538   const char* mode = cmd->PopOpt();
01539   if ( mode and ! strcmp(mode,"off") ) enableTimer = false;
01540   DbiTimerManager::gTimerManager.Enable(enableTimer);
01541   MSG("Dbm",Msg::kInfo) << "Setting Timer " << (enableTimer ? "on" : "off") << endl;
01542   
01543 }
01544 
01545 /*    Template for New Member Function
01546 
01547 //.....................................................................
01548 
01549 DbmModule::{
01550 //
01551 //
01552 //  Purpose:  
01553 //
01554 //  Arguments: 
01555 //    xxxxxxxxx    in    yyyyyy
01556 //
01557 //  Return:    
01558 //
01559 //  Contact:   N. West
01560 //
01561 //  Specification:-
01562 //  =============
01563 //
01564 //  o 
01565 
01566 //  Program Notes:-
01567 //  =============
01568 
01569 //  None.
01570 
01571 
01572 }
01573 
01574 */

Generated on Mon Feb 15 11:06:35 2010 for loon by  doxygen 1.3.9.1