#include #include #include #include namespace RAT { DBLink::DBLink(DB *_db, std::string _tblname, std::string _index, int _pass) { db = _db; tblname = _tblname; index = _index; pass = _pass; currentRun = db->GetRunID(); loadFromDefaultPlane = !db->GetTblNoDefaultPlaneStatus(tblname,index); #ifdef RATDB_DEBUG debug << "DBLink::DBLink : Table default plane loading status for table " << tblname <<": " << loadFromDefaultPlane << newline; #endif // -- preload from Run plane, if available // Preload the table from the remote server into the cache, in case it exists there PreLoadRunTable(); } DBLink::~DBLink() { // We don't own the db or table pointers, but we do need to inform // the db object of our destruction, if it still exists if (db) db->RemoveLink(this); } int DBLink::GetI(const std::string &name) { return Pick(name); } double DBLink::GetD(const std::string &name) { return Pick(name); } std::string DBLink::GetS(const std::string &name) { return Pick(name); } bool DBLink::GetZ(const std::string &name) { return Pick(name); } std::vector DBLink::GetIArray(const std::string &name) { return Pick< std::vector >(name); } std::vector DBLink::GetFArrayFromD(const std::string &name) { std::vector returnVal; std::vector tempVal; tempVal = DBLink::GetDArray(name); returnVal = DBLink::DArrayToFArray(tempVal); return returnVal; } std::vector DBLink::DArrayToFArray(const std::vector &input) { int nval = input.size(); std::vector returnVal; returnVal.resize(nval); for(int i=0;i DBLink::GetDArray(const std::string &name) { return Pick< std::vector >(name); } std::vector DBLink::GetSArray(const std::string &name) { return Pick< std::vector >(name); } std::vector DBLink::GetZArray(const std::string &name) { return Pick< std::vector >(name); } json::Value DBLink::GetJSON(const std::string &name) { return Pick< json::Value >(name); } void DBLink::PreLoadRunTable() { // Preloading is only necessary if we are loading from the remote database // But avoids remote access after BeginOfRun (void) db->GetRunTable(tblname, index, currentRun); } // Pushes type checking and casting onto DBTable::Get since that checks types // and more gracefully handles special cases. template T DBLink::Pick(std::string fieldname) const { DBTable *tbl = NULL; T value; #ifdef RATDB_VERBOSE info << "DBLink::Pick : Grabbing field " << fieldname << newline; #endif // First try user plane tbl = db->GetUserTable(tblname, index); #ifdef RATDB_VERBOSE if (tbl) info << "DBLink::Pick : Fetched the user table " << tblname << "[" << index<< "] : " << (void*)tbl << newline; #endif try { if (tbl) value = tbl->DBTable::Get(fieldname); } catch (DBNotFoundError &e_user) { tbl = NULL; } // Then try the run plane if (!tbl) { tbl = db->GetRunTable(tblname, index, currentRun, pass); #ifdef RATDB_VERBOSE if (tbl) info << "DBLink::Pick : Fetched the run table " << tblname << "[" << index<< "][" << currentRun << "] : " << (void*)tbl << newline; #endif try { if (tbl) value = tbl->DBTable::Get(fieldname); } catch (DBNotFoundError &e_user) { // A run plane table was found but it was missing the field or wrong type // in this case DO NOT fall back to default plane since run plane tables // should be complete. if (tbl) throw DBNotFoundError(tblname, index, fieldname); } } // Finally try the default plane if (!tbl && loadFromDefaultPlane) { tbl = db->GetDefaultTable(tblname, index); #ifdef RATDB_VERBOSE if (tbl) info << "DBLink::Pick : Fetched the default table " << tblname << "[" << index<< "] : " << (void*)tbl << newline; #endif try { if (tbl) value = tbl->DBTable::Get(fieldname); } catch (DBNotFoundError &e_user) { tbl = NULL; } } #ifdef RATDB_VERBOSE if (!tbl) warn << "DBLink::Pick : Failed to find the member " << fieldname << " in table " << tblname << "[" << index<< "] " << newline; #endif // Did we eventually find a good value? Otherwise tbl is NULL if (!tbl) throw DBNotFoundError(tblname, index, fieldname); // Trace DB accesses Log::TraceDBAccess(tblname, index, fieldname, value); return value; } }