From 9c1bdfdf11e94ceb12106139a708902ccd7a7013 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Tue, 4 Dec 2007 18:33:28 +0000 Subject: [PATCH] Add runtime versus compile time mysql version check, distinguish between unrecoverable errors from init context and errors during connection from db module in bkserver. --- org.glite.lb.common/interface/context.h | 1 + org.glite.lb.common/src/context.c | 1 + org.glite.lb.server/src/bkindex.c | 1 - org.glite.lb.server/src/bkserverd.c | 29 ++++++++----- org.glite.lb.server/src/openserver.c | 9 ++++- org.glite.lbjp-common.db/Makefile | 2 +- org.glite.lbjp-common.db/src/db.c | 72 ++++++++++++++++++++------------- 7 files changed, 75 insertions(+), 40 deletions(-) diff --git a/org.glite.lb.common/interface/context.h b/org.glite.lb.common/interface/context.h index 7f29593..ad366de 100644 --- a/org.glite.lb.common/interface/context.h +++ b/org.glite.lb.common/interface/context.h @@ -181,6 +181,7 @@ typedef enum _edg_wll_ErrorCode { EDG_WLL_ERROR_XML_PARSE, /**< Error in parsing XML protocol. */ EDG_WLL_ERROR_SERVER_RESPONSE, /**< Generic failure on server. See syslog on the server machine for details. */ EDG_WLL_ERROR_JOBID_FORMAT, /**< Malformed jobid */ + EDG_WLL_ERROR_DB_INIT, /**< Failed DB initialization (dynamic load, version mismatch, ...) */ EDG_WLL_ERROR_DB_CALL, /**< Failure of underlying database engine. See errDesc returned by edg_wll_ErrorCode(). */ EDG_WLL_ERROR_MD5_CLASH, /**< MD5 hash same for different strings. Very unlikely :-). */ diff --git a/org.glite.lb.common/src/context.c b/org.glite.lb.common/src/context.c index 33f7ef5..6e3e53e 100644 --- a/org.glite.lb.common/src/context.c +++ b/org.glite.lb.common/src/context.c @@ -157,6 +157,7 @@ static const char* const errTexts[] = { "XML Parse error", "Server response error", "Bad JobId format", + "Database initialization failed", "Database call failed", "MD5 key clash", "GSSAPI Error", diff --git a/org.glite.lb.server/src/bkindex.c b/org.glite.lb.server/src/bkindex.c index 38490c8..772c289 100644 --- a/org.glite.lb.server/src/bkindex.c +++ b/org.glite.lb.server/src/bkindex.c @@ -93,7 +93,6 @@ int main(int argc,char **argv) } edg_wll_InitContext(&ctx); - glite_lbu_InitDBContext(&ctx->dbctx); if (!dbstring) dbstring = DEFAULTCS; if (edg_wll_Open(ctx,dbstring)) do_exit(ctx,EX_UNAVAILABLE); if ((ctx->dbcaps = glite_lbu_DBQueryCaps(ctx->dbctx)) == -1) do_exit(ctx, EX_SOFTWARE); diff --git a/org.glite.lb.server/src/bkserverd.c b/org.glite.lb.server/src/bkserverd.c index 8bae798..cc4bf3b 100644 --- a/org.glite.lb.server/src/bkserverd.c +++ b/org.glite.lb.server/src/bkserverd.c @@ -58,6 +58,7 @@ enum lb_srv_perf_sink sink_mode; #include "stats.h" #include "db_calls.h" #include "db_supp.h" +#include "openserver.h" #ifdef GLITE_LB_SERVER_WITH_WS # if GSOAP_VERSION < 20700 @@ -71,8 +72,6 @@ enum lb_srv_perf_sink sink_mode; #endif /* GLITE_LB_SERVER_WITH_WS */ extern int edg_wll_StoreProto(edg_wll_Context ctx); -extern edg_wll_ErrorCode edg_wll_Open(edg_wll_Context ctx, char *cs); -extern edg_wll_ErrorCode edg_wll_Close(edg_wll_Context); extern int edg_wll_StoreProtoProxy(edg_wll_Context ctx); extern char *lbproxy_ilog_socket_path; @@ -276,7 +275,7 @@ static void usage(char *me) ,me); } -static void wait_for_open(edg_wll_Context,const char *); +static int wait_for_open(edg_wll_Context,const char *); static int decrement_timeout(struct timeval *, struct timeval, struct timeval); static int add_root(char *); static int read_roots(const char *); @@ -699,8 +698,7 @@ int main(int argc, char *argv[]) /* Just check the database and let it be. The slaves do the job. */ edg_wll_InitContext(&ctx); - glite_lbu_InitDBContext(&ctx->dbctx); - wait_for_open(ctx, dbstring); + if (wait_for_open(ctx, dbstring)) return 1; if ((ctx->dbcaps = glite_lbu_DBQueryCaps(ctx->dbctx)) == -1) { @@ -1321,6 +1319,7 @@ int bk_accept_store(int conn, struct timeval *timeout, void *cdata) */ break; + case EDG_WLL_ERROR_DB_INIT: case EDG_WLL_ERROR_DB_CALL: case EDG_WLL_ERROR_SERVER_RESPONSE: default: @@ -1544,17 +1543,17 @@ int bk_clnt_reject_proxy(int conn) } -static void wait_for_open(edg_wll_Context ctx, const char *dbstring) +static int wait_for_open(edg_wll_Context ctx, const char *dbstring) { char *dbfail_string1, *dbfail_string2; + char *errt,*errd; + int err; dbfail_string1 = dbfail_string2 = NULL; - while (edg_wll_Open(ctx, (char *) dbstring)) { - char *errt,*errd; - + while (((err = edg_wll_Open(ctx, (char *) dbstring)) != EDG_WLL_ERROR_DB_INIT) && err) { if (dbfail_string1) free(dbfail_string1); - glite_lbu_DBError(ctx->dbctx,&errt,&errd); + edg_wll_Error(ctx,&errt,&errd); asprintf(&dbfail_string1,"%s (%s)\n",errt,errd); if (dbfail_string1 != NULL) { if (dbfail_string2 == NULL || strcmp(dbfail_string1,dbfail_string2)) { @@ -1574,6 +1573,16 @@ static void wait_for_open(edg_wll_Context ctx, const char *dbstring) dprintf(("[%d]: DB connection established\n",getpid())); if (!debug) syslog(LOG_INFO,"DB connection established\n"); } + + if (err) { + edg_wll_Error(ctx,&errt,&errd); + asprintf(&dbfail_string1,"%s (%s)\n",errt,errd); + dprintf(("[%d]: %s\n", getpid(), dbfail_string1)); + if (!debug) syslog(LOG_ERR,dbfail_string1); + free(dbfail_string1); + } + + return err; } static void free_hostent(struct hostent *h){ diff --git a/org.glite.lb.server/src/openserver.c b/org.glite.lb.server/src/openserver.c index dfac76d..9b043d5 100644 --- a/org.glite.lb.server/src/openserver.c +++ b/org.glite.lb.server/src/openserver.c @@ -6,7 +6,14 @@ edg_wll_ErrorCode edg_wll_Open(edg_wll_Context ctx, char *cs) { - glite_lbu_InitDBContext(&ctx->dbctx); + if (glite_lbu_InitDBContext(&ctx->dbctx) != 0) { + char *ed; + + glite_lbu_DBError(ctx->dbctx, NULL, &ed); + edg_wll_SetError(ctx, EDG_WLL_ERROR_DB_INIT, ed); + free(ed); + return EDG_WLL_ERROR_DB_INIT; + } return glite_lbu_DBConnect(ctx->dbctx,cs) ? edg_wll_SetErrorDB(ctx) : 0; } diff --git a/org.glite.lbjp-common.db/Makefile b/org.glite.lbjp-common.db/Makefile index 767badb..62a04bd 100644 --- a/org.glite.lbjp-common.db/Makefile +++ b/org.glite.lbjp-common.db/Makefile @@ -73,7 +73,7 @@ default all: compile doc libglite_lbu_db.la: ${LOBJS} if [ -z "${MYSQL_LIBPATH}" ]; then \ - echo "MySQL shared library not found!"; \ + echo "Warning: MySQL shared library not found!"; \ sleep 15; \ fi ${LINK} -o $@ $< ${EXT_LIBS} diff --git a/org.glite.lbjp-common.db/src/db.c b/org.glite.lbjp-common.db/src/db.c index 1c8e663..5624a05 100644 --- a/org.glite.lbjp-common.db/src/db.c +++ b/org.glite.lbjp-common.db/src/db.c @@ -14,6 +14,7 @@ #include #include +#include #include #include "glite/lbu/trio.h" @@ -36,7 +37,7 @@ #define USE_TRANS(CTX) ((CTX->caps & GLITE_LBU_DB_CAP_TRANSACTIONS) != 0) #define LOAD(SYM, SYM2) if ((*(void **)(&db_handle.SYM) = dlsym(db_handle.lib, SYM2)) == NULL) { \ - err = ERR(ctx, ENOENT, "can't load symbol %s from mysql library (%s)", SYM2, dlerror()); \ + err = ERR(*ctx, ENOENT, "can't load symbol %s from mysql library (%s)", SYM2, dlerror()); \ break; \ } @@ -109,6 +110,7 @@ typedef struct { pthread_mutex_t lock; void *(*mysql_init)(void *); + unsigned long (*mysql_get_client_version)(void); int (*mysql_options)(MYSQL *mysql, enum mysql_option option, const char *arg); unsigned int (*mysql_errno)(MYSQL *mysql); const char *(*mysql_error)(MYSQL *mysql); @@ -157,6 +159,7 @@ static int transaction_test(glite_lbu_DBContext ctx); static int FetchRowSimple(glite_lbu_DBContext ctx, MYSQL_RES *result, unsigned long *lengths, char **results); static int FetchRowPrepared(glite_lbu_DBContext ctx, glite_lbu_Statement stmt, unsigned int n, unsigned long *lengths, char **results); static void set_time(MYSQL_TIME *mtime, const time_t time); +static void glite_lbu_DBCleanup(void); /* ---- common ---- */ @@ -174,41 +177,21 @@ int glite_lbu_DBError(glite_lbu_DBContext ctx, char **text, char **desc) { int glite_lbu_InitDBContext(glite_lbu_DBContext *ctx) { - *ctx = calloc(1, sizeof **ctx); - return *ctx == NULL ? ENOMEM : 0; -} - - -void glite_lbu_FreeDBContext(glite_lbu_DBContext ctx) { - if (ctx) { - assert(ctx->mysql == NULL); - free(ctx->err.desc); - free(ctx); - } -} - - -static void glite_lbu_DBCleanup(void) { - pthread_mutex_lock(&db_handle.lock); - if (db_handle.lib) { - dlclose(db_handle.lib); - db_handle.lib = NULL; - } - pthread_mutex_unlock(&db_handle.lock); -} - - -int glite_lbu_DBConnect(glite_lbu_DBContext ctx, const char *cs) { int err = 0; + unsigned int ver_u; + + *ctx = calloc(1, sizeof **ctx); + if (!*ctx) return ENOMEM; /* dynamic load the mysql library */ pthread_mutex_lock(&db_handle.lock); if (!db_handle.lib) { if ((!MYSQL_LIBPATH[0] || (db_handle.lib = dlopen(MYSQL_LIBPATH, RTLD_LAZY | RTLD_LOCAL)) == NULL) && (db_handle.lib = dlopen("libmysqlclient.so", RTLD_LAZY | RTLD_LOCAL)) == NULL) - return ERR(ctx, ENOENT, "can't load '%s' or 'libmysqlclient.so' (%s)", MYSQL_LIBPATH, dlerror()); + return ERR(*ctx, ENOENT, "can't load '%s' or 'libmysqlclient.so' (%s)", MYSQL_LIBPATH, dlerror()); do { LOAD(mysql_init, "mysql_init"); + LOAD(mysql_get_client_version, "mysql_get_client_version"); LOAD(mysql_options, "mysql_options"); LOAD(mysql_errno, "mysql_errno"); LOAD(mysql_error, "mysql_error"); @@ -237,9 +220,18 @@ int glite_lbu_DBConnect(glite_lbu_DBContext ctx, const char *cs) { LOAD(mysql_stmt_affected_rows, "mysql_stmt_affected_rows"); LOAD(mysql_stmt_result_metadata, "mysql_stmt_result_metadata"); LOAD(mysql_stmt_fetch_column, "mysql_stmt_fetch_column"); + + // check the runtime version + ver_u = db_handle.mysql_get_client_version(); + if (ver_u != MYSQL_VERSION_ID) { + err = ERR(*ctx, EINVAL, "version mismatch (compiled '%lu', runtime '%lu')", MYSQL_VERSION_ID, ver_u); + break; + } + pthread_mutex_unlock(&db_handle.lock); atexit(glite_lbu_DBCleanup); } while(0); + if (err) { dlclose(db_handle.lib); db_handle.lib = NULL; @@ -248,6 +240,20 @@ int glite_lbu_DBConnect(glite_lbu_DBContext ctx, const char *cs) { } } else pthread_mutex_unlock(&db_handle.lock); + return 0; +} + + +void glite_lbu_FreeDBContext(glite_lbu_DBContext ctx) { + if (ctx) { + assert(ctx->mysql == NULL); + free(ctx->err.desc); + free(ctx); + } +} + + +int glite_lbu_DBConnect(glite_lbu_DBContext ctx, const char *cs) { if (db_connect(ctx, cs, &ctx->mysql) != 0) return STATUS(ctx); return 0; } @@ -1131,3 +1137,15 @@ static void set_time(MYSQL_TIME *mtime, const time_t time) { mtime->minute = tm.tm_min; mtime->second = tm.tm_sec; } + + +static void glite_lbu_DBCleanup(void) { + pthread_mutex_lock(&db_handle.lock); + if (db_handle.lib) { + dlclose(db_handle.lib); + db_handle.lib = NULL; + } + pthread_mutex_unlock(&db_handle.lock); +} + + -- 1.8.2.3