#include <DbiCascader.h>
Public Types | |
| enum | Status { kFailed, kClosed, kOpen } |
Public Member Functions | |
| DbiStatement * | CreateStatement (UInt_t dbNo) const |
| Create a DbiStatement. Caller must delete. | |
| const DbiConnection * | GetConnection (UInt_t dbNo) const |
| Return associated DbiConnection. DbiCascader retains ownership. | |
| DbiConnection * | GetConnection (UInt_t dbNo) |
| string | GetDbName (UInt_t dbNo) const |
| Int_t | GetDbNo (const string &dbName) const |
| Int_t | GetStatus (UInt_t dbNo) const |
| string | GetStatusAsString (UInt_t dbNo) const |
| string | GetURL (UInt_t dbNo) const |
| Bool_t | IsTemporaryTable (const string &tableName, Int_t dbNo) const |
| Int_t | AllocateSeqNo (const string &tableName, Int_t requireGlobal=0, Int_t dbNo=0) const |
| Int_t | GetAuthorisingDbNo () const |
| UInt_t | GetNumDb () const |
| Int_t | GetTableDbNo (const string &tableName, Int_t selectDbNo=-1) const |
| Bool_t | TableExists (const string &tableName, Int_t selectDbNo=-1) const |
| Int_t | CreateTemporaryTable (const string &tableName, const string &tableDescr) |
| void | HoldConnections () |
| void | ReleaseConnections () |
| void | SetPermanent (UInt_t dbNo, Bool_t permanent=true) |
Private Member Functions | |
| Int_t | ReserveNextSeqNo (const string &tableName, Bool_t isGlobal, UInt_t dbNo) const |
| void | SetAuthorisingEntry (Int_t entry) |
| DbiCascader () | |
| virtual | ~DbiCascader () |
| DbiCascader (const DbiCascader &) | |
Private Attributes | |
| Int_t | fGlobalSeqNoDbNo |
| 1st db in cascade with GlobalSeqNo table | |
| vector< DbiConnection * > | fConnections |
| Vector of DbiConnections, one for each DB. | |
| std::map< string, Int_t > | fTemporaryTables |
| Mapping Name->DbNo for temporary tables. | |
Friends | |
| class | DbiTableProxyRegistry |
| class | DbiValidate |
| ostream & | operator<< (ostream &s, const DbiCascader &cascader) |
DatabaseInterface
Contact: n.west1@physics.ox.ac.uk
Definition at line 51 of file DbiCascader.h.
|
|
Definition at line 61 of file DbiCascader.h. 00061 { kFailed, kClosed, kOpen };
|
|
|
Definition at line 38 of file DbiCascader.cxx. References gSystem(), LEA_CTOR, MSG, DbiConnection::Open(), and UtilString::StringTok(). 00038 : 00039 fGlobalSeqNoDbNo(-1) 00040 { 00041 // 00042 // 00043 // Purpose: Default constructor 00044 // 00045 // Arguments: 00046 // 00047 // Return: n/a 00048 // 00049 // Contact: N. West 00050 // 00051 // Specification:- 00052 // ============= 00053 // 00054 // o Create Cascader. 00055 00056 00057 // Program Notes:- 00058 // ============= 00059 00060 // Current cascader configuration comes from 3 environmental 00061 // variables:- 00062 // 00063 // ENV_TSQL_URL a semi-colon separated list of URLs 00064 // ENV_TSQL_USER user name (one or a semi-colon separated list) 00065 // ENV_TSQL_PSWD password (one or a semi-colon separated list) 00066 // 00067 // or the _UPDATE alternatives e.g. ENV_TSQL_UPDATE_USER 00068 // 00069 // The _UPDATE versions take priority. 00070 00071 LEA_CTOR //Leak Checker 00072 00073 MSG("Dbi", Msg::kVerbose) << "Creating DbiCascader" << endl; 00074 00075 // Extract args from ENV_TSQL environmental variables 00076 const char* strUser = gSystem->Getenv("ENV_TSQL_UPDATE_USER"); 00077 if ( ! strUser ) strUser = gSystem->Getenv("ENV_TSQL_USER"); 00078 const char* strPswd = gSystem->Getenv("ENV_TSQL_UPDATE_PSWD"); 00079 if ( ! strPswd ) strPswd = gSystem->Getenv("ENV_TSQL_PSWD"); 00080 const char* strUrl = gSystem->Getenv("ENV_TSQL_UPDATE_URL"); 00081 if ( !strUrl ) strUrl = gSystem->Getenv("ENV_TSQL_URL"); 00082 string userList = ( strUser ) ? strUser : ""; 00083 string pswdList = ( strPswd ) ? strPswd : ""; 00084 string urlList = ( strUrl ) ? strUrl : ""; 00085 00086 if ( urlList == "" || userList == "" || pswdList == "" ) { 00087 MSG("Dbi",Msg::kFatal) 00088 << "Cannnot open a Database cascade;\n" 00089 << " the environmental variables ENV_TSQL_*:-" << endl 00090 << "USER: \"" << userList << "\" PSWD:\"" << pswdList 00091 << "\" URL:\"" << urlList << endl 00092 << " are either not defined or empty.\n" 00093 << " Please check your settings of ENV_TSQL_USER," 00094 << " ENV_TSQL_PSWD and ENV_TSQL_URL\n" 00095 << "Aborting due to above errors" << endl; 00096 exit(1); 00097 } 00098 00099 std::vector<std::string> users, pswds, urls; 00100 UtilString::StringTok(users, userList, ";"); 00101 UtilString::StringTok(pswds, pswdList, ";"); 00102 UtilString::StringTok(urls, urlList, ";"); 00103 00104 bool fail = false; 00105 00106 for (unsigned entry = 0; entry < urls.size(); ++entry ) { 00107 string url = urls[entry]; 00108 string user = ( entry >= users.size() ) ? users[0] : users[entry]; 00109 string pswd = ( entry >= pswds.size() ) ? pswds[0] : pswds[entry]; 00110 00111 // Handle empty password designated as '\0' (an empty null terminated character string) 00112 if ( pswd == "\\0" ) pswd = ""; 00113 00114 DbiConnection* con = new DbiConnection(url,user,pswd); 00115 fConnections.push_back(con); 00116 if ( ! con->Open() ) { 00117 fail = true; 00118 continue; 00119 } 00120 00121 // Attempt to locate first GlobalSeqNo/GLOBALSEQNO table. 00122 if ( fGlobalSeqNoDbNo != -1 ) continue; 00123 auto_ptr<DbiStatement> stmtDb(new DbiStatement(*con)); 00124 if ( ! stmtDb.get() ) continue; 00125 TSQLStatement* stmt = stmtDb->ExecuteQuery("Select * from GLOBALSEQNO where 1=0"); 00126 if ( stmt ) { 00127 fGlobalSeqNoDbNo = fConnections.size()-1; 00128 delete stmt; 00129 stmt = 0; 00130 } 00131 00132 // Check for presence of a DBI_STATE_FLAG table 00133 00134 if ( this->GetTableDbNo("DBI_STATE_FLAGS",entry) != -1 ) { 00135 MSG("Dbi",Msg::kFatal) << " POSSIBLE VERSION SHEAR DETECTED !!!\n" 00136 << " The DBI_STATE_FLAGS table is present on cascade entry " << entry << ". This table will\n" 00137 << " only be introduced to manage backward incompatible changes that could lead\n" 00138 << " to version shear between the code and the database. This version of the\n" 00139 << " code does not support the change the presence of that table indicates\n" 00140 << " so has to shut down. \n"; 00141 fail = true; 00142 } 00143 } 00144 00145 MSG("Dbi",Msg::kInfo) << *this; 00146 00147 // Abort, if there have been any failures. 00148 if ( fail ) { 00149 MSG("Dbi",Msg::kFatal) 00150 << "Aborting due to above errors" << endl; 00151 exit(1); 00152 } 00153 00154 }
|
|
|
Definition at line 158 of file DbiCascader.cxx. References fConnections, GetNumDb(), LEA_DTOR, and MSG. 00158 {
00159 //
00160 //
00161 // Purpose: Destructor
00162 //
00163
00164 LEA_DTOR //Leak Checker
00165
00166 MSG("Dbi", Msg::kVerbose) << "Destroying DbiCascader" << endl;
00167
00168 for (Int_t dbNo = this->GetNumDb()-1; dbNo >= 0; --dbNo) delete fConnections[dbNo];
00169
00170 }
|
|
|
|
|
||||||||||||||||
|
Definition at line 212 of file DbiCascader.cxx. References fGlobalSeqNoDbNo, IsTemporaryTable(), MSG, and ReserveNextSeqNo(). Referenced by DbiWriter< T >::Close(), DbmModule::ExportTable(), DbmModule::GlobaliseSeqNo(), DbiLogEntry::Write(), and DbiConfigStream::Write(). 00214 {
00215 //
00216 //
00217 // Purpose: Allocate a unique (either locally or globally) SEQNO.
00218 //
00219 // Arguments:
00220 // tableName in The table for which the SEQNO is required.
00221 // requireGlobal in The type of SEQNO required:-
00222 // > 0 Must be global
00223 // = 0 Must be global if supplied dbNo is authorising
00224 // and table isn't temporary otherwise local
00225 // < 0 Must be local
00226 // dbNo in The entry in the cascade for which the SEQNO is required
00227 //
00228 // Return: The allocated SEQNO or 0 if failure.
00229 //
00230 // Contact: N. West
00231
00232 // Program Notes:-
00233 // =============
00234
00235 // Requests for SEQNOs take account of any pre-existing entries; local entries
00236 // should only be used for development and this allows for the LOCALSEQNO table
00237 // and the local data to be wiped at different times without causing conflicts.
00238 // Global entries should not be a problem as the GLOBALSEQNO table isn't wiped
00239 // but it provides protection in case the table is damaged (which has happened!).
00240
00241 bool isTemporary = IsTemporaryTable(tableName,dbNo);
00242
00243 // Deal with global requests.
00244
00245 if ( requireGlobal > 0
00246 || ( requireGlobal == 0 && dbNo == fGlobalSeqNoDbNo && ! isTemporary ) ) {
00247 if ( fGlobalSeqNoDbNo < 0 ) {
00248 MSG("Dbi",Msg::kWarning) << "Unable to issue global SEQNO - no authorising DB in cascade\n"
00249 << " will issue local one instead" << endl;
00250 }
00251 else if ( isTemporary ) {
00252 MSG("Dbi",Msg::kWarning) << "Unable to issue global SEQNO - " << tableName << " is temporary\n"
00253 << " will issue local one instead" << endl;
00254 }
00255 else return this->ReserveNextSeqNo(tableName,true,fGlobalSeqNoDbNo);
00256 }
00257
00258 // Deal with local requests
00259
00260 return this->ReserveNextSeqNo(tableName,false,dbNo);
00261
00262 }
|
|
|
Create a DbiStatement. Caller must delete.
Definition at line 266 of file DbiCascader.cxx. References fConnections, GetStatus(), and DbiStatement::PrintExceptions(). Referenced by DbuDaqFileModule::BeginJob(), createSpillTables(), PhotonStatSummarizer::CreateTables(), CreateTables(), DbmValidate::DbmValidate(), DTFtest(), DbiDBProxy::FindTimeBoundaries(), DbmModule::Import(), DbuDaqMonitorModule::InitTSQLConnection(), DbmModule::ListTables(), DbiDBProxy::QueryAllValidities(), DbiDBProxy::QuerySeqNo(), DbiDBProxy::QuerySeqNos(), DbiDBProxy::QueryValidity(), DbiDBProxy::RemoveSeqNo(), DbiDBProxy::ReplaceInsertDate(), DbiDBProxy::ReplaceSeqNo(), and DbiDBProxy::ReplaceSeqNoOracle(). 00266 {
00267 //
00268 //
00269 // Purpose: Return a Statement to caller.
00270 //
00271 // Arguments:
00272 // dbNo in Database no. in cascade for which statement
00273 // is required.
00274 //
00275 // Return: Created statement (or 0 if creation failed).
00276 // User must delete.
00277 // Program Notes:-
00278 // =============
00279
00280 // As the caller is responsible for destroying the statement after use
00281 // consider:-
00282 //
00283 // #include <memory>
00284 // using std::auto_ptr;
00285 //
00286 // ...
00287 //
00288 // auto_ptr<DbiStatement> stmt(cascader.CreateStatement(dbNo));
00289
00290
00291 if ( this->GetStatus(dbNo) == kFailed ) return 0;
00292 DbiConnection& conDb = *fConnections[dbNo];
00293 DbiStatement* stmtDb = new DbiStatement(conDb);
00294 stmtDb->PrintExceptions();
00295 return stmtDb;
00296
00297 }
|
|
||||||||||||
|
Definition at line 300 of file DbiCascader.cxx. References DbiStatement::ExecuteUpdate(), fConnections, fTemporaryTables, GetConnection(), DbiConnection::GetUrl(), Dbi::GetVldDescr(), MsgService::Instance(), MsgService::IsActive(), DbiConnection::IsTemporary(), MAXMSG, MSG, DbiConnection::SetPermanent(), DbiConnection::SetTableExists(), and UtilString::ToUpper(). Referenced by DetailedTimeCal(), load_better_mipcal(), load_mc_mipcal(), LoadBeamMomentum(), LoadCERRange(), LoadCERTimeWin(), LoadOverlapWin(), LoadTOFRange(), main(), MakeFilterChannelList(), UgliGeometryReroot::MakeTempDbiGeometry(), UgliGeometryReroot::MakeTempDbiPosInfo(), UgliGeometryReroot::MakeTempDbiScintStruct(), MakeTimeCal(), AutoPIDMaker::Reco(), FillSpillServerMon::WriteToDatabase(), FillNearRunQuality::WriteToDatabase(), FillHvFromSingles::WriteToDatabase(), and FillFarRunQuality::WriteToDatabase(). 00301 {
00302 //
00303 //
00304 // Purpose: Creat temporary table with associated validity table
00305 //
00306 // Arguments:
00307 // tableNameMc in Table name
00308 // tableDescr in Table description as parenthesised comma
00309 // separated list e.g.:-
00310 // "(MyInt int, MyFloat float, MyString text)"
00311 //
00312 // Return: The database cascade number on which the table was
00313 // created or = -1 if unable to create.
00314 //
00315 // Contact: N. West
00316 //
00317 // Specification:-
00318 // =============
00319 //
00320 // o Loop over all databases in cascade, starting at the highest
00321 // priority i.e. entry 0 and find the first that will accept create
00322 // temporary table requests. Return -1 if none will.
00323 //
00324 // o Make connection permanent so that temporary data won't be lost.
00325 //
00326 // o Generate and submit requests to create temporary table with
00327 // associated validity table and return the cascade number of
00328 // the database that has accepted the tables, recording table
00329 // name in fTemporaryTables.
00330 //
00331
00332
00333 // Check that input args look plausible.
00334
00335 string tableName = UtilString::ToUpper(tableNameMc);
00336 if ( tableName == ""
00337 || tableDescr[0] != '('
00338 || tableDescr[tableDescr.size()-1] != ')' ) {
00339 MAXMSG("Dbi",Msg::kError,20) << "Illegal input args:-" << endl
00340 << " Table Name: " << tableName
00341 << " Table Description: " << tableDescr
00342 <<endl;
00343 return -1;
00344 }
00345
00346 // Find a DB that will accept the command.
00347 string sqlMakeTable;
00348
00349 Int_t dbNoAcc = -1;
00350 auto_ptr<DbiStatement> stmtDb;
00351 for (UInt_t dbNoTry = 0; dbNoTry < fConnections.size(); ++dbNoTry ) {
00352 stmtDb.reset(this->CreateStatement(dbNoTry));
00353 if ( stmtDb.get() ) {
00354 sqlMakeTable = " create temporary table ";
00355 sqlMakeTable += tableName;
00356 sqlMakeTable += " ";
00357 sqlMakeTable += tableDescr;
00358 sqlMakeTable += ";";
00359 stmtDb->ExecuteUpdate(sqlMakeTable.c_str());
00360 if ( stmtDb->GetExceptionLog().IsEmpty() ) {
00361 dbNoAcc = dbNoTry;
00362 this->GetConnection(dbNoAcc)->SetTableExists(tableName);
00363 break;
00364 }
00365 if ( MsgService::Instance()->IsActive("Dbi",Msg::kSynopsis) )stmtDb->PrintExceptions();
00366 }
00367 }
00368
00369 if ( dbNoAcc < 0 ) {
00370 if ( stmtDb.get()) stmtDb->PrintExceptions();
00371 return -1;
00372 }
00373
00374 // Make connection permanent if not already.
00375 DbiConnection& conDb = *fConnections[dbNoAcc];
00376 if ( conDb.IsTemporary() ) {
00377 conDb.SetPermanent();
00378 MSG("Dbi",Msg::kInfo) << "Making connection: " << conDb.GetUrl()
00379 << " permanent to preserve temporary tables." << endl;
00380 }
00381
00382 // Create SQL to create auxillary validity table and write to same Db.
00383 sqlMakeTable = Dbi::GetVldDescr(tableName.c_str(),true);
00384
00385 MSG("Dbi",Msg::kSynopsis) << "Validity Table creation: "
00386 << " Database: " << dbNoAcc << " "
00387 << sqlMakeTable << endl;
00388 stmtDb->ExecuteUpdate(sqlMakeTable.c_str());
00389 if ( stmtDb->PrintExceptions() ) return -1;
00390 this->GetConnection(dbNoAcc)->SetTableExists(tableName+"VLD");
00391 fTemporaryTables[tableName] = dbNoAcc;
00392 return dbNoAcc;
00393
00394 }
|
|
|
Definition at line 91 of file DbiCascader.h. Referenced by DbmModule::GlobaliseSeqNo(), and DbiWriter< T >::WritingToMaster(). 00091 { return fGlobalSeqNoDbNo; }
|
|
|
Definition at line 410 of file DbiCascader.cxx. References fConnections, and GetStatus(). 00410 {
00411 //
00412 //
00413 // Purpose: Return a connection to caller (DbiCascader retains ownership)
00414
00415
00416 if ( this->GetStatus(dbNo) == kFailed ) return 0;
00417 return fConnections[dbNo];
00418
00419 }
|
|
|
Return associated DbiConnection. DbiCascader retains ownership.
Definition at line 398 of file DbiCascader.cxx. References fConnections, and GetStatus(). Referenced by CreateTemporaryTable(), DTFtest(), GetTableDbNo(), DbiDBProxy::ReplaceSeqNo(), and DbiDBProxy::StoreMetaData(). 00398 {
00399 //
00400 //
00401 // Purpose: Return a connection to caller (DbiCascader retains ownership)
00402
00403
00404 if ( this->GetStatus(dbNo) == kFailed ) return 0;
00405 return fConnections[dbNo];
00406
00407 }
|
|
|
Definition at line 424 of file DbiCascader.cxx. References fConnections, DbiConnection::GetDbName(), GetNumDb(), and MSG. 00424 {
00425 //
00426 //
00427 // Purpose: Return Database Name for cascade entry number.
00428
00429 string dbName;
00430
00431 if ( dbNo < this->GetNumDb() ) dbName = fConnections[dbNo]->GetDbName();
00432 else MSG("Dbi",Msg::kWarning) << "Database does not contain entry " << dbNo << endl;
00433 return dbName;
00434
00435 }
|
|
|
Definition at line 439 of file DbiCascader.cxx. References fConnections, GetNumDb(), and MSG. Referenced by DbiWriter< T >::SetDbName(). 00439 {
00440 //
00441 //
00442 // Purpose: Return number of first DB in cascade with name dbName.
00443 //
00444 // Return: Database number corresponding to dbName or -1 if none.
00445
00446 for ( unsigned dbNo = 0; dbNo < this->GetNumDb(); ++dbNo) {
00447 if ( dbName == fConnections[dbNo]->GetDbName() ) return dbNo;
00448 }
00449
00450 MSG("Dbi",Msg::kWarning) << "Database does not contain entry " << dbName << endl;
00451 return -1;
00452
00453 }
|
|
|
Definition at line 92 of file DbiCascader.h. Referenced by DbiTableProxyRegistry::Config(), GetDbName(), GetDbNo(), DbiDBProxy::GetNumDb(), main(), operator<<(), DbiDBProxy::StoreMetaData(), and ~DbiCascader(). 00092 {return fConnections.size();}
|
|
|
Definition at line 78 of file DbiCascader.h. Referenced by CreateStatement(), GetConnection(), and GetStatusAsString(). 00078 {
00079 if ( dbNo >= GetNumDb() || ! fConnections[dbNo] ) return kFailed;
00080 return fConnections[dbNo]->IsClosed() ? kClosed : kOpen; }
|
|
|
Definition at line 457 of file DbiCascader.cxx. References GetStatus(), kClosed, and kOpen. Referenced by operator<<(). 00457 {
00458 //
00459 //
00460 // Purpose: Return DB connection status as a string.
00461 //
00462 // Arguments:
00463 // dbNo in Database number (0..GetNumDb()-1)
00464
00465 Int_t status = GetStatus(dbNo);
00466
00467 switch ( status ) {
00468 case kClosed: return "Closed";
00469 case kOpen: return "Open ";
00470 default: return "Failed";
00471 }
00472
00473 }
|
|
||||||||||||
|
Definition at line 476 of file DbiCascader.cxx. References fConnections, GetConnection(), and DbiConnection::TableExists(). Referenced by DbmModule::LogEntry(), and DbiSqlValPacket::SetMetaData(). 00477 {
00478 //
00479 //
00480 // Purpose: Return cascade number of first database that holds table
00481 // or -1 if none.
00482
00483 // If selectDbNo >= 0 only look in this entry in the cascade.
00484
00485 // If table name has any lower case letters then fail.
00486 // Lower case are not allowed by ORACLE which kindly
00487 // converts to upper case so SQL would pass if upper case version
00488 // exists.
00489 string::const_iterator itr = tableName.begin();
00490 string::const_iterator itrEnd = tableName.end();
00491 while ( itr != itrEnd ) if ( islower(*itr++) ) return -1;
00492
00493 // Loop over cascade looking for table.
00494
00495 for (UInt_t dbNoTry = 0; dbNoTry < fConnections.size(); ++dbNoTry ) {
00496 if ( selectDbNo >= 0 && (UInt_t) selectDbNo != dbNoTry ) continue;
00497 const DbiConnection* con = this->GetConnection(dbNoTry);
00498 if ( con && con->TableExists(tableName) ) return dbNoTry;
00499 }
00500
00501 return -1;
00502
00503 }
|
|
|
Definition at line 82 of file DbiCascader.h. Referenced by operator<<(), and DbiLogEntry::SetServerName(). 00082 {
00083 return ( dbNo < GetNumDb() ) ? fConnections[dbNo]-> GetUrl(): ""; }
|
|
|
Definition at line 506 of file DbiCascader.cxx. References DbiConnection::ConnectStatement(), and fConnections. 00506 {
00507 //
00508 //
00509 // Purpose: Hold temporary connections open
00510
00511 // Specification:-
00512 // =============
00513
00514 // Hold all connections open by telling them that they have a
00515 // connected statement.
00516
00517 // Program Notes:-
00518 // =============
00519
00520 // See DbiConnectionMaintainer for use.
00521
00522 for (UInt_t dbNo = 0; dbNo < fConnections.size(); ++dbNo )
00523 fConnections[dbNo]->ConnectStatement();
00524 }
|
|
||||||||||||
|
Definition at line 528 of file DbiCascader.cxx. References fTemporaryTables. Referenced by AllocateSeqNo(), ReserveNextSeqNo(), and DbiWriter< T >::WritingToMaster(). 00529 {
00530 //
00531 //
00532 // Purpose: Return kTRUE if tableName is temporary in cascade member dbNo
00533
00534 map<string,Int_t>::const_iterator itr
00535 = fTemporaryTables.find(tableName);
00536 return ( itr != fTemporaryTables.end()
00537 && (*itr).second == dbNo );
00538
00539 }
|
|
|
Definition at line 626 of file DbiCascader.cxx. References fConnections. Referenced by DbiConnectionMaintainer::~DbiConnectionMaintainer(). 00626 {
00627 //
00628 //
00629 // Purpose: Release temporary connections held open by HoldConnections.
00630
00631
00632 // Specification:-
00633 // =============
00634
00635 // Undo HoldConnections() by telling all connections that they no longer
00636 // have a connected statement.
00637
00638 // Program Notes:-
00639 // =============
00640
00641 // See DbiConnectionMaintainer for use.
00642
00643 for (UInt_t dbNo = 0; dbNo < fConnections.size(); ++dbNo )
00644 fConnections[dbNo]->DisConnectStatement();
00645 }
|
|
||||||||||||||||
|
Definition at line 648 of file DbiCascader.cxx. References DbiString::c_str(), DbiString::Clear(), IsTemporaryTable(), MAXMSG, MSG, and TableExists(). Referenced by AllocateSeqNo(). 00650 {
00651 //
00652 //
00653 // Purpose: Reserve the next higher available unique (either locally or globally) SEQNO.
00654 // in the appropriate SEQNO table.
00655 //
00656 // Arguments:
00657 // tableName in The table for which the SEQNO is required.
00658 // isGlobal in = true - reserve in GLOBALSEQNO table(dbNo must be authorizing)
00659 // = false - reserve in LOCALSEQNO table (creating if required)
00660 // dbNo in The entry in the cascade holding the SEQNO table.
00661 //
00662 // Return: The allocated SEQNO or 0 if failure.
00663 //
00664 // Contact: N. West
00665
00666 // Program Notes:-
00667 // =============
00668
00669 // Requests for local SEQNOs may result in the creation of a LOCALSEQNO table.
00670
00671 DbiString sql;
00672
00673 string seqnoTableName = isGlobal ? "GLOBALSEQNO" : "LOCALSEQNO";
00674 bool seqnoTableNameExists = this->TableExists(seqnoTableName,dbNo);
00675 bool tableNameExists = this->TableExists(tableName,dbNo);
00676
00677 auto_ptr<DbiStatement> stmtDb(this->CreateStatement(dbNo) );
00678 if ( ! stmtDb.get() ) return 0;
00679
00680 // Check that required SEQNO table exists.
00681
00682 if ( isGlobal ) {
00683 if ( ! seqnoTableNameExists ) {
00684 MAXMSG("Dbi",Msg::kError,20) << "Unable to issue global SEQNO - " << dbNo
00685 << " is not an authorising DB" << endl;
00686 return 0;
00687 }
00688 }
00689 else {
00690 if ( ! seqnoTableNameExists ) {
00691 sql.Clear();
00692 sql << "CREATE TABLE " << seqnoTableName
00693 << "(TABLENAME CHAR(64) NOT NULL PRIMARY KEY,\n"
00694 << " LASTUSEDSEQNO INT )";
00695
00696 MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00697 << " create local SEQNO table query: " << sql.c_str() << endl;
00698 stmtDb->ExecuteUpdate(sql.c_str());
00699 if ( stmtDb->PrintExceptions() ) return 0;
00700 sql.Clear();
00701 sql << "INSERT INTO " << seqnoTableName << " VALUES ('*',0)";
00702 MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00703 << " prime local SEQNO table query: " << sql.c_str() << endl;
00704 stmtDb->ExecuteUpdate(sql.c_str());
00705 if ( stmtDb->PrintExceptions() ) return 0;
00706 }
00707 }
00708
00709 // Lock seqno table by creating a lock object on the stack.
00710 // Table will be unlocked when lock object destroyed.
00711
00712 string dataTable;
00713 // Only pass in table name if it's not temporary and exists in
00714 // the selected DB otherwise Lock will try to lock a non-existent table.
00715 if ( ! this->IsTemporaryTable(tableName,dbNo)
00716 && tableNameExists ) dataTable = tableName;
00717 Lock lock(this->CreateStatement(dbNo),seqnoTableName,dataTable);
00718 if ( ! lock.IsLocked() ) {
00719 MAXMSG("Dbi",Msg::kError,20) << "Unable to lock " << seqnoTableName << endl;
00720 return 0;
00721 }
00722
00723 // Find row containing last used SeqNo for this table.
00724 // Not that comparison is case insensitive.
00725 sql.Clear();
00726 sql << "select * from " << seqnoTableName << " where TABLENAME = '*' or TABLENAME = '";
00727 sql << tableName + "' order by TABLENAME";
00728 MSG("Dbi",Msg::kSynopsis) << seqnoTableName << " query: " << sql.c_str() << endl;
00729 TSQLStatement* stmt = stmtDb->ExecuteQuery(sql.c_str());
00730 stmtDb->PrintExceptions(Msg::kDebug);
00731 Int_t seqNoDefault = 0;
00732 if ( stmt && stmt->NextResultRow() ) {
00733 seqNoDefault = stmt->GetInt(1);
00734 }
00735 else {
00736 MAXMSG("Dbi",Msg::kError,20) << "Unable to find default SeqNo"
00737 << " due to above error" << endl;
00738 delete stmt;
00739 stmt = 0;
00740 return 0;
00741 }
00742 Int_t seqNoTable = seqNoDefault;
00743 if ( stmt->NextResultRow() ) {
00744 seqNoTable = stmt->GetInt(1);
00745 }
00746 delete stmt;
00747 stmt = 0;
00748 MSG("Dbi",Msg::kSynopsis) << " query returned last used seqno: " << seqNoTable << endl;
00749
00750 // If the table exists, make sure that the seqNo hasn't already been used.
00751 // This is paranoia code and expensive, so only do the check once for
00752 // each tableName/isGlobal/dbNo combination.
00753
00754 static std::string checkedCombinations;
00755 ostringstream combination;
00756 combination << ":" << tableName << isGlobal << dbNo << ":";
00757 bool notChecked = checkedCombinations.find(combination.str()) == std::string::npos;
00758 if ( notChecked ) checkedCombinations += combination.str();
00759 if ( tableNameExists && notChecked ) {
00760 Int_t seqNoMin = seqNoDefault;
00761 Int_t seqNoMax = seqNoDefault + Dbi::kMAXLOCALSEQNO;
00762 sql.Clear();
00763 sql << "select max(SEQNO) from " << tableName << "VLD"
00764 << " where SEQNO between " << seqNoMin << " and " << seqNoMax;
00765 MSG("Dbi",Msg::kSynopsis) << "Database: " << dbNo
00766 << " max SEQNO query: " << sql.c_str() << endl;
00767 stmt = stmtDb->ExecuteQuery(sql.c_str());
00768 if ( stmtDb->PrintExceptions() ) return 0;
00769 Int_t minValue = 0;
00770 // Queries returning group function results can be null.
00771 if ( stmt && stmt->NextResultRow() && ! stmt->IsNull(0) ) {
00772 minValue = stmt->GetInt(0);
00773 if ( minValue <= 0 ) minValue = 0; // Should never happen.
00774 }
00775 delete stmt;
00776 stmt = 0;
00777
00778 if ( minValue > seqNoTable ) {
00779 MAXMSG("Dbi",Msg::kError,20)
00780 << "Database: " << dbNo << " "
00781 << seqnoTableName << " has last used SEQNO of "
00782 << seqNoTable << " for table " << tableName
00783 << ",\n but the highest SEQNO in the band " << seqNoMin << " to " << seqNoMax
00784 << " is " << minValue << " for that table\n "
00785 << seqnoTableName << " is out of date! It will be updated for " << tableName << endl;
00786 seqNoTable = minValue;
00787 }
00788 }
00789
00790
00791 // Update last used SeqNo and record in table.
00792 sql.Clear();
00793 sql << "delete from " << seqnoTableName << " where TABLENAME='";
00794 sql << tableName + "'";
00795 MSG("Dbi",Msg::kSynopsis) << "SEQNO entry removal: " << sql.c_str() << endl;
00796 stmtDb->ExecuteUpdate(sql.c_str());
00797 if ( stmtDb->PrintExceptions() ) return 0;
00798
00799 seqNoTable++;
00800
00801 sql.Clear();
00802 sql << "insert into " << seqnoTableName << " values('";
00803 sql << tableName + "'," << seqNoTable << ")";
00804 MSG("Dbi",Msg::kSynopsis) << "SEQNO entry add: " << sql.c_str() << endl;
00805 stmtDb->ExecuteUpdate(sql.c_str());
00806 if ( stmtDb->PrintExceptions() ) return 0;
00807
00808 return seqNoTable;
00809
00810 }
|
|
|
Definition at line 112 of file DbiCascader.h. 00112 {fGlobalSeqNoDbNo = entry;}
|
|
||||||||||||
|
Definition at line 813 of file DbiCascader.cxx. References fConnections. Referenced by DbiTableProxyRegistry::Config(), and main(). 00814 {
00815 //
00816 //
00817 // Purpose: Set connection permanent.
00818
00819 if ( dbNo < fConnections.size() ) fConnections[dbNo]->SetPermanent(permanent);
00820
00821 }
|
|
||||||||||||
|
Definition at line 94 of file DbiCascader.h. Referenced by FillSpillServerMon::ReadFromDatabase(), FillNearRunQuality::ReadFromDatabase(), FillHvFromSingles::ReadFromDatabase(), FillFarRunQuality::ReadFromDatabase(), DbiSqlValPacket::Recreate(), ReserveNextSeqNo(), DbiDBProxy::TableExists(), FillSpillServerMon::WriteToDatabase(), FillNearRunQuality::WriteToDatabase(), FillHvFromSingles::WriteToDatabase(), and FillFarRunQuality::WriteToDatabase(). 00094 {
00095 return this->GetTableDbNo(tableName,selectDbNo) >= 0; }
|
|
|
Definition at line 54 of file DbiCascader.h. |
|
|
Definition at line 59 of file DbiCascader.h. |
|
||||||||||||
|
Definition at line 174 of file DbiCascader.cxx. 00174 {
00175 //
00176 //
00177 // Purpose: Output DbiCascader status to message stream.
00178 //
00179 // Arguments:
00180 // os in ostream to output on
00181 // cascader in Cascader to be output
00182 //
00183 // Return: ostream
00184 //
00185 // Contact: N. West
00186 //
00187 // Specification:-
00188 // =============
00189 //
00190 // o Output DbiCascader status to ostream.
00191
00192 // Program Notes:-
00193 // =============
00194
00195 // None.
00196
00197 os << "DbiCascader Status:- " << endl
00198 << "Status URL" << endl << endl;
00199
00200 int maxDb = cascader.GetNumDb();
00201 for (Int_t dbNo = 0; dbNo < maxDb; ++dbNo)
00202 os << cascader.GetStatusAsString(dbNo) << " "
00203 << ( ( dbNo == cascader.fGlobalSeqNoDbNo ) ? "(auth) " : " ")
00204 << cascader.GetURL(dbNo) << endl;
00205 os << endl;
00206 return os;
00207
00208 }
|
|
|
Vector of DbiConnections, one for each DB.
Definition at line 125 of file DbiCascader.h. Referenced by CreateStatement(), CreateTemporaryTable(), GetConnection(), GetDbName(), GetDbNo(), GetTableDbNo(), HoldConnections(), ReleaseConnections(), SetPermanent(), and ~DbiCascader(). |
|
|
1st db in cascade with GlobalSeqNo table
Definition at line 122 of file DbiCascader.h. Referenced by AllocateSeqNo(), and operator<<(). |
|
|
Mapping Name->DbNo for temporary tables.
Definition at line 128 of file DbiCascader.h. Referenced by CreateTemporaryTable(), and IsTemporaryTable(). |
1.3.9.1