From 6bae4fd17d2660d53279dac9287de52be2a00c6c Mon Sep 17 00:00:00 2001 From: deva Date: Fri, 4 Feb 2011 13:34:40 +0000 Subject: Database pool is now used instead of one connection per session. Admin interface supports session unlock. --- server/src/admin_connection.cc | 36 ++++++++++++++++---- server/src/admin_connection.h | 5 ++- server/src/database.h | 44 +++++++++++++++---------- server/src/environment.cc | 7 ++-- server/src/environment.h | 4 +-- server/src/pracrodao.h | 1 + server/src/pracrodaopgsql.cc | 21 ++++++++++++ server/src/pracrodaopgsql.h | 1 + server/src/pracrodaotest.h | 1 + server/src/queryhandlerpracro.cc | 2 +- server/src/server.cc | 2 +- server/src/session.cc | 71 ++++++++++++++++++++++++++-------------- server/src/session.h | 13 +++++--- server/src/sessionserialiser.cc | 12 ++++--- server/src/sessionserialiser.h | 5 ++- server/src/transactionhandler.cc | 21 +++++++----- server/src/widgetgenerator.cc | 5 +-- server/src/widgetgenerator.h | 1 + 18 files changed, 176 insertions(+), 76 deletions(-) diff --git a/server/src/admin_connection.cc b/server/src/admin_connection.cc index 517b17a..32cc67e 100644 --- a/server/src/admin_connection.cc +++ b/server/src/admin_connection.cc @@ -27,19 +27,46 @@ */ #include "admin_connection.h" -AdminConnection::AdminConnection(Environment &e, headers_t a) - : env(e), args(a) {} +#include "debug.h" + +static std::string admin_sessionunlock(Environment &env, std::string id) +{ + Session *session = env.sessions.session(id); + if(session) { + if(session->isreadonly) { + env.sessions.deleteSession(id); + return "Session " + id + " was 'readonly' and has been discarded."; + } else { + session->setActive(false); + return "Session " + id + " has been deactivated (set to idle)."; + } + } + return "Session " + id + " does not exist or has been committed."; +} + +AdminConnection::AdminConnection(Environment &e, headers_t a, std::string u) + : env(e), args(a), uri(u) {} AdminConnection::~AdminConnection() {} bool AdminConnection::handle(const char *data, size_t size) { + if(data == NULL && size == 0) { + if(uri == "/sessionunlock" && args.find("id") != args.end()) { + reply = admin_sessionunlock(env, args["id"]); + return true; + } + + reply = "Try something else..."; + return false; + } + return true; } std::string AdminConnection::getResponse() { - return "Hello Admin World"; + return reply; } headers_t AdminConnection::getHeaders() @@ -50,11 +77,8 @@ headers_t AdminConnection::getHeaders() #ifdef TEST_ADMIN_CONNECTION -//Additional dependency files //deps: -//Required cflags (autoconf vars may be used) //cflags: -//Required link options (autoconf vars may be used) //libs: #include "test.h" diff --git a/server/src/admin_connection.h b/server/src/admin_connection.h index 98ddda7..c3f70b7 100644 --- a/server/src/admin_connection.h +++ b/server/src/admin_connection.h @@ -35,7 +35,7 @@ class AdminConnection : public Connection { public: - AdminConnection(Environment &e, headers_t args); + AdminConnection(Environment &e, headers_t args, std::string uri); ~AdminConnection(); bool handle(const char *data, size_t size); @@ -46,6 +46,9 @@ public: private: Environment &env; headers_t args; + std::string uri; + + std::string reply; }; #endif/*__PRACRO_ADMIN_CONNECTION_H__*/ diff --git a/server/src/database.h b/server/src/database.h index f3b42e2..fe644bc 100644 --- a/server/src/database.h +++ b/server/src/database.h @@ -42,23 +42,24 @@ public: std::string _passwd, std::string _dbname); ~Database(); - std::string sessionId() + std::string newSessionId() { - if(dao && sessionid == "") { - sessionid = dao->newSessionId(); + if(dao) { + return dao->newSessionId(); } - return sessionid; + return ""; } - + /* void setSessionId(std::string sessionid) { this->sessionid = sessionid; } - + */ // Make a commit to the db void commitTransaction(Transaction &transaction, Commit &commit, Macro ¯o, + std::string sessionid, time_t now = time(NULL)) { if(!dao) return; @@ -67,13 +68,14 @@ public: DEBUG(db, "%s, %s, %s,...\n", transaction.user.c_str(), transaction.cpr.c_str(), macro.attributes["name"].c_str()); - dao->commitTransaction(sessionId(), transaction, commit, macro, now); + dao->commitTransaction(sessionid, transaction, commit, macro, now); mutex.unlock(); } // Get a list of values from the db Values getValues(std::string patientid, Fieldnames &fieldnames, + std::string sessionid, time_t oldest = 0) { if(!dao) return Values(); @@ -89,6 +91,7 @@ public: // Check if a macro has been committed. bool checkMacro(std::string patientid, std::string macro, + std::string sessionid, time_t oldest = 0) { DEBUG(db, "%s, %s, %ld\n", @@ -101,7 +104,8 @@ public: } // Get latest resume of a given macro - std::string getResume(std::string patientid, Macro ¯o, time_t oldest) + std::string getResume(std::string patientid, Macro ¯o, + time_t oldest, std::string sessionid) { DEBUG(db, "%s, %s, %ld\n", patientid.c_str(), macro.attributes["name"].c_str(), oldest); @@ -144,22 +148,22 @@ public: return fieldnames; } - void commit() + void commit(std::string sessionid) { if(!dao || sessionid == "") return; - return dao->commit(sessionId()); + return dao->commit(sessionid); } - void nocommit() + void nocommit(std::string sessionid) { if(!dao || sessionid == "") return; - return dao->nocommit(sessionId()); + return dao->nocommit(sessionid); } - void discard() + void discard(std::string sessionid) { if(!dao || sessionid == "") return; - return dao->discard(sessionId()); + return dao->discard(sessionid); } std::string serialise() @@ -174,16 +178,22 @@ public: return dao->restore(data); } - bool active() + bool active(std::string sessionid) { if(!dao || sessionid == "") return false; - return dao->active(sessionId()); + return dao->active(sessionid); + } + + void setActive(std::string sessionid, bool val) + { + if(dao && sessionid != "") { + dao->setActive(sessionid, val); + } } private: PracroDAO *dao; Mutex mutex; - std::string sessionid; }; #endif/*__PRACRO_DATABASE_H__*/ diff --git a/server/src/environment.cc b/server/src/environment.cc index a2b7cb9..b40c3ca 100644 --- a/server/src/environment.cc +++ b/server/src/environment.cc @@ -31,15 +31,16 @@ #include "database.h" Environment::Environment() - : macrolist(Conf::xml_basedir + "/macros"), + : sessions(this), + macrolist(Conf::xml_basedir + "/macros"), templatelist(Conf::xml_basedir + "/templates") { - /* + for(int i = 0; i < Conf::database_poolsize; i++) { dbpool.add(new Database(Conf::database_backend, Conf::database_addr, "", Conf::database_user, Conf::database_passwd, "")); } - */ + for(int i = 0; i < Conf::artefact_poolsize; i++) { atfpool.add(new Artefact); } diff --git a/server/src/environment.h b/server/src/environment.h index 3e2ac95..a7b9677 100644 --- a/server/src/environment.h +++ b/server/src/environment.h @@ -28,7 +28,7 @@ #ifndef __PRACRO_ENVIRONMENT_H__ #define __PRACRO_ENVIRONMENT_H__ -//#include "database.h" +#include "database.h" #include "artefact.h" #include "connectionpool.h" #include "session.h" @@ -40,7 +40,7 @@ public: Environment(); ~Environment(); - // ConnectionPool dbpool; + ConnectionPool dbpool; ConnectionPool atfpool; Sessions sessions; MacroList macrolist; diff --git a/server/src/pracrodao.h b/server/src/pracrodao.h index d74aeaa..53c7db2 100644 --- a/server/src/pracrodao.h +++ b/server/src/pracrodao.h @@ -69,6 +69,7 @@ public: virtual std::string serialise() = 0; virtual void restore(const std::string &data) = 0; virtual bool active(std::string sessionid) = 0; + virtual void setActive(std::string sessionid, bool active) = 0; protected: std::string host; diff --git a/server/src/pracrodaopgsql.cc b/server/src/pracrodaopgsql.cc index 5a08e3a..c86797d 100644 --- a/server/src/pracrodaopgsql.cc +++ b/server/src/pracrodaopgsql.cc @@ -510,6 +510,27 @@ bool PracroDAOPgsql::active(std::string sessionid) return false; } +void PracroDAOPgsql::setActive(std::string sessionid, bool a) +{ + std::string ts; + try { + pqxx::work W(*conn); + if(a) { + ts = "UPDATE commits SET status='idle' WHERE uid="+sessionid+ + " AND status='active';"; + } else { + ts = "UPDATE commits SET status='active' WHERE uid="+sessionid+ + " AND status='idle';"; + } + /*pqxx::result R = */W.exec(ts); + + W.commit(); + } catch (std::exception &e) { + ERR_LOG(db, "setActive failed: %s: %s\n", e.what(), ts.c_str()); + } + +} + #endif/*WITHOUT_DB*/ #ifdef TEST_PRACRODAOPGSQL diff --git a/server/src/pracrodaopgsql.h b/server/src/pracrodaopgsql.h index 4d424f0..c943e93 100644 --- a/server/src/pracrodaopgsql.h +++ b/server/src/pracrodaopgsql.h @@ -70,6 +70,7 @@ public: std::string serialise() { return ""; } void restore(const std::string &data) {} bool active(std::string sessionid); + void setActive(std::string sessionid, bool active); private: pqxx::connection *conn; diff --git a/server/src/pracrodaotest.h b/server/src/pracrodaotest.h index 67df596..1e1a8c0 100644 --- a/server/src/pracrodaotest.h +++ b/server/src/pracrodaotest.h @@ -105,6 +105,7 @@ public: std::string serialise() { return ""; } void restore(const std::string &data) {} bool active(std::string sessionid) {return false;} + void setActive(std::string sessionid, bool active) {} private: Data data; diff --git a/server/src/queryhandlerpracro.cc b/server/src/queryhandlerpracro.cc index 6868e47..85dcdf9 100644 --- a/server/src/queryhandlerpracro.cc +++ b/server/src/queryhandlerpracro.cc @@ -56,7 +56,7 @@ QueryResult QueryHandlerPracro::exec(Query &query) oldest = time(NULL) - Conf::db_max_ttl; } - Values values = db.getValues(cpr, fields, oldest); + Values values = db.getValues(cpr, fields, ""/*no session*/, oldest); if(values.find(field) != values.end()) { std::string value = values[field].value; diff --git a/server/src/server.cc b/server/src/server.cc index 1665bbf..745b77b 100644 --- a/server/src/server.cc +++ b/server/src/server.cc @@ -61,7 +61,7 @@ public: if(headers.find("User-Agent") != headers.end() && headers["User-Agent"].find("Pracro") == std::string::npos) { // Admin - connection = new AdminConnection(env, getargs); + connection = new AdminConnection(env, getargs, url); } else { // Pracro client ClientConnection::Parameters parms; if(headers.contains("SessionID")) diff --git a/server/src/session.cc b/server/src/session.cc index c919e54..7290c31 100644 --- a/server/src/session.cc +++ b/server/src/session.cc @@ -43,29 +43,35 @@ #include "configuration.h" #include "connectionpool.h" #include "sessionserialiser.h" +#include "environment.h" -Session::Session(std::string sessionid, std::string pid, std::string t) +Session::Session(Environment *e, + std::string sid, std::string pid, std::string t) + : env(e) { _journal = NULL; - _database = NULL; + sessionid = sid; patientid = pid; templ = t; isreadonly = true; - - database()->setSessionId(sessionid); } Session::~Session() { if(_journal) delete _journal; - if(_database) delete _database; } std::string Session::id() { - return database()->sessionId(); + if(sessionid == "") { + AutoBorrower borrower(env->dbpool); + Database *db = borrower.get(); + sessionid = db->newSessionId(); + } + + return sessionid; } void Session::lock() @@ -80,7 +86,22 @@ void Session::unlock() bool Session::active() { - return isreadonly || database()->active(); + if(isreadonly) return true; + + { + AutoBorrower borrower(env->dbpool); + Database *db = borrower.get(); + return db->active(id()); + } +} + +void Session::setActive(bool a) +{ + if(isreadonly == false) { + AutoBorrower borrower(env->dbpool); + Database *db = borrower.get(); + return db->setActive(id(), a); + } } void Session::commit() @@ -90,17 +111,19 @@ void Session::commit() delete _journal; _journal = NULL; } - if(_database != NULL) { - _database->commit(); - delete _database; - _database = NULL; + if(isreadonly == false) { + AutoBorrower borrower(env->dbpool); + Database *db = borrower.get(); + db->commit(id()); } } void Session::nocommit() { - if(_database != NULL) { - _database->nocommit(); + if(isreadonly == false) { + AutoBorrower borrower(env->dbpool); + Database *db = borrower.get(); + db->nocommit(id()); } } @@ -110,10 +133,10 @@ void Session::discard() delete _journal; _journal = NULL; } - if(_database != NULL) { - _database->discard(); - delete _database; - _database = NULL; + if(isreadonly == false) { + AutoBorrower borrower(env->dbpool); + Database *db = borrower.get(); + db->discard(id()); } } @@ -126,7 +149,7 @@ Journal *Session::journal() } return _journal; } - +/* Database *Session::database() { if(_database == NULL) { @@ -136,8 +159,8 @@ Database *Session::database() } return _database; } - -Sessions::Sessions() +*/ +Sessions::Sessions(Environment *e) : env(e) { } @@ -168,7 +191,7 @@ Session *Sessions::newSession(std::string patientid, std::string templ) } { // Look up patientid / template tupple in session files. - SessionSerialiser ser(Conf::session_path); + SessionSerialiser ser(env, Conf::session_path); Session *session = ser.findFromTupple(patientid, templ); if(session) { sessions[session->id()] = session; @@ -176,7 +199,7 @@ Session *Sessions::newSession(std::string patientid, std::string templ) } } - Session *session = new Session("", patientid, templ); + Session *session = new Session(env, "", patientid, templ); sessions[session->id()] = session; return session; } @@ -188,7 +211,7 @@ Session *Sessions::session(std::string sessionid) std::string filename = getSessionFilename(Conf::session_path, sessionid); if(fexists(filename)) { - SessionSerialiser ser(Conf::session_path); + SessionSerialiser ser(env, Conf::session_path); Session *s = ser.load(sessionid); sessions[s->id()] = s; return s; @@ -229,7 +252,7 @@ void Sessions::store() { std::map::iterator i = sessions.begin(); while(i != sessions.end()) { - SessionSerialiser ser(Conf::session_path); + SessionSerialiser ser(env, Conf::session_path); ser.save(i->second); delete i->second; sessions.erase(i); diff --git a/server/src/session.h b/server/src/session.h index 31dee3f..f532452 100644 --- a/server/src/session.h +++ b/server/src/session.h @@ -34,12 +34,13 @@ #include "mutex.h" -class Database; +class Environment; class Journal; class Session { public: - Session(std::string sessionid, std::string patientid, std::string templ); + Session(Environment *env, + std::string sessionid, std::string patientid, std::string templ); ~Session(); std::string id(); @@ -52,19 +53,20 @@ public: void discard(); Journal *journal(); - Database *database(); std::string patientid; std::string templ; bool active(); + void setActive(bool active); bool isreadonly; private: + Environment *env; Journal *_journal; - Database *_database; Mutex mutex; + std::string sessionid; }; class Sessions { @@ -76,7 +78,7 @@ public: const std::string sessionid; }; - Sessions(); + Sessions(Environment *env); /** * Create a new session, with a unique id. Insert it into the session list, @@ -114,6 +116,7 @@ public: private: std::map sessions; + Environment *env; }; class SessionAutolock { diff --git a/server/src/sessionserialiser.cc b/server/src/sessionserialiser.cc index f2e2f39..0929a30 100644 --- a/server/src/sessionserialiser.cc +++ b/server/src/sessionserialiser.cc @@ -39,6 +39,8 @@ #include "xml_encode_decode.h" //#include "base64.h" +#include "environment.h" + #include #include @@ -58,7 +60,8 @@ static std::string itostr(int i) return sid; } -SessionSerialiser::SessionSerialiser(std::string path) +SessionSerialiser::SessionSerialiser(Environment *e, std::string path) + : env(e) { this->path = path; } @@ -75,7 +78,8 @@ Session *SessionSerialiser::loadStr(const std::string &xml) SessionParser parser; parser.parse(xml.data(), xml.length()); - Session *session = new Session(XDEC(parser.sessionid), + Session *session = new Session(env, + XDEC(parser.sessionid), XDEC(parser.patientid), XDEC(parser.templ)); Journal *j = session->journal(); @@ -87,7 +91,7 @@ Session *SessionSerialiser::loadStr(const std::string &xml) i++; } - session->database()->restore(XDEC(parser.database)); + // session->database()->restore(XDEC(parser.database)); return session; } @@ -125,7 +129,7 @@ std::string SessionSerialiser::saveStr(Session *session) std::string dbtype = "pgsql"; xml += " "+ - XENC(session->database()->serialise())+ + // XENC(session->database()->serialise())+ "\n"; xml += "\n"; diff --git a/server/src/sessionserialiser.h b/server/src/sessionserialiser.h index acc9ad6..a85fc63 100644 --- a/server/src/sessionserialiser.h +++ b/server/src/sessionserialiser.h @@ -32,9 +32,11 @@ #include "session.h" +class Environment; + class SessionSerialiser { public: - SessionSerialiser(std::string path); + SessionSerialiser(Environment *e, std::string path); Session *loadStr(const std::string &xml); std::string saveStr(Session *session); @@ -47,6 +49,7 @@ public: private: std::string path; + Environment *env; }; std::string getSessionFilename(const std::string &path, diff --git a/server/src/transactionhandler.cc b/server/src/transactionhandler.cc index 6d0b922..32d37eb 100644 --- a/server/src/transactionhandler.cc +++ b/server/src/transactionhandler.cc @@ -54,9 +54,9 @@ static std::string handleCommits(Transaction &transaction, Environment &env, std::string answer; if(transaction.commits.size() > 0) { - // AutoBorrower borrower(env.dbpool); - // Database *db = borrower.get(); - Database *db = session.database(); + AutoBorrower borrower(env.dbpool); + Database *db = borrower.get(); + //Database *db = session.database(); Commits::iterator i = transaction.commits.begin(); while(i != transaction.commits.end()) { @@ -69,7 +69,7 @@ static std::string handleCommits(Transaction &transaction, Environment &env, std::string resume = resume_parser(*macro, commit); commit.fields["journal.resume"] = resume; session.isreadonly = false; - db->commitTransaction(transaction, commit, *macro); + db->commitTransaction(transaction, commit, *macro, session.id()); if(resume != "") { @@ -94,9 +94,9 @@ static std::string handleRequest(Transaction &transaction, Environment &env, if(transaction.requests.size() > 0) { - // AutoBorrower borrower(env.dbpool); - // Database *db = borrower.get(); - Database *db = session.database(); + AutoBorrower borrower(env.dbpool); + Database *db = borrower.get(); + // Database *db = session.database(); Requests::iterator i = transaction.requests.begin(); while(i != transaction.requests.end()) { @@ -133,6 +133,7 @@ static std::string handleRequest(Transaction &transaction, Environment &env, bool completed = db->checkMacro(transaction.cpr, macro.attributes["name"], + session.id(), time(NULL)-Conf::db_max_ttl); answer += " \n"; } - answer += widgetgenerator(transaction.cpr, *m, lqm, *db); + answer += widgetgenerator(transaction.cpr, session.id(), + *m, lqm, *db); } else { // only find macro title MacroParser mp(env.macrolist.getLatestVersion(macro.attributes["name"])); @@ -246,7 +248,8 @@ static std::string handleRequest(Transaction &transaction, Environment &env, std::string state = "old"; std::string resume = db->getResume(transaction.cpr, macro, - time(NULL) - Conf::db_max_ttl); + time(NULL) - Conf::db_max_ttl, + session.id()); if(session.journal()->dirty(macro.attributes["name"])) { state = "dirty"; } else { diff --git a/server/src/widgetgenerator.cc b/server/src/widgetgenerator.cc index aa5786d..7a39190 100644 --- a/server/src/widgetgenerator.cc +++ b/server/src/widgetgenerator.cc @@ -90,13 +90,14 @@ static void get_fields(Widget &widget, Fieldnames &fields) } } -std::string widgetgenerator(std::string cpr, Macro ¯o, +std::string widgetgenerator(std::string cpr, std::string sessionid, + Macro ¯o, LUAQueryMapper &mapper, Database &db) { Fieldnames fields; get_fields(macro.widgets, fields); - Values values = db.getValues(cpr, fields); + Values values = db.getValues(cpr, fields, sessionid); return getWidgetString(macro, macro.widgets, " ", mapper, values); } diff --git a/server/src/widgetgenerator.h b/server/src/widgetgenerator.h index 17160fc..0e87cac 100644 --- a/server/src/widgetgenerator.h +++ b/server/src/widgetgenerator.h @@ -50,6 +50,7 @@ * @return An std::srting containing the prettyprinted version of the Macro. */ std::string widgetgenerator(std::string cpr, + std::string sessionid, Macro ¯o, LUAQueryMapper &mapper, Database &db); -- cgit v1.2.3