1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-22 13:33:52 +03:00

feature #206: OpenNebula can now be compiled with several DB backends

This commit is contained in:
Ruben S. Montero 2010-05-07 14:45:27 +02:00
parent 1b9ada2f8d
commit a8905b2704
7 changed files with 444 additions and 254 deletions

View File

@ -39,6 +39,7 @@ main_env.Append(CPPPATH=[
# Library dirs
main_env.Append(LIBPATH=[
cwd+'/src/common',
cwd+'/src/sql',
cwd+'/src/host',
cwd+'/src/mad',
cwd+'/src/nebula',
@ -70,18 +71,27 @@ main_env.Append(LDFLAGS=["-g"])
#######################
# SQLITE
sqlite_dir=ARGUMENTS.get('sqlite', 'none')
sqlite_dir=ARGUMENTS.get('sqlite_dir', 'none')
if sqlite_dir!='none':
main_env.Append(LIBPATH=[sqlite_dir+"/lib"])
main_env.Append(CPPPATH=[sqlite_dir+"/include"])
sqlite=ARGUMENTS.get('sqlite', 'yes')
if sqlite=='yes':
main_env.Append(sqlite='yes')
main_env.Append(CPPFLAGS=["-DSQLITE_DB"])
else:
main_env.Append(sqlite='no')
# MySQL
mysql=ARGUMENTS.get('mysql', 'no')
if mysql=='yes':
main_env.Append(mysql='yes')
main_env.Append(CPPFLAGS=["-DMYSQL_DB"])
else:
main_env.Append(mysql='no')
# xmlrpc
xmlrpc_dir=ARGUMENTS.get('xmlrpc', 'none')
if xmlrpc_dir!='none':
@ -99,10 +109,10 @@ if not main_env.GetOption('clean'):
try:
main_env.ParseConfig('share/scons/get_xmlrpc_config server')
main_env.ParseConfig('share/scons/get_xmlrpc_config client')
if mysql=='yes':
main_env.ParseConfig('mysql_config --cflags --libs')
except Exception, e:
print ""
print "Error searching for xmlrpc-c libraries. Please check this"+\
@ -130,6 +140,7 @@ else:
# SCONS scripts to build
build_scripts=[
'src/client/SConstruct',
'src/sql/SConstruct',
'src/common/SConstruct',
'src/template/SConstruct',
'src/host/SConstruct',
@ -143,7 +154,7 @@ build_scripts=[
'src/tm/SConstruct',
'src/im/SConstruct',
'src/dm/SConstruct',
'src/scheduler/SConstruct',
# 'src/scheduler/SConstruct',
'src/vnm/SConstruct',
'src/hm/SConstruct',
'src/um/SConstruct',

View File

@ -20,7 +20,6 @@
#include <string>
#include <sstream>
#include <stdexcept>
#include <mysql.h>
#include <sys/time.h>
#include <sys/types.h>
@ -30,11 +29,12 @@
#include "SqlDB.h"
#include "ObjectSQL.h"
using namespace std;
/*********
* Doc: http://dev.mysql.com/doc/refman/5.5/en/c-api-function-overview.html
********/
#ifdef MYSQL_DB
#include <mysql.h>
/**
* SqliteDB class. Provides a wrapper to the mysql database interface.
@ -43,37 +43,12 @@ class MySqlDB : public SqlDB
{
public:
MySqlDB(
string server,
string user,
string password,
char * database)
{
MySqlDB(const string& server,
const string& user,
const string& password,
char * database);
// 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(), database, 0, NULL, 0))
{
throw runtime_error("Could not open database.");
}
pthread_mutex_init(&mutex,0);
};
~MySqlDB()
{
// Close the connection to the MySQL server
mysql_close(db);
// End use of the MySQL library
mysql_library_end();
};
~MySqlDB();
/**
* Wraps the mysql_query function call
@ -81,97 +56,7 @@ public:
* @param obj Callbackable obj to call if the query succeeds
* @return 0 on success
*/
int exec(ostringstream& cmd, Callbackable* obj=0)
{
int rc;
const char * c_str;
string str;
int (*callback)(void*,int,char**,char**);
void * arg;
str = cmd.str();
c_str = str.c_str();
callback = 0;
arg = 0;
lock();
rc = mysql_query(db, c_str);
if (rc != 0)
{
ostringstream oss;
const char * err_msg = mysql_error(db);
int err_num = mysql_errno(db);
oss << "SQL command was: " << c_str;
oss << ", error " << err_num << " : " << err_msg;
NebulaLog::log("ONE",Log::ERROR,oss);
unlock();
return -1;
}
if ( (obj != 0) && (obj->isCallBackSet()) )
{
MYSQL_RES * result;
MYSQL_ROW row;
MYSQL_FIELD * fields;
unsigned int num_fields;
// Retrieve the entire result set all at once
result = mysql_store_result(db);
if (result == NULL)
{
ostringstream oss;
const char * err_msg = mysql_error(db);
int err_num = mysql_errno(db);
oss << "SQL command was: " << c_str;
oss << ", error " << err_num << " : " << err_msg;
NebulaLog::log("ONE",Log::ERROR,oss);
unlock();
return -1;
}
// Fetch the names of the fields
num_fields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
char ** names = new char*[num_fields];
for(unsigned int i = 0; i < num_fields; i++)
{
names[i] = fields[i].name;
}
// Fetch each row, and call-back the object waiting for them
while((row = mysql_fetch_row(result)))
{
obj->do_callback(num_fields, row, names);
}
// Free the result object
mysql_free_result(result);
delete[] names;
}
unlock();
return 0;
};
int exec(ostringstream& cmd, Callbackable* obj=0);
/**
* This function returns a legal SQL string that can be used in an SQL
@ -180,23 +65,13 @@ public:
* @param str the string to be escaped
* @return a valid SQL string or NULL in case of failure
*/
char * escape_str(const string& str)
{
char * result = new char[str.size()*2+1];
mysql_real_escape_string(db, result, str.c_str(), str.size());
return result;
};
char * escape_str(const string& str);
/**
* Frees a previously scaped string
* @param str pointer to the str
*/
void free_str(char * str)
{
delete[] str;
};
void free_str(char * str);
private:
@ -226,5 +101,29 @@ private:
pthread_mutex_unlock(&mutex);
};
};
#else
//CLass stub
class MySqlDB : public SqlDB
{
public:
#endif /*MYSQL_DB_H_*/
MySqlDB(
string server,
string user,
string password,
char * database)
{
throw runtime_error("Aborting oned, MySQL support not compiled!");
};
~MySqlDB(){};
int exec(ostringstream& cmd, Callbackable* obj=0){return -1;};
char * escape_str(const string& str){return 0;};
void free_str(char * str){};
};
#endif
#endif /*MYSQL_DB_H_*/

View File

@ -20,7 +20,6 @@
#include <string>
#include <sstream>
#include <stdexcept>
#include <sqlite3.h>
#include <sys/time.h>
#include <sys/types.h>
@ -33,23 +32,9 @@
using namespace std;
extern "C" int sqlite_callback (
void * _obj,
int num,
char ** values,
char ** names)
{
Callbackable *obj;
#ifdef SQLITE_DB
obj = static_cast<Callbackable *>(_obj);
if (obj == 0)
{
return -1;
}
return obj->do_callback(num,values,names);
};
#include <sqlite3.h>
/**
* SqliteDB class. Provides a wrapper to the sqlite3 database interface. It also
@ -60,26 +45,9 @@ class SqliteDB : public SqlDB
{
public:
SqliteDB(string& db_name)
{
int rc;
SqliteDB(string& db_name);
pthread_mutex_init(&mutex,0);
rc = sqlite3_open(db_name.c_str(), &db);
if ( rc != SQLITE_OK )
{
throw runtime_error("Could not open database.");
}
};
~SqliteDB()
{
pthread_mutex_destroy(&mutex);
sqlite3_close(db);
};
~SqliteDB();
/**
* Wraps the sqlite3_exec function call, and locks the DB mutex.
@ -89,72 +57,7 @@ public:
* @param arg to pass to the callback function
* @return 0 on success
*/
int exec(ostringstream& cmd, Callbackable* obj=0)
{
int rc;
const char * c_str;
string str;
int counter = 0;
char * err_msg = 0;
int (*callback)(void*,int,char**,char**);
void * arg;
str = cmd.str();
c_str = str.c_str();
callback = 0;
arg = 0;
if ((obj != 0)&&(obj->isCallBackSet()))
{
callback = sqlite_callback;
arg = static_cast<void *>(obj);
}
lock();
do
{
counter++;
rc = sqlite3_exec(db, c_str, callback, arg, &err_msg);
if (rc == SQLITE_BUSY || rc == SQLITE_IOERR_BLOCKED)
{
struct timeval timeout;
fd_set zero;
FD_ZERO(&zero);
timeout.tv_sec = 0;
timeout.tv_usec = 250000;
select(0, &zero, &zero, &zero, &timeout);
}
}while( (rc == SQLITE_BUSY || rc == SQLITE_IOERR_BLOCKED) &&
(counter < 10));
unlock();
if (rc != SQLITE_OK)
{
if (err_msg != 0)
{
ostringstream oss;
oss << "SQL command was: " << c_str << ", error: " << err_msg;
NebulaLog::log("ONE",Log::ERROR,oss);
sqlite3_free(err_msg);
}
return -1;
}
return 0;
};
int exec(ostringstream& cmd, Callbackable* obj=0);
/**
* This function returns a legal SQL string that can be used in an SQL
@ -162,19 +65,13 @@ public:
* @param str the string to be escaped
* @return a valid SQL string or NULL in case of failure
*/
char * escape_str(const string& str)
{
return sqlite3_mprintf("%q",str.c_str());
};
char * escape_str(const string& str);
/**
* Frees a previously scaped string
* @param str pointer to the str
*/
void free_str(char * str)
{
sqlite3_free(str);
};
void free_str(char * str);
private:
/**
@ -203,5 +100,25 @@ private:
pthread_mutex_unlock(&mutex);
};
};
#else
//CLass stub
class SqliteDB : public SqlDB
{
public:
SqliteDB(string& db_name)
{
throw runtime_error("Aborting oned, Sqlite support not compiled!");
};
~SqliteDB(){};
int exec(ostringstream& cmd, Callbackable* obj=0){return -1;};
char * escape_str(const string& str){return 0;};
void free_str(char * str){};
};
#endif
#endif /*SQLITE_DB_H_*/

View File

@ -49,10 +49,17 @@ env.Append(LIBS=[
'nebula_vnm',
'nebula_vm',
'nebula_common',
'sqlite3',
'nebula_sql',
'crypto'
])
# Sources to generate the library
if env['sqlite']=='yes':
env.Append(LIBS=['sqlite3'])
if env['mysql']=='yes':
env.Append(LIBS=['mysqlclient'])
if not env.GetOption('clean'):
env.ParseConfig('../../share/scons/get_xmlrpc_config server')

174
src/sql/MySqlDB.cc Normal file
View File

@ -0,0 +1,174 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "MySqlDB.h"
/*********
* Doc: http://dev.mysql.com/doc/refman/5.5/en/c-api-function-overview.html
********/
/* -------------------------------------------------------------------------- */
MySqlDB::MySqlDB(
const string& server,
const string& user,
const string& password,
char * database)
{
// 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(), database, 0, NULL, 0))
{
throw runtime_error("Could not open database.");
}
pthread_mutex_init(&mutex,0);
}
/* -------------------------------------------------------------------------- */
MySqlDB::~MySqlDB()
{
// Close the connection to the MySQL server
mysql_close(db);
// End use of the MySQL library
mysql_library_end();
pthread_mutex_destroy(&mutex);
}
/* -------------------------------------------------------------------------- */
int MySqlDB::exec(ostringstream& cmd, Callbackable* obj)
{
int rc;
const char * c_str;
string str;
int (*callback)(void*,int,char**,char**);
void * arg;
str = cmd.str();
c_str = str.c_str();
callback = 0;
arg = 0;
lock();
rc = mysql_query(db, c_str);
if (rc != 0)
{
ostringstream oss;
const char * err_msg = mysql_error(db);
int err_num = mysql_errno(db);
oss << "SQL command was: " << c_str;
oss << ", error " << err_num << " : " << err_msg;
NebulaLog::log("ONE",Log::ERROR,oss);
unlock();
return -1;
}
if ( (obj != 0) && (obj->isCallBackSet()) )
{
MYSQL_RES * result;
MYSQL_ROW row;
MYSQL_FIELD * fields;
unsigned int num_fields;
// Retrieve the entire result set all at once
result = mysql_store_result(db);
if (result == NULL)
{
ostringstream oss;
const char * err_msg = mysql_error(db);
int err_num = mysql_errno(db);
oss << "SQL command was: " << c_str;
oss << ", error " << err_num << " : " << err_msg;
NebulaLog::log("ONE",Log::ERROR,oss);
unlock();
return -1;
}
// Fetch the names of the fields
num_fields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
char ** names = new char*[num_fields];
for(unsigned int i = 0; i < num_fields; i++)
{
names[i] = fields[i].name;
}
// Fetch each row, and call-back the object waiting for them
while((row = mysql_fetch_row(result)))
{
obj->do_callback(num_fields, row, names);
}
// Free the result object
mysql_free_result(result);
delete[] names;
}
unlock();
return 0;
}
/* -------------------------------------------------------------------------- */
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());
return result;
}
/* -------------------------------------------------------------------------- */
void MySqlDB::free_str(char * str)
{
delete[] str;
}
/* -------------------------------------------------------------------------- */

33
src/sql/SConstruct Normal file
View File

@ -0,0 +1,33 @@
# SConstruct for src/pool
# -------------------------------------------------------------------------- #
# Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
Import('env')
lib_name='nebula_sql'
source_files=[]
# Sources to generate the library
if env['sqlite']=='yes':
source_files.append('SqliteDB.cc')
if env['mysql']=='yes':
source_files.append('MySqlDB.cc')
# Build library
env.StaticLibrary(lib_name, source_files)

149
src/sql/SqliteDB.cc Normal file
View File

@ -0,0 +1,149 @@
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
#include "SqliteDB.h"
using namespace std;
/* -------------------------------------------------------------------------- */
extern "C" int sqlite_callback (
void * _obj,
int num,
char ** values,
char ** names)
{
Callbackable *obj;
obj = static_cast<Callbackable *>(_obj);
if (obj == 0)
{
return -1;
}
return obj->do_callback(num,values,names);
};
/* -------------------------------------------------------------------------- */
SqliteDB::SqliteDB(string& db_name)
{
int rc;
pthread_mutex_init(&mutex,0);
rc = sqlite3_open(db_name.c_str(), &db);
if ( rc != SQLITE_OK )
{
throw runtime_error("Could not open database.");
}
}
/* -------------------------------------------------------------------------- */
SqliteDB::~SqliteDB()
{
pthread_mutex_destroy(&mutex);
sqlite3_close(db);
}
/* -------------------------------------------------------------------------- */
int SqliteDB::exec(ostringstream& cmd, Callbackable* obj)
{
int rc;
const char * c_str;
string str;
int counter = 0;
char * err_msg = 0;
int (*callback)(void*,int,char**,char**);
void * arg;
str = cmd.str();
c_str = str.c_str();
callback = 0;
arg = 0;
if ((obj != 0)&&(obj->isCallBackSet()))
{
callback = sqlite_callback;
arg = static_cast<void *>(obj);
}
lock();
do
{
counter++;
rc = sqlite3_exec(db, c_str, callback, arg, &err_msg);
if (rc == SQLITE_BUSY || rc == SQLITE_IOERR_BLOCKED)
{
struct timeval timeout;
fd_set zero;
FD_ZERO(&zero);
timeout.tv_sec = 0;
timeout.tv_usec = 250000;
select(0, &zero, &zero, &zero, &timeout);
}
}while( (rc == SQLITE_BUSY || rc == SQLITE_IOERR_BLOCKED) &&
(counter < 10));
unlock();
if (rc != SQLITE_OK)
{
if (err_msg != 0)
{
ostringstream oss;
oss << "SQL command was: " << c_str << ", error: " << err_msg;
NebulaLog::log("ONE",Log::ERROR,oss);
sqlite3_free(err_msg);
}
return -1;
}
return 0;
}
/* -------------------------------------------------------------------------- */
char * SqliteDB::escape_str(const string& str)
{
return sqlite3_mprintf("%q",str.c_str());
}
/* -------------------------------------------------------------------------- */
void SqliteDB::free_str(char * str)
{
sqlite3_free(str);
}