/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set et sw=2 ts=2: */ /*************************************************************************** * connectionpool.cc * * Wed Dec 16 12:20:44 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 "connectionpool.h" ConnectionPool::ConnectionPool() { } void ConnectionPool::addDatabase(Database *db) { mutex.lock(); passivedbs.push_back(db); semaphore.post(); mutex.unlock(); } static inline bool contains(std::list list, Database *db) { std::list::iterator i = list.begin(); while(i != list.end()) { if(*i == db) return true; i++; } return false; } void ConnectionPool::removeDatabase(Database *db) { mutex.lock(); if(contains(passivedbs, db)) { semaphore.post(); passivedbs.remove(db); } mutex.unlock(); } bool ConnectionPool::testFree(Database *db) { bool testfree = false; mutex.lock(); testfree = contains(passivedbs, db); mutex.unlock(); return testfree; } int ConnectionPool::numFreeDatabases() { int num; mutex.lock(); num = passivedbs.size(); mutex.unlock(); return num; } #include Database *ConnectionPool::borrowDatabase() { Database *db = NULL; semaphore.wait(); mutex.lock(); db = passivedbs.front(); passivedbs.remove(db); activedbs.push_back(db); mutex.unlock(); return db; } void ConnectionPool::returnDatabase(Database *db) { mutex.lock(); if(contains(activedbs, db)) { activedbs.remove(db); passivedbs.push_back(db); semaphore.post(); } mutex.unlock(); } AutoBorrower::AutoBorrower(ConnectionPool &p) : pool(p) { _db = pool.borrowDatabase(); } AutoBorrower::~AutoBorrower() { pool.returnDatabase(_db); } Database *AutoBorrower::db() { return _db; } #ifdef TEST_CONNECTIONPOOL //deps: mutex.cc semaphore.cc //cflags: //libs: -lpthread #include #include #include static void* thread_run(void *data) { ConnectionPool *pool = (ConnectionPool*)data; Database *db1 = pool->borrowDatabase(); Database *db2 = pool->borrowDatabase(); Database *db3 = pool->borrowDatabase(); Database *db4 = pool->borrowDatabase(); usleep(100); pool->returnDatabase(db1); pool->returnDatabase(db2); pool->returnDatabase(db3); pool->returnDatabase(db4); return NULL; } TEST_BEGIN; ConnectionPool pool; Database *db1 = (Database*)1; Database *db2 = (Database*)2; Database *db3 = (Database*)3; Database *db4 = (Database*)4; pool.addDatabase(db1); pool.addDatabase(db2); pool.addDatabase(db3); pool.addDatabase(db4); TEST_TRUE(pool.testFree(db1), "Testing if db1 is free."); TEST_TRUE(pool.testFree(db2), "Testing if db2 is free."); TEST_TRUE(pool.testFree(db3), "Testing if db3 is free."); TEST_TRUE(pool.testFree(db4), "Testing if db4 is free."); TEST_EQUAL(pool.numFreeDatabases(), 4, "Testing number of free databases."); Database *b_db1 = pool.borrowDatabase(); TEST_FALSE(pool.testFree(b_db1), "Testing if borrowed db is free."); Database *b_db2 = pool.borrowDatabase(); TEST_NOTEQUAL(b_db1, b_db2, "Testing if borrowed db is unique."); pool.returnDatabase(b_db1); TEST_TRUE(pool.testFree(b_db1), "Testing if returned db is free."); pool.returnDatabase(b_db2); TEST_EQUAL(pool.numFreeDatabases(), 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.numFreeDatabases() > 0) { usleep(10); } Database *b_db3 = pool.borrowDatabase(); TEST_FALSE(pool.testFree(b_db3), "Testing if returned db is free (semaphore test)."); pool.returnDatabase(db3); pthread_join(tid, NULL); pthread_attr_destroy(&attr); TEST_EQUAL(pool.numFreeDatabases(), 4, "Testing if all database are now available again"); { TEST_EQUAL(pool.numFreeDatabases(), 4, "Testing if autoborrower has not yet borrowed a db."); AutoBorrower b(pool); TEST_EQUAL(pool.numFreeDatabases(), 3, "Testing if autoborrower has borrowed a db."); TEST_FALSE(pool.testFree(b.db()), "Testing if the autoborrowed db is actually taken."); } TEST_EQUAL(pool.numFreeDatabases(), 4, "Testing if autoborrower has returned the db."); TEST_END; #endif/*TEST_CONNECTIONPOOL*/