summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/src/admin_connection.cc21
-rw-r--r--server/src/admin_export.cc48
-rw-r--r--server/src/admin_export.h4
-rw-r--r--server/src/client_connection.cc15
-rw-r--r--server/src/client_connection.h7
-rw-r--r--server/src/fieldnamescanner.cc6
-rw-r--r--server/src/fieldnamescanner.h4
-rw-r--r--server/src/httpd.cc9
-rw-r--r--server/src/session.cc23
-rw-r--r--server/src/session.h12
-rw-r--r--server/xml/courses/test.xml1
11 files changed, 97 insertions, 53 deletions
diff --git a/server/src/admin_connection.cc b/server/src/admin_connection.cc
index 0fe5380..fac52a1 100644
--- a/server/src/admin_connection.cc
+++ b/server/src/admin_connection.cc
@@ -27,6 +27,8 @@
*/
#include "admin_connection.h"
+#include <stdlib.h>
+
#include "admin_rc.h"
#include "admin_export.h"
@@ -36,7 +38,11 @@
static std::string admin_sessionunlock(Environment &env, std::string id)
{
- Session *session = env.sessions.session(id);
+ // NOTE: Returned session is returned in locked state!
+ Session *session = NULL;
+ SessionAutounlock l(&session);
+
+ session = env.sessions.lockedSession(id);
if(session) {
if(session->isReadonly()) {
env.sessions.deleteSession(id);
@@ -56,8 +62,10 @@ static std::string admin_listactivesessions(Environment &env)
std::vector<std::string> act = env.sessions.activeSessions();
std::vector<std::string>::iterator i = act.begin();
while(i != act.end()) {
- Session *s = env.sessions.session(*i);
- SessionAutolock lock(*s);
+ // NOTE: Returned session is returned in locked state!
+ Session *s = NULL;
+ SessionAutounlock l(&s);
+ s = env.sessions.lockedSession(*i);
str += "Session " + *i + ": "+s->templ+" on "+s->patientid+" "+
std::string(s->idle()?"[idle]":"[active]")+"\n";
i++;
@@ -118,8 +126,13 @@ bool AdminConnection::handle(const char *data, size_t size)
}
if(uri == "/export" && args.find("template") != args.end()) {
+ time_t from = 0;
+ if(args.find("from") != args.end()) from = atoi(args["from"].c_str());
+
+ time_t to = time(NULL);
+ if(args.find("to") != args.end()) to = atoi(args["to"].c_str());
bool ok;
- std::string res = admin_export(env, args["template"], &ok);
+ std::string res = admin_export(env, args["template"], &ok, from, to);
if(!ok) reply = admin_header(uri) + res + admin_rc("footer");
else {
reply = res;
diff --git a/server/src/admin_export.cc b/server/src/admin_export.cc
index 3ec77d1..0aa290c 100644
--- a/server/src/admin_export.cc
+++ b/server/src/admin_export.cc
@@ -47,8 +47,10 @@ static std::string escape(std::string &str)
std::string::iterator i = str.begin();
while(i != str.end()) {
if(*i == '\"') out += "''";
+ else if(*i == '\n') out += "\342\220\244"; // N/L controlcharacter pictogram
+ else if(*i == '\r') { }
else out += *i;
- i++;
+ i++;
}
out += "\"";
return out;
@@ -59,34 +61,22 @@ public:
File(fieldnames_t &f, pqxx::work &w)
: work(w), fieldnames(f)
{
- // name += ".csf";
- // fp = fopen(name.c_str(), "w");
-
pos["id"] = 0;
pos["patientid"] = 1;
pos["time"] = 2;
pos["template"] = 3;
- //printf("%s\n", n.c_str());
-
size_t idx = 4;
fieldnames_t::iterator i = f.begin();
while(i != f.end()) {
- //printf("%s ", i->c_str());
pos[*i] = idx;
idx++;
i++;
}
- // printf("\n");
output_header();
}
- ~File()
- {
- // if(fp) fclose(fp);
- }
-
void output_header()
{
beginrow();
@@ -144,7 +134,8 @@ private:
};
-static std::string do_export(std::string templ, bool *ok)
+static std::string do_export(Environment &env, std::string templ, bool *ok,
+ time_t from, time_t to)
{
if(Conf::database_backend != "pgsql") {
*ok = false;
@@ -182,7 +173,7 @@ static std::string do_export(std::string templ, bool *ok)
}
}
- templates_t t = scanfieldnames(filter);
+ templates_t t = scanfieldnames(env, filter);
/*
templates_t::iterator ti = t.begin();
while(ti != t.end()) {
@@ -198,10 +189,24 @@ static std::string do_export(std::string templ, bool *ok)
File file(t[templ], work);
+ std::string tostr;
+ std::string fromstr;
{
- pqxx::result result =
- work.exec("SELECT * FROM commits WHERE template='"+templ+"'"
- " AND status='committed' ORDER BY patientid, timestamp;");
+ char buf[32];
+ sprintf(buf, "%d", (int)from);
+ fromstr = buf;
+ sprintf(buf, "%d", (int)to);
+ tostr = buf;
+ }
+
+ {
+ std::string q = "SELECT * FROM commits WHERE template='"+templ+"'"
+ " AND status='committed' AND timestamp>=" +fromstr+
+ " AND timestamp<="+tostr+" ORDER BY patientid, timestamp;";
+
+ DEBUG(export, "QUERY: %s\n", q.c_str());
+
+ pqxx::result result = work.exec(q);
pqxx::result::const_iterator ri = result.begin();
for(unsigned int r = 0; r < result.size(); r++) {
pqxx::result::tuple tuple = result.at(r);
@@ -210,7 +215,7 @@ static std::string do_export(std::string templ, bool *ok)
std::string version = tuple.at(2).c_str();
std::string timestamp = tuple.at(3).c_str();
std::string uid = tuple.at(4).c_str();
- std::string status = tuple.at(5).c_str();
+ // std::string status = tuple.at(5).c_str();
file.beginrow();
file.addcell("id", uid);
@@ -253,10 +258,11 @@ static std::string do_export(std::string templ, bool *ok)
#endif/* WITHOUT_DB */
-std::string admin_export(Environment &env, std::string templ, bool *ok)
+std::string admin_export(Environment &env, std::string templ, bool *ok,
+ time_t from, time_t to)
{
#ifndef WITHOUT_DB
- return do_export(templ, ok);
+ return do_export(env, templ, ok, from, to);
#else
return "No database available";
#endif/* WITHOUT_DB */
diff --git a/server/src/admin_export.h b/server/src/admin_export.h
index 69c7a36..804d373 100644
--- a/server/src/admin_export.h
+++ b/server/src/admin_export.h
@@ -29,9 +29,11 @@
#define __PRACRO_ADMIN_EXPORT_H__
#include <string>
+#include <time.h>
#include "environment.h"
-std::string admin_export(Environment &env, std::string templ, bool *ok);
+std::string admin_export(Environment &env, std::string templ, bool *ok,
+ time_t from, time_t to);
#endif/*__PRACRO_ADMIN_EXPORT_H__*/
diff --git a/server/src/client_connection.cc b/server/src/client_connection.cc
index fe55efc..075dc46 100644
--- a/server/src/client_connection.cc
+++ b/server/src/client_connection.cc
@@ -44,7 +44,7 @@ static std::string error_box(std::string message)
static bool did_commit = false;
#endif
-ClientConnection::ClientConnection(Environment &e, headers_t &headers,
+ClientConnection::ClientConnection(Environment &e, headers_t headers,
headers_t args, std::string uri)
: env(e), parser(&transaction)
{
@@ -154,17 +154,22 @@ bool ClientConnection::handle(const char *data, size_t size)
}
Session *session = NULL;
+ SessionAutounlock l(&session);
+
try {
if(sessionid == "") {
// Create new session
- session = env.sessions.newSession(patientid, templ);
+ // NOTE: New session is returned in locked state!
+ session = env.sessions.newLockedSession(patientid, templ);
} else {
// Attach to old session
- session = env.sessions.session(sessionid);
+ // NOTE: Returned session is returned in locked state!
+ session = env.sessions.lockedSession(sessionid);
// Session didn't exist - create a new one anyway.
if(session == NULL) {
- session = env.sessions.newSession(patientid, templ);
+ // NOTE: New session is returned in locked state!
+ session = env.sessions.newLockedSession(patientid, templ);
}
}
} catch(Sessions::SessionAlreadyActive &e) {
@@ -201,7 +206,7 @@ bool ClientConnection::handle(const char *data, size_t size)
parser_complete = true;
{
- SessionAutolock lock(*session);
+ //SessionAutolock lock(session);
response = handleTransaction(request, transaction, env, *session);
}
diff --git a/server/src/client_connection.h b/server/src/client_connection.h
index b811b7f..e64dcad 100644
--- a/server/src/client_connection.h
+++ b/server/src/client_connection.h
@@ -40,7 +40,12 @@ class Session;
class ClientConnection : public Connection {
public:
- ClientConnection(Environment &e, headers_t &headers,
+ /**
+ * URI: course/template/macro
+ * Params: petientid, sessionid and statechange (commit, nocommit or discard)
+ * Headers are currently not used.
+ */
+ ClientConnection(Environment &e, headers_t headers,
headers_t args, std::string uri);
~ClientConnection();
diff --git a/server/src/fieldnamescanner.cc b/server/src/fieldnamescanner.cc
index 5418bb4..ba3b61f 100644
--- a/server/src/fieldnamescanner.cc
+++ b/server/src/fieldnamescanner.cc
@@ -58,12 +58,12 @@ fieldnames_t getFields(Widget &widget)
return fieldnames;
}
-templates_t scanfieldnames(std::set<std::string> &filter)
+templates_t scanfieldnames(Environment &env, std::set<std::string> &filter)
{
templates_t templates;
// TemplateList templatelist(Conf::xml_basedir + "/templates");
- MacroList macrolist(Conf::xml_basedir + "/macros");
+ // MacroList macrolist(Conf::xml_basedir + "/macros");
// Iterate templates:
std::vector<std::string> templatefiles = getTemplates();
@@ -83,7 +83,7 @@ templates_t scanfieldnames(std::set<std::string> &filter)
if(ms->isHeader == false) {
std::string macro = ms->name;
DEBUG(scanner, "Name '%s'\n", macro.c_str());
- std::string macrofile = macrolist.getLatestVersion(macro);
+ std::string macrofile = env.macrolist.getLatestVersion(macro);
DEBUG(scanner, "File '%s'\n", macrofile.c_str());
// Iterate fields:
diff --git a/server/src/fieldnamescanner.h b/server/src/fieldnamescanner.h
index c766ba1..6201db7 100644
--- a/server/src/fieldnamescanner.h
+++ b/server/src/fieldnamescanner.h
@@ -33,12 +33,14 @@
#include <string>
#include <set>
+#include "environment.h"
+
typedef std::string fieldname_t;
typedef std::vector< fieldname_t > fieldnames_t;
typedef std::string template_name_t;
typedef std::map< template_name_t, fieldnames_t > templates_t;
-templates_t scanfieldnames(std::set<std::string> &filter);
+templates_t scanfieldnames(Environment &env, std::set<std::string> &filter);
#endif/*__PRACRO_FIELDNAMESCANNER_H__*/
diff --git a/server/src/httpd.cc b/server/src/httpd.cc
index f7ad7f4..1c0575a 100644
--- a/server/src/httpd.cc
+++ b/server/src/httpd.cc
@@ -68,6 +68,11 @@ static int request_handler(void *cls,
unsigned int *data_size,
void **con_cls)
{
+ DEBUG(httpd, "request_handler: cls(%p) con(%p) url(%s) method(%s)"
+ " version(%s) *con_cls(%p)\n",
+ cls, con, url, method, version, *con_cls);
+ DEBUG(httpd, "request_handler: *data_size(%u) data:[%s]\n", *data_size, data);
+
int ret = MHD_YES;
Httpd *httpd = (Httpd*)cls;
@@ -176,7 +181,7 @@ Httpd::~Httpd()
void Httpd::listen(unsigned short int port,
unsigned int cn_limit, unsigned int cn_timeout)
{
- int flags = MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY;
+ int flags = MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION;
d = MHD_start_daemon(flags, port, NULL, NULL,
request_handler, this,
@@ -196,7 +201,7 @@ void Httpd::listen_ssl(unsigned short int port,
std::string key, std::string cert,
unsigned int cn_limit, unsigned int cn_timeout)
{
- int flags = MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL;
+ int flags = MHD_USE_DEBUG | MHD_USE_THREAD_PER_CONNECTION | MHD_USE_SSL;
d_ssl = MHD_start_daemon(flags, port, NULL, NULL,
request_handler, this,
diff --git a/server/src/session.cc b/server/src/session.cc
index 8071d45..fcd138a 100644
--- a/server/src/session.cc
+++ b/server/src/session.cc
@@ -195,7 +195,7 @@ static bool fexists(const std::string &f)
return ret;
}
-Session *Sessions::newSession(std::string patientid, std::string templ)
+Session *Sessions::newLockedSession(std::string patientid, std::string templ)
throw(SessionAlreadyActive)
{
MutexAutolock lock(mutex);
@@ -209,6 +209,7 @@ Session *Sessions::newSession(std::string patientid, std::string templ)
DEBUG(session, "Patient/template matched session is already active.");
throw SessionAlreadyActive(session->id());
}
+ session->lock();
return session;
}
@@ -224,27 +225,33 @@ Session *Sessions::newSession(std::string patientid, std::string templ)
DEBUG(session, "Looked up session by id is already active.");
throw SessionAlreadyActive(session->id());
}
+ session->lock();
return session;
}
}
Session *session = new Session(env, "", patientid, templ);
sessions[session->id()] = session;
+ session->lock();
return session;
}
-Session *Sessions::session(std::string sessionid)
+Session *Sessions::lockedSession(std::string sessionid)
{
MutexAutolock lock(mutex);
- if(sessions.find(sessionid) != sessions.end())
- return sessions[sessionid];
+ if(sessions.find(sessionid) != sessions.end()) {
+ Session *s = sessions[sessionid];
+ s->lock();
+ return s;
+ }
std::string filename = getSessionFilename(Conf::session_path, sessionid);
if(fexists(filename)) {
SessionSerialiser ser(env, Conf::session_path);
Session *s = ser.load(sessionid);
sessions[s->id()] = s;
+ s->lock();
return s;
}
@@ -311,15 +318,15 @@ std::vector<std::string> Sessions::activeSessions()
return act;
}
-SessionAutolock::SessionAutolock(Session &s)
+SessionAutounlock::SessionAutounlock(Session **s)
: session(s)
{
- session.lock();
+ // session->lock();
}
-SessionAutolock::~SessionAutolock()
+SessionAutounlock::~SessionAutounlock()
{
- session.unlock();
+ if(*session) (*session)->unlock();
}
#ifdef TEST_SESSION
diff --git a/server/src/session.h b/server/src/session.h
index b5c31d7..4d1ed12 100644
--- a/server/src/session.h
+++ b/server/src/session.h
@@ -95,14 +95,14 @@ public:
* 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 *newLockedSession(std::string patientid, std::string templ)
throw(SessionAlreadyActive);
/**
* Lookup session in session list. Returns the session or NULL if no session
* exists with that sessionid.
*/
- Session *session(std::string sessionid);
+ Session *lockedSession(std::string sessionid);
/**
* Remove session from the session list and return its pointer. It is up to
@@ -136,13 +136,13 @@ private:
Mutex mutex;
};
-class SessionAutolock {
+class SessionAutounlock {
public:
- SessionAutolock(Session &session);
- ~SessionAutolock();
+ SessionAutounlock(Session **session);
+ ~SessionAutounlock();
private:
- Session &session;
+ Session **session;
};
#endif/*__PRACRO_SESSION_H__*/
diff --git a/server/xml/courses/test.xml b/server/xml/courses/test.xml
index 4594409..9dabdb9 100644
--- a/server/xml/courses/test.xml
+++ b/server/xml/courses/test.xml
@@ -1,5 +1,4 @@
<?xml version='1.0' encoding='UTF-8'?>
<course name="test" title="Test Course" version="1.0">
<template name="test"/>
- <template name="test2"/>
</course>