summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordeva <deva>2010-05-27 09:45:12 +0000
committerdeva <deva>2010-05-27 09:45:12 +0000
commitf92dd279a1e26dad7507d5d6944567c23834d440 (patch)
tree59dbd43d60937c6b3eaa82a36de8859a209e8163
parent73934812611cc7120175e26761d71fae9233c1e8 (diff)
A lot of session handling. A lot of new unit tests. Add of a more structured commit/discard handling. Fix of some wierd line break bugs in journalwriter
-rw-r--r--server/src/Makefile.am4
-rw-r--r--server/src/artefact.cc59
-rw-r--r--server/src/artefact.h4
-rw-r--r--server/src/configuration.cc2
-rw-r--r--server/src/configuration.h2
-rw-r--r--server/src/configurationparser.cc6
-rw-r--r--server/src/connection.cc242
-rw-r--r--server/src/connection.h10
-rw-r--r--server/src/connectionpool.cc69
-rw-r--r--server/src/connectionpool.h79
-rw-r--r--server/src/environment.cc26
-rw-r--r--server/src/journal_commit.cc2
-rw-r--r--server/src/journalwriter.cc15
-rw-r--r--server/src/journalwriter.h5
-rw-r--r--server/src/server.cc14
-rw-r--r--server/src/session.cc108
-rw-r--r--server/src/session.h7
-rw-r--r--server/src/sessionparser.cc110
-rw-r--r--server/src/sessionparser.h64
-rw-r--r--server/src/sessionserialiser.cc200
-rw-r--r--server/src/sessionserialiser.h53
-rw-r--r--server/src/transactionhandler.cc2
-rw-r--r--server/src/transactionparser.cc73
23 files changed, 1025 insertions, 131 deletions
diff --git a/server/src/Makefile.am b/server/src/Makefile.am
index 0a3569f..942ced5 100644
--- a/server/src/Makefile.am
+++ b/server/src/Makefile.am
@@ -44,6 +44,8 @@ pracrod_SOURCES = \
semaphore.cc \
server.cc \
session.cc \
+ sessionparser.cc \
+ sessionserialiser.cc \
templatelist.cc \
templateheaderparser.cc \
templateparser.cc \
@@ -126,6 +128,8 @@ EXTRA_DIST = \
semaphore.h \
server.h \
session.h \
+ sessionparser.h \
+ sessionserialiser.h \
templatelist.h \
templateheaderparser.h \
templateparser.h \
diff --git a/server/src/artefact.cc b/server/src/artefact.cc
index 24114f9..f3e739d 100644
--- a/server/src/artefact.cc
+++ b/server/src/artefact.cc
@@ -34,10 +34,10 @@
Artefact::Artefact()
{
-#ifndef WITHOUT_PENTOMINOS
+#ifndef WITHOUT_ARTEFACT
+
PRACRO_DEBUG(artefact, "Creating artefact connection %s : %d\n",
Conf::artefact_addr.c_str(), Conf::artefact_port);
-#endif/*WITHOUT_PENTOMINOS*/
atfh = atf_init();
if(!atfh) PRACRO_ERR(artefact, "Out of memory!\n");
@@ -46,19 +46,26 @@ Artefact::Artefact()
Conf::artefact_addr.c_str(),
Conf::artefact_port,
Conf::artefact_use_ssl);
+
+#endif/*WITHOUT_ARTEFACT*/
}
Artefact::~Artefact()
{
+#ifndef WITHOUT_ARTEFACT
+
atf_disconnect(conn);
atf_close(atfh);
+
+#endif/*WITHOUT_ARTEFACT*/
}
+#ifndef WITHOUT_ARTEFACT
static QueryResult node2result(atf_result_node_t *node, time_t timestamp)
{
QueryResult rnode;
rnode.timestamp = timestamp;
- rnode.source = "pentominos";
+ rnode.source = "artefact";
if(!node) return rnode;
@@ -74,11 +81,18 @@ static QueryResult node2result(atf_result_node_t *node, time_t timestamp)
return rnode;
}
+#endif/*WITHOUT_ARTEFACT*/
QueryResult Artefact::exec(Query &query,
std::string patientid,
std::string user)
{
+ QueryResult rroot;
+ rroot.timestamp = 0;
+ rroot.source = "pentominos";
+
+#ifndef WITHOUT_ARTEFACT
+
atf_transaction_t* atft = NULL;
atf_reply_t *reply = NULL;
atf_result_t *result = NULL;
@@ -87,10 +101,6 @@ QueryResult Artefact::exec(Query &query,
time_t timestamp;
atf_id id;
- QueryResult rroot;
- rroot.timestamp = 0;
- rroot.source = "pentominos";
-
if(query.attributes.find("class") == query.attributes.end()) {
PRACRO_ERR(artefact, "Missing 'class' attribute!\n");
goto aaarg;
@@ -135,22 +145,43 @@ QueryResult Artefact::exec(Query &query,
if(reply) atf_free_reply(reply);
if(atft) atf_free_transaction(atft);
+#endif/*WITHOUT_ARTEFACT*/
+
return rroot;
}
#ifdef TEST_ARTEFACT
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
+//deps: configuration.cc debug.cc
+//cflags: $(ATF_CFLAGS) -I..
+//libs: $(ATF_LIBS)
#include "test.h"
TEST_BEGIN;
-// TODO: Put some testcode here (see test.h for usable macros).
+pracro_debug_init();
+pracro_debug_parse("+all");
+
+{
+ Artefact atf;
+ Query q;
+ q.attributes["class"] = "echo";
+ QueryResult res = atf.exec(q, "1505050505", "me");
+
+ res.print();
+}
+
+{
+ Conf::artefact_addr = "nowhere_at_all.com";
+ Conf::artefact_port = 10000;
+
+ Artefact atf;
+ Query q;
+ q.attributes["class"] = "echo";
+ QueryResult res = atf.exec(q, "1505050505", "me");
+
+ res.print();
+}
TEST_END;
diff --git a/server/src/artefact.h b/server/src/artefact.h
index 7eb1a6b..fa1602d 100644
--- a/server/src/artefact.h
+++ b/server/src/artefact.h
@@ -31,7 +31,9 @@
#include "template.h"
#include "queryresult.h"
+#ifndef WITHOUT_ARTEFACT
#include <libartefact.h>
+#endif/*WITHOUT_ARTEFACT*/
class Artefact {
public:
@@ -43,8 +45,10 @@ public:
std::string user);
private:
+#ifndef WITHOUT_ARTEFACT
atf_handle_t *atfh;
atf_connection_t *conn;
+#endif/*WITHOUT_ARTEFACT*/
};
#endif/*__PRACRO_ARTEFACT_H__*/
diff --git a/server/src/configuration.cc b/server/src/configuration.cc
index ace07e7..b222639 100644
--- a/server/src/configuration.cc
+++ b/server/src/configuration.cc
@@ -59,3 +59,5 @@ std::string Conf::ssl_cert = "";
int Conf::connection_limit = 42;
int Conf::connection_timeout = 0;
+
+std::string Conf::session_path = "/tmp";
diff --git a/server/src/configuration.h b/server/src/configuration.h
index d077806..8980bfd 100644
--- a/server/src/configuration.h
+++ b/server/src/configuration.h
@@ -66,6 +66,8 @@ namespace Conf {
extern int connection_limit;
extern int connection_timeout;
+
+ extern std::string session_path;
};
#endif/*__ARTEFACT_CONFIGURATION_H__*/
diff --git a/server/src/configurationparser.cc b/server/src/configurationparser.cc
index 3823ee9..bc10e2b 100644
--- a/server/src/configurationparser.cc
+++ b/server/src/configurationparser.cc
@@ -181,6 +181,12 @@ void ConfigurationParser::reload()
Conf::connection_timeout = i;
} catch( ... ) {
}
+
+ try {
+ std::string s = lookup("session_path");
+ Conf::session_path = s;
+ } catch( ... ) {
+ }
}
#ifdef TEST_CONFIGURATIONPARSER
diff --git a/server/src/connection.cc b/server/src/connection.cc
index 36c030e..ed5a7a9 100644
--- a/server/src/connection.cc
+++ b/server/src/connection.cc
@@ -40,13 +40,23 @@ static std::string error_box(std::string message)
return errorbox;
}
-Connection::Connection(Environment &e, std::string sid, bool c)
+#ifdef TEST_CONNECTION
+static bool did_commit = false;
+#endif
+
+Connection::Connection(Environment &e, std::string sid, bool c, bool d)
: env(e), parser(&transaction)
{
PRACRO_DEBUG(connection, "[%p] CREATE\n", this);
sessionid = sid;
- commit = c;
+ docommit = c;
+ dodiscard = d;
+
+#ifdef TEST_CONNECTION
+ did_commit = false;
+#endif
+
}
Connection::~Connection()
@@ -54,6 +64,27 @@ Connection::~Connection()
PRACRO_DEBUG(connection, "[%p] DESTROY\n", this);
}
+void Connection::commit(Session *session)
+{
+ if(docommit) {
+ session->commit();
+ env.sessions.deleteSession(session->id());
+ sessionid = "";
+#ifdef TEST_CONNECTION
+ did_commit = true;
+#endif
+ }
+}
+
+void Connection::discard(Session *session)
+{
+ if(dodiscard) {
+ session->discard();
+ env.sessions.deleteSession(session->id());
+ sessionid = "";
+ }
+}
+
bool Connection::handle(const char *data, size_t size)
{
Session *session = NULL;
@@ -76,20 +107,22 @@ bool Connection::handle(const char *data, size_t size)
sessionid = session->id();
- if(!data || !size) return true;
-
try {
+
+ if(!data || !size) {
+ commit(session);
+ discard(session);
+ return true;
+ }
+
if(parser.parse(data, size)) {
{
SessionAutolock lock(*session);
response = handleTransaction(transaction, env, *session);
}
- if(commit) {
- session->commit();
- env.sessions.deleteSession(session->id());
- }
-
+ commit(session);
+ discard(session);
return true;
}
} catch(...) {
@@ -112,17 +145,194 @@ std::string Connection::getSessionID()
}
#ifdef TEST_CONNECTION
-//Additional dependency files
-//deps:
-//Required cflags (autoconf vars may be used)
-//cflags:
-//Required link options (autoconf vars may be used)
-//libs:
+//deps: debug.cc transactionparser.cc session.cc xml_encode_decode.cc saxparser.cc transactionhandler.cc journalwriter.cc mutex.cc templateparser.cc exception.cc configuration.cc macroparser.cc semaphore.cc entitylist.cc luaquerymapper.cc inotify.cc log.cc queryhandlerpentominos.cc widgetgenerator.cc queryhandlerpracro.cc resumeparser.cc journal_commit.cc versionstr.cc luaresume.cc luautil.cc artefact.cc environment.cc database.cc macrolist.cc templatelist.cc pracrodao.cc templateheaderparser.cc macroheaderparser.cc pracrodaotest.cc pracrodaopgsql.cc
+//cflags: -DWITHOUT_DATABASE -DWITHOUT_ARTEFACT -I.. $(LUA_CFLAGS) $(EXPAT_CFLAGS) $(PTHREAD_CFLAGS) $(PQXX_CXXFLAGS)
+//libs: $(LUA_LIBS) $(EXPAT_LIBS) $(PTHREAD_LIBS) $(PQXX_LIBS)
#include "test.h"
+static char xml_request[] =
+"<?xml version='1.0' encoding='UTF-8'?>\n"
+"<pracro version=\"1.0\" user=\"testuser\" cpr=\"1505050505\">\n"
+" <request macro=\"test\" template=\"test\"/>\n"
+"</pracro>\n"
+ ;
+
+static char xml_commit[] =
+"<?xml version='1.0' encoding='UTF-8'?>\n"
+"<pracro version=\"1.0\" user=\"testuser\" cpr=\"1505050505\">\n"
+" <commit version=\"\" macro=\"referral\" template=\"amd_forunders\" >\n"
+" <field value=\"Some docs\" name=\"referral.doctor\"/>\n"
+" <field value=\"DIMS\" name=\"referral.diagnosecode\"/>\n"
+" <field value=\"Avs\" name=\"referral.diagnose\"/>\n"
+" </commit>\n"
+"</pracro>\n"
+ ;
+
+static char xml_commit_p1[] =
+"<?xml version='1.0' encoding='UTF-8'?>\n"
+"<pracro version=\"1.0\" user=\"testuser\" cpr=\"1505050505\">\n"
+" <commit version=\"\" macro=\"referral\" template=\"amd_forunders\" >\n"
+" <field value=\"Some docs\" name=\"referral.doctor\"/>\n"
+" <field value=\"DIMS\" name=\"referral.diagn"
+ ;
+
+static char xml_commit_p2[] =
+"ose\"/>\n"
+" </commit>\n"
+"</pracro>\n"
+ ;
+
TEST_BEGIN;
-// TODO: Put some testcode here (see test.h for usable macros).
+Environment env;
+std::string sid;
+
+// Without data
+{
+ Connection con(env, "", false);
+ TEST_TRUE(con.handle("", 0), "Test handler return value.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ sid = con.getSessionID();
+ TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ Connection con(env, sid, false);
+ TEST_TRUE(con.handle("", 0), "Test handler return value.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_EQUAL_STR(con.getSessionID(), sid, "Test existing session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ Connection con(env, sid, true);
+ TEST_TRUE(con.handle("", 0), "Test handler return value.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_EQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_TRUE(did_commit, "Commit.");
+}
+
+{
+ Connection con(env, sid, false);
+ TEST_TRUE(con.handle("", 0), "Test handler return value.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), sid, "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+// With commit partial data
+{
+ Connection con(env, "", false);
+ TEST_FALSE(con.handle(xml_commit_p1, sizeof(xml_commit_p1) - 1),
+ "Test handler return value.");
+ sid = con.getSessionID();
+ TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_TRUE(con.handle(xml_commit_p2, sizeof(xml_commit_p2) - 1),
+ "Test handler return value.");
+ TEST_EQUAL_STR(con.getSessionID(), sid, "Test session id.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+// With commit partial data and journal commit
+{
+ Connection con(env, "", true);
+ TEST_FALSE(con.handle(xml_commit_p1, sizeof(xml_commit_p1) - 1),
+ "Test handler return value.");
+ sid = con.getSessionID();
+ TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_FALSE(did_commit, "No commit.");
+ TEST_TRUE(con.handle(xml_commit_p2, sizeof(xml_commit_p2) - 1),
+ "Test handler return value.");
+ TEST_EQUAL_STR(con.getSessionID(), "", "Test session id.");
+ TEST_TRUE(did_commit, "No commit.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+}
+
+// With commit data
+{
+ Connection con(env, "", false);
+ TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
+ "Test handler return value.");
+ sid = con.getSessionID();
+ TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ Connection con(env, sid, false);
+ TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_EQUAL_STR(con.getSessionID(), sid, "Test existing session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ Connection con(env, sid, true);
+ TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_EQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_TRUE(did_commit, "Commit.");
+}
+
+{
+ Connection con(env, sid, false);
+ TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), sid, "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+// With request data
+{
+ Connection con(env, "", false);
+ TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ sid = con.getSessionID();
+ TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ Connection con(env, sid, false);
+ TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_EQUAL_STR(con.getSessionID(), sid, "Test existing session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ Connection con(env, sid, true);
+ TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_EQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_TRUE(did_commit, "Commit.");
+}
+
+{
+ Connection con(env, sid, false);
+ TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), sid, "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
TEST_END;
diff --git a/server/src/connection.h b/server/src/connection.h
index f91ddc1..61997da 100644
--- a/server/src/connection.h
+++ b/server/src/connection.h
@@ -33,9 +33,11 @@
#include "transaction.h"
#include "transactionparser.h"
+class Session;
+
class Connection {
public:
- Connection(Environment &e, std::string sessionid, bool commit);
+ Connection(Environment &e, std::string sessionid, bool commit, bool discard);
~Connection();
bool handle(const char *data, size_t size);
@@ -44,8 +46,12 @@ public:
std::string getSessionID();
private:
+ void commit(Session *session);
+ void discard(Session *session);
+
std::string sessionid;
- bool commit;
+ bool docommit;
+ bool dodiscard;
Environment &env;
Transaction transaction;
diff --git a/server/src/connectionpool.cc b/server/src/connectionpool.cc
index 07e6aa2..e2b6bfc 100644
--- a/server/src/connectionpool.cc
+++ b/server/src/connectionpool.cc
@@ -58,6 +58,20 @@ static void* thread_run(void *data)
return NULL;
}
+static void* thread_run_clear_test(void *data)
+{
+ ConnectionPool<int> *pool = (ConnectionPool<int>*)data;
+ pool->giveBack(1);
+ pool->giveBack(2);
+
+ sleep(1);
+
+ pool->giveBack(3);
+ pool->giveBack(4);
+
+ return NULL;
+}
+
TEST_BEGIN;
ConnectionPool<int> pool;
@@ -90,19 +104,21 @@ pool.giveBack(b_db2);
TEST_EQUAL(pool.numFree(), 4, "Testing number of free databases.");
-pthread_attr_t attr;
-pthread_t tid;
-pthread_attr_init(&attr);
-pthread_create(&tid, &attr, thread_run, &pool);
-
-while(pool.numFree() > 0) { usleep(10); }
-
-int b_db3 = pool.borrow();
-TEST_FALSE(pool.testFree(b_db3), "Testing if returned db is free (semaphore test).");
-pool.giveBack(db3);
-
-pthread_join(tid, NULL);
-pthread_attr_destroy(&attr);
+{
+ pthread_attr_t attr;
+ pthread_t tid;
+ pthread_attr_init(&attr);
+ pthread_create(&tid, &attr, thread_run, &pool);
+
+ while(pool.numFree() > 0) { usleep(10); }
+
+ int b_db3 = pool.borrow();
+ TEST_FALSE(pool.testFree(b_db3), "Testing if returned db is free (semaphore test).");
+ pool.giveBack(db3);
+
+ pthread_join(tid, NULL);
+ pthread_attr_destroy(&attr);
+}
TEST_EQUAL(pool.numFree(), 4, "Testing if all database are now available again");
@@ -114,6 +130,33 @@ TEST_EQUAL(pool.numFree(), 4, "Testing if all database are now available again")
}
TEST_EQUAL(pool.numFree(), 4, "Testing if autoborrower has returned the db.");
+// Force remove all elements.
+pool.borrow();
+pool.clear(true);
+TEST_EQUAL(pool.numFree(), 0, "Testing number of free databases.");
+
+// Add them again.
+pool.add(db1);
+pool.add(db2);
+pool.add(db3);
+pool.add(db4);
+TEST_EQUAL(pool.numFree(), 4, "Testing number of free databases.");
+
+pool.borrow();
+pool.borrow();
+pool.borrow();
+pool.borrow();
+
+{
+ pthread_attr_t attr;
+ pthread_t tid;
+ pthread_attr_init(&attr);
+ pthread_create(&tid, &attr, thread_run_clear_test, &pool);
+ pool.clear(false);
+ pthread_join(tid, NULL);
+ pthread_attr_destroy(&attr);
+}
+
TEST_END;
#endif/*TEST_CONNECTIONPOOL*/
diff --git a/server/src/connectionpool.h b/server/src/connectionpool.h
index 77fc33b..33473e5 100644
--- a/server/src/connectionpool.h
+++ b/server/src/connectionpool.h
@@ -45,6 +45,8 @@ public:
T borrow();
void giveBack(T t);
+ std::list<T> clear(bool force = true);
+
private:
bool contains(std::list<T> &list, T t);
@@ -75,10 +77,11 @@ private:
template <class T>
void ConnectionPool<T>::add(T t)
{
- mutex.lock();
+ MutexAutolock lock(mutex);
+
passive.push_back(t);
semaphore.post();
- mutex.unlock();
+
}
template <class T>
@@ -96,12 +99,13 @@ bool ConnectionPool<T>::contains(std::list<T> &list, T t)
template <class T>
void ConnectionPool<T>::remove(T t)
{
- mutex.lock();
+ MutexAutolock lock(mutex);
+
if(contains(passive, t)) {
semaphore.post();
passive.remove(t);
}
- mutex.unlock();
+
}
template <class T>
@@ -109,9 +113,8 @@ bool ConnectionPool<T>::testFree(T t)
{
bool testfree = false;
- mutex.lock();
+ MutexAutolock lock(mutex);
testfree = contains(passive, t);
- mutex.unlock();
return testfree;
}
@@ -120,9 +123,10 @@ template <class T>
int ConnectionPool<T>::numFree()
{
int num;
- mutex.lock();
+
+ MutexAutolock lock(mutex);
num = passive.size();
- mutex.unlock();
+
return num;
}
@@ -133,13 +137,13 @@ T ConnectionPool<T>::borrow()
semaphore.wait();
- mutex.lock();
+ {
+ MutexAutolock lock(mutex);
- t = passive.front();
- passive.remove(t);
- active.push_back(t);
-
- mutex.unlock();
+ t = passive.front();
+ passive.remove(t);
+ active.push_back(t);
+ }
return t;
}
@@ -147,17 +151,58 @@ T ConnectionPool<T>::borrow()
template <class T>
void ConnectionPool<T>::giveBack(T t)
{
- mutex.lock();
+ MutexAutolock lock(mutex);
if(contains(active, t)) {
active.remove(t);
passive.push_back(t);
semaphore.post();
}
-
- mutex.unlock();
}
+template <class T>
+std::list<T> ConnectionPool<T>::clear(bool force)
+{
+ typename std::list<T> lst;
+
+ if(force == false) {
+ size_t num = 0;
+ {
+ MutexAutolock lock(mutex);
+ num = active.size() + passive.size();
+ }
+
+ while(num) {
+ borrow();
+ num--;
+ }
+ }
+
+ {
+ MutexAutolock lock(mutex);
+
+ typename std::list<T>::iterator i;
+
+ i = active.begin();
+ while(i != active.end()) {
+ lst.push_back(*i);
+ // i = active.erase(i);
+ semaphore.post();
+ i++;
+ }
+ active.clear();
+
+ i = passive.begin();
+ while(i != passive.end()) {
+ lst.push_back(*i);
+ // i = passive.erase(i);
+ i++;
+ }
+ passive.clear();
+ }
+
+ return lst;
+}
template <class T>
AutoBorrower<T>::AutoBorrower(ConnectionPool<T> &p)
diff --git a/server/src/environment.cc b/server/src/environment.cc
index 14dbd79..9904afc 100644
--- a/server/src/environment.cc
+++ b/server/src/environment.cc
@@ -46,18 +46,26 @@ Environment::Environment()
Environment::~Environment()
{
-}
+ // Remove, but wait until resources are released
+ std::list<Database*> dblst = dbpool.clear(false);
+ std::list<Database*>::iterator i = dblst.begin();
+ while(i != dblst.end()) {
+ delete *i;
+ i++;
+ }
-/*
- TCPSocket pentominos_socket;
-#ifndef WITHOUT_PENTOMINOS
- pentominos_socket.connect(Conf::pentominos_addr, Conf::pentominos_port);
-#endif
-*/
+ // Remove, but wait until resources are released
+ std::list<Artefact*> atflst = atfpool.clear(false);
+ std::list<Artefact*>::iterator j = atflst.begin();
+ while(j != atflst.end()) {
+ delete *j;
+ j++;
+ }
+}
#ifdef TEST_ENVIRONMENT
//deps: configuration.cc database.cc artefact.cc pracrodao.cc session.cc mutex.cc semaphore.cc debug.cc pracrodaotest.cc pracrodaopgsql.cc journalwriter.cc journal_commit.cc entitylist.cc inotify.cc exception.cc versionstr.cc tcpsocket.cc macrolist.cc templatelist.cc saxparser.cc log.cc macroheaderparser.cc templateheaderparser.cc
-//cflags: -I.. $(PQXX_CXXFLAGS) $(PTHREAD_CFLAGS) $(EXPAT_CFLAGS)
+//cflags: -DWITHOUT_ARTEFACT -I.. $(PQXX_CXXFLAGS) $(PTHREAD_CFLAGS) $(EXPAT_CFLAGS)
//libs: $(PQXX_LIBS) -lpthread $(EXPAT_LIBS) $(PTHREAD_LIBS)
#include "test.h"
@@ -68,6 +76,8 @@ Conf::database_poolsize = 1;
Conf::artefact_poolsize = 1;
+Conf::xml_basedir = "/tmp";
+
TEST_NOEXCEPTION(Environment env, "Check if the Enviroment can be created.");
TEST_END;
diff --git a/server/src/journal_commit.cc b/server/src/journal_commit.cc
index bc47fce..56e7baf 100644
--- a/server/src/journal_commit.cc
+++ b/server/src/journal_commit.cc
@@ -192,7 +192,7 @@ int journal_commit(const char *cpr, const char *user,
if(sock != -1 && write(sock, resume.c_str(), resume.size()) != (ssize_t)resume.size()) {
PRACRO_ERR_LOG(journal, "write did not write all the bytes in the buffer.\n");
}
- PRACRO_DEBUG(journal, "%s", buf);
+ PRACRO_DEBUG(journal, "%s\n", buf);
#ifndef WITHOUT_UPLOADSERVER
// close socket
diff --git a/server/src/journalwriter.cc b/server/src/journalwriter.cc
index c73a841..4b2b4be 100644
--- a/server/src/journalwriter.cc
+++ b/server/src/journalwriter.cc
@@ -187,7 +187,9 @@ void JournalWriter::addEntry(Transaction &transaction, Commit &commit,
PRACRO_DEBUG(journal, "addEntry: template(%s)\n", templ->attributes["name"].c_str());
- // Add the template resume as the header (ie. first entry) of the journal entry.
+#if 0 // this feature is no longer nessecary...
+ // Add the template resume as the header (ie. first entry)
+ // of the journal entry.
if(entrylist.size() == 0 && templ->attributes["name"] != "") {
std::string template_resume = templ->attributes["resume"];
@@ -200,16 +202,23 @@ void JournalWriter::addEntry(Transaction &transaction, Commit &commit,
entrylist[-1] = re; // Make sure it comes first.
}
}
+#endif
- // Test if the username or the cpr has changed... if so, commit and clear the list.
+ // Test if the username or the cpr has changed...
+ // if so, commit and clear the list.
if(currentuser != transaction.user || currentcpr != transaction.cpr) {
this->commit();
entrylist.clear();
}
+ addEntry(resume, commit.macro, index);
+}
+
+void JournalWriter::addEntry(std::string resume, std::string macro, int index)
+{
// Strip trailing whitespace, and add newlines.
std::string r = stripTrailingWhitepace(addNewlines(resume, 60));
- std::string m = commit.macro;
+ std::string m = macro;
ResumeEntry re;
re.resume = r;
diff --git a/server/src/journalwriter.h b/server/src/journalwriter.h
index 5bde707..2cd191d 100644
--- a/server/src/journalwriter.h
+++ b/server/src/journalwriter.h
@@ -34,13 +34,18 @@
#include "transaction.h"
#include "template.h"
+class SessionSerialiser;
+
class JournalWriter {
+ friend class SessionSerialiser;
public:
JournalWriter(std::string host, unsigned short int port);
void addEntry(Transaction &transaction, Commit &commit,
std::string resume, Template *templ);
+ void addEntry(std::string resume, std::string macro, int index);
+
void commit();
private:
diff --git a/server/src/server.cc b/server/src/server.cc
index 118db85..1f85479 100644
--- a/server/src/server.cc
+++ b/server/src/server.cc
@@ -69,8 +69,12 @@ static int handle_request_callback(void *cls,
const char *scm = MHD_lookup_connection_value(con, MHD_HEADER_KIND,
"SessionCommit");
+
+ const char *sdc = MHD_lookup_connection_value(con, MHD_HEADER_KIND,
+ "SessionDiscard");
+
Environment *env = (Environment *)cls;
- connection = new Connection(*env, sessionid, scm != NULL);
+ connection = new Connection(*env, sessionid, scm != NULL, sdc != NULL);
*con_cls = connection;
}
@@ -130,7 +134,7 @@ void server()
{
srand(time(NULL));
- bool forceshutdown = false;
+ // bool forceshutdown = false;
port_t port = Conf::server_port;
int flags = MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY;
@@ -161,9 +165,9 @@ void server()
PRACRO_ERR(server, "Failed to initialise MHD_start_daemon!\n");
return;
}
- again:
+ // again:
while(pracro_is_running) sleep(1);
-
+ /*
if(!forceshutdown && env.sessions.size() != 0) {
char *errbuf;
if(asprintf(&errbuf, "There are %d live sessions."
@@ -177,6 +181,8 @@ void server()
forceshutdown = true;
goto again;
}
+ */
+ env.sessions.store();
MHD_stop_daemon(d);
diff --git a/server/src/session.cc b/server/src/session.cc
index 74adb32..803a515 100644
--- a/server/src/session.cc
+++ b/server/src/session.cc
@@ -29,9 +29,16 @@
#include <stdlib.h>
+// for stat
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
#include "journalwriter.h"
#include "configuration.h"
#include "connectionpool.h"
+#include "sessionserialiser.h"
Session::Session(std::string sessionid)
{
@@ -39,6 +46,11 @@ Session::Session(std::string sessionid)
_journal = NULL;
}
+Session::~Session()
+{
+ if(_journal) delete _journal;
+}
+
std::string Session::id()
{
return _id;
@@ -63,6 +75,14 @@ void Session::commit()
}
}
+void Session::discard()
+{
+ if(_journal) {
+ delete _journal;
+ _journal = NULL;
+ }
+}
+
JournalWriter *Session::journal()
{
if(_journal == NULL) {
@@ -76,12 +96,32 @@ Sessions::Sessions()
{
}
+static bool fexists(const std::string &f)
+{
+ bool ret;
+
+/*
+ struct stat sbuf;
+ int n = stat(f.c_str(), &sbuf);
+ if(n != -1) ret = true;
+ ret = errno != ENOENT;
+*/
+
+ FILE *fp = fopen(f.c_str(), "r");
+ ret = fp != NULL;
+ if(fp) fclose(fp);
+
+ return ret;
+}
+
Session *Sessions::newSession()
{
char sessionid[32];
+ std::string filename;
do {
snprintf(sessionid, sizeof(sessionid)-1, "%d", rand());
- } while(sessions.find(sessionid) != sessions.end());
+ filename = getSessionFilename(Conf::session_path, sessionid);
+ } while(sessions.find(sessionid) != sessions.end() || fexists(filename));
Session *session = new Session(sessionid);
sessions[session->id()] = session;
@@ -90,16 +130,35 @@ Session *Sessions::newSession()
Session *Sessions::session(std::string sessionid)
{
- if(sessions.find(sessionid) == sessions.end()) return NULL;
- return sessions[sessionid];
+ if(sessions.find(sessionid) != sessions.end())
+ return sessions[sessionid];
+
+ std::string filename = getSessionFilename(Conf::session_path, sessionid);
+ if(fexists(filename)) {
+ Session *s = new Session(sessionid);
+ SessionSerialiser ser(Conf::session_path, s);
+ ser.load();
+ sessions[s->id()] = s;
+
+ fprintf(stderr, "s: %p\n",s);
+
+ return s;
+ }
+
+ return NULL;
}
Session *Sessions::takeSession(std::string sessionid)
{
- Session *s = session(sessionid);
+ Session *s = NULL;
+ if(sessions.find(sessionid) != sessions.end()) {
+ s = sessions[sessionid];
+ }
+
if(s) {
sessions.erase(sessionid);
}
+
return s;
}
@@ -114,6 +173,19 @@ size_t Sessions::size()
return sessions.size();
}
+void Sessions::store()
+{
+ std::map<std::string, Session*>::iterator i = sessions.begin();
+ while(i != sessions.end()) {
+ SessionSerialiser ser(Conf::session_path, i->second);
+ ser.save();
+ delete i->second;
+ sessions.erase(i);
+ i++;
+ }
+ sessions.clear();
+}
+
SessionAutolock::SessionAutolock(Session &s)
: session(s)
{
@@ -126,23 +198,41 @@ SessionAutolock::~SessionAutolock()
}
#ifdef TEST_SESSION
-//deps: configuration.cc journalwriter.cc journal_commit.cc mutex.cc debug.cc
-//cflags: -I.. $(PTHREAD_CFLAGS)
-//libs: $(PTHREAD_LIBS)
+//deps: configuration.cc journalwriter.cc journal_commit.cc mutex.cc debug.cc sessionserialiser.cc sessionparser.cc saxparser.cc
+//cflags: -I.. $(PTHREAD_CFLAGS) $(EXPAT_CFLAGS)
+//libs: $(PTHREAD_LIBS) $(EXPAT_LIBS)
#include <test.h>
TEST_BEGIN;
Sessions sessions;
-srand(0);
+Conf::session_path = "/tmp";
+
+srand(0); // force seed
Session *s1 = sessions.newSession();
-srand(0);
+srand(0); // force seed
Session *s2 = sessions.newSession();
TEST_NOTEQUAL(s1->id(), s2->id(), "Testing if IDs are unique.");
TEST_EQUAL(sessions.size(), 2, "Testing if size match.");
+std::string sessionid = s1->id();
+SessionSerialiser ser(Conf::session_path, s1);
+ser.save();
+
+sessions.deleteSession(sessionid);
+TEST_EQUAL(sessions.size(), 1, "Testing if size match.");
+
+s1 = sessions.session(sessionid);
+TEST_NOTEQUAL(s1, NULL, "Did we reload the session from disk?");
+
+sessions.store();
+TEST_EQUAL(sessions.size(), 0, "Testing if size match.");
+
+s1 = sessions.session(sessionid);
+TEST_NOTEQUAL(s1, NULL, "Did we reload the session from disk?");
+
TEST_END;
#endif/*TEST_SESSION*/
diff --git a/server/src/session.h b/server/src/session.h
index 48c01d7..6c614c7 100644
--- a/server/src/session.h
+++ b/server/src/session.h
@@ -38,6 +38,7 @@ class JournalWriter;
class Session {
public:
Session(std::string sessionid);
+ ~Session();
std::string id();
@@ -45,6 +46,7 @@ public:
void unlock();
void commit();
+ void discard();
JournalWriter *journal();
@@ -86,6 +88,11 @@ public:
*/
size_t size();
+ /**
+ * Write all active sessions to disc.
+ */
+ void store();
+
private:
std::map<std::string, Session *> sessions;
};
diff --git a/server/src/sessionparser.cc b/server/src/sessionparser.cc
new file mode 100644
index 0000000..ba3693d
--- /dev/null
+++ b/server/src/sessionparser.cc
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * sessionparser.cc
+ *
+ * Thu May 20 14:30:23 CEST 2010
+ * Copyright 2010 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Pracro is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "sessionparser.h"
+
+#include "debug.h"
+
+SessionParser::SessionParser()
+{
+ done = false;
+ totalbytes = 0;
+ inresume = false;
+}
+
+SessionParser::~SessionParser()
+{
+}
+
+void SessionParser::characterData(std::string &data)
+{
+ if(inresume) {
+ entries[entries.size()-1].resume += data;
+ }
+}
+
+void SessionParser::startTag(std::string name,
+ std::map<std::string, std::string> attributes)
+{
+ PRACRO_DEBUG(sessionparser, "<%s>\n", name.c_str());
+
+ if(name == "session") {
+ sessionid = attributes["id"];
+ }
+
+ if(name == "journal") {
+ patientid = attributes["patientid"];
+ userid = attributes["userid"];
+ }
+
+ if(name == "entry") {
+ Entry e;
+ e.index = atoi(attributes["index"].c_str());
+ e.macro = attributes["macro"];
+ entries.push_back(e);
+ }
+
+ if(name == "resume") {
+ inresume = true;
+ }
+}
+
+void SessionParser::endTag(std::string name)
+{
+ if(name == "resume") {
+ inresume = false;
+ }
+}
+
+void SessionParser::parseError(const char *buf, size_t len,
+ std::string error, int lineno)
+{
+ PRACRO_ERR(sessionnparser, "SessionParser error at line %d: %s\n",
+ lineno, error.c_str());
+
+ std::string xml;
+ xml.append(buf, len);
+
+ PRACRO_ERR(sessionparser, "\tBuffer %u bytes: [%s]\n",
+ len, xml.c_str());
+
+ throw std::exception();
+}
+
+#ifdef TEST_SESSIONPARSER
+//deps:
+//cflags:
+//libs:
+#include "test.h"
+
+TEST_BEGIN;
+
+#error "Put some testcode here (see test.h for usable macros)."
+
+TEST_END;
+
+#endif/*TEST_SESSIONPARSER*/
diff --git a/server/src/sessionparser.h b/server/src/sessionparser.h
new file mode 100644
index 0000000..37899aa
--- /dev/null
+++ b/server/src/sessionparser.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * sessionparser.h
+ *
+ * Thu May 20 14:30:23 CEST 2010
+ * Copyright 2010 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Pracro is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __PRACRO_SESSIONPARSER_H__
+#define __PRACRO_SESSIONPARSER_H__
+
+#include "saxparser.h"
+
+#include <string>
+#include <vector>
+
+class SessionParser : public SAXParser {
+public:
+ SessionParser();
+ ~SessionParser();
+
+ void characterData(std::string &data);
+ void startTag(std::string name,
+ std::map< std::string, std::string> attributes);
+ void endTag(std::string name);
+ void parseError(const char *buf, size_t len, std::string error, int lineno);
+
+ std::string sessionid;
+ std::string patientid;
+ std::string userid;
+
+ class Entry {
+ public:
+ int index;
+ std::string macro;
+ std::string resume;
+ };
+
+ std::vector<Entry> entries;
+
+private:
+ bool inresume;
+};
+
+#endif/*__PRACRO_SESSIONPARSER_H__*/
diff --git a/server/src/sessionserialiser.cc b/server/src/sessionserialiser.cc
new file mode 100644
index 0000000..10d449d
--- /dev/null
+++ b/server/src/sessionserialiser.cc
@@ -0,0 +1,200 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * sessionserialiser.cc
+ *
+ * Thu May 20 11:26:18 CEST 2010
+ * Copyright 2010 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Pracro is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "sessionserialiser.h"
+
+#include "journalwriter.h"
+
+#include "sessionparser.h"
+
+#include <stdio.h>
+#include <string.h>
+
+std::string getSessionFilename(const std::string &path,
+ const std::string &sessionid)
+{
+ return path + "/pracro_session." + sessionid;
+}
+
+
+static std::string itostr(int i)
+{
+ char sid[32];
+ snprintf(sid, sizeof(sid), "%d", i);
+ return sid;
+}
+
+SessionSerialiser::SessionSerialiser(std::string path, Session *session)
+{
+ this->session = session;
+ this->path = path;
+}
+
+void SessionSerialiser::loadStr(const std::string &xml)
+{
+ // SessionAutolock lock(*session);
+ SessionParser parser;
+ parser.parse(xml.data(), xml.length());
+ JournalWriter *j = session->journal();
+ j->currentuser = parser.userid;
+ j->currentcpr = parser.patientid;
+ std::vector<SessionParser::Entry>::iterator i = parser.entries.begin();
+ while(i != parser.entries.end()) {
+ j->addEntry(i->resume, i->macro, i->index);
+ i++;
+ }
+}
+
+std::string SessionSerialiser::saveStr()
+{
+ // SessionAutolock lock(*session);
+
+ std::string xml;
+
+ xml += "<?xml version='1.0' encoding='UTF-8'?>\n";
+ xml += "<session timestamp=\""+itostr(time(NULL))+"\" "
+ "id=\""+session->id()+"\">\n";
+
+ JournalWriter *journal = session->journal();
+
+ xml += " <journal patientid=\"" + journal->currentcpr +
+ "\" userid=\"" + journal->currentuser + "\">\n";
+
+ std::map< int, JournalWriter::ResumeEntry >::iterator i =
+ journal->entrylist.begin();
+ while(i != journal->entrylist.end()) {
+
+ xml += " <entry index=\""+itostr(i->first) + "\""
+ " macro=\"" + i->second.macro + "\">\n";
+ xml += " <resume>" + i->second.resume + "</resume>\n";
+ xml += " </entry>\n";
+
+ i++;
+ }
+
+ xml += " </journal>\n";
+ xml += "</session>\n";
+
+ return xml;
+}
+
+void SessionSerialiser::load()
+{
+ // read xml from file
+ std::string filename = getSessionFilename(path, session->id());
+
+ FILE *fp = fopen(filename.c_str(), "r");
+ char xml[2048];
+ memset(xml, 0, sizeof(xml));
+ fread(xml, sizeof(xml), 1, fp);
+ fclose(fp);
+
+ loadStr(xml);
+
+ // delete file
+ unlink(filename.c_str());
+
+}
+
+void SessionSerialiser::save()
+{
+ std::string filename = getSessionFilename(path, session->id());
+
+ std::string xml = saveStr();
+
+ // write xml to file
+ FILE *fp = fopen(filename.c_str(), "w");
+ fwrite(xml.data(), xml.size(), 1, fp);
+ fclose(fp);
+}
+
+#ifdef TEST_SESSIONSERIALISER
+//deps: session.cc journalwriter.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)
+#include "test.h"
+
+#define SID "42"
+#define SPATH "/tmp"
+
+TEST_BEGIN;
+
+std::string xml;
+
+{
+ Session session(SID);
+ JournalWriter *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();
+ s.loadStr(xml);
+ std::string xml2 = s.saveStr();
+ TEST_EQUAL_STR(xml, xml2, "Compare");
+}
+
+{
+ Session session(SID);
+ JournalWriter *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();
+}
+
+{
+ Session session(SID);
+ SessionSerialiser s(SPATH, &session);
+ s.loadStr(xml);
+ std::string xml2 = s.saveStr();
+ TEST_EQUAL_STR(xml, xml2, "Compare");
+}
+
+{
+ Session session(SID);
+ JournalWriter *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();
+}
+
+{
+ Session session(SID);
+ SessionSerialiser s(SPATH, &session);
+ s.load();
+ std::string xml2 = s.saveStr();
+ TEST_EQUAL_STR(xml, xml2, "Compare");
+}
+
+
+TEST_END;
+
+#endif/*TEST_SESSIONSERIALISER*/
diff --git a/server/src/sessionserialiser.h b/server/src/sessionserialiser.h
new file mode 100644
index 0000000..4002760
--- /dev/null
+++ b/server/src/sessionserialiser.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * sessionserialiser.h
+ *
+ * Thu May 20 11:26:18 CEST 2010
+ * Copyright 2010 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Pracro.
+ *
+ * Pracro is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Pracro is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pracro; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __PRACRO_SESSIONSERIALISER_H__
+#define __PRACRO_SESSIONSERIALISER_H__
+
+#include <string>
+
+#include "session.h"
+
+class SessionSerialiser {
+public:
+ SessionSerialiser(std::string path, Session *session);
+
+ void loadStr(const std::string &xml);
+ std::string saveStr();
+
+ void load();
+ void save();
+
+private:
+ Session *session;
+ std::string path;
+};
+
+std::string getSessionFilename(const std::string &path,
+ const std::string &sessionid);
+
+#endif/*__PRACRO_SESSIONSERIALISER_H__*/
diff --git a/server/src/transactionhandler.cc b/server/src/transactionhandler.cc
index 662896b..c9c58b6 100644
--- a/server/src/transactionhandler.cc
+++ b/server/src/transactionhandler.cc
@@ -280,7 +280,7 @@ std::string handleTransaction(Transaction &transaction, Environment &env,
TEST_BEGIN;
-// TODO: Put some testcode here (see test.h for usable macros).
+#error TODO: Put some testcode here (see test.h for usable macros).
TEST_END;
diff --git a/server/src/transactionparser.cc b/server/src/transactionparser.cc
index 7595bb2..b33cac6 100644
--- a/server/src/transactionparser.cc
+++ b/server/src/transactionparser.cc
@@ -106,6 +106,10 @@ void TransactionParser::parseError(const char *buf, size_t len,
}
#ifdef TEST_TRANSACTIONPARSER
+//deps: saxparser.cc debug.cc exception.cc log.cc
+//cflags: -I.. $(EXPAT_CFLAGS)
+//libs: $(EXPAT_LIBS)
+#include "test.h"
static char xml_minimal[] =
"<?xml version='1.0' encoding='UTF-8'?>\n"
@@ -137,53 +141,36 @@ static char xml_fail[] =
"</pracro>\n"
;
-int main()
-{
- // Test minimal
- try {
- Transaction transaction;
- TransactionParser parser(&transaction);
- parser.parse(xml_minimal, strlen(xml_minimal));
- } catch(Exception &e) {
- printf("ERROR: %s\n", e.what());
- return 1;
- }
-
- // Test request
- try {
- Transaction transaction;
- TransactionParser parser(&transaction);
- parser.parse(xml_request, strlen(xml_request));
- } catch(Exception &e) {
- printf("ERROR: %s\n", e.what());
- return 1;
- }
+TEST_BEGIN;
- // Test commit
- try {
- Transaction transaction;
- TransactionParser parser(&transaction);
- parser.parse(xml_commit, strlen(xml_commit));
- } catch(Exception &e) {
- printf("ERROR: %s\n", e.what());
- return 1;
- }
+// Test minimal
+{
+ Transaction transaction;
+ TransactionParser parser(&transaction);
+ TEST_NOEXCEPTION(parser.parse(xml_minimal, sizeof(xml_minimal)-1), "minimal");
+}
- // Test parse error (should throw an exception)
- try {
- Transaction transaction;
- TransactionParser parser(&transaction);
- parser.parse(xml_fail, strlen(xml_fail));
- } catch(Exception &e) {
- printf("ERROR: %s\n", e.what());
- goto onandon;
- }
- printf("We should fail here...\n");
- return 1;
+// Test request
+{
+ Transaction transaction;
+ TransactionParser parser(&transaction);
+ TEST_NOEXCEPTION(parser.parse(xml_request, sizeof(xml_request)-1), "request");
+}
- onandon:
+// Test commit
+{
+ Transaction transaction;
+ TransactionParser parser(&transaction);
+ TEST_NOEXCEPTION(parser.parse(xml_commit, sizeof(xml_commit)-1), "commit");
+}
- return 0;
+// Test parse error (should throw an exception)
+{
+ Transaction transaction;
+ TransactionParser parser(&transaction);
+ TEST_EXCEPTION(parser.parse(xml_fail, sizeof(xml_fail)-1), std::exception, "parse error");
}
+TEST_END;
+
#endif/*TEST_TRANSACTIONPARSER*/