00001 #include "MBSpillAccessor.h"
00002
00003 #include <Validity/VldContext.h>
00004
00005 #include <MessageService/MsgService.h>
00006 CVSID("$Id: MBSpillAccessor.cxx,v 1.2 2006/06/29 03:45:03 rhatcher Exp $");
00007
00008 #include <DatabaseInterface/DbiResultPtr.h>
00009 #include <DatabaseInterface/DbiSqlContext.h>
00010
00011 #include <cmath>
00012 using namespace std;
00013
00014 MBSpillAccessor* MBSpillAccessor::fInstance = 0;
00015
00016 MBSpillAccessor& MBSpillAccessor::Get()
00017 {
00018 if (!fInstance) fInstance = new MBSpillAccessor();
00019 return *fInstance;
00020 }
00021
00022
00023 MBSpillAccessor::MBSpillAccessor()
00024 : fPrevPtr(0)
00025 , fCenterPtr(new DbiResultPtr<MBSpill>)
00026 , fNextPtr(0)
00027 , fNeedNext(true)
00028 , fNeedPrev(true)
00029 {
00030 }
00031 MBSpillAccessor::~MBSpillAccessor()
00032 {
00033 if (fPrevPtr) delete fPrevPtr;
00034 if (fCenterPtr) delete fCenterPtr;
00035 if (fNextPtr) delete fNextPtr;
00036 fPrevPtr = fCenterPtr = fNextPtr = 0;
00037 }
00038
00039 const MBSpill* MBSpillAccessor::LoadSpill(VldTimeStamp vts, int which)
00040 {
00041 const MBSpill *before=0, *after=0;
00042 this->SeekClosest(vts,before,after);
00043
00044 if (which < 0) return before;
00045 if (which > 0) return after;
00046
00047 if (!before) return after;
00048 if (!after) return before;
00049
00050 VldTimeStamp vts_before = before->GetTimeStamp();
00051 VldTimeStamp vts_after = after->GetTimeStamp();
00052
00053 MSG("MBU",Msg::kDebug)
00054 << vts_before << " " << vts << " " << vts_after << endl;
00055
00056 if (vts - vts_before < vts_after - vts)
00057 return before;
00058 return after;
00059
00060 }
00061
00062
00063 void MBSpillAccessor::SeekClosest(const VldTimeStamp &vts,
00064 const MBSpill* &before,
00065 const MBSpill* &after)
00066 {
00067 Detector::Detector_t det = Detector::kNear;
00068 SimFlag::SimFlag_t simflag = SimFlag::kData;
00069 VldContext vc(det,simflag,vts);
00070
00071 fCenterPtr->NewQuery(vc,0,true);
00072
00073 if (! fResKey.IsEqualTo(fCenterPtr->GetKey())) {
00074 fNeedPrev = fNeedNext = true;
00075 }
00076
00077 const DbiValidityRec* vr = fCenterPtr->GetValidityRec();
00078
00079 VldTimeStamp beg = vr->GetVldRange().GetTimeStart();
00080 VldTimeStamp end = vr->GetVldRange().GetTimeEnd();
00081
00082 before=after=0;
00083 this->TableSearch(*fCenterPtr,vts,before,after);
00084
00085 if (before && after) return;
00086
00087 MSG("MBU",Msg::kDebug)
00088 << vts << " not in center table, before @ " << (void*)before
00089 << " after @ " << (void*)after
00090 << " seqno = " << vr->GetSeqNo() << endl;
00091
00092 if (!before) {
00093 const char* sqltxt = Form("(TIMEEND<='%s') order by TIMEEND desc limit 1",
00094 beg.AsString("s"));
00095 DbiSqlContext dscx(sqltxt);
00096 if(fPrevPtr && fNeedPrev)
00097 fPrevPtr->NewQuery(dscx,Dbi::kAnyTask);
00098 else
00099 fPrevPtr = new DbiResultPtr<MBSpill>("MBSpill",dscx);
00100 fNeedPrev = false;
00101
00102 const MBSpill* dummy=0;
00103 this->TableSearch(*fPrevPtr,vts,before,dummy);
00104 if(dummy)
00105 MSG("MBU",Msg::kError)
00106 << "Found next time in previous table: "
00107 << dummy->GetTimeStamp() << endl;
00108 }
00109 if (!after) {
00110 const char* sqltxt = Form("(TIMESTART>='%s') order by TIMEEND asc limit 1",
00111 end.AsString("s"));
00112 DbiSqlContext dscx(sqltxt);
00113 if(fNextPtr && fNeedNext)
00114 fNextPtr->NewQuery(dscx,Dbi::kAnyTask);
00115 else
00116 fNextPtr = new DbiResultPtr<MBSpill>("MBSpill",dscx);
00117 fNeedNext = false;
00118
00119 const MBSpill* dummy=0;
00120 this->TableSearch(*fNextPtr,vts,dummy,after);
00121 if(dummy)
00122 MSG("MBU",Msg::kError)
00123 << "Found previous time in next table: "
00124 << dummy->GetTimeStamp() << endl;
00125
00126 }
00127
00128 }
00129
00130 void MBSpillAccessor::TableSearch(DbiResultPtr<MBSpill> &table,
00131 const VldTimeStamp& vts,
00132 const MBSpill* &before,
00133 const MBSpill* &after)
00134 {
00135 before = after = 0;
00136
00137 int nrows = table.GetNumRows();
00138 if (nrows <= 0) return;
00139
00140 double minneg = 1e10;
00141 double minpos = 1e10;
00142 for (int row = 0; row < nrows; ++row) {
00143 const MBSpill* spill = table.GetRow(row);
00144 double dt = spill->GetTimeStamp() - vts;
00145 if (dt <= 0) {
00146 if (-dt < minneg) {
00147 minneg = -dt;
00148 before = spill;
00149 }
00150 }
00151 else {
00152 if (dt < minpos) {
00153 minpos = dt;
00154 after = spill;
00155 }
00156 }
00157 }
00158 }
00159