diff --git a/include/dmlite/dm_errno.h b/include/dmlite/dm_errno.h index a1a0aaba917cbbe5d37daf9ca07d7238ada8c668..eb50d6eeaa2a95d4638b7b06b8bec4192048389b 100644 --- a/include/dmlite/dm_errno.h +++ b/include/dmlite/dm_errno.h @@ -24,6 +24,7 @@ #define DM_CONNECTION_ERROR 0x0201 #define DM_SERVICE_UNAVAILABLE 0x0202 #define DM_QUERY_FAILED 0x0203 +#define DM_UNKNOWN_FIELD 0x0204 #define DM_NOT_IMPLEMENTED 0x1001 #define DM_NULL_POINTER 0x1002 diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 3662c768aee32b85fbf5357eb20e9fe39d3703e8..76120a800540af55253acffcdeb2d2d31762340f 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -6,4 +6,4 @@ add_subdirectory (mysql) #add_subdirectory (librarian) #add_subdirectory (memcache) #add_subdirectory (oracle) -add_subdirectory (hadoop) +#add_subdirectory (hadoop) diff --git a/plugins/mysql/DpmMySql.cpp b/plugins/mysql/DpmMySql.cpp index a9e6209c5eaa3c8a496ffc540ecec522ca295610..05c89ca0e9f50ea07d777888acdee5645c60c15a 100644 --- a/plugins/mysql/DpmMySql.cpp +++ b/plugins/mysql/DpmMySql.cpp @@ -208,16 +208,34 @@ void MySqlPoolManager::setSecurityContext(const SecurityContext* ctx) throw (DmE std::vector<Pool> MySqlPoolManager::getPools() throw (DmException) { Pool pool; - Statement stmt(this->conn_, this->dpmDb_, STMT_GET_POOLS); + std::vector<Pool> pools; + + try { + Statement stmt(this->conn_, this->dpmDb_, STMT_GET_POOLS); - stmt.execute(); + stmt.execute(); - stmt.bindResult(0, pool.pool_name, sizeof(pool.pool_name)); - stmt.bindResult(1, pool.pool_type, sizeof(pool.pool_type)); + stmt.bindResult(0, pool.pool_name, sizeof(pool.pool_name)); + stmt.bindResult(1, pool.pool_type, sizeof(pool.pool_type)); - std::vector<Pool> pools; - while (stmt.fetch()) - pools.push_back(pool); + while (stmt.fetch()) + pools.push_back(pool); + } + catch (DmException e) { + if (e.code() != DM_UNKNOWN_FIELD) + throw; + + // Fallback to legacy mode + Statement stmt(this->conn_, this->dpmDb_, STMT_GET_POOLS_LEGACY); + + stmt.execute(); + + stmt.bindResult(0, pool.pool_name, sizeof(pool.pool_name)); + stmt.bindResult(1, pool.pool_type, sizeof(pool.pool_type)); + + while (stmt.fetch()) + pools.push_back(pool); + } return pools; } @@ -227,17 +245,25 @@ std::vector<Pool> MySqlPoolManager::getPools() throw (DmException) Pool MySqlPoolManager::getPool(const std::string& poolname) throw (DmException) { Pool pool; - Statement stmt(this->conn_, this->dpmDb_, STMT_GET_POOL); - - stmt.bindParam(0, poolname); - - stmt.execute(); - - stmt.bindResult(0, pool.pool_name, sizeof(pool.pool_name)); - stmt.bindResult(1, pool.pool_type, sizeof(pool.pool_type)); - if (!stmt.fetch()) - throw DmException(DM_NO_SUCH_POOL, poolname + " not found"); - + + try { + Statement stmt(this->conn_, this->dpmDb_, STMT_GET_POOL); + + stmt.bindParam(0, poolname); + stmt.execute(); + stmt.bindResult(0, pool.pool_name, sizeof(pool.pool_name)); + stmt.bindResult(1, pool.pool_type, sizeof(pool.pool_type)); + if (!stmt.fetch()) + throw DmException(DM_NO_SUCH_POOL, poolname + " not found"); + } + catch (DmException e) { + if (e.code() != DM_UNKNOWN_FIELD) + throw; + // Fallback to legacy mode + strncpy(pool.pool_name, poolname.c_str(), sizeof(pool.pool_name)); + strcpy(pool.pool_type, "filesystem"); + } + return pool; } diff --git a/plugins/mysql/MySqlWrapper.cpp b/plugins/mysql/MySqlWrapper.cpp index d82002034bb077a59762aa4ac2caa34e92754650..a1bbaabde5fd52284d8b5dbbab869ee5b9957339 100644 --- a/plugins/mysql/MySqlWrapper.cpp +++ b/plugins/mysql/MySqlWrapper.cpp @@ -5,6 +5,7 @@ #include <cstring> #include <cstdlib> +#include <mysql/mysqld_error.h> #include <vector> using namespace dmlite; @@ -72,9 +73,8 @@ Statement::Statement(MYSQL* conn, const std::string& db, const char* query) thro throw DmException(DM_QUERY_FAILED, std::string(mysql_error(conn))); this->stmt_ = mysql_stmt_init(conn); - if (mysql_stmt_prepare(this->stmt_, query, strlen(query)) != 0) { - throw DmException(DM_QUERY_FAILED, std::string(mysql_stmt_error(this->stmt_))); - } + if (mysql_stmt_prepare(this->stmt_, query, strlen(query)) != 0) + this->throwException(); this->nParams_ = mysql_stmt_param_count(this->stmt_); this->params_ = new MYSQL_BIND [this->nParams_]; @@ -166,10 +166,8 @@ unsigned long Statement::execute(bool autobind) throw (DmException) mysql_stmt_bind_param(this->stmt_, this->params_); - if (mysql_stmt_execute(this->stmt_) != 0) { - this->status_ = STMT_FAILED; - throw DmException(DM_QUERY_FAILED, mysql_stmt_error(this->stmt_)); - } + if (mysql_stmt_execute(this->stmt_) != 0) + this->throwException(); // Count fields and reserve MYSQL_RES* meta = mysql_stmt_result_metadata(this->stmt_); @@ -356,8 +354,7 @@ bool Statement::fetch(void) throw (DmException) this->status_ = STMT_DONE; return false; default: - this->status_ = STMT_FAILED; - throw DmException(DM_INTERNAL_ERROR, mysql_stmt_error(this->stmt_)); + this->throwException(); } } @@ -394,3 +391,17 @@ std::string Statement::getString(unsigned index) else return std::string((char*)this->fieldBuffer_[index]); } + + + +void Statement::throwException() throw (DmException) +{ + this->status_ = STMT_FAILED; + switch (mysql_stmt_errno(this->stmt_)) { + case ER_BAD_FIELD_ERROR: + throw DmException(DM_UNKNOWN_FIELD, mysql_stmt_error(this->stmt_)); + default: + throw DmException(DM_QUERY_FAILED, "%s (%d)", mysql_stmt_error(this->stmt_), + mysql_stmt_errno(this->stmt_)); + } +} diff --git a/plugins/mysql/MySqlWrapper.h b/plugins/mysql/MySqlWrapper.h index dea9acbda74daae467030508e8a3a439621715d3..8cf2abac4b8287f08fad7caf8a6db95101d9eaf2 100644 --- a/plugins/mysql/MySqlWrapper.h +++ b/plugins/mysql/MySqlWrapper.h @@ -75,6 +75,9 @@ private: // For autobind std::map<std::string, unsigned> fieldIndex_; std::vector<void*> fieldBuffer_; + + /// Throws the proper exception + void throwException() throw (DmException); }; }; diff --git a/plugins/mysql/Queries.h b/plugins/mysql/Queries.h index 0e61aeb74dd081650313d2cc25c8f694cf686d30..875f021cad04f676ebc12e44cf8e32e8373db5dc 100644 --- a/plugins/mysql/Queries.h +++ b/plugins/mysql/Queries.h @@ -172,6 +172,9 @@ static const char* STMT_UPDATE_REPLICA = static const char* STMT_GET_POOLS = "SELECT poolname, COALESCE(pooltype, 'filesystem')\ FROM dpm_pool"; +static const char* STMT_GET_POOLS_LEGACY = + "SELECT poolname, 'filesystem'\ + FROM dpm_pool"; static const char* STMT_GET_POOL = "SELECT poolname, COALESCE(pooltype, 'filesystem')\ FROM dpm_pool\