From 1f6466d87db777abc262cfd89d4377bf516e45a9 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 7 May 2005 17:21:59 +0000 Subject: [PATCH] More work on cached attributes + sig git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@2006 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/cats/cats.h | 2 + bacula/src/cats/mysql.c | 137 +++++++-------- bacula/src/cats/postgresql.c | 131 +++++++------- bacula/src/cats/sql.c | 102 ++++++----- bacula/src/cats/sql_create.c | 12 +- bacula/src/cats/sqlite.c | 95 +++++----- bacula/src/dird/catreq.c | 30 ++-- bacula/src/dird/fd_cmds.c | 324 ++++++++++++++++++----------------- bacula/src/dird/getmsg.c | 256 +++++++++++++-------------- bacula/src/jcr.h | 3 + 10 files changed, 562 insertions(+), 530 deletions(-) diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index e65e3103b7..5319f74de1 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -619,6 +619,8 @@ struct ATTR_DBR { DBId_t PathId; DBId_t FilenameId; FileId_t FileId; + char *Sig; + int SigType; }; diff --git a/bacula/src/cats/mysql.c b/bacula/src/cats/mysql.c index a8cd052bbd..cf5972fbc7 100644 --- a/bacula/src/cats/mysql.c +++ b/bacula/src/cats/mysql.c @@ -9,7 +9,7 @@ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -32,7 +32,7 @@ /* 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" @@ -57,8 +57,8 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; */ 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; @@ -66,16 +66,16 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char Jmsg(jcr, M_FATAL, 0, _("A user name for MySQL must be supplied.\n")); return NULL; } - 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(100, "DB REopen %d %s\n", mdb->ref_count, db_name); - mdb->ref_count++; - V(mutex); - return mdb; /* already open */ - } + 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"); @@ -103,7 +103,7 @@ 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); - qinsert(&db_list, &mdb->bq); /* put db in list */ + qinsert(&db_list, &mdb->bq); /* put db in list */ V(mutex); return mdb; } @@ -128,7 +128,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; } @@ -142,31 +142,31 @@ db_open_database(JCR *jcr, B_DB *mdb) /* 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 */ - mdb->db_address, /* default = localhost */ - mdb->db_user, /* login name */ - mdb->db_password, /* password */ - mdb->db_name, /* database name */ - mdb->db_port, /* default port */ - mdb->db_socket, /* default = socket */ - CLIENT_FOUND_ROWS); /* flags */ + &(mdb->mysql), /* db */ + mdb->db_address, /* default = localhost */ + mdb->db_user, /* login name */ + mdb->db_password, /* password */ + mdb->db_name, /* database name */ + 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; + 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); + 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"), - mdb->db_name, mdb->db_user); + mdb->db_name, mdb->db_user); V(mutex); return 0; } @@ -191,6 +191,7 @@ db_close_database(JCR *jcr, B_DB *mdb) if (!mdb) { return; } + db_end_transaction(jcr, mdb); P(mutex); mdb->ref_count--; #ifdef HAVE_TREAD_SAFE_MYSQL @@ -199,9 +200,9 @@ db_close_database(JCR *jcr, B_DB *mdb) if (mdb->ref_count == 0) { qdchain(&mdb->bq); if (mdb->connected && mdb->db) { - sql_close(mdb); + sql_close(mdb); #ifdef HAVE_EMBEDDED_MYSQL - mysql_server_end(); + mysql_server_end(); #endif } rwl_destroy(&mdb->lock); @@ -212,19 +213,19 @@ db_close_database(JCR *jcr, B_DB *mdb) free_pool_memory(mdb->path); free_pool_memory(mdb->esc_name); if (mdb->db_name) { - free(mdb->db_name); + free(mdb->db_name); } if (mdb->db_user) { - free(mdb->db_user); + free(mdb->db_user); } if (mdb->db_password) { - free(mdb->db_password); + free(mdb->db_password); } if (mdb->db_address) { - free(mdb->db_address); + free(mdb->db_address); } if (mdb->db_socket) { - free(mdb->db_socket); + free(mdb->db_socket); } free(mdb); } @@ -249,8 +250,8 @@ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index) * 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. + * string must be long enough (max 2*old+1) to hold + * the escaped output. */ void db_escape_string(char *snew, char *old, int len) @@ -269,42 +270,42 @@ unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, while (len--) { switch (*o) { case 0: - *n++= '\\'; - *n++= '0'; - o++; - break; + *n++= '\\'; + *n++= '0'; + o++; + break; case '\n': - *n++= '\\'; - *n++= 'n'; - o++; - break; + *n++= '\\'; + *n++= 'n'; + o++; + break; case '\r': - *n++= '\\'; - *n++= 'r'; - o++; - break; + *n++= '\\'; + *n++= 'r'; + o++; + break; case '\\': - *n++= '\\'; - *n++= '\\'; - o++; - break; + *n++= '\\'; + *n++= '\\'; + o++; + break; case '\'': - *n++= '\\'; - *n++= '\''; - o++; - break; + *n++= '\\'; + *n++= '\''; + o++; + break; case '"': - *n++= '\\'; - *n++= '"'; - o++; - break; + *n++= '\\'; + *n++= '"'; + o++; + break; case '\032': - *n++= '\\'; - *n++= 'Z'; - o++; - break; + *n++= '\\'; + *n++= 'Z'; + o++; + break; default: - *n++= *o++; + *n++= *o++; } } *n = 0; @@ -327,14 +328,14 @@ int db_sql_query(B_DB *mdb, const char *query, DB_RESULT_HANDLER *result_handler } if (result_handler != NULL) { if ((mdb->result = sql_store_result(mdb)) != NULL) { - int num_fields = sql_num_fields(mdb); + int num_fields = sql_num_fields(mdb); - while ((row = sql_fetch_row(mdb)) != NULL) { - if (result_handler(ctx, num_fields, row)) - break; - } + while ((row = sql_fetch_row(mdb)) != NULL) { + if (result_handler(ctx, num_fields, row)) + break; + } - sql_free_result(mdb); + sql_free_result(mdb); } } db_unlock(mdb); diff --git a/bacula/src/cats/postgresql.c b/bacula/src/cats/postgresql.c index 19d730a33a..f0af40cf3a 100644 --- a/bacula/src/cats/postgresql.c +++ b/bacula/src/cats/postgresql.c @@ -9,7 +9,7 @@ */ /* - Copyright (C) 2003-2004 Kern Sibbald and John Walker + Copyright (C) 2003-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -32,7 +32,7 @@ /* 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" @@ -59,8 +59,8 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; */ 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; @@ -68,16 +68,16 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char Jmsg(jcr, M_FATAL, 0, _("A user name for PostgreSQL must be supplied.\n")); return NULL; } - P(mutex); /* lock DB queue */ + P(mutex); /* lock DB queue */ if (!mult_db_connections) { /* 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 (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"); @@ -96,17 +96,17 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char } mdb->db_port = db_port; mdb->have_insert_id = TRUE; - mdb->errmsg = get_pool_memory(PM_EMSG); /* get error message buffer */ + 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->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->fname = get_pool_memory(PM_FNAME); + mdb->path = get_pool_memory(PM_FNAME); mdb->esc_name = 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; } @@ -132,7 +132,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; } @@ -148,30 +148,30 @@ db_open_database(JCR *jcr, B_DB *mdb) for (int retry=0; retry < 6; retry++) { /* connect to the database */ mdb->db = PQsetdbLogin( - mdb->db_address, /* default = localhost */ - port, /* default port */ - NULL, /* pg options */ - NULL, /* tty, ignored */ - mdb->db_name, /* database name */ - mdb->db_user, /* login name */ - mdb->db_password); /* password */ + mdb->db_address, /* default = localhost */ + port, /* default port */ + NULL, /* pg options */ + NULL, /* tty, ignored */ + mdb->db_name, /* database name */ + mdb->db_user, /* login name */ + mdb->db_password); /* password */ /* If no connect, try once more in case it is a timing problem */ if (PQstatus(mdb->db) == CONNECTION_OK) { - break; + break; } bmicrosleep(5, 0); } Dmsg0(50, "pg_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); + mdb->db_password==NULL?"(NULL)":mdb->db_password); if (PQstatus(mdb->db) != CONNECTION_OK) { Mmsg2(&mdb->errmsg, _("Unable to connect to PostgreSQL server.\n" - "Database=%s User=%s\n" - "It is probably not running or your password is incorrect.\n"), - mdb->db_name, mdb->db_user); + "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; } @@ -192,12 +192,13 @@ db_close_database(JCR *jcr, B_DB *mdb) if (!mdb) { return; } + db_end_transaction(jcr, mdb); P(mutex); mdb->ref_count--; if (mdb->ref_count == 0) { qdchain(&mdb->bq); if (mdb->connected && mdb->db) { - sql_close(mdb); + sql_close(mdb); } rwl_destroy(&mdb->lock); free_pool_memory(mdb->errmsg); @@ -207,19 +208,19 @@ db_close_database(JCR *jcr, B_DB *mdb) free_pool_memory(mdb->path); free_pool_memory(mdb->esc_name); if (mdb->db_name) { - free(mdb->db_name); + free(mdb->db_name); } if (mdb->db_user) { - free(mdb->db_user); + free(mdb->db_user); } if (mdb->db_password) { - free(mdb->db_password); + free(mdb->db_password); } if (mdb->db_address) { - free(mdb->db_address); + free(mdb->db_address); } if (mdb->db_socket) { - free(mdb->db_socket); + free(mdb->db_socket); } my_postgresql_free_result(mdb); free(mdb); @@ -245,8 +246,8 @@ int db_next_index(JCR *jcr, B_DB *mdb, char *table, char *index) * Escape strings so that PostgreSQL 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) @@ -276,17 +277,17 @@ int db_sql_query(B_DB *mdb, const char *query, DB_RESULT_HANDLER *result_handler if (result_handler != NULL) { Dmsg0(500, "db_sql_query invoking handler\n"); if ((mdb->result = sql_store_result(mdb)) != NULL) { - int num_fields = sql_num_fields(mdb); + int num_fields = sql_num_fields(mdb); - Dmsg0(500, "db_sql_query sql_store_result suceeded\n"); - while ((row = sql_fetch_row(mdb)) != NULL) { + Dmsg0(500, "db_sql_query sql_store_result suceeded\n"); + while ((row = sql_fetch_row(mdb)) != NULL) { - Dmsg0(500, "db_sql_query sql_fetch_row worked\n"); - if (result_handler(ctx, num_fields, row)) - break; - } + Dmsg0(500, "db_sql_query sql_fetch_row worked\n"); + if (result_handler(ctx, num_fields, row)) + break; + } - sql_free_result(mdb); + sql_free_result(mdb); } } db_unlock(mdb); @@ -309,9 +310,9 @@ POSTGRESQL_ROW my_postgresql_fetch_row(B_DB *mdb) Dmsg1(500, "we have need space of %d bytes\n", sizeof(char *) * mdb->num_fields); if (mdb->row != NULL) { - Dmsg0(500, "my_postgresql_fetch_row freeing space\n"); - free(mdb->row); - mdb->row = NULL; + Dmsg0(500, "my_postgresql_fetch_row freeing space\n"); + free(mdb->row); + mdb->row = NULL; } mdb->row = (POSTGRESQL_ROW) malloc(sizeof(char *) * mdb->num_fields); @@ -325,8 +326,8 @@ POSTGRESQL_ROW my_postgresql_fetch_row(B_DB *mdb) Dmsg2(500, "my_postgresql_fetch_row row number '%d' is acceptable (0..%d)\n", mdb->row_number, mdb->num_rows); // get each value from this row for (j = 0; j < mdb->num_fields; j++) { - mdb->row[j] = PQgetvalue(mdb->result, mdb->row_number, j); - Dmsg2(500, "my_postgresql_fetch_row field '%d' has value '%s'\n", j, mdb->row[j]); + mdb->row[j] = PQgetvalue(mdb->result, mdb->row_number, j); + Dmsg2(500, "my_postgresql_fetch_row field '%d' has value '%s'\n", j, mdb->row[j]); } // increment the row number for the next call mdb->row_number++; @@ -352,13 +353,13 @@ int my_postgresql_max_length(B_DB *mdb, int field_num) { max_length = 0; for (i = 0; i < mdb->num_rows; i++) { if (PQgetisnull(mdb->result, i, field_num)) { - this_length = 4; // "NULL" + this_length = 4; // "NULL" } else { - this_length = strlen(PQgetvalue(mdb->result, i, field_num)); + this_length = cstrlen(PQgetvalue(mdb->result, i, field_num)); } if (max_length < this_length) { - max_length = this_length; + max_length = this_length; } } @@ -367,7 +368,7 @@ int my_postgresql_max_length(B_DB *mdb, int field_num) { POSTGRESQL_FIELD * my_postgresql_fetch_field(B_DB *mdb) { - int i; + int i; Dmsg0(500, "my_postgresql_fetch_field starts\n"); if (mdb->fields == NULL) { @@ -375,15 +376,15 @@ POSTGRESQL_FIELD * my_postgresql_fetch_field(B_DB *mdb) mdb->fields = (POSTGRESQL_FIELD *)malloc(sizeof(POSTGRESQL_FIELD) * mdb->num_fields); for (i = 0; i < mdb->num_fields; i++) { - Dmsg1(500, "filling field %d\n", i); - mdb->fields[i].name = PQfname(mdb->result, i); - mdb->fields[i].max_length = my_postgresql_max_length(mdb, i); - mdb->fields[i].type = PQftype(mdb->result, i); - mdb->fields[i].flags = 0; - - Dmsg4(500, "my_postgresql_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n", - mdb->fields[i].name, mdb->fields[i].max_length, mdb->fields[i].type, - mdb->fields[i].flags); + Dmsg1(500, "filling field %d\n", i); + mdb->fields[i].name = PQfname(mdb->result, i); + mdb->fields[i].max_length = my_postgresql_max_length(mdb, i); + mdb->fields[i].type = PQftype(mdb->result, i); + mdb->fields[i].flags = 0; + + Dmsg4(500, "my_postgresql_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n", + mdb->fields[i].name, mdb->fields[i].max_length, mdb->fields[i].type, + mdb->fields[i].flags); } // end for } // end if @@ -467,7 +468,7 @@ int my_postgresql_currval(B_DB *mdb, char *table_name) // Obtain the current value of the sequence that // provides the serial value for primary key of the table. - // currval is local to our session. It is not affected by + // currval is local to our session. It is not affected by // other transactions. // Determine the name of the sequence. @@ -483,7 +484,7 @@ int my_postgresql_currval(B_DB *mdb, char *table_name) char sequence[NAMEDATALEN-1]; char query [NAMEDATALEN+50]; PGresult *result; - int id = 0; + int id = 0; if (strcasecmp(table_name, "basefiles") == 0) { bstrncpy(sequence, "basefiles_baseid", sizeof(sequence)); diff --git a/bacula/src/cats/sql.c b/bacula/src/cats/sql.c index e61133530e..6d9f815b71 100644 --- a/bacula/src/cats/sql.c +++ b/bacula/src/cats/sql.c @@ -2,7 +2,7 @@ * Bacula Catalog Database interface routines * * Almost generic set of SQL database interface routines - * (with a little more work) + * (with a little more work) * * Kern Sibbald, March 2000 * @@ -32,7 +32,7 @@ /* The following is necessary so that we do not include * the dummy external definition of B_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" @@ -80,7 +80,7 @@ int check_tables_version(JCR *jcr, B_DB *mdb) db_sql_query(mdb, query, int_handler, (void *)&bacula_db_version); if (bacula_db_version != BDB_VERSION) { Mmsg(mdb->errmsg, "Version error for database \"%s\". Wanted %d, got %d\n", - mdb->db_name, BDB_VERSION, bacula_db_version); + mdb->db_name, BDB_VERSION, bacula_db_version); Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg); return 0; } @@ -109,7 +109,7 @@ QueryDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) /* * Utility routine to do inserts * Returns: 0 on failure - * 1 on success + * 1 on success */ int InsertDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) @@ -130,7 +130,7 @@ InsertDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) if (mdb->num_rows != 1) { char ed1[30]; m_msg(file, line, &mdb->errmsg, _("Insertion problem: affected_rows=%s\n"), - edit_uint64(mdb->num_rows, ed1)); + edit_uint64(mdb->num_rows, ed1)); if (verbose) { j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } @@ -142,7 +142,7 @@ InsertDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) /* Utility routine for updates. * Returns: 0 on failure - * 1 on success + * 1 on success */ int UpdateDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) @@ -160,7 +160,7 @@ UpdateDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) if (mdb->num_rows < 1) { char ed1[30]; m_msg(file, line, &mdb->errmsg, _("Update problem: affected_rows=%s\n"), - edit_uint64(mdb->num_rows, ed1)); + edit_uint64(mdb->num_rows, ed1)); if (verbose) { // j_msg(file, line, jcr, M_INFO, 0, "%s\n", cmd); } @@ -173,7 +173,7 @@ UpdateDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) /* Utility routine for deletes * * Returns: -1 on error - * n number of rows affected + * n number of rows affected */ int DeleteDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) @@ -197,7 +197,7 @@ DeleteDB(const char *file, int line, JCR *jcr, B_DB *mdb, char *cmd) * No locking done * * Returns: -1 on failure - * count on success + * count on success */ int get_sql_record_max(JCR *jcr, B_DB *mdb) { @@ -207,9 +207,9 @@ int get_sql_record_max(JCR *jcr, B_DB *mdb) if (QUERY_DB(jcr, mdb, mdb->cmd)) { if ((row = sql_fetch_row(mdb)) == NULL) { Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb)); - stat = -1; + stat = -1; } else { - stat = str_to_int64(row[0]); + stat = str_to_int64(row[0]); } sql_free_result(mdb); } else { @@ -238,7 +238,7 @@ void _db_lock(const char *file, int line, B_DB *mdb) if ((errstat=rwl_writelock(&mdb->lock)) != 0) { berrno be; e_msg(file, line, M_ABORT, 0, "rwl_writelock failure. ERR=%s\n", - be.strerror(errstat)); + be.strerror(errstat)); } } @@ -253,7 +253,7 @@ void _db_unlock(const char *file, int line, B_DB *mdb) if ((errstat=rwl_writeunlock(&mdb->lock)) != 0) { berrno be; e_msg(file, line, M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n", - be.strerror(errstat)); + be.strerror(errstat)); } } @@ -264,6 +264,9 @@ void _db_unlock(const char *file, int line, B_DB *mdb) */ void db_start_transaction(JCR *jcr, B_DB *mdb) { + if (!jcr->attr) { + jcr->attr = get_pool_memory(PM_FNAME); + } #ifdef HAVE_SQLITE if (!mdb->allow_transactions) { return; @@ -307,11 +310,20 @@ void db_end_transaction(JCR *jcr, B_DB *mdb) { /* * This can be called during thread cleanup and - * the db may already be closed. So simply return. + * the db may already be closed. So simply return. */ if (!mdb) { return; } + if (jcr->cached_attribute) { + if (!db_create_file_attributes_record(jcr, jcr->db, &jcr->ar)) { + Jmsg1(jcr, M_FATAL, 0, _("Attribute create error. %s"), db_strerror(jcr->db)); + } + jcr->cached_attribute = false; + } + if (jcr->attr) { + free_pool_memory(jcr->attr); + } #ifdef HAVE_SQLITE if (!mdb->allow_transactions) { return; @@ -358,12 +370,12 @@ void split_path_and_file(JCR *jcr, B_DB *mdb, const char *fname) */ for (p=f=fname; *p; p++) { if (*p == '/') { - f = p; /* set pos of last slash */ + f = p; /* set pos of last slash */ } } if (*f == '/') { /* did we find a slash? */ - f++; /* yes, point to filename */ - } else { /* no, whole thing must be path name */ + f++; /* yes, point to filename */ + } else { /* no, whole thing must be path name */ f = p; } @@ -375,7 +387,7 @@ void split_path_and_file(JCR *jcr, B_DB *mdb, const char *fname) mdb->fnl = p - f; if (mdb->fnl > 0) { mdb->fname = check_pool_memory_size(mdb->fname, mdb->fnl+1); - memcpy(mdb->fname, f, mdb->fnl); /* copy filename */ + memcpy(mdb->fname, f, mdb->fnl); /* copy filename */ mdb->fname[mdb->fnl] = 0; } else { mdb->fname[0] = 0; @@ -442,22 +454,22 @@ 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); - col_len = strlen(field->name); + col_len = cstrlen(field->name); if (type == VERT_LIST) { - if (col_len > max_len) { - max_len = col_len; - } + if (col_len > max_len) { + max_len = col_len; + } } else { - if (IS_NUM(field->type) && (int)field->max_length > 0) { /* fixup for commas */ - field->max_length += (field->max_length - 1) / 3; - } - if (col_len < (int)field->max_length) { - col_len = field->max_length; - } - if (col_len < 4 && !IS_NOT_NULL(field->flags)) { + if (IS_NUM(field->type) && (int)field->max_length > 0) { /* fixup for commas */ + field->max_length += (field->max_length - 1) / 3; + } + if (col_len < (int)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 */ + } + field->max_length = col_len; /* reset column info */ } } @@ -484,16 +496,16 @@ list_result(JCR *jcr, B_DB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type t 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) { + field = sql_fetch_field(mdb); + 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])) { + } else if (IS_NUM(field->type) && !jcr->gui && is_an_integer(row[i])) { bsnprintf(buf, sizeof(buf), " %*s |", (int)field->max_length, - add_commas(row[i], ewc)); - } else { + add_commas(row[i], ewc)); + } else { bsnprintf(buf, sizeof(buf), " %-*s |", (int)field->max_length, row[i]); - } - send(ctx, buf); + } + send(ctx, buf); } send(ctx, "\n"); } @@ -506,16 +518,16 @@ vertical_list: while ((row = sql_fetch_row(mdb)) != NULL) { sql_field_seek(mdb, 0); for (i = 0; i < sql_num_fields(mdb); i++) { - field = sql_fetch_field(mdb); - if (row[i] == NULL) { + field = sql_fetch_field(mdb); + 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])) { + } else if (IS_NUM(field->type) && !jcr->gui && is_an_integer(row[i])) { bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, - add_commas(row[i], ewc)); - } else { + add_commas(row[i], ewc)); + } else { bsnprintf(buf, sizeof(buf), " %*s: %s\n", max_len, field->name, row[i]); - } - send(ctx, buf); + } + send(ctx, buf); } send(ctx, "\n"); } diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 3c3590c7a6..bef5a43b43 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -713,17 +713,25 @@ bail_out: static int db_create_file_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar) { int stat; + static char *no_sig = "0"; + char *sig; ASSERT(ar->JobId); ASSERT(ar->PathId); ASSERT(ar->FilenameId); + if (ar->Sig == NULL) { + sig = no_sig; + } else { + sig = ar->Sig; + } + /* Must create it */ Mmsg(mdb->cmd, "INSERT INTO File (FileIndex,JobId,PathId,FilenameId," - "LStat,MD5) VALUES (%u,%u,%u,%u,'%s','0')", + "LStat,MD5) VALUES (%u,%u,%u,%u,'%s','%s')", ar->FileIndex, ar->JobId, ar->PathId, ar->FilenameId, - ar->attr); + ar->attr, sig); if (!INSERT_DB(jcr, mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Create db File record %s failed. ERR=%s"), diff --git a/bacula/src/cats/sqlite.c b/bacula/src/cats/sqlite.c index 4af75d52d0..67332ff2d5 100644 --- a/bacula/src/cats/sqlite.c +++ b/bacula/src/cats/sqlite.c @@ -7,7 +7,7 @@ */ /* - Copyright (C) 2002-2004 Kern Sibbald and John Walker + Copyright (C) 2002-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -30,7 +30,7 @@ /* 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" @@ -60,21 +60,21 @@ int QueryDB(const char *file, int line, JCR *jcr, B_DB *db, char *select_cmd); */ 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) { + 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 */ - } + mdb->ref_count++; + V(mutex); + return mdb; /* already open */ + } } } Dmsg0(300, "db_open first time\n"); @@ -92,7 +92,7 @@ db_init_database(JCR *jcr, const char *db_name, const char *db_user, const char mdb->path = get_pool_memory(PM_FNAME); mdb->esc_name = 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 +120,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,7 +134,7 @@ 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; @@ -150,9 +150,9 @@ db_open_database(JCR *jcr, B_DB *mdb) #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"); @@ -181,12 +181,13 @@ db_close_database(JCR *jcr, B_DB *mdb) if (!mdb) { return; } + db_end_transaction(jcr, mdb); P(mutex); 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); @@ -196,7 +197,7 @@ db_close_database(JCR *jcr, B_DB *mdb) free_pool_memory(mdb->path); free_pool_memory(mdb->esc_name); if (mdb->db_name) { - free(mdb->db_name); + free(mdb->db_name); } free(mdb); } @@ -249,8 +250,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) @@ -264,16 +265,16 @@ db_escape_string(char *snew, char *old, int len) case '\'': *n++ = '\''; *n++ = '\''; - o++; - break; + o++; + break; case 0: *n++ = '\\'; - *n++ = 0; - o++; - break; + *n++ = 0; + o++; + break; default: - *n++ = *o++; - break; + *n++ = *o++; + break; } } *n = 0; @@ -339,8 +340,8 @@ int my_sqlite_query(B_DB *mdb, char *cmd) 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 */ + &mdb->sqlite_errmsg); + mdb->row = 0; /* row fetched */ return stat; } @@ -360,7 +361,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; @@ -379,23 +380,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; } diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index 945a34d165..8d0c3ebe17 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -323,15 +323,18 @@ void catalog_update(JCR *jcr, BSOCK *bs, char *msg) int32_t Stream; uint32_t FileIndex; uint32_t data_len; - char *p = bs->msg; + char *p; int len; char *fname, *attr; - ATTR_DBR ar; + ATTR_DBR *ar = &jcr->ar; if (!jcr->pool->catalog_files) { return; } db_start_transaction(jcr, jcr->db); /* start transaction if not already open */ + jcr->attr = check_pool_memory_size(jcr->attr, bs->msglen); + memcpy(jcr->attr, bs->msg, bs->msglen); + p = jcr->attr; skip_nonspaces(&p); /* UpdCat */ skip_spaces(&p); skip_nonspaces(&p); /* Job=nnn */ @@ -361,25 +364,24 @@ void catalog_update(JCR *jcr, BSOCK *bs, char *msg) Dmsg2(400, "dirdJobId; + ar->attr = attr; + ar->fname = fname; + ar->FileIndex = FileIndex; + ar->Stream = Stream; + ar->link = NULL; + ar->JobId = jcr->JobId; + ar->Sig = NULL; + ar->SigType = 0; Dmsg2(400, "dirddb, &ar)) { + if (!db_create_file_attributes_record(jcr, jcr->db, ar)) { Jmsg1(jcr, M_FATAL, 0, _("Attribute create error. %s"), db_strerror(jcr->db)); } - /* Save values for SIG update */ - jcr->FileId = ar.FileId; - jcr->FileIndex = FileIndex; } else if (Stream == STREAM_MD5_SIGNATURE || Stream == STREAM_SHA1_SIGNATURE) { fname = p; - if (jcr->FileIndex != FileIndex) { + if (ar->FileIndex != FileIndex) { Jmsg(jcr, M_WARNING, 0, "Got MD5/SHA1 but not same File as attributes\n"); } else { /* Update signature in catalog */ @@ -394,7 +396,7 @@ void catalog_update(JCR *jcr, BSOCK *bs, char *msg) } bin_to_base64(SIGbuf, fname, len); Dmsg3(400, "SIGlen=%d SIG=%s type=%d\n", strlen(SIGbuf), SIGbuf, Stream); - if (!db_add_SIG_to_file_record(jcr, jcr->db, jcr->FileId, SIGbuf, type)) { + if (!db_add_SIG_to_file_record(jcr, jcr->db, ar->FileId, SIGbuf, type)) { Jmsg(jcr, M_ERROR, 0, _("Catalog error updating MD5/SHA1. %s"), db_strerror(jcr->db)); } diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index 97dc669ac5..1059f9d971 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -69,21 +69,21 @@ extern int FDConnectTimeout; */ int connect_to_file_daemon(JCR *jcr, int retry_interval, int max_retry_time, - int verbose) + int verbose) { BSOCK *fd; if (!jcr->file_bsock) { fd = bnet_connect(jcr, retry_interval, max_retry_time, _("File daemon"), jcr->client->address, - NULL, jcr->client->FDport, verbose); + NULL, jcr->client->FDport, verbose); if (fd == NULL) { - set_jcr_job_status(jcr, JS_ErrorTerminated); - return 0; + set_jcr_job_status(jcr, JS_ErrorTerminated); + return 0; } Dmsg0(10, "Opened connection with File daemon\n"); } else { - fd = jcr->file_bsock; /* use existing connection */ + fd = jcr->file_bsock; /* use existing connection */ } fd->res = (RES *)jcr->client; /* save resource in BSOCK */ jcr->file_bsock = fd; @@ -107,25 +107,25 @@ int connect_to_file_daemon(JCR *jcr, int retry_interval, int max_retry_time, Dmsg1(110, "msg); if (strncmp(fd->msg, OKjob, strlen(OKjob)) != 0) { Jmsg(jcr, M_FATAL, 0, _("File daemon \"%s\" rejected Job command: %s\n"), - jcr->client->hdr.name, fd->msg); - set_jcr_job_status(jcr, JS_ErrorTerminated); - return 0; + jcr->client->hdr.name, fd->msg); + set_jcr_job_status(jcr, JS_ErrorTerminated); + return 0; } else if (jcr->db) { - CLIENT_DBR cr; - memset(&cr, 0, sizeof(cr)); - bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name)); - cr.AutoPrune = jcr->client->AutoPrune; - cr.FileRetention = jcr->client->FileRetention; - cr.JobRetention = jcr->client->JobRetention; - bstrncpy(cr.Uname, fd->msg+strlen(OKjob)+1, sizeof(cr.Uname)); - if (!db_update_client_record(jcr, jcr->db, &cr)) { + CLIENT_DBR cr; + memset(&cr, 0, sizeof(cr)); + bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name)); + cr.AutoPrune = jcr->client->AutoPrune; + cr.FileRetention = jcr->client->FileRetention; + cr.JobRetention = jcr->client->JobRetention; + bstrncpy(cr.Uname, fd->msg+strlen(OKjob)+1, sizeof(cr.Uname)); + if (!db_update_client_record(jcr, jcr->db, &cr)) { Jmsg(jcr, M_WARNING, 0, _("Error updating Client record. ERR=%s\n"), - db_strerror(jcr->db)); - } + db_strerror(jcr->db)); + } } } else { Jmsg(jcr, M_FATAL, 0, _("FD gave bad response to JobId command: %s\n"), - bnet_strerror(fd)); + bnet_strerror(fd)); set_jcr_job_status(jcr, JS_ErrorTerminated); return 0; } @@ -147,7 +147,7 @@ void get_level_since_time(JCR *jcr, char *since, int since_len) if (jcr->cloned) { if ( jcr->stime && jcr->stime[0]) { bstrncpy(since, ", since=", since_len); - bstrncat(since, jcr->stime, since_len); + bstrncat(since, jcr->stime, since_len); } return; } @@ -164,26 +164,26 @@ void get_level_since_time(JCR *jcr, char *since, int since_len) /* Look up start time of last job */ jcr->jr.JobId = 0; /* flag for db_find_job_start time */ if (!db_find_job_start_time(jcr, jcr->db, &jcr->jr, &jcr->stime)) { - /* No job found, so upgrade this one to Full */ + /* No job found, so upgrade this one to Full */ Jmsg(jcr, M_INFO, 0, "%s", db_strerror(jcr->db)); Jmsg(jcr, M_INFO, 0, _("No prior or suitable Full backup found. Doing FULL backup.\n")); bsnprintf(since, since_len, " (upgraded from %s)", - level_to_str(jcr->JobLevel)); - jcr->JobLevel = jcr->jr.JobLevel = L_FULL; + level_to_str(jcr->JobLevel)); + jcr->JobLevel = jcr->jr.JobLevel = L_FULL; } else { - if (jcr->job->rerun_failed_levels) { - if (db_find_failed_job_since(jcr, jcr->db, &jcr->jr, jcr->stime, JobLevel)) { + if (jcr->job->rerun_failed_levels) { + if (db_find_failed_job_since(jcr, jcr->db, &jcr->jr, jcr->stime, JobLevel)) { Jmsg(jcr, M_INFO, 0, _("Prior failed job found. Upgrading to %s.\n"), - level_to_str(JobLevel)); + level_to_str(JobLevel)); bsnprintf(since, since_len, " (upgraded from %s)", - level_to_str(jcr->JobLevel)); - jcr->JobLevel = jcr->jr.JobLevel = JobLevel; - jcr->jr.JobId = jcr->JobId; - break; - } - } + level_to_str(jcr->JobLevel)); + jcr->JobLevel = jcr->jr.JobLevel = JobLevel; + jcr->jr.JobId = jcr->JobId; + break; + } + } bstrncpy(since, ", since=", since_len); - bstrncat(since, jcr->stime, since_len); + bstrncat(since, jcr->stime, since_len); } jcr->jr.JobId = jcr->JobId; break; @@ -235,7 +235,7 @@ bool send_level_command(JCR *jcr) case L_SINCE: default: Jmsg2(jcr, M_FATAL, 0, _("Unimplemented backup level %d %c\n"), - jcr->JobLevel, jcr->JobLevel); + jcr->JobLevel, jcr->JobLevel); return 0; } Dmsg1(120, ">filed: %s", fd->msg); @@ -257,136 +257,136 @@ static int send_fileset(JCR *jcr) for ( ;; ) { if (include) { - num = fileset->num_includes; + num = fileset->num_includes; } else { - num = fileset->num_excludes; + num = fileset->num_excludes; } for (int i=0; iinclude_items[i]; + BPIPE *bpipe; + FILE *ffd; + char buf[2000]; + char *p; + int optlen, stat; + INCEXE *ie; + int j, k; + + if (include) { + ie = fileset->include_items[i]; bnet_fsend(fd, "I\n"); - } else { - ie = fileset->exclude_items[i]; + } else { + ie = fileset->exclude_items[i]; bnet_fsend(fd, "E\n"); - } - for (j=0; jnum_opts; j++) { - FOPTS *fo = ie->opts_list[j]; + } + for (j=0; jnum_opts; j++) { + FOPTS *fo = ie->opts_list[j]; bnet_fsend(fd, "O %s\n", fo->opts); - for (k=0; kregex.size(); k++) { + for (k=0; kregex.size(); k++) { bnet_fsend(fd, "R %s\n", fo->regex.get(k)); - } - for (k=0; kregexdir.size(); k++) { + } + for (k=0; kregexdir.size(); k++) { bnet_fsend(fd, "RD %s\n", fo->regexdir.get(k)); - } - for (k=0; kregexfile.size(); k++) { + } + for (k=0; kregexfile.size(); k++) { bnet_fsend(fd, "RF %s\n", fo->regexfile.get(k)); - } - for (k=0; kwild.size(); k++) { + } + for (k=0; kwild.size(); k++) { bnet_fsend(fd, "W %s\n", fo->wild.get(k)); - } - for (k=0; kwilddir.size(); k++) { + } + for (k=0; kwilddir.size(); k++) { bnet_fsend(fd, "WD %s\n", fo->wilddir.get(k)); - } - for (k=0; kwildfile.size(); k++) { + } + for (k=0; kwildfile.size(); k++) { bnet_fsend(fd, "WF %s\n", fo->wildfile.get(k)); - } - for (k=0; kbase.size(); k++) { + } + for (k=0; kbase.size(); k++) { bnet_fsend(fd, "B %s\n", fo->base.get(k)); - } - for (k=0; kfstype.size(); k++) { + } + for (k=0; kfstype.size(); k++) { bnet_fsend(fd, "X %s\n", fo->fstype.get(k)); - } - if (fo->reader) { + } + if (fo->reader) { bnet_fsend(fd, "D %s\n", fo->reader); - } - if (fo->writer) { + } + if (fo->writer) { bnet_fsend(fd, "T %s\n", fo->writer); - } + } bnet_fsend(fd, "N\n"); - } + } - for (j=0; jname_list.size(); j++) { - p = (char *)ie->name_list.get(j); - switch (*p) { + for (j=0; jname_list.size(); j++) { + p = (char *)ie->name_list.get(j); + switch (*p) { case '|': - p++; /* skip over the | */ + p++; /* skip over the | */ fd->msg = edit_job_codes(jcr, fd->msg, p, ""); bpipe = open_bpipe(fd->msg, 0, "r"); - if (!bpipe) { - berrno be; + if (!bpipe) { + berrno be; Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"), - p, be.strerror()); - goto bail_out; - } + p, be.strerror()); + goto bail_out; + } bstrncpy(buf, "F ", sizeof(buf)); Dmsg1(500, "Opts=%s\n", buf); - optlen = strlen(buf); - while (fgets(buf+optlen, sizeof(buf)-optlen, bpipe->rfd)) { + optlen = strlen(buf); + while (fgets(buf+optlen, sizeof(buf)-optlen, bpipe->rfd)) { fd->msglen = Mmsg(fd->msg, "%s", buf); Dmsg2(500, "Inc/exc len=%d: %s", fd->msglen, fd->msg); - if (!bnet_send(fd)) { + if (!bnet_send(fd)) { Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n")); - goto bail_out; - } - } - if ((stat=close_bpipe(bpipe)) != 0) { - berrno be; + goto bail_out; + } + } + if ((stat=close_bpipe(bpipe)) != 0) { + berrno be; Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. ERR=%s\n"), - p, be.strerror(stat)); - goto bail_out; - } - break; + p, be.strerror(stat)); + goto bail_out; + } + break; case '<': - p++; /* skip over < */ + p++; /* skip over < */ if ((ffd = fopen(p, "r")) == NULL) { - berrno be; + berrno be; Jmsg(jcr, M_FATAL, 0, _("Cannot open included file: %s. ERR=%s\n"), - p, be.strerror()); - goto bail_out; - } + p, be.strerror()); + goto bail_out; + } bstrncpy(buf, "F ", sizeof(buf)); Dmsg1(500, "Opts=%s\n", buf); - optlen = strlen(buf); - while (fgets(buf+optlen, sizeof(buf)-optlen, ffd)) { + optlen = strlen(buf); + while (fgets(buf+optlen, sizeof(buf)-optlen, ffd)) { fd->msglen = Mmsg(fd->msg, "%s", buf); - if (!bnet_send(fd)) { + if (!bnet_send(fd)) { Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n")); - goto bail_out; - } - } - fclose(ffd); - break; + goto bail_out; + } + } + fclose(ffd); + break; case '\\': p++; /* skip over \ */ - /* Note, fall through wanted */ - default: + /* Note, fall through wanted */ + default: pm_strcpy(fd->msg, "F "); - fd->msglen = pm_strcat(fd->msg, p); + fd->msglen = pm_strcat(fd->msg, p); Dmsg1(500, "Inc/Exc name=%s\n", fd->msg); - if (!bnet_send(fd)) { + if (!bnet_send(fd)) { Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n")); - goto bail_out; - } - break; - } - } + goto bail_out; + } + break; + } + } bnet_fsend(fd, "N\n"); } - if (!include) { /* If we just did excludes */ - break; /* all done */ + if (!include) { /* If we just did excludes */ + break; /* all done */ } - include = false; /* Now do excludes */ + include = false; /* Now do excludes */ } - bnet_sig(fd, BNET_EOD); /* end of data */ + bnet_sig(fd, BNET_EOD); /* end of data */ if (!response(jcr, fd, OKinc, "Include", DISPLAY_ERROR)) { goto bail_out; } @@ -444,7 +444,7 @@ bool send_bootstrap_file(JCR *jcr) if (!bs) { berrno be; Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"), - jcr->RestoreBootstrap, be.strerror()); + jcr->RestoreBootstrap, be.strerror()); set_jcr_job_status(jcr, JS_ErrorTerminated); return 0; } @@ -473,9 +473,9 @@ int send_run_before_and_after_commands(JCR *jcr) bash_spaces(msg); bnet_fsend(fd, runbefore, msg); if (!response(jcr, fd, OKRunBefore, "ClientRunBeforeJob", DISPLAY_ERROR)) { - set_jcr_job_status(jcr, JS_ErrorTerminated); - free_pool_memory(msg); - return 0; + set_jcr_job_status(jcr, JS_ErrorTerminated); + free_pool_memory(msg); + return 0; } } if (jcr->job->ClientRunAfterJob) { @@ -483,9 +483,9 @@ int send_run_before_and_after_commands(JCR *jcr) bash_spaces(msg); bnet_fsend(fd, runafter, msg); if (!response(jcr, fd, OKRunAfter, "ClientRunAfterJob", DISPLAY_ERROR)) { - set_jcr_job_status(jcr, JS_ErrorTerminated); - free_pool_memory(msg); - return 0; + set_jcr_job_status(jcr, JS_ErrorTerminated); + free_pool_memory(msg); + return 0; } } free_pool_memory(msg); @@ -526,66 +526,68 @@ int get_attributes_and_put_in_catalog(JCR *jcr) if ((len = sscanf(fd->msg, "%ld %d %s", &file_index, &stream, Opts_SIG)) != 3) { Jmsg(jcr, M_FATAL, 0, _("msglen, fd->msg); - set_jcr_job_status(jcr, JS_ErrorTerminated); - return 0; + set_jcr_job_status(jcr, JS_ErrorTerminated); + return 0; } p = fd->msg; - skip_nonspaces(&p); /* skip FileIndex */ + skip_nonspaces(&p); /* skip FileIndex */ skip_spaces(&p); - skip_nonspaces(&p); /* skip Stream */ + skip_nonspaces(&p); /* skip Stream */ skip_spaces(&p); - skip_nonspaces(&p); /* skip Opts_SHA1 */ - p++; /* skip space */ + skip_nonspaces(&p); /* skip Opts_SHA1 */ + p++; /* skip space */ fn = jcr->fname; while (*p != 0) { - *fn++ = *p++; /* copy filename */ + *fn++ = *p++; /* copy filename */ } - *fn = *p++; /* term filename and point to attribs */ + *fn = *p++; /* term filename and point to attribs */ attr = p; if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_UNIX_ATTRIBUTES_EX) { - jcr->JobFiles++; - jcr->FileIndex = file_index; - ar.attr = attr; - ar.fname = jcr->fname; - ar.FileIndex = file_index; - ar.Stream = stream; - ar.link = NULL; - ar.JobId = jcr->JobId; - ar.ClientId = jcr->ClientId; - ar.PathId = 0; - ar.FilenameId = 0; + jcr->JobFiles++; + jcr->FileIndex = file_index; + ar.attr = attr; + ar.fname = jcr->fname; + ar.FileIndex = file_index; + ar.Stream = stream; + ar.link = NULL; + ar.JobId = jcr->JobId; + ar.ClientId = jcr->ClientId; + ar.PathId = 0; + ar.FilenameId = 0; + ar.Sig = NULL; + ar.SigType = 0; Dmsg2(111, "dirdfname); Dmsg1(120, "dirddb, &ar)) { + if (!db_create_file_attributes_record(jcr, jcr->db, &ar)) { Jmsg1(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); - set_jcr_job_status(jcr, JS_Error); - continue; - } - jcr->FileId = ar.FileId; + set_jcr_job_status(jcr, JS_Error); + continue; + } + jcr->FileId = ar.FileId; } else if (stream == STREAM_MD5_SIGNATURE || stream == STREAM_SHA1_SIGNATURE) { - if (jcr->FileIndex != (uint32_t)file_index) { + if (jcr->FileIndex != (uint32_t)file_index) { Jmsg2(jcr, M_ERROR, 0, _("MD5/SHA1 index %d not same as attributes %d\n"), - file_index, jcr->FileIndex); - set_jcr_job_status(jcr, JS_Error); - continue; - } - db_escape_string(SIG, Opts_SIG, strlen(Opts_SIG)); + file_index, jcr->FileIndex); + set_jcr_job_status(jcr, JS_Error); + continue; + } + db_escape_string(SIG, Opts_SIG, strlen(Opts_SIG)); Dmsg2(120, "SIGlen=%d SIG=%s\n", strlen(SIG), SIG); - if (!db_add_SIG_to_file_record(jcr, jcr->db, jcr->FileId, SIG, - stream==STREAM_MD5_SIGNATURE?MD5_SIG:SHA1_SIG)) { + if (!db_add_SIG_to_file_record(jcr, jcr->db, jcr->FileId, SIG, + stream==STREAM_MD5_SIGNATURE?MD5_SIG:SHA1_SIG)) { Jmsg1(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); - set_jcr_job_status(jcr, JS_Error); - } + set_jcr_job_status(jcr, JS_Error); + } } jcr->jr.JobFiles = jcr->JobFiles = file_index; jcr->jr.LastIndex = file_index; } if (is_bnet_error(fd)) { Jmsg1(jcr, M_FATAL, 0, _("msg); if (is_bnet_stop(bs)) { - return n; /* error or terminate */ + return n; /* error or terminate */ } - if (n == BNET_SIGNAL) { /* handle signal */ - /* BNET_SIGNAL (-1) return from bnet_recv() => network signal */ - switch (bs->msglen) { - case BNET_EOD: /* end of data */ - return n; - case BNET_EOD_POLL: - bnet_fsend(bs, OK_msg);/* send response */ - return n; /* end of data */ - case BNET_TERMINATE: - bs->terminated = 1; - return n; - case BNET_POLL: - bnet_fsend(bs, OK_msg); /* send response */ - break; - case BNET_HEARTBEAT: -// encode_time(time(NULL), Job); + if (n == BNET_SIGNAL) { /* handle signal */ + /* BNET_SIGNAL (-1) return from bnet_recv() => network signal */ + switch (bs->msglen) { + case BNET_EOD: /* end of data */ + return n; + case BNET_EOD_POLL: + bnet_fsend(bs, OK_msg);/* send response */ + return n; /* end of data */ + case BNET_TERMINATE: + bs->terminated = 1; + return n; + case BNET_POLL: + bnet_fsend(bs, OK_msg); /* send response */ + break; + case BNET_HEARTBEAT: +// encode_time(time(NULL), Job); // Dmsg1(100, "%s got heartbeat.\n", Job); - break; - case BNET_HB_RESPONSE: - break; - case BNET_STATUS: - /* *****FIXME***** Implement more completely */ + break; + case BNET_HB_RESPONSE: + break; + case BNET_STATUS: + /* *****FIXME***** Implement more completely */ bnet_fsend(bs, "Status OK\n"); - bnet_sig(bs, BNET_EOD); - break; - case BNET_BTIME: /* send Bacula time */ - char ed1[50]; + bnet_sig(bs, BNET_EOD); + break; + case BNET_BTIME: /* send Bacula time */ + char ed1[50]; bnet_fsend(bs, "btime %s\n", edit_uint64(get_current_btime(),ed1)); - break; - default: + break; + default: Emsg1(M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen); - return n; - } - continue; + return n; + } + continue; } /* Handle normal data */ - if (n > 0 && B_ISDIGIT(bs->msg[0])) { /* response? */ - return n; /* yes, return it */ + if (n > 0 && B_ISDIGIT(bs->msg[0])) { /* response? */ + return n; /* yes, return it */ } /* - * If we get here, it must be a request. Either + * If we get here, it must be a request. Either * a message to dispatch, or a catalog request. * Try to fulfill it. */ if (sscanf(bs->msg, "%020s Job=%127s ", MsgType, Job) != 2) { Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); - continue; + continue; } if (strcmp(Job, "*System*") == 0) { - jcr = NULL; /* No jcr */ + jcr = NULL; /* No jcr */ } else if (!(jcr=get_jcr_by_full_name(Job))) { Emsg1(M_ERROR, 0, _("Job not found: %s\n"), bs->msg); - continue; + continue; } Dmsg1(900, "Getmsg got jcr 0x%x\n", jcr); /* Skip past "Jmsg Job=nnn" */ if (!(msg=find_msg_start(bs->msg))) { Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); - free_jcr(jcr); - continue; + free_jcr(jcr); + continue; } /* @@ -174,23 +174,23 @@ int bget_dirmsg(BSOCK *bs) */ if (bs->msg[0] == 'J') { /* Job message */ if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%d", - Job, &type, &level) != 3) { + Job, &type, &level) != 3) { Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); - free_jcr(jcr); - continue; - } + free_jcr(jcr); + continue; + } Dmsg1(900, "Got msg: %s\n", bs->msg); - skip_spaces(&msg); - skip_nonspaces(&msg); /* skip type=nnn */ - skip_spaces(&msg); - skip_nonspaces(&msg); /* skip level=nnn */ + skip_spaces(&msg); + skip_nonspaces(&msg); /* skip type=nnn */ + skip_spaces(&msg); + skip_nonspaces(&msg); /* skip level=nnn */ if (*msg == ' ') { - msg++; /* skip leading space */ - } + msg++; /* skip leading space */ + } Dmsg1(900, "Dispatch msg: %s", msg); - dispatch_message(jcr, type, level, msg); - free_jcr(jcr); - continue; + dispatch_message(jcr, type, level, msg); + free_jcr(jcr); + continue; } /* * Here we expact a CatReq message @@ -198,85 +198,85 @@ int bget_dirmsg(BSOCK *bs) */ if (bs->msg[0] == 'C') { /* Catalog request */ Dmsg2(900, "Catalog req jcr 0x%x: %s", jcr, bs->msg); - catalog_request(jcr, bs, msg); + catalog_request(jcr, bs, msg); Dmsg1(900, "Calling freejcr 0x%x\n", jcr); - free_jcr(jcr); - continue; + free_jcr(jcr); + continue; } if (bs->msg[0] == 'U') { /* Catalog update */ Dmsg2(900, "Catalog upd jcr 0x%x: %s", jcr, bs->msg); - catalog_update(jcr, bs, msg); + catalog_update(jcr, bs, msg); Dmsg1(900, "Calling freejcr 0x%x\n", jcr); - free_jcr(jcr); - continue; + free_jcr(jcr); + continue; } if (bs->msg[0] == 'M') { /* Mount request */ Dmsg1(900, "Mount req: %s", bs->msg); - mount_request(jcr, bs, msg); - free_jcr(jcr); - continue; + mount_request(jcr, bs, msg); + free_jcr(jcr); + continue; } if (bs->msg[0] == 'S') { /* Status change */ - int JobStatus; - char Job[MAX_NAME_LENGTH]; - if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) { - jcr->SDJobStatus = JobStatus; /* current status */ - } else { + int JobStatus; + char Job[MAX_NAME_LENGTH]; + if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) { + jcr->SDJobStatus = JobStatus; /* current status */ + } else { Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); - } - free_jcr(jcr); - continue; + } + free_jcr(jcr); + continue; } -#ifdef needec +#ifdef needed /* No JCR for Device Updates! */ if (bs->msg[0] = 'D') { /* Device update */ - DEVICE *dev; - POOL_MEM dev_name, changer_name, media_type, volume_name; - int dev_open, dev_append, dev_read, dev_labeled; - int dev_offline, dev_autochanger, dev_autoselect; - int dev_num_writers, dev_max_writers, dev_reserved; - uint64_t dev_PoolId; + DEVICE *dev; + POOL_MEM dev_name, changer_name, media_type, volume_name; + int dev_open, dev_append, dev_read, dev_labeled; + int dev_offline, dev_autochanger, dev_autoselect; + int dev_num_writers, dev_max_writers, dev_reserved; + uint64_t dev_PoolId; Dmsg1(100, "msg); - if (sscanf(bs->msg, Device_update, - &Job, dev_name.c_str(), - &dev_append, &dev_read, - &dev_num_writers, &dev_open, - &dev_labeled, &dev_offline, &dev_reserved, - &dev_max_writers, &dev_autoselect, - &dev_autochanger, - changer_name.c_str(), media_type.c_str(), - volume_name.c_str()) != 15) { + if (sscanf(bs->msg, Device_update, + &Job, dev_name.c_str(), + &dev_append, &dev_read, + &dev_num_writers, &dev_open, + &dev_labeled, &dev_offline, &dev_reserved, + &dev_max_writers, &dev_autoselect, + &dev_autochanger, + changer_name.c_str(), media_type.c_str(), + volume_name.c_str()) != 15) { Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); - } else { - unbash_spaces(dev_name); - dev = (DEVICE *)GetResWithName(R_DEVICE, dev_name.c_str()); - if (!dev) { - continue; - } - unbash_spaces(changer_name); - unbash_spaces(media_type); - unbash_spaces(volume_name); - bstrncpy(dev->ChangerName, changer_name.c_str(), sizeof(dev->ChangerName)); - bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType)); - bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName)); - /* Note, these are copied because they are boolean rather than - * integer. - */ - dev->open = dev_open; - dev->append = dev_append; - dev->read = dev_read; - dev->labeled = dev_labeled; - dev->offline = dev_offline; - dev->autoselect = dev_autoselect; - dev->autochanger = dev_autochanger > 0; - dev->num_drives = dev_autochanger; /* does double duty */ - dev->PoolId = dev_PoolId; - dev->num_writers = dev_num_writers; - dev->max_writers = dev_max_writers; - dev->reserved = dev_reserved; - dev->found = true; - } - continue; + } else { + unbash_spaces(dev_name); + dev = (DEVICE *)GetResWithName(R_DEVICE, dev_name.c_str()); + if (!dev) { + continue; + } + unbash_spaces(changer_name); + unbash_spaces(media_type); + unbash_spaces(volume_name); + bstrncpy(dev->ChangerName, changer_name.c_str(), sizeof(dev->ChangerName)); + bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType)); + bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName)); + /* Note, these are copied because they are boolean rather than + * integer. + */ + dev->open = dev_open; + dev->append = dev_append; + dev->read = dev_read; + dev->labeled = dev_labeled; + dev->offline = dev_offline; + dev->autoselect = dev_autoselect; + dev->autochanger = dev_autochanger > 0; + dev->num_drives = dev_autochanger; /* does double duty */ + dev->PoolId = dev_PoolId; + dev->num_writers = dev_num_writers; + dev->max_writers = dev_max_writers; + dev->reserved = dev_reserved; + dev->found = true; + } + continue; } #endif return n; @@ -287,10 +287,10 @@ static char *find_msg_start(char *msg) { char *p = msg; - skip_nonspaces(&p); /* skip message type */ + skip_nonspaces(&p); /* skip message type */ skip_spaces(&p); - skip_nonspaces(&p); /* skip Job */ - skip_spaces(&p); /* after spaces come the message */ + skip_nonspaces(&p); /* skip Job */ + skip_spaces(&p); /* after spaces come the message */ return p; } @@ -299,7 +299,7 @@ static char *find_msg_start(char *msg) * sent. Check that the response agrees with what we expect. * * Returns: false on failure - * true on success + * true on success */ bool response(JCR *jcr, BSOCK *bs, char *resp, const char *cmd, e_prtmsg prtmsg) { @@ -311,16 +311,16 @@ bool response(JCR *jcr, BSOCK *bs, char *resp, const char *cmd, e_prtmsg prtmsg) if ((n = bget_dirmsg(bs)) >= 0) { Dmsg0(900, bs->msg); if (strcmp(bs->msg, resp) == 0) { - return true; + return true; } Dmsg1(900, "Bad response: ERR=%s", bs->msg); if (prtmsg == DISPLAY_ERROR) { Jmsg(jcr, M_FATAL, 0, _("Bad response to %s command: wanted %s got: %s\n"), - cmd, resp, bs->msg); + cmd, resp, bs->msg); } return false; } Jmsg(jcr, M_FATAL, 0, _("Socket error on %s command: ERR=%s\n"), - cmd, bnet_strerror(bs)); + cmd, bnet_strerror(bs)); return false; } diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index 271655b635..2b448ebb7c 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -196,6 +196,9 @@ struct JCR { bool write_part_after_job; /* Write part after job in SD */ bool needs_sd; /* set if SD needed by Job */ bool cloned; /* set if cloned */ + bool cached_attribute; /* set if attribute is cached */ + ATTR_DBR ar; /* DB attribute record */ + POOLMEM *attr; /* Attribute string from SD */ #endif /* DIRECTOR_DAEMON */ -- 2.39.5