diff options
Diffstat (limited to 'server')
| -rw-r--r-- | server/src/database.h | 10 | ||||
| -rw-r--r-- | server/src/pracrodao.h | 1 | ||||
| -rw-r--r-- | server/src/pracrodaopgsql.cc | 33 | ||||
| -rw-r--r-- | server/src/pracrodaopgsql.h | 1 | ||||
| -rw-r--r-- | server/src/pracrodaotest.h | 1 | ||||
| -rw-r--r-- | server/src/session.cc | 22 | ||||
| -rw-r--r-- | server/src/session.h | 15 | ||||
| -rw-r--r-- | server/src/sessionparser.cc | 4 | ||||
| -rw-r--r-- | server/src/sessionparser.h | 1 | ||||
| -rw-r--r-- | server/src/sessionserialiser.cc | 167 | ||||
| -rw-r--r-- | server/src/sessionserialiser.h | 5 | ||||
| -rw-r--r-- | server/src/transactionhandler.cc | 1 | 
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 != "") { | 
