00001
00002 #include "SpillServerMonFinder.h"
00003 #include "MessageService/MsgService.h"
00004 #include "DatabaseInterface/DbiSqlContext.h"
00005 #include <cmath>
00006
00007 ClassImp(SpillServerMonFinder)
00008
00009 CVSID("$Id: SpillServerMonFinder.cxx,v 1.5 2007/08/14 16:48:00 blake Exp $");
00010
00011 static SpillServerMon kDefaultSpillFD_BeginningOfTime(0,0,-1,0,0,0,0,-999,0,0,0);
00012
00013 static SpillServerMon kDefaultSpillFD_EndOfTime(1556150400,0,-1,1556150400,0,1556150400,0,-999,0,0,0);
00014
00015 SpillServerMonFinder* SpillServerMonFinder::fMyInstance = 0;
00016
00017 SpillServerMonFinder& SpillServerMonFinder::Instance()
00018 {
00019 MSG("SpillServerMon", Msg::kDebug) << " *** SpillServerMonFinder::Instance() *** " << endl;
00020
00021
00022 static Cleaner cleaner;
00023
00024
00025 if(!fMyInstance){
00026 MSG("SpillServerMon", Msg::kDebug) << " Creating new instance of SpillServerMonFinder " << endl;
00027 cleaner.UseMe();
00028 fMyInstance = new SpillServerMonFinder();
00029 }
00030
00031
00032 if(!fMyInstance){
00033 MSG("SpillServerMon", Msg::kFatal) << " No SpillServerMonFinder Instance - aagghhh, I'm going to die!!!." << endl;
00034 assert(fMyInstance);
00035 }
00036
00037
00038 if(fMyInstance){
00039
00040 }
00041
00042 return *fMyInstance;
00043 }
00044
00045 SpillServerMonFinder::SpillServerMonFinder() :
00046 fPrevTable(0),
00047 fNextTable(0),
00048 fLastQueryPrev(kDefaultSpillFD_EndOfTime),
00049 fLastQueryNext(kDefaultSpillFD_BeginningOfTime),
00050 fTask(0)
00051 {
00052 MSG("SpillServerMon", Msg::kVerbose) << " *** SpillServerMonFinder::SpillServerMonFinder() *** " << endl;
00053 }
00054
00055 SpillServerMonFinder::~SpillServerMonFinder()
00056 {
00057 MSG("SpillServerMon", Msg::kVerbose) << " *** SpillServerMonFinder::~SpillServerMonFinder() *** " << endl;
00058
00059 if(fPrevTable) delete fPrevTable;
00060 if(fNextTable) delete fNextTable;
00061 }
00062
00063 Bool_t SpillServerMonFinder::DataIsAvailable(const VldContext& context)
00064 {
00065 MSG("SpillServerMon", Msg::kDebug) << " *** SpillServerMonFinder::DataIsAvailable(...) *** " << endl;
00066
00067
00068
00069 fCurrentTable.NewQuery(context,fTask);
00070
00071 const DbiValidityRec* vldRec = fCurrentTable.GetValidityRec();
00072 const VldRange& vldRange = vldRec->GetVldRange();
00073 VldTimeStamp start = vldRange.GetTimeStart();
00074 VldTimeStamp end = vldRange.GetTimeEnd();
00075
00076 MSG("SpillServerMon", Msg::kVerbose) << " timestamp = " << context.GetTimeStamp().GetSec() << endl;
00077 MSG("SpillServerMon", Msg::kVerbose) << " range = " << start.GetSec() << "->" << end.GetSec() << endl;
00078
00079 if ( vldRec->IsGap () ){
00080 MSG("SpillServerMon", Msg::kDebug) << " NO data is available " << endl;
00081 return false;
00082 }
00083 else{
00084 MSG("SpillServerMon", Msg::kDebug) << " data is available " << endl;
00085 return true;
00086 }
00087 }
00088
00089 const SpillServerMon& SpillServerMonFinder::GetPreviousSpill(const VldContext& context)
00090 {
00091 MSG("SpillServerMon", Msg::kDebug) << " *** SpillServerMonFinder::GetPreviousSpill(...) *** " << endl;
00092
00093 const SpillServerMon* prev;
00094 const SpillServerMon* next;
00095 this->FindClosestEntries(context,prev,next);
00096 if(prev) return *prev;
00097
00098 MSG("SpillServerMon", Msg::kWarning) << " can't find the previous spill, defaulting to the beginning of time! " << endl;
00099 return kDefaultSpillFD_BeginningOfTime;
00100 }
00101
00102 const SpillServerMon& SpillServerMonFinder::GetNextSpill(const VldContext& context)
00103 {
00104 MSG("SpillServerMon", Msg::kDebug) << " *** SpillServerMonFinder::GetNextSpill(...) *** " << endl;
00105
00106 const SpillServerMon* prev;
00107 const SpillServerMon* next;
00108 this->FindClosestEntries(context,prev,next);
00109 if(next) return *next;
00110
00111 MSG("SpillServerMon", Msg::kWarning) << " can't find the next spill, defaulting to the end of time! " << endl;
00112 return kDefaultSpillFD_EndOfTime;
00113 }
00114
00115 const SpillServerMon& SpillServerMonFinder::GetNearestSpill(const VldContext& context)
00116 {
00117 MSG("SpillServerMon", Msg::kDebug) << " *** SpillServerMonFinder::GetNearestSpill(...) *** " << endl;
00118
00119 const SpillServerMon* prev;
00120 const SpillServerMon* next;
00121 this->FindClosestEntries(context,prev,next);
00122
00123 if(prev && !next){
00124 MSG("SpillServerMon", Msg::kVerbose) << " no next entry, return previous entry " << endl;
00125 return *prev;
00126 }
00127
00128 if(!prev && next){
00129 MSG("SpillServerMon", Msg::kVerbose) << " no previous entry, return next entry " << endl;
00130 return *next;
00131 }
00132
00133 double dtNeg=-999.9;
00134 if(prev) dtNeg = this->GetTimeDifference( prev->GetSpillTime(),
00135 context.GetTimeStamp() );
00136
00137 double dtPos=-999.9;
00138 if(next) dtPos = this->GetTimeDifference( context.GetTimeStamp(),
00139 next->GetSpillTime() );
00140
00141 if( dtNeg>=0 && dtPos>=0 ){
00142 MSG("SpillServerMon", Msg::kVerbose) << " dtNeg=" << dtNeg << " dtPos=" << dtPos << endl;
00143 if( dtPos<=dtNeg ) return *next; else return *prev;
00144 }
00145
00146 MSG("SpillServerMon", Msg::kWarning) << " can't find the nearest spill, moving back to the beginning of time! " << endl;
00147 return kDefaultSpillFD_BeginningOfTime;
00148 }
00149
00150 Int_t SpillServerMonFinder::GetSpillTimeError(const VldContext& context, Bool_t usewindow, Double_t window)
00151 {
00152 MSG("SpillServerMon", Msg::kDebug) << " *** SpillServerMonFinder::GetSpillTimeError(...) *** " << endl;
00153
00154 if( usewindow ){
00155
00156
00157 Int_t gpserror = -999;
00158 Double_t gpswindow = window;
00159 if( gpswindow<5.0 ) gpswindow=5.0;
00160
00161 const SpillServerMon& prev = this->GetPreviousSpill(context);
00162 MSG("SpillServerMon", Msg::kVerbose) << " prev: time=" << prev.GetTimeStamp().GetSec() << ", delta=" << this->GetTimeDifference(context.GetTimeStamp(),prev.GetTimeStamp()) << ", error=" << prev.GetSpillTimeError() << endl;
00163 if( fabs(this->GetTimeDifference(context.GetTimeStamp(),prev.GetTimeStamp()))<gpswindow ){
00164 if( prev.GetSpillTimeError()>gpserror ) gpserror = prev.GetSpillTimeError();
00165 }
00166
00167 const SpillServerMon& next = this->GetNextSpill(context);
00168 MSG("SpillServerMon", Msg::kVerbose) << " next: time=" << next.GetTimeStamp().GetSec() << ", delta=" << this->GetTimeDifference(context.GetTimeStamp(),next.GetTimeStamp()) << ", error=" << next.GetSpillTimeError() << endl;
00169 if( fabs(this->GetTimeDifference(context.GetTimeStamp(),next.GetTimeStamp()))<gpswindow ){
00170 if( next.GetSpillTimeError()>gpserror ) gpserror = next.GetSpillTimeError();
00171 }
00172
00173 return gpserror;
00174 }
00175
00176 else{
00177
00178 const SpillServerMon& near = this->GetNearestSpill(context);
00179 return near.GetSpillTimeError();
00180 }
00181
00182 return -999;
00183 }
00184
00185 void SpillServerMonFinder::FindClosestEntries(const VldContext& context,const SpillServerMon* &prevEntry,const SpillServerMon* &nextEntry)
00186 {
00187 MSG("SpillServerMon", Msg::kDebug) << " *** SpillServerMonFinder::FindClosestEntries(...) *** " << endl;
00188
00189 prevEntry = 0;
00190 nextEntry = 0;
00191
00192 VldTimeStamp timestamp = context.GetTimeStamp();
00193
00194
00195 if( timestamp >= fLastQueryPrev.GetSpillTime()
00196 && timestamp <= fLastQueryNext.GetSpillTime() ){
00197 MSG("SpillServerMon", Msg::kDebug) << " Returning same results as before... " << endl;
00198 prevEntry = &fLastQueryPrev;
00199 nextEntry = &fLastQueryNext;
00200 return;
00201 }
00202
00203
00204 MSG("SpillServerMon", Msg::kDebug) << " Searching the database... " << endl;
00205 fCurrentTable.NewQuery(context,fTask);
00206 this->FindClosestEntries(fCurrentTable,timestamp,prevEntry,nextEntry);
00207
00208
00209 if( prevEntry==0 ){
00210 MSG("SpillServerMon", Msg::kDebug) << " Need to find a previous entry... " << endl;
00211 const DbiValidityRec* vldRec = fCurrentTable.GetValidityRec();
00212 const VldRange& vldRange = vldRec->GetVldRange();
00213 VldTimeStamp newstarttime(vldRange.GetTimeStart());
00214 VldTimeStamp starttime(1556150400,0);
00215
00216 while( prevEntry==0 && newstarttime<starttime){
00217 MSG("SpillServerMon",Msg::kVerbose) << " No previous entry yet..." << endl;
00218 MSG("SpillServerMon",Msg::kVerbose) << " ... try start time: " << newstarttime.AsString("s") << endl;
00219
00220 starttime=newstarttime;
00221 const char* sqltxt = Form("(TIMEEND<='%s') and (TASK=%d) and (DETECTORMASK & %d) and (SIMMASK & %d) order by TIMEEND desc limit 1",
00222 starttime.AsString("s"),
00223 fTask,
00224 context.GetDetector(),
00225 context.GetSimFlag() );
00226
00227
00228 DbiSqlContext prevcontext(sqltxt);
00229 if(fPrevTable) {
00230 fPrevTable->NewQuery(prevcontext,Dbi::kAnyTask);
00231 } else {
00232 fPrevTable = new DbiResultPtr<SpillServerMon>("SPILLSERVERMON",prevcontext);
00233 }
00234
00235 const SpillServerMon* temp;
00236 this->FindClosestEntries(*fPrevTable,timestamp,prevEntry,temp);
00237
00238 if( prevEntry ){
00239 MSG("SpillServerMon",Msg::kVerbose) << " Found a previous entry" << endl;
00240 if( temp ) MSG("SpillServerMon",Msg::kWarning) << " potential conflict... also found a next entry! " << endl;
00241 }
00242 else{
00243 newstarttime = fPrevTable->GetValidityRec()->GetVldRange().GetTimeStart();
00244 }
00245 }
00246
00247 if( prevEntry==0 ){
00248 MSG("SpillServerMon", Msg::kWarning) << " can't find the previous entry, defaulting to the beginning of time! " << endl;
00249 prevEntry = &kDefaultSpillFD_BeginningOfTime;
00250 }
00251 }
00252
00253
00254 if( nextEntry==0 ){
00255 MSG("SpillServerMon",Msg::kVerbose) << " Need to find a next entry..." << endl;
00256
00257 const DbiValidityRec* vldRec = fCurrentTable.GetValidityRec();
00258 const VldRange& vldRange = vldRec->GetVldRange();
00259 VldTimeStamp newendtime(vldRange.GetTimeEnd());
00260 VldTimeStamp endtime(0,0);
00261
00262 while( nextEntry==0 && newendtime>endtime ){
00263 MSG("SpillServerMon",Msg::kVerbose) << " No next entry yet... " << endl;
00264 MSG("SpillServerMon",Msg::kVerbose) << " ...Try end time:" << newendtime.AsString("s") << endl;
00265
00266 endtime = newendtime;
00267 const char* sqltxt = Form("(TIMESTART>='%s') and (TASK=%d) and (DETECTORMASK & %d) and (SIMMASK & %d) order by TIMESTART asc limit 1",
00268 endtime.AsString("s"),
00269 fTask,
00270 context.GetDetector(),
00271 context.GetSimFlag() );
00272
00273 DbiSqlContext nextcontext(sqltxt);
00274 if(fNextTable) {
00275 fNextTable->NewQuery(nextcontext,Dbi::kAnyTask);
00276 } else {
00277 fNextTable = new DbiResultPtr<SpillServerMon>("SPILLSERVERMON",nextcontext);
00278 }
00279
00280 const SpillServerMon* temp;
00281 this->FindClosestEntries(*fNextTable,timestamp,temp,nextEntry);
00282
00283 if( nextEntry ){
00284 MSG("SpillServerMon",Msg::kVerbose) << " Found a next entry" << endl;
00285 if( temp ) MSG("SpillServerMon",Msg::kWarning) << " potential conflict... also found a previous entry! " << endl;
00286 }
00287 else{
00288 newendtime = fNextTable->GetValidityRec()->GetVldRange().GetTimeEnd();
00289 }
00290 }
00291
00292 if( nextEntry==0 ){
00293 MSG("SpillServerMon", Msg::kWarning) << " can't find the next entry, defaulting to the end of time! " << endl;
00294 nextEntry = &kDefaultSpillFD_EndOfTime;
00295 }
00296 }
00297
00298
00299 MSG("SpillServerMon",Msg::kVerbose) << " storing the results... " << endl;
00300 fLastQueryPrev = *prevEntry;
00301 fLastQueryNext = *nextEntry;
00302
00303 return;
00304 }
00305
00306 void SpillServerMonFinder::FindClosestEntries(DbiResultPtr<SpillServerMon> &table,const VldTimeStamp& timestamp,const SpillServerMon* &prevEntry,const SpillServerMon* &nextEntry)
00307 {
00308 MSG("SpillServerMon", Msg::kDebug) << " *** SpillServerMonFinder::FindClosestEntriesInDb(...) *** " << endl;
00309
00310
00311
00312
00313 prevEntry = 0;
00314 nextEntry = 0;
00315
00316 const DbiValidityRec* vldRec = table.GetValidityRec();
00317
00318 const VldRange& vldRange = vldRec->GetVldRange();
00319 VldTimeStamp start = vldRange.GetTimeStart();
00320 VldTimeStamp end = vldRange.GetTimeEnd();
00321
00322 if( table.GetNumRows() <=0 ){
00323 MSG("SpillServerMon",Msg::kWarning) << " This table has no rows " << endl;
00324 }
00325
00326 double dt;
00327 double dtNeg=start.GetSec()-timestamp.GetSec()-1.0;
00328 double dtPos=end.GetSec()-timestamp.GetSec()+1.0;
00329
00330 for(unsigned int i=0; i<table.GetNumRows(); i++){
00331 const SpillServerMon* entry = table.GetRow(i);
00332
00333 dt = this->GetTimeDifference( timestamp, entry->GetSpillTime() );
00334
00335 if( dt<=0.0 && dt>dtNeg ){
00336 dtNeg=dt;
00337 prevEntry=entry;
00338 }
00339
00340 if( dt>=0.0 && dt<dtPos ){
00341 dtPos=dt;
00342 nextEntry=entry;
00343 }
00344 }
00345
00346 if( prevEntry ){
00347 MSG("SpillServerMon",Msg::kDebug) << " Db Search: Found previous entry at " << dtNeg << " seconds" << endl;
00348 }
00349 else{
00350 MSG("SpillServerMon",Msg::kVerbose) << " Db Search: No previous entry " << endl;
00351 }
00352
00353 if( nextEntry ){
00354 MSG("SpillServerMon",Msg::kDebug) << " Db Search: Found next entry at +" << dtPos << " seconds" << endl;
00355 }
00356 else{
00357 MSG("SpillServerMon",Msg::kVerbose) << " Db Search: No next entry " << endl;
00358 }
00359
00360 return;
00361 }
00362
00363 Double_t SpillServerMonFinder::GetTimeDifference(VldTimeStamp first, VldTimeStamp second)
00364 {
00365 return ( second.GetSec()-first.GetSec() )
00366 + 1.0e-9*( second.GetNanoSec()-first.GetNanoSec() );
00367 }