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
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
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
00119
00120 std::stringstream sql;
00121 int count = 1;
00122 if (getLMFRunIOVID() > 0) {
00123
00124
00125 sql << "SELECT * FROM " << getTableName() << " WHERE "
00126 << getIovIdFieldName() << " = " << getLMFRunIOVID();
00127 } else {
00128
00129
00130
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
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);
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
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
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
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
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
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
00378 for (int i = 0; i < nData; i++) {
00379 intSize[i] = sizeof(int);
00380 floatSize[i] = sizeof(int);
00381 }
00382
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
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
00402 oracle::occi::Type type = oracle::occi::OCCIFLOAT;
00403 for (int i = 0; i < nParameters; i++) {
00404 b = data2write.begin();
00405
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
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
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
00510 bool ret = true;
00511 m_Error = "";
00512
00513 if (m_className == "LMFUnique") {
00514 m_Error = "class name not set ";
00515 ret = false;
00516 }
00517
00518 if (getTableName() == "") {
00519 m_Error += "table name not set ";
00520 ret = false;
00521 }
00522
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
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
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
00567
00568 std::map<int, std::vector<float> > LMFDat::getData() {
00569 return m_data;
00570 }
00571
00572
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
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 }