diff --git a/include/MySqlDB.h b/include/MySqlDB.h index 5e4643abaf..d9059190c3 100644 --- a/include/MySqlDB.h +++ b/include/MySqlDB.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -77,9 +78,19 @@ public: private: /** - * The MySql connection handler + * Number of concurrent DB connections. */ - MYSQL * db; + static const int DB_CONNECT_SIZE; + + /** + * The MySql connection pool handler + */ + queue db_connect; + + /** + * Cached DB connection to escape strings (it uses the server character set) + */ + MYSQL * db_escape_connect; /** * MySQL Connection parameters @@ -95,25 +106,24 @@ private: string database; /** - * Fine-grain mutex for DB access + * Fine-grain mutex for DB access (pool of DB connections) */ - pthread_mutex_t mutex; + pthread_mutex_t mutex; /** - * Function to lock the DB + * Conditional variable to wake-up waiting threads. */ - void lock() - { - pthread_mutex_lock(&mutex); - }; + pthread_cond_t cond; /** - * Function to unlock the DB + * Gets a free DB connection from the pool. */ - void unlock() - { - pthread_mutex_unlock(&mutex); - }; + MYSQL * get_db_connection(); + + /** + * Returns the connection to the pool. + */ + void free_db_connection(MYSQL * db); }; #else //CLass stub diff --git a/src/nebula/Nebula.cc b/src/nebula/Nebula.cc index 926e6c91ec..45c64c373f 100644 --- a/src/nebula/Nebula.cc +++ b/src/nebula/Nebula.cc @@ -454,22 +454,6 @@ void Nebula::start() ostringstream oss; db = new MySqlDB(server,port,user,passwd,db_name); - - oss << "CREATE DATABASE IF NOT EXISTS " << db_name; - rc = db->exec(oss); - - if ( rc != 0 ) - { - throw runtime_error("Could not create database."); - } - - oss.str(""); - oss << "USE " << db_name; - rc = db->exec(oss); - if ( rc != 0 ) - { - throw runtime_error("Could not open database."); - } } // --------------------------------------------------------------------- diff --git a/src/sql/MySqlDB.cc b/src/sql/MySqlDB.cc index 5fb1b228bc..652b799af8 100644 --- a/src/sql/MySqlDB.cc +++ b/src/sql/MySqlDB.cc @@ -21,6 +21,8 @@ * Doc: http://dev.mysql.com/doc/refman/5.5/en/c-api-function-overview.html ********/ +const int MySqlDB::DB_CONNECT_SIZE = 10; + /* -------------------------------------------------------------------------- */ MySqlDB::MySqlDB( @@ -30,6 +32,11 @@ MySqlDB::MySqlDB( const string& _password, const string& _database) { + vector connections(DB_CONNECT_SIZE); + MYSQL * rc; + + ostringstream oss; + server = _server; port = _port; user = _user; @@ -39,30 +46,88 @@ MySqlDB::MySqlDB( // Initialize the MySQL library mysql_library_init(0, NULL, NULL); - // Initialize a connection handler - db = mysql_init(NULL); - - // Connect to the server - if (!mysql_real_connect(db, server.c_str(), user.c_str(), - password.c_str(), 0, port, NULL, 0)) + // Create connection pool to the server + for (int i=0 ; i < DB_CONNECT_SIZE ; i++) { - throw runtime_error("Could not open database."); + connections[i] = mysql_init(NULL); + + rc = mysql_real_connect(connections[i], + server.c_str(), + user.c_str(), + password.c_str(), + 0, + port, + NULL, + 0); + if ( rc == NULL) + { + throw runtime_error("Could not open connect to database server."); + } + } + + db_escape_connect = mysql_init(NULL); + + rc = mysql_real_connect(db_escape_connect, + server.c_str(), + user.c_str(), + password.c_str(), + 0, + port, + NULL, + 0); + + if ( rc == NULL) + { + throw runtime_error("Could not open connect to database server."); + } + + //Connect to the database & initialize connection pool + oss << "CREATE DATABASE IF NOT EXISTS " << database; + + if ( mysql_query(connections[0], oss.str().c_str()) != 0 ) + { + throw runtime_error("Could not create the database."); + } + + oss.str(""); + oss << "USE " << database; + + for (int i=0 ; i < DB_CONNECT_SIZE ; i++) + { + if ( mysql_query(connections[i], oss.str().c_str()) != 0 ) + { + throw runtime_error("Could not connect to the database."); + } + + db_connect.push(connections[i]); } pthread_mutex_init(&mutex,0); + + pthread_cond_init(&cond,0); } /* -------------------------------------------------------------------------- */ MySqlDB::~MySqlDB() { - // Close the connection to the MySQL server - mysql_close(db); + // Close the connections to the MySQL server + while (!db_connect.empty()) + { + MYSQL * db = db_connect.front(); + db_connect.pop(); + + mysql_close(db); + } + + mysql_close(db_escape_connect); // End use of the MySQL library mysql_library_end(); pthread_mutex_destroy(&mutex); + + pthread_cond_destroy(&cond); } /* -------------------------------------------------------------------------- */ @@ -77,7 +142,9 @@ int MySqlDB::exec(ostringstream& cmd, Callbackable* obj) str = cmd.str(); c_str = str.c_str(); - lock(); + MYSQL *db; + + db = get_db_connection(); rc = mysql_query(db, c_str); @@ -111,7 +178,7 @@ int MySqlDB::exec(ostringstream& cmd, Callbackable* obj) NebulaLog::log("ONE",Log::ERROR,oss); - unlock(); + free_db_connection(db); return -1; } @@ -139,7 +206,7 @@ int MySqlDB::exec(ostringstream& cmd, Callbackable* obj) NebulaLog::log("ONE",Log::ERROR,oss); - unlock(); + free_db_connection(db); return -1; } @@ -167,7 +234,7 @@ int MySqlDB::exec(ostringstream& cmd, Callbackable* obj) delete[] names; } - unlock(); + free_db_connection(db); return 0; } @@ -178,7 +245,7 @@ char * MySqlDB::escape_str(const string& str) { char * result = new char[str.size()*2+1]; - mysql_real_escape_string(db, result, str.c_str(), str.size()); + mysql_real_escape_string(db_escape_connect, result, str.c_str(), str.size()); return result; } @@ -191,3 +258,38 @@ void MySqlDB::free_str(char * str) } /* -------------------------------------------------------------------------- */ + +MYSQL * MySqlDB::get_db_connection() +{ + MYSQL *db; + + pthread_mutex_lock(&mutex); + + while ( db_connect.empty() == true ) + { + pthread_cond_wait(&cond, &mutex); + } + + db = db_connect.front(); + + db_connect.pop(); + + pthread_mutex_unlock(&mutex); + + return db; +} + +/* -------------------------------------------------------------------------- */ + +void MySqlDB::free_db_connection(MYSQL * db) +{ + pthread_mutex_lock(&mutex); + + db_connect.push(db); + + pthread_cond_signal(&cond); + + pthread_mutex_unlock(&mutex); +} + +/* -------------------------------------------------------------------------- */