*
* 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
#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;
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);
}
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
free(DBId);
}
-
/*
* Called here to retrieve an integer from the database
*/
-static int int_handler(void *ctx, int num_fields, char **row)
+int db_int_handler(void *ctx, int num_fields, char **row)
{
uint32_t *val = (uint32_t *)ctx;
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
const char *query = "SELECT VersionId FROM Version";
bacula_db_version = 0;
- if (!db_sql_query(mdb, query, int_handler, (void *)&bacula_db_version)) {
+ if (!db_sql_query(mdb, query, db_int_handler, (void *)&bacula_db_version)) {
Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
return false;
}
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));
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) {
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;
*/
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) {
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,
* 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;
}
}
-#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL*/
+#endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_INGRES*/