]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/stored/acquire.c
This commit was manufactured by cvs2svn to create tag
[bacula/bacula] / bacula / src / stored / acquire.c
index e1fe5acfab31b17050ca8bc02537731ff9ce196c..671fb8bee278826bbfb315a8f1c8ef821a5c8803 100644 (file)
@@ -42,6 +42,9 @@ DCR *new_dcr(JCR *jcr, DEVICE *dev)
    }
    dcr->jcr = jcr;
    dcr->dev = dev;
+   if (dev) {
+      dcr->device = dev->device;
+   }
    dcr->block = new_block(dev);
    dcr->rec = new_record();
    dcr->spool_fd = -1;
@@ -80,8 +83,8 @@ void free_dcr(DCR *dcr)
  *  only one reader.  We read the Volume label from the block and
  *  leave the block pointers just after the label.
  *
- *  Returns: 0 if failed for any reason
- *          1 if successful
+ *  Returns: NULL if failed for any reason
+ *          dcr  if successful
  */
 DCR *acquire_device_for_read(JCR *jcr)
 {
@@ -129,12 +132,12 @@ DCR *acquire_device_for_read(JCR *jcr)
    for (i=1; i<jcr->CurVolume; i++) {
       vol = vol->next;
    }
-   pm_strcpy(&jcr->VolumeName, vol->VolumeName);
    bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
 
    for (i=0; i<5; i++) {
+      dcr->dev->state &= ~ST_LABEL;          /* force reread of label */
       if (job_canceled(jcr)) {
-         Mmsg1(&dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
+         Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
         goto get_out;                /* error return */
       }
       /*
@@ -143,8 +146,11 @@ DCR *acquire_device_for_read(JCR *jcr)
        * If it is a tape, it checks the volume name 
        */
       for ( ; !(dev->state & ST_OPENED); ) {
-         Dmsg1(120, "bstored: open vol=%s\n", jcr->VolumeName);
+         Dmsg1(120, "bstored: open vol=%s\n", dcr->VolumeName);
         if (open_dev(dev, dcr->VolumeName, OPEN_READ_ONLY) < 0) {
+           if (dev->dev_errno == EIO) {   /* no tape loaded */
+              goto default_path;
+           }
             Jmsg(jcr, M_FATAL, 0, _("Open device %s volume %s failed, ERR=%s\n"), 
                dev_name(dev), dcr->VolumeName, strerror_dev(dev));
            goto get_out;
@@ -155,11 +161,11 @@ DCR *acquire_device_for_read(JCR *jcr)
        *  correctly possitioned.  Possibly have way user can turn
        *  this optimization (to be implemented) off.
        */
-      dcr->dev->state &= ~ST_LABEL;          /* force reread of label */
       Dmsg0(200, "calling read-vol-label\n");
-      switch (read_dev_volume_label(dcr, dcr->block)) {
+      switch (read_dev_volume_label(dcr)) {
       case VOL_OK:
         vol_ok = true;
+        memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
         break;                    /* got it */
       case VOL_IO_ERROR:
         /*
@@ -189,7 +195,7 @@ default_path:
         if (try_autochanger) {
            int stat;
             Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
-              jcr->VolumeName, jcr->VolCatInfo.Slot);                         
+              dcr->VolumeName, dcr->VolCatInfo.Slot);                         
            stat = autoload_device(dcr, 0, NULL);
            if (stat > 0) {
               try_autochanger = false;
@@ -214,11 +220,10 @@ default_path:
 
    dev->state &= ~ST_APPEND;         /* clear any previous append mode */
    dev->state |= ST_READ;            /* set read mode */
-   attach_jcr_to_device(dev, jcr);    /* attach jcr to device */
    set_jcr_job_status(jcr, JS_Running);
    dir_send_job_status(jcr);
    Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
-      jcr->VolumeName, dev_name(dev));
+      dcr->VolumeName, dev_name(dev));
 
 get_out:
    P(dev->mutex); 
@@ -260,8 +265,8 @@ DCR *acquire_device_for_append(JCR *jcr)
    P(mutex);                        /* lock all devices */
    Dmsg1(190, "acquire_append device is %s\n", dev_is_tape(dev)?"tape":"disk");
             
-
    if (dev_state(dev, ST_APPEND)) {
+      Dmsg0(190, "device already in append.\n");
       /* 
        * Device already in append mode  
        *
@@ -271,11 +276,11 @@ DCR *acquire_device_for_append(JCR *jcr)
        *   otherwise mount desired volume obtained from
        *    dir_find_next_appendable_volume
        */
-      pm_strcpy(&jcr->VolumeName, dev->VolHdr.VolName);
       bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName));
       if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
          !(dir_find_next_appendable_volume(dcr) &&
-           strcmp(dev->VolHdr.VolName, jcr->VolumeName) == 0)) { /* wrong tape mounted */
+           strcmp(dev->VolHdr.VolName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
+         Dmsg0(190, "Wrong tape mounted.\n");
         if (dev->num_writers != 0) {
            DEVICE *d = ((DEVRES *)dev->device)->dev;
            uint32_t open_vols = 0;
@@ -304,6 +309,7 @@ DCR *acquire_device_for_append(JCR *jcr)
            }
         }
         /* Wrong tape mounted, release it, then fall through to get correct one */
+         Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
         release = true;
         do_mount = true;
       } else {
@@ -312,15 +318,20 @@ DCR *acquire_device_for_append(JCR *jcr)
          *   we do not need to do mount_next_write_volume(), unless
          *   we need to recycle the tape.
          */
-          recycle = strcmp(jcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
+          recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
+          Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
          if (recycle && dev->num_writers != 0) {
              Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
                   " because it is in use by another job.\n"));
             goto get_out;
          }
+         if (dev->num_writers == 0) {
+            memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
+         }
        }
    } else { 
       /* Not already in append mode, so mount the device */
+      Dmsg0(190, "Not in append mode, try mount.\n");
       if (dev_state(dev, ST_READ)) {
          Jmsg(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev_name(dev));
         goto get_out;
@@ -330,7 +341,11 @@ DCR *acquire_device_for_append(JCR *jcr)
    }
 
    if (do_mount || recycle) {
-      if (!mount_next_write_volume(dcr, dcr->block, release)) {
+      Dmsg0(190, "Do mount_next_write_vol\n");
+      V(mutex);                       /* don't lock everything during mount */
+      bool mounted = mount_next_write_volume(dcr, release);
+      P(mutex);                      /* re-lock */
+      if (!mounted) {
         if (!job_canceled(jcr)) {
             /* Reduce "noise" -- don't print if job canceled */
             Jmsg(jcr, M_FATAL, 0, _("Could not ready device \"%s\" for append.\n"),
@@ -344,7 +359,6 @@ DCR *acquire_device_for_append(JCR *jcr)
    if (jcr->NumVolumes == 0) {
       jcr->NumVolumes = 1;
    }
-   attach_jcr_to_device(dev, jcr);    /* attach jcr to device */
    set_jcr_job_status(jcr, JS_Running);
    dir_send_job_status(jcr);
    goto ok_out;
@@ -375,8 +389,8 @@ bool release_device(JCR *jcr)
    DEVICE *dev = dcr->dev;   
    lock_device(dev);
    Dmsg1(100, "release_device device is %s\n", dev_is_tape(dev)?"tape":"disk");
-   if (dev_state(dev, ST_READ)) {
-      dev->state &= ~ST_READ;        /* clear read bit */
+   if (dev->can_read()) {
+      dev->clear_read();             /* clear read bit */
       if (!dev_is_tape(dev) || !dev_cap(dev, CAP_ALWAYSOPEN)) {
         offline_or_rewind_dev(dev);
         close_dev(dev);
@@ -386,11 +400,11 @@ bool release_device(JCR *jcr)
    } else if (dev->num_writers > 0) {
       dev->num_writers--;
       Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
-      if (dev_state(dev, ST_LABEL)) {
+      if (dev->is_labeled()) {
          Dmsg0(100, "dir_create_jobmedia_record. Release\n");
         if (!dir_create_jobmedia_record(dcr)) {
-            Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
-           jcr->VolCatInfo.VolCatName, jcr->Job);
+            Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
+              dcr->VolCatInfo.VolCatName, jcr->Job);
         }
         /* If no more writers, write an EOF */
         if (!dev->num_writers && dev_can_write(dev)) {
@@ -408,10 +422,37 @@ bool release_device(JCR *jcr)
         close_dev(dev);
       }
    } else {
-      Jmsg2(jcr, M_ERROR, 0, _("BAD ERROR: release_device %s, Volume \"%s\" not in use.\n"), 
-           dev_name(dev), NPRT(jcr->VolumeName));
+      Jmsg2(jcr, M_FATAL, 0, _("BAD ERROR: release_device %s, Volume \"%s\" not in use.\n"), 
+           dev_name(dev), NPRT(dcr->VolumeName));
+      Jmsg2(jcr, M_ERROR, 0, _("num_writers=%d state=%x\n"), dev->num_writers, dev->state);
+   }
+
+   /* Fire off Alert command and include any output */
+   if (!job_canceled(jcr) && jcr->device->alert_command) {
+      POOLMEM *alert;
+      int status = 1;
+      BPIPE *bpipe;
+      char line[MAXSTRING];
+      alert = get_pool_memory(PM_FNAME);
+      alert = edit_device_codes(jcr, alert, jcr->device->alert_command, "");
+      bpipe = open_bpipe(alert, 0, "r");
+      if (bpipe) {
+        while (fgets(line, sizeof(line), bpipe->rfd)) {
+            Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
+        }
+        status = close_bpipe(bpipe);
+      } else {
+        status = errno;
+      }
+      if (status != 0) {
+        berrno be;
+         Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
+             alert, be.strerror(status));
+      }
+
+      Dmsg1(400, "alert status=%d\n", status);
+      free_pool_memory(alert);
    }
-   detach_jcr_from_device(dev, jcr);
    if (dev->prev && !dev_state(dev, ST_READ) && !dev->num_writers) {
       P(mutex);
       unlock_device(dev);