X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fcats%2Fmysql.c;h=a8cd052bbd89dcded1e2ee4d802da5a407e16770;hb=27c6094b93454811a6e966558ec187f8ad5a229c;hp=a35e21d6c8c73d9d95489481bdf870be8645473a;hpb=f7fb2261ab648bfc02a32773b7a5a2201783e189;p=bacula%2Fbacula diff --git a/bacula/src/cats/mysql.c b/bacula/src/cats/mysql.c index a35e21d6c8..a8cd052bbd 100644 --- a/bacula/src/cats/mysql.c +++ b/bacula/src/cats/mysql.c @@ -9,7 +9,7 @@ */ /* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2004 Kern Sibbald and John Walker This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -56,18 +56,26 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; * never have errors, or it is really fatal. */ B_DB * -db_init_database(char *db_name, char *db_user, char *db_password) +db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char *db_password, + const char *db_address, int db_port, const char *db_socket, + int mult_db_connections) { B_DB *mdb; + if (!db_user) { + Jmsg(jcr, M_FATAL, 0, _("A user name for MySQL must be supplied.\n")); + return NULL; + } P(mutex); /* lock DB queue */ /* Look to see if DB already open */ - for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) { - if (strcmp(mdb->db_name, db_name) == 0) { - Dmsg2(100, "DB REopen %d %s\n", mdb->ref_count, db_name); - mdb->ref_count++; - V(mutex); - return mdb; /* already open */ + if (!mult_db_connections) { + for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) { + if (strcmp(mdb->db_name, db_name) == 0) { + Dmsg2(100, "DB REopen %d %s\n", mdb->ref_count, db_name); + mdb->ref_count++; + V(mutex); + return mdb; /* already open */ + } } } Dmsg0(100, "db_open first time\n"); @@ -75,12 +83,26 @@ db_init_database(char *db_name, char *db_user, char *db_password) memset(mdb, 0, sizeof(B_DB)); mdb->db_name = bstrdup(db_name); mdb->db_user = bstrdup(db_user); - mdb->db_password = bstrdup(db_password); + if (db_password) { + mdb->db_password = bstrdup(db_password); + } + if (db_address) { + mdb->db_address = bstrdup(db_address); + } + if (db_socket) { + mdb->db_socket = bstrdup(db_socket); + } + mdb->db_port = db_port; mdb->have_insert_id = TRUE; mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */ *mdb->errmsg = 0; mdb->cmd = get_pool_memory(PM_EMSG); /* get command buffer */ + mdb->cached_path = get_pool_memory(PM_FNAME); + mdb->cached_path_id = 0; mdb->ref_count = 1; + mdb->fname = get_pool_memory(PM_FNAME); + mdb->path = get_pool_memory(PM_FNAME); + mdb->esc_name = get_pool_memory(PM_FNAME); qinsert(&db_list, &mdb->bq); /* put db in list */ V(mutex); return mdb; @@ -88,94 +110,107 @@ db_init_database(char *db_name, char *db_user, char *db_password) /* * Now actually open the database. This can generate errors, - * which are returned in the errmsg + * which are returned in the errmsg + * + * DO NOT close the database or free(mdb) here !!!! */ int -db_open_database(B_DB *mdb) +db_open_database(JCR *jcr, B_DB *mdb) { + int errstat; + P(mutex); if (mdb->connected) { V(mutex); return 1; } mdb->connected = FALSE; -#ifdef needed - if (pthread_mutex_init(&mdb->mutex, NULL) != 0) { - Mmsg1(&mdb->errmsg, "Unable to initialize DB mutex. ERR=%s\n", strerror(errno)); - V(mutex); - return 0; - } -#endif - if (rwl_init(&mdb->lock) != 0) { - Mmsg1(&mdb->errmsg, "Unable to initialize DB lock. ERR=%s\n", strerror(errno)); + if ((errstat=rwl_init(&mdb->lock)) != 0) { + Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), + strerror(errstat)); V(mutex); return 0; } /* connect to the database */ +#ifdef HAVE_EMBEDDED_MYSQL + mysql_server_init(0, NULL, NULL); +#endif mysql_init(&(mdb->mysql)); Dmsg0(50, "mysql_init done\n"); - mdb->db = mysql_real_connect( - &(mdb->mysql), /* db */ - NULL, /* default = localhost */ - mdb->db_user, /* login name */ - mdb->db_password, /* password */ - mdb->db_name, /* database name */ - 0, /* default port */ - NULL, /* default = socket */ - 0); /* flags = none */ - - /* If no connect, try once more incase it is a timing problem */ - if (mdb->db == NULL) { + /* If connection fails, try at 5 sec intervals for 30 seconds. */ + for (int retry=0; retry < 6; retry++) { mdb->db = mysql_real_connect( &(mdb->mysql), /* db */ - NULL, /* default = localhost */ + mdb->db_address, /* default = localhost */ mdb->db_user, /* login name */ mdb->db_password, /* password */ mdb->db_name, /* database name */ - 0, /* default port */ - NULL, /* default = socket */ - 0); /* flags = none */ + mdb->db_port, /* default port */ + mdb->db_socket, /* default = socket */ + CLIENT_FOUND_ROWS); /* flags */ + + /* If no connect, try once more in case it is a timing problem */ + if (mdb->db != NULL) { + break; + } + bmicrosleep(5,0); } - + Dmsg0(50, "mysql_real_connect done\n"); - Dmsg3(50, "db_user=%s db_name=%s db_password=%s\n", mdb->db_user, mdb->db_name, - mdb->db_password==NULL?"(NULL)":mdb->db_password); - + Dmsg3(50, "db_user=%s db_name=%s db_password=%s\n", mdb->db_user, mdb->db_name, + mdb->db_password==NULL?"(NULL)":mdb->db_password); + if (mdb->db == NULL) { - Mmsg2(&mdb->errmsg, _("Unable to connect to MySQL server. \n\ -Database=%s User=%s\n\ -It is probably not running or your password is incorrect.\n"), + Mmsg2(&mdb->errmsg, _("Unable to connect to MySQL server. \n" +"Database=%s User=%s\n" +"It is probably not running or your password is incorrect.\n"), mdb->db_name, mdb->db_user); V(mutex); return 0; } - if (!check_tables_version(mdb)) { + if (!check_tables_version(jcr, mdb)) { V(mutex); return 0; } +#ifdef HAVE_THREAD_SAFE_MYSQL + my_thread_init(); +#endif + mdb->connected = TRUE; V(mutex); return 1; } void -db_close_database(B_DB *mdb) +db_close_database(JCR *jcr, B_DB *mdb) { + if (!mdb) { + return; + } P(mutex); mdb->ref_count--; +#ifdef HAVE_TREAD_SAFE_MYSQL + my_thread_end(); +#endif if (mdb->ref_count == 0) { qdchain(&mdb->bq); if (mdb->connected && mdb->db) { sql_close(mdb); +#ifdef HAVE_EMBEDDED_MYSQL + mysql_server_end(); +#endif } -/* pthread_mutex_destroy(&mdb->mutex); */ - rwl_destroy(&mdb->lock); + rwl_destroy(&mdb->lock); free_pool_memory(mdb->errmsg); free_pool_memory(mdb->cmd); + free_pool_memory(mdb->cached_path); + free_pool_memory(mdb->fname); + free_pool_memory(mdb->path); + free_pool_memory(mdb->esc_name); if (mdb->db_name) { free(mdb->db_name); } @@ -185,6 +220,12 @@ db_close_database(B_DB *mdb) if (mdb->db_password) { free(mdb->db_password); } + if (mdb->db_address) { + free(mdb->db_address); + } + if (mdb->db_socket) { + free(mdb->db_socket); + } free(mdb); } V(mutex); @@ -193,34 +234,94 @@ db_close_database(B_DB *mdb) /* * Return the next unique index (auto-increment) for * the given table. Return NULL on error. - * + * * For MySQL, NULL causes the auto-increment value * to be updated. */ -char *db_next_index(B_DB *mdb, char *table) +int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index) { - return "NULL"; -} - + strcpy(index, "NULL"); + return 1; +} +/* + * Escape strings so that MySQL is happy + * + * NOTE! len is the length of the old string. Your new + * string must be long enough (max 2*old+1) to hold + * the escaped output. + */ void db_escape_string(char *snew, char *old, int len) { mysql_escape_string(snew, old, len); + +#ifdef DO_IT_MYSELF + +/* Should use mysql_real_escape_string ! */ +unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length); + + char *n, *o; + + n = snew; + o = old; + while (len--) { + switch (*o) { + case 0: + *n++= '\\'; + *n++= '0'; + o++; + break; + case '\n': + *n++= '\\'; + *n++= 'n'; + o++; + break; + case '\r': + *n++= '\\'; + *n++= 'r'; + o++; + break; + case '\\': + *n++= '\\'; + *n++= '\\'; + o++; + break; + case '\'': + *n++= '\\'; + *n++= '\''; + o++; + break; + case '"': + *n++= '\\'; + *n++= '"'; + o++; + break; + case '\032': + *n++= '\\'; + *n++= 'Z'; + o++; + break; + default: + *n++= *o++; + } + } + *n = 0; +#endif } /* * Submit a general SQL command (cmd), and for each row returned, * the sqlite_handler is called with the ctx. */ -int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void *ctx) +int db_sql_query(B_DB *mdb, const char *query, DB_RESULT_HANDLER *result_handler, void *ctx) { SQL_ROW row; - + db_lock(mdb); if (sql_query(mdb, query) != 0) { - Mmsg(&mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror(mdb)); + Mmsg(mdb->errmsg, _("Query failed: %s: ERR=%s\n"), query, sql_strerror(mdb)); db_unlock(mdb); return 0; } @@ -241,80 +342,4 @@ int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void } - -static void -list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx) -{ - SQL_FIELD *field; - unsigned int i, j; - - sql_field_seek(mdb, 0); - send(ctx, "+"); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - for (j = 0; j < field->max_length + 2; j++) - send(ctx, "-"); - send(ctx, "+"); - } - send(ctx, "\n"); -} - -void -list_result(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx) -{ - SQL_FIELD *field; - SQL_ROW row; - unsigned int i, col_len; - char buf[2000], ewc[30]; - - if (mdb->result == NULL) { - return; - } - /* determine column display widths */ - sql_field_seek(mdb, 0); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - if (IS_NUM(field->type) && field->max_length > 0) { /* fixup for commas */ - field->max_length += (field->max_length - 1) / 3; - } - col_len = strlen(field->name); - if (col_len < field->max_length) - col_len = field->max_length; - if (col_len < 4 && !IS_NOT_NULL(field->flags)) - col_len = 4; /* 4 = length of the word "NULL" */ - field->max_length = col_len; /* reset column info */ - } - - list_dashes(mdb, send, ctx); - send(ctx, "|"); - sql_field_seek(mdb, 0); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - sprintf(buf, " %-*s |", field->max_length, field->name); - send(ctx, buf); - } - send(ctx, "\n"); - list_dashes(mdb, send, ctx); - - while ((row = sql_fetch_row(mdb)) != NULL) { - sql_field_seek(mdb, 0); - send(ctx, "|"); - for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - if (row[i] == NULL) { - sprintf(buf, " %-*s |", field->max_length, "NULL"); - } else if (IS_NUM(field->type)) { - sprintf(buf, " %*s |", field->max_length, - add_commas(row[i], ewc)); - } else { - sprintf(buf, " %-*s |", field->max_length, row[i]); - } - send(ctx, buf); - } - send(ctx, "\n"); - } - list_dashes(mdb, send, ctx); -} - - #endif /* HAVE_MYSQL */