]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/cats/sql.c
Fix SQL warning message about concurrency pointed out by Graham
[bacula/bacula] / bacula / src / cats / sql.c
index 6b8d3faf87a537a73769e89f3769f3009ed16742..54e4671c69e3c338af675a68ce4c7d85d60f43ae 100644 (file)
@@ -35,7 +35,7 @@
  *
  *    Kern Sibbald, March 2000
  *
- *    Version $Id$
+ *    Version $Id: sql.c 8034 2008-11-11 14:33:46Z ricozz $
  */
 
 /* The following is necessary so that we do not include
@@ -46,7 +46,7 @@
 #include "bacula.h"
 #include "cats.h"
 
-#if    HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_DBI
+#if    HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI
 
 uint32_t bacula_db_version = 0;
 
@@ -77,6 +77,8 @@ B_DB *db_init(JCR *jcr, const char *db_driver, const char *db_name, const char *
       db_type = SQL_TYPE_SQLITE;
    } else if (strcasecmp(p, "sqlite3") == 0) {
       db_type = SQL_TYPE_SQLITE3;
+   } else if (strcasecmp(p, "ingres") == 0) {
+      db_type = SQL_TYPE_INGRES;
    } else {
       Jmsg1(jcr, M_ABORT, 0, _("Unknown database type: %s\n"), p);
    }
@@ -84,6 +86,8 @@ B_DB *db_init(JCR *jcr, const char *db_driver, const char *db_name, const char *
    db_type = SQL_TYPE_MYSQL;
 #elif HAVE_POSTGRESQL
    db_type = SQL_TYPE_POSTGRESQL;
+#elif HAVE_INGRES
+   db_type = SQL_TYPE_INGRES;
 #elif HAVE_SQLITE
    db_type = SQL_TYPE_SQLITE;
 #elif HAVE_SQLITE3
@@ -108,7 +112,6 @@ dbid_list::~dbid_list()
    free(DBId);
 }
 
-
 /*
  * Called here to retrieve an integer from the database
  */
@@ -144,7 +147,70 @@ int db_int64_handler(void *ctx, int num_fields, char **row)
    return 0;
 }
 
+/*
+ * Use to build a comma separated list of values from a query. "10,20,30"
+ */
+int db_list_handler(void *ctx, int num_fields, char **row)
+{
+   db_list_ctx *lctx = (db_list_ctx *)ctx;
+   if (num_fields == 1 && row[0]) {
+      if (lctx->list[0]) {
+         pm_strcat(lctx->list, ",");
+      }
+      pm_strcat(lctx->list, row[0]);
+      lctx->count++;
+   }
+   return 0;
+}
+
+
+/*
+ * Called here to retrieve an integer from the database
+ */
+static int db_max_connections_handler(void *ctx, int num_fields, char **row)
+{
+   uint32_t *val = (uint32_t *)ctx;
+   uint32_t index = sql_get_max_connections_index[db_type];
+   if (row[index]) {
+      *val = str_to_int64(row[index]);
+   } else {
+      Dmsg0(800, "int_handler finds zero\n");
+      *val = 0;
+   }
+   return 0;
+}
+
+/* 
+ * Check catalog max_connections setting
+ */
+bool db_check_max_connections(JCR *jcr, B_DB *mdb, uint32_t max_concurrent_jobs)
+{
+   uint32_t max_conn=0;
+   int ret=true;
+
+   /* Without Batch insert, no need to verify max_connections */
+#ifndef HAVE_BATCH_FILE_INSERT
+   return ret;
+#endif
+
+   /* Check max_connections setting */
+   if (!db_sql_query(mdb, sql_get_max_connections[db_type], 
+                     db_max_connections_handler, &max_conn)) {
+      Jmsg(jcr, M_ERROR, 0, "Can't verify max_connections settings %s", mdb->errmsg);
+      return ret;
+   }
+   if (max_conn && max_concurrent_jobs && max_concurrent_jobs > max_conn) {
+      Mmsg(mdb->errmsg, 
+           _("Potential performance problem:\n"
+             "max_connections=%d set for %s database \"%s\" should be larger than Director's "
+             "MaxConcurrentJobs=%d\n"),
+           max_conn, db_get_type(), mdb->db_name, max_concurrent_jobs);
+      Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
+      ret = false;
+   }
 
+   return ret;
+}
 
 /* NOTE!!! The following routines expect that the
  *  calling subroutine sets and clears the mutex
@@ -319,7 +385,7 @@ char *db_strerror(B_DB *mdb)
 void _db_lock(const char *file, int line, B_DB *mdb)
 {
    int errstat;
-   if ((errstat=rwl_writelock(&mdb->lock)) != 0) {
+   if ((errstat=rwl_writelock_p(&mdb->lock, file, line)) != 0) {
       berrno be;
       e_msg(file, line, M_FATAL, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
            errstat, be.bstrerror(errstat));
@@ -393,6 +459,23 @@ void db_start_transaction(JCR *jcr, B_DB *mdb)
    db_unlock(mdb);
 #endif
 
+#ifdef HAVE_INGRES
+   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 Ingres transaction\n");
+      mdb->transaction = 1;
+   }
+   db_unlock(mdb);
+#endif
+
 #ifdef HAVE_DBI
    if (db_type == SQL_TYPE_SQLITE) {
       if (!mdb->allow_transactions) {
@@ -461,6 +544,23 @@ void db_end_transaction(JCR *jcr, B_DB *mdb)
    db_unlock(mdb);
 #endif
 
+
+
+#ifdef HAVE_INGRES
+   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 Ingres transaction changes=%d\n", mdb->changes);
+   }
+   mdb->changes = 0;
+   db_unlock(mdb);
+#endif
+
+
 #ifdef HAVE_POSTGRESQL
    if (!mdb->allow_transactions) {
       return;
@@ -726,10 +826,10 @@ vertical_list:
  */
 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 */
+   const int multi_db = true;   /* we force a new connection only if batch insert is enabled */
+#else
+   const int multi_db = false;
 #endif
 
    if (!jcr->db_batch) {
@@ -742,14 +842,15 @@ bool db_open_batch_connexion(JCR *jcr, B_DB *mdb)
                                       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");
+         Mmsg0(&mdb->errmsg, _("Could not init database batch connection"));
+         Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
          return false;
       }
 
       if (!db_open_database(jcr, jcr->db_batch)) {
-         Mmsg2(&jcr->db_batch->errmsg,  _("Could not open database \"%s\": ERR=%s\n"),
+         Mmsg2(&mdb->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);
+         Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
          return false;
       }      
       Dmsg3(100, "initdb ref=%d connected=%d db=%p\n", jcr->db_batch->ref_count,
@@ -764,7 +865,7 @@ bool db_open_batch_connexion(JCR *jcr, B_DB *mdb)
  * 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)
+void db_debug_print(JCR *jcr, FILE *fp)
 {
    B_DB *mdb = jcr->db;
 
@@ -780,4 +881,4 @@ void _dbg_print_db(JCR *jcr, FILE *fp)
    }
 }
 
-#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/
+#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_INGRES*/