diff options
author | deva <deva> | 2011-08-02 08:00:20 +0000 |
---|---|---|
committer | deva <deva> | 2011-08-02 08:00:20 +0000 |
commit | ed9e290b441a6486c576c2e2e4baa69fa0f3ed37 (patch) | |
tree | 759ace8ca615e3a4167a5e783297cc761b89b992 /server | |
parent | 23f39df8b8edeacfa5821050abbdc855acb2edd6 (diff) |
New 'open course' feature.
Diffstat (limited to 'server')
-rw-r--r-- | server/src/Makefile.am | 4 | ||||
-rw-r--r-- | server/src/client_connection.cc | 49 | ||||
-rw-r--r-- | server/src/client_connection.h | 5 | ||||
-rw-r--r-- | server/src/courselist.cc | 76 | ||||
-rw-r--r-- | server/src/courselist.h | 41 | ||||
-rw-r--r-- | server/src/courseparser.cc | 178 | ||||
-rw-r--r-- | server/src/courseparser.h | 68 | ||||
-rw-r--r-- | server/src/database.h | 2 | ||||
-rw-r--r-- | server/src/environment.cc | 3 | ||||
-rw-r--r-- | server/src/environment.h | 2 | ||||
-rw-r--r-- | server/src/httpd.cc | 2 | ||||
-rw-r--r-- | server/src/httpd.h | 8 | ||||
-rw-r--r-- | server/src/journal.cc | 4 | ||||
-rw-r--r-- | server/src/luaquerymapper.cc | 2 | ||||
-rw-r--r-- | server/src/pracrodaopgsql.cc | 6 | ||||
-rw-r--r-- | server/src/pracrodaotest.cc | 6 | ||||
-rw-r--r-- | server/src/server.cc | 2 | ||||
-rw-r--r-- | server/src/session.cc | 14 | ||||
-rw-r--r-- | server/src/transaction.h | 6 | ||||
-rw-r--r-- | server/src/transactionhandler.cc | 364 | ||||
-rw-r--r-- | server/src/transactionhandler.h | 5 | ||||
-rw-r--r-- | server/src/transactionparser.cc | 9 | ||||
-rw-r--r-- | server/xml/courses/test.xml | 1 | ||||
-rw-r--r-- | server/xml/macros/test_lineedit.xml | 2 |
24 files changed, 649 insertions, 210 deletions
diff --git a/server/src/Makefile.am b/server/src/Makefile.am index 2697fed..0bdfddb 100644 --- a/server/src/Makefile.am +++ b/server/src/Makefile.am @@ -21,6 +21,8 @@ pracrod_SOURCES = \ configurationparser.cc \ connection.cc \ connectionpool.cc \ + courseparser.cc \ + courselist.cc \ daemon.cc \ database.cc \ debug.cc \ @@ -79,6 +81,8 @@ EXTRA_DIST = \ configurationparser.h \ connection.h \ connectionpool.h \ + courseparser.h \ + courselist.h \ daemon.h \ database.h \ dbtypes.h \ diff --git a/server/src/client_connection.cc b/server/src/client_connection.cc index 9a1ac0f..1ec7e7c 100644 --- a/server/src/client_connection.cc +++ b/server/src/client_connection.cc @@ -44,21 +44,42 @@ 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) { DEBUG(connection, "[%p] CREATE\n", this); - if(headers.contains("SessionID")) - sessionid = headers["SessionID"]; - if(headers.contains("SessionPatientID")) - patientid = headers["SessionPatientID"]; - if(headers.contains("SessionTemplate")) - templ = headers["SessionTemplate"]; - - docommit = headers.contains("SessionCommit"); - donocommit = headers.contains("SessionNoCommit"); - dodiscard = headers.contains("SessionDiscard"); + size_t i = 0; + std::string *tar[3]; + tar[0] = &request.course; + tar[1] = &request.templ; + tar[2] = &request.macro; + int p = -1; + while(i < uri.size() && p < 3) { + if(uri[i] == '/') { + p++; + } else if(p > -1) { + *(tar[p]) += uri[i]; + } else { + ERR(connection, "Malformed URI. Missing beginning '/'!"); + } + i++; + } + + DEBUG(connection, "Course: %s, Template: %s, Macro: %s\n", + request.course.c_str(), + request.templ.c_str(), + request.macro.c_str()); + + templ = request.templ; + + request.patientid = patientid = args.lookup("patientid"); + sessionid = args.lookup("sessionid"); + + docommit = args.lookup("statechange") == "commit"; + donocommit = args.lookup("statechange") == "nocommit"; + dodiscard = args.lookup("statechange") == "discard"; #ifdef TEST_CLIENT_CONNECTION did_commit = false; @@ -151,7 +172,7 @@ bool ClientConnection::handle(const char *data, size_t size) try { - if(!data || !size) { + if((!data || !size) && (docommit || donocommit || dodiscard)) { parser_complete = true; commit(session); nocommit(session); @@ -159,12 +180,12 @@ bool ClientConnection::handle(const char *data, size_t size) return true; } - if(parser.parse(data, size)) { + if(size == 0 || parser.parse(data, size)) { parser_complete = true; { SessionAutolock lock(*session); - response = handleTransaction(transaction, env, *session); + response = handleTransaction(request, transaction, env, *session); } commit(session); diff --git a/server/src/client_connection.h b/server/src/client_connection.h index a509221..b811b7f 100644 --- a/server/src/client_connection.h +++ b/server/src/client_connection.h @@ -40,7 +40,8 @@ class Session; class ClientConnection : public Connection { public: - ClientConnection(Environment &e, headers_t &headers); + ClientConnection(Environment &e, headers_t &headers, + headers_t args, std::string uri); ~ClientConnection(); bool handle(const char *data, size_t size); @@ -67,6 +68,8 @@ private: bool docommit; bool dodiscard; bool donocommit; + + Request request; }; #endif/*__PRACRO_CLIENT_CONNECTION_H__*/ diff --git a/server/src/courselist.cc b/server/src/courselist.cc new file mode 100644 index 0000000..b6d2b29 --- /dev/null +++ b/server/src/courselist.cc @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * courselist.cc + * + * Thu Jul 7 10:25:06 CEST 2011 + * Copyright 2011 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 "courselist.h" + +#include "courseparser.h" + +#include "debug.h" + +CourseList::CourseList(std::string path) + : EntityList(path, "course") +{ + rescan(); +} + +void CourseList::addFile(std::string file) +{ + if(file.substr(file.size() - 4) != ".xml") { + DEBUG(courselist, "Skipping file: %s\n", file.c_str()); + return; + } + + DEBUG(courselist, "Adding file: %s\n", file.c_str()); + CourseParser parser(file); + try { + parser.parse(); + Course *templ = parser.getCourse(); + insertEntity(templ->name, + templ->version, + file); + } catch(Exception &e) { + WARN(courselist, "Skipping %s: %s\n", file.c_str(), e.what()); + } +} + +#ifdef TEST_COURSELIST +//Additional dependency files +//deps: +//Required cflags (autoconf vars may be used) +//cflags: +//Required link options (autoconf vars may be used) +//libs: +#include "test.h" + +TEST_BEGIN; + +// TODO: Put some testcode here (see test.h for usable macros). +TEST_TRUE(false, "No tests yet!"); + +TEST_END; + +#endif/*TEST_COURSELIST*/ diff --git a/server/src/courselist.h b/server/src/courselist.h new file mode 100644 index 0000000..12e5fba --- /dev/null +++ b/server/src/courselist.h @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * courselist.h + * + * Thu Jul 7 10:25:06 CEST 2011 + * Copyright 2011 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_COURSELIST_H__ +#define __PRACRO_COURSELIST_H__ + +#include "entitylist.h" + +class CourseList : public EntityList { +public: + CourseList(std::string path); + +private: + void addFile(std::string file); +}; + +#endif/*__PRACRO_COURSELIST_H__*/ diff --git a/server/src/courseparser.cc b/server/src/courseparser.cc new file mode 100644 index 0000000..af78ca1 --- /dev/null +++ b/server/src/courseparser.cc @@ -0,0 +1,178 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * courseparser.cc + * + * Tue Jun 28 10:52:41 CEST 2011 + * Copyright 2011 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 "courseparser.h" + +// For assert +#include <assert.h> + +// For open and friends +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +// For vprintf and friends +#include <stdarg.h> + +#include <errno.h> +#include <string.h> + +#include <stdio.h> + +#include "configuration.h" +#include "debug.h" +#include "exception.h" + +void CourseParser::error(const char* fmt, ...) +{ + va_list argp; + char *p; + va_start(argp, fmt); + vasprintf(&p, fmt, argp); + va_end(argp); + ERR_LOG(course, "Error in CourseParser: %s\n", p); + throw Exception(std::string("Error in CourseParser: ") + p); + free(p); +} + +CourseParser::CourseParser(std::string coursefile) +{ + state = C_UNDEFINED; + c = new Course(); + + file = coursefile; + + DEBUG(course, "Using course file: %s\n", file.c_str()); + + fd = open(file.c_str(), O_RDONLY); + if(fd == -1) error("Could not open file %s", file.c_str()); +} + +CourseParser::~CourseParser() +{ + if(fd != -1) close(fd); + delete c; +} + +void CourseParser::characterData(std::string &data) +{ +} + +void CourseParser::startTag(std::string name, attributes_t &attr) +{ + if(name == "course") { + if(state != C_UNDEFINED) error("Course found not a root node."); + state = C_COURSE; + + assert(c); // A Course has not yet been allocated, cannot create course! + + if(attr.find("name") != attr.end()) c->name = attr["name"]; + if(attr.find("title") != attr.end()) c->title = attr["title"]; + if(attr.find("version") != attr.end()) c->version = attr["version"]; + + return; + } + + if(name == "template") { + if(state != C_COURSE) error("template found outside course."); + state = C_TEMPLATE; + + assert(c); // A Course has not yet been allocated, cannot create template! + + Template t; + + if(attr.find("name") != attr.end()) t.name = attr["name"]; + if(attr.find("title") != attr.end()) t.title = attr["title"]; + + c->templates.push_back(t); + + return; + } + + error("Unknown/illegal tag: %s", name.c_str()); +} + +void CourseParser::endTag(std::string name) +{ + if(name == "course") state = C_UNDEFINED; + if(name == "template") state = C_COURSE; +} + +int CourseParser::readData(char *data, size_t size) +{ + if(fd == -1) { + ERR_LOG(course, "Invalid file descriptor.\n"); + return 0; + } + ssize_t r = read(fd, data, size); + if(r == -1) { + ERR_LOG(course, "Could not read...%s\n", strerror(errno)); + return 0; + } + return r; +} + +void CourseParser::parseError(const char *buf, size_t len, std::string error, + int lineno) +{ + fprintf(stderr, "CourseParser[%s] error at line %d: %s\n", + file.c_str(), lineno, error.c_str()); + fprintf(stderr, "\tBuffer %u bytes: [", len); + if(fwrite(buf, len, 1, stderr) != len) {} + fprintf(stderr, "]\n"); + fflush(stderr); + + char *slineno; + if(asprintf(&slineno, " at line %d\n", lineno) != -1) { + throw Exception(error + slineno); + free(slineno); + } +} + +Course *CourseParser::getCourse() +{ + return c; +} + +#ifdef TEST_COURSEPARSER +//deps: saxparser.cc debug.cc log.cc exception.cc +//cflags: -I.. $(EXPAT_CFLAGS) +//libs: $(EXPAT_LIBS) +#include "test.h" + +TEST_BEGIN; + +CourseParser p("../xml/courses/test.xml"); +p.parse(); + +Course *c = p.getCourse(); +TEST_NOTEQUAL(c, NULL, "Got one?"); + +TEST_END; + +#endif/*TEST_COURSEPARSER*/ diff --git a/server/src/courseparser.h b/server/src/courseparser.h new file mode 100644 index 0000000..7ab4c05 --- /dev/null +++ b/server/src/courseparser.h @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * courseparser.h + * + * Tue Jun 28 10:52:41 CEST 2011 + * Copyright 2011 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_COURSEPARSER_H__ +#define __PRACRO_COURSEPARSER_H__ + +#include "saxparser.h" +#include "template.h" + +typedef enum { + C_UNDEFINED, + C_TEMPLATE, + C_COURSE +} CourseParserState; + +class CourseParser : public SAXParser { +public: + CourseParser(std::string course); + ~CourseParser(); + + void characterData(std::string &data); + void startTag(std::string name, attributes_t &attr); + void endTag(std::string name); + void parseError(const char *buf, size_t len, std::string error, int lineno); + + Course *getCourse(); + +protected: + int readData(char *data, size_t size); + +private: + int fd; + + std::string file; + + // Parser state data + CourseParserState state; + Course *c; + + // Error callback function. + void error(const char* fmt, ...); +}; + +#endif/*__PRACRO_COURSEPARSER_H__*/ diff --git a/server/src/database.h b/server/src/database.h index 27169fe..0c28e60 100644 --- a/server/src/database.h +++ b/server/src/database.h @@ -66,7 +66,7 @@ public: mutex.lock(); DEBUG(db, "%s, %s, %s,...\n", - transaction.user.c_str(), transaction.cpr.c_str(), + transaction.user.c_str(), transaction.patientid.c_str(), macro.name.c_str()); dao->commitTransaction(sessionid, transaction, commit, macro, now); mutex.unlock(); diff --git a/server/src/environment.cc b/server/src/environment.cc index da475ce..d232174 100644 --- a/server/src/environment.cc +++ b/server/src/environment.cc @@ -33,7 +33,8 @@ Environment::Environment() : sessions(this), macrolist(Conf::xml_basedir + "/macros"), - templatelist(Conf::xml_basedir + "/templates") + templatelist(Conf::xml_basedir + "/templates"), + courselist(Conf::xml_basedir + "/courses") { for(int i = 0; i < Conf::database_poolsize; i++) { diff --git a/server/src/environment.h b/server/src/environment.h index a7b9677..7f34230 100644 --- a/server/src/environment.h +++ b/server/src/environment.h @@ -32,6 +32,7 @@ #include "artefact.h" #include "connectionpool.h" #include "session.h" +#include "courselist.h" #include "templatelist.h" #include "macrolist.h" @@ -45,6 +46,7 @@ public: Sessions sessions; MacroList macrolist; TemplateList templatelist; + CourseList courselist; }; #endif/*__PRACRO_ENVIRONMENT_H__*/ diff --git a/server/src/httpd.cc b/server/src/httpd.cc index 1d121b5..f7ad7f4 100644 --- a/server/src/httpd.cc +++ b/server/src/httpd.cc @@ -76,6 +76,8 @@ static int request_handler(void *cls, headers_t headers; headers_t getargs; + DEBUG(httpd, "URI: %s\n", url); + MHD_get_connection_values(con, MHD_HEADER_KIND, &hdit, &headers); int n = MHD_get_connection_values(con, MHD_GET_ARGUMENT_KIND, &hdit, &getargs); DEBUG(httpd, "Num args: %d\n", n); diff --git a/server/src/httpd.h b/server/src/httpd.h index 455fa35..24646fa 100644 --- a/server/src/httpd.h +++ b/server/src/httpd.h @@ -35,7 +35,13 @@ class headers_t : public std::map< std::string, std::string > { public: bool contains(std::string name) { return find(name) != end(); - } + } + + std::string lookup(std::string key, std::string defval = "") + { + if(contains(key)) return (*this)[key]; + return defval; + } }; struct MHD_Daemon; diff --git a/server/src/journal.cc b/server/src/journal.cc index c38246f..fc4203c 100644 --- a/server/src/journal.cc +++ b/server/src/journal.cc @@ -55,7 +55,7 @@ void Journal::addEntry(Transaction &transaction, Commit &commit, if(entrylist.size() == 0) { //if(user() == "") setUser(transaction.user); - if(patientID() == "")setPatientID(transaction.cpr); + if(patientID() == "") setPatientID(transaction.patientid); } DEBUG(journal, "addEntry: template(%s)\n", @@ -64,7 +64,7 @@ void Journal::addEntry(Transaction &transaction, Commit &commit, // Test if the username or the cpr has changed... // if so, commit and clear the list. #if 0 // no - it breaks things... - if(user() != transaction.user || patientID() != transaction.cpr) { + if(user() != transaction.user || patientID() != transaction.patientid) { this->commit(); entrylist.clear(); } diff --git a/server/src/luaquerymapper.cc b/server/src/luaquerymapper.cc index 56b7c1b..27dc21f 100644 --- a/server/src/luaquerymapper.cc +++ b/server/src/luaquerymapper.cc @@ -78,7 +78,7 @@ static void loadResult(lua_State *L, QueryResult &res, while(lua_gettop(L)) lua_pop(L, 1); - printf("< %d\n", lua_gettop(L)); fflush(stdout); + // printf("< %d\n", lua_gettop(L)); fflush(stdout); std::map< std::string, QueryResult >::iterator g = res.groups.begin(); while(g != res.groups.end()) { diff --git a/server/src/pracrodaopgsql.cc b/server/src/pracrodaopgsql.cc index c1a0c93..f9a773f 100644 --- a/server/src/pracrodaopgsql.cc +++ b/server/src/pracrodaopgsql.cc @@ -107,7 +107,7 @@ void PracroDAOPgsql::commitTransaction(std::string sessionid, time_t now) { DEBUG(db, "commitTransaction (%s, %s, %s, <%u fields>, %ld)\n", - transaction.user.c_str(), transaction.cpr.c_str(), + transaction.user.c_str(), transaction.patientid.c_str(), _macro.name.c_str(), commit.fields.size(), now); @@ -132,7 +132,7 @@ void PracroDAOPgsql::commitTransaction(std::string sessionid, if(!R.size()) { ts = "INSERT INTO commits (patientid, template, version," " \"timestamp\", uid, status) VALUES (" - " '" + W.esc(transaction.cpr) + "', " + " '" + W.esc(transaction.patientid) + "', " " '" + W.esc(commit.templ) + "', " " '" + "1.0" + "', " " '" + W.esc(timestamp.str()) + "', " @@ -606,7 +606,7 @@ std::string sid2 = db.newSessionId(); TEST_NOTEQUAL_STR(sid1, sid2, "Do not produce the same uid each time."); Transaction transaction; -transaction.cpr = PATIENTID; +transaction.patientid = PATIENTID; transaction.user = "me"; Commit commit; diff --git a/server/src/pracrodaotest.cc b/server/src/pracrodaotest.cc index 532877b..705d4b8 100644 --- a/server/src/pracrodaotest.cc +++ b/server/src/pracrodaotest.cc @@ -71,7 +71,7 @@ void PracroDAOTest::commitTransaction(std::string sessionid, { DEBUG(db, "(%s, %s, %s, <%u fields>, %ld)\n", transaction.user.c_str(), - transaction.cpr.c_str(), + transaction.patientid.c_str(), _macro.name.c_str(), commit.fields.size(), now); @@ -86,7 +86,7 @@ void PracroDAOTest::commitTransaction(std::string sessionid, if(ci == data.commits.end()) { DEBUG(db, "Create new commit: %s\n", sessionid.c_str()); dbrow_t c; - c["patientid"] = transaction.cpr; + c["patientid"] = transaction.patientid; c["template"] = commit.templ; c["version"] = "1.0"; c["timestamp"] = timestamp.str(); @@ -378,7 +378,7 @@ std::string sid2 = db.newSessionId(); TEST_NOTEQUAL_STR(sid1, sid2, "Do not produce the same uid each time."); Transaction transaction; -transaction.cpr = PATIENTID; +transaction.patientid = PATIENTID; transaction.user = "me"; Commit commit; diff --git a/server/src/server.cc b/server/src/server.cc index 9046594..e4d6474 100644 --- a/server/src/server.cc +++ b/server/src/server.cc @@ -63,7 +63,7 @@ public: headers["User-Agent"].find("Pracro") == std::string::npos) { // Admin connection = new AdminConnection(env, getargs, url); } else { // Pracro client - connection = new ClientConnection(env, headers); + connection = new ClientConnection(env, headers, getargs, url); } return connection; diff --git a/server/src/session.cc b/server/src/session.cc index 31c9fe8..e236416 100644 --- a/server/src/session.cc +++ b/server/src/session.cc @@ -55,11 +55,16 @@ Session::Session(Environment *e, patientid = pid; templ = t; + DEBUG(session, "[%p] new Session(sessionid: '%s', patientid: '%s'," + " template: '%s')\n", this, sid.c_str(), pid.c_str(), t.c_str()); + isreadonly = true; } Session::~Session() { + DEBUG(session, "[%p] delete Session(sessionid: '%s')\n", this, + sessionid.c_str()); if(_journal) delete _journal; } @@ -87,6 +92,9 @@ void Session::unlock() void Session::commitMacro(Transaction &transaction, Commit &commit, Macro ¯o) { + DEBUG(session, "[%p] commitMacro(sessionid: '%s')\n", this, + sessionid.c_str()); + AutoBorrower<Database*> borrower(env->dbpool); Database *db = borrower.get(); db->commitTransaction(transaction, commit, macro, id()); @@ -115,6 +123,8 @@ void Session::setIdle(bool idle) void Session::commit() { + DEBUG(session, "[%p] commit(sessionid: '%s')\n", this, sessionid.c_str()); + if(_journal != NULL) { _journal->commit(); delete _journal; @@ -129,6 +139,8 @@ void Session::commit() void Session::nocommit() { + DEBUG(session, "[%p] nocommit(sessionid: '%s')\n", this, sessionid.c_str()); + if(isreadonly == false) { AutoBorrower<Database*> borrower(env->dbpool); Database *db = borrower.get(); @@ -138,6 +150,8 @@ void Session::nocommit() void Session::discard() { + DEBUG(session, "[%p] discard(sessionid: '%s')\n", this, sessionid.c_str()); + if(_journal) { delete _journal; _journal = NULL; diff --git a/server/src/transaction.h b/server/src/transaction.h index 2cca49c..54e283b 100644 --- a/server/src/transaction.h +++ b/server/src/transaction.h @@ -35,6 +35,9 @@ class Request { public: std::string macro; std::string templ; + std::string course; + + std::string patientid; }; typedef std::vector< Request > Requests; @@ -52,10 +55,9 @@ typedef std::vector< Commit > Commits; class Transaction { public: std::string user; - std::string cpr; + std::string patientid; std::string version; - Requests requests; Commits commits; }; diff --git a/server/src/transactionhandler.cc b/server/src/transactionhandler.cc index 4b4e7ca..0821cef 100644 --- a/server/src/transactionhandler.cc +++ b/server/src/transactionhandler.cc @@ -30,6 +30,8 @@ #include "macroparser.h" #include "resumeparser.h" #include "templateparser.h" +#include "templateheaderparser.h" +#include "courseparser.h" #include "configuration.h" #include "luaquerymapper.h" #include "queryhandlerpentominos.h" @@ -83,206 +85,228 @@ static std::string handleCommits(Transaction &transaction, Environment &env, return answer; } -static std::string handleRequest(Transaction &transaction, Environment &env, +static std::string handleRequest(Request &request, Environment &env, Session &session) { std::string answer; - if(transaction.requests.size() > 0) { + if(request.course == "" && request.templ == "" && request.macro == "") + return ""; - AutoBorrower<Database*> borrower(env.dbpool); - Database *db = borrower.get(); - // Database *db = session.database(); + if(request.course != "" && request.templ == "" && request.macro == "") { + CourseParser cp(env.courselist.getLatestVersion(request.course)); + cp.parse(); + Course *course = cp.getCourse(); + answer += " <course name=\"" + course->name + "\" title=\"" + + course->title + "\">\n"; - Requests::iterator i = transaction.requests.begin(); - while(i != transaction.requests.end()) { - Request &request = *i; + std::vector< Template >::iterator ti = course->templates.begin(); + while(ti != course->templates.end()) { + std::string tname = ti->name; - DEBUG(server, "Handling request - macro: %s, template: %s\n", - request.macro.c_str(), request.templ.c_str()); - - // Read and parse the template file. - TemplateParser tp(env.templatelist.getLatestVersion(request.templ)); + TemplateHeaderParser tp(env.templatelist.getLatestVersion(tname)); tp.parse(); - Template *templ = tp.getTemplate(); - - answer += " <template name=\"" + templ->name + "\" title=\"" + - templ->title + "\">\n"; - - bool foundmacro = false; - - // Generate the macro and return it to the client - std::vector< Macro >::iterator mi2 = templ->macros.begin(); - while(mi2 != templ->macros.end()) { - Macro ¯o = (*mi2); - if(macro.isHeader) { - answer += " <header caption=\"" + macro.caption + "\"/>\n"; - mi2++; - continue; - } - - size_t oldest = time(NULL) - Conf::db_max_ttl; - if(macro.ttl != "") oldest = time(NULL) - atoi(macro.ttl.c_str()); - - bool completed = - db->checkMacro(transaction.cpr, macro.name, session.id(), oldest); + answer += " <template name=\"" + templ->name + "\" title=\"" + + templ->title + "\"/>\n"; - answer += " <macro uid=\"42\" completed="; - if(completed) answer += "\"true\""; - else answer += "\"false\""; + ti++; + } + + answer += " </course>\n"; - attributes_t attr; - attr["name"] = macro.name; - attr["version"] = macro.version; - if(macro.caption != "") attr["caption"] = macro.caption; - if(macro.requires != "") attr["requires"] = macro.requires; - attr["static"] = macro.isStatic?"true":"false"; - attr["compact"] = macro.isCompact?"true":"false"; - attr["important"] = macro.isImportant?"true":"false"; + return answer; + } - attributes_t::iterator ai = attr.begin(); - while(ai != attr.end()) { - std::string name = ai->first; - std::string value = ai->second; - answer += " "+name+"=\"" + value + "\""; - ai++; + AutoBorrower<Database*> borrower(env.dbpool); + Database *db = borrower.get(); + // Database *db = session.database(); + + DEBUG(server, "Handling request - macro: %s, template: %s\n", + request.macro.c_str(), request.templ.c_str()); + + // Read and parse the template file. + TemplateParser tp(env.templatelist.getLatestVersion(request.templ)); + tp.parse(); + + Template *templ = tp.getTemplate(); + + answer += " <template name=\"" + templ->name + "\" title=\"" + + templ->title + "\">\n"; + + bool foundmacro = false; + + // Generate the macro and return it to the client + std::vector< Macro >::iterator mi2 = templ->macros.begin(); + while(mi2 != templ->macros.end()) { + Macro ¯o = (*mi2); + + if(macro.isHeader) { + answer += " <header caption=\"" + macro.caption + "\"/>\n"; + mi2++; + continue; + } + + size_t oldest = time(NULL) - Conf::db_max_ttl; + if(macro.ttl != "") oldest = time(NULL) - atoi(macro.ttl.c_str()); + + bool completed = + db->checkMacro(request.patientid, macro.name, session.id(), + oldest); + + answer += " <macro uid=\"42\" completed="; + if(completed) answer += "\"true\""; + else answer += "\"false\""; + + attributes_t attr; + attr["name"] = macro.name; + attr["version"] = macro.version; + if(macro.caption != "") attr["caption"] = macro.caption; + if(macro.requires != "") attr["requires"] = macro.requires; + attr["static"] = macro.isStatic?"true":"false"; + attr["compact"] = macro.isCompact?"true":"false"; + attr["important"] = macro.isImportant?"true":"false"; + + attributes_t::iterator ai = attr.begin(); + while(ai != attr.end()) { + std::string name = ai->first; + std::string value = ai->second; + answer += " "+name+"=\"" + value + "\""; + ai++; + } + + if(macro.name == request.macro || macro.isStatic) { + foundmacro = true; + + MacroParser mp(env.macrolist.getLatestVersion(macro.name)); + mp.parse(); + Macro *m = mp.getMacro(); + answer += " caption=\"" + m->widgets.attributes["caption"] + "\""; + answer += ">\n"; + + AutoBorrower<Artefact*> borrower(env.atfpool); + Artefact *atf = borrower.get(); + + LUAQueryMapper lqm; + + //////////////////////// + std::vector< Query >::iterator qi = m->queries.begin(); + while(qi != m->queries.end()) { + + Query &query = *qi; + std::string service = query.attributes["service"]; + + if(service == "pentominos") { + // Send the queries to Pentominos (if any) + QueryHandlerPentominos qh(*atf, request.patientid, + "pracrod"/*user*/); + + QueryResult queryresult = qh.exec(*qi); + lqm.addQueryResult(queryresult); } - - if(macro.name == request.macro || macro.isStatic) { - foundmacro = true; - - MacroParser mp(env.macrolist.getLatestVersion(macro.name)); - mp.parse(); - Macro *m = mp.getMacro(); - answer += " caption=\"" + m->widgets.attributes["caption"] + "\""; - answer += ">\n"; - - AutoBorrower<Artefact*> borrower(env.atfpool); - Artefact *atf = borrower.get(); - - LUAQueryMapper lqm; - - //////////////////////// - std::vector< Query >::iterator qi = m->queries.begin(); - while(qi != m->queries.end()) { - - Query &query = *qi; - std::string service = query.attributes["service"]; - - if(service == "pentominos") { - // Send the queries to Pentominos (if any) - QueryHandlerPentominos qh(*atf, transaction.cpr, - "pracrod"/*user*/); - - QueryResult queryresult = qh.exec(*qi); - lqm.addQueryResult(queryresult); - } - - if(service == "pracro") { - // Send the queries to Pentominos (if any) - QueryHandlerPracro qh(*db, transaction.cpr); - - QueryResult queryresult = qh.exec(*qi); - lqm.addQueryResult(queryresult); - } - - qi++; - } - - // Handle scripts - if(m->scripts.size()) { - answer += " <scripts>\n"; - - std::vector< Script >::iterator spi = m->scripts.begin(); - while(spi != m->scripts.end()) { - // answer += " <script language=\"" + - // spi->attributes["language"] + "\">"; - answer += " <script>"; - - if(spi->attributes.find("src") != spi->attributes.end()) { - std::string file = + + if(service == "pracro") { + // Send the queries to Pentominos (if any) + QueryHandlerPracro qh(*db, request.patientid); + + QueryResult queryresult = qh.exec(*qi); + lqm.addQueryResult(queryresult); + } + + qi++; + } + + // Handle scripts + if(m->scripts.size()) { + answer += " <scripts>\n"; + + std::vector< Script >::iterator spi = m->scripts.begin(); + while(spi != m->scripts.end()) { + // answer += " <script language=\"" + + // spi->attributes["language"] + "\">"; + answer += " <script>"; + + if(spi->attributes.find("src") != spi->attributes.end()) { + std::string file = Conf::xml_basedir + "/include/" + spi->attributes["src"]; - FILE *fp = fopen(file.c_str(), "r"); - if(fp) { - char buf[64]; - size_t sz; - std::string inc; - while((sz = fread(buf, 1, sizeof(buf), fp)) != 0) { - inc.append(buf, sz); - } - fclose(fp); - answer += "\n-- BEGIN INCLUDE: '" + spi->attributes["src"] + "'\n"; - answer += xml_encode(inc); - answer += "\n-- END INCLUDE: '" + spi->attributes["src"] + "'\n"; - } - } else { - answer += xml_encode(spi->attributes["code"]); + FILE *fp = fopen(file.c_str(), "r"); + if(fp) { + char buf[64]; + size_t sz; + std::string inc; + while((sz = fread(buf, 1, sizeof(buf), fp)) != 0) { + inc.append(buf, sz); } - answer += "</script>\n"; - spi++; + fclose(fp); + answer +="\n-- BEGIN INCLUDE: '"+spi->attributes["src"]+"'\n"; + answer += xml_encode(inc); + answer +="\n-- END INCLUDE: '"+spi->attributes["src"]+"'\n"; } - - answer += " </scripts>\n"; + } else { + answer += xml_encode(spi->attributes["code"]); } - - answer += widgetgenerator(transaction.cpr, session.id(), *m, lqm, - *db, oldest); - } else { - // only find macro title - MacroParser mp(env.macrolist.getLatestVersion(macro.name)); - mp.parse(); - Macro *m = mp.getMacro(); - answer += " caption=\"" + m->widgets.attributes["caption"] + "\""; - answer += ">\n"; - + answer += "</script>\n"; + spi++; } - - if(completed) { - std::string jresume = session.journal()->getEntry(macro.name); - - std::string state = "old"; - std::string resume = db->getResume(transaction.cpr, macro, oldest, - session.id()); - if(session.journal()->dirty(macro.name)) { + + answer += " </scripts>\n"; + } + + answer += widgetgenerator(request.patientid, session.id(), *m, + lqm, *db, oldest); + } else { + // only find macro title + MacroParser mp(env.macrolist.getLatestVersion(macro.name)); + mp.parse(); + Macro *m = mp.getMacro(); + answer += " caption=\"" + m->widgets.attributes["caption"] + "\""; + answer += ">\n"; + + } + + if(completed) { + std::string jresume = session.journal()->getEntry(macro.name); + + std::string state = "old"; + std::string resume = db->getResume(request.patientid, macro, + oldest, session.id()); + if(session.journal()->dirty(macro.name)) { + state = "dirty"; + } else { + if(resume == jresume) { + state = "new"; + } else { + if(jresume != "") { state = "dirty"; + session.journal()->setDirty(macro.name); } else { - if(resume == jresume) { - state = "new"; - } else { - if(jresume != "") { - state = "dirty"; - session.journal()->setDirty(macro.name); - } else { - state = "old"; - } - } + state = "old"; } - - answer += " <resume state=\""+state+"\">"; - answer += xml_encode(resume); - answer += "</resume>\n"; } - - answer += " </macro>\n"; - mi2++; - } - if(foundmacro == false && request.macro != "") - throw NotFoundException(request); - - answer += " </template>\n"; - - i++; + answer += " <resume state=\""+state+"\">"; + answer += xml_encode(resume); + answer += "</resume>\n"; } + + answer += " </macro>\n"; + mi2++; + } + + if(foundmacro == false && request.macro != "") + throw NotFoundException(request); + + answer += " </template>\n"; return answer; } -std::string handleTransaction(Transaction &transaction, Environment &env, +std::string handleTransaction(Request &request, + Transaction &transaction, + Environment &env, Session &session) { std::string answer; @@ -298,7 +322,7 @@ std::string handleTransaction(Transaction &transaction, Environment &env, } try { - answer += handleRequest(transaction, env, session); + answer += handleRequest(request, env, session); } catch( std::exception &e ) { ERR(server, "Request error: %s\n", e.what()); return error_box(xml_encode(e.what())); diff --git a/server/src/transactionhandler.h b/server/src/transactionhandler.h index ae1857c..43ecf0b 100644 --- a/server/src/transactionhandler.h +++ b/server/src/transactionhandler.h @@ -40,6 +40,9 @@ public: : Exception("Macro " + r.macro + " not found in template " + r.templ) {} }; -std::string handleTransaction(Transaction &transaction, Environment &env, Session &session); +std::string handleTransaction(Request &resuest, + Transaction &transaction, + Environment &env, + Session &session); #endif/*__PRACRO_TRANSACTIONHANDLER_H__*/ diff --git a/server/src/transactionparser.cc b/server/src/transactionparser.cc index 142b95f..a52d797 100644 --- a/server/src/transactionparser.cc +++ b/server/src/transactionparser.cc @@ -49,17 +49,10 @@ void TransactionParser::startTag(std::string name, attributes_t &attr) if(name == "pracro") { transaction->user = attr["user"]; - transaction->cpr = attr["cpr"]; + transaction->patientid = attr["patientid"]; transaction->version = attr["version"]; } - if(name == "request") { - Request r; - r.templ = attr["template"]; - r.macro = attr["macro"]; - transaction->requests.push_back(r); - } - if(name == "commit") { Commit c; c.templ = attr["template"]; diff --git a/server/xml/courses/test.xml b/server/xml/courses/test.xml index 9dabdb9..4594409 100644 --- a/server/xml/courses/test.xml +++ b/server/xml/courses/test.xml @@ -1,4 +1,5 @@ <?xml version='1.0' encoding='UTF-8'?> <course name="test" title="Test Course" version="1.0"> <template name="test"/> + <template name="test2"/> </course> diff --git a/server/xml/macros/test_lineedit.xml b/server/xml/macros/test_lineedit.xml index d706b50..a9b510a 100644 --- a/server/xml/macros/test_lineedit.xml +++ b/server/xml/macros/test_lineedit.xml @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='UTF-8'?> <macro name="test_lineedit" version="1.0"> - <resume></resume> + <resume><script>return 'hello'..value('dims')</script></resume> <queries> <query service="pentominos" class="test" ttl="1000000"/> </queries> |