]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/dircmd.c
11Apr07
[bacula/bacula] / bacula / src / stored / dircmd.c
index d2d871958ebadaa36b591240dcfb648446b5f923..77ff63e0587ee8166e08ee151e29d12941013ffa 100644 (file)
@@ -1,3 +1,30 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2001-2007 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.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation plus additions
+   that are listed in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
 /*
  *  This file handles accepting Director Commands
  *
@@ -7,7 +34,7 @@
  *    in job.c.
  *
  *    N.B. in this file, in general we must use P(dev->mutex) rather
- *      than lock_device(dev) so that we can examine the blocked
+ *      than dev->r_lock() so that we can examine the blocked
  *      state rather than blocking ourselves because a Job
  *      thread has the device blocked. In some "safe" cases,
  *      we can do things to a blocked device. CAREFUL!!!!
  *   Version $Id$
  *
  */
-/*
-   Copyright (C) 2001-2006 Kern Sibbald
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   version 2 as amended with additional clauses defined in the
-   file LICENSE in the main source directory.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
-   the file LICENSE for additional details.
-
- */
 
 #include "bacula.h"
 #include "stored.h"
@@ -49,7 +62,7 @@ extern bool init_done;
 /* Static variables */
 static char derrmsg[]     = "3900 Invalid command\n";
 static char OKsetdebug[]  = "3000 OK setdebug=%d\n";
-static char illegal_cmd[] = "3997 Illegal command for a Director with Monitor directive enabled\n";
+static char invalid_cmd[] = "3997 Invalid command for a Director with Monitor directive enabled.\n";
 
 /* Imported functions */
 extern void terminate_child();
@@ -62,6 +75,7 @@ extern bool qstatus_cmd(JCR *jcr);
 
 /* Forward referenced functions */
 static bool label_cmd(JCR *jcr);
+static bool die_cmd(JCR *jcr);
 static bool relabel_cmd(JCR *jcr);
 static bool readlabel_cmd(JCR *jcr);
 static bool release_cmd(JCR *jcr);
@@ -94,6 +108,7 @@ static struct s_cmds cmds[] = {
    {"autochanger", changer_cmd,     0},
    {"bootstrap",   bootstrap_cmd,   0},
    {"cancel",      cancel_cmd,      0},
+   {".die",        die_cmd,         0},
    {"label",       label_cmd,       0},     /* label a tape */
    {"mount",       mount_cmd,       0},
    {"readlabel",   readlabel_cmd,   0},
@@ -135,7 +150,7 @@ void *handle_connection_request(void *arg)
    int bnet_stat = 0;
    char name[MAX_NAME_LENGTH];
 
-   if (bnet_recv(bs) <= 0) {
+   if (bs->recv() <= 0) {
       Emsg0(M_ERROR, 0, _("Connection request failed.\n"));
       bnet_close(bs);
       return NULL;
@@ -155,6 +170,7 @@ void *handle_connection_request(void *arg)
     */
    Dmsg1(110, "Conn: %s", bs->msg);
    if (sscanf(bs->msg, "Hello Start Job %127s", name) == 1) {
+      Dmsg0(110, "Got a FD connection\n");
       handle_filed_connection(bs, name);
       return NULL;
    }
@@ -162,10 +178,10 @@ void *handle_connection_request(void *arg)
    /* 
     * This is a connection from the Director, so setup a JCR 
     */
-   Dmsg0(110, "Start Dir Job\n");
+   Dmsg0(110, "Got a DIR connection\n");
    jcr = new_jcr(sizeof(JCR), stored_free_jcr); /* create Job Control Record */
    jcr->dir_bsock = bs;               /* save Director bsock */
-   jcr->dir_bsock->jcr = jcr;
+   jcr->dir_bsock->set_jcr(jcr);
    jcr->dcrs = New(alist(10, not_owned_by_alist));
    /* Initialize FD start condition variable */
    int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
@@ -187,7 +203,7 @@ void *handle_connection_request(void *arg)
 
    for (quit=false; !quit;) {
       /* Read command */
-      if ((bnet_stat = bnet_recv(bs)) <= 0) {
+      if ((bnet_stat = bs->recv()) <= 0) {
          break;               /* connection terminated */
       }
       Dmsg1(199, "<dird: %s\n", bs->msg);
@@ -199,9 +215,9 @@ void *handle_connection_request(void *arg)
       for (i=0; cmds[i].cmd; i++) {
         if (strncmp(cmds[i].cmd, bs->msg, strlen(cmds[i].cmd)) == 0) {
            if ((!cmds[i].monitoraccess) && (jcr->director->monitor)) {
-              Dmsg1(100, "Command %s illegal.\n", cmds[i].cmd);
-              bnet_fsend(bs, illegal_cmd);
-              bnet_sig(bs, BNET_EOD);
+              Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd);
+              bnet_fsend(bs, invalid_cmd);
+              bs->signal(BNET_EOD);
               break;
            }
            Dmsg1(200, "Do command: %s\n", cmds[i].cmd);
@@ -226,6 +242,24 @@ bail_out:
    return NULL;
 }
 
+
+/*
+ * Force SD to die, and hopefully dump itself.  Turned on only
+ *  in development version.
+ */
+static bool die_cmd(JCR *jcr)
+{
+#ifdef DEVELOPER
+   JCR *djcr = NULL;
+   int a;
+   Pmsg0(000, "I have been requested to die ...");
+   a = djcr->JobId;   /* ref NULL pointer */
+#endif
+   return 0;
+}
+
+     
+
 /*
  * Set debug level as requested by the Director
  *
@@ -279,6 +313,7 @@ static bool cancel_cmd(JCR *cjcr)
             pthread_cond_broadcast(&jcr->read_dcr->dev->wait_next_vol);
             pthread_cond_broadcast(&wait_device_release);
          }
+         Jmsg(jcr, M_INFO, 0, _("Job %s marked to be canceled.\n"), jcr->Job);
          bnet_fsend(dir, _("3000 Job %s marked to be canceled.\n"), jcr->Job);
          free_jcr(jcr);
       }
@@ -341,7 +376,7 @@ static bool do_label(JCR *jcr, int relabel)
       dcr = find_device(jcr, dev_name, drive);
       if (dcr) {
          dev = dcr->dev;
-         P(dev->mutex);               /* Use P to avoid indefinite block */
+         dev->dlock();                 /* Use P to avoid indefinite block */
          if (!dev->is_open()) {
             Dmsg1(400, "Can %slabel. Device is not open\n", relabel?"re":"");
             label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel);
@@ -356,7 +391,7 @@ static bool do_label(JCR *jcr, int relabel)
             Dmsg0(400, "Can relabel. device not used\n");
             label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel);
          }
-         V(dev->mutex);
+         dev->dunlock();
          free_dcr(dcr);
          jcr->dcr = NULL;
       } else {
@@ -390,18 +425,14 @@ static void label_volume_if_ok(DCR *dcr, char *oldname,
    DEVICE *dev = dcr->dev;
    int label_status;
    int mode;
-   const char *volname = (relabel == 0) ? newname : oldname;
+   const char *volname = (relabel == 1) ? oldname : newname;
    char ed1[50];
 
    steal_device_lock(dev, &hold, BST_WRITING_LABEL);
    Dmsg1(100, "Stole device %s lock, writing label.\n", dev->print_name());
 
-   Dmsg0(90, "try_autoload_device - looking for volume_info\n");
-   if (relabel && dev->is_dvd()) {
-      /* Fake at least one partition to ensure that we look for the old volume */
-      dcr->VolCatInfo.VolCatParts = 1;
-   }
 
+   Dmsg0(90, "try_autoload_device - looking for volume_info\n");
    if (!try_autoload_device(dcr->jcr, slot, volname)) {
       goto bail_out;                  /* error */
    }
@@ -412,10 +443,12 @@ static void label_volume_if_ok(DCR *dcr, char *oldname,
    } else {
       mode = CREATE_READ_WRITE;
    }
-   if (dev->is_dvd()) {
-      bstrncpy(dcr->VolCatInfo.VolCatName, volname, sizeof(dcr->VolCatInfo.VolCatName));
-   }
 
+   if (relabel) {
+      dev->truncating = true;         /* let open() know we will truncate it */
+   }
+   /* Set old volume name for open if relabeling */
+   bstrncpy(dcr->VolCatInfo.VolCatName, volname, sizeof(dcr->VolCatInfo.VolCatName));
    if (dev->open(dcr, mode) < 0) {
       bnet_fsend(dir, _("3910 Unable to open device %s: ERR=%s\n"),
          dev->print_name(), dev->strerror());
@@ -425,6 +458,8 @@ static void label_volume_if_ok(DCR *dcr, char *oldname,
    /* See what we have for a Volume */
    label_status = read_dev_volume_label(dcr);
    
+   /* Set new volume name */
+   bstrncpy(dcr->VolCatInfo.VolCatName, newname, sizeof(dcr->VolCatInfo.VolCatName));
    switch(label_status) {
    case VOL_NAME_ERROR:
    case VOL_VERSION_ERROR:
@@ -446,19 +481,11 @@ static void label_volume_if_ok(DCR *dcr, char *oldname,
          bnet_fsend(dir, _("3922 Cannot relabel an ANSI/IBM labeled Volume.\n"));
          break;
       }
-      if (relabel && dev->is_dvd()) {
-         /* Change the partition file name */
-         bstrncpy(dcr->VolumeName, newname, sizeof(dcr->VolumeName));
-         if (!dev->truncate(dcr)) {
-            bnet_fsend(dir, _("3912 Failed to truncate previous DVD volume.\n"));
-            break;
-         }
-      }
-      free_volume(dev);               /* release old volume name */
       /* Fall through wanted! */
    case VOL_IO_ERROR:
    case VOL_NO_LABEL:
-      if (!write_new_volume_label_to_dev(dcr, newname, poolname, true /* write dvd now */)) {
+      if (!write_new_volume_label_to_dev(dcr, newname, poolname, 
+           relabel, true /* write dvd now */)) {
          bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), dev->bstrerror());
          break;
       }
@@ -469,7 +496,7 @@ static void label_volume_if_ok(DCR *dcr, char *oldname,
                  dev->is_dvd()?1:0, newname, dev->print_name());
       break;
    case VOL_NO_MEDIA:
-      bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), dev->bstrerror());
+      bnet_fsend(dir, _("3914 Failed to label Volume (no media): ERR=%s\n"), dev->bstrerror());
       break;
    default:
       bnet_fsend(dir, _("3913 Cannot label Volume. "
@@ -479,7 +506,7 @@ static void label_volume_if_ok(DCR *dcr, char *oldname,
 
 bail_out:
    if (!dev->is_open()) {
-      free_volume(dev);
+      dev->clear_volhdr();
    }
    give_back_device_lock(dev, &hold);
    return;
@@ -613,13 +640,13 @@ static bool mount_cmd(JCR *jcr)
       dcr = find_device(jcr, devname, drive);
       if (dcr) {
          dev = dcr->dev;
-         P(dev->mutex);               /* Use P to avoid indefinite block */
-         Dmsg1(100, "mount cmd blocked=%d\n", dev->dev_blocked);
-         switch (dev->dev_blocked) {         /* device blocked? */
+         dev->dlock();                 /* Use P to avoid indefinite block */
+         Dmsg1(100, "mount cmd blocked=%d\n", dev->blocked());
+         switch (dev->blocked()) {         /* device blocked? */
          case BST_WAITING_FOR_SYSOP:
             /* Someone is waiting, wake him */
             Dmsg0(100, "Waiting for mount. Attempting to wake thread\n");
-            dev->dev_blocked = BST_MOUNT;
+            dev->set_blocked(BST_MOUNT);
             bnet_fsend(dir, "3001 OK mount. Device=%s\n", 
                dev->print_name());
             pthread_cond_broadcast(&dev->wait_next_vol);
@@ -636,7 +663,7 @@ static bool mount_cmd(JCR *jcr)
             if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
                bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
                   dev->bstrerror());
-               if (dev->dev_blocked == BST_UNMOUNTED) {
+               if (dev->blocked() == BST_UNMOUNTED) {
                   /* We blocked the device, so unblock it */
                   Dmsg0(100, "Unmounted. Unblocking device\n");
                   unblock_device(dev);
@@ -644,14 +671,14 @@ static bool mount_cmd(JCR *jcr)
                break;
             }
             read_dev_volume_label(dcr);
-            if (dev->dev_blocked == BST_UNMOUNTED) {
+            if (dev->blocked() == BST_UNMOUNTED) {
                /* We blocked the device, so unblock it */
                Dmsg0(100, "Unmounted. Unblocking device\n");
                read_label(dcr);       /* this should not be necessary */
                unblock_device(dev);
             } else {
                Dmsg0(100, "Unmounted waiting for mount. Attempting to wake thread\n");
-               dev->dev_blocked = BST_MOUNT;
+               dev->set_blocked(BST_MOUNT);
             }
             if (dev->is_labeled()) {
                bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"),
@@ -704,7 +731,7 @@ static bool mount_cmd(JCR *jcr)
                              dev->print_name());
                }
             } else if (dev->is_dvd()) {
-               if (mount_dvd(dev, 1)) {
+               if (dev->mount(1)) {
                   bnet_fsend(dir, _("3002 Device %s is mounted.\n"), 
                      dev->print_name());
                } else {
@@ -717,10 +744,10 @@ static bool mount_cmd(JCR *jcr)
             break;
 
          default:
-            bnet_fsend(dir, _("3905 Bizarre wait state %d\n"), dev->dev_blocked);
+            bnet_fsend(dir, _("3905 Bizarre wait state %d\n"), dev->blocked());
             break;
          }
-         V(dev->mutex);
+         dev->dunlock();
          free_dcr(dcr);
          jcr->dcr = NULL;
       } else {
@@ -749,13 +776,13 @@ static bool unmount_cmd(JCR *jcr)
       dcr = find_device(jcr, devname, drive);
       if (dcr) {
          dev = dcr->dev;
-         P(dev->mutex);               /* Use P to avoid indefinite block */
+         dev->dlock();                 /* Use P to avoid indefinite block */
          if (!dev->is_open()) {
             if (!dev->is_busy()) {
-               unload_autochanger(jcr->dcr, -1);          
+               unload_autochanger(dcr, -1);          
             }
             if (dev->is_dvd()) {
-               if (unmount_dvd(dev, 0)) {
+               if (dev->unmount(0)) {
                   bnet_fsend(dir, _("3002 Device %s unmounted.\n"), 
                      dev->print_name());
                } else {
@@ -766,25 +793,26 @@ static bool unmount_cmd(JCR *jcr)
                bnet_fsend(dir, _("3901 Device %s is already unmounted.\n"), 
                   dev->print_name());
             }
-         } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) {
+         } else if (dev->blocked() == BST_WAITING_FOR_SYSOP) {
             Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
-               dev->dev_blocked);
-            if (!unload_autochanger(jcr->dcr, -1)) {
+               dev->blocked());
+            if (!unload_autochanger(dcr, -1)) {
+               /* ***FIXME**** what is this ????  */
                dev->close();
             }
-            if (dev->is_dvd() && !unmount_dvd(dev, 0)) {
+            if (dev->is_dvd() && !dev->unmount(0)) {
                bnet_fsend(dir, _("3907 %s"), dev->bstrerror());
             } else {
-               dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP;
+               dev->set_blocked(BST_UNMOUNTED_WAITING_FOR_SYSOP);
                bnet_fsend(dir, _("3001 Device %s unmounted.\n"), 
                   dev->print_name());
             }
 
-         } else if (dev->dev_blocked == BST_DOING_ACQUIRE) {
+         } else if (dev->blocked() == BST_DOING_ACQUIRE) {
             bnet_fsend(dir, _("3902 Device %s is busy in acquire.\n"), 
                dev->print_name());
 
-         } else if (dev->dev_blocked == BST_WRITING_LABEL) {
+         } else if (dev->blocked() == BST_WRITING_LABEL) {
             bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), 
                dev->print_name());
 
@@ -798,19 +826,19 @@ static bool unmount_cmd(JCR *jcr)
              * we simply do it by hand.  Gross, but a solution.
              */
             /*  block_device(dev, BST_UNMOUNTED); replace with 2 lines below */
-            dev->dev_blocked = BST_UNMOUNTED;
+            dev->set_blocked(BST_UNMOUNTED);
             dev->no_wait_id = 0;
-            if (!unload_autochanger(jcr->dcr, -1)) {
+            if (!unload_autochanger(dcr, -1)) {
                dev->close();
             }
-            if (dev->is_dvd() && !unmount_dvd(dev, 0)) {
+            if (dev->is_dvd() && !dev->unmount(0)) {
                bnet_fsend(dir, _("3907 %s"), dev->bstrerror());
             } else {
                bnet_fsend(dir, _("3002 Device %s unmounted.\n"), 
                   dev->print_name());
             }
          }
-         V(dev->mutex);
+         dev->dunlock();
          free_dcr(dcr);
          jcr->dcr = NULL;
       } else {
@@ -844,36 +872,46 @@ static bool release_cmd(JCR *jcr)
       dcr = find_device(jcr, devname, drive);
       if (dcr) {
          dev = dcr->dev;
-         P(dev->mutex);               /* Use P to avoid indefinite block */
+         dev->dlock();                 /* Use P to avoid indefinite block */
          if (!dev->is_open()) {
+            if (!dev->is_busy()) {
+               unload_autochanger(dcr, -1);
+            }
             Dmsg0(90, "Device already released\n");
             bnet_fsend(dir, _("3921 Device %s already released.\n"), 
                dev->print_name());
 
-         } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
-                    dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP) {
+         } else if (dev->blocked() == BST_WAITING_FOR_SYSOP) {
+            Dmsg2(90, "%d waiter dev_block=%d.\n", dev->num_waiting,
+               dev->blocked());
+            unload_autochanger(dcr, -1);
+            bnet_fsend(dir, _("3922 Device %s waiting for sysop.\n"), 
+               dev->print_name());
+
+         } else if (dev->blocked() == BST_UNMOUNTED_WAITING_FOR_SYSOP) {
             Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
-               dev->dev_blocked);
+               dev->blocked());
             bnet_fsend(dir, _("3922 Device %s waiting for mount.\n"), 
                dev->print_name());
 
-         } else if (dev->dev_blocked == BST_DOING_ACQUIRE) {
+         } else if (dev->blocked() == BST_DOING_ACQUIRE) {
             bnet_fsend(dir, _("3923 Device %s is busy in acquire.\n"), 
                dev->print_name());
 
-         } else if (dev->dev_blocked == BST_WRITING_LABEL) {
+         } else if (dev->blocked() == BST_WRITING_LABEL) {
             bnet_fsend(dir, _("3914 Device %s is being labeled.\n"), 
                dev->print_name());
 
          } else if (dev->is_busy()) {
             send_dir_busy_message(dir, dev);
          } else {                     /* device not being used */
-            Dmsg0(90, "Device not in use, unmounting\n");
-            release_volume(jcr->dcr);
+            Dmsg0(90, "Device not in use, releaseing\n");
+            unload_autochanger(dcr, -1);
+            release_volume(dcr);
             bnet_fsend(dir, _("3022 Device %s released.\n"), 
                dev->print_name());
          }
-         V(dev->mutex);
+         dev->dunlock();
          free_dcr(dcr);
          jcr->dcr = NULL;
       } else {
@@ -925,7 +963,7 @@ static bool changer_cmd(JCR *jcr)
       dcr = find_device(jcr, devname, -1);
       if (dcr) {
          dev = dcr->dev;
-         P(dev->mutex);               /* Use P to avoid indefinite block */
+         dev->dlock();                 /* Use P to avoid indefinite block */
          if (!dev->device->changer_res) {
             bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), 
                dev->print_name());
@@ -937,7 +975,7 @@ static bool changer_cmd(JCR *jcr)
          } else {                     /* device not being used */
             autochanger_cmd(dcr, dir, cmd);
          }
-         V(dev->mutex);
+         dev->dunlock();
          free_dcr(dcr);
          jcr->dcr = NULL;
       } else {
@@ -948,7 +986,7 @@ static bool changer_cmd(JCR *jcr)
       bnet_fsend(dir, _("3908 Error scanning autocharger drives/list/slots command: %s\n"),
          jcr->errmsg);
    }
-   bnet_sig(dir, BNET_EOD);
+   dir->signal(BNET_EOD);
    return true;
 }
 
@@ -969,7 +1007,7 @@ static bool readlabel_cmd(JCR *jcr)
       dcr = find_device(jcr, devname, drive);
       if (dcr) {
          dev = dcr->dev;
-         P(dev->mutex);               /* Use P to avoid indefinite block */
+         dev->dlock();                 /* Use P to avoid indefinite block */
          if (!dev->is_open()) {
             read_volume_label(jcr, dev, Slot);
             dev->close();
@@ -981,7 +1019,7 @@ static bool readlabel_cmd(JCR *jcr)
          } else {                     /* device not being used */
             read_volume_label(jcr, dev, Slot);
          }
-         V(dev->mutex);
+         dev->dunlock();
          free_dcr(dcr);
          jcr->dcr = NULL;
       } else {
@@ -991,7 +1029,7 @@ static bool readlabel_cmd(JCR *jcr)
       pm_strcpy(jcr->errmsg, dir->msg);
       bnet_fsend(dir, _("3909 Error scanning readlabel command: %s\n"), jcr->errmsg);
    }
-   bnet_sig(dir, BNET_EOD);
+   dir->signal(BNET_EOD);
    return true;
 }
 
@@ -1049,7 +1087,7 @@ static bool try_autoload_device(JCR *jcr, int slot, const char *VolName)
 static void send_dir_busy_message(BSOCK *dir, DEVICE *dev)
 {
    if (dev->is_blocked()) {
-      switch (dev->dev_blocked) {
+      switch (dev->blocked()) {
       case BST_UNMOUNTED:
          bnet_fsend(dir, _("3931 Device %s is BLOCKED. user unmounted.\n"),
             dev->print_name());