CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch13/src/OnlineDB/EcalCondDB/src/LMFDat.cc

Go to the documentation of this file.
00001 #include "OnlineDB/EcalCondDB/interface/LMFDat.h"
00002 
00003 #include <sstream>
00004 #include <math.h>
00005 
00006 using std::cout;
00007 using std::endl;
00008 
00009 LMFDat::LMFDat() : LMFUnique() { 
00010   m_tableName = ""; 
00011   m_max = -1; 
00012 }
00013 
00014 LMFDat::LMFDat(EcalDBConnection *c) : LMFUnique(c) {
00015   m_tableName = "";
00016   m_max = -1;
00017 }
00018 
00019 LMFDat::LMFDat(oracle::occi::Environment* env,
00020                oracle::occi::Connection* conn) : LMFUnique(env, conn) {
00021   m_tableName = "";
00022   m_max = -1;
00023 }
00024 
00025 std::string LMFDat::foreignKeyName() const {
00026   return "lmfRunIOV";
00027 }
00028 
00029 int LMFDat::getLMFRunIOVID() {
00030   int id = getInt(foreignKeyName());
00031   if (id == 0) {
00032     // try to get it from the list of foreign keys
00033     std::map<std::string, LMFUnique*>::iterator i = 
00034       m_foreignKeys.find(foreignKeyName());
00035     if (i != m_foreignKeys.end()) {
00036       LMFRunIOV *iov = (LMFRunIOV*)(i->second);
00037       if (iov != NULL) {
00038         id = iov->fetchID();
00039         setInt(foreignKeyName(), id);
00040       }
00041     }
00042   }
00043   return id;
00044 }
00045 
00046 LMFDat& LMFDat::setMaxDataToDump(int n) {
00047   m_max = n;
00048   return *this;
00049 }
00050 
00051 std::map<unsigned int, std::string> LMFDat::getReverseMap() const {
00052   std::map<unsigned int, std::string> m;
00053   std::map<std::string, unsigned int>::const_iterator i = m_keys.begin();
00054   std::map<std::string, unsigned int>::const_iterator e = m_keys.end();
00055   while (i != e) {
00056     m[i->second] = i->first;
00057     i++;
00058   }
00059   return m;
00060 }
00061 
00062 void LMFDat::dump() const {
00063   dump(0, m_max);
00064 }
00065 
00066 void LMFDat::dump(int n) const {
00067   dump(n, m_max);
00068 }
00069 
00070 void LMFDat::dump(int n, int max) const {
00071   LMFUnique::dump(n);
00072   int s = m_data.size();
00073   cout << "Stored data: " << s << endl;
00074   if (max >= 0) {
00075     std::map<int, std::vector<float> >::const_iterator p = m_data.begin();
00076     std::map<int, std::vector<float> >::const_iterator end = m_data.end();
00077     int c = 0;
00078     std::map<unsigned int, std::string> rm = getReverseMap();
00079     while ((p != end) && (c < max)) {
00080       int id = p->first;
00081       std::vector<float> x = p->second;
00082       cout << c << " -------------------------------------------" << endl;
00083       cout << "   ID: " << id << endl;
00084       for (unsigned int j = 0; j < x.size(); j++) {
00085         if (j % 4 == 0) {
00086           cout << endl << "   ";
00087         }
00088         cout << rm[j] << ":" << x[j] << "\t";
00089       }
00090       cout << endl;
00091       p++;
00092       c++;
00093     }
00094   }
00095 }
00096 
00097 std::string LMFDat::buildInsertSql() {
00098   // create the insert statement
00099   std::stringstream sql;
00100   sql << "INSERT INTO " + getTableName() + " VALUES (";
00101   unsigned int nParameters = m_keys.size() + 2; 
00102   for (unsigned int i = 0; i < nParameters - 1; i++) {
00103     sql << ":" << i + 1 << ", ";
00104   }
00105   sql << ":" << nParameters << ")";
00106   std::string sqls = sql.str();
00107   if (m_debug) {
00108     cout << m_className << "::writeDB: " << sqls << endl;
00109   }
00110   return sqls;
00111 }
00112 
00113 std::string LMFDat::getIovIdFieldName() const {
00114   return "LMF_IOV_ID";
00115 }
00116 
00117 std::string LMFDat::buildSelectSql(int logic_id, int direction) {
00118   // create the insert statement
00119   // if logic_id = 0 select all channels for a given iov_id
00120   std::stringstream sql;
00121   int count = 1;
00122   if (getLMFRunIOVID() > 0) {
00123     // in this case we are looking for all data collected during the same
00124     // IOV. There can be many logic_ids per IOV.
00125     sql << "SELECT * FROM " << getTableName() << " WHERE "
00126         << getIovIdFieldName() << " = " << getLMFRunIOVID();
00127   } else {
00128     // in this case we are looking for a specific logic_id whose
00129     // data have been collected at a given time. There is only
00130     // one record in this case.
00131     std::string op = ">";
00132     std::string order = "ASC";
00133     if (direction < 0) {
00134       op = "<";
00135       order = "DESC";
00136     }
00137     sql << "SELECT * FROM (SELECT " << getTableName() << ".* FROM " 
00138         << getTableName() 
00139         << " JOIN LMF_RUN_IOV ON " 
00140         << "LMF_RUN_IOV.LMF_IOV_ID = " 
00141         << getTableName() << "." << getIovIdFieldName() << " "
00142         << "WHERE SUBRUN_START " << op << "= TO_DATE(:" << count;
00143     count++;
00144     sql << ", 'YYYY-MM-DD HH24:MI:SS') ORDER BY SUBRUN_START " 
00145         << order << ") WHERE ROWNUM <= 1";
00146   }
00147   if (logic_id > 0) {
00148     sql << " AND LOGIC_ID = :" << count;
00149   }
00150   std::string sqls = sql.str();
00151   if (m_debug) {
00152     cout << m_className << "::buildSelectSqlDB: " << sqls << endl;
00153   }
00154   return sqls;
00155 }
00156 
00157 void LMFDat::getPrevious(LMFDat *dat)
00158   throw(std::runtime_error)
00159 {
00160   getNeighbour(dat, -1);
00161 }
00162 
00163 void LMFDat::getNext(LMFDat *dat)
00164   throw(std::runtime_error)
00165 {
00166   getNeighbour(dat, +1);
00167 }
00168 
00169 void LMFDat::getNeighbour(LMFDat *dat, int which)
00170   throw(std::runtime_error)
00171 {
00172   // there should be just one record in this case
00173   if (m_data.size() == 1) {
00174     dat->setConnection(this->getEnv(), this->getConn());
00175     int logic_id = m_data.begin()->first;
00176     Tm lastMeasuredOn = getSubrunStart();
00177     lastMeasuredOn += which;
00178     dat->fetch(logic_id, &lastMeasuredOn, which);
00179     dat->setMaxDataToDump(m_max);
00180   } else {
00181     dump();
00182     throw(std::runtime_error(m_className + "::getPrevious: Too many LOGIC_IDs in "
00183                         "this object"));
00184   }
00185 }
00186 
00187 void LMFDat::fetch(const EcalLogicID &id) 
00188   throw(std::runtime_error)
00189 {
00190   fetch(id.getLogicID());
00191 }
00192 
00193 void LMFDat::fetch(const EcalLogicID &id, const Tm &tm) 
00194   throw(std::runtime_error)
00195 {
00196   fetch(id.getLogicID(), &tm, 1);
00197 }
00198 
00199 void LMFDat::fetch(const EcalLogicID &id, const Tm &tm, int direction) 
00200   throw(std::runtime_error)
00201 {
00202   setInt(foreignKeyName(), 0); /* set the LMF_IOV_ID to undefined */
00203   fetch(id.getLogicID(), &tm, direction);
00204 }
00205 
00206 void LMFDat::fetch() 
00207   throw(std::runtime_error)
00208 {
00209   fetch(0);
00210 }
00211 
00212 void LMFDat::fetch(int logic_id) 
00213   throw(std::runtime_error)
00214 {
00215   fetch(logic_id, NULL, 0);
00216 }
00217 
00218 void LMFDat::fetch(int logic_id, const Tm &tm) 
00219   throw(std::runtime_error)
00220 {
00221   fetch(logic_id, &tm, 1);
00222 }
00223 
00224 void LMFDat::fetch(int logic_id, const Tm *timestamp, int direction) 
00225   throw(std::runtime_error)
00226 {
00227   bool ok = check();
00228   if ((timestamp == NULL) && (getLMFRunIOVID() == 0)) {
00229     throw(std::runtime_error(m_className + "::fetch: Cannot fetch data with "
00230                         "timestamp = 0 and LMFRunIOV = 0"));
00231   }
00232   if (ok && isValid()) {
00233     if (m_debug) {
00234       std::cout << "[LMFDat] This object is valid..." << std::endl;
00235     }
00236     try {
00237       Statement * stmt = m_conn->createStatement();
00238       std::string sql = buildSelectSql(logic_id, direction);
00239       if (m_debug) {
00240         std::cout << "[LMFDat] Executing query " << std::endl;
00241         std::cout << "         " << sql << std::endl << std::flush;
00242       }
00243       if (logic_id == 0) {
00244         // get data for all crystals with a given timestamp
00245         stmt->setPrefetchRowCount(131072);
00246       }
00247       stmt->setSQL(sql);
00248       int count = 1;
00249       if (logic_id > 0) {
00250         if (timestamp != NULL) {
00251           stmt->setString(count, timestamp->str());
00252           count++;
00253         }
00254         stmt->setInt(count, logic_id);
00255       }
00256       ResultSet *rset = stmt->executeQuery();
00257       std::vector<float> x;
00258       int nData = m_keys.size();
00259       x.reserve(nData);
00260       while (rset->next()) {
00261         for (int i = 0; i < nData; i++) {
00262           x.push_back(rset->getFloat(i + 3));
00263         }
00264         int id = rset->getInt(2);
00265         if (timestamp != NULL) {
00266           setInt(foreignKeyName(), rset->getInt(1));
00267         }
00268         this->setData(id, x);
00269         x.clear();
00270       }
00271       stmt->setPrefetchRowCount(0);
00272       m_conn->terminateStatement(stmt);
00273     }
00274     catch (oracle::occi::SQLException &e) {
00275       throw(std::runtime_error(m_className + "::fetch: " + e.getMessage()));
00276     }
00277     m_ID = m_data.size();
00278   }
00279 }
00280 
00281 bool LMFDat::isValid() {
00282   bool ret = true;
00283   if (m_foreignKeys.find(foreignKeyName()) == m_foreignKeys.end()) {
00284     ret = false;
00285     m_Error += " Can't find lmfRunIOV within foreign keys.";
00286     if (m_debug) {
00287       cout << m_className << ": Foreign keys map size: " << m_foreignKeys.size() 
00288            << endl;
00289     }
00290   }
00291   return ret;
00292 }
00293 
00294 std::map<int, std::vector<float> > LMFDat::fetchData() 
00295   throw(std::runtime_error)
00296 {
00297   // see if any of the data is already in the database
00298   std::map<int, std::vector<float> > s = m_data;
00299   std::string sql = "SELECT LOGIC_ID FROM " + getTableName() + " WHERE "
00300     + getIovIdFieldName() + " = :1";
00301   if (m_debug) {
00302     cout << m_className << ":: candidate data items to be written = " 
00303          << s.size() << endl;
00304     cout << m_className << "   Executing " << sql;
00305     cout << " where " << getIovIdFieldName() << " = " 
00306          << getLMFRunIOVID() << endl;
00307   }
00308   try {
00309     Statement* stmt = m_conn->createStatement();
00310     stmt->setSQL(sql);
00311     stmt->setInt(1, getLMFRunIOVID());
00312     stmt->setPrefetchRowCount(131072);
00313     ResultSet* rset = stmt->executeQuery();
00314     std::map<int, std::vector<float> >::iterator i = s.end();
00315     std::map<int, std::vector<float> >::iterator e = s.end();
00316     while (rset->next()) {
00317       if (m_debug) {
00318         cout << m_className << ":: checking " << rset->getInt(1) << endl
00319              << std::flush;
00320       }
00321       i = s.find(rset->getInt(1));
00322       if (i != e) {
00323         s.erase(i);
00324       }
00325     }
00326     stmt->setPrefetchRowCount(0);
00327     m_conn->terminateStatement(stmt);
00328   }
00329   catch (oracle::occi::SQLException &e) {
00330     throw(std::runtime_error(m_className + "::fetchData:  "+e.getMessage()));
00331   }
00332   if (m_debug) {
00333     cout << m_className << ":: data items to write = " 
00334          << s.size() << endl;
00335   }
00336   return s;
00337 }
00338 
00339 int LMFDat::writeDB() 
00340   throw(std::runtime_error)
00341 {
00342   // first of all check if data already present
00343   if (m_debug) {
00344     cout << m_className << ": Writing foreign keys" << endl;
00345   }
00346   LMFUnique::writeForeignKeys();
00347   if (m_debug) {
00348     cout << m_className << ": Foreign keys written" << endl;
00349   }
00350   // write data on the database
00351   int ret = 0;
00352   std::map<int, std::vector<float> > data2write = fetchData();
00353   if (data2write.size() > 0) {
00354     this->checkConnection();
00355     bool ok = check();
00356     // write
00357     if (ok && isValid()) {
00358       std::list<dvoid *> bufPointers;
00359       int nParameters = m_keys.size(); 
00360       int nData = data2write.size();
00361       if (m_debug) {
00362         cout << m_className << ": # data items = " << nData << endl;
00363         cout << m_className << ": # parameters = " << nParameters << endl;
00364       }
00365       int * iovid_vec = new int[nData];
00366       int * logicid_vec = new int[nData];
00367       int *intArray = new int[nData];
00368       float *floatArray = new float[nData];
00369       ub2 * intSize = new ub2[nData];
00370       ub2 * floatSize = new ub2[nData];
00371       size_t intTotalSize = sizeof(int)*nData;
00372       size_t floatTotalSize = sizeof(float)*nData;
00373       try {
00374         Statement * stmt = m_conn->createStatement();
00375         std::string sql = buildInsertSql();
00376         stmt->setSQL(sql);
00377         // build the array of the size of each column
00378         for (int i = 0; i < nData; i++) {
00379           intSize[i] = sizeof(int);
00380           floatSize[i] = sizeof(int);
00381         }
00382         // build the data array for first column: the same run iov id
00383         LMFRunIOV *runiov = (LMFRunIOV*)m_foreignKeys[foreignKeyName()];
00384         int iov_id = runiov->getID();
00385         std::map<int, std::vector<float> >::const_iterator b = data2write.begin();
00386         std::map<int, std::vector<float> >::const_iterator e = data2write.end();
00387         for (int i = 0; i < nData; i++) {
00388           iovid_vec[i] = iov_id;
00389         }
00390         stmt->setDataBuffer(1, (dvoid*)iovid_vec, oracle::occi::OCCIINT,
00391                             sizeof(iovid_vec[0]), intSize);
00392         // build the data array for second column: the logic ids
00393         int c = 0;
00394         while (b != e) {
00395           int id = b->first;
00396           logicid_vec[c++] = id;
00397           b++;
00398         }
00399         stmt->setDataBuffer(2, (dvoid*)logicid_vec, oracle::occi::OCCIINT,
00400                             sizeof(logicid_vec[0]), intSize);
00401         // for each column build the data array
00402         oracle::occi::Type type = oracle::occi::OCCIFLOAT;
00403         for (int i = 0; i < nParameters; i++) {
00404           b = data2write.begin();
00405           // loop on all logic ids
00406           c = 0;
00407           while (b != e) {
00408             std::vector<float> x = b->second;
00409             if (m_type[i] == "INT") {
00410               intArray[c] = (int)rint(x[i]);
00411             } else if ((m_type[i] == "FLOAT") || (m_type[i] == "NUMBER")) {
00412               floatArray[c] = x[i];
00413             } else {
00414               throw(std::runtime_error("ERROR: LMFDat::writeDB: unsupported type"));
00415             }
00416             c++;
00417             b++;
00418           }
00419           // copy data into a "permanent" buffer
00420           dvoid * buffer;
00421           type = oracle::occi::OCCIINT;
00422           ub2 *sizeArray = intSize;
00423           int size = sizeof(intArray[0]);
00424           if ((m_type[i] == "FLOAT") || (m_type[i] == "NUMBER")) {
00425             buffer = (dvoid *)malloc(sizeof(float)*nData);
00426             memcpy(buffer, floatArray, floatTotalSize);
00427             type = oracle::occi::OCCIFLOAT;
00428             sizeArray = floatSize;
00429             size = sizeof(floatArray[0]);
00430           } else {
00431             buffer = (dvoid *)malloc(sizeof(int)*nData);
00432             memcpy(buffer, intArray, intTotalSize);
00433           }
00434           bufPointers.push_back(buffer);
00435           if (m_debug) {
00436             for (int k = 0; ((k < nData) && (k < m_max)); k++) {
00437               cout << m_className << ": === Index=== " << k << endl;
00438               cout << m_className << ": RUN_IOV_ID = " << iovid_vec[k] << endl;
00439               cout << m_className << ": LOGIC_ID = " << logicid_vec[k] << endl;
00440               cout << m_className << ": FIELD " << i << ": " 
00441                    << ((float *)(buffer))[k] << endl;
00442             }
00443           }
00444           stmt->setDataBuffer(i + 3, buffer, type, size, sizeArray);
00445         }
00446         stmt->executeArrayUpdate(nData);
00447         delete [] intArray;
00448         delete [] floatArray;
00449         delete [] intSize;
00450         delete [] floatSize;
00451         delete [] logicid_vec;
00452         delete [] iovid_vec;
00453         std::list<dvoid *>::const_iterator bi = bufPointers.begin();
00454         std::list<dvoid *>::const_iterator be = bufPointers.end();
00455         while (bi != be) {
00456           free(*bi);
00457           bi++;
00458         }
00459         m_conn->commit();
00460         m_conn->terminateStatement(stmt);
00461         ret = nData;
00462       } catch (oracle::occi::SQLException &e) {
00463         debug();
00464         setMaxDataToDump(nData);
00465         dump();
00466         m_conn->rollback();
00467         throw(std::runtime_error(m_className + "::writeDB: " + 
00468                                  e.getMessage()));
00469       }
00470     } else {
00471       cout << m_className << "::writeDB: Cannot write because " << 
00472         m_Error << endl;
00473       dump();
00474     }
00475   }
00476   return ret;
00477 }
00478 
00479 void LMFDat::getKeyTypes() 
00480   throw(std::runtime_error)
00481 {
00482   m_type.reserve(m_keys.size());
00483   for (unsigned int i = 0; i < m_keys.size(); i++) {
00484     m_type.push_back("");
00485   }
00486   // get the description of the table
00487   std::string sql = "";
00488   try {
00489     Statement *stmt = m_conn->createStatement();
00490     sql = "SELECT COLUMN_NAME, DATA_TYPE FROM " 
00491       "USER_TAB_COLS WHERE TABLE_NAME = '" + getTableName() + "' " 
00492       "AND COLUMN_NAME != '" + getIovIdFieldName() +  "' AND COLUMN_NAME != " 
00493       "'LOGIC_ID'";
00494     stmt->setSQL(sql);
00495     ResultSet *rset = stmt->executeQuery();
00496     while (rset->next()) {
00497       std::string name = rset->getString(1);
00498       std::string t = rset->getString(2);
00499       m_type[m_keys[name]] = t;
00500     }
00501     m_conn->terminateStatement(stmt);
00502   } catch (oracle::occi::SQLException &e) {
00503     throw(std::runtime_error(m_className + "::getKeyTypes: " + e.getMessage() +
00504                         " [" + sql + "]"));
00505   }
00506 }
00507 
00508 bool LMFDat::check() {
00509   // check that everything has been correctly setup
00510   bool ret = true;
00511   m_Error = "";
00512   // first of all we need to check that the class name has been set
00513   if (m_className == "LMFUnique") {
00514     m_Error = "class name not set ";
00515     ret = false;
00516   }
00517   //then check that the table name has been set
00518   if (getTableName() == "") {
00519     m_Error += "table name not set ";
00520     ret = false;
00521   }
00522   // fill key types if not yet done
00523   if (m_type.size() != m_keys.size()) {
00524     getKeyTypes();
00525     if (m_type.size() != m_keys.size()) {
00526       m_Error += "key size does not correspond to table definition";
00527       ret = false;
00528     }
00529   }
00530   return ret;
00531 }
00532 
00533 /* unsafe methods */
00534 
00535 std::vector<float> LMFDat::getData(int id) {
00536   std::vector<float> ret;
00537   if (m_data.find(id) != m_data.end()) {
00538     ret = m_data[id];
00539   }
00540   return ret;
00541 }
00542 
00543 std::vector<float> LMFDat::operator[](int id) {
00544   return getData(id);
00545 }
00546 
00547 std::vector<float> LMFDat::getData(const EcalLogicID &id) {
00548   return getData(id.getLogicID());
00549 }
00550 
00551 /* safe methods */
00552 
00553 bool LMFDat::getData(int id, std::vector<float> &ret) {
00554   bool retval = false;
00555   if (m_data.find(id) != m_data.end()) {
00556     ret= m_data[id];
00557     retval = true;
00558   }
00559   return retval;
00560 }
00561 
00562 bool LMFDat::getData(const EcalLogicID &id, std::vector<float> &ret) {
00563   return getData(id.getLogicID(), ret);
00564 }
00565 
00566 /* all data */
00567 
00568 std::map<int, std::vector<float> > LMFDat::getData() {
00569   return m_data;
00570 }
00571 
00572 /* unsafe */
00573 
00574 float LMFDat::getData(int id, unsigned int k) {
00575   return m_data[id][k];
00576 }
00577 
00578 float LMFDat::getData(const EcalLogicID &id, unsigned int k) {
00579   return getData(id.getLogicID(), k);
00580 }
00581 
00582 float LMFDat::getData(const EcalLogicID &id, const std::string &key) {
00583   return getData(id.getLogicID(), m_keys[key]);
00584 }
00585 
00586 float LMFDat::getData(int id, const std::string &key) {
00587   return getData(id, m_keys[key]);
00588 }
00589 
00590 /* safe */
00591 
00592 bool LMFDat::getData(int id, unsigned int k, float &ret) {
00593   bool retval = false;
00594   std::vector<float> v;
00595   retval = getData(id, v);
00596   if ((retval) && (v.size() > k)) {
00597     ret= v[k];
00598     retval = true;
00599   } else {
00600     retval = false;
00601   }
00602   return retval;
00603 }
00604 
00605 bool LMFDat::getData(const EcalLogicID &id, unsigned int k, float &ret) {
00606   return getData(id.getLogicID(), k, ret);
00607 }
00608 
00609 bool LMFDat::getData(int id, const std::string &key, float &ret) {
00610   bool retval = false;
00611   if (m_keys.find(key) != m_keys.end()) {
00612     retval = getData(id, m_keys[key], ret); 
00613   }
00614   return retval;
00615 }
00616 
00617 bool LMFDat::getData(const EcalLogicID &id, const std::string &key, float &ret)
00618 {
00619   return getData(id.getLogicID(), key, ret);
00620 }