diff options
Diffstat (limited to 'server/src')
| -rw-r--r-- | server/src/Makefile.am | 20 | ||||
| -rw-r--r-- | server/src/configuration.cc | 1 | ||||
| -rw-r--r-- | server/src/configuration.h | 1 | ||||
| -rw-r--r-- | server/src/configurationparser.cc | 6 | ||||
| -rw-r--r-- | server/src/database.cc | 5 | ||||
| -rw-r--r-- | server/src/pracrod.cc | 13 | ||||
| -rw-r--r-- | server/src/pracrodaotest.cc | 336 | ||||
| -rw-r--r-- | server/src/pracrodaotest.h | 93 | ||||
| -rw-r--r-- | server/src/server.cc | 2 | 
9 files changed, 475 insertions, 2 deletions
| diff --git a/server/src/Makefile.am b/server/src/Makefile.am index 3bc3069..399d7fa 100644 --- a/server/src/Makefile.am +++ b/server/src/Makefile.am @@ -25,6 +25,7 @@ pracrod_SOURCES = \  	macroparser.cc \  	pracrodao.cc \  	pracrodaopgsql.cc \ +	pracrodaotest.cc \  	resumeparser.cc \  	saxparser.cc \  	server.cc \ @@ -59,6 +60,7 @@ macrotool_SOURCES = \  	macrotool_util.cc \  	pracrodao.cc \  	pracrodaopgsql.cc \ +	pracrodaotest.cc \  	saxparser.cc \  	templateparser.cc \  	versionstr.cc @@ -88,6 +90,7 @@ EXTRA_DIST = \  	macrotool_util.h \  	pracrodao.h \  	pracrodaopgsql.h \ +	pracrodaotest.h \  	resumeparser.h \  	saxparser.h \  	server.h \ @@ -106,6 +109,8 @@ EXTRA_DIST = \  ################  TESTFILES = \ +	test_pracrodaotest \ +	test_widgetgenerator \  	test_configurationparser \  	test_exception \  	test_templateheaderparser \ @@ -143,6 +148,21 @@ test: $(TESTFILES)  test_clean:  	rm -f $(TESTFILES) $(TESTLOGS) +TEST_PRACRODAOTEST_FILES = \ +	pracrodaotest.cc \ +	pracrodao.cc \ +	$(BASICFILES) +test_pracrodaotest: $(TEST_PRACRODAOTEST_FILES) +	@../../tools/test $(TEST_PRACRODAOTEST_FILES) $(BASICFLAGS) + +TEST_WIDGETGENERATOR_FILES = \ +	widgetgenerator.cc \ +	xml_encode_decode.cc \ +	luaquerymapper.cc \ +	$(BASICFILES) +test_widgetgenerator: $(TEST_WIDGETGENERATOR_FILES) +	@../../tools/test $(TEST_WIDGETGENERATOR_FILES) $(BASICFLAGS) $(LUA_LIBS) +  TEST_CONFIGURATIONPARSER_FILES = \  	configurationparser.cc \  	configuration.cc \ diff --git a/server/src/configuration.cc b/server/src/configuration.cc index c921da6..c1dcab1 100644 --- a/server/src/configuration.cc +++ b/server/src/configuration.cc @@ -41,6 +41,7 @@ time_t Conf::pentominos_max_ttl = 7 * 60 * 60 * 24;  std::string Conf::pentominos_addr = "localhost";  port_t Conf::pentominos_port = 11108; +std::string Conf::database_backend = "pgsql";  std::string Conf::database_addr = "localhost";  std::string Conf::database_user = "pracro";  std::string Conf::database_passwd = "pracro"; diff --git a/server/src/configuration.h b/server/src/configuration.h index 56a2f0e..3d9f7f1 100644 --- a/server/src/configuration.h +++ b/server/src/configuration.h @@ -48,6 +48,7 @@ namespace Conf {    extern std::string pentominos_addr;    extern port_t pentominos_port; +  extern std::string database_backend;    extern std::string database_addr;    extern std::string database_user;    extern std::string database_passwd; diff --git a/server/src/configurationparser.cc b/server/src/configurationparser.cc index a3e7532..8247a45 100644 --- a/server/src/configurationparser.cc +++ b/server/src/configurationparser.cc @@ -105,6 +105,12 @@ void ConfigurationParser::reload()    }    try { +    std::string a = lookup("database_backend"); +    Conf::database_backend = a; +  } catch( ... ) { +  } + +  try {      std::string a = lookup("database_addr");      Conf::database_addr = a;    } catch( ... ) { diff --git a/server/src/database.cc b/server/src/database.cc index 5a03126..9a4905b 100644 --- a/server/src/database.cc +++ b/server/src/database.cc @@ -32,6 +32,7 @@  #include "debug.h"  #include "pracrodaopgsql.h" +#include "pracrodaotest.h"  Database::Database(std::string _backend, std::string _host, std::string _port, std::string _user, std::string _passwd, std::string _dbname)  { @@ -42,6 +43,10 @@ Database::Database(std::string _backend, std::string _host, std::string _port, s      dao = new PracroDAOPgsql(_host, _port, _user, _passwd, _dbname);    }  #endif/*WITHOUT_DB*/ +  if(_backend == "testdb") { +    Data data; +    dao = new PracroDAOTest(data, true); +  }  }  Database::~Database() diff --git a/server/src/pracrod.cc b/server/src/pracrod.cc index a929f63..75f58a6 100644 --- a/server/src/pracrod.cc +++ b/server/src/pracrod.cc @@ -88,6 +88,7 @@ static const char usage_str[] =  "  -v, --version       Print version information and exit.\n"  "  -h, --help          Print this message and exit.\n"  "  -D, --debug ddd     Enable debug messages on 'ddd'; see documentation for details\n" +"  -d  --database db   Use db as the database backend. Can be one of pgsql or testdb (default pgsql).\n"  ;  ConfigurationParser *configparser = NULL; @@ -145,6 +146,7 @@ int main(int argc, char *argv[])    bool foreground = false;    char *xml_basedir = NULL;    char *debugstr = NULL; +  std::string database;    pracro_debug_init(); @@ -160,15 +162,20 @@ int main(int argc, char *argv[])        {"version", no_argument, 0, 'v'},        {"xml-basedir", required_argument, 0, 'x'},        {"debug", required_argument, 0, 'D'}, +      {"database", required_argument, 0, 'd'},        {0, 0, 0, 0}      }; -    c = getopt_long (argc, argv, "D:hvfc:u:g:x:", long_options, &option_index); +    c = getopt_long (argc, argv, "D:hvfc:u:g:x:d:", long_options, &option_index);      if (c == -1)        break;      switch(c) { +    case 'd': +      database = optarg; +      break; +      case 'c':        configfile = strdup(optarg);        break; @@ -217,6 +224,10 @@ int main(int argc, char *argv[])    if(configfile) configparser = new ConfigurationParser(configfile);    else configparser = new ConfigurationParser(ETC"/pracrod.conf"); +  if(database != "") { +    Conf::database_backend = database; +  } +    if(!user) {      user = strdup(Conf::server_user.c_str());    } diff --git a/server/src/pracrodaotest.cc b/server/src/pracrodaotest.cc new file mode 100644 index 0000000..c084e5b --- /dev/null +++ b/server/src/pracrodaotest.cc @@ -0,0 +1,336 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + *            pracrodaotest.cc + * + *  Fri Aug  7 10:25:07 CEST 2009 + *  Copyright 2009 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 "pracrodaotest.h" + +#include <stdlib.h> +#include <sstream> + +#include "debug.h" + +PracroDAOTest::PracroDAOTest(Data &data, bool ignore_fieldnames) +  : PracroDAO("", "", "", "", "") +{ +  this->data = data; +  this->ignore_fieldnames = ignore_fieldnames; +  PRACRO_DEBUG(db, "New test (memory only) database\n"); +} + +PracroDAOTest::~PracroDAOTest() +{ +  PRACRO_DEBUG(db, "Delete test (memory only) database\n"); +} + +void PracroDAOTest::commitTransaction(std::string user, std::string patientid, +                                      Macro &_macro, Fields &fields, time_t now) +{ +  PRACRO_DEBUG(db, "(%s, %s, %s, <%u fields>, %ld)\n", +               user.c_str(), +               patientid.c_str(), +               _macro.attributes["name"].c_str(), +               fields.size(), +               now); +  if(fields.size() == 0) return; + +  std::string version = _macro.attributes["version"]; +  std::string macro = _macro.attributes["name"]; +  std::stringstream timestamp; timestamp << now; + +  dbrow_t t; +  t["uid"] = data.trseq.nextval(); +  t["patientid"] = patientid; +  t["macro"] = macro; +  t["version"] = version; +  t["timestamp"] = timestamp.str(); +  t["user"] = user; +  data.transactions.push_back(t); + +  // Iterate fields... +  Fields::iterator fi = fields.begin(); +  while(fi != fields.end()) { +     +    if(ignore_fieldnames == false) { +      // Search for it in fieldnames table +      dbtable_t::iterator ti = data.fieldnames.begin(); +      while(ti != data.fieldnames.end()) { +         +        // If found, insert the field values into the fields table. +        if(fi->first == (*ti)["name"]) { +           +          dbrow_t f; +          f["transaction"] = data.trseq.currval(); +          f["name"] = fi->first; +          f["value"] = fi->second; +          data.fields.push_back(f); +           +        } +         +        ti++; +      } +    } else { +      dbrow_t f; +      f["transaction"] = data.trseq.currval(); +      f["name"] = fi->first; +      f["value"] = fi->second; +      data.fields.push_back(f); +    } +     +    fi++; +  } +} + +Values PracroDAOTest::getLatestValues(std::string patientid, Macro *macro, +                                      Fieldnames &fieldnames, time_t oldest) +{ +  PRACRO_DEBUG(db, "(%s, %s, <%u fieldnames>, %ld)\n", +               patientid.c_str(), +               macro ? macro->attributes["name"].c_str() : "(null)", fieldnames.size(), +               oldest); +  Values values; + +  // TODO: Take Macro* into account. If supplied (not NULL) the macro name, and +  //  optionally version number should match the transaction. + +  Fieldnames::iterator fi = fieldnames.begin(); +  while(fi != fieldnames.end()) { +    std::string fieldname = *fi; + +    // Find matching transactions +    dbtable_t::iterator ti = data.transactions.begin(); +    while(ti != data.transactions.end()) { +      std::map<std::string, std::string> &transaction = *ti; +      time_t timestamp = atol(transaction["timestamp"].c_str()); +      if(transaction["patientid"] == patientid && timestamp >= oldest) { +        std::string tid = transaction["uid"]; + +        // Find transaction values +        dbtable_t::iterator vi = data.fields.begin(); +        while(vi != data.fields.end()) { +          std::map<std::string, std::string> &field = *vi; +           +          // Upon match, insert it into values +          if(field["transaction"] == tid && field["name"] == fieldname) { +            if(values.find(fieldname) == values.end() || values[fieldname].timestamp < timestamp) { +              values[fieldname].timestamp = timestamp; +              values[fieldname].value = field["value"]; +              values[fieldname].source = "testdb"; +            } +          } +          vi++; +        } +     +      } +      ti++; +    } +     +    fi++; +  } + +  return values; +} + + +unsigned PracroDAOTest::nrOfCommits(std::string patientid, std::string macroname, time_t oldest) +{ +  unsigned num = 0; + +  // Find and count matching transactions +  dbtable_t::iterator ti = data.transactions.begin(); +  while(ti != data.transactions.end()) { +    std::map<std::string, std::string> &transaction = *ti; +    time_t timestamp = atol(transaction["timestamp"].c_str()); +    if(transaction["patientid"] == patientid && +       transaction["macro"] == macroname && +       timestamp >= oldest) { +      num++; +    } +    ti++; +  } + +  return num; +} + +void PracroDAOTest::addFieldname(std::string name, std::string description) +{ +  // TODO +   +  /* +  std::stringstream timestamp; timestamp << time(NULL); +  std::string ts; +  try { +    pqxx::work W(*conn); +    ts = "INSERT INTO fieldnames (name, description, \"timestamp\") VALUES (" +      " '" + W.esc(name) + "', " +      " '" + W.esc(description) + "', " +      " '" + W.esc(timestamp.str()) + "' " +      ")" +      ; +    PRACRO_DEBUG(sql, "Query: %s\n", ts.c_str()); +    pqxx::result R = W.exec(ts); +    W.commit(); +  } catch (std::exception &e) { +    PRACRO_ERR_LOG(db, "Query failed: %s: %s\n", e.what(), ts.c_str()); +  } +  */ +} + +void PracroDAOTest::delFieldname(std::string name) +{ +  // TODO + +  /* +  std::string ts; +  try { +    pqxx::work W(*conn); +    ts = "DELETE FROM fieldnames WHERE name=" +      "'" + W.esc(name) + "' "; +    PRACRO_DEBUG(sql, "Query: %s\n", ts.c_str()); +    pqxx::result R = W.exec(ts); +    W.commit(); +  } catch (std::exception &e) { +    PRACRO_ERR_LOG(db, "Query failed: %s: %s\n", e.what(), ts.c_str()); +  } +  */ +} + +std::vector<Fieldname> PracroDAOTest::getFieldnames() +{ +  // TODO + +  std::vector<Fieldname> fieldnames; +  /* +  std::string query; +  try { +    pqxx::work W(*conn); +    query = "SELECT * FROM fieldnames"; +    PRACRO_DEBUG(sql, "Query: %s\n", query.c_str()); +    pqxx::result R = W.exec(query); +    pqxx::result::const_iterator ri = R.begin(); +    while(ri != R.end()) { +      Fieldname f; +      f.name = (*ri)[0].c_str(); +      f.description = (*ri)[1].c_str(); +      f.timestamp = atol((*ri)[2].c_str()); +      fieldnames.push_back(f); +      ri++; +    } +  } catch (std::exception &e) { +    PRACRO_ERR_LOG(db, "Query failed: %s: %s\n", e.what(), query.c_str()); +  } +  */ +  return fieldnames; +} + + + + +#ifdef TEST_PRACRODAOTEST + +#define PATIENTID "1234567890" + +int main() +{ +  time_t now = time(NULL); + +  Data data; + +  // Add some fieldnames +  dbrow_t f; +  f["name"] = "field1"; data.fieldnames.push_back(f); +  f["name"] = "field2"; data.fieldnames.push_back(f); +  f["name"] = "field3"; data.fieldnames.push_back(f); + +  PracroDAOTest db(data); + +  // Make a commit +  Macro macro; +  macro.attributes["version"] = "1.0"; +  macro.attributes["name"] = "testmacro"; + +  Fields fields; +  fields["field1"] = "testval1"; +  fields["field2"] = "testval2"; +  fields["field3"] = "testval3"; +  fields["field4"] = "testval4"; +  db.commitTransaction("testuser", PATIENTID, macro, fields, now); + +  // Retrieve the data again +  unsigned num = db.nrOfCommits(PATIENTID, "testmacro", now); +  if(num != 1) return 1; + +  Fieldnames fieldnames; +  fieldnames.push_back("field1"); +  fieldnames.push_back("field2"); +  fieldnames.push_back("field3"); +  fieldnames.push_back("field4"); +  Values values = db.getLatestValues(PATIENTID, NULL, fieldnames, now); + +  Values::iterator i = values.begin(); +  while(i != values.end()) { +    printf("%s => %s\n", i->first.c_str(), i->second.value.c_str()); +    i++; +  } +  if(values["field1"].value != "testval1") return 1; +  if(values["field2"].value != "testval2") return 1; +  if(values["field3"].value != "testval3") return 1; + +  // This value was not committed, since it wasn't in the fieldnames table. +  if(values.find("field4") != values.end()) return 1; + +  // Make another commit (one second later) +  fields["field1"] = "testval1-2"; +  fields["field2"] = "testval2-2"; +  fields["field3"] = "testval3-2"; +  fields["field4"] = "testval4-2"; +  db.commitTransaction("testuser", PATIENTID, macro, fields, now+1); + +  // Retrieve the data again +  num = db.nrOfCommits(PATIENTID, "testmacro", now); +  if(num != 2) return 1; + +  fieldnames.push_back("field1"); +  fieldnames.push_back("field2"); +  fieldnames.push_back("field3"); +  fieldnames.push_back("field4"); +  values = db.getLatestValues(PATIENTID, NULL, fieldnames, now); + +  i = values.begin(); +  while(i != values.end()) { +    printf("%s => %s\n", i->first.c_str(), i->second.value.c_str()); +    i++; +  } +  if(values["field1"].value != "testval1-2") return 1; +  if(values["field2"].value != "testval2-2") return 1; +  if(values["field3"].value != "testval3-2") return 1; + +  // This value was not committed, since it wasn't in the fieldnames table. +  if(values.find("field4") != values.end()) return 1; + +  return 0; +} + +#endif/*TEST_PRACRODAOTEST*/ diff --git a/server/src/pracrodaotest.h b/server/src/pracrodaotest.h new file mode 100644 index 0000000..8dd4655 --- /dev/null +++ b/server/src/pracrodaotest.h @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + *            pracrodaotest.h + * + *  Fri Aug  7 10:25:07 CEST 2009 + *  Copyright 2009 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_PRACRODAOTEST_H__ +#define __PRACRO_PRACRODAOTEST_H__ + +#include <string> +#include <vector> +#include <map> + +#include <config.h> + +#include "pracrodao.h" + +typedef std::map<std::string, std::string> dbrow_t;  +typedef std::vector< dbrow_t > dbtable_t; + +class dbcounter_t { +public: +  dbcounter_t() +  { +    counter = 0; +  } + +  std::string nextval() +  { +    counter++; +    return currval(); +  } + +  std::string currval() +  { +    char buf[32]; +    sprintf(buf, "%d", counter); +    return buf; +  } + +private: +  size_t counter; +}; + +class Data { +public: +  dbcounter_t trseq; +  dbtable_t transactions; +  dbtable_t fieldnames; +  dbtable_t fields; +}; + +class PracroDAOTest : public PracroDAO +{ +public: +  PracroDAOTest(Data &data, bool ignore_fieldnames = false); +  ~PracroDAOTest(); + +  void commitTransaction(std::string user, std::string patientid, Macro ¯o, Fields &fields, time_t now); +  Values getLatestValues(std::string patientid, Macro *macro, Fieldnames &fieldnames, time_t oldest); +  unsigned nrOfCommits(std::string patientid, std::string macroname, time_t oldest); + +  void addFieldname(std::string name, std::string description); +  void delFieldname(std::string name); +  std::vector<Fieldname> getFieldnames(); + +private:  +  Data data; +  bool ignore_fieldnames; +}; + +#endif/*__PRACRO_PRACRODAOTEST_H__*/ diff --git a/server/src/server.cc b/server/src/server.cc index d0e9524..a47eb28 100644 --- a/server/src/server.cc +++ b/server/src/server.cc @@ -299,7 +299,7 @@ static void handleConnection(TCPSocket *socket)    pentominos_socket.connect(Conf::pentominos_addr, Conf::pentominos_port);  #endif/*WITHOUT_PENTOMINOS*/ -  Database db("pgsql", Conf::database_addr, "", Conf::database_user, Conf::database_passwd, ""); +  Database db(Conf::database_backend, Conf::database_addr, "", Conf::database_user, Conf::database_passwd, "");    JournalWriter journalwriter(Conf::journal_commit_addr.c_str(), Conf::journal_commit_port); | 
