Implemented transaction support test. Using transactions can be forced by -b option.
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Fri, 30 Jun 2006 13:06:26 +0000 (13:06 +0000)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Fri, 30 Jun 2006 13:06:26 +0000 (13:06 +0000)
org.glite.lb.server/interface/lbs_db.h
org.glite.lb.server/src/bkserverd.c
org.glite.lb.server/src/lbs_db.c
org.glite.lb.server/test/test_query_events.cpp

index df557c0..8febdf0 100644 (file)
@@ -20,7 +20,7 @@ typedef struct _edg_wll_Stmt *edg_wll_Stmt;
 
 edg_wll_ErrorCode edg_wll_DBConnect(
        edg_wll_Context,        /* INOUT: */
-       char *          /* IN: connect string user/password@host:database */
+       const char *            /* IN: connect string user/password@host:database */
 );
 
 
index 7567f5f..24f5929 100644 (file)
@@ -120,6 +120,7 @@ static int                          hardJobsLimit = 0;
 static int                             hardEventsLimit = 0;
 static int                             hardRespSizeLimit = 0;
 static char                       *dbstring = NULL,*fake_host = NULL;
+int                                    transactions = -1;
 static int                             fake_port = 0;
 static char                      **super_users = NULL;
 static int                             slaves = 10,
@@ -177,11 +178,11 @@ static struct option opts[] = {
 #ifdef LB_PERF
        {"perf-sink",           1, NULL,        'K'},
 #endif
-       {"transactions",        0,      NULL,   'b'},
+       {"transactions",        1,      NULL,   'b'},
        {NULL,0,NULL,0}
 };
 
-static const char *get_opt_string = "a:c:k:C:V:p:drm:ns:l:L:N:i:S:D:X:Y:T:t:J:jzb"
+static const char *get_opt_string = "a:c:k:C:V:p:drm:ns:l:L:N:i:S:D:X:Y:T:t:J:jzb:"
 #ifdef GLITE_LB_SERVER_WITH_WS
        "w:"
 #endif
@@ -194,7 +195,7 @@ static void usage(char *me)
 {
        fprintf(stderr,"usage: %s [option]\n"
                "\t-a, --address\t use this server address (may be faked for debugging)\n"
-               "\t-b, --transactions\t use transactions\n"
+               "\t-b, --transactions\t transactions switch\n"
                "\t-k, --key\t private key file\n"
                "\t-c, --cert\t certificate file\n"
                "\t-C, --CAdir\t trusted certificates directory\n"
@@ -285,6 +286,7 @@ struct clnt_data_t {
 #ifdef GLITE_LB_SERVER_WITH_WS
        struct soap                        *soap;
 #endif /* GLITE_LB_SERVER_WITH_WS */
+       int                         use_transactions;
        void                               *mysql;
        edg_wll_QueryRec          **job_index;
        edg_wll_IColumnRec         *job_index_cols;
@@ -312,7 +314,6 @@ int main(int argc, char *argv[])
        struct timeval          to;
        int                     request_timeout = REQUEST_TIMEOUT;
        int                     silent = 0;
-       int                     transactions = 0;
 
 
 
@@ -336,7 +337,7 @@ int main(int argc, char *argv[])
 
        while ((opt = getopt_long(argc,argv,get_opt_string,opts,NULL)) != EOF) switch (opt) {
                case 'a': fake_host = strdup(optarg); break;
-               case 'b': transactions = 1; break;
+               case 'b': transactions = atoi(optarg); break;
                case 'c': server_cert = optarg; break;
                case 'k': server_key = optarg; break;
                case 'C': cadir = optarg; break;
@@ -564,7 +565,6 @@ a.sin_addr.s_addr = INADDR_ANY;
 
        /* Just check the database and let it be. The slaves do the job. */
        edg_wll_InitContext(&ctx);
-       ctx->use_transactions = transactions;
        wait_for_open(ctx, dbstring);
 
        if (edg_wll_DBCheckVersion(ctx))
@@ -645,6 +645,7 @@ int bk_clnt_data_init(void **data)
        if ( !dbstring ) dbstring = getenv("LBDB");
        wait_for_open(ctx, dbstring);
        cdata->mysql = ctx->mysql;
+       cdata->use_transactions = ctx->use_transactions;
 
        if ( edg_wll_QueryJobIndices(ctx, &job_index, NULL) )
        {
@@ -753,6 +754,7 @@ int bk_handle_connection(int conn, struct timeval *timeout, void *data)
        /* Shared structures (pointers)
         */
        ctx->mysql = cdata->mysql;
+       ctx->use_transactions = cdata->use_transactions;
        ctx->job_index_cols = cdata->job_index_cols;
        ctx->job_index = cdata->job_index; 
        
@@ -1261,6 +1263,14 @@ 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 (!ctx->use_transactions && transactions != 0) {
+               fprintf(stderr, "[%d]: transaction aren't supported!\n", getpid());
+       }
+       if (transactions >= 0) {
+               ctx->use_transactions = transactions;
+               fprintf(stderr, "[%d]: transactions forced from %d to %d\n", getpid(), ctx->use_transactions, transactions);
+       }
 }
 
 static void free_hostent(struct hostent *h){
index 6a28fa7..9f169ba 100644 (file)
@@ -27,7 +27,8 @@ struct _edg_wll_Stmt {
        edg_wll_Context ctx;
 };
 
-edg_wll_ErrorCode edg_wll_DBConnect(edg_wll_Context ctx,char *cs)
+
+static edg_wll_ErrorCode db_connect(edg_wll_Context ctx, const char *cs, MYSQL **mysql)
 {
        char    *buf = NULL;
        char    *host,*user,*pw,*db; 
@@ -35,10 +36,10 @@ edg_wll_ErrorCode edg_wll_DBConnect(edg_wll_Context ctx,char *cs)
 
        if (!cs) cs = DEFAULTCS;
 
-       if (!(ctx->mysql = (void *) mysql_init(NULL))) 
+       if (!(*mysql = mysql_init(NULL))) 
                return edg_wll_SetError(ctx,ENOMEM,NULL);
 
-       mysql_options(ctx->mysql, MYSQL_READ_DEFAULT_FILE, "my");
+       mysql_options(*mysql, MYSQL_READ_DEFAULT_FILE, "my");
 
        host = user = pw = db = NULL;
 
@@ -61,24 +62,81 @@ edg_wll_ErrorCode edg_wll_DBConnect(edg_wll_Context ctx,char *cs)
        /* ljocha: CLIENT_FOUND_ROWS added to make authorization check
         * working in update_notif(). 
         * Hope it does not break anything else */ 
-       if (!mysql_real_connect((MYSQL *) ctx->mysql,host,user,pw,db,0,NULL,CLIENT_FOUND_ROWS)) {
+       if (!mysql_real_connect(*mysql,host,user,pw,db,0,NULL,CLIENT_FOUND_ROWS)) {
                free(buf);
                return my_err();
        }
 
        free(buf);
+       return edg_wll_ResetError(ctx);
+}
+
+
+static void db_close(MYSQL *mysql) {
+       mysql_close(mysql);
+}
+
+
+static int transaction_test(edg_wll_Context ctx, MYSQL *m2) {
+       MYSQL *m1;
+       char *desc;
+       int retval;
+       edg_wll_ErrorCode err;
+
+       ctx->use_transactions = 1;
+
+       m1 = (MYSQL *)ctx->mysql;
+       edg_wll_ExecStmt(ctx, "drop table test", NULL);
+       if (edg_wll_ExecStmt(ctx, "create table test (item int)", NULL) != 0) goto err1;
+       if (edg_wll_Transaction(ctx) != 0) goto err2;
+       if (edg_wll_ExecStmt(ctx, "insert into test (item) values (1)", NULL) != 1) goto err2;
+
+       ctx->mysql = (void *)m2;
+       if ((retval = edg_wll_ExecStmt(ctx, "select item from test", NULL)) == -1) goto err2;
+       ctx->use_transactions = (retval == 0);
+
+       ctx->mysql = (void *)m1;
+       if (edg_wll_Commit(ctx) != 0) goto err2;
+       if (edg_wll_ExecStmt(ctx, "drop table test", NULL) != 0) goto err1;
+
 #ifdef LBS_DB_PROFILE
        fprintf(stderr, "[%d] use_transactions = %d\n", getpid(), ctx->use_transactions);
 #endif
-       return edg_wll_ResetError(ctx);
+
+       return 0;
+err2:
+       edg_wll_Error(ctx, &err, &desc);
+       edg_wll_ExecStmt(ctx, "drop table test", NULL);
+       edg_wll_SetError(ctx, err, desc);
+err1:
+       return edg_wll_Error(ctx, NULL, NULL);
 }
 
+
+edg_wll_ErrorCode edg_wll_DBConnect(edg_wll_Context ctx, const char *cs)
+{
+       MYSQL *m2;
+       int errcode;
+
+       if ((errcode = db_connect(ctx, cs, (MYSQL **)&ctx->mysql)) == 0) {
+               if ((errcode = db_connect(ctx, cs, (MYSQL **)&m2)) == 0) {
+                       errcode = transaction_test(ctx, m2);
+                       db_close(m2);
+               }
+               if (errcode) edg_wll_DBClose(ctx);
+       }
+
+       return errcode;
+}
+
+
 void edg_wll_DBClose(edg_wll_Context ctx)
 {
-       mysql_close((MYSQL *) ctx->mysql);
+       db_close((MYSQL *) ctx->mysql);
        ctx->mysql = NULL;
 }
 
+
 int edg_wll_ExecStmt(edg_wll_Context ctx,char *txt,edg_wll_Stmt *stmt)
 {
        int     err;
@@ -233,41 +291,32 @@ int edg_wll_DBCheckVersion(edg_wll_Context ctx)
 
 
 int edg_wll_Transaction(edg_wll_Context ctx) {
-       int err = 0;
-
        if (ctx->use_transactions) {
-               err = edg_wll_ExecStmt(ctx, "set autocommit=0", NULL);
-               if (!err)
-                       return edg_wll_ExecStmt(ctx, "begin", NULL);
+               if (edg_wll_ExecStmt(ctx, "set autocommit=0", NULL) < 0) goto err;
+               if (edg_wll_ExecStmt(ctx, "begin", NULL) < 0) goto err;
        }
-
-       return err;
+err:
+       return edg_wll_Error(ctx, NULL, NULL);
 }
 
 
 int edg_wll_Commit(edg_wll_Context ctx) {
-       int err = 0;
-
        if (ctx->use_transactions) {
-               err = edg_wll_ExecStmt(ctx, "commit", NULL);
-               if (!err)
-                       return edg_wll_ExecStmt(ctx, "set autocommit=1", NULL);
+               if (edg_wll_ExecStmt(ctx, "commit", NULL) < 0) goto err;
+               if (edg_wll_ExecStmt(ctx, "set autocommit=1", NULL) < 0) goto err;
        }
-
-       return err;
+err:
+       return edg_wll_Error(ctx, NULL, NULL);
 }
 
 
 int edg_wll_Rollback(edg_wll_Context ctx) {
-       int err = 0;
-
        if (ctx->use_transactions) { 
-               err = edg_wll_ExecStmt(ctx, "rollback", NULL);
-               if (!err)
-                       return edg_wll_ExecStmt(ctx, "set autocommit=1", NULL);
+               if (edg_wll_ExecStmt(ctx, "rollback", NULL) < 0) goto err;
+               if (edg_wll_ExecStmt(ctx, "set autocommit=1", NULL) < 0) goto err;
        }
-
-       return err;
+err:
+       return edg_wll_Error(ctx, NULL, NULL);
 }
 
 
index 8234f99..cda12eb 100644 (file)
@@ -131,7 +131,7 @@ int edg_wll_QueryColumns(edg_wll_Stmt stmt, char**cols) { return 0; }
 char *edg_wll_TimeToDB(long t) { return NULL; }
 
 time_t edg_wll_DBToTime(char *c) { return (time_t)-1; }
-edg_wll_ErrorCode edg_wll_DBConnect(edg_wll_Context ctx, char*str) { 
+edg_wll_ErrorCode edg_wll_DBConnect(edg_wll_Context ctx, const char*str) { 
   return (edg_wll_ErrorCode)0;
 }