]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/ua_purge.c
Fix problem in BVFS with concurrent queries
[bacula/bacula] / bacula / src / dird / ua_purge.c
index 33adb4012bec98dbbf8f462e1fe67af7f0c2c3d7..550ab37c383c3e9bf1895a76b0d10c8c9cd6f0d7 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2010 Free Software Foundation Europe e.V.
+   Copyright (C) 2002-2012 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.
@@ -389,7 +389,7 @@ void upgrade_copies(UAContext *ua, char *jobs)
    db_lock(ua->db);
 
    /* Do it in two times for mysql */
-   Mmsg(query, uap_upgrade_copies_oldest_job[db_type], JT_JOB_COPY, jobs, jobs);
+   Mmsg(query, uap_upgrade_copies_oldest_job[db_get_type_index(ua->db)], JT_JOB_COPY, jobs, jobs);
    db_sql_query(ua->db, query.c_str(), NULL, (void *)NULL);
    Dmsg1(050, "Upgrade copies Log sql=%s\n", query.c_str());
 
@@ -427,6 +427,9 @@ void purge_jobs_from_catalog(UAContext *ua, char *jobs)
    db_sql_query(ua->db, query.c_str(), NULL, (void *)NULL);
    Dmsg1(050, "Delete RestoreObject sql=%s\n", query.c_str());
 
+   Mmsg(query, "DELETE FROM PathVisibility WHERE JobId IN (%s)", jobs);
+   db_sql_query(ua->db, query.c_str(), NULL, (void *)NULL);
+   Dmsg1(050, "Delete PathVisibility sql=%s\n", query.c_str());
 
    upgrade_copies(ua, jobs);
 
@@ -447,12 +450,11 @@ void purge_files_from_volume(UAContext *ua, MEDIA_DBR *mr )
 bool purge_jobs_from_volume(UAContext *ua, MEDIA_DBR *mr, bool force)
 {
    POOL_MEM query(PM_MESSAGE);
-   struct del_ctx del;
+   db_list_ctx lst;
+   char *jobids=NULL;
    int i;
    bool purged = false;
    bool stat;
-   JOB_DBR jr;
-   char ed1[50];
 
    stat = strcmp(mr->VolStatus, "Append") == 0 ||
           strcmp(mr->VolStatus, "Full")   == 0 ||
@@ -465,42 +467,34 @@ bool purge_jobs_from_volume(UAContext *ua, MEDIA_DBR *mr, bool force)
       return 0;
    }
 
-   memset(&jr, 0, sizeof(jr));
-   memset(&del, 0, sizeof(del));
-   del.max_ids = 1000;
-   del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids);
-
    /*
     * Check if he wants to purge a single jobid
     */
    i = find_arg_with_value(ua, "jobid");
-   if (i >= 0) {
-      del.num_ids = 1;
-      del.JobId[0] = str_to_int64(ua->argv[i]);
+   if (i >= 0 && is_a_number_list(ua->argv[i])) {
+      jobids = ua->argv[i];
    } else {
       /*
        * Purge ALL JobIds
        */
-      Mmsg(query, "SELECT DISTINCT JobId FROM JobMedia WHERE MediaId=%s", 
-           edit_int64(mr->MediaId, ed1));
-      if (!db_sql_query(ua->db, query.c_str(), file_delete_handler, (void *)&del)) {
+      if (!db_get_volume_jobids(ua->jcr, ua->db, mr, &lst)) {
          ua->error_msg("%s", db_strerror(ua->db));
          Dmsg0(050, "Count failed\n");
          goto bail_out;
       }
+      jobids = lst.list;
    }
 
-   purge_job_list_from_catalog(ua, del);
+   if (*jobids) {
+      purge_jobs_from_catalog(ua, jobids);
+   }
 
-   ua->info_msg(_("%d File%s on Volume \"%s\" purged from catalog.\n"), del.num_del,
-      del.num_del==1?"":"s", mr->VolumeName);
+   ua->info_msg(_("%d File%s on Volume \"%s\" purged from catalog.\n"), 
+                lst.count, lst.count<=1?"":"s", mr->VolumeName);
 
    purged = is_volume_purged(ua, mr, force); 
 
 bail_out:
-   if (del.JobId) {
-      free(del.JobId);
-   }
    return purged;
 }
 
@@ -535,7 +529,7 @@ bool is_volume_purged(UAContext *ua, MEDIA_DBR *mr, bool force)
 
    /* If purged, mark it so */
    cnt.count = 0;
-   Mmsg(query, "SELECT count(*) FROM JobMedia WHERE MediaId=%s", 
+   Mmsg(query, "SELECT 1 FROM JobMedia WHERE MediaId=%s LIMIT 1", 
         edit_int64(mr->MediaId, ed1));
    if (!db_sql_query(ua->db, query.c_str(), del_count_handler, (void *)&cnt)) {
       ua->error_msg("%s", db_strerror(ua->db));
@@ -624,6 +618,7 @@ static void do_truncate_on_purge(UAContext *ua, MEDIA_DBR *mr,
    if (ok) {
       mr->VolBytes = VolBytes;
       mr->VolFiles = 0;
+      set_storageid_in_mr(NULL, mr);
       if (!db_update_media_record(ua->jcr, ua->db, mr)) {
          ua->error_msg(_("Can't update volume size in the catalog\n"));
       }
@@ -651,23 +646,25 @@ static int action_on_purge_cmd(UAContext *ua, const char *cmd)
    BSOCK *sd = NULL;
    
    memset(&pr, 0, sizeof(pr));
-   memset(&mr, 0, sizeof(mr));
 
    /* Look at arguments */
    for (int i=1; i<ua->argc; i++) {
       if (strcasecmp(ua->argk[i], NT_("allpools")) == 0) {
          allpools = true;
             
-      } else if (strcasecmp(ua->argk[i], NT_("volume")) == 0 && ua->argv[i]) {
+      } else if (strcasecmp(ua->argk[i], NT_("volume")) == 0 
+                 && is_name_valid(ua->argv[i], NULL)) {
          bstrncpy(mr.VolumeName, ua->argv[i], sizeof(mr.VolumeName));
 
-      } else if (strcasecmp(ua->argk[i], NT_("devicetype")) == 0 && ua->argv[i]) {
+      } else if (strcasecmp(ua->argk[i], NT_("devicetype")) == 0 
+                 && ua->argv[i]) {
          bstrncpy(mr.MediaType, ua->argv[i], sizeof(mr.MediaType));
          
       } else if (strcasecmp(ua->argk[i], NT_("drive")) == 0 && ua->argv[i]) {
          drive = atoi(ua->argv[i]);
 
-      } else if (strcasecmp(ua->argk[i], NT_("action")) == 0 && ua->argv[i]) {
+      } else if (strcasecmp(ua->argk[i], NT_("action")) == 0 
+                 && is_name_valid(ua->argv[i], NULL)) {
          action=ua->argv[i];
       }
    }
@@ -677,7 +674,6 @@ static int action_on_purge_cmd(UAContext *ua, const char *cmd)
    if (!store) {
       goto bail_out;
    }
-   mr.StorageId = store->StorageId;
 
    if (!open_db(ua)) {
       Dmsg0(100, "Can't open db\n");
@@ -706,6 +702,7 @@ static int action_on_purge_cmd(UAContext *ua, const char *cmd)
    mr.Recycle = 1;
    mr.Enabled = 1;
    mr.VolBytes = 10000;
+   set_storageid_in_mr(store, &mr);
    bstrncpy(mr.VolStatus, "Purged", sizeof(mr.VolStatus));
    if (!db_get_media_ids(ua->jcr, ua->db, &mr, &nb, &results)) {
       Dmsg0(100, "No results from db_get_media_ids\n");
@@ -726,7 +723,7 @@ static int action_on_purge_cmd(UAContext *ua, const char *cmd)
     * Loop over the candidate Volumes and actually truncate them
     */
    for (int i=0; i < nb; i++) {
-      memset(&mr, 0, sizeof(mr));
+      mr.clear();
       mr.MediaId = results[i];
       if (db_get_media_record(ua->jcr, ua->db, &mr)) {         
          /* TODO: ask for drive and change Pool */
@@ -765,12 +762,13 @@ bool mark_media_purged(UAContext *ua, MEDIA_DBR *mr)
        strcmp(mr->VolStatus, "Used")   == 0 ||
        strcmp(mr->VolStatus, "Error")  == 0) {
       bstrncpy(mr->VolStatus, "Purged", sizeof(mr->VolStatus));
+      set_storageid_in_mr(NULL, mr);
       if (!db_update_media_record(jcr, ua->db, mr)) {
          return false;
       }
       pm_strcpy(jcr->VolumeName, mr->VolumeName);
       generate_job_event(jcr, "VolumePurged");
-      generate_plugin_event(jcr, bEventVolumePurged);
+      generate_plugin_event(jcr, bDirEventVolumePurged);
       /*
        * If the RecyclePool is defined, move the volume there
        */