From d3e8c0b903f2b3d49c5b832f359ebdfb96bd80aa Mon Sep 17 00:00:00 2001 From: Marco van Wieringen Date: Tue, 14 Jun 2016 13:44:20 +0200 Subject: [PATCH] dird: Allow to restore from copies. Until now you can specify the keyword copies when doing a restore but it will only show the copies but not actually use them for restore. This is somewhat counter intuitive so this patch adds the code that asks if you really want to use the copies for the restore. If you specify the yes keyword you can skip this question. --- src/cats/sql_cmds.c | 27 ++++++++++++++-------- src/cats/sql_cmds.h | 3 ++- src/dird/ua_cmds.c | 11 ++++----- src/dird/ua_label.c | 3 +-- src/dird/ua_prune.c | 6 ++--- src/dird/ua_restore.c | 53 ++++++++++++++++++++++++++++++++----------- src/dird/ua_run.c | 5 ++-- src/dird/ua_select.c | 6 ++--- src/dird/ua_update.c | 7 +++--- 9 files changed, 76 insertions(+), 45 deletions(-) diff --git a/src/cats/sql_cmds.c b/src/cats/sql_cmds.c index 33111c53bf1..339b3517cb1 100644 --- a/src/cats/sql_cmds.c +++ b/src/cats/sql_cmds.c @@ -234,8 +234,8 @@ const char *uar_full = "FROM temp1,Job,JobMedia,Media " "WHERE temp1.JobId=Job.JobId " "AND Level='F' AND JobStatus IN ('T','W') AND Type='B' " - "AND Media.Enabled=1 " "AND JobMedia.JobId=Job.JobId " + "AND Media.Enabled=1 " "AND JobMedia.MediaId=Media.MediaId"; const char *uar_dif = @@ -263,20 +263,14 @@ const char *uar_inc = "FROM Job,JobMedia,Media,FileSet " "WHERE Job.JobTDate>%s AND Job.StartTime<'%s' " "AND Job.ClientId=%s " - "AND Media.Enabled=1 " "AND JobMedia.JobId=Job.JobId " + "AND Media.Enabled=1 " "AND JobMedia.MediaId=Media.MediaId " "AND Job.Level='I' AND JobStatus IN ('T','W') AND Type='B' " "AND Job.FileSetId=FileSet.FileSetId " "AND FileSet.FileSet='%s' " "%s"; -const char *uar_list_temp = - "SELECT DISTINCT JobId,Level,JobFiles,JobBytes,StartTime,VolumeName" - " FROM temp" - " ORDER BY StartTime ASC"; - - const char *uar_sel_jobid_temp = "SELECT DISTINCT JobId,StartTime FROM temp ORDER BY StartTime ASC"; @@ -284,7 +278,22 @@ const char *uar_sel_all_temp1 = "SELECT * FROM temp1"; const char *uar_sel_all_temp = "SELECT * FROM temp"; - +const char *uar_sel_jobid_copies = + "SELECT DISTINCT JobId,StartTime " + "FROM Job " + "WHERE Type = 'C' " + "AND (PriorJobId IN (%s)) " + "ORDER BY StartTime ASC"; + +const char *uar_list_jobs_by_idlist = + "SELECT DISTINCT Job.JobId,Job.Level,Job.JobFiles,Job.JobBytes," + "Job.StartTime,Media.VolumeName " + "FROM Job,JobMedia,Media " + "WHERE Job.JobId IN (%s) " + "AND JobMedia.JobId=Job.JobId " + "AND Media.Enabled=1 " + "AND JobMedia.MediaId=Media.MediaId " + "ORDER BY StartTime ASC"; /* Select FileSet names for this Client */ const char *uar_sel_fileset = diff --git a/src/cats/sql_cmds.h b/src/cats/sql_cmds.h index 622487805da..6ff92459c77 100644 --- a/src/cats/sql_cmds.h +++ b/src/cats/sql_cmds.h @@ -46,7 +46,7 @@ extern const char CATS_IMP_EXP *uar_last_full; extern const char CATS_IMP_EXP *uar_last_full_no_pool; extern const char CATS_IMP_EXP *uar_full; extern const char CATS_IMP_EXP *uar_inc; -extern const char CATS_IMP_EXP *uar_list_temp; +extern const char CATS_IMP_EXP *uar_list_jobs_by_idlist; extern const char CATS_IMP_EXP *uar_sel_all_temp1; extern const char CATS_IMP_EXP *uar_sel_fileset; extern const char CATS_IMP_EXP *uar_sel_filesetid; @@ -58,6 +58,7 @@ extern const char CATS_IMP_EXP *uar_count_files; extern const char CATS_IMP_EXP *uar_jobids_fileindex; extern const char CATS_IMP_EXP *uar_jobid_fileindex_from_table; extern const char CATS_IMP_EXP *uar_sel_jobid_temp; +extern const char CATS_IMP_EXP *uar_sel_jobid_copies; extern const char CATS_IMP_EXP *select_recent_version[]; extern const char CATS_IMP_EXP *select_recent_version_with_basejob[]; diff --git a/src/dird/ua_cmds.c b/src/dird/ua_cmds.c index de2f7707f20..370aecc7a9b 100644 --- a/src/dird/ua_cmds.c +++ b/src/dird/ua_cmds.c @@ -2035,9 +2035,8 @@ static bool delete_job_id_range(UAContext *ua, char *tok) */ if ((j2 - j1) > 25) { bsnprintf(buf, sizeof(buf), - _("Are you sure you want to delete %d JobIds ? (yes/no): "), - j2 - j1); - if (!get_yesno(ua, buf)) { + _("Are you sure you want to delete %d JobIds ? (yes/no): "), j2 - j1); + if (!get_yesno(ua, buf) || !ua->pint32_val) { return true; } } @@ -2045,8 +2044,7 @@ static bool delete_job_id_range(UAContext *ua, char *tok) do_job_delete(ua, j); } } else { - ua->warning_msg(_("Illegal JobId range %s - %s should define increasing JobIds, ignored\n"), - tok, tok2); + ua->warning_msg(_("Illegal JobId range %s - %s should define increasing JobIds, ignored\n"), tok, tok2); } } else { ua->warning_msg(_("Illegal JobId range %s - %s, ignored\n"), tok, tok2); @@ -2087,8 +2085,7 @@ static bool delete_volume(UAContext *ua) if (find_arg(ua, "yes") >= 0) { ua->pint32_val = 1; /* Have "yes" on command line already" */ } else { - bsnprintf(buf, sizeof(buf), _("Are you sure you want to delete Volume \"%s\"? (yes/no): "), - mr.VolumeName); + bsnprintf(buf, sizeof(buf), _("Are you sure you want to delete Volume \"%s\"? (yes/no): "), mr.VolumeName); if (!get_yesno(ua, buf)) { return true; } diff --git a/src/dird/ua_label.c b/src/dird/ua_label.c index 1519cc53267..6b52dbc3927 100644 --- a/src/dird/ua_label.c +++ b/src/dird/ua_label.c @@ -397,8 +397,7 @@ static void label_from_barcodes(UAContext *ua, int drive, } if (!yes && - ( !get_yesno(ua, _("Do you want to label these Volumes? (yes|no): ")) || - (ua->pint32_val == 0))) { + (!get_yesno(ua, _("Do you want to label these Volumes? (yes|no): ")) || !ua->pint32_val)) { goto bail_out; } diff --git a/src/dird/ua_prune.c b/src/dird/ua_prune.c index a81fac5a9b4..520a8606e2f 100644 --- a/src/dird/ua_prune.c +++ b/src/dird/ua_prune.c @@ -253,8 +253,7 @@ static bool prune_directory(UAContext *ua, CLIENTRES *client) */ if (!client) { if (!get_yesno(ua, _("No client restriction given really remove " - "directory for all clients (yes/no): ")) || - ua->pint32_val == 0) { + "directory for all clients (yes/no): ")) || !ua->pint32_val) { if (!(client = get_client_resource(ua))) { return false; } @@ -338,8 +337,7 @@ static bool prune_directory(UAContext *ua, CLIENTRES *client) * them anymore. */ if (!client) { - if (!get_yesno(ua, _("Cleanup orphaned path records (yes/no):")) || - ua->pint32_val == 0) { + if (!get_yesno(ua, _("Cleanup orphaned path records (yes/no):")) || !ua->pint32_val) { retval = true; goto bail_out; } diff --git a/src/dird/ua_restore.c b/src/dird/ua_restore.c index a579c0c195c..b1451496496 100644 --- a/src/dird/ua_restore.c +++ b/src/dird/ua_restore.c @@ -1109,8 +1109,10 @@ static bool ask_for_fileregex(UAContext *ua, RESTORE_CTX *rx) "so file selection is not possible.\n" "Most likely your retention policy pruned the files.\n")); if (get_yesno(ua, _("\nDo you want to restore all the files? (yes|no): "))) { - if (ua->pint32_val == 1) + if (ua->pint32_val) { return true; + } + while (get_cmd(ua, _("\nRegexp matching files to restore? (empty to abort): "))) { if (ua->cmd[0] == '\0') { break; @@ -1135,6 +1137,7 @@ static bool ask_for_fileregex(UAContext *ua, RESTORE_CTX *rx) } } } + return false; } @@ -1303,17 +1306,20 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx) */ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *date) { - bool ok = false; - FILESET_DBR fsr; + int i; CLIENT_DBR cr; - char fileset_name[MAX_NAME_LENGTH]; + FILESET_DBR fsr; + bool ok = false; char ed1[50], ed2[50]; char pool_select[MAX_NAME_LENGTH]; - int i; + char fileset_name[MAX_NAME_LENGTH]; - /* Create temp tables */ + /* + * Create temp tables + */ db_sql_query(ua->db, uar_del_temp); db_sql_query(ua->db, uar_del_temp1); + if (!db_sql_query(ua->db, uar_create_temp[db_get_type_index(ua->db)])) { ua->error_msg("%s\n", db_strerror(ua->db)); } @@ -1338,8 +1344,7 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat if (i >= 0 && is_name_valid(ua->argv[i], &ua->errmsg)) { bstrncpy(fsr.FileSet, ua->argv[i], sizeof(fsr.FileSet)); if (!db_get_fileset_record(ua->jcr, ua->db, &fsr)) { - ua->error_msg(_("Error getting FileSet \"%s\": ERR=%s\n"), fsr.FileSet, - db_strerror(ua->db)); + ua->error_msg(_("Error getting FileSet \"%s\": ERR=%s\n"), fsr.FileSet, db_strerror(ua->db)); i = -1; } } else if (i >= 0) { /* name is invalid */ @@ -1363,7 +1368,7 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat if (!db_get_fileset_record(ua->jcr, ua->db, &fsr)) { ua->warning_msg(_("Error getting FileSet record: %s\n"), db_strerror(ua->db)); ua->send_msg(_("This probably means you modified the FileSet.\n" - "Continuing anyway.\n")); + "Continuing anyway.\n")); } } @@ -1373,11 +1378,11 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat pool_select[0] = 0; if (rx->pool) { POOL_DBR pr; + memset(&pr, 0, sizeof(pr)); bstrncpy(pr.Name, rx->pool->name(), sizeof(pr.Name)); if (db_get_pool_record(ua->jcr, ua->db, &pr)) { - bsnprintf(pool_select, sizeof(pool_select), "AND Media.PoolId=%s ", - edit_int64(pr.PoolId, ed1)); + bsnprintf(pool_select, sizeof(pool_select), "AND Media.PoolId=%s ", edit_int64(pr.PoolId, ed1)); } else { ua->warning_msg(_("Pool \"%s\" not found, using any pool.\n"), pr.Name); } @@ -1456,7 +1461,6 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat * Get the JobIds from that list */ rx->last_jobid[0] = rx->JobIds[0] = 0; - if (!db_sql_query(ua->db, uar_sel_jobid_temp, jobid_handler, (void *)rx)) { ua->warning_msg("%s\n", db_strerror(ua->db)); } @@ -1467,12 +1471,34 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat * Display a list of all copies */ db_list_copies_records(ua->jcr, ua->db, "", rx->JobIds, ua->send, HORZ_LIST); + + if (find_arg(ua, NT_("yes")) > 0) { + ua->pint32_val == 1; + } else { + get_yesno(ua, _("\nDo you want to restore from these copies? (yes|no): ")); + } + + if (ua->pint32_val) { + POOL_MEM JobIds(PM_FNAME); + + /* + * Change the list of jobs needed to do the restore to the copies of the Job. + */ + pm_strcpy(JobIds, rx->JobIds); + rx->last_jobid[0] = rx->JobIds[0] = 0; + Mmsg(rx->query, uar_sel_jobid_copies, JobIds.c_str()); + if (!db_sql_query(ua->db, rx->query, jobid_handler, (void *)rx)) { + ua->warning_msg("%s\n", db_strerror(ua->db)); + } + } } /* * Display a list of Jobs selected for this restore */ - db_list_sql_query(ua->jcr, ua->db, uar_list_temp, ua->send, HORZ_LIST, true); + Mmsg(rx->query, uar_list_jobs_by_idlist, rx->JobIds); + db_list_sql_query(ua->jcr, ua->db, rx->query, ua->send, HORZ_LIST, true); + ok = true; } else { ua->warning_msg(_("No jobs found.\n")); @@ -1481,6 +1507,7 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat bail_out: db_sql_query(ua->db, uar_del_temp); db_sql_query(ua->db, uar_del_temp1); + return ok; } diff --git a/src/dird/ua_run.c b/src/dird/ua_run.c index 45de26ba23c..7c0badf7832 100644 --- a/src/dird/ua_run.c +++ b/src/dird/ua_run.c @@ -309,7 +309,8 @@ bool rerun_cmd(UAContext *ua, const char *cmd) } ua->send_msg("\n"); - if (!yes && (!get_yesno(ua, _("rerun these jobids? (yes/no): ")) || ua->pint32_val == 0 )) { + if (!yes && + (!get_yesno(ua, _("rerun these jobids? (yes/no): ")) || !ua->pint32_val)) { goto bail_out; } /* @@ -672,7 +673,7 @@ int modify_job_parameters(UAContext *ua, JCR *jcr, RUN_CTX &rc) case 7: /* Priority */ if (get_pint(ua, _("Enter new Priority: "))) { - if (ua->pint32_val == 0) { + if (!ua->pint32_val) { ua->send_msg(_("Priority must be a positive integer.\n")); } else { jcr->JobPriority = ua->pint32_val; diff --git a/src/dird/ua_select.c b/src/dird/ua_select.c index 4a15c82e427..adeea7365c4 100644 --- a/src/dird/ua_select.c +++ b/src/dird/ua_select.c @@ -1535,7 +1535,7 @@ alist *select_jobs(UAContext *ua, const char *reason) * Only ask for confirmation when not in batch mode and there is no yes on the cmdline. */ if (!ua->batch && find_arg(ua, NT_("yes")) == -1) { - if (!get_yesno(ua, _("Confirm cancel (yes/no): ")) || ua->pint32_val == 0) { + if (!get_yesno(ua, _("Confirm cancel (yes/no): ")) || !ua->pint32_val) { goto bail_out; } } @@ -1570,12 +1570,12 @@ alist *select_jobs(UAContext *ua, const char *reason) char nbuf[1000]; bsnprintf(nbuf, sizeof(nbuf), _("Cancel: %s\n\n%s"), buf, _("Confirm cancel?")); - if (!get_yesno(ua, nbuf) || ua->pint32_val == 0) { + if (!get_yesno(ua, nbuf) || !ua->pint32_val) { goto bail_out; } } else { if (njobs == 1) { - if (!get_yesno(ua, _("Confirm cancel (yes/no): ")) || ua->pint32_val == 0) { + if (!get_yesno(ua, _("Confirm cancel (yes/no): ")) || !ua->pint32_val) { goto bail_out; } } diff --git a/src/dird/ua_update.c b/src/dird/ua_update.c index 0faa7dd3762..9515e3f76b6 100644 --- a/src/dird/ua_update.c +++ b/src/dird/ua_update.c @@ -713,7 +713,7 @@ static bool update_volume(UAContext *ua) case 6: /* Recycle */ ua->info_msg(_("Current recycle flag is: %s\n"), - mr.Recycle==1?_("yes"):_("no")); + (mr.Recycle == 1) ? _("yes") : _("no")); if (!get_yesno(ua, _("Enter new Recycle status: "))) { return false; } @@ -730,8 +730,7 @@ static bool update_volume(UAContext *ua) case 8: /* InChanger */ ua->info_msg(_("Current InChanger flag is: %d\n"), mr.InChanger); - bsnprintf(buf, sizeof(buf), _("Set InChanger flag for Volume \"%s\": yes/no: "), - mr.VolumeName); + bsnprintf(buf, sizeof(buf), _("Set InChanger flag for Volume \"%s\": yes/no: "), mr.VolumeName); if (!get_yesno(ua, buf)) { return false; } @@ -760,7 +759,7 @@ static bool update_volume(UAContext *ua) VolFiles = ua->pint32_val; if (VolFiles != (int)(mr.VolFiles + 1)) { ua->warning_msg(_("Normally, you should only increase Volume Files by one!\n")); - if (!get_yesno(ua, _("Increase Volume Files? (yes/no): ")) || ua->pint32_val == 0) { + if (!get_yesno(ua, _("Increase Volume Files? (yes/no): ")) || !ua->pint32_val) { break; } }