]> git.sur5r.net Git - bacula/bacula/commitdiff
Implement truncate on purge setting
authorMichael Stapelberg <michael@stapelberg.de>
Mon, 21 Sep 2009 23:16:53 +0000 (01:16 +0200)
committerKern Sibbald <kern@sibbald.com>
Sat, 3 Oct 2009 15:34:04 +0000 (17:34 +0200)
bacula/src/dird/ua_purge.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/dircmd.c
bacula/src/stored/status.c
bacula/src/stored/stored_conf.c
bacula/src/stored/stored_conf.h

index e4cb4288560495a42e71f822bcdeab2d8bdbc807..c0276da19d05b8093ab2e96a6e59059f3995bafc 100644 (file)
@@ -552,6 +552,21 @@ bail_out:
    return purged;
 }
 
+static BSOCK *open_sd_bsock(UAContext *ua)
+{
+   STORE *store = ua->jcr->wstore;
+
+   if (!ua->jcr->store_bsock) {
+      ua->send_msg(_("Connecting to Storage daemon %s at %s:%d ...\n"),
+         store->name(), store->address, store->SDport);
+      if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
+         ua->error_msg(_("Failed to connect to Storage daemon.\n"));
+         return NULL;
+      }
+   }
+   return ua->jcr->store_bsock;
+}
+
 /*
  * IF volume status is Append, Full, Used, or Error, mark it Purged
  *   Purged volumes can then be recycled (if enabled).
@@ -567,6 +582,21 @@ bool mark_media_purged(UAContext *ua, MEDIA_DBR *mr)
       if (!db_update_media_record(jcr, ua->db, mr)) {
          return false;
       }
+
+      /* Send the command to truncate the volume after purge. If this feature
+       * is disabled for the specific device, this will be a no-op. */
+      BSOCK *sd;
+      if ((sd=open_sd_bsock(ua)) != NULL) {
+         sd->fsend("truncate_on_purge %s vol=%s", ua->jcr->wstore->dev_name(), mr->VolumeName);
+
+         while (sd->recv() >= 0)
+            ua->send_msg("%s", sd->msg);
+
+         sd->signal(BNET_TERMINATE);
+         sd->close();
+         ua->jcr->store_bsock = NULL;
+      }
+
       pm_strcpy(jcr->VolumeName, mr->VolumeName);
       generate_job_event(jcr, "VolumePurged");
       generate_plugin_event(jcr, bEventVolumePurged);
index 5969b49eef9c7126dedcd6c73ee62e660ea5e328..2e63db01c8f1d6737267632297ddcdc05f441b6c 100644 (file)
@@ -169,6 +169,7 @@ init_dev(JCR *jcr, DEVRES *device)
    dev->max_spool_size = device->max_spool_size;
    dev->drive_index = device->drive_index;
    dev->autoselect = device->autoselect;
+   dev->truncate_on_purge = device->truncate_on_purge;
    dev->dev_type = device->dev_type;
    dev->init_backend();
    if (dev->is_tape()) { /* No parts on tapes */
index f77c18f0d325faee31d562a31a83b438675ca9c4..50753a939ee57f1bf60a90ba726ee61c00166255 100644 (file)
@@ -237,6 +237,7 @@ public:
    int openmode;                      /* parameter passed to open_dev (useful to reopen the device) */
    int dev_type;                      /* device type */
    bool autoselect;                   /* Autoselect in autochanger */
+   bool truncate_on_purge;            /* Truncate this volume when it gets purged? */
    bool initiated;                    /* set when init_dev() called */
    int label_type;                    /* Bacula/ANSI/IBM label types */
    uint32_t drive_index;              /* Autochanger drive index (base 0) */
index b0118027808ab0cfc674060c35d076fc55ad147a..ff2aa951e7a07670d7140e9e777edfa8b027ac82 100644 (file)
@@ -83,6 +83,7 @@ static bool setdebug_cmd(JCR *jcr);
 static bool cancel_cmd(JCR *cjcr);
 static bool mount_cmd(JCR *jcr);
 static bool unmount_cmd(JCR *jcr);
+static bool truncate_on_purge_cmd(JCR *jcr);
 static bool bootstrap_cmd(JCR *jcr);
 static bool changer_cmd(JCR *sjcr);
 static bool do_label(JCR *jcr, int relabel);
@@ -118,6 +119,7 @@ static struct s_cmds cmds[] = {
    {"status",      status_cmd,      1},
    {".status",     qstatus_cmd,     1},
    {"unmount",     unmount_cmd,     0},
+   {"truncate_on_purge",       truncate_on_purge_cmd,  0},
    {"use storage=", use_cmd,        0},
    {"run",         run_cmd,         0},
 // {"query",       query_cmd,       0},
@@ -869,6 +871,53 @@ static bool unmount_cmd(JCR *jcr)
    return true;
 }
 
+/*
+ * The truncate command will recycle a volume. The director can call this
+ * after purging a volume so that disk space will not be wasted. Only useful
+ * for File Storage, of course.
+ *
+ */
+static bool truncate_on_purge_cmd(JCR *jcr)
+{
+   POOL_MEM devname;
+   POOL_MEM volumename;
+   BSOCK *dir = jcr->dir_bsock;
+   DEVICE *dev;
+   DCR *dcr;
+   int drive;
+
+   if (sscanf(dir->msg, "truncate_on_purge %127s vol=%s", devname.c_str(), volumename.c_str()) != 2) {
+      dir->fsend(_("3916 Error scanning truncate_on_purge command\n"));
+      goto done;
+   }
+
+   /* FIXME: autochanger, drive = 0? how can we avoid that? we only work on files */
+   if ((dcr = find_device(jcr, devname, 0)) == NULL) {
+      dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
+      goto done;
+   }
+
+   dev = dcr->dev;
+
+   if (!dev->truncate_on_purge) {
+      dir->fsend(_("3919 Truncate on purge not enabled, skipping\n"));
+      goto done;
+   }
+
+   /* Store the VolumeName for opening and re-labeling the volume */
+   bstrncpy(dcr->VolumeName, volumename.c_str(), sizeof(dcr->VolumeName));
+   bstrncpy(dev->VolHdr.VolumeName, volumename.c_str(), sizeof(dev->VolHdr.VolumeName));
+
+   /* Re-write the label with the recycle flag */
+   if (rewrite_volume_label(dcr, true))
+      dir->fsend(_("3917 Volume recycled\n"));
+   else dir->fsend(_("3918 Recycle failed\n"));
+
+done:
+   dir->signal(BNET_EOD);
+   return true;
+}
+
 /*
  * Release command from Director. This rewinds the device and if
  *   configured does a offline and ensures that Bacula will
index 11939fb247c99b873501a2505ac0436c81283488..16bc52f3854b804c385ab2b069bc9cb490bdff61 100644 (file)
@@ -372,6 +372,9 @@ static void send_device_status(DEVICE *dev, STATUS_PKT *sp)
    len = Mmsg(msg, _("Device parameters:\n"));
    sendit(msg, len, sp);
 
+   len = Mmsg(msg, _("truncate on purge: %d\n"), dev->device->truncate_on_purge);
+   sendit(msg, len, sp);
+
    len = Mmsg(msg, _("Archive name: %s Device name: %s\n"), dev->archive_name(),
       dev->name());
    sendit(msg, len, sp);
index 813a94c15106692923b74f42c5a0c83268b6256f..3ea6361f5484b3c910585582356cb9cc5d395844 100644 (file)
@@ -142,6 +142,7 @@ static RES_ITEM dev_items[] = {
    {"offlineonunmount",      store_bit,  ITEM(res_dev.cap_bits), CAP_OFFLINEUNMOUNT, ITEM_DEFAULT, 0},
    {"blockchecksum",         store_bit,  ITEM(res_dev.cap_bits), CAP_BLOCKCHECKSUM, ITEM_DEFAULT, 1},
    {"autoselect",            store_bool, ITEM(res_dev.autoselect), 1, ITEM_DEFAULT, 1},
+   {"truncateonpurge",       store_bool, ITEM(res_dev.truncate_on_purge), 1, ITEM_DEFAULT, 0},
    {"changerdevice",         store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
    {"changercommand",        store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
    {"alertcommand",          store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
index 7972f80c68f36c19a0f9119d6b3ed1b6f8165c9e..47c7ea6b64faf7c1ff6de0ac9aaa6935ee3c3b2d 100644 (file)
@@ -127,6 +127,7 @@ public:
    uint32_t dev_type;                 /* device type */
    uint32_t label_type;               /* label type */
    bool autoselect;                   /* Automatically select from AutoChanger */
+   bool truncate_on_purge;            /* Truncate this volume when it gets purged? */
    uint32_t drive_index;              /* Autochanger drive index */
    uint32_t cap_bits;                 /* Capabilities of this device */
    utime_t max_changer_wait;          /* Changer timeout */