MysqlClient query performance boost, reconnect function. ArgParse ctor argument order changed

master
Denes Matetelki 13 years ago
parent baa3d0137d
commit 5f5d376b4b

@ -42,11 +42,11 @@ public:
* @param name short and/or long form: "-f,--foo" * @param name short and/or long form: "-f,--foo"
* The value can be retreived with this string passed to the argAs... functions. * The value can be retreived with this string passed to the argAs... functions.
* @param help Description of the argument, printed when --help is given. * @param help Description of the argument, printed when --help is given.
* @param valueType Type of the paramterer, required by the argument.
* @param valueRequired Parameter requiered/optional after the argument.
* @param argRequired Argument is required or optional. * @param argRequired Argument is required or optional.
* It's a bad practice to have a required argument, * It's a bad practice to have a required argument,
* "options", shall be optional. * "options", shall be optional.
* @param valueType Type of the paramterer, required by the argument.
* @param valueRequired Parameter requiered/optional after the argument.
* @param valueName Default is the type. But some short text can be better. * @param valueName Default is the type. But some short text can be better.
* @param choices Comma separeted list of strings without whitespaces: * @param choices Comma separeted list of strings without whitespaces:
* "yes,no,maybe" * "yes,no,maybe"
@ -55,8 +55,8 @@ public:
void addArgument(const std::string name, void addArgument(const std::string name,
const std::string help, const std::string help,
const ValueType valueType = NONE, const ValueType valueType = NONE,
const Required argRequired = OPTIONAL,
const Required valueRequired = REQUIRED, const Required valueRequired = REQUIRED,
const Required argRequired = OPTIONAL,
const std::string valueName = std::string(""), const std::string valueName = std::string(""),
const std::string choices = std::string("")); const std::string choices = std::string(""));
@ -121,8 +121,8 @@ private:
struct Argument { struct Argument {
const std::string m_help; const std::string m_help;
const ValueType m_type; const ValueType m_type;
const Required m_argRequired;
const Required m_valueRequired; const Required m_valueRequired;
const Required m_argRequired;
const std::string m_valueName; const std::string m_valueName;
const std::string m_choices; const std::string m_choices;
std::string m_value; std::string m_value;
@ -131,8 +131,8 @@ private:
Argument (const std::string help, Argument (const std::string help,
const ValueType type = NONE, const ValueType type = NONE,
const Required argRequired = OPTIONAL,
const Required valueRequired = REQUIRED, const Required valueRequired = REQUIRED,
const Required argRequired = OPTIONAL,
const std::string valueName = std::string(""), const std::string valueName = std::string(""),
const std::string choices = std::string(""), const std::string choices = std::string(""),
const std::string value = std::string("")); const std::string value = std::string(""));

@ -11,54 +11,41 @@ class MysqlClient
public: public:
/** /// @note Call init_client_errs() / finish_client_errs() before / after
* For more details about the params,
* check the documentation of mysql_real_connect
*
* @note Call init_client_errs() / finish_client_errs() before / after.
*
* @param host May be either a host name or an IP address.
* If host is NULL or the string "localhost",
* a connection to the local host is assumed.
* @param user If user is NULL or the empty string "",
* the current user is assumed.
* @param passwd If passwd is NULL, only entries in the user table
* for the user that have a blank (empty) password field
* are checked for a match.
* @param db If db is not NULL, the connection sets the default
* database to this value.
* @param port If port is not 0, the value is used as the port number
* for the TCP/IP connection. Note that the host parameter determines
* the type of the connection.
* @param unix_socket If unix_socket is not NULL, the string specifies
* the socket or named pipe that should be used. Note that the host parameter
* determines the type of the connection.
* @param clientflag Usually 0, but can be set to a combination
* of flags to enable certain features.
*/
MysqlClient ( const char *host = NULL, MysqlClient ( const char *host = NULL,
const char *user = NULL, const char *user = NULL,
const char *passwd = NULL, const char *passwd = NULL,
const char *db = NULL, const char *db = NULL,
unsigned int port = 0, const unsigned int port = 0,
const char *unix_socket = NULL, const char *unix_socket = NULL,
unsigned long clientflag = 0 ); const unsigned long clientflag = 0,
const int maxRetry = 5
);
~MysqlClient(); ~MysqlClient();
/// @note clients side shall handle connect failure (reconnect)
bool connect(); bool connect();
bool querty(const std::string queryLine, /// @note clients side shall handle querty failure (reconnect)
/// @note call mysql_free_result( result ) after
bool querty(const char* queryMsg,
const int queryMsgLen,
MYSQL_RES **result);
bool reconnect();
/// @note Slow. Use only to log during debug
/// @todo optimize this
static void queryResultToStringList(const MYSQL_RES *res_set,
std::list<std::string> &result); std::list<std::string> &result);
private: private:
MysqlClient(const MysqlClient&); MysqlClient(const MysqlClient&);
MysqlClient& operator=(const MysqlClient&); MysqlClient& operator=(const MysqlClient&);
/// @todo optimize this
void queryResultToStringList(MYSQL_RES *res_set,
std::list<std::string> &result);
const char *m_host; const char *m_host;
const char *m_user; const char *m_user;
@ -67,6 +54,7 @@ private:
unsigned int m_port; unsigned int m_port;
const char *m_unix_socket; const char *m_unix_socket;
unsigned long m_clientflag; unsigned long m_clientflag;
int m_maxRetry;
bool m_connected; bool m_connected;
MYSQL *m_connection; MYSQL *m_connection;

@ -1,5 +1,6 @@
// g++ mysqlclient_main.cpp src/Logger.cpp src/MysqlClient.cpp src/ArgParse.cpp -I./include -lmysqlclient // gpp mysqlclient_main.cpp ../src/Logger.cpp ../src/MysqlClient.cpp ../src/ArgParse.cpp -I../include -lmysqlclient -o mysqlclient
// ./mysqlclient -u USER -db MYSQL_DB -p PASS
#include "Logger.hpp" #include "Logger.hpp"
#include "Common.hpp" #include "Common.hpp"
@ -15,21 +16,23 @@
void setUpArgs(ArgParse &argParse) void setUpArgs(ArgParse &argParse)
{ {
TRACE_STATIC;
argParse.addArgument("--host", argParse.addArgument("--host",
"Hostname/IP", "Hostname/IP",
ArgParse::STRING ); ArgParse::STRING );
argParse.addArgument("-u, --user", argParse.addArgument("-u, --user",
"Username", "Username",
ArgParse::STRING, ArgParse::STRING,
ArgParse::REQUIRED ); ArgParse::REQUIRED, ArgParse::REQUIRED );
argParse.addArgument("-db, --database", argParse.addArgument("-db, --database",
"Database", "Database",
ArgParse::STRING, ArgParse::STRING,
ArgParse::REQUIRED ); ArgParse::REQUIRED, ArgParse::REQUIRED );
argParse.addArgument("-p, --password", argParse.addArgument("-p, --password",
"Password", "Password",
ArgParse::STRING, ArgParse::STRING,
ArgParse::REQUIRED ); ArgParse::REQUIRED, ArgParse::REQUIRED );
argParse.addArgument("-port", argParse.addArgument("-port",
"Port", "Port",
ArgParse::INT ); ArgParse::INT );
@ -39,6 +42,11 @@ void setUpArgs(ArgParse &argParse)
argParse.addArgument("-f, --client-flags", argParse.addArgument("-f, --client-flags",
"Client flags", "Client flags",
ArgParse::INT ); ArgParse::INT );
argParse.addArgument("-r, --max-reconnect",
"Maximum number of retries if connection is lost. "
"Default is 5.",
ArgParse::INT,
ArgParse::REQUIRED );
} }
@ -50,8 +58,11 @@ void getArgs( int argc, char* argv[],
std::string &pass, std::string &pass,
std::string &unixsocket, std::string &unixsocket,
int &port, int &port,
int &clientflags ) int &clientflags,
int &retry )
{ {
TRACE_STATIC;
argParse.parseArgs(argc, argv); argParse.parseArgs(argc, argv);
argParse.argAsString("--host", host); argParse.argAsString("--host", host);
@ -61,11 +72,14 @@ void getArgs( int argc, char* argv[],
argParse.argAsInt("-port", port); argParse.argAsInt("-port", port);
argParse.argAsString("-s, --unix-socket", unixsocket); argParse.argAsString("-s, --unix-socket", unixsocket);
argParse.argAsInt("-f, --client-flags", clientflags); argParse.argAsInt("-f, --client-flags", clientflags);
argParse.argAsInt("-r, --max-reconnect", retry);
} }
void printResults(std::list<std::string> &results) void printResults(std::list<std::string> &results)
{ {
TRACE_STATIC;
LOG ( Logger::DEBUG, std::string("Got query result number of rows: "). LOG ( Logger::DEBUG, std::string("Got query result number of rows: ").
append(TToStr(results.size())).c_str() ); append(TToStr(results.size())).c_str() );
@ -89,13 +103,13 @@ int main(int argc, char* argv[] )
setUpArgs(argParse); setUpArgs(argParse);
std::string host, user, db, pass, unixsocket; std::string host, user, db, pass, unixsocket;
int port, clientflags; int port, clientflags, retry;
try { try {
getArgs( argc, argv, getArgs( argc, argv,
argParse, argParse,
host, user, db, pass, unixsocket, host, user, db, pass, unixsocket,
port, clientflags ); port, clientflags, retry );
} catch (std::runtime_error e) { } catch (std::runtime_error e) {
if ( argParse.foundArg("-h, --help") ) { if ( argParse.foundArg("-h, --help") ) {
std::cout << argParse.usage() << std::endl; std::cout << argParse.usage() << std::endl;
@ -121,17 +135,42 @@ int main(int argc, char* argv[] )
argParse.foundArg("-db, --database") ? db .c_str() : NULL, argParse.foundArg("-db, --database") ? db .c_str() : NULL,
argParse.foundArg("-port") ? port : 0, argParse.foundArg("-port") ? port : 0,
argParse.foundArg("-s, --unix-socket") ? unixsocket.c_str() : NULL, argParse.foundArg("-s, --unix-socket") ? unixsocket.c_str() : NULL,
argParse.foundArg("-f, --client-flags") ? clientflags : 0 ); argParse.foundArg("-f, --client-flags") ? clientflags : 0,
argParse.foundArg("-r, --max-reconnect") ? retry : 5 );
std::list<std::string> results; if ( !mysqlClient.connect() && !mysqlClient.reconnect() ) {
if ( !mysqlClient.querty("SELECT * FROM seats", results) ) { finish_client_errs();
Logger::destroy();
return 0;
}
std::string queryMsg("SELECT * FROM seats");
MYSQL_RES *queryResult;
if ( !mysqlClient.querty(queryMsg.c_str(), queryMsg.length(), &queryResult) ) {
LOG( Logger::ERR, "Could not execute query." ); LOG( Logger::ERR, "Could not execute query." );
} else { if ( !mysqlClient.reconnect() ) {
printResults(results); LOG( Logger::ERR, "Reconnect failed, exiting." );
finish_client_errs();
Logger::destroy();
return 0;
} }
LOG( Logger::ERR, "Trying query again." );
if ( !mysqlClient.querty(queryMsg.c_str(), queryMsg.length(), &queryResult) ) {
LOG( Logger::ERR, "Query failed again, exiting." );
finish_client_errs(); finish_client_errs();
Logger::destroy();
return 0;
}
}
std::list<std::string> results;
MysqlClient::queryResultToStringList(queryResult, results);
printResults(results);
mysql_free_result(queryResult);
finish_client_errs();
Logger::destroy(); Logger::destroy();
return 0; return 0;
} }

@ -31,8 +31,8 @@ ArgParse::ArgParse(const std::string description,
void ArgParse::addArgument(const std::string arg, void ArgParse::addArgument(const std::string arg,
const std::string help, const std::string help,
const ValueType valueType, const ValueType valueType,
const Required argRequired,
const Required valueRequired, const Required valueRequired,
const Required argRequired,
const std::string valueName, const std::string valueName,
const std::string choices) const std::string choices)
{ {
@ -62,8 +62,8 @@ void ArgParse::addArgument(const std::string arg,
Argument argument(help, Argument argument(help,
valueType, valueType,
argRequired,
valueRequired, valueRequired,
argRequired,
typeToString(valueType, valueName), typeToString(valueType, valueName),
choices, choices,
""); "");
@ -408,15 +408,15 @@ void ArgParse::validateBool( const std::string name,
ArgParse::Argument::Argument (const std::string help, ArgParse::Argument::Argument (const std::string help,
const ValueType type, const ValueType type,
const Required argRequired,
const Required valueRequired, const Required valueRequired,
const Required argRequired,
const std::string valueName, const std::string valueName,
const std::string choices, const std::string choices,
const std::string value) const std::string value)
: m_help(help) : m_help(help)
, m_type(type) , m_type(type)
, m_argRequired(argRequired)
, m_valueRequired(valueRequired) , m_valueRequired(valueRequired)
, m_argRequired(argRequired)
, m_valueName(valueName) , m_valueName(valueName)
, m_choices(choices) , m_choices(choices)
, m_value(value) , m_value(value)

@ -10,9 +10,11 @@ MysqlClient::MysqlClient( const char *host,
const char *user, const char *user,
const char *passwd, const char *passwd,
const char *db, const char *db,
unsigned int port, const unsigned int port,
const char *unix_socket, const char *unix_socket,
unsigned long clientflag ) const unsigned long clientflag,
const int maxRetry
)
: m_host(host) : m_host(host)
, m_user(user) , m_user(user)
, m_passwd(passwd) , m_passwd(passwd)
@ -20,6 +22,7 @@ MysqlClient::MysqlClient( const char *host,
, m_port(port) , m_port(port)
, m_unix_socket(unix_socket) , m_unix_socket(unix_socket)
, m_clientflag(clientflag) , m_clientflag(clientflag)
, m_maxRetry(maxRetry)
, m_connected(false) , m_connected(false)
, m_connection(0) , m_connection(0)
{ {
@ -60,10 +63,10 @@ MysqlClient::connect()
return false; return false;
} }
LOG ( Logger::DEBUG, LOG ( Logger::INFO,
std::string("MySQL client connected to ").append(m_host ? m_host : "NULL") std::string("MySQL client connected to ").append(m_host ? m_host : "localhost")
.append(", on port: ").append(TToStr(m_port)) .append(", on port: ").append(m_port ? TToStr(m_port) : "TCP/IP")
.append(", as user: ").append(m_user ? m_user : "NULL") .append(", as user: ").append(m_user ? m_user : "CURRENT_USER")
.append(", with passwd: ").append(m_passwd ? m_passwd : "NULL") .append(", with passwd: ").append(m_passwd ? m_passwd : "NULL")
.append(", to DB: ").append(m_db ? m_db : "NULL") .append(", to DB: ").append(m_db ? m_db : "NULL")
.append(", with unix_socket: ").append(m_unix_socket ? m_unix_socket : "NULL") .append(", with unix_socket: ").append(m_unix_socket ? m_unix_socket : "NULL")
@ -76,17 +79,21 @@ MysqlClient::connect()
bool bool
MysqlClient::querty(const std::string queryLine, MysqlClient::querty(const char* queryMsg,
std::list<std::string> &result) const int queryMsgLen,
MYSQL_RES **result)
{ {
TRACE; TRACE;
if ( !m_connected && !connect() ) if ( !m_connected ) {
LOG( Logger::ERR, "Not connected to MySQL server." );
return false; return false;
}
if ( mysql_query(m_connection,queryLine.c_str()) != 0 ) { if ( mysql_real_query(m_connection, queryMsg, queryMsgLen) != 0 ) {
LOG ( Logger::ERR, std::string("MySQL query failed! "). LOG ( Logger::ERR, std::string("MySQL query failed! ").
append(mysql_error(m_connection)).c_str()); append(mysql_error(m_connection)).c_str());
return false; return false;
} }
@ -99,24 +106,48 @@ MysqlClient::querty(const std::string queryLine,
return false; return false;
} }
queryResultToStringList( res_set, result); *result = res_set;
return true;
}
bool
MysqlClient::reconnect()
{
TRACE;
for (int i = 0; i < m_maxRetry; ++i ) {
LOG( Logger::INFO, std::string("Reconnecting to MySQL server, ").
append(TToStr(i+1)).
append(" try of maximum: ").
append(TToStr(m_maxRetry)).c_str() );
mysql_free_result( res_set ); if ( connect() )
return true; return true;
sleep(1);
} }
LOG( Logger::ERR, "Maximum number of retries reached, giving up." );
return false;
}
void void
MysqlClient::queryResultToStringList(MYSQL_RES *res_set, MysqlClient::queryResultToStringList(const MYSQL_RES *res_set,
std::list<std::string> &result) std::list<std::string> &result)
{ {
unsigned int numrows = mysql_num_rows(res_set); TRACE_STATIC;
LOG( Logger::DEBUG, std::string("MySQL query returned number of rows: ").
append(TToStr(numrows)).c_str()); // unsigned int numrows = mysql_num_rows(res_set);
// LOG( Logger::DEBUG, std::string("MySQL query returned number of rows: ").
// append(TToStr(numrows)).c_str());
unsigned int num_fields = mysql_num_fields(res_set); unsigned int num_fields = mysql_num_fields(const_cast<MYSQL_RES *>(res_set));
MYSQL_ROW row; MYSQL_ROW row;
while ((row = mysql_fetch_row(res_set)) != NULL) { while ((row = mysql_fetch_row(const_cast<MYSQL_RES *>(res_set))) != NULL) {
std::string rowString; std::string rowString;
for( unsigned int i = 0; i < num_fields; ++i ) { for( unsigned int i = 0; i < num_fields; ++i ) {
rowString.append(row[i] ? row[i] : "NULL"); rowString.append(row[i] ? row[i] : "NULL");

Loading…
Cancel
Save