]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/ua_restore.c
Fix problem in BVFS with concurrent queries
[bacula/bacula] / bacula / src / dird / ua_restore.c
index 1562a0cf8df39192a2eee313cee9675a9044973b..67f4f3fa727e4b8a44bdd394c826df9a5d761feb 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2010 Free Software Foundation Europe e.V.
+   Copyright (C) 2002-2011 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -46,7 +46,6 @@
 extern void print_bsr(UAContext *ua, RBSR *bsr);
 
 
-
 /* Forward referenced functions */
 static int last_full_handler(void *ctx, int num_fields, char **row);
 static int jobid_handler(void *ctx, int num_fields, char **row);
@@ -108,6 +107,12 @@ int restore_cmd(UAContext *ua, const char *cmd)
       rx.where = ua->argv[i];
    }
 
+   i = find_arg_with_value(ua, "replace");
+   if (i >= 0) {
+      rx.replace = ua->argv[i];
+   }
+   
+
    i = find_arg_with_value(ua, "strip_prefix");
    if (i >= 0) {
       strip_prefix = ua->argv[i];
@@ -220,7 +225,7 @@ int restore_cmd(UAContext *ua, const char *cmd)
    if (rx.restore_jobs == 1) {
       job = rx.restore_job;
    } else {
-      job = select_restore_job_resource(ua);
+      job = get_restore_job(ua);
    }
    if (!job) {
       goto bail_out;
@@ -257,6 +262,11 @@ int restore_cmd(UAContext *ua, const char *cmd)
    }
    pm_strcat(ua->cmd, buf);
 
+   if (rx.replace) {
+      Mmsg(buf, " replace=%s", rx.replace);
+      pm_strcat(ua->cmd, buf);
+   }
+
    if (rx.comment) {
       Mmsg(buf, " comment=\"%s\"", rx.comment);
       pm_strcat(ua->cmd, buf);
@@ -284,6 +294,7 @@ int restore_cmd(UAContext *ua, const char *cmd)
    parse_ua_args(ua);
    run_cmd(ua, ua->cmd);
    free_rx(&rx);
+   garbage_collect_memory();       /* release unused memory */
    return 1;
 
 bail_out:
@@ -300,6 +311,7 @@ bail_out:
    }
 
    free_rx(&rx);
+   garbage_collect_memory();       /* release unused memory */
    return 0;
 
 }
@@ -359,7 +371,8 @@ static int get_client_name(UAContext *ua, RESTORE_CTX *rx)
          i = find_arg_with_value(ua, NT_("backupclient"));
       }
       if (i >= 0) {
-         if (!has_value(ua, i)) {
+         if (!is_name_valid(ua->argv[i], &ua->errmsg)) {
+            ua->error_msg("%s argument: %s", ua->argk[i], ua->errmsg);
             return 0;
          }
          bstrncpy(rx->ClientName, ua->argv[i], sizeof(rx->ClientName));
@@ -385,7 +398,8 @@ static int get_restore_client_name(UAContext *ua, RESTORE_CTX &rx)
    /* try command line argument */
    int i = find_arg_with_value(ua, NT_("restoreclient"));
    if (i >= 0) {
-      if (!has_value(ua, i)) {
+      if (!is_name_valid(ua->argv[i], &ua->errmsg)) {
+         ua->error_msg("%s argument: %s", ua->argk[i], ua->errmsg);
          return 0;
       }
       bstrncpy(rx.RestoreClientName, ua->argv[i], sizeof(rx.RestoreClientName));
@@ -458,6 +472,8 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
       "restoreclient", /* 19 */
       "copies",        /* 20 */
       "comment",       /* 21 */
+      "restorejob",    /* 22 */
+      "replace",       /* 23 */
       NULL
    };
 
@@ -599,7 +615,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
          len = strlen(ua->cmd);
          fname = (char *)malloc(len * 2 + 1);
          db_escape_string(ua->jcr, ua->db, fname, ua->cmd, len);
-         Mmsg(rx->query, uar_file[db_type], rx->ClientName, fname);
+         Mmsg(rx->query, uar_file[db_get_type_index(ua->db)], rx->ClientName, fname);
          free(fname);
          gui_save = ua->jcr->gui;
          ua->jcr->gui = true;
@@ -945,7 +961,7 @@ static bool insert_dir_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *di
       ua->error_msg(_("No JobId specified cannot continue.\n"));
       return false;
    } else {
-      Mmsg(rx->query, uar_jobid_fileindex_from_dir[db_type], rx->JobIds, dir, rx->ClientName);
+      Mmsg(rx->query, uar_jobid_fileindex_from_dir[db_get_type_index(ua->db)], rx->JobIds, dir, rx->ClientName);
    }
    rx->found = false;
    /* Find and insert jobid and File Index */
@@ -1066,6 +1082,23 @@ static bool ask_for_fileregex(UAContext *ua, RESTORE_CTX *rx)
    return false;
 }
 
+/* Walk on the delta_list of a TREE_NODE item and insert all parts
+ * TODO: Optimize for bootstrap creation, remove recursion
+ * 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0
+ * should insert as
+ * 0, 1, 2, 3, 4, 5, 6
+ */
+static void add_delta_list_findex(RESTORE_CTX *rx, struct delta_list *lst)
+{
+   if (lst == NULL) {
+      return;
+   }
+   if (lst->next) {
+      add_delta_list_findex(rx, lst->next);
+   }
+   add_findex(rx->bsr, lst->JobId, lst->FileIndex);
+}
+
 static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx)
 {
    TREE_CTX tree;
@@ -1108,6 +1141,7 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx)
 #ifdef new_get_file_list
    if (!db_get_file_list(ua->jcr, ua->db, 
                          rx->JobIds, false /* do not use md5 */, 
+                         true /* get delta */,
                          insert_tree_handler, (void *)&tree))
    {
       ua->error_msg("%s", db_strerror(ua->db));
@@ -1133,6 +1167,13 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx)
       }
    }
 #endif
+   /* 
+    * At this point, the tree is built, so we can garbage collect
+    * any memory released by the SQL engine that RedHat has 
+    * not returned to the OS :-( 
+    */
+    garbage_collect_memory();
+
    /*
     * Look at the first JobId on the list (presumably the oldest) and
     *  if it is marked purged, don't do the manual selection because
@@ -1184,6 +1225,8 @@ static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx)
             Dmsg2(400, "FI=%d node=0x%x\n", node->FileIndex, node);
             if (node->extract || node->extract_dir) {
                Dmsg3(400, "JobId=%lld type=%d FI=%d\n", (uint64_t)node->JobId, node->type, node->FileIndex);
+               /* TODO: optimize bsr insertion when jobid are non sorted */
+               add_delta_list_findex(rx, node->delta_list);
                add_findex(rx->bsr, node->JobId, node->FileIndex);
                if (node->extract && node->type != TN_NEWDIR) {
                   rx->selected_files++;  /* count only saved files */
@@ -1215,10 +1258,10 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat
    /* Create temp tables */
    db_sql_query(ua->db, uar_del_temp, NULL, NULL);
    db_sql_query(ua->db, uar_del_temp1, NULL, NULL);
-   if (!db_sql_query(ua->db, uar_create_temp[db_type], NULL, NULL)) {
+   if (!db_sql_query(ua->db, uar_create_temp[db_get_type_index(ua->db)], NULL, NULL)) {
       ua->error_msg("%s\n", db_strerror(ua->db));
    }
-   if (!db_sql_query(ua->db, uar_create_temp1[db_type], NULL, NULL)) {
+   if (!db_sql_query(ua->db, uar_create_temp1[db_get_type_index(ua->db)], NULL, NULL)) {
       ua->error_msg("%s\n", db_strerror(ua->db));
    }
    /*
@@ -1235,14 +1278,18 @@ static bool select_backups_before_date(UAContext *ua, RESTORE_CTX *rx, char *dat
     */
    memset(&fsr, 0, sizeof(fsr));
    i = find_arg_with_value(ua, "FileSet");
-   if (i >= 0) {
+
+   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));
          i = -1;
       }
+   } else if (i >= 0) {         /* name is invalid */
+      ua->error_msg(_("FileSet argument: %s\n"), ua->errmsg);
    }
+
    if (i < 0) {                       /* fileset not found */
       edit_int64(cr.ClientId, ed1);
       Mmsg(rx->query, uar_sel_fileset, ed1, ed1);