From: Kern Sibbald Date: Thu, 7 Oct 2004 15:26:37 +0000 (+0000) Subject: - Added Rerun Failed Levels = yes/no X-Git-Tag: Release-1.35.8~7 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=901d263fc1ddff636eb3ea1f992eb357958d77ec;p=bacula%2Fbacula - Added Rerun Failed Levels = yes/no - Made calling offline_or_rewind() non-fatal if the device is not open. - Added Martin's suggestion to have multiple level index on the file table. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1635 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/cats/make_mysql_tables.in b/bacula/src/cats/make_mysql_tables.in index 4a8b9623a0..f4395b6668 100644 --- a/bacula/src/cats/make_mysql_tables.in +++ b/bacula/src/cats/make_mysql_tables.in @@ -32,9 +32,7 @@ CREATE TABLE File ( LStat TINYBLOB NOT NULL, MD5 TINYBLOB NOT NULL, PRIMARY KEY(FileId), - INDEX (JobId), - INDEX (PathId), - INDEX (FilenameId) + INDEX (JobId, PathId, FilenameId), ); diff --git a/bacula/src/cats/make_postgresql_tables.in b/bacula/src/cats/make_postgresql_tables.in index 47d5d40ca1..f055fd7267 100644 --- a/bacula/src/cats/make_postgresql_tables.in +++ b/bacula/src/cats/make_postgresql_tables.in @@ -210,9 +210,7 @@ create table file primary key (fileid) ); -create index file_jobid_idx on file (jobid); -create index file_pathid_idx on file(pathid); -create index file_filenameid_idx on file(filenameid); +create index file_jpfid_idx on file (jobid, pathid, filenameid); create table jobmedia ( diff --git a/bacula/src/cats/make_sqlite_tables.in b/bacula/src/cats/make_sqlite_tables.in index 23657baef8..850b8f1efd 100644 --- a/bacula/src/cats/make_sqlite_tables.in +++ b/bacula/src/cats/make_sqlite_tables.in @@ -35,9 +35,7 @@ CREATE TABLE File ( PRIMARY KEY(FileId) ); -CREATE INDEX inx3 ON File (JobId); -CREATE INDEX inx4 ON File (PathId); -CREATE INDEX inx5 ON File (FileNameId); +CREATE INDEX inx3 ON File (JobId, PathId, FileNameId); CREATE TABLE Job ( JobId INTEGER UNSIGNED NOT NULL, diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index 22ed9f6de6..6fe707657a 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -34,8 +34,8 @@ /* sql.c */ 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); int db_open_database(JCR *jcr, B_DB *db); void db_close_database(JCR *jcr, B_DB *db); void db_escape_string(char *snew, char *old, int len); @@ -52,7 +52,7 @@ int db_create_job_record(JCR *jcr, B_DB *db, JOB_DBR *jr); int db_create_media_record(JCR *jcr, B_DB *db, MEDIA_DBR *media_dbr); int db_create_client_record(JCR *jcr, B_DB *db, CLIENT_DBR *cr); int db_create_fileset_record(JCR *jcr, B_DB *db, FILESET_DBR *fsr); -int db_create_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pool_dbr); +int db_create_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pool_dbr); bool db_create_jobmedia_record(JCR *jcr, B_DB *mdb, JOBMEDIA_DBR *jr); int db_create_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr); @@ -64,6 +64,7 @@ int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr); int db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime); int db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr); int db_find_next_volume(JCR *jcr, B_DB *mdb, int index, bool InChanger, MEDIA_DBR *mr); +bool db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &JobLevel); /* get.c */ int db_get_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pdbr); diff --git a/bacula/src/cats/sql_find.c b/bacula/src/cats/sql_find.c index dc47ba6924..436340d804 100644 --- a/bacula/src/cats/sql_find.c +++ b/bacula/src/cats/sql_find.c @@ -143,6 +143,47 @@ db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime) return 1; } +/* + * Find last failed job since given start-time + * it must be either Full or Diff. + * + * Returns: false on failure + * true on success, jr is unchanged and stime unchanged + * level returned in JobLevel + */ +bool +db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &JobLevel) +{ + SQL_ROW row; + + db_lock(mdb); + /* Differential is since last Full backup */ + Mmsg(mdb->cmd, +"SELECT JobLevel FROM Job WHERE JobStatus!='T' AND Type='%c' AND " +"Level IN ('%c','%c') AND Name='%s' AND ClientId=%u " +"AND FileSetId=%u AND StartTime>'%s' " +"ORDER BY StartTime DESC LIMIT 1", + jr->JobType, L_INCREMENTAL, L_DIFFERENTIAL, jr->Name, + jr->ClientId, jr->FileSetId, stime); + + if (!QUERY_DB(jcr, mdb, mdb->cmd)) { + db_unlock(mdb); + return false; + } + + if ((row = sql_fetch_row(mdb)) == NULL) { + sql_free_result(mdb); + db_unlock(mdb); + return false; + } + JobLevel = str_to_int64(row[0]); + sql_free_result(mdb); + + db_unlock(mdb); + return true; +} + + /* * Find JobId of last job that ran. E.g. for * VERIFY_CATALOG we want the JobId of the last INIT. diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index a2f4a75e9d..33ed9bee98 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -8,14 +8,14 @@ * 1. The generic lexical scanner in lib/lex.c and lib/lex.h * * 2. The generic config scanner in lib/parse_config.c and - * lib/parse_config.h. - * These files contain the parser code, some utility - * routines, and the common store routines (name, int, - * string). + * lib/parse_config.h. + * These files contain the parser code, some utility + * routines, and the common store routines (name, int, + * string). * * 3. The daemon specific file, which contains the Resource - * definitions as well as any specific store routines - * for the resource records. + * definitions as well as any specific store routines + * for the resource records. * * Kern Sibbald, January MM * @@ -83,7 +83,7 @@ int res_all_size = sizeof(res_all); /* * Director Resource * - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM dir_items[] = { {"name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0}, @@ -108,7 +108,7 @@ static RES_ITEM dir_items[] = { /* * Console Resource * - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM con_items[] = { {"name", store_name, ITEM(res_con.hdr.name), 0, ITEM_REQUIRED, 0}, @@ -131,7 +131,7 @@ static RES_ITEM con_items[] = { /* * Client or File daemon resource * - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM cli_items[] = { @@ -153,7 +153,7 @@ static RES_ITEM cli_items[] = { /* Storage daemon resource * - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM store_items[] = { {"name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0}, @@ -176,7 +176,7 @@ static RES_ITEM store_items[] = { /* * Catalog Resource Directives * - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM cat_items[] = { {"name", store_name, ITEM(res_cat.hdr.name), 0, ITEM_REQUIRED, 0}, @@ -197,7 +197,7 @@ static RES_ITEM cat_items[] = { /* * Job Resource Directives * - * name handler value code flags default_value + * name handler value code flags default_value */ RES_ITEM job_items[] = { {"name", store_name, ITEM(res_job.hdr.name), 0, ITEM_REQUIRED, 0}, @@ -229,6 +229,7 @@ RES_ITEM job_items[] = { {"prunevolumes",store_yesno, ITEM(res_job.PruneVolumes), 1, ITEM_DEFAULT, 0}, {"spoolattributes",store_yesno, ITEM(res_job.SpoolAttributes), 1, ITEM_DEFAULT, 0}, {"spooldata", store_yesno, ITEM(res_job.spool_data), 1, ITEM_DEFAULT, 0}, + {"rerunfailedlevels", store_yesno, ITEM(res_job.rerun_failed_levels), 1, ITEM_DEFAULT, 0}, {"runbeforejob", store_str, ITEM(res_job.RunBeforeJob), 0, 0, 0}, {"runafterjob", store_str, ITEM(res_job.RunAfterJob), 0, 0, 0}, {"runafterfailedjob", store_str, ITEM(res_job.RunAfterFailedJob), 0, 0, 0}, @@ -244,7 +245,7 @@ RES_ITEM job_items[] = { /* FileSet resource * - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM fs_items[] = { {"name", store_name, ITEM(res_fs.hdr.name), 0, ITEM_REQUIRED, 0}, @@ -252,13 +253,13 @@ static RES_ITEM fs_items[] = { {"include", store_inc, NULL, 0, ITEM_NO_EQUALS, 0}, {"exclude", store_inc, NULL, 1, ITEM_NO_EQUALS, 0}, {"ignorefilesetchanges", store_yesno, ITEM(res_fs.ignore_fs_changes), 1, ITEM_DEFAULT, 0}, - {NULL, NULL, NULL, 0, 0, 0} + {NULL, NULL, NULL, 0, 0, 0} }; /* Schedule -- see run_conf.c */ /* Schedule * - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM sch_items[] = { {"name", store_name, ITEM(res_sch.hdr.name), 0, ITEM_REQUIRED, 0}, @@ -269,7 +270,7 @@ static RES_ITEM sch_items[] = { /* Pool resource * - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM pool_items[] = { {"name", store_name, ITEM(res_pool.hdr.name), 0, ITEM_REQUIRED, 0}, @@ -297,7 +298,7 @@ static RES_ITEM pool_items[] = { /* * Counter Resource - * name handler value code flags default_value + * name handler value code flags default_value */ static RES_ITEM counter_items[] = { {"name", store_name, ITEM(res_counter.hdr.name), 0, ITEM_REQUIRED, 0}, @@ -320,7 +321,7 @@ extern RES_ITEM msgs_items[]; * NOTE!!! keep it in the same order as the R_codes * or eliminate all resources[rindex].name * - * name items rcode res_head + * name items rcode res_head */ RES_TABLE resources[] = { {"director", dir_items, R_DIRECTOR}, @@ -335,13 +336,13 @@ RES_TABLE resources[] = { {"counter", counter_items, R_COUNTER}, {"console", con_items, R_CONSOLE}, {"jobdefs", job_items, R_JOBDEFS}, - {NULL, NULL, 0} + {NULL, NULL, 0} }; /* Keywords (RHS) permitted in Job Level records * - * level_name level job_type + * level_name level job_type */ struct s_jl joblevels[] = { {"Full", L_FULL, JT_BACKUP}, @@ -356,19 +357,19 @@ struct s_jl joblevels[] = { {"Data", L_VERIFY_DATA, JT_VERIFY}, {" ", L_NONE, JT_ADMIN}, {" ", L_NONE, JT_RESTORE}, - {NULL, 0, 0} + {NULL, 0, 0} }; /* Keywords (RHS) permitted in Job type records * - * type_name job_type + * type_name job_type */ struct s_jt jobtypes[] = { {"backup", JT_BACKUP}, {"admin", JT_ADMIN}, {"verify", JT_VERIFY}, {"restore", JT_RESTORE}, - {NULL, 0} + {NULL, 0} }; #ifdef old_deprecated_code @@ -378,7 +379,7 @@ static struct s_kw BakVerFields[] = { {"client", 'C'}, {"fileset", 'F'}, {"level", 'L'}, - {NULL, 0} + {NULL, 0} }; /* Keywords (RHS) permitted in Restore records */ @@ -389,7 +390,7 @@ static struct s_kw RestoreFields[] = { {"where", 'W'}, /* root of restore */ {"replace", 'R'}, /* replacement options */ {"bootstrap", 'B'}, /* bootstrap file */ - {NULL, 0} + {NULL, 0} }; #endif @@ -399,7 +400,7 @@ struct s_kw ReplaceOptions[] = { {"ifnewer", REPLACE_IFNEWER}, {"ifolder", REPLACE_IFOLDER}, {"never", REPLACE_NEVER}, - {NULL, 0} + {NULL, 0} }; const char *level_to_str(int level) @@ -411,8 +412,8 @@ const char *level_to_str(int level) bsnprintf(level_no, sizeof(level_no), "%d", level); /* default if not found */ for (i=0; joblevels[i].level_name; i++) { if (level == joblevels[i].level) { - str = joblevels[i].level_name; - break; + str = joblevels[i].level_name; + break; } } return str; @@ -429,93 +430,93 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm sendit(sock, "No %s resource defined\n", res_to_str(type)); return; } - if (type < 0) { /* no recursion */ + if (type < 0) { /* no recursion */ type = - type; recurse = false; } switch (type) { case R_DIRECTOR: sendit(sock, "Director: name=%s MaxJobs=%d FDtimeout=%s SDtimeout=%s\n", - reshdr->name, res->res_dir.MaxConcurrentJobs, - edit_uint64(res->res_dir.FDConnectTimeout, ed1), - edit_uint64(res->res_dir.SDConnectTimeout, ed2)); + reshdr->name, res->res_dir.MaxConcurrentJobs, + edit_uint64(res->res_dir.FDConnectTimeout, ed1), + edit_uint64(res->res_dir.SDConnectTimeout, ed2)); if (res->res_dir.query_file) { sendit(sock, " query_file=%s\n", res->res_dir.query_file); } if (res->res_dir.messages) { sendit(sock, " --> "); - dump_resource(-R_MSGS, (RES *)res->res_dir.messages, sendit, sock); + dump_resource(-R_MSGS, (RES *)res->res_dir.messages, sendit, sock); } break; case R_CONSOLE: sendit(sock, "Console: name=%s SSL=%d\n", - res->res_con.hdr.name, res->res_con.enable_ssl); + res->res_con.hdr.name, res->res_con.enable_ssl); break; case R_COUNTER: if (res->res_counter.WrapCounter) { sendit(sock, "Counter: name=%s min=%d max=%d cur=%d wrapcntr=%s\n", - res->res_counter.hdr.name, res->res_counter.MinValue, - res->res_counter.MaxValue, res->res_counter.CurrentValue, - res->res_counter.WrapCounter->hdr.name); + res->res_counter.hdr.name, res->res_counter.MinValue, + res->res_counter.MaxValue, res->res_counter.CurrentValue, + res->res_counter.WrapCounter->hdr.name); } else { sendit(sock, "Counter: name=%s min=%d max=%d\n", - res->res_counter.hdr.name, res->res_counter.MinValue, - res->res_counter.MaxValue); + res->res_counter.hdr.name, res->res_counter.MinValue, + res->res_counter.MaxValue); } if (res->res_counter.Catalog) { sendit(sock, " --> "); - dump_resource(-R_CATALOG, (RES *)res->res_counter.Catalog, sendit, sock); + dump_resource(-R_CATALOG, (RES *)res->res_counter.Catalog, sendit, sock); } break; case R_CLIENT: sendit(sock, "Client: name=%s address=%s FDport=%d MaxJobs=%u\n", - res->res_client.hdr.name, res->res_client.address, res->res_client.FDport, - res->res_client.MaxConcurrentJobs); + res->res_client.hdr.name, res->res_client.address, res->res_client.FDport, + res->res_client.MaxConcurrentJobs); sendit(sock, " JobRetention=%s FileRetention=%s AutoPrune=%d\n", - edit_utime(res->res_client.JobRetention, ed1, sizeof(ed1)), - edit_utime(res->res_client.FileRetention, ed2, sizeof(ed2)), - res->res_client.AutoPrune); + edit_utime(res->res_client.JobRetention, ed1, sizeof(ed1)), + edit_utime(res->res_client.FileRetention, ed2, sizeof(ed2)), + res->res_client.AutoPrune); if (res->res_client.catalog) { sendit(sock, " --> "); - dump_resource(-R_CATALOG, (RES *)res->res_client.catalog, sendit, sock); + dump_resource(-R_CATALOG, (RES *)res->res_client.catalog, sendit, sock); } break; case R_STORAGE: sendit(sock, "Storage: name=%s address=%s SDport=%d MaxJobs=%u\n\ DeviceName=%s MediaType=%s\n", - res->res_store.hdr.name, res->res_store.address, res->res_store.SDport, - res->res_store.MaxConcurrentJobs, - res->res_store.dev_name, res->res_store.media_type); + res->res_store.hdr.name, res->res_store.address, res->res_store.SDport, + res->res_store.MaxConcurrentJobs, + res->res_store.dev_name, res->res_store.media_type); break; case R_CATALOG: sendit(sock, "Catalog: name=%s address=%s DBport=%d db_name=%s\n\ db_user=%s\n", - res->res_cat.hdr.name, NPRT(res->res_cat.db_address), - res->res_cat.db_port, res->res_cat.db_name, NPRT(res->res_cat.db_user)); + res->res_cat.hdr.name, NPRT(res->res_cat.db_address), + res->res_cat.db_port, res->res_cat.db_name, NPRT(res->res_cat.db_user)); break; case R_JOB: case R_JOBDEFS: sendit(sock, "%s: name=%s JobType=%d level=%s Priority=%d MaxJobs=%u\n", type == R_JOB ? "Job" : "JobDefs", - res->res_job.hdr.name, res->res_job.JobType, - level_to_str(res->res_job.JobLevel), res->res_job.Priority, - res->res_job.MaxConcurrentJobs); + res->res_job.hdr.name, res->res_job.JobType, + level_to_str(res->res_job.JobLevel), res->res_job.Priority, + res->res_job.MaxConcurrentJobs); sendit(sock, " Resched=%d Times=%d Interval=%s Spool=%d\n", - res->res_job.RescheduleOnError, res->res_job.RescheduleTimes, - edit_uint64_with_commas(res->res_job.RescheduleInterval, ed1), - res->res_job.spool_data); + res->res_job.RescheduleOnError, res->res_job.RescheduleTimes, + edit_uint64_with_commas(res->res_job.RescheduleInterval, ed1), + res->res_job.spool_data); if (res->res_job.client) { sendit(sock, " --> "); - dump_resource(-R_CLIENT, (RES *)res->res_job.client, sendit, sock); + dump_resource(-R_CLIENT, (RES *)res->res_job.client, sendit, sock); } if (res->res_job.fileset) { sendit(sock, " --> "); - dump_resource(-R_FILESET, (RES *)res->res_job.fileset, sendit, sock); + dump_resource(-R_FILESET, (RES *)res->res_job.fileset, sendit, sock); } if (res->res_job.schedule) { sendit(sock, " --> "); - dump_resource(-R_SCHEDULE, (RES *)res->res_job.schedule, sendit, sock); + dump_resource(-R_SCHEDULE, (RES *)res->res_job.schedule, sendit, sock); } if (res->res_job.RestoreWhere) { sendit(sock, " --> Where=%s\n", NPRT(res->res_job.RestoreWhere)); @@ -537,33 +538,33 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm } if (res->res_job.storage[0]) { sendit(sock, " --> "); - /* ***FIXME*** */ -// dump_resource(-R_STORAGE, (RES *)res->res_job.storage, sendit, sock); + /* ***FIXME*** */ +// dump_resource(-R_STORAGE, (RES *)res->res_job.storage, sendit, sock); } if (res->res_job.pool) { sendit(sock, " --> "); - dump_resource(-R_POOL, (RES *)res->res_job.pool, sendit, sock); + dump_resource(-R_POOL, (RES *)res->res_job.pool, sendit, sock); } if (res->res_job.full_pool) { sendit(sock, " --> "); - dump_resource(-R_POOL, (RES *)res->res_job.full_pool, sendit, sock); + dump_resource(-R_POOL, (RES *)res->res_job.full_pool, sendit, sock); } if (res->res_job.inc_pool) { sendit(sock, " --> "); - dump_resource(-R_POOL, (RES *)res->res_job.inc_pool, sendit, sock); + dump_resource(-R_POOL, (RES *)res->res_job.inc_pool, sendit, sock); } if (res->res_job.dif_pool) { sendit(sock, " --> "); - dump_resource(-R_POOL, (RES *)res->res_job.dif_pool, sendit, sock); + dump_resource(-R_POOL, (RES *)res->res_job.dif_pool, sendit, sock); } if (res->res_job.verify_job) { sendit(sock, " --> "); - dump_resource(-type, (RES *)res->res_job.verify_job, sendit, sock); + dump_resource(-type, (RES *)res->res_job.verify_job, sendit, sock); } break; if (res->res_job.messages) { sendit(sock, " --> "); - dump_resource(-R_MSGS, (RES *)res->res_job.messages, sendit, sock); + dump_resource(-R_MSGS, (RES *)res->res_job.messages, sendit, sock); } break; case R_FILESET: @@ -571,151 +572,151 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm int i, j, k; sendit(sock, "FileSet: name=%s\n", res->res_fs.hdr.name); for (i=0; ires_fs.num_includes; i++) { - INCEXE *incexe = res->res_fs.include_items[i]; - for (j=0; jnum_opts; j++) { - FOPTS *fo = incexe->opts_list[j]; + INCEXE *incexe = res->res_fs.include_items[i]; + for (j=0; jnum_opts; j++) { + FOPTS *fo = incexe->opts_list[j]; sendit(sock, " O %s\n", fo->opts); - for (k=0; kregex.size(); k++) { + for (k=0; kregex.size(); k++) { sendit(sock, " R %s\n", fo->regex.get(k)); - } - for (k=0; kwild.size(); k++) { + } + for (k=0; kwild.size(); k++) { sendit(sock, " W %s\n", fo->wild.get(k)); - } - for (k=0; kbase.size(); k++) { + } + for (k=0; kbase.size(); k++) { sendit(sock, " B %s\n", fo->base.get(k)); - } - if (fo->reader) { + } + if (fo->reader) { sendit(sock, " D %s\n", fo->reader); - } - if (fo->writer) { + } + if (fo->writer) { sendit(sock, " T %s\n", fo->writer); - } + } sendit(sock, " N\n"); - } - for (j=0; jname_list.size(); j++) { + } + for (j=0; jname_list.size(); j++) { sendit(sock, " I %s\n", incexe->name_list.get(j)); - } - if (incexe->name_list.size()) { + } + if (incexe->name_list.size()) { sendit(sock, " N\n"); - } + } } - + for (i=0; ires_fs.num_excludes; i++) { - INCEXE *incexe = res->res_fs.exclude_items[i]; - for (j=0; jname_list.size(); j++) { + INCEXE *incexe = res->res_fs.exclude_items[i]; + for (j=0; jname_list.size(); j++) { sendit(sock, " E %s\n", incexe->name_list.get(j)); - } - if (incexe->name_list.size()) { + } + if (incexe->name_list.size()) { sendit(sock, " N\n"); - } + } } break; } case R_SCHEDULE: if (res->res_sch.run) { - int i; - RUN *run = res->res_sch.run; - char buf[1000], num[30]; + int i; + RUN *run = res->res_sch.run; + char buf[1000], num[30]; sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name); - if (!run) { - break; - } + if (!run) { + break; + } next_run: sendit(sock, " --> Run Level=%s\n", level_to_str(run->level)); bstrncpy(buf, " hour=", sizeof(buf)); - for (i=0; i<24; i++) { - if (bit_is_set(i, run->hour)) { + for (i=0; i<24; i++) { + if (bit_is_set(i, run->hour)) { bsnprintf(num, sizeof(num), "%d ", i); - bstrncat(buf, num, sizeof(buf)); - } - } + bstrncat(buf, num, sizeof(buf)); + } + } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); + sendit(sock, buf); bstrncpy(buf, " mday=", sizeof(buf)); - for (i=0; i<31; i++) { - if (bit_is_set(i, run->mday)) { + for (i=0; i<31; i++) { + if (bit_is_set(i, run->mday)) { bsnprintf(num, sizeof(num), "%d ", i); - bstrncat(buf, num, sizeof(buf)); - } - } + bstrncat(buf, num, sizeof(buf)); + } + } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); + sendit(sock, buf); bstrncpy(buf, " month=", sizeof(buf)); - for (i=0; i<12; i++) { - if (bit_is_set(i, run->month)) { + for (i=0; i<12; i++) { + if (bit_is_set(i, run->month)) { bsnprintf(num, sizeof(num), "%d ", i); - bstrncat(buf, num, sizeof(buf)); - } - } + bstrncat(buf, num, sizeof(buf)); + } + } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); + sendit(sock, buf); bstrncpy(buf, " wday=", sizeof(buf)); - for (i=0; i<7; i++) { - if (bit_is_set(i, run->wday)) { + for (i=0; i<7; i++) { + if (bit_is_set(i, run->wday)) { bsnprintf(num, sizeof(num), "%d ", i); - bstrncat(buf, num, sizeof(buf)); - } - } + bstrncat(buf, num, sizeof(buf)); + } + } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); + sendit(sock, buf); bstrncpy(buf, " wom=", sizeof(buf)); - for (i=0; i<5; i++) { - if (bit_is_set(i, run->wom)) { + for (i=0; i<5; i++) { + if (bit_is_set(i, run->wom)) { bsnprintf(num, sizeof(num), "%d ", i); - bstrncat(buf, num, sizeof(buf)); - } - } + bstrncat(buf, num, sizeof(buf)); + } + } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); + sendit(sock, buf); bstrncpy(buf, " woy=", sizeof(buf)); - for (i=0; i<54; i++) { - if (bit_is_set(i, run->woy)) { + for (i=0; i<54; i++) { + if (bit_is_set(i, run->woy)) { bsnprintf(num, sizeof(num), "%d ", i); - bstrncat(buf, num, sizeof(buf)); - } - } + bstrncat(buf, num, sizeof(buf)); + } + } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); + sendit(sock, buf); sendit(sock, " mins=%d\n", run->minute); - if (run->pool) { + if (run->pool) { sendit(sock, " --> "); - dump_resource(-R_POOL, (RES *)run->pool, sendit, sock); - } - if (run->storage) { + dump_resource(-R_POOL, (RES *)run->pool, sendit, sock); + } + if (run->storage) { sendit(sock, " --> "); - dump_resource(-R_STORAGE, (RES *)run->storage, sendit, sock); - } - if (run->msgs) { + dump_resource(-R_STORAGE, (RES *)run->storage, sendit, sock); + } + if (run->msgs) { sendit(sock, " --> "); - dump_resource(-R_MSGS, (RES *)run->msgs, sendit, sock); - } - /* If another Run record is chained in, go print it */ - if (run->next) { - run = run->next; - goto next_run; - } + dump_resource(-R_MSGS, (RES *)run->msgs, sendit, sock); + } + /* If another Run record is chained in, go print it */ + if (run->next) { + run = run->next; + goto next_run; + } } else { sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name); } break; case R_POOL: sendit(sock, "Pool: name=%s PoolType=%s\n", res->res_pool.hdr.name, - res->res_pool.pool_type); + res->res_pool.pool_type); sendit(sock, " use_cat=%d use_once=%d acpt_any=%d cat_files=%d\n", - res->res_pool.use_catalog, res->res_pool.use_volume_once, - res->res_pool.accept_any_volume, res->res_pool.catalog_files); + res->res_pool.use_catalog, res->res_pool.use_volume_once, + res->res_pool.accept_any_volume, res->res_pool.catalog_files); sendit(sock, " max_vols=%d auto_prune=%d VolRetention=%s\n", - res->res_pool.max_volumes, res->res_pool.AutoPrune, - edit_utime(res->res_pool.VolRetention, ed1, sizeof(ed1))); + res->res_pool.max_volumes, res->res_pool.AutoPrune, + edit_utime(res->res_pool.VolRetention, ed1, sizeof(ed1))); sendit(sock, " VolUse=%s recycle=%d LabelFormat=%s\n", - edit_utime(res->res_pool.VolUseDuration, ed1, sizeof(ed1)), - res->res_pool.Recycle, - NPRT(res->res_pool.label_format)); + edit_utime(res->res_pool.VolUseDuration, ed1, sizeof(ed1)), + res->res_pool.Recycle, + NPRT(res->res_pool.label_format)); sendit(sock, " CleaningPrefix=%s\n", - NPRT(res->res_pool.cleaning_prefix)); + NPRT(res->res_pool.cleaning_prefix)); sendit(sock, " recyleOldest=%d MaxVolJobs=%d MaxVolFiles=%d\n", - res->res_pool.purge_oldest_volume, - res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles); + res->res_pool.purge_oldest_volume, + res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles); break; case R_MSGS: sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name); @@ -745,10 +746,10 @@ static void free_incexe(INCEXE *incexe) fopt->wild.destroy(); fopt->base.destroy(); if (fopt->reader) { - free(fopt->reader); + free(fopt->reader); } if (fopt->writer) { - free(fopt->writer); + free(fopt->writer); } free(fopt); } @@ -768,7 +769,7 @@ static void free_incexe(INCEXE *incexe) void free_resource(RES *sres, int type) { int num; - RES *nres; /* next resource if linked */ + RES *nres; /* next resource if linked */ URES *res = (URES *)sres; if (res == NULL) @@ -786,152 +787,152 @@ void free_resource(RES *sres, int type) switch (type) { case R_DIRECTOR: if (res->res_dir.working_directory) { - free(res->res_dir.working_directory); + free(res->res_dir.working_directory); } if (res->res_dir.pid_directory) { - free(res->res_dir.pid_directory); + free(res->res_dir.pid_directory); } if (res->res_dir.subsys_directory) { - free(res->res_dir.subsys_directory); + free(res->res_dir.subsys_directory); } if (res->res_dir.password) { - free(res->res_dir.password); + free(res->res_dir.password); } if (res->res_dir.query_file) { - free(res->res_dir.query_file); + free(res->res_dir.query_file); } if (res->res_dir.DIRaddrs) { - free_addresses(res->res_dir.DIRaddrs); + free_addresses(res->res_dir.DIRaddrs); } break; case R_COUNTER: break; case R_CONSOLE: if (res->res_con.password) { - free(res->res_con.password); + free(res->res_con.password); } for (int i=0; ires_con.ACL_lists[i]) { - delete res->res_con.ACL_lists[i]; - res->res_con.ACL_lists[i] = NULL; - } + if (res->res_con.ACL_lists[i]) { + delete res->res_con.ACL_lists[i]; + res->res_con.ACL_lists[i] = NULL; + } } break; case R_CLIENT: if (res->res_client.address) { - free(res->res_client.address); + free(res->res_client.address); } if (res->res_client.password) { - free(res->res_client.password); + free(res->res_client.password); } break; case R_STORAGE: if (res->res_store.address) { - free(res->res_store.address); + free(res->res_store.address); } if (res->res_store.password) { - free(res->res_store.password); + free(res->res_store.password); } if (res->res_store.media_type) { - free(res->res_store.media_type); + free(res->res_store.media_type); } if (res->res_store.dev_name) { - free(res->res_store.dev_name); + free(res->res_store.dev_name); } break; case R_CATALOG: if (res->res_cat.db_address) { - free(res->res_cat.db_address); + free(res->res_cat.db_address); } if (res->res_cat.db_socket) { - free(res->res_cat.db_socket); + free(res->res_cat.db_socket); } if (res->res_cat.db_user) { - free(res->res_cat.db_user); + free(res->res_cat.db_user); } if (res->res_cat.db_name) { - free(res->res_cat.db_name); + free(res->res_cat.db_name); } if (res->res_cat.db_password) { - free(res->res_cat.db_password); + free(res->res_cat.db_password); } break; case R_FILESET: if ((num=res->res_fs.num_includes)) { - while (--num >= 0) { - free_incexe(res->res_fs.include_items[num]); - } - free(res->res_fs.include_items); + while (--num >= 0) { + free_incexe(res->res_fs.include_items[num]); + } + free(res->res_fs.include_items); } res->res_fs.num_includes = 0; if ((num=res->res_fs.num_excludes)) { - while (--num >= 0) { - free_incexe(res->res_fs.exclude_items[num]); - } - free(res->res_fs.exclude_items); + while (--num >= 0) { + free_incexe(res->res_fs.exclude_items[num]); + } + free(res->res_fs.exclude_items); } res->res_fs.num_excludes = 0; break; case R_POOL: if (res->res_pool.pool_type) { - free(res->res_pool.pool_type); + free(res->res_pool.pool_type); } if (res->res_pool.label_format) { - free(res->res_pool.label_format); + free(res->res_pool.label_format); } if (res->res_pool.cleaning_prefix) { - free(res->res_pool.cleaning_prefix); + free(res->res_pool.cleaning_prefix); } break; case R_SCHEDULE: if (res->res_sch.run) { - RUN *nrun, *next; - nrun = res->res_sch.run; - while (nrun) { - next = nrun->next; - free(nrun); - nrun = next; - } + RUN *nrun, *next; + nrun = res->res_sch.run; + while (nrun) { + next = nrun->next; + free(nrun); + nrun = next; + } } break; case R_JOB: case R_JOBDEFS: if (res->res_job.RestoreWhere) { - free(res->res_job.RestoreWhere); + free(res->res_job.RestoreWhere); } if (res->res_job.RestoreBootstrap) { - free(res->res_job.RestoreBootstrap); + free(res->res_job.RestoreBootstrap); } if (res->res_job.WriteBootstrap) { - free(res->res_job.WriteBootstrap); + free(res->res_job.WriteBootstrap); } if (res->res_job.RunBeforeJob) { - free(res->res_job.RunBeforeJob); + free(res->res_job.RunBeforeJob); } if (res->res_job.RunAfterJob) { - free(res->res_job.RunAfterJob); + free(res->res_job.RunAfterJob); } if (res->res_job.RunAfterFailedJob) { - free(res->res_job.RunAfterFailedJob); + free(res->res_job.RunAfterFailedJob); } if (res->res_job.ClientRunBeforeJob) { - free(res->res_job.ClientRunBeforeJob); + free(res->res_job.ClientRunBeforeJob); } if (res->res_job.ClientRunAfterJob) { - free(res->res_job.ClientRunAfterJob); + free(res->res_job.ClientRunAfterJob); } for (int i=0; i < MAX_STORE; i++) { - if (res->res_job.storage[i]) { - delete (alist *)res->res_job.storage[i]; - } + if (res->res_job.storage[i]) { + delete (alist *)res->res_job.storage[i]; + } } break; case R_MSGS: if (res->res_msgs.mail_cmd) { - free(res->res_msgs.mail_cmd); + free(res->res_msgs.mail_cmd); } if (res->res_msgs.operator_cmd) { - free(res->res_msgs.operator_cmd); + free(res->res_msgs.operator_cmd); } free_msgs_res((MSGS *)res); /* free message resource */ res = NULL; @@ -967,16 +968,16 @@ void save_resource(int type, RES_ITEM *items, int pass) * Ensure that all required items are present */ for (i=0; items[i].name; i++) { - if (items[i].flags & ITEM_REQUIRED) { - if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) { + if (items[i].flags & ITEM_REQUIRED) { + if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) { Emsg2(M_ERROR_TERM, 0, "%s item is required in %s resource, but not found.\n", - items[i].name, resources[rindex]); - } - } - /* If this triggers, take a look at lib/parse_conf.h */ - if (i >= MAX_RES_ITEMS) { + items[i].name, resources[rindex]); + } + } + /* If this triggers, take a look at lib/parse_conf.h */ + if (i >= MAX_RES_ITEMS) { Emsg1(M_ERROR_TERM, 0, "Too many items in %s resource\n", resources[rindex]); - } + } } } @@ -995,76 +996,76 @@ void save_resource(int type, RES_ITEM *items, int pass) case R_POOL: case R_MSGS: case R_FILESET: - break; + break; /* Resources containing another resource */ case R_DIRECTOR: - if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) { + if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) { Emsg1(M_ERROR_TERM, 0, "Cannot find Director resource %s\n", res_all.res_dir.hdr.name); - } - res->res_dir.messages = res_all.res_dir.messages; - break; + } + res->res_dir.messages = res_all.res_dir.messages; + break; case R_JOB: case R_JOBDEFS: - if ((res = (URES *)GetResWithName(type, res_all.res_dir.hdr.name)) == NULL) { + if ((res = (URES *)GetResWithName(type, res_all.res_dir.hdr.name)) == NULL) { Emsg1(M_ERROR_TERM, 0, "Cannot find Job resource %s\n", - res_all.res_dir.hdr.name); - } - res->res_job.messages = res_all.res_job.messages; - res->res_job.schedule = res_all.res_job.schedule; - res->res_job.client = res_all.res_job.client; - res->res_job.fileset = res_all.res_job.fileset; - for (int i=0; i < MAX_STORE; i++) { - res->res_job.storage[i] = res_all.res_job.storage[i]; - } - res->res_job.pool = res_all.res_job.pool; - res->res_job.full_pool = res_all.res_job.full_pool; - res->res_job.inc_pool = res_all.res_job.inc_pool; - res->res_job.dif_pool = res_all.res_job.dif_pool; - res->res_job.verify_job = res_all.res_job.verify_job; - res->res_job.jobdefs = res_all.res_job.jobdefs; - break; + res_all.res_dir.hdr.name); + } + res->res_job.messages = res_all.res_job.messages; + res->res_job.schedule = res_all.res_job.schedule; + res->res_job.client = res_all.res_job.client; + res->res_job.fileset = res_all.res_job.fileset; + for (int i=0; i < MAX_STORE; i++) { + res->res_job.storage[i] = res_all.res_job.storage[i]; + } + res->res_job.pool = res_all.res_job.pool; + res->res_job.full_pool = res_all.res_job.full_pool; + res->res_job.inc_pool = res_all.res_job.inc_pool; + res->res_job.dif_pool = res_all.res_job.dif_pool; + res->res_job.verify_job = res_all.res_job.verify_job; + res->res_job.jobdefs = res_all.res_job.jobdefs; + break; case R_COUNTER: - if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) { + if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) { Emsg1(M_ERROR_TERM, 0, "Cannot find Counter resource %s\n", res_all.res_counter.hdr.name); - } - res->res_counter.Catalog = res_all.res_counter.Catalog; - res->res_counter.WrapCounter = res_all.res_counter.WrapCounter; - break; + } + res->res_counter.Catalog = res_all.res_counter.Catalog; + res->res_counter.WrapCounter = res_all.res_counter.WrapCounter; + break; case R_CLIENT: - if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_client.hdr.name)) == NULL) { + if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_client.hdr.name)) == NULL) { Emsg1(M_ERROR_TERM, 0, "Cannot find Client resource %s\n", res_all.res_client.hdr.name); - } - res->res_client.catalog = res_all.res_client.catalog; - break; + } + res->res_client.catalog = res_all.res_client.catalog; + break; case R_SCHEDULE: - /* - * Schedule is a bit different in that it contains a RUN record + /* + * Schedule is a bit different in that it contains a RUN record * chain which isn't a "named" resource. This chain was linked - * in by run_conf.c during pass 2, so here we jam the pointer - * into the Schedule resource. - */ - if ((res = (URES *)GetResWithName(R_SCHEDULE, res_all.res_client.hdr.name)) == NULL) { + * in by run_conf.c during pass 2, so here we jam the pointer + * into the Schedule resource. + */ + if ((res = (URES *)GetResWithName(R_SCHEDULE, res_all.res_client.hdr.name)) == NULL) { Emsg1(M_ERROR_TERM, 0, "Cannot find Schedule resource %s\n", res_all.res_client.hdr.name); - } - res->res_sch.run = res_all.res_sch.run; - break; + } + res->res_sch.run = res_all.res_sch.run; + break; default: Emsg1(M_ERROR, 0, "Unknown resource type %d in save_resource.\n", type); - error = 1; - break; + error = 1; + break; } /* Note, the resource name was already saved during pass 1, * so here, we can just release it. */ if (res_all.res_dir.hdr.name) { - free(res_all.res_dir.hdr.name); - res_all.res_dir.hdr.name = NULL; + free(res_all.res_dir.hdr.name); + res_all.res_dir.hdr.name = NULL; } if (res_all.res_dir.hdr.desc) { - free(res_all.res_dir.hdr.desc); - res_all.res_dir.hdr.desc = NULL; + free(res_all.res_dir.hdr.desc); + res_all.res_dir.hdr.desc = NULL; } return; } @@ -1118,22 +1119,22 @@ void save_resource(int type, RES_ITEM *items, int pass) res = (URES *)malloc(size); memcpy(res, &res_all, size); if (!res_head[rindex]) { - res_head[rindex] = (RES *)res; /* store first entry */ + res_head[rindex] = (RES *)res; /* store first entry */ Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type), - res->res_dir.hdr.name, rindex); + res->res_dir.hdr.name, rindex); } else { - RES *next; - /* Add new res to end of chain */ - for (next=res_head[rindex]; next->next; next=next->next) { - if (strcmp(next->name, res->res_dir.hdr.name) == 0) { - Emsg2(M_ERROR_TERM, 0, + RES *next; + /* Add new res to end of chain */ + for (next=res_head[rindex]; next->next; next=next->next) { + if (strcmp(next->name, res->res_dir.hdr.name) == 0) { + Emsg2(M_ERROR_TERM, 0, _("Attempt to define second %s resource named \"%s\" is not permitted.\n"), - resources[rindex].name, res->res_dir.hdr.name); - } - } - next->next = (RES *)res; + resources[rindex].name, res->res_dir.hdr.name); + } + } + next->next = (RES *)res; Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type), - res->res_dir.hdr.name, rindex, pass); + res->res_dir.hdr.name, rindex, pass); } } } @@ -1150,9 +1151,9 @@ void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass) /* Store the type both pass 1 and pass 2 */ for (i=0; jobtypes[i].type_name; i++) { if (strcasecmp(lc->str, jobtypes[i].type_name) == 0) { - *(int *)(item->value) = jobtypes[i].job_type; - i = 0; - break; + *(int *)(item->value) = jobtypes[i].job_type; + i = 0; + break; } } if (i != 0) { @@ -1174,9 +1175,9 @@ void store_level(LEX *lc, RES_ITEM *item, int index, int pass) /* Store the level pass 2 so that type is defined */ for (i=0; joblevels[i].level_name; i++) { if (strcasecmp(lc->str, joblevels[i].level_name) == 0) { - *(int *)(item->value) = joblevels[i].level; - i = 0; - break; + *(int *)(item->value) = joblevels[i].level; + i = 0; + break; } } if (i != 0) { @@ -1193,9 +1194,9 @@ void store_replace(LEX *lc, RES_ITEM *item, int index, int pass) /* Scan Replacement options */ for (i=0; ReplaceOptions[i].name; i++) { if (strcasecmp(lc->str, ReplaceOptions[i].name) == 0) { - *(int *)(item->value) = ReplaceOptions[i].token; - i = 0; - break; + *(int *)(item->value) = ReplaceOptions[i].token; + i = 0; + break; } } if (i != 0) { @@ -1216,16 +1217,16 @@ void store_acl(LEX *lc, RES_ITEM *item, int index, int pass) for (;;) { token = lex_get_token(lc, T_NAME); if (pass == 1) { - if (((alist **)item->value)[item->code] == NULL) { - ((alist **)item->value)[item->code] = New(alist(10, owned_by_alist)); + if (((alist **)item->value)[item->code] == NULL) { + ((alist **)item->value)[item->code] = New(alist(10, owned_by_alist)); Dmsg1(900, "Defined new ACL alist at %d\n", item->code); - } - ((alist **)item->value)[item->code]->append(bstrdup(lc->str)); + } + ((alist **)item->value)[item->code]->append(bstrdup(lc->str)); Dmsg2(900, "Appended to %d %s\n", item->code, lc->str); } token = lex_get_token(lc, T_ALL); if (token == T_COMMA) { - continue; /* get another ACL */ + continue; /* get another ACL */ } break; } diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index bd864082b6..d3344eb4c6 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -221,6 +221,7 @@ struct JOB { int PruneVolumes; /* Force pruning of Volumes */ int SpoolAttributes; /* Set to spool attributes in SD */ int spool_data; /* Set to spool data in SD */ + int rerun_failed_levels; /* Upgrade to rerun failed levels */ uint32_t MaxConcurrentJobs; /* Maximume concurrent jobs */ int RescheduleOnError; /* Set to reschedule on error */ int RescheduleTimes; /* Number of times to reschedule job */ diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index ee2e89eda4..46131fc04b 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -144,6 +144,7 @@ int connect_to_file_daemon(JCR *jcr, int retry_interval, int max_retry_time, */ void get_level_since_time(JCR *jcr, char *since, int since_len) { + int JobLevel; /* Lookup the last FULL backup job to get the time/date for a * differential or incremental save. */ @@ -158,12 +159,24 @@ 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 */ 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; } else { + 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)); + bsnprintf(since, since_len, " (upgraded from %s)", + 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); } diff --git a/bacula/src/stored/dev.c b/bacula/src/stored/dev.c index b4f8639480..d38c0a3b14 100644 --- a/bacula/src/stored/dev.c +++ b/bacula/src/stored/dev.c @@ -350,7 +350,7 @@ open_dev(DEVICE *dev, char *VolName, int mode) #ifdef debug_tracing #undef rewind_dev -int _rewind_dev(char *file, int line, DEVICE *dev) +bool _rewind_dev(char *file, int line, DEVICE *dev) { Dmsg2(100, "rewind_dev called from %s:%d\n", file, line); return rewind_dev(dev); @@ -763,8 +763,11 @@ bool offline_dev(DEVICE *dev) return true; } -int offline_or_rewind_dev(DEVICE *dev) +bool offline_or_rewind_dev(DEVICE *dev) { + if (dev->fd < 0) { + return false; + } if (dev_cap(dev, CAP_OFFLINEUNMOUNT)) { return offline_dev(dev); } else { diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 4c8560a49f..38633dc1c8 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -28,173 +28,173 @@ uint32_t new_VolSessionId(); /* From acquire.c */ -DCR *acquire_device_for_append(JCR *jcr); -DCR *acquire_device_for_read(JCR *jcr); -bool release_device(JCR *jcr); -DCR *new_dcr(JCR *jcr, DEVICE *dev); -void free_dcr(DCR *dcr); +DCR *acquire_device_for_append(JCR *jcr); +DCR *acquire_device_for_read(JCR *jcr); +bool release_device(JCR *jcr); +DCR *new_dcr(JCR *jcr, DEVICE *dev); +void free_dcr(DCR *dcr); /* From askdir.c */ enum get_vol_info_rw { GET_VOL_INFO_FOR_WRITE, GET_VOL_INFO_FOR_READ }; -bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw); -bool dir_find_next_appendable_volume(DCR *dcr); -bool dir_update_volume_info(DCR *dcr, bool label); -bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr); -bool dir_ask_sysop_to_mount_volume(DCR *dcr); -bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec); -bool dir_send_job_status(JCR *jcr); -bool dir_create_jobmedia_record(DCR *dcr); +bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw); +bool dir_find_next_appendable_volume(DCR *dcr); +bool dir_update_volume_info(DCR *dcr, bool label); +bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr); +bool dir_ask_sysop_to_mount_volume(DCR *dcr); +bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec); +bool dir_send_job_status(JCR *jcr); +bool dir_create_jobmedia_record(DCR *dcr); /* authenticate.c */ -int authenticate_director(JCR *jcr); -int authenticate_filed(JCR *jcr); +int authenticate_director(JCR *jcr); +int authenticate_filed(JCR *jcr); /* From autochanger.c */ -int autoload_device(DCR *dcr, int writing, BSOCK *dir); -bool autochanger_list(DCR *dcr, BSOCK *dir); -void invalidate_slot_in_catalog(DCR *dcr); -char *edit_device_codes(JCR *jcr, char *omsg, const char *imsg, const char *cmd); +int autoload_device(DCR *dcr, int writing, BSOCK *dir); +bool autochanger_list(DCR *dcr, BSOCK *dir); +void invalidate_slot_in_catalog(DCR *dcr); +char *edit_device_codes(JCR *jcr, char *omsg, const char *imsg, const char *cmd); /* From block.c */ -void dump_block(DEV_BLOCK *b, const char *msg); +void dump_block(DEV_BLOCK *b, const char *msg); DEV_BLOCK *new_block(DEVICE *dev); DEV_BLOCK *dup_block(DEV_BLOCK *eblock); -void init_block_write(DEV_BLOCK *block); -void empty_block(DEV_BLOCK *block); -void free_block(DEV_BLOCK *block); -bool write_block_to_device(DCR *dcr); -bool write_block_to_dev(DCR *dcr); -void print_block_read_errors(JCR *jcr, DEV_BLOCK *block); -void ser_block_header(DEV_BLOCK *block); +void init_block_write(DEV_BLOCK *block); +void empty_block(DEV_BLOCK *block); +void free_block(DEV_BLOCK *block); +bool write_block_to_device(DCR *dcr); +bool write_block_to_dev(DCR *dcr); +void print_block_read_errors(JCR *jcr, DEV_BLOCK *block); +void ser_block_header(DEV_BLOCK *block); #define CHECK_BLOCK_NUMBERS true #define NO_BLOCK_NUMBER_CHECK false -bool read_block_from_device(DCR *dcr, bool check_block_numbers); -bool read_block_from_dev(DCR *dcr, bool check_block_numbers); +bool read_block_from_device(DCR *dcr, bool check_block_numbers); +bool read_block_from_dev(DCR *dcr, bool check_block_numbers); /* From butil.c -- utilities for SD tool programs */ -void print_ls_output(const char *fname, const char *link, int type, struct stat *statp); +void print_ls_output(const char *fname, const char *link, int type, struct stat *statp); JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr, - const char *VolumeName, int mode); -void display_tape_error_status(JCR *jcr, DEVICE *dev); + const char *VolumeName, int mode); +void display_tape_error_status(JCR *jcr, DEVICE *dev); /* From dev.c */ -DEVICE *init_dev(DEVICE *dev, DEVRES *device); -int open_dev(DEVICE *dev, char *VolName, int mode); -void close_dev(DEVICE *dev); -void force_close_dev(DEVICE *dev); -bool truncate_dev(DEVICE *dev); -void term_dev(DEVICE *dev); -char * strerror_dev(DEVICE *dev); -void clrerror_dev(DEVICE *dev, int func); -bool update_pos_dev(DEVICE *dev); -bool rewind_dev(DEVICE *dev); -bool load_dev(DEVICE *dev); -bool offline_dev(DEVICE *dev); -int flush_dev(DEVICE *dev); -int weof_dev(DEVICE *dev, int num); -int write_block(DEVICE *dev); +DEVICE *init_dev(DEVICE *dev, DEVRES *device); +int open_dev(DEVICE *dev, char *VolName, int mode); +void close_dev(DEVICE *dev); +void force_close_dev(DEVICE *dev); +bool truncate_dev(DEVICE *dev); +void term_dev(DEVICE *dev); +char * strerror_dev(DEVICE *dev); +void clrerror_dev(DEVICE *dev, int func); +bool update_pos_dev(DEVICE *dev); +bool rewind_dev(DEVICE *dev); +bool load_dev(DEVICE *dev); +bool offline_dev(DEVICE *dev); +int flush_dev(DEVICE *dev); +int weof_dev(DEVICE *dev, int num); +int write_block(DEVICE *dev); uint32_t status_dev(DEVICE *dev); -int eod_dev(DEVICE *dev); -bool fsf_dev(DEVICE *dev, int num); -bool fsr_dev(DEVICE *dev, int num); -bool bsf_dev(DEVICE *dev, int num); -bool bsr_dev(DEVICE *dev, int num); -void attach_jcr_to_device(DEVICE *dev, JCR *jcr); -void detach_jcr_from_device(DEVICE *dev, JCR *jcr); -JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); -bool dev_can_write(DEVICE *dev); -int offline_or_rewind_dev(DEVICE *dev); -bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); -void init_dev_wait_timers(DEVICE *dev); -bool double_dev_wait_time(DEVICE *dev); +int eod_dev(DEVICE *dev); +bool fsf_dev(DEVICE *dev, int num); +bool fsr_dev(DEVICE *dev, int num); +bool bsf_dev(DEVICE *dev, int num); +bool bsr_dev(DEVICE *dev, int num); +void attach_jcr_to_device(DEVICE *dev, JCR *jcr); +void detach_jcr_from_device(DEVICE *dev, JCR *jcr); +JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); +bool dev_can_write(DEVICE *dev); +bool offline_or_rewind_dev(DEVICE *dev); +bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); +void init_dev_wait_timers(DEVICE *dev); +bool double_dev_wait_time(DEVICE *dev); /* Get info about device */ -char * dev_name(DEVICE *dev); -char * dev_vol_name(DEVICE *dev); +char * dev_name(DEVICE *dev); +char * dev_vol_name(DEVICE *dev); uint32_t dev_block(DEVICE *dev); uint32_t dev_file(DEVICE *dev); -bool dev_is_tape(DEVICE *dev); +bool dev_is_tape(DEVICE *dev); /* From device.c */ -bool open_device(DCR *dcr); -bool first_open_device(DEVICE *dev); -bool fixup_device_block_write_error(DCR *dcr); -void _lock_device(const char *file, int line, DEVICE *dev); -void _unlock_device(const char *file, int line, DEVICE *dev); -void _block_device(const char *file, int line, DEVICE *dev, int state); -void _unblock_device(const char *file, int line, DEVICE *dev); -void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state); -void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold); -void set_new_volume_parameters(DCR *dcr); -void set_new_file_parameters(DCR *dcr); -bool device_is_unmounted(DEVICE *dev); -void dev_lock(DEVICE *dev); -void dev_unlock(DEVICE *dev); +bool open_device(DCR *dcr); +bool first_open_device(DEVICE *dev); +bool fixup_device_block_write_error(DCR *dcr); +void _lock_device(const char *file, int line, DEVICE *dev); +void _unlock_device(const char *file, int line, DEVICE *dev); +void _block_device(const char *file, int line, DEVICE *dev, int state); +void _unblock_device(const char *file, int line, DEVICE *dev); +void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state); +void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold); +void set_new_volume_parameters(DCR *dcr); +void set_new_file_parameters(DCR *dcr); +bool device_is_unmounted(DEVICE *dev); +void dev_lock(DEVICE *dev); +void dev_unlock(DEVICE *dev); const char *edit_blocked_reason(DEVICE *dev); /* From dircmd.c */ -void *handle_connection_request(void *arg); +void *handle_connection_request(void *arg); /* From fd_cmds.c */ -void run_job(JCR *jcr); -bool bootstrap_cmd(JCR *jcr); +void run_job(JCR *jcr); +bool bootstrap_cmd(JCR *jcr); /* From job.c */ -void stored_free_jcr(JCR *jcr); -void connection_from_filed(void *arg); -void handle_filed_connection(BSOCK *fd, char *job_name); +void stored_free_jcr(JCR *jcr); +void connection_from_filed(void *arg); +void handle_filed_connection(BSOCK *fd, char *job_name); /* From label.c */ -int read_dev_volume_label(DCR *dcr); -void create_session_label(DCR *dcr, DEV_RECORD *rec, int label); -void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName); -bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName); -bool write_session_label(DCR *dcr, int label); -bool write_volume_label_to_block(DCR *dcr); -void dump_volume_label(DEVICE *dev); -void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); -bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec); -bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); +int read_dev_volume_label(DCR *dcr); +void create_session_label(DCR *dcr, DEV_RECORD *rec, int label); +void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName); +bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName); +bool write_session_label(DCR *dcr, int label); +bool write_volume_label_to_block(DCR *dcr); +void dump_volume_label(DEVICE *dev); +void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); +bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec); +bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); /* From match_bsr.c */ -int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, - SESSION_LABEL *sesrec); -int match_bsr_block(BSR *bsr, DEV_BLOCK *block); -void position_bsr_block(BSR *bsr, DEV_BLOCK *block); -BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); -bool match_set_eof(BSR *bsr, DEV_RECORD *rec); +int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, + SESSION_LABEL *sesrec); +int match_bsr_block(BSR *bsr, DEV_BLOCK *block); +void position_bsr_block(BSR *bsr, DEV_BLOCK *block); +BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); +bool match_set_eof(BSR *bsr, DEV_RECORD *rec); /* From mount.c */ -bool mount_next_write_volume(DCR *dcr, bool release); -bool mount_next_read_volume(DCR *dcr); -void release_volume(DCR *ddr); -void mark_volume_in_error(DCR *dcr); +bool mount_next_write_volume(DCR *dcr, bool release); +bool mount_next_read_volume(DCR *dcr); +void release_volume(DCR *ddr); +void mark_volume_in_error(DCR *dcr); /* From parse_bsr.c */ -BSR *parse_bsr(JCR *jcr, char *lf); -void dump_bsr(BSR *bsr, bool recurse); -void free_bsr(BSR *bsr); +BSR *parse_bsr(JCR *jcr, char *lf); +void dump_bsr(BSR *bsr, bool recurse); +void free_bsr(BSR *bsr); VOL_LIST *new_vol(); -int add_vol(JCR *jcr, VOL_LIST *vol); -void free_vol_list(JCR *jcr); -void create_vol_list(JCR *jcr); +int add_vol(JCR *jcr, VOL_LIST *vol); +void free_vol_list(JCR *jcr); +void create_vol_list(JCR *jcr); /* From record.c */ const char *FI_to_ascii(int fi); const char *stream_to_ascii(int stream, int fi); -bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); +bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); DEV_RECORD *new_record(); -void free_record(DEV_RECORD *rec); -void empty_record(DEV_RECORD *rec); +void free_record(DEV_RECORD *rec); +void empty_record(DEV_RECORD *rec); /* From read_record.c */ bool read_records(DCR *dcr, @@ -202,12 +202,12 @@ bool read_records(DCR *dcr, bool mount_cb(DCR *dcr)); /* From spool.c */ -bool begin_data_spool (JCR *jcr); -bool discard_data_spool (JCR *jcr); -bool commit_data_spool (JCR *jcr); -bool are_attributes_spooled (JCR *jcr); -bool begin_attribute_spool (JCR *jcr); -bool discard_attribute_spool (JCR *jcr); -bool commit_attribute_spool (JCR *jcr); -bool write_block_to_spool_file (DCR *dcr); -void list_spool_stats (BSOCK *bs); +bool begin_data_spool (JCR *jcr); +bool discard_data_spool (JCR *jcr); +bool commit_data_spool (JCR *jcr); +bool are_attributes_spooled (JCR *jcr); +bool begin_attribute_spool (JCR *jcr); +bool discard_attribute_spool (JCR *jcr); +bool commit_attribute_spool (JCR *jcr); +bool write_block_to_spool_file (DCR *dcr); +void list_spool_stats (BSOCK *bs);