]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/ua_restore.c
Add heap stats to Dir and SD -- eliminate #ifdefs
[bacula/bacula] / bacula / src / dird / ua_restore.c
index 6027674d0fb613b19456e492e660820f9607b50f..8d5347dbc36071c066bb9d7c8c0264ae10cf7fd7 100644 (file)
@@ -38,7 +38,7 @@
 
 
 /* Imported functions */
-extern int run_cmd(UAContext *ua, char *cmd);
+extern int run_cmd(UAContext *ua, const char *cmd);
 extern void print_bsr(UAContext *ua, RBSR *bsr);
 
 /* Imported variables */
@@ -48,6 +48,7 @@ extern char *uar_create_temp1,         *uar_last_full,   *uar_full;
 extern char *uar_inc,           *uar_list_temp,   *uar_sel_jobid_temp;
 extern char *uar_sel_all_temp1,  *uar_sel_fileset, *uar_mediatype;
 extern char *uar_jobid_fileindex, *uar_dif,       *uar_sel_all_temp;
+extern char *uar_count_files;
 
 
 struct NAME_LIST {
@@ -74,12 +75,13 @@ struct RESTORE_CTX {
    uint32_t selected_files;
    char *where;
    RBSR *bsr;
-   POOLMEM *fname;
-   POOLMEM *path;
+   POOLMEM *fname;                   /* filename only */
+   POOLMEM *path;                    /* path only */
    POOLMEM *query;
-   int fnl;
-   int pnl;
+   int fnl;                          /* filename length */
+   int pnl;                          /* path length */
    bool found;
+   bool all;                         /* mark all as default */
    NAME_LIST name_list;
 };
 
@@ -107,12 +109,13 @@ static int insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *fi
 static void insert_one_file(UAContext *ua, RESTORE_CTX *rx, char *date);
 static int get_client_name(UAContext *ua, RESTORE_CTX *rx);
 static int get_date(UAContext *ua, char *date, int date_len);
+static int count_handler(void *ctx, int num_fields, char **row);
 
 /*
  *   Restore files
  *
  */
-int restore_cmd(UAContext *ua, char *cmd)
+int restore_cmd(UAContext *ua, const char *cmd)
 {
    RESTORE_CTX rx;                   /* restore context */
    JOB *job;
@@ -176,7 +179,9 @@ int restore_cmd(UAContext *ua, char *cmd)
          bsendmsg(ua, _("Unable to construct a valid BSR. Cannot continue.\n"));
         goto bail_out;
       }
-      write_bsr_file(ua, rx.bsr);
+      if (!write_bsr_file(ua, rx.bsr)) {
+        goto bail_out;
+      }
       bsendmsg(ua, _("\n%u file%s selected to be restored.\n\n"), rx.selected_files,
          rx.selected_files==1?"":"s");
    } else {
@@ -208,9 +213,10 @@ int restore_cmd(UAContext *ua, char *cmd)
          working_directory, rx.where, rx.selected_files);
    } else {
       Mmsg(&ua->cmd, 
-          "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s/restore.bsr\"",
+          "run job=\"%s\" client=\"%s\" storage=\"%s\" bootstrap=\"%s/restore.bsr\""
+          " files=%d",
           job->hdr.name, rx.ClientName, rx.store?rx.store->hdr.name:"",
-         working_directory);
+         working_directory, rx.selected_files);
    }
    if (find_arg(ua, _("yes")) > 0) {
       pm_strcat(&ua->cmd, " yes");    /* pass it on to the run command */
@@ -286,7 +292,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
    JOB_DBR jr;
    bool done = false;
    int i, j;
-   char *list[] = { 
+   const char *list[] = { 
       "List last 20 Jobs run",
       "List Jobs where a given File is saved",
       "Enter list of comma separated JobIds to select",
@@ -298,18 +304,20 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
       "Cancel",
       NULL };
 
-   char *kw[] = {
+   const char *kw[] = {
       "jobid",     /* 0 */
       "current",   /* 1 */
       "before",    /* 2 */
       "file",      /* 3 */
       "select",    /* 4 */
       "pool",      /* 5 */
-      "client",    /* 6 */
-      "storage",   /* 7 */
-      "where",     /* 8 */
-      "all",       /* 9 */
-      "yes",       /* 10 */
+      "all",       /* 6 */
+      "client",    /* 7 */
+      "storage",   /* 8 */
+      "fileset",   /* 9 */
+      "where",     /* 10 */
+      "yes",       /* 11 */
+      "done",      /* 12 */
       NULL
    };
 
@@ -384,8 +392,11 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
            return 0;
         }
         break;
+      case 6:                        /* all specified */
+        rx->all = true;
+        break;
       /*     
-       * All keywords 6 or greater are ignored or handled by a select prompt
+       * All keywords 7 or greater are ignored or handled by a select prompt
        */
       default:
         break;
@@ -692,7 +703,6 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx)
    TREE_CTX tree;
    JobId_t JobId, last_JobId;
    char *p;
-   char *nofname = "";
    bool OK = true;
 
    memset(&tree, 0, sizeof(TREE_CTX));
@@ -700,14 +710,28 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx)
     * Build the directory tree containing JobIds user selected
     */
    tree.root = new_tree(rx->TotalFiles);
-   tree.root->fname = nofname;
    tree.ua = ua;
+   tree.all = rx->all;
    last_JobId = 0;
    /*
     * For display purposes, the same JobId, with different volumes may
     * appear more than once, however, we only insert it once.
     */
    int items = 0;
+   p = rx->JobIds;
+   tree.FileEstimate = 0;
+   if (get_next_jobid_from_list(&p, &JobId) > 0) {
+      /* Use first JobId as estimate of the number of files to restore */
+      Mmsg(&rx->query, uar_count_files, JobId);
+      if (!db_sql_query(ua->db, rx->query, count_handler, (void *)rx)) {
+         bsendmsg(ua, "%s\n", db_strerror(ua->db));
+      }
+      if (rx->found) {
+        /* Add about 25% more than this job for over estimate */
+        tree.FileEstimate = rx->JobId + (rx->JobId >> 2);
+        tree.DeltaCount = rx->JobId/50; /* print 50 ticks */
+      }
+   }
    for (p=rx->JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) {
 
       if (JobId == last_JobId) {            
@@ -731,13 +755,15 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx)
          bsendmsg(ua, "%s", db_strerror(ua->db));
       }
    }
-   bsendmsg(ua, "%d Job%s inserted into the tree and marked for extraction.\n", 
-      items, items==1?"":"s");
+   char ec1[50];
+   bsendmsg(ua, "\n%d Job%s, %s files inserted into the tree%s.\n", 
+      items, items==1?"":"s", edit_uint64_with_commas(tree.FileCount, ec1),
+      tree.all?" and marked for extraction":"");
 
    /* Check MediaType and select storage that corresponds */
    get_storage_from_mediatype(ua, &rx->name_list, rx);
 
-   if (find_arg(ua, _("all")) < 0) {
+   if (find_arg(ua, _("done")) < 0) {
       /* Let the user interact in selecting which files to restore */
       OK = user_select_files_from_tree(&tree);
    }
@@ -752,7 +778,9 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx)
         if (node->extract || node->extract_dir) {
             Dmsg2(400, "type=%d FI=%d\n", node->type, node->FileIndex);
            add_findex(rx->bsr, node->JobId, node->FileIndex);
-           rx->selected_files++;
+           if (node->extract) {
+              rx->selected_files++;  /* count only saved files */
+           }
         }
       }
    }
@@ -934,6 +962,14 @@ static int get_next_jobid_from_list(char **p, uint32_t *JobId)
    return 1;
 }
 
+static int count_handler(void *ctx, int num_fields, char **row)
+{
+   RESTORE_CTX *rx = (RESTORE_CTX *)ctx;
+   rx->JobId = atoi(row[0]);
+   rx->found = true;
+   return 0;
+}
+
 /*
  * Callback handler to get JobId and FileIndex for files
  */
@@ -1074,14 +1110,33 @@ static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, REST
    LockRes();
    foreach_res(store, R_STORAGE) {
       if (strcmp(name_list->name[0], store->media_type) == 0) {
-        rx->store = store;
-        UnlockRes();
-        return;
+        if (acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
+           rx->store = store;
+        }
+        break;
       }
    }
    UnlockRes();
 
-   /* Try asking user */
+   if (rx->store) {
+      /* Check if an explicit storage resource is given */
+      store = NULL;
+      int i = find_arg_with_value(ua, "storage");        
+      if (i > 0) {
+        store = (STORE *)GetResWithName(R_STORAGE, ua->argv[i]);
+        if (store && !acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
+           store = NULL;
+        }
+      }
+      if (store && (store != rx->store)) {
+         bsendmsg(ua, _("Warning default storage overridden by %s on command line.\n"),
+           store->hdr.name);
+        rx->store = store;
+      }
+      return;
+   }
+
+   /* Take command line arg, or ask user if none */
    rx->store = get_storage_resource(ua, false /* don't use default */);
 
    if (!rx->store) {