X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fcats%2Fsql.c;h=bbee8561b840073c21884939587ba6c6b9c0eead;hb=d6a2978cea17ce237b4ea9c71853cb96b9f4416f;hp=56b9ccaf0421b7395bf77d3ef953f4d22e671403;hpb=fcb3b570da979395c9d89726bc8335b0b4d22148;p=bacula%2Fbacula diff --git a/bacula/src/cats/sql.c b/bacula/src/cats/sql.c index 56b9ccaf04..bbee8561b8 100644 --- a/bacula/src/cats/sql.c +++ b/bacula/src/cats/sql.c @@ -20,7 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Bacula® is a registered trademark of John Walker. + Bacula® is a registered trademark of Kern Sibbald. The licensor of Bacula is the Free Software Foundation Europe (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. @@ -50,16 +50,16 @@ uint32_t bacula_db_version = 0; -int db_type = -1; +int db_type = -1; /* SQL engine type index */ /* Forward referenced subroutines */ void print_dashes(B_DB *mdb); void print_result(B_DB *mdb); -B_DB *db_init(JCR *jcr, const char *db_driver, const char *db_name, const char *db_user, - const char *db_password, const char *db_address, int db_port, +B_DB *db_init(JCR *jcr, const char *db_driver, 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) -{ +{ #ifdef HAVE_DBI char *p; if (!db_driver) { @@ -68,13 +68,15 @@ B_DB *db_init(JCR *jcr, const char *db_driver, const char *db_name, const char * if (strlen(db_driver) < 5 || db_driver[3] != ':' || strncasecmp(db_driver, "dbi", 3) != 0) { Jmsg0(jcr, M_ABORT, 0, _("Invalid driver type, must be \"dbi:\"\n")); } - p = (char *)(db_driver + 4); + p = (char *)(db_driver + 4); if (strcasecmp(p, "mysql") == 0) { db_type = SQL_TYPE_MYSQL; } else if (strcasecmp(p, "postgresql") == 0) { db_type = SQL_TYPE_POSTGRESQL; } else if (strcasecmp(p, "sqlite") == 0) { db_type = SQL_TYPE_SQLITE; + } else if (strcasecmp(p, "sqlite3") == 0) { + db_type = SQL_TYPE_SQLITE3; } else { Jmsg1(jcr, M_ABORT, 0, _("Unknown database type: %s\n"), p); } @@ -85,14 +87,14 @@ B_DB *db_init(JCR *jcr, const char *db_driver, const char *db_name, const char * #elif HAVE_SQLITE db_type = SQL_TYPE_SQLITE; #elif HAVE_SQLITE3 - db_type = SQL_TYPE_SQLITE; + db_type = SQL_TYPE_SQLITE3; #endif return db_init_database(jcr, db_name, db_user, db_password, db_address, db_port, db_socket, mult_db_connections); } -dbid_list::dbid_list() +dbid_list::dbid_list() { memset(this, 0, sizeof(dbid_list)); max_ids = 1000; @@ -101,8 +103,8 @@ dbid_list::dbid_list() PurgedFiles = NULL; } -dbid_list::~dbid_list() -{ +dbid_list::~dbid_list() +{ free(DBId); } @@ -390,6 +392,41 @@ void db_start_transaction(JCR *jcr, B_DB *mdb) } db_unlock(mdb); #endif + +#ifdef HAVE_DBI + if (db_type == SQL_TYPE_SQLITE) { + if (!mdb->allow_transactions) { + return; + } + db_lock(mdb); + /* Allow only 10,000 changes per transaction */ + if (mdb->transaction && mdb->changes > 10000) { + db_end_transaction(jcr, mdb); + } + if (!mdb->transaction) { + //my_sqlite_query(mdb, "BEGIN"); /* begin transaction */ + db_sql_query(mdb, "BEGIN", NULL, NULL); /* begin transaction */ + Dmsg0(400, "Start SQLite transaction\n"); + mdb->transaction = 1; + } + db_unlock(mdb); + } else if (db_type == SQL_TYPE_POSTGRESQL) { + if (!mdb->allow_transactions) { + return; + } + db_lock(mdb); + /* Allow only 25,000 changes per transaction */ + if (mdb->transaction && mdb->changes > 25000) { + db_end_transaction(jcr, mdb); + } + if (!mdb->transaction) { + db_sql_query(mdb, "BEGIN", NULL, NULL); /* begin transaction */ + Dmsg0(400, "Start PosgreSQL transaction\n"); + mdb->transaction = 1; + } + db_unlock(mdb); + } +#endif } void db_end_transaction(JCR *jcr, B_DB *mdb) @@ -437,6 +474,35 @@ void db_end_transaction(JCR *jcr, B_DB *mdb) mdb->changes = 0; db_unlock(mdb); #endif + +#ifdef HAVE_DBI + if (db_type == SQL_TYPE_SQLITE) { + if (!mdb->allow_transactions) { + return; + } + db_lock(mdb); + if (mdb->transaction) { + //my_sqlite_query(mdb, "COMMIT"); /* end transaction */ + db_sql_query(mdb, "COMMIT", NULL, NULL); /* end transaction */ + mdb->transaction = 0; + Dmsg1(400, "End SQLite transaction changes=%d\n", mdb->changes); + } + mdb->changes = 0; + db_unlock(mdb); + } else if (db_type == SQL_TYPE_POSTGRESQL) { + if (!mdb->allow_transactions) { + return; + } + db_lock(mdb); + if (mdb->transaction) { + db_sql_query(mdb, "COMMIT", NULL, NULL); /* end transaction */ + mdb->transaction = 0; + Dmsg1(400, "End PostgreSQL transaction changes=%d\n", mdb->changes); + } + mdb->changes = 0; + db_unlock(mdb); + } +#endif } /* @@ -508,6 +574,9 @@ list_dashes(B_DB *mdb, DB_LIST_HANDLER *send, void *ctx) send(ctx, "+"); for (i = 0; i < sql_num_fields(mdb); i++) { field = sql_fetch_field(mdb); + if (!field) { + break; + } for (j = 0; j < (int)field->max_length + 2; j++) { send(ctx, "-"); } @@ -540,6 +609,9 @@ list_result(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type t for (i = 0; i < sql_num_fields(mdb); i++) { Dmsg1(800, "list_result processing field %d\n", i); field = sql_fetch_field(mdb); + if (!field) { + break; + } col_len = cstrlen(field->name); if (type == VERT_LIST) { if (col_len > max_len) { @@ -571,6 +643,9 @@ list_result(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type t for (i = 0; i < sql_num_fields(mdb); i++) { Dmsg1(800, "list_result looking at field %d\n", i); field = sql_fetch_field(mdb); + if (!field) { + break; + } bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, field->name); send(ctx, buf); } @@ -583,6 +658,9 @@ list_result(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type t send(ctx, "|"); for (i = 0; i < sql_num_fields(mdb); i++) { field = sql_fetch_field(mdb); + if (!field) { + break; + } if (row[i] == NULL) { bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, "NULL"); } else if (IS_NUM(field->type) && !jcr->gui && is_an_integer(row[i])) { @@ -605,6 +683,9 @@ vertical_list: sql_field_seek(mdb, 0); for (i = 0; i < sql_num_fields(mdb); i++) { field = sql_fetch_field(mdb); + if (!field) { + break; + } if (row[i] == NULL) { bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, "NULL"); } else if (IS_NUM(field->type) && !jcr->gui && is_an_integer(row[i])) { @@ -620,5 +701,67 @@ vertical_list: return; } +/* + * Open a new connexion to mdb catalog. This function is used + * by batch and accurate mode. + */ +bool db_open_batch_connexion(JCR *jcr, B_DB *mdb) +{ + int multi_db=false; + +#ifdef HAVE_BATCH_FILE_INSERT + multi_db=true; /* we force a new connexion only if batch insert is enabled */ +#endif + + if (!jcr->db_batch) { + jcr->db_batch = db_init_database(jcr, + mdb->db_name, + mdb->db_user, + mdb->db_password, + mdb->db_address, + mdb->db_port, + mdb->db_socket, + multi_db /* multi_db = true when using batch mode */); + if (!jcr->db_batch) { + Jmsg0(jcr, M_FATAL, 0, "Could not init batch connexion"); + return false; + } + + if (!db_open_database(jcr, jcr->db_batch)) { + Mmsg2(&jcr->db_batch->errmsg, _("Could not open database \"%s\": ERR=%s\n"), + jcr->db_batch->db_name, db_strerror(jcr->db_batch)); + Jmsg1(jcr, M_FATAL, 0, "%s", jcr->db_batch->errmsg); + return false; + } + Dmsg3(100, "initdb ref=%d connected=%d db=%p\n", jcr->db_batch->ref_count, + jcr->db_batch->connected, jcr->db_batch->db); + + } + return true; +} + +/* + * !!! WARNING !!! Use this function only when bacula is stopped. + * ie, after a fatal signal and before exiting the program + * Print information about a B_DB object. + */ +void _dbg_print_db(JCR *jcr, FILE *fp) +{ + B_DB *mdb = jcr->db; + + if (!mdb) { + return; + } + + fprintf(fp, "B_DB=%p db_name=%s db_user=%s connected=%i\n", + mdb, NPRTB(mdb->db_name), NPRTB(mdb->db_user), mdb->connected); + fprintf(fp, "\tcmd=\"%s\" changes=%i\n", NPRTB(mdb->cmd), mdb->changes); + if (mdb->lock.valid == RWLOCK_VALID) { + fprintf(fp, "\tRWLOCK=%p w_active=%i w_wait=%i\n", &mdb->lock, mdb->lock.w_active, mdb->lock.w_wait); +#ifndef HAVE_WIN32 + fprintf(fp, "\t\tthreadid=0x%x mutex=%p\n", (int)mdb->lock.writer_id, &mdb->lock.mutex); +#endif + } +} #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/