#include #include #include "FairDbWriter.h" #include "FairDbMultConnector.h" #include "FairDbOutRowStream.h" #include "FairDbResPtr.h" #include "FairDbSqlValPacket.h" #include "FairDbTableProxy.h" using std::cout; using std::endl; //templateClassImpUnique(FairDbWriter,T) ClassImpT(FairDbWriter,T) //..................................................................... template FairDbWriter::FairDbWriter() : fAggregateNo(-2), fDbNo(0), fPacket(new FairDbSqlValPacket), fRequireGlobalSeqno(0), fTableProxy(&FairDbWriter::GetTableProxy()), fTableName(fTableProxy->GetTableName()), fUseOverlayCreationDate(kFALSE), fValidRec(0), fLogEntry(fTableName) { } //..................................................................... template FairDbWriter::FairDbWriter(const ValRange& vr, Int_t aggNo, FairDb::Version task, ValTimeStamp creationDate, UInt_t dbNo, const std::string& logComment, const std::string& tableName) : fAggregateNo(aggNo), fDbNo(dbNo), fPacket(new FairDbSqlValPacket), fRequireGlobalSeqno(0), fTableProxy(&FairDbWriter::GetTableProxy(tableName)), fTableName(fTableProxy->GetTableName()), fUseOverlayCreationDate(creationDate == ValTimeStamp(0,0)), fValidRec(0), fLogEntry(fTableName,logComment,vr.GetDetectorMask(),vr.GetSimMask(),task) { //cout << " -I- FairDbWriter Open() called " << endl; Open(vr,aggNo,task,creationDate,dbNo,logComment); } //..................................................................... template FairDbWriter::FairDbWriter(const ValRange& vr, Int_t aggNo, FairDb::Version task, ValTimeStamp creationDate, const std::string& dbName, const std::string& logComment, const std::string& tableName) : fAggregateNo(aggNo), fDbNo(), fPacket(new FairDbSqlValPacket), fRequireGlobalSeqno(0), fTableProxy(&FairDbWriter::GetTableProxy(tableName)), fTableName(fTableProxy->GetTableName()), fUseOverlayCreationDate(creationDate == ValTimeStamp(0,0)), fValidRec(0), fLogEntry(fTableName,logComment,vr.GetDetectorMask(),vr.GetSimMask(),task) { Open(vr,aggNo,task,creationDate,dbName,logComment); } //..................................................................... template FairDbWriter::FairDbWriter(const FairDbValidityRec& vrec, UInt_t dbNo, const std::string& logComment) : fAggregateNo(0), fDbNo(dbNo), fPacket(new FairDbSqlValPacket), fRequireGlobalSeqno(0), fTableProxy(0), fTableName(), fUseOverlayCreationDate(kFALSE), fValidRec(new FairDbValidityRec(vrec)), fLogEntry(fTableName,logComment,vrec.GetValRange().GetDetectorMask(), vrec.GetValRange().GetSimMask(),vrec.GetVersion()) { T pet; this->Open(vrec,dbNo,logComment); } //..................................................................... template FairDbWriter::FairDbWriter(const FairDbValidityRec& vrec, const std::string& dbName, const std::string& logComment) : fAggregateNo(0), fDbNo(), fPacket(new FairDbSqlValPacket), fRequireGlobalSeqno(0), fTableProxy(0), fTableName(), fUseOverlayCreationDate(kFALSE), fValidRec(new FairDbValidityRec(vrec)), fLogEntry(fTableName,logComment,vrec.GetValRange().GetDetectorMask(), vrec.GetValRange().GetSimMask(),vrec.GetVersion()) { T pet; this->Open(vrec,dbName,logComment); } //..................................................................... template FairDbWriter::~FairDbWriter() { Reset(); delete fPacket; fPacket = 0; delete fValidRec; fValidRec = 0; } //..................................................................... template FairDbWriter& FairDbWriter::operator<<(const T& row) { //cout << "Writer ---> 1" << endl; if ( ! this->IsOpen() ) { return *this; } Int_t AggNoRow = row.GetAggregateNo(); if ( fAggregateNo != AggNoRow ) { cout << "Cannot store row data for table " << fTableName << ", current set has aggregate no.: " << fAggregateNo << ", but it has: " << AggNoRow << " \n closing FairDbWriter" << endl; this->Abort(); return *this; } //cout << "Writer ---> 2" << endl; if ( ! fPacket->AddDataRow(*fTableProxy,fValidRec,row) ) { cout << "Closing FairDbWriter due to above error." << endl; this->Abort(); } //cout << "Writer ---> 3" << endl; return *this; } //..................................................................... template Bool_t FairDbWriter::CanOutput(Bool_t reportErrors) const { // // // Purpose: Return true if open and ready to receive/output data. if ( ! this->IsOpen(reportErrors) ) { return kFALSE; } if ( this->NeedsLogEntry() && ! fLogEntry.HasReason() ) { if ( reportErrors ) cout << "Cannot output validity set for table " << fTableName << ", writing to Master DB but no log comment has been supplied." << endl; return kFALSE; } UInt_t nstmts = fPacket->GetNumSqlStmts(); if ( nstmts == 0 ) { // not even a VLD insert if ( reportErrors ) cout << "Cannot output validity set for table " << fTableName << ", no data has been written." << endl; return kFALSE; } if ( nstmts == 1 ) { // if VLD insert present but no data rows, just issue a stern warning // as it may be intended to obscure now invalid data string stmt = fPacket->GetStmt(0); bool isvldentry = (stmt.find("INSERT INTO") != string::npos ) && (stmt.find("VLD VALUES") != string::npos); if ( isvldentry ) { if ( reportErrors ) cout << "VAL entry but no data for " << fTableName << endl; } else { // this should never, ever happen ... but let's be paranoid if ( reportErrors ) { cout << "Cannot output validity set for table " << fTableName << ", (no VLD info) no data has been written." << endl; fPacket->Print(); } return kFALSE; } } return kTRUE; } //..................................................................... template Bool_t FairDbWriter::Close(const char* fileSpec) { Bool_t ok = kFALSE; // Skip output unless good data to output. if ( CanOutput() ) { // Find the next free sequence number. It must be global if writing to a // to a file, otherwise it can be local if DB isn't authorising. int seqNoType = fileSpec ? 1 : fRequireGlobalSeqno; Int_t seqNo = fTableProxy->GetMultConnector().AllocateSeqNo(fTableName,seqNoType,fDbNo); if ( seqNo <= 0 ) { cout << "Cannot get sequence number for table " << fTableName << endl; } else { // Use overlay creation date if required. if ( fUseOverlayCreationDate && fValidRec ) { fPacket->SetCreationDate(fTableProxy->QueryOverlayCreationDate(*fValidRec,fDbNo)); } // Set SEQNO and perform I/O. fPacket->SetSeqNo(seqNo); if ( fileSpec ) { ofstream fs(fileSpec,ios_base::app); if ( ! fs ) { cout << "Unable to open " << fileSpec << endl; } else { ok = fPacket->Write(fs,true); } } else { ok = fPacket->Store(fDbNo); } // Record update if I/O successful and required. if ( ok && this->WritingToMaster() ) { if ( this->NeedsLogEntry() || fLogEntry.HasReason() ) { ok = fLogEntry.Write(fDbNo,seqNo); } } } } // Clear out ready for any further I/O. fPacket->Clear(); return ok; } //..................................................................... template void FairDbWriter::CompleteOpen(UInt_t dbNo, const std::string& logComment) { fDbNo = dbNo; if ( (int) fDbNo < 0 ) { cout << "Bad database name/number selected. " << endl; this->Reset(); return; } fAggregateNo = fValidRec->GetAggregateNo(); fTableName = fTableProxy->GetTableName(), // Recreate validity packet. fPacket->Recreate(fTableName, fValidRec->GetValRange(), fAggregateNo, fValidRec->GetVersion(), fValidRec->GetCreationDate()); // Recreate log entry. const ValRange& vr = fValidRec->GetValRange(); fLogEntry.Recreate(fTableName, logComment, vr.GetDetectorMask(), vr.GetSimMask(), fValidRec->GetVersion()); } //..................................................................... template FairDbTableProxy& FairDbWriter::GetTableProxy() { return FairDbResultPtr::GetTableProxy(); } //..................................................................... template FairDbTableProxy& FairDbWriter::GetTableProxy( const std::string& tableName) { return FairDbResultPtr::GetTableProxy(tableName); } //..................................................................... template Bool_t FairDbWriter::IsOpen(Bool_t reportErrors) const { if ( ! FairDbTableProxyRegistry::IsActive() ) { if ( reportErrors ) { cout << "Cannot use FairDbWriter, the DB has been shutdown." << endl; } } else if ( !fValidRec || fPacket->GetNumSqlStmts() < 1 ) { if ( reportErrors ) cout << "Cannot do I/O on FairDbWriter for " << fTableName <<", it is currently closed." << endl; } else { return kTRUE; } return kFALSE; } //..................................................................... template Bool_t FairDbWriter::NeedsLogEntry() const { // Some tables are created automatically so don't require entries. string tableName(fTableName); if ( tableName.substr(0,7) == "BEAMMON" || tableName.substr(0,3) == "CAL" || tableName.substr(0,9) == "DBU" ) { return kFALSE; } // All other tables need entries if writing to a Master database. return this->WritingToMaster(); } //..................................................................... template Bool_t FairDbWriter::Open (const ValRange& vr, Int_t aggNo, FairDb::Version task, ValTimeStamp creationDate, UInt_t dbNo, const std::string& logComment) { bool ok = true; if ( ! FairDbTableProxyRegistry::IsActive() ) { return kFALSE; } if ( this->CanOutput(kFALSE) ) { ok = Close(); } // Test for special creation date. fUseOverlayCreationDate = creationDate == ValTimeStamp(0,0); // Create a validity record. delete fValidRec; fValidRec = new FairDbValidityRec(vr,task,aggNo,0,0,kFALSE,creationDate); // Get a proxy. fTableProxy = &FairDbWriter::GetTableProxy(fTableName); // Complete opening. this->CompleteOpen(dbNo,logComment); return ok; } //..................................................................... template Bool_t FairDbWriter::Open (const ValRange& vr, Int_t aggNo, FairDb::Version task, ValTimeStamp creationDate, const string& dbName, const std::string& logComment) { this->SetDbName(dbName); return this->Open(vr, aggNo, task, creationDate, fDbNo, logComment); } //..................................................................... template Bool_t FairDbWriter::Open(const FairDbValidityRec& vrec, UInt_t dbNo, const std::string& logComment) { bool ok = true; if ( ! FairDbTableProxyRegistry::IsActive() ) { return kFALSE; } if ( this->CanOutput(kFALSE) ) { ok = Close(); } // Check that vrec is associated with the right table, but waive // test for FairDbConfigSet so that it can be used with any. const FairDbTableProxy& proxyDefault = FairDbWriter::GetTableProxy(); const FairDbTableProxy& proxyVrec = *vrec.GetTableProxy(); if ( proxyDefault.GetTableName() != "FAIRDBCONFIGSET" && proxyVrec.GetTableName() != proxyDefault.GetTableName() ) { cout << "Unable to create FairDbWriter from query:" << endl << vrec << " was filled by " << proxyVrec.GetTableName() << " not by " << proxyDefault.GetTableName() << endl; this->Reset(); return false; } else { // Have to cast away const - FairDbWriter needs a modifiable FairDbTableProxy. fTableProxy = const_cast(&proxyVrec); } fUseOverlayCreationDate = vrec.GetCreationDate() == ValTimeStamp(0,0); delete fValidRec; fValidRec = new FairDbValidityRec(vrec); // Complete opening. this->CompleteOpen(dbNo,logComment); return ok; } //..................................................................... template Bool_t FairDbWriter::Open(const FairDbValidityRec& vrec, const string& dbName, const std::string& logComment) { this->SetDbName(dbName); return this->Open(vrec, fDbNo, logComment); } //..................................................................... template void FairDbWriter::Reset() { fAggregateNo = 0; fDbNo = 0; fPacket->Clear(); fTableProxy = &FairDbWriter::GetTableProxy(); fTableName = fTableProxy->GetTableName(); delete fValidRec; fValidRec = 0; } //..................................................................... template void FairDbWriter::SetDbName(const string& dbName) { if ( dbName == "" ) { fDbNo = 0; } else { fDbNo = FairDbTableProxyRegistry::Instance().GetMultConnector().GetDbNo(dbName); } } //..................................................................... template void FairDbWriter::SetLogComment(const std::string& reason) { fLogEntry.SetReason(reason); } //..................................................................... template FairDbTableProxy& FairDbWriter::TableProxy() const { assert( FairDbTableProxyRegistry::IsActive() ); return *fTableProxy; } //..................................................................... template Bool_t FairDbWriter::WritingToMaster() const { FairDbMultConnector& cascader = FairDbTableProxyRegistry::Instance().GetMultConnector(); return ( fDbNo == (UInt_t) cascader.GetAuthorisingDbNo() && ! cascader.IsTemporaryTable(fTableName,fDbNo)); }