00001 #include "IOManagerDB.h"
00002 #include "MySqlException.h"
00003 #include "ZlibStringCompressor.h"
00004 #include "Sct/Serializable.h"
00005 #include "Sct/SctNames.h"
00006 #include "Sct/XmlStyleStream.h"
00007 #include "Sct/StdExceptionWrapper.h"
00008 #include "Sct/Archive/IONameArchiveFile.h"
00009
00010 #include "Sct/UniqueID.h"
00011 #include "SctData/ScanResult.h"
00012 #include "SctData/TestResult.h"
00013 #include <sstream>
00014 #include <boost/date_time/posix_time/posix_time.hpp>
00015
00016 using std::string;
00017 using std::ostringstream;
00018 using boost::posix_time::to_simple_string;
00019 using boost::shared_ptr;
00020 using namespace Sct;
00021
00022 namespace SctArchiving {
00023 MysqlException::MysqlException(const string& msg, const string& file, int line){
00024 initialize("MYSQL_EXCEPTION", "ArchivingService::MysqlException", msg, 0, file, line);
00025 }
00026
00027 MysqlException::MysqlException(const string& msg, const string& query, const string& file, int line) {
00028 std::ostringstream full_message;
00029 full_message << msg << "\nwhile executing query:\n" << query;
00030 initialize("MYSQL_EXCEPTION", "ArchivingService::MysqlException", full_message.str(), 0, file, line);
00031 }
00032
00033 MysqlException::MysqlException(){}
00034
00035 MysqlException::~MysqlException() throw(){}
00036
00037 void IOManagerDB::checkForErrors(const string& msg, const string& file, int line){
00038 if(mysql_errno(m_mysql)){
00039 std::ostringstream full_message;
00040 full_message << msg << "\n"
00041 << mysql_error(m_mysql);
00042 std::cerr << "ERROR:" << full_message.str() << "\nat " << file << ":" << line << std::endl;
00043 throw MysqlException(full_message.str(), file, line);
00044 }
00045 }
00046
00047 void IOManagerDB::checkForErrors(const string& msg, const string& query, const string& file, int line){
00048 if(mysql_errno(m_mysql)){
00049 std::ostringstream full_message;
00050 full_message << msg << "\n"
00051 << mysql_error(m_mysql);
00052 std::cerr << "ERROR:" << full_message.str()
00053 << "\n executing: "
00054 << query
00055 << "\nat " << file << ":" << line << std::endl;
00056 throw MysqlException(full_message.str(), query, file, line);
00057 }
00058 }
00059
00060
00061
00062 IOManagerDB::IOManagerDB() : m_locationName("nowhere") {
00063 std::cout <<"Creating IOManagerDB" << std::endl;
00064 m_compressor = shared_ptr<ZlibStringCompressor>(new ZlibStringCompressor());
00065 m_mysql = mysql_init((MYSQL*) 0);
00066 checkForErrors("Problem during initialisation of MYSQL structure.", __FILE__, __LINE__);
00067
00068
00069 std::cout <<"Connecting IOManagerDB" << std::endl;
00070 mysql_real_connect(m_mysql, "localhost", "daquser", "", NULL, 3306, NULL, 0);
00071 checkForErrors("Failed to connect to mysql server", __FILE__, __LINE__);
00072 SctNames::Mrs() << MRS_TEXT("Have connected to mysql server") << "IOMANAGER_DB_CONNECT"
00073 << MRS_INFORMATION << ENDM;
00074
00075
00076 std::string dbname="test_srd";
00077 std::cout <<"Connecting IOManagerDB to database name=`" << dbname << "'" << std::endl;
00078 mysql_select_db(m_mysql, dbname.c_str());
00079 std::string message("Failed to connect to database");
00080 message += dbname;
00081 checkForErrors(message, __FILE__, __LINE__);
00082 SctNames::Mrs() << MRS_TEXT("Have connected to mysql database") << "IOMANAGER_DB_CONNECT"
00083 << MRS_PARAM<const char*>("database_name",dbname.c_str())
00084 << MRS_INFORMATION << ENDM;
00085 }
00086
00087 IOManagerDB::~IOManagerDB(){
00088 #warning "AJB This never seems to get called because the manager is a static beast. **Hopefully** this dosent matter!"
00089 std::string message("Closing connection to mysql server");
00090 std::cout << message << endl;
00091 SctNames::Mrs() << MRS_TEXT(message) << "IOMANAGER_DB_CONNECT"
00092 << MRS_INFORMATION << ENDM;
00093 mysql_close(m_mysql);
00094 }
00095
00096 IOManagerDB* IOManagerDB::s_man=0;
00097
00098 IOManagerDB& IOManagerDB::instance() {
00099 if (!s_man) s_man=new IOManagerDB();
00100 return *s_man;
00101 }
00102
00103 std::string IOManagerDB::status() const {
00104 std::ostringstream oss;
00105 oss << "IOManagerDB";
00106 if (m_compressor.get()){
00107 oss << "String compressor buffer size : "
00108 << m_compressor->getBufferSize() << std::endl;
00109 } else {
00110 oss << "String compressor not initialized" << endl;
00111 }
00112 return oss.str();
00113 }
00114
00115 const SctData::ResultHeader& IOManagerDB::getHeader(const Serializable& ob){
00116 const SctData::ResultHeader* header=0;
00117 if (ob.getClassName().find("TestResult")!=string::npos) {
00118 header = & dynamic_cast<const SctData::TestResult&>(ob).getHeader();
00119 }
00120 if (ob.getClassName().find("ScanResult")!=string::npos) {
00121 header = & dynamic_cast<const SctData::ScanResult&>(ob).getHeader();
00122 }
00123 if (header) {
00124 return *header;
00125 } else {
00126 ostringstream oss;
00127 oss << "Dont know how to find a header for object with class name : "
00128 << ob.getClassName() << " which has UniqueID : "
00129 << (string) ob.getUniqueID();
00130 throw IoException(oss.str(), __FILE__, __LINE__);
00131 }
00132 }
00133
00134 string IOManagerDB::getTable(const Serializable& ob){
00135 return "data";
00136 }
00137
00138 void IOManagerDB::write(const Serializable& ob, const IOParams* par) const {
00139 try{
00140 boost::recursive_mutex::scoped_lock lock (getMutex());
00141 setReadMode(false);
00142
00143 }catch (Sct::Throwable& e){
00144 throw;
00145 }catch(std::exception& e){
00146 StdExceptionWrapper sew(e);
00147 throw IoException(sew, __FILE__, __LINE__);
00148 }
00149 }
00150
00151 boost::shared_ptr<Serializable> IOManagerDB::read(const string& name, const IOParams* par) const {
00152 try{
00153 boost::recursive_mutex::scoped_lock lock (getMutex());
00154 setReadMode(true);
00155 getReadVersionMap().clear();
00156 const string compressed;
00157 #warning "AJB added null string above"
00158 std::istringstream iss(m_compressor->inflate(compressed));
00159 XmlStyleIStream in_ad(iss);
00160 return boost::dynamic_pointer_cast<Serializable>(readImpl(in_ad));
00161 }catch (Sct::Throwable& e) {
00162 throw;
00163 }catch(std::exception& e){
00164 StdExceptionWrapper sew(e);
00165 throw IoException(sew, __FILE__, __LINE__);
00166 }
00167 }
00168
00169 bool IOManagerDB::testExists(const TestData& testdata){
00170 const std::string tableName="tblTests";
00171 std::ostringstream select;
00172 select << "SELECT tblTests.* FROM tblTestTypes "
00173 << "\nINNER JOIN ((tblLocations INNER JOIN tblRuns ON "
00174 << "\ntblLocations.LocationID = tblRuns.LocationID) INNER JOIN tblTests ON "
00175 << "tblRuns.RunID = tblTests.RunID) ON tblTestTypes.TestTypeID = tblTests.TestTypeID"
00176 << "\nWHERE (((tblTestTypes.TestTypeName) = '" << testdata.testName << "' )\n"
00177 << "AND ((tblLocations.LocationName) = '" << getLocationName() << "')"
00178 << "\n AND ((tblRuns.RunNr)=" << testdata.runNumber
00179 << ")\n AND ((tblTests.StartTime)='"
00180 << convertToMysqlDateTimeFormat(testdata.startTime)
00181 << "'))";
00182
00183 mysql_query(m_mysql, select.str().c_str());
00184 checkForErrors("Could not check for test", select.str(), __FILE__, __LINE__);
00185
00186 shared_ptr<MYSQL_RES> result (mysql_store_result(m_mysql));
00187 checkForErrors("Error storing result", select.str(), __FILE__, __LINE__);
00188
00189 unsigned number_of_rows = mysql_num_rows(result.get());
00190 return (number_of_rows);
00191 }
00192
00193
00194 bool IOManagerDB::runExists(unsigned long runNumber){
00195 const std::string tableName="tblRuns";
00196 std::ostringstream select;
00197 select << "SELECT * FROM tblLocations INNER JOIN tblRuns "
00198 <<" ON tblLocations.LocationID = tblRuns.LocationID "
00199 <<" WHERE (((tblLocations.LocationName)='"
00200 << getLocationName()
00201 << "') AND ((tblRuns.RunNr)=" << runNumber << "))";
00202 mysql_query(m_mysql, select.str().c_str());
00203
00204 checkForErrors("Could not check for run", select.str(), __FILE__, __LINE__);
00205
00206 shared_ptr<MYSQL_RES> result (mysql_store_result(m_mysql));
00207 checkForErrors("Error storing result", __FILE__, __LINE__);
00208
00209 unsigned number_of_rows = mysql_num_rows(result.get());
00210 return (number_of_rows);
00211 }
00212
00213 void IOManagerDB::addRun(unsigned long runNumber){
00214 const std::string tableName="tblRuns";
00215 bool trash;
00216 std::ostringstream select;
00217 select << "INSERT INTO " << tableName << "\n("
00218 << "LocationID, RunNr, Trash"
00219 << ")"
00220 << "\nSELECT tblLocations.LocationID" << ", "
00221 << runNumber << " AS RunNr, 0 AS Trash "
00222 << "\nFROM tblLocations"
00223 << "\nWHERE ((tblLocations.LocationName) = '"
00224 << getLocationName()
00225 << "')";
00226 mysql_query(m_mysql, select.str().c_str());
00227 checkForErrors("Cannot execute", select.str(), __FILE__, __LINE__);
00228 if (mysql_affected_rows(m_mysql)!=1){
00229 throw MysqlException("Did NOT add row", select.str(), __FILE__, __LINE__);
00230 }
00231 }
00232
00233 std::string IOManagerDB::convertToMysqlDateTimeFormat(const std::string& original){
00234 std::string copy=original;
00235 unsigned t = copy.find('T');
00236 if (t==string::npos) {
00237 std::ostringstream msg;
00238 msg << "could not parse date/time since I couldn't find a `T' in " << copy;
00239 throw Sct::IoException(msg.str(), __FILE__, __LINE__);
00240 }
00241 return copy.erase(t,1);
00242 }
00243
00244 void IOManagerDB::addTest(const TestData& testdata, bool alsoAddScans){
00245 const std::string tableName="tblTests";
00246 std::ostringstream select;
00247
00248 select << "INSERT INTO " << tableName
00249 << "\n(RunID, TestTypeID, StartTime, EndTime )"
00250 << "\nSELECT tblRuns.RunID, tblTestTypes.TestTypeID, "
00251 << "'" << convertToMysqlDateTimeFormat( testdata.startTime )
00252 << "' AS StartTime, "
00253 << "'" << convertToMysqlDateTimeFormat( testdata.endTime )
00254 << "' AS EndTime ";
00255 select << "\nFROM " << "tblTestTypes" << ", " << "tblLocations"
00256 << " INNER JOIN " << "tblRuns" << " ON "
00257 << "tblLocations.LocationID = tblRuns.LocationID";
00258 select << "\nWHERE (("
00259 << "(tblTestTypes.TestTypeName) = '" << testdata.testName << "')"
00260 << "\nAND ((tblRuns.RunNr) = " << testdata.runNumber << ")"
00261 << "\nAND ((tblLocations.LocationName) = '" << getLocationName() << "'))";
00262
00263 mysql_query(m_mysql, select.str().c_str());
00264 checkForErrors("Cannot execute", select.str(), __FILE__, __LINE__);
00265 if (mysql_affected_rows(m_mysql)!=1){
00266 throw MysqlException("Did NOT add row", select.str(), __FILE__, __LINE__);
00267 }
00268 if (alsoAddScans){
00269 for (unsigned iscan=testdata.startScanNumber;
00270 iscan < (testdata.startScanNumber + testdata.nScans);
00271 ++iscan){
00272 addScan(testdata, iscan);
00273 }
00274 }
00275 }
00276
00277 bool IOManagerDB::scanExists(const TestData& testdata, unsigned scanNumber){
00278 #warning "NOT IMPLIMENTED"
00279 return false;
00280 }
00281
00282 void IOManagerDB::addScan(const TestData& testdata, unsigned scanNumber){
00283 const std::string tableName="tblScans";
00284 std::ostringstream select;
00285
00286 select << "INSERT INTO " << tableName
00287 << "\n(TestID, ScanNr)"
00288 << "\nSELECT tblTests.TestID, " << scanNumber
00289 << " AS ScanNr ";
00290 select << "\nFROM " << "tblTestTypes INNER JOIN (" << "tblLocations"
00291 << " INNER JOIN (" << "tblRuns INNER JOIN "
00292 << "tblTests ON tblRuns.RunID = tblTests.RunID)"
00293 << " ON tblLocations.LocationID = tblRuns.LocationID)"
00294 << " ON tblTestTypes.TestTypeID = tblTests.TestTYpeID";
00295 select << "\nWHERE (("
00296 << "(tblTestTypes.TestTypeName) = '" << testdata.testName << "')"
00297 << "\nAND ((tblRuns.RunNr) = " << testdata.runNumber << ")"
00298 << "\nAND ((tblLocations.LocationName) = '" << getLocationName() << "'))"
00299 << "\nAND ((tblTests.StartTime) = '" << convertToMysqlDateTimeFormat(testdata.startTime) << "')";
00300
00301 mysql_query(m_mysql, select.str().c_str());
00302 checkForErrors("Cannot execute", select.str(), __FILE__, __LINE__);
00303 if (mysql_affected_rows(m_mysql)!=1){
00304 throw MysqlException("Did NOT add row", select.str(), __FILE__, __LINE__);
00305 }
00306 }
00307
00308 void IOManagerDB::setLocationName(const std::string& name){
00309 m_locationName=name;
00310 }
00311
00312 std::string IOManagerDB::getLocationName(){
00313 return m_locationName;
00314 }
00315
00316 }