X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fcats%2Fsqlite.c;h=856a769699b286687682bd39a620031024c2004e;hb=a2bbe5fe90fa7b488146142f1c56af3e4da56867;hp=c0398f9aa8f52dc6658f849eb3fa31103c4dc8ea;hpb=66696d1cadedbb362c392dadce9a8ce275dd5d80;p=bacula%2Fbacula diff --git a/bacula/src/cats/sqlite.c b/bacula/src/cats/sqlite.c index c0398f9aa8..856a769699 100644 --- a/bacula/src/cats/sqlite.c +++ b/bacula/src/cats/sqlite.c @@ -1,41 +1,49 @@ /* - * Bacula Catalog Database routines specific to SQLite - * - * Kern Sibbald, January 2002 - * - * Version $Id$ - */ + Bacula® - The Network Backup Solution -/* - Copyright (C) 2002-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version two of the GNU General Public + License as published by the Free Software Foundation plus additions + that are listed in the file LICENSE. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + Bacula® is a registered trademark of John Walker. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * Bacula Catalog Database routines specific to SQLite + * + * Kern Sibbald, January 2002 + * + * Version $Id$ */ + /* The following is necessary so that we do not include * the dummy external definition of DB. */ -#define __SQL_C /* indicate that this is sql.c */ +#define __SQL_C /* indicate that this is sql.c */ #include "bacula.h" #include "cats.h" -#ifdef HAVE_SQLITE +#if HAVE_SQLITE || HAVE_SQLITE3 /* ----------------------------------------------------------------------- * @@ -44,8 +52,6 @@ * ----------------------------------------------------------------------- */ -extern const char *working_directory; - /* List of open databases */ static BQUEUE db_list = {&db_list, &db_list}; @@ -54,27 +60,58 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; int QueryDB(const char *file, int line, JCR *jcr, B_DB *db, char *select_cmd); +/* + * Retrieve database type + */ +const char * +db_get_type(void) +{ + return "SQLite"; +} + +/* + * When using mult_db_connections = 1, + * sqlite can be BUSY. We just need sleep a little in this case. + */ + +#ifdef HAVE_SQLITE3 +static int my_busy_handler(void *arg, int calls) +{ + bmicrosleep(0, 500); + return 1; +} +#else +static int my_busy_handler(void *arg, const char* p, int calls) +{ + bmicrosleep(0, 500); + return 1; +} +#endif + + /* * Initialize database data structure. In principal this should * never have errors, or it is really fatal. */ B_DB * 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) + const char *db_address, int db_port, const char *db_socket, + int mult_db_connections) { B_DB *mdb; - P(mutex); /* lock DB queue */ + P(mutex); /* lock DB queue */ /* Look to see if DB 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(300, "DB REopen %d %s\n", mdb->ref_count, db_name); - mdb->ref_count++; - V(mutex); - return mdb; /* already open */ - } + if (bstrcmp(mdb->db_name, db_name) && + bstrcmp(mdb->db_address, db_address) && + mdb->db_port == db_port) { + Dmsg2(300, "DB REopen %d %s\n", mdb->ref_count, db_name); + mdb->ref_count++; + V(mutex); + return mdb; /* already open */ + } } } Dmsg0(300, "db_open first time\n"); @@ -91,8 +128,9 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char mdb->fname = get_pool_memory(PM_FNAME); mdb->path = get_pool_memory(PM_FNAME); mdb->esc_name = get_pool_memory(PM_FNAME); + mdb->esc_path = get_pool_memory(PM_FNAME); mdb->allow_transactions = mult_db_connections; - qinsert(&db_list, &mdb->bq); /* put db in list */ + qinsert(&db_list, &mdb->bq); /* put db in list */ V(mutex); return mdb; } @@ -120,7 +158,7 @@ db_open_database(JCR *jcr, B_DB *mdb) if ((errstat=rwl_init(&mdb->lock)) != 0) { Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), - strerror(errstat)); + strerror(errstat)); V(mutex); return 0; } @@ -134,32 +172,52 @@ db_open_database(JCR *jcr, B_DB *mdb) strcat(db_name, ".db"); if (stat(db_name, &statbuf) != 0) { Mmsg1(&mdb->errmsg, _("Database %s does not exist, please create it.\n"), - db_name); + db_name); free(db_name); V(mutex); return 0; } + +#ifdef HAVE_SQLITE3 + int stat = sqlite3_open(db_name, &mdb->db); + if (stat != SQLITE_OK) { + mdb->sqlite_errmsg = (char *)sqlite3_errmsg(mdb->db); + sqlite3_close(mdb->db); + mdb->db = NULL; + } else { + mdb->sqlite_errmsg = NULL; + } + +#else mdb->db = sqlite_open( - db_name, /* database name */ - 644, /* mode */ - &mdb->sqlite_errmsg); /* error message */ + db_name, /* database name */ + 644, /* mode */ + &mdb->sqlite_errmsg); /* error message */ +#endif Dmsg0(300, "sqlite_open\n"); if (mdb->db == NULL) { Mmsg2(&mdb->errmsg, _("Unable to open Database=%s. ERR=%s\n"), - db_name, mdb->sqlite_errmsg ? mdb->sqlite_errmsg : _("unknown")); + db_name, mdb->sqlite_errmsg ? mdb->sqlite_errmsg : _("unknown")); free(db_name); V(mutex); return 0; - } + } + mdb->connected = true; free(db_name); if (!check_tables_version(jcr, mdb)) { V(mutex); return 0; } - mdb->connected = TRUE; + /* set busy handler to wait when we use mult_db_connections = 1 */ +#ifdef HAVE_SQLITE3 + sqlite3_busy_handler(mdb->db, my_busy_handler, NULL); +#else + sqlite_busy_handler(mdb->db, my_busy_handler, NULL); +#endif + V(mutex); return 1; } @@ -170,12 +228,14 @@ db_close_database(JCR *jcr, B_DB *mdb) if (!mdb) { return; } + db_end_transaction(jcr, mdb); P(mutex); + sql_free_result(mdb); mdb->ref_count--; if (mdb->ref_count == 0) { qdchain(&mdb->bq); if (mdb->connected && mdb->db) { - sqlite_close(mdb->db); + sqlite_close(mdb->db); } rwl_destroy(&mdb->lock); free_pool_memory(mdb->errmsg); @@ -184,8 +244,9 @@ db_close_database(JCR *jcr, B_DB *mdb) free_pool_memory(mdb->fname); free_pool_memory(mdb->path); free_pool_memory(mdb->esc_name); + free_pool_memory(mdb->esc_path); if (mdb->db_name) { - free(mdb->db_name); + free(mdb->db_name); } free(mdb); } @@ -198,6 +259,7 @@ db_close_database(JCR *jcr, B_DB *mdb) */ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index) { +#ifdef xxxx SQL_ROW row; db_lock(mdb); @@ -227,6 +289,8 @@ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index) sql_free_result(mdb); db_unlock(mdb); +#endif + strcpy(index, "NULL"); return 1; } @@ -235,8 +299,8 @@ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index) * Escape strings so that SQLite 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. + * string must be long enough (max 2*old+1) to hold + * the escaped output. */ void db_escape_string(char *snew, char *old, int len) @@ -248,18 +312,18 @@ db_escape_string(char *snew, char *old, int len) while (len--) { switch (*o) { case '\'': - *n++ = '\''; - *n++ = '\''; - o++; - break; + *n++ = '\''; + *n++ = '\''; + o++; + break; case 0: - *n++ = '\\'; - *n++ = 0; - o++; - break; + *n++ = '\\'; + *n++ = 0; + o++; + break; default: - *n++ = *o++; - break; + *n++ = *o++; + break; } } *n = 0; @@ -294,7 +358,11 @@ int db_sql_query(B_DB *mdb, const char *query, DB_RESULT_HANDLER *result_handler db_lock(mdb); if (mdb->sqlite_errmsg) { +#ifdef HAVE_SQLITE3 + sqlite3_free(mdb->sqlite_errmsg); +#else actuallyfree(mdb->sqlite_errmsg); +#endif mdb->sqlite_errmsg = NULL; } rh_data.result_handler = result_handler; @@ -312,17 +380,21 @@ int db_sql_query(B_DB *mdb, const char *query, DB_RESULT_HANDLER *result_handler /* * Submit a sqlite query and retrieve all the data */ -int my_sqlite_query(B_DB *mdb, char *cmd) +int my_sqlite_query(B_DB *mdb, const char *cmd) { int stat; if (mdb->sqlite_errmsg) { +#ifdef HAVE_SQLITE3 + sqlite3_free(mdb->sqlite_errmsg); +#else actuallyfree(mdb->sqlite_errmsg); +#endif mdb->sqlite_errmsg = NULL; } - stat = sqlite_get_table(mdb->db, cmd, &mdb->result, &mdb->nrow, &mdb->ncolumn, - &mdb->sqlite_errmsg); - mdb->row = 0; /* row fetched */ + stat = sqlite_get_table(mdb->db, (char *)cmd, &mdb->result, &mdb->nrow, &mdb->ncolumn, + &mdb->sqlite_errmsg); + mdb->row = 0; /* row fetched */ return stat; } @@ -342,7 +414,7 @@ void my_sqlite_free_table(B_DB *mdb) if (mdb->fields_defined) { for (i=0; i < sql_num_fields(mdb); i++) { - free(mdb->fields[i]); + free(mdb->fields[i]); } free(mdb->fields); mdb->fields_defined = false; @@ -361,23 +433,23 @@ void my_sqlite_field_seek(B_DB *mdb, int field) if (!mdb->fields_defined && sql_num_fields(mdb) > 0) { mdb->fields = (SQL_FIELD **)malloc(sizeof(SQL_FIELD) * mdb->ncolumn); for (i=0; i < sql_num_fields(mdb); i++) { - mdb->fields[i] = (SQL_FIELD *)malloc(sizeof(SQL_FIELD)); - mdb->fields[i]->name = mdb->result[i]; - mdb->fields[i]->length = strlen(mdb->fields[i]->name); - mdb->fields[i]->max_length = mdb->fields[i]->length; - for (j=1; j <= mdb->nrow; j++) { - int len; - if (mdb->result[i + mdb->ncolumn *j]) { - len = (uint32_t)strlen(mdb->result[i + mdb->ncolumn * j]); - } else { - len = 0; - } - if (len > mdb->fields[i]->max_length) { - mdb->fields[i]->max_length = len; - } - } - mdb->fields[i]->type = 0; - mdb->fields[i]->flags = 1; /* not null */ + mdb->fields[i] = (SQL_FIELD *)malloc(sizeof(SQL_FIELD)); + mdb->fields[i]->name = mdb->result[i]; + mdb->fields[i]->length = cstrlen(mdb->fields[i]->name); + mdb->fields[i]->max_length = mdb->fields[i]->length; + for (j=1; j <= mdb->nrow; j++) { + int len; + if (mdb->result[i + mdb->ncolumn *j]) { + len = (uint32_t)cstrlen(mdb->result[i + mdb->ncolumn * j]); + } else { + len = 0; + } + if (len > mdb->fields[i]->max_length) { + mdb->fields[i]->max_length = len; + } + } + mdb->fields[i]->type = 0; + mdb->fields[i]->flags = 1; /* not null */ } mdb->fields_defined = TRUE; } @@ -393,6 +465,16 @@ SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb) return mdb->fields[mdb->field++]; } +char *my_sqlite_batch_lock_query = "BEGIN"; +char *my_sqlite_batch_unlock_query = "COMMIT"; +char *my_sqlite_batch_fill_path_query = "INSERT INTO Path (Path) " + " SELECT DISTINCT Path FROM batch " + " EXCEPT SELECT Path FROM Path "; + +char *my_sqlite_batch_fill_filename_query = "INSERT INTO Filename (Name) " + " SELECT DISTINCT Name FROM batch " + " EXCEPT SELECT Name FROM Filename "; + #endif /* HAVE_SQLITE */