From: Kern Sibbald Date: Fri, 2 May 2008 13:06:54 +0000 (+0000) Subject: kes Apply libdbi patch from Joao Freitas for regress and for X-Git-Tag: Release-3.0.0~1511 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=2722f0d8e0b1ca1a738c0398580004bedc605144;p=bacula%2Fbacula kes Apply libdbi patch from Joao Freitas for regress and for Bacula trunk. Regress now works with libdbi. Nice. kes Apply .nobackup patch from bug #1077 submitted by Edwin Groothuis. kes Apply Bastian Friedrich's patch that adds %p to edit the pool name into jobs cloned via the run directive. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6874 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/AUTHORS b/bacula/AUTHORS index 605ae87e7e..72282f4e96 100644 --- a/bacula/AUTHORS +++ b/bacula/AUTHORS @@ -36,6 +36,7 @@ D. Scott Barninger Devin Reade Dirk Bartley Eamon Brosnan +Edwin Groothuis Eric Bollengier Erich Prinz Felix Schwarz diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 52b3841a7a..38f8180cc3 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -548,6 +548,10 @@ typedef struct dbi_field { unsigned int flags; // 1 == not null } DBI_FIELD; +typedef struct dbi_field_get { + BQUEUE bq; + char *value; +} DBI_FIELD_GET; /* * This is the "real" definition that should only be @@ -562,10 +566,10 @@ struct B_DB { dbi_conn *db; dbi_result *result; dbi_inst instance; - // TODO: change dbi_error_flag to int for more compatible with bacula dbi_error_flag status; DBI_ROW row; DBI_FIELD *fields; + DBI_FIELD_GET *field_get; int num_rows; int row_size; /* size of malloced rows */ int num_fields; diff --git a/bacula/src/cats/dbi.c b/bacula/src/cats/dbi.c index 4582dce4d0..6cdaf88b2b 100644 --- a/bacula/src/cats/dbi.c +++ b/bacula/src/cats/dbi.c @@ -57,6 +57,9 @@ /* List of open databases */ static BQUEUE db_list = {&db_list, &db_list}; +/* Control allocated fields by my_dbi_getvalue */ +static BQUEUE dbi_getvalue_list = {&dbi_getvalue_list, &dbi_getvalue_list}; + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /* @@ -427,8 +430,9 @@ DBI_ROW my_dbi_fetch_row(B_DB *mdb) DBI_ROW row = NULL; // by default, return NULL Dmsg0(500, "my_dbi_fetch_row start\n"); + - if (!mdb->row || mdb->row_size < mdb->num_fields) { + if (!mdb->row || mdb->row_size < mdb->num_fields) { int num_fields = mdb->num_fields; Dmsg1(500, "we have need space of %d bytes\n", sizeof(char *) * mdb->num_fields); @@ -437,7 +441,7 @@ DBI_ROW my_dbi_fetch_row(B_DB *mdb) Dmsg2(500, "my_dbi_free_row row: '%p' num_fields: '%d'\n", mdb->row, mdb->num_fields); if (mdb->num_rows != 0) { for(j = 0; j < mdb->num_fields; j++) { - Dmsg2(500, "my_dbi_free_row row '%p' '%d'\n", mdb->row[j], j); + Dmsg2(500, "my_dbi_free_row row '%p' '%d'\n", mdb->row[j], j); if(mdb->row[j]) { free(mdb->row[j]); } @@ -445,7 +449,7 @@ DBI_ROW my_dbi_fetch_row(B_DB *mdb) } free(mdb->row); } - num_fields += 20; /* add a bit extra */ + //num_fields += 20; /* add a bit extra */ mdb->row = (DBI_ROW)malloc(sizeof(char *) * num_fields); mdb->row_size = num_fields; @@ -455,18 +459,25 @@ DBI_ROW my_dbi_fetch_row(B_DB *mdb) // if still within the result set if (mdb->row_number <= mdb->num_rows) { - Dmsg2(500, "my_dbi_fetch_row row number '%d' is acceptable (0..%d)\n", mdb->row_number, mdb->num_rows); + Dmsg2(500, "my_dbi_fetch_row row number '%d' is acceptable (1..%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] = my_dbi_getvalue(mdb->result, mdb->row_number, j); - Dmsg3(500, "my_dbi_fetch_row field '%p' '%d' has value '%s'\n",mdb->row[j], j, mdb->row[j]); + mdb->row[j] = my_dbi_getvalue(mdb->result, mdb->row_number, j); + // allocate space to queue row + mdb->field_get = (DBI_FIELD_GET *)malloc(sizeof(DBI_FIELD_GET)); + // store the pointer in queue + mdb->field_get->value = mdb->row[j]; + Dmsg4(500, "my_dbi_fetch_row row[%d] field: '%p' in queue: '%p' has value: '%s'\n", + j, mdb->row[j], mdb->field_get->value, mdb->row[j]); + // insert in queue to future free + qinsert(&dbi_getvalue_list, &mdb->field_get->bq); } // increment the row number for the next call mdb->row_number++; row = mdb->row; } else { - Dmsg2(500, "my_dbi_fetch_row row number '%d' is NOT acceptable (0..%d)\n", mdb->row_number, mdb->num_rows); + Dmsg2(500, "my_dbi_fetch_row row number '%d' is NOT acceptable (1..%d)\n", mdb->row_number, mdb->num_rows); } Dmsg1(500, "my_dbi_fetch_row finishes returning %p\n", row); @@ -488,9 +499,9 @@ int my_dbi_max_length(B_DB *mdb, int field_num) { if (my_dbi_getisnull(mdb->result, i, field_num)) { this_length = 4; // "NULL" } else { - // TODO: error cbuf = my_dbi_getvalue(mdb->result, i, field_num); this_length = cstrlen(cbuf); + // cbuf is always free free(cbuf); } @@ -516,8 +527,9 @@ DBI_FIELD * my_dbi_fetch_field(B_DB *mdb) Dmsg1(500, "allocating space for %d fields\n", mdb->num_fields); mdb->fields = (DBI_FIELD *)malloc(sizeof(DBI_FIELD) * mdb->num_fields); mdb->fields_size = mdb->num_fields; - + for (i = 0; i < mdb->num_fields; i++) { + // num_fileds is starting at 1, increment i by 1 dbi_index = i + 1; Dmsg1(500, "filling field %d\n", i); mdb->fields[i].name = (char *)dbi_result_get_field_name(mdb->result, dbi_index); @@ -584,9 +596,10 @@ int my_dbi_query(B_DB *mdb, const char *query) Dmsg1(500, "we have a result\n", query); // how many fields in the set? + // num_fields starting at 1 mdb->num_fields = dbi_result_get_numfields(mdb->result); Dmsg1(500, "we have %d fields\n", mdb->num_fields); - + // if no result num_rows is 0 mdb->num_rows = dbi_result_get_numrows(mdb->result); Dmsg1(500, "we have %d rows\n", mdb->num_rows); @@ -613,6 +626,7 @@ bail_out: void my_dbi_free_result(B_DB *mdb) { + DBI_FIELD_GET *f; db_lock(mdb); int i = 0; if (mdb->result) { @@ -623,25 +637,30 @@ void my_dbi_free_result(B_DB *mdb) mdb->result = NULL; if (mdb->row) { - Dmsg2(500, "my_dbi_free_result row: '%p' num_fields: '%d'\n", mdb->row, mdb->num_fields); - if (mdb->num_rows != 0) { - for(i = 0; i < mdb->num_fields; i++) { - Dmsg2(500, "my_dbi_free_result row '%p' '%d'\n", mdb->row[i], i); - if(mdb->row[i]) { - free(mdb->row[i]); - } - } - } free(mdb->row); - mdb->row = NULL; } - + + /* now is time to free all value return by my_dbi_get_value + * this is necessary because libdbi don't free memory return by yours results + * and Bacula has some routine wich call more than once time my_dbi_fetch_row + * + * Using a queue to store all pointer allocate is a good way to free all things + * when necessary + */ + while((f=(DBI_FIELD_GET *)qremove(&dbi_getvalue_list))) { + Dmsg2(500, "my_dbi_free_result field value: '%p' in queue: '%p'\n", f->value, f); + free(f->value); + free(f); + } + + mdb->row = NULL; + if (mdb->fields) { free(mdb->fields); mdb->fields = NULL; } db_unlock(mdb); - //Dmsg0(500, "my_dbi_free_result finish\n"); + Dmsg0(500, "my_dbi_free_result finish\n"); } @@ -1015,13 +1034,11 @@ int my_dbi_getisnull(dbi_result *result, int row_number, int column_number) { */ char *my_dbi_getvalue(dbi_result *result, int row_number, unsigned int column_number) { - /* TODO: This is very bad, need refactoring */ - //POOLMEM *buf = get_pool_memory(PM_FNAME); char *buf = NULL; const char *errmsg; const char *field_name; unsigned short dbitype; - int32_t field_length = 0; + size_t field_length; int64_t num; /* correct the index for dbi interface @@ -1046,18 +1063,17 @@ char *my_dbi_getvalue(dbi_result *result, int row_number, unsigned int column_nu field_length = dbi_result_get_field_length(result, field_name); dbitype = dbi_result_get_field_type_idx(result,column_number); + Dmsg3(500, "my_dbi_getvalue start: type: '%d' " + "field_length bytes: '%d' fieldname: '%s'\n", + dbitype, field_length, field_name); + if(field_length) { - //buf = check_pool_memory_size(buf, field_length + 1); - buf = (char *)malloc(sizeof(char *) * field_length + 1); + //buf = (char *)malloc(sizeof(char *) * field_length + 1); + buf = (char *)malloc(field_length + 1); } else { /* if numbers */ - //buf = check_pool_memory_size(buf, 50); buf = (char *)malloc(sizeof(char *) * 50); - } - - Dmsg4(500, "my_dbi_getvalue result '%p' type '%d' \n\tfield name '%s'\n\t" - "field_length '%d'\n", - result, dbitype, field_name, field_length); + } switch (dbitype) { case DBI_TYPE_INTEGER: @@ -1106,100 +1122,13 @@ char *my_dbi_getvalue(dbi_result *result, int row_number, unsigned int column_nu Dmsg1(500, "my_dbi_getvalue error: %s\n", errmsg); } - Dmsg3(500, "my_dbi_getvalue finish result '%p' num bytes '%d' data '%s'\n", - result, field_length, buf); - + Dmsg3(500, "my_dbi_getvalue finish buffer: '%p' num bytes: '%d' data: '%s'\n", + buf, field_length, buf); + + // don't worry about this buf return buf; } -//int my_dbi_getvalue(dbi_result *result, int row_number, unsigned int column_number, char *value) { -// -// void *v; -// const char *errmsg; -// int error = 0; -// const char *field_name; -// unsigned short dbitype; -// int32_t field_length = 0; -// int64_t num; -// -// /* correct the index for dbi interface -// * dbi index begins 1 -// * I prefer do not change others functions -// */ -// Dmsg3(600, "my_dbi_getvalue pre-starting result '%p' row number '%d' column number '%d'\n", -// result, row_number, column_number); -// -// column_number++; -// -// if(row_number == 0) { -// row_number++; -// } -// -// Dmsg3(600, "my_dbi_getvalue starting result '%p' row number '%d' column number '%d'\n", -// result, row_number, column_number); -// -// if(dbi_result_seek_row(result, row_number)) { -// -// field_name = dbi_result_get_field_name(result, column_number); -// field_length = dbi_result_get_field_length(result, field_name); -// dbitype = dbi_result_get_field_type_idx(result,column_number); -// -// Dmsg4(500, "my_dbi_getvalue result '%p' type '%d' \n\tfield name '%s'\n\t" -// "field_length '%d'\n", result, dbitype, field_name, field_length); -// -// switch (dbitype) { -// case DBI_TYPE_INTEGER: -// v = (int64_t *)malloc(sizeof(int64_t)); -// error = dbi_result_bind_longlong(result, field_name, (int64_t *)v); -// // transform in string -// num = *(int64_t *)v; -// edit_int64(num, value); -// field_length = strlen(value); -// break; -// case DBI_TYPE_STRING: -// if(field_length) { -// dbi_result_bind_string(result, field_name, (const char **)v); -// value = (char *) v; -// } else { -// value[0] = 0; -// } -// break; -// case DBI_TYPE_BINARY: -// if(field_length) { -// dbi_result_bind_binary(result, field_name, (const unsigned char **)v); -// value = (char *)v; -// } else { -// value[0] = 0; -// } -// break; -// case DBI_TYPE_DATETIME: -// //time_t last; -// struct tm tm; -// -// v = (time_t *)dbi_result_get_datetime(result, field_name); -// dbi_result_bind_datetime(result, field_name, (time_t *)v); -// if(!v) { -// field_length = bsnprintf(value, 20, "0000-00-00 00:00:00"); -// } else { -// (void)localtime_r((time_t *)v, &tm); -// field_length = bsnprintf(value, 20, "%04d-%02d-%02d %02d:%02d:%02d", -// (tm.tm_year + 1900), (tm.tm_mon + 1), tm.tm_mday, -// tm.tm_hour, tm.tm_min, tm.tm_sec); -// } -// break; -// } -// -// } else { -// dbi_conn_error(dbi_result_get_conn(result), &errmsg); -// Dmsg1(500, "my_dbi_getvalue error: %s\n", errmsg); -// } -// -// Dmsg2(500, "my_dbi_getvalue finish result '%p' num bytes '%d'\n", -// result, field_length); -// -// return 1; -//} - int my_dbi_sql_insert_id(B_DB *mdb, char *table_name) { /* diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 57bc4bc432..031f81eff8 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -460,6 +460,7 @@ struct FOPTS { alist drivetype; /* drive type limitation */ char *reader; /* reader program */ char *writer; /* writer program */ + char *ignoredir; /* ignoredir string */ char *plugin; /* plugin program */ }; diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index 827f6a3378..2561e70c78 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -369,6 +369,9 @@ static bool send_fileset(JCR *jcr) if (fo->plugin) { fd->fsend("G %s\n", fo->plugin); } + if (fo->ignoredir) { + bnet_fsend(fd, "Z %s\n", fo->ignoredir); + } if (fo->reader) { fd->fsend("D %s\n", fo->reader); } diff --git a/bacula/src/dird/inc_conf.c b/bacula/src/dird/inc_conf.c index 62837e42bc..3dc445fd9d 100644 --- a/bacula/src/dird/inc_conf.c +++ b/bacula/src/dird/inc_conf.c @@ -58,6 +58,7 @@ static void options_res(LEX *lc, RES_ITEM *item, int index, int pass); static void store_base(LEX *lc, RES_ITEM *item, int index, int pass); static void store_plugin(LEX *lc, RES_ITEM *item, int index, int pass); static void store_reader(LEX *lc, RES_ITEM *item, int index, int pass); +static void store_ignoredir(LEX *lc, RES_ITEM *item, int index, int pass); static void store_writer(LEX *lc, RES_ITEM *item, int index, int pass); static void setup_current_opts(void); @@ -84,9 +85,10 @@ static INCEXE res_incexe; * name handler value code flags default_value */ static RES_ITEM newinc_items[] = { - {"file", store_fname, {0}, 0, 0, 0}, - {"plugin", store_plugin_name, {0}, 0, 0, 0}, - {"options", options_res, {0}, 0, 0, 0}, + {"file", store_fname, {0}, 0, 0, 0}, + {"plugin", store_plugin_name, {0}, 0, 0, 0}, + {"ignoredir", store_ignoredir, {0}, 0, 0, 0}, + {"options", options_res, {0}, 0, 0, 0}, {NULL, NULL, {0}, 0, 0, 0} }; @@ -604,6 +606,21 @@ static void store_fstype(LEX *lc, RES_ITEM *item, int index, int pass) scan_to_eol(lc); } +/* Store ignoredir info */ +static void store_ignoredir(LEX *lc, RES_ITEM *item, int index, int pass) +{ + int token; + + token = lex_get_token(lc, T_NAME); + if (pass == 1) { + /* + * Pickup reader command + */ + res_incexe.current_opts->ignoredir = bstrdup(lc->str); + } + scan_to_eol(lc); +} + /* Store drivetype info */ static void store_drivetype(LEX *lc, RES_ITEM *item, int index, int pass) { diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 56b15930b9..cf3c1da504 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -567,8 +567,8 @@ static bool job_check_maxruntime(JCR *jcr) return false; } Dmsg6(200, "check_maxruntime %u - %u >= %u|%u|%u|%u\n\n", - watchdog_time, jcr->start_time, job->MaxRunTime, job->FullMaxRunTime, - job->IncMaxRunTime, job->DiffMaxRunTime); + watchdog_time, jcr->start_time, job->MaxRunTime, job->FullMaxRunTime, + job->IncMaxRunTime, job->DiffMaxRunTime); if (jcr->JobLevel == L_FULL && job->FullMaxRunTime != 0 && (watchdog_time - jcr->start_time) >= job->FullMaxRunTime) { @@ -1307,12 +1307,12 @@ void free_wstorage(JCR *jcr) jcr->wstore = NULL; } -char *job_code_callback_clones(JCR *jcr, const char* param) { - if (param[0] == 'p') { - return jcr->pool->name(); - } else { - return NULL; - } +char *job_code_callback_clones(JCR *jcr, const char* param) +{ + if (param[0] == 'p') { + return jcr->pool->name(); + } + return NULL; } void create_clones(JCR *jcr) diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index 1338e4a2f2..6c45c3bb9a 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -321,6 +321,9 @@ void *handle_client_request(void *dirp) fo->base.destroy(); fo->fstype.destroy(); fo->drivetype.destroy(); + if (fo->ignoredir != NULL) { + free(fo->ignoredir); + } } incexe->opts_list.destroy(); incexe->name_list.destroy(); @@ -680,7 +683,7 @@ static void add_file_to_fileset(JCR *jcr, const char *fname, findFILESET *filese } break; case '<': - Dmsg0(100, "Doing < include on client.\n"); + Dmsg1(100, "Doing < of '%s' include on client.\n", p + 1); p++; /* skip over < */ if ((ffd = fopen(p, "rb")) == NULL) { berrno be; @@ -846,6 +849,11 @@ static void add_fileset(JCR *jcr, const char *item) set_options(current_opts, item); state = state_options; break; + case 'Z': + current_opts = start_options(ff); + current_opts->ignoredir = bstrdup(item); + state = state_options; + break; case 'D': current_opts = start_options(ff); // current_opts->reader = bstrdup(item); @@ -907,6 +915,9 @@ static bool term_fileset(JCR *jcr) for (k=0; kdrivetype.size(); k++) { Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k)); } + if (fo->ignoredir) { + Dmsg1(400, "Z %s\n", fo->ignoredir); + } } dlistString *node; foreach_dlist(node, &incexe->name_list) { diff --git a/bacula/src/findlib/find.c b/bacula/src/findlib/find.c index 7e059e4b22..3542a5b43a 100644 --- a/bacula/src/findlib/find.c +++ b/bacula/src/findlib/find.c @@ -280,6 +280,7 @@ static bool accept_file(FF_PKT *ff) findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j); ff->flags = fo->flags; ff->GZIP_level = fo->GZIP_level; + ff->ignoredir = fo->ignoredir; ff->fstypes = fo->fstype; ff->drivetypes = fo->drivetype; diff --git a/bacula/src/findlib/find.h b/bacula/src/findlib/find.h index 040458d5d2..4c012f5981 100644 --- a/bacula/src/findlib/find.h +++ b/bacula/src/findlib/find.h @@ -44,6 +44,7 @@ #endif #include +#include #if HAVE_UTIME_H #include #else @@ -158,6 +159,7 @@ struct findFOPTS { alist base; /* list of base names */ alist fstype; /* file system type limitation */ alist drivetype; /* drive type limitation */ + char *ignoredir; /* ignore directories with this file */ }; @@ -223,6 +225,7 @@ struct FF_PKT { uint32_t flags; /* backup options */ int GZIP_level; /* compression level */ int strip_path; /* strip path count */ + char *ignoredir; /* ignore directories with this file */ bool cmd_plugin; /* set if we have a command plugin */ alist fstypes; /* allowed file system types */ alist drivetypes; /* allowed drive types */ diff --git a/bacula/src/findlib/find_one.c b/bacula/src/findlib/find_one.c index 576d4c6b88..7c22ee0a41 100644 --- a/bacula/src/findlib/find_one.c +++ b/bacula/src/findlib/find_one.c @@ -513,6 +513,28 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, } } + /* + * Ignore this directory and everything below if the file .nobackup + * (or what is defined for IgnoreDir in this fileset) exists + */ + if (ff_pkt->ignoredir != NULL) { + struct stat sb; + char fname[MAXPATHLEN]; + + if (strlen(ff_pkt->fname) + strlen("/") + + strlen(ff_pkt->ignoredir) + 1 > MAXPATHLEN) + return 1; /* Is this wisdom? */ + + strcpy(fname, ff_pkt->fname); + strcat(fname, "/"); + strcat(fname, ff_pkt->ignoredir); + if (stat(fname, &sb) == 0) { + Dmsg2(100, "Directory '%s' ignored (found %s)\n", + ff_pkt->fname, ff_pkt->ignoredir); + return 1; /* Just ignore this directory */ + } + } + /* Build a canonical directory name with a trailing slash in link var */ len = strlen(fname); link_len = len + 200; diff --git a/bacula/src/version.h b/bacula/src/version.h index 57bdc43f34..40e7b9d8bf 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -3,9 +3,9 @@ */ #undef VERSION -#define VERSION "2.3.18" -#define BDATE "01 May 2008" -#define LSMDATE "01May08" +#define VERSION "2.3.19" +#define BDATE "02 May 2008" +#define LSMDATE "02May08" #define PROG_COPYRIGHT "Copyright (C) %d-2008 Free Software Foundation Europe e.V.\n" #define BYEAR "2008" /* year for copyright messages in progs */ diff --git a/bacula/technotes-2.3 b/bacula/technotes-2.3 index 7d93b5e066..96cdb8b566 100644 --- a/bacula/technotes-2.3 +++ b/bacula/technotes-2.3 @@ -24,6 +24,13 @@ Add long term statistics job table General: +02May08 +kes Apply libdbi patch from Joao Freitas for regress and for + Bacula trunk. Regress now works with libdbi. Nice. +kes Apply .nobackup patch from bug #1077 submitted by + Edwin Groothuis. +kes Apply Bastian Friedrich's patch that adds %p to edit the pool + name into jobs cloned via the run directive. 01May08 kes Prevent a Volume that is being swapped from being freed from the volume list. This will most likely fix, at least partially,