From 93500a9656dffde57ab32410642c2dd74098b9f8 Mon Sep 17 00:00:00 2001 From: deva Date: Thu, 12 Nov 2009 10:02:54 +0000 Subject: Make database connection shared among threads and make is thread safe. --- server/src/Makefile.am | 5 ++++- server/src/database.h | 31 +++++++++++++++++++++------ server/src/mutex.cc | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ server/src/mutex.h | 45 +++++++++++++++++++++++++++++++++++++++ server/src/server.cc | 23 ++++++++++++++------ 5 files changed, 148 insertions(+), 13 deletions(-) create mode 100644 server/src/mutex.cc create mode 100644 server/src/mutex.h diff --git a/server/src/Makefile.am b/server/src/Makefile.am index 3da4f19..a753ee7 100644 --- a/server/src/Makefile.am +++ b/server/src/Makefile.am @@ -23,6 +23,7 @@ pracrod_SOURCES = \ macroheaderparser.cc \ macrolist.cc \ macroparser.cc \ + mutex.cc \ pracrodao.cc \ pracrodaopgsql.cc \ pracrodaotest.cc \ @@ -58,6 +59,7 @@ macrotool_SOURCES = \ macrotool_fieldnames.cc \ macrotool_filehandler.cc \ macrotool_util.cc \ + mutex.cc \ pracrodao.cc \ pracrodaopgsql.cc \ pracrodaotest.cc \ @@ -88,6 +90,7 @@ EXTRA_DIST = \ macrotool_fieldnames.h \ macrotool_filehandler.h \ macrotool_util.h \ + mutex.h \ pracrodao.h \ pracrodaopgsql.h \ pracrodaotest.h \ @@ -140,7 +143,7 @@ BASICFLAGS = -I.. -DHAVE_CONFIG_H $(CONFIG_CXXFLAGS) $(CONFIG_LIBS) PARSERFILES = saxparser.cc PARSERFLAGS = -lexpat -DBFILES = database.cc pracrodao.cc pracrodaopgsql.cc pracrodaotest.cc +DBFILES = database.cc pracrodao.cc pracrodaopgsql.cc pracrodaotest.cc mutex.cc DBFLAGS = $(PQXX_LIBS) $(PQXX_CXXFLAGS) test: $(TESTFILES) diff --git a/server/src/database.h b/server/src/database.h index 396dda4..f253ba5 100644 --- a/server/src/database.h +++ b/server/src/database.h @@ -32,7 +32,7 @@ #include "pracrodao.h" #include "transaction.h" #include "template.h" - +#include "mutex.h" #include "debug.h" class Database { @@ -42,22 +42,31 @@ public: // Make a commit to the db void commitTransaction(std::string user, std::string patientid, Macro ¯o, Fields &fields, time_t now = time(NULL)) { + if(!dao) return; + mutex.lock(); PRACRO_DEBUG(db, "%s, %s, %s,...\n", user.c_str(), patientid.c_str(), macro.attributes["name"].c_str()); - if(dao) dao->commitTransaction(user, patientid, macro, fields, now); + dao->commitTransaction(user, patientid, macro, fields, now); + mutex.unlock(); } // Get a list of values from the db Values getValues(std::string patientid, Fieldnames &fieldnames, time_t oldest = 0) { + if(!dao) return Values(); + mutex.lock(); PRACRO_DEBUG(db, "%s, <%u fieldnames>, %ld\n", patientid.c_str(), fieldnames.size(), oldest); - if(dao) return dao->getLatestValues(patientid, NULL, fieldnames, oldest); - else return Values(); + Values values = dao->getLatestValues(patientid, NULL, fieldnames, oldest); + mutex.unlock(); + return values; } // Check if a macro has been committed. bool checkMacro(std::string patientid, std::string macro, time_t oldest = 0) { PRACRO_DEBUG(db, "%s, %s, %ld\n", patientid.c_str(), macro.c_str(), oldest); if(!dao) return false; - return dao->nrOfCommits(patientid, macro, oldest) > 0; + mutex.lock(); + bool res = dao->nrOfCommits(patientid, macro, oldest) > 0; + mutex.unlock(); + return res; } // Get latest resume of a given macro @@ -66,7 +75,9 @@ public: if(!dao) return ""; Fieldnames fn; fn.push_back("journal.resume"); + mutex.lock(); Values v = dao->getLatestValues(patientid, ¯o, fn, oldest); + mutex.unlock(); Values::iterator i = v.find("journal.resume"); if(i != v.end()) return i->second.value; else return ""; @@ -75,13 +86,17 @@ public: void addFieldname(std::string name, std::string description) { if(!dao) return; + mutex.lock(); dao->addFieldname(name, description); + mutex.unlock(); } void delFieldname(std::string name) { if(!dao) return; + mutex.lock(); dao->delFieldname(name); + mutex.unlock(); } std::vector getFieldnames() @@ -90,11 +105,15 @@ public: std::vector fieldnames; return fieldnames; } - return dao->getFieldnames(); + mutex.lock(); + std::vector fieldnames = dao->getFieldnames(); + mutex.unlock(); + return fieldnames; } private: PracroDAO *dao; + Mutex mutex; }; #endif/*__PRACRO_DATABASE_H__*/ diff --git a/server/src/mutex.cc b/server/src/mutex.cc new file mode 100644 index 0000000..2cc75cc --- /dev/null +++ b/server/src/mutex.cc @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * mutex.cc + * + * Thu Nov 12 10:51:32 CET 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 "mutex.h" + +Mutex::Mutex() +{ + pthread_mutex_init (&mutex, NULL); +} + +Mutex::~Mutex() +{ + pthread_mutex_destroy(&mutex); +} + +void Mutex::lock() +{ + pthread_mutex_lock( &mutex ); +} + +void Mutex::unlock() +{ + pthread_mutex_unlock( &mutex ); +} + +#ifdef TEST_MUTEX + +int main() +{ + return 0; +} + +#endif/*TEST_MUTEX*/ diff --git a/server/src/mutex.h b/server/src/mutex.h new file mode 100644 index 0000000..8b35042 --- /dev/null +++ b/server/src/mutex.h @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * mutex.h + * + * Thu Nov 12 10:51:32 CET 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_MUTEX_H__ +#define __PRACRO_MUTEX_H__ + +#include + +class Mutex { +public: + Mutex(); + ~Mutex(); + + void lock(); + void unlock(); + +private: + pthread_mutex_t mutex; +}; + +#endif/*__PRACRO_MUTEX_H__*/ diff --git a/server/src/server.cc b/server/src/server.cc index d9b28a9..67ae74d 100644 --- a/server/src/server.cc +++ b/server/src/server.cc @@ -60,6 +60,11 @@ #include "templatelist.h" #include "versionstr.h" +struct conn_t { + Database *db; + +}; + static std::string error_box(std::string message) { std::string errorbox = @@ -296,7 +301,7 @@ static std::string handleTransaction(Transaction *transaction, } -static std::string handleConnection(char *buf, size_t size) +static std::string handleConnection(char *buf, size_t size, struct conn_t *conn) { if(size == 0) return error_box(xml_encode("Empty document received.")); @@ -306,8 +311,6 @@ static std::string handleConnection(char *buf, size_t size) pentominos_socket.connect(Conf::pentominos_addr, Conf::pentominos_port); #endif/*WITHOUT_PENTOMINOS*/ - 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); MacroList macrolist(Conf::xml_basedir + "/macros"); @@ -322,7 +325,7 @@ static std::string handleConnection(char *buf, size_t size) PRACRO_DEBUG(server, "Got complete XML document, %d bytes in current buffer.\n", size); std::string res = handleTransaction(&transaction, pentominos_socket, - db, journalwriter, macrolist, templatelist); + *conn->db, journalwriter, macrolist, templatelist); journalwriter.commit(); return res; @@ -341,12 +344,14 @@ static int handle_request(void *cls, unsigned int *data_size, void **ptr) { + struct conn_t *conn = (struct conn_t*)cls; + PRACRO_DEBUG(httpd, "handle_request(url=\"%s\", method=\"%s\"," " version=\"%s\", data_size=\"%d\")\n", url, method, version, *data_size); - std::string reply = handleConnection((char*)data, *data_size); + std::string reply = handleConnection((char*)data, *data_size, conn); struct MHD_Response *rsp; rsp = MHD_create_response_from_data(reply.length(), (char*)reply.c_str(), MHD_NO, MHD_YES); @@ -404,6 +409,10 @@ void server() PRACRO_DEBUG(server, "Server running on port %d.\n", port); + struct conn_t conn; + conn.db = new Database(Conf::database_backend, Conf::database_addr, + "", Conf::database_user, Conf::database_passwd, ""); + struct MHD_Daemon *d; d = MHD_start_daemon(MHD_USE_DEBUG | MHD_USE_SELECT_INTERNALLY @@ -412,7 +421,7 @@ void server() , port, NULL, NULL, - handle_request, NULL, + handle_request, &conn, MHD_OPTION_NOTIFY_COMPLETED, NULL, NULL, // MHD_OPTION_CONNECTION_LIMIT, 42, MHD_OPTION_HTTPS_MEM_KEY, KEY, @@ -428,6 +437,8 @@ void server() while(pracro_is_running) sleep(1); + delete conn.db; + MHD_stop_daemon(d); PRACRO_DEBUG(server, "Server gracefully shut down.\n"); -- cgit v1.2.3