summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordeva <deva>2011-02-04 07:43:00 +0000
committerdeva <deva>2011-02-04 07:43:00 +0000
commitbfe5d3000182cb10db583fe42ffa7b48f84d8b5b (patch)
tree8b4228e258716267e854975df7f8a01294c89562
parentf825cb9f6f5a01f2029c79a363a89047b482c788 (diff)
Session locking mechanism gone crazy. This needs a rewamp at some point.
-rw-r--r--server/src/database.h10
-rw-r--r--server/src/pracrodao.h1
-rw-r--r--server/src/pracrodaopgsql.cc33
-rw-r--r--server/src/pracrodaopgsql.h1
-rw-r--r--server/src/pracrodaotest.h1
-rw-r--r--server/src/session.cc22
-rw-r--r--server/src/session.h15
-rw-r--r--server/src/sessionparser.cc4
-rw-r--r--server/src/sessionparser.h1
-rw-r--r--server/src/sessionserialiser.cc167
-rw-r--r--server/src/sessionserialiser.h5
-rw-r--r--server/src/transactionhandler.cc1
12 files changed, 227 insertions, 34 deletions
diff --git a/server/src/database.h b/server/src/database.h
index a366f43..f3b42e2 100644
--- a/server/src/database.h
+++ b/server/src/database.h
@@ -62,6 +62,7 @@ public:
time_t now = time(NULL))
{
if(!dao) return;
+
mutex.lock();
DEBUG(db, "%s, %s, %s,...\n",
transaction.user.c_str(), transaction.cpr.c_str(),
@@ -79,7 +80,8 @@ public:
mutex.lock();
DEBUG(db, "%s, <%u fieldnames>, %ld\n",
patientid.c_str(), fieldnames.size(), oldest);
- Values values = dao->getLatestValues(sessionid, patientid, NULL, fieldnames, oldest);
+ Values values = dao->getLatestValues(sessionid, patientid,
+ NULL, fieldnames, oldest);
mutex.unlock();
return values;
}
@@ -172,6 +174,12 @@ public:
return dao->restore(data);
}
+ bool active()
+ {
+ if(!dao || sessionid == "") return false;
+ return dao->active(sessionId());
+ }
+
private:
PracroDAO *dao;
Mutex mutex;
diff --git a/server/src/pracrodao.h b/server/src/pracrodao.h
index 3371e2c..d74aeaa 100644
--- a/server/src/pracrodao.h
+++ b/server/src/pracrodao.h
@@ -68,6 +68,7 @@ public:
virtual void discard(std::string sessionid) = 0;
virtual std::string serialise() = 0;
virtual void restore(const std::string &data) = 0;
+ virtual bool active(std::string sessionid) = 0;
protected:
std::string host;
diff --git a/server/src/pracrodaopgsql.cc b/server/src/pracrodaopgsql.cc
index 14cb9c1..5a08e3a 100644
--- a/server/src/pracrodaopgsql.cc
+++ b/server/src/pracrodaopgsql.cc
@@ -97,6 +97,21 @@ std::string PracroDAOPgsql::newSessionId()
pqxx::result::const_iterator ri = R.begin();
if(ri != R.end()) {
DEBUG(db, "New session id: %s\n", (*ri)[0].c_str());
+ /*
+ std::string ts;
+ ts = "INSERT INTO commits (patientid, template, version,"
+ " \"timestamp\", uid, status) VALUES ("
+ " '" + W.esc(transaction.cpr) + "', "
+ " '" + W.esc(commit.templ) + "', "
+ " '" + "1.0" + "', "
+ " '" + W.esc(timestamp.str()) + "', "
+ " '" + W.esc(sessionid) + "', "
+ " 'active' "
+ ");"
+ ;
+ DEBUG(sql, "Query: %s\n", ts.c_str());
+ pqxx::result R = W.exec(ts);
+ */
return (*ri)[0].c_str();
}
ERR(db, "No pgsql connection\n");
@@ -477,6 +492,24 @@ void PracroDAOPgsql::discard(std::string sessionid)
}
}
+bool PracroDAOPgsql::active(std::string sessionid)
+{
+ std::string ts = "SELECT status FROM commits WHERE uid='"+sessionid+"';";
+ pqxx::work W(*conn);
+ pqxx::result R = W.exec(ts);
+ pqxx::result::const_iterator ri = R.begin();
+ if(ri != R.end()) {
+ std::string status = (*ri)[0].c_str();
+ if(status == "idle") {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ return false;
+}
+
#endif/*WITHOUT_DB*/
#ifdef TEST_PRACRODAOPGSQL
diff --git a/server/src/pracrodaopgsql.h b/server/src/pracrodaopgsql.h
index e3664f9..4d424f0 100644
--- a/server/src/pracrodaopgsql.h
+++ b/server/src/pracrodaopgsql.h
@@ -69,6 +69,7 @@ public:
void discard(std::string sessionid);
std::string serialise() { return ""; }
void restore(const std::string &data) {}
+ bool active(std::string sessionid);
private:
pqxx::connection *conn;
diff --git a/server/src/pracrodaotest.h b/server/src/pracrodaotest.h
index 0bd9be5..67df596 100644
--- a/server/src/pracrodaotest.h
+++ b/server/src/pracrodaotest.h
@@ -104,6 +104,7 @@ public:
void discard(std::string sessionid) {}
std::string serialise() { return ""; }
void restore(const std::string &data) {}
+ bool active(std::string sessionid) {return false;}
private:
Data data;
diff --git a/server/src/session.cc b/server/src/session.cc
index 58249af..c919e54 100644
--- a/server/src/session.cc
+++ b/server/src/session.cc
@@ -51,6 +51,8 @@ Session::Session(std::string sessionid, std::string pid, std::string t)
patientid = pid;
templ = t;
+
+ isreadonly = true;
database()->setSessionId(sessionid);
}
@@ -76,6 +78,11 @@ void Session::unlock()
mutex.unlock();
}
+bool Session::active()
+{
+ return isreadonly || database()->active();
+}
+
void Session::commit()
{
if(_journal != NULL) {
@@ -146,16 +153,29 @@ static bool fexists(const std::string &f)
}
Session *Sessions::newSession(std::string patientid, std::string templ)
+ throw(SessionAlreadyActive)
{
std::map<std::string, Session *>::iterator i = sessions.begin();
while(i != sessions.end()) {
if(i->second->patientid == patientid &&
i->second->templ == templ) {
- return i->second;
+ Session *s = i->second;
+ if(s->active()) throw SessionAlreadyActive(s->id());
+ return s;
}
+
i++;
}
+ { // Look up patientid / template tupple in session files.
+ SessionSerialiser ser(Conf::session_path);
+ Session *session = ser.findFromTupple(patientid, templ);
+ if(session) {
+ sessions[session->id()] = session;
+ return session;
+ }
+ }
+
Session *session = new Session("", patientid, templ);
sessions[session->id()] = session;
return session;
diff --git a/server/src/session.h b/server/src/session.h
index 5b9b0bb..31dee3f 100644
--- a/server/src/session.h
+++ b/server/src/session.h
@@ -30,6 +30,7 @@
#include <string>
#include <map>
+#include <exception>
#include "mutex.h"
@@ -56,6 +57,10 @@ public:
std::string patientid;
std::string templ;
+ bool active();
+
+ bool isreadonly;
+
private:
Journal *_journal;
Database *_database;
@@ -64,13 +69,21 @@ private:
class Sessions {
public:
+ class SessionAlreadyActive : public std::exception {
+ public:
+ SessionAlreadyActive(const std::string sid) : sessionid(sid) {}
+ ~SessionAlreadyActive() throw() {}
+ const std::string sessionid;
+ };
+
Sessions();
/**
* Create a new session, with a unique id. Insert it into the session list,
* and return its pointer.
*/
- Session *newSession(std::string patientid, std::string templ);
+ Session *newSession(std::string patientid, std::string templ)
+ throw(SessionAlreadyActive);
/**
* Lookup session in session list. Returns the session or NULL if no session
diff --git a/server/src/sessionparser.cc b/server/src/sessionparser.cc
index f449ba5..9666c2f 100644
--- a/server/src/sessionparser.cc
+++ b/server/src/sessionparser.cc
@@ -60,11 +60,13 @@ void SessionParser::startTag(std::string name,
DEBUG(sessionparser, "<%s>\n", name.c_str());
if(name == "session") {
+ patientid = attributes["patientid"];
sessionid = attributes["id"];
+ templ = attributes["template"];
}
if(name == "journal") {
- patientid = attributes["patientid"];
+ // patientid = attributes["patientid"];
userid = attributes["userid"];
}
diff --git a/server/src/sessionparser.h b/server/src/sessionparser.h
index f364a28..903dc56 100644
--- a/server/src/sessionparser.h
+++ b/server/src/sessionparser.h
@@ -44,6 +44,7 @@ public:
void endTag(std::string name);
void parseError(const char *buf, size_t len, std::string error, int lineno);
+ std::string templ;
std::string sessionid;
std::string patientid;
std::string userid;
diff --git a/server/src/sessionserialiser.cc b/server/src/sessionserialiser.cc
index 4065214..f2e2f39 100644
--- a/server/src/sessionserialiser.cc
+++ b/server/src/sessionserialiser.cc
@@ -27,6 +27,10 @@
*/
#include "sessionserialiser.h"
+#include <dirent.h>
+#include <sys/stat.h>
+#include <errno.h>
+
#include "journal.h"
#include "sessionparser.h"
@@ -38,10 +42,12 @@
#include <stdio.h>
#include <string.h>
+#define PRE "pracro_session"
+
std::string getSessionFilename(const std::string &path,
const std::string &sessionid)
{
- return path + "/pracro_session." + sessionid;
+ return path + "/"PRE"." + sessionid;
}
@@ -63,14 +69,15 @@ SessionSerialiser::SessionSerialiser(std::string path)
//#define BENC(s) base64encode(s)
//#define BDEC(s) base64decode(s)
-Session *SessionSerialiser::loadStr(const std::string &xml,
- const std::string &sessionid)
+Session *SessionSerialiser::loadStr(const std::string &xml)
{
// SessionAutolock lock(*session);
SessionParser parser;
parser.parse(xml.data(), xml.length());
- Session *session = new Session(sessionid, parser.patientid, "");
+ Session *session = new Session(XDEC(parser.sessionid),
+ XDEC(parser.patientid),
+ XDEC(parser.templ));
Journal *j = session->journal();
j->setUser(XDEC(parser.userid));
j->setPatientID(XDEC(parser.patientid));
@@ -93,7 +100,9 @@ std::string SessionSerialiser::saveStr(Session *session)
xml += "<?xml version='1.0' encoding='UTF-8'?>\n";
xml += "<session timestamp=\""+itostr(time(NULL))+"\" "
- "id=\""+session->id()+"\">\n";
+ "id=\""+XENC(session->id())+"\" "
+ "template=\""+XENC(session->templ)+ "\" "
+ "patientid=\"" + XENC(session->patientid) + "\">\n";
Journal *journal = session->journal();
@@ -139,7 +148,7 @@ Session *SessionSerialiser::load(const std::string &sessionid)
}
fclose(fp);
- Session *session = loadStr(xml, sessionid);
+ Session *session = loadStr(xml);
// delete file
unlink(filename.c_str());
@@ -159,68 +168,168 @@ void SessionSerialiser::save(Session *session)
fclose(fp);
}
+static inline bool isxmlfile(std::string name)
+{
+ if(name.find(PRE,0) == std::string::npos) return false;
+
+ struct stat s;
+ stat(name.c_str(), &s);
+
+ if(S_ISREG(s.st_mode) == false) return false;
+
+ return true;
+}
+
+Session *SessionSerialiser::findFromTupple(const std::string &patientid,
+ const std::string &templ)
+{
+ DEBUG(sessionserialiser, "Looking for: PatientID %s - Template %s\n",
+ patientid.c_str(), templ.c_str());
+
+ DIR *dir = opendir(path.c_str());
+ if(!dir) {
+ ERR(sessionserialiser, "Could not open directory: %s - %s\n",
+ path.c_str(), strerror(errno));
+ return NULL;
+ }
+
+ struct dirent *dirent;
+ while( (dirent = readdir(dir)) != NULL ) {
+
+ std::string filename = path+"/"+dirent->d_name;
+
+ DEBUG(sessionserialiser, "Looking at file: %s\n", filename.c_str());
+
+ if(isxmlfile(filename)) {
+
+ DEBUG(sessionserialiser, "Is xml file\n");
+
+ // Load session file
+ FILE *fp = fopen(filename.c_str(), "r");
+ std::string xml;
+ while(!feof(fp)) {
+ char str[64];
+ memset(str, 0, sizeof(str));
+ fread(str, sizeof(str) - 1, 1, fp);
+ xml += str;
+ }
+ fclose(fp);
+
+ Session *session = loadStr(xml);
+
+ DEBUG(sessionserialiser, "PatientID %s - Template %s\n",
+ session->patientid.c_str(),
+ session->templ.c_str());
+
+ if(session->patientid == patientid &&
+ session->templ == templ) {
+ closedir(dir);
+ unlink(filename.c_str());
+ return session;
+ }
+ }
+ }
+
+ closedir(dir);
+
+ return NULL;
+}
+
#ifdef TEST_SESSIONSERIALISER
-//deps: session.cc journal.cc debug.cc configuration.cc mutex.cc journal_commit.cc sessionparser.cc saxparser.cc
-//cflags: -I.. $(PTHREAD_CFLAGS) $(EXPAT_CFLAGS)
-//libs: $(PTHREAD_LIBS) $(EXPAT_LIBS)
+//deps: session.cc journal.cc debug.cc configuration.cc mutex.cc journal_commit.cc sessionparser.cc saxparser.cc xml_encode_decode.cc database.cc pracrodaopgsql.cc pracrodaotest.cc pracrodao.cc journal_uploadserver.cc log.cc
+//cflags: -I.. $(PTHREAD_CFLAGS) $(EXPAT_CFLAGS) $(PQXX_CFLAGS)
+//libs: $(PTHREAD_LIBS) $(EXPAT_LIBS) $(PQXX_LIBS)
#include "test.h"
+#include <stdio.h>
+
#define SID "42"
+#define PID "1234567890"
+#define TID "sometemplate"
#define SPATH "/tmp"
TEST_BEGIN;
std::string xml;
+debug_parse("+all");
+
+{
+ FILE *fp = fopen("/tmp/"PRE".42", "w");
+ fclose(fp);
+ TEST_TRUE(isxmlfile("/tmp/"PRE".42"), "Xml file");
+ unlink("/tmp/"PRE".42");
+
+ fp = fopen("/tmp/pracro_diller.42", "w");
+ fclose(fp);
+ TEST_FALSE(isxmlfile("/tmp/pracro_diller.42"), "Txt file");
+ unlink("/tmp/pracro_diller.42");
+
+ TEST_FALSE(isxmlfile("/tmp/"PRE".42"), "No file");
+ TEST_FALSE(isxmlfile("/tmp/badname"), "No file, bad name");
+}
+
{
- Session session(SID);
+ Session session(SID, PID, TID);
Journal *j = session.journal();
j->addEntry("some text", "macro1", 0);
j->addEntry("some more text", "macro2", 2);
j->addEntry("yet some more text", "macro3", 1);
- SessionSerialiser s(SPATH, &session);
- xml = s.saveStr();
+ SessionSerialiser s(SPATH);
+ xml = s.saveStr(&session);
s.loadStr(xml);
- std::string xml2 = s.saveStr();
+ std::string xml2 = s.saveStr(&session);
TEST_EQUAL_STR(xml, xml2, "Compare");
}
{
- Session session(SID);
+ Session session(SID, PID, TID);
Journal *j = session.journal();
j->addEntry("some text", "macro1", 0);
j->addEntry("some more text", "macro2", 2);
j->addEntry("yet some more text", "macro3", 1);
- SessionSerialiser s(SPATH, &session);
- xml = s.saveStr();
+ SessionSerialiser s(SPATH);
+ xml = s.saveStr(&session);
}
-
+/*
{
- Session session(SID);
- SessionSerialiser s(SPATH, &session);
+ Session session(SID, PID, TID);
+ SessionSerialiser s(SPATH);
s.loadStr(xml);
- std::string xml2 = s.saveStr();
+ std::string xml2 = s.saveStr(&session);
TEST_EQUAL_STR(xml, xml2, "Compare");
}
-
+*/
{
- Session session(SID);
+ Session session(SID, PID, TID);
Journal *j = session.journal();
j->addEntry("some text", "macro1", 0);
j->addEntry("some more text", "macro2", 2);
j->addEntry("yet some more text", "macro3", 1);
- SessionSerialiser s(SPATH, &session);
- s.save();
+ SessionSerialiser s(SPATH);
+ s.save(&session);
}
-
+/*
{
- Session session(SID);
- SessionSerialiser s(SPATH, &session);
- s.load();
- std::string xml2 = s.saveStr();
+ Session session(SID, PID, TID);
+ SessionSerialiser s(SPATH);
+ s.load(SID);
+ std::string xml2 = s.saveStr(&session);
TEST_EQUAL_STR(xml, xml2, "Compare");
}
+*/
+{
+ Session session(SID, PID, TID);
+ SessionSerialiser s(SPATH);
+ s.save(&session);
+ Session *s1 = s.findFromTupple(PID, TID);
+ TEST_NOTEQUAL(s1, NULL, "Found it?");
+ TEST_EQUAL(s1->id(), SID, "Compare found tuple.");
+ TEST_EQUAL(s1->patientid, PID, "Compare found tuple.");
+ TEST_EQUAL(s1->templ, TID, "Compare found tuple.");
+ delete s1;
+}
TEST_END;
diff --git a/server/src/sessionserialiser.h b/server/src/sessionserialiser.h
index f184d35..acc9ad6 100644
--- a/server/src/sessionserialiser.h
+++ b/server/src/sessionserialiser.h
@@ -36,9 +36,12 @@ class SessionSerialiser {
public:
SessionSerialiser(std::string path);
- Session *loadStr(const std::string &xml, const std::string &sessionid);
+ Session *loadStr(const std::string &xml);
std::string saveStr(Session *session);
+ Session *findFromTupple(const std::string &patientid,
+ const std::string &templ);
+
Session *load(const std::string &sessionid);
void save(Session *session);
diff --git a/server/src/transactionhandler.cc b/server/src/transactionhandler.cc
index 8ebbd69..6d0b922 100644
--- a/server/src/transactionhandler.cc
+++ b/server/src/transactionhandler.cc
@@ -68,6 +68,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);
if(resume != "") {