Add runtime versus compile time mysql version check,
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Tue, 4 Dec 2007 18:33:28 +0000 (18:33 +0000)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Tue, 4 Dec 2007 18:33:28 +0000 (18:33 +0000)
distinguish between unrecoverable errors from init context and errors during connection from db module in bkserver.

org.glite.lb.common/interface/context.h
org.glite.lb.common/src/context.c
org.glite.lb.server/src/bkindex.c
org.glite.lb.server/src/bkserverd.c
org.glite.lb.server/src/openserver.c
org.glite.lbjp-common.db/Makefile
org.glite.lbjp-common.db/src/db.c

index 7f29593..ad366de 100644 (file)
@@ -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 :-). */
index 33f7ef5..6e3e53e 100644 (file)
@@ -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",
index 38490c8..772c289 100644 (file)
@@ -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);
index 8bae798..cc4bf3b 100644 (file)
@@ -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){
index dfac76d..9b043d5 100644 (file)
@@ -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;
 }
 
index 767badb..62a04bd 100644 (file)
@@ -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}
index 1c8e663..5624a05 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <mysql.h>
 #include <mysqld_error.h>
+#include <mysql_version.h>
 #include <errmsg.h>
 
 #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);
+}
+
+