]> git.sur5r.net Git - bacula/bacula/commitdiff
Fix bug #1643 about orphan records with delete volume= command
authorEric Bollengier <eric@eb.homelinux.org>
Wed, 13 Oct 2010 09:20:07 +0000 (11:20 +0200)
committerEric Bollengier <eric@eb.homelinux.org>
Wed, 13 Oct 2010 18:05:50 +0000 (20:05 +0200)
bacula/src/cats/protos.h
bacula/src/cats/sql_delete.c
bacula/src/cats/sql_get.c
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_purge.c

index d40070a802fd503c1f3434597390c994a84ee6f9..4eaf6f3f760a350585480f8a209d74d97e72219c 100644 (file)
@@ -102,6 +102,8 @@ int db_find_next_volume(JCR *jcr, B_DB *mdb, int index, bool InChanger, MEDIA_DB
 bool db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &JobLevel);
 
 /* sql_get.c */
+bool db_get_volume_jobids(JCR *jcr, B_DB *mdb, 
+                         MEDIA_DBR *mr, db_list_ctx *lst);
 bool db_get_base_file_list(JCR *jcr, B_DB *mdb,
                            DB_RESULT_HANDLER *result_handler,void *ctx);
 int db_get_path_record(JCR *jcr, B_DB *mdb);
index f9556a048b695efa02ea5d12b698ea60236b7809..ce949afcb46976a568808bad403effb0c90cf048 100644 (file)
@@ -151,6 +151,10 @@ static int delete_handler(void *ctx, int num_fields, char **row)
  * This routine will purge (delete) all records
  * associated with a particular Volume. It will
  * not delete the media record itself.
+ * TODO: This function is broken and it doesn't purge
+ *       File, BaseFiles, Log, ...
+ *       We call it from relabel and delete volume=, both ensure
+ *       that the volume is properly purged.
  */
 static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr)
 {
index 372fd9e79b57344b0add19ceccc12a8149e8cdef..f5b226d902417c90d53b3ab6e09d237ce64bfaac 100644 (file)
@@ -1295,4 +1295,19 @@ bail_out:
    return ret;
 }
 
+/* Get JobIds associated with a volume */
+bool db_get_volume_jobids(JCR *jcr, B_DB *mdb, 
+                         MEDIA_DBR *mr, db_list_ctx *lst)
+{
+   char ed1[50];
+   bool ret=false;
+
+   db_lock(mdb);
+   Mmsg(mdb->cmd, "SELECT DISTINCT JobId FROM JobMedia WHERE MediaId=%s", 
+        edit_int64(mr->MediaId, ed1));
+   ret = db_sql_query(mdb, mdb->cmd, db_list_handler, lst);
+   db_unlock(mdb);
+   return ret;
+}
+
 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL || HAVE_INGRES || HAVE_DBI */
index 8f99ee8b934b92342e3ef93fb087387f16e0aa6b..1496cccfa085caaf40b9e5575db7371460511d42 100644 (file)
@@ -1529,6 +1529,7 @@ static int delete_volume(UAContext *ua)
 {
    MEDIA_DBR mr;
    char buf[1000];
+   db_list_ctx lst;
 
    if (!select_media_dbr(ua, &mr)) {
       return 1;
@@ -1546,9 +1547,22 @@ static int delete_volume(UAContext *ua)
          return 1;
       }
    }
-   if (ua->pint32_val) {
-      db_delete_media_record(ua->jcr, ua->db, &mr);
+   if (!ua->pint32_val) {
+      return 1;
+   }
+
+   /* If not purged, do it */
+   if (strcmp(mr.VolStatus, "Purged") != 0) {
+      if (!db_get_volume_jobids(ua->jcr, ua->db, &mr, &lst)) {
+         ua->error_msg(_("Can't list jobs on this volume\n"));
+         return 1;
+      }
+      if (lst.count) {
+         purge_jobs_from_catalog(ua, lst.list);
+      }
    }
+
+   db_delete_media_record(ua->jcr, ua->db, &mr);
    return 1;
 }
 
index bd0efcea7d66360fc1542bb85d28ae5eae7c1be1..3e98455e09928d463cd9ea4bf966041c70521273 100644 (file)
@@ -450,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 ||
@@ -468,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;
 }