src/stored/acquire.c
bool release_device(DCR *dcr)
{
   JCR *jcr = dcr->jcr;
   DEVICE *dev = dcr->dev;
   bool ok = true;
   char tbuf[100];
   bsteal_lock_t holder;

   dev->Lock();
   if (!obtain_device_block(dev,
                            &holder,
                            0,  /* infinite wait */
                            BST_RELEASING)) {
      ASSERT2(0, "unable to obtain device block");
   }

   lock_volumes();
   Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");

   /* if device is reserved, job never started, so release the reserve here */
   dcr->clear_reserved();

   if (dev->can_read()) {
      VOLUME_CAT_INFO *vol = &dev->VolCatInfo;
      generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
      dev->clear_read();              /* clear read bit */
      Dmsg2(150, "dir_update_vol_info. label=%d Vol=%s\n",
         dev->is_labeled(), vol->VolCatName);
      if (dev->is_labeled() && vol->VolCatName[0] != 0) {
         dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
         remove_read_volume(jcr, dcr->VolumeName);
         volume_unused(dcr);
      }
   } else if (dev->num_writers > 0) {
      /*
       * Note if WEOT is set, we are at the end of the tape
       *   and may not be positioned correctly, so the
       *   job_media_record and update_vol_info have already been
       *   done, which means we skip them here.
       */
      dev->num_writers--;
      Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
      if (dev->is_labeled()) {
         if (!dev->at_weot()) {
            Dmsg2(200, "dir_create_jobmedia. Release vol=%s dev=%s\n",
                  dev->getVolCatName(), dev->print_name());
         }
         if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
            Jmsg2(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
               dcr->getVolCatName(), jcr->Job);
         }
         /* If no more writers, and no errors, and wrote something, write an EOF */
         if (!dev->num_writers && dev->can_write() && dev->block_num > 0) {
            dev->weof(dcr, 1);
            write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
         }
         if (!dev->at_weot()) {
            dev->VolCatInfo.VolCatFiles = dev->get_file();   /* set number of files */
            /* Note! do volume update before close, which zaps VolCatInfo */
            dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
            Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n",
                  dev->getVolCatName(), dev->print_name());
         }
         if (dev->num_writers == 0) {         /* if not being used */
            volume_unused(dcr);               /*  we obviously are not using the volume */
            generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
         }
      }

   } else {
      /*
       * If we reach here, it is most likely because the job
       *   has failed, since the device is not in read mode and
       *   there are no writers. It was probably reserved.
       */
      volume_unused(dcr);
      generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
   }
   Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(),
         dev->print_name());

   /* If no writers, close if file or !CAP_ALWAYS_OPEN */
   if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
      generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
      if (!dev->close(dcr) && dev->errmsg[0]) {
         Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
      }
      free_volume(dev);
   }
   unlock_volumes();

   /* Do new tape alert code */
   dev->get_tape_alerts(dcr);
   /* alert_callback is in tape_alert.c -- show only most recent (last) alert */
   dev->show_tape_alerts(dcr, list_long, list_last, alert_callback);

   pthread_cond_broadcast(&dev->wait_next_vol);
   Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n",
         (uint32_t)jcr->JobId, bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL)));
   pthread_cond_broadcast(&wait_device_release);

   give_back_device_block(dev, &holder);
   /*
    * If we are the thread that blocked the device, then unblock it
    */
   if (pthread_equal(dev->no_wait_id, pthread_self())) {
      dev->dunblock(true);
   } else {
      dev->Unlock();
   }

   dev->end_of_job(dcr);

   if (dcr->keep_dcr) {
      dev->detach_dcr_from_dev(dcr);
   } else {
      free_dcr(dcr);
   }
   Dmsg2(100, "Device %s released by JobId=%u\n", dev->print_name(),
         (uint32_t)jcr->JobId);
   return ok;
}
/*
 * This job is done, so release the device. From a Unix standpoint,
 *  the device remains open.
 *
 * Note, if we were spooling, we may enter with the device blocked.
 *   We unblock at the end, only if it was us who blocked the
 *   device.
 *
 */
This job is done, so release the device. From a Unix standpoint,
the device remains open.

Note, if we were spooling, we may enter with the device blocked.
We unblock at the end, only if it was us who blocked the
device.
This job is done so release the device . From a Unix standpoint the device remains open . Note if we were spooling we may enter with the device blocked . We unblock at the end only if it was us who blocked the device .
bool release_device(DCR *dcr)
{
   JCR *jcr = dcr->jcr;
   DEVICE *dev = dcr->dev;
   bool ok = true;
   char tbuf[100];
   bsteal_lock_t holder;
   dev->Lock();
   if (!obtain_device_block(dev,
                            &holder,
                            0,  
                            BST_RELEASING)) {
      ASSERT2(0, "unable to obtain device block");
   }
   lock_volumes();
   Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
   dcr->clear_reserved();
   if (dev->can_read()) {
      VOLUME_CAT_INFO *vol = &dev->VolCatInfo;
      generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
      dev->clear_read();              
      Dmsg2(150, "dir_update_vol_info. label=%d Vol=%s\n",
         dev->is_labeled(), vol->VolCatName);
      if (dev->is_labeled() && vol->VolCatName[0] != 0) {
         dir_update_volume_info(dcr, false, false); 
         remove_read_volume(jcr, dcr->VolumeName);
         volume_unused(dcr);
      }
   } else if (dev->num_writers > 0) {
      dev->num_writers--;
      Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
      if (dev->is_labeled()) {
         if (!dev->at_weot()) {
            Dmsg2(200, "dir_create_jobmedia. Release vol=%s dev=%s\n",
                  dev->getVolCatName(), dev->print_name());
         }
         if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
            Jmsg2(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
               dcr->getVolCatName(), jcr->Job);
         }
         if (!dev->num_writers && dev->can_write() && dev->block_num > 0) {
            dev->weof(dcr, 1);
            write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
         }
         if (!dev->at_weot()) {
            dev->VolCatInfo.VolCatFiles = dev->get_file();   
            dir_update_volume_info(dcr, false, false); 
            Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n",
                  dev->getVolCatName(), dev->print_name());
         }
         if (dev->num_writers == 0) {         
            volume_unused(dcr);               
            generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
         }
      }
   } else {
      volume_unused(dcr);
      generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
   }
   Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(),
         dev->print_name());
   if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
      generate_plugin_event(jcr, bsdEventDeviceClose, dcr);
      if (!dev->close(dcr) && dev->errmsg[0]) {
         Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
      }
      free_volume(dev);
   }
   unlock_volumes();
   dev->get_tape_alerts(dcr);
   dev->show_tape_alerts(dcr, list_long, list_last, alert_callback);
   pthread_cond_broadcast(&dev->wait_next_vol);
   Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n",
         (uint32_t)jcr->JobId, bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL)));
   pthread_cond_broadcast(&wait_device_release);
   give_back_device_block(dev, &holder);
   if (pthread_equal(dev->no_wait_id, pthread_self())) {
      dev->dunblock(true);
   } else {
      dev->Unlock();
   }
   dev->end_of_job(dcr);
   if (dcr->keep_dcr) {
      dev->detach_dcr_from_dev(dcr);
   } else {
      free_dcr(dcr);
   }
   Dmsg2(100, "Device %s released by JobId=%u\n", dev->print_name(),
         (uint32_t)jcr->JobId);
   return ok;
}
bool release_device ( DCR * dcr ) { JCR * jcr = dcr -> jcr ; DEVICE * dev = dcr -> dev ; bool ok = true ; char tbuf [ 100 ] ; bsteal_lock_t holder ; dev -> Lock ( ) ; if ( ! obtain_device_block ( dev , & holder , 0 , BST_RELEASING ) ) { ASSERT2 ( 0 , " " ) ; } lock_volumes ( ) ; Dmsg2 ( 100 , " \n " , dev -> print_name ( ) , dev -> is_tape ( ) ? " " : " " ) ; dcr -> clear_reserved ( ) ; if ( dev -> can_read ( ) ) { VOLUME_CAT_INFO * vol = & dev -> VolCatInfo ; generate_plugin_event ( jcr , bsdEventDeviceClose , dcr ) ; dev -> clear_read ( ) ; Dmsg2 ( 150 , " \n " , dev -> is_labeled ( ) , vol -> VolCatName ) ; if ( dev -> is_labeled ( ) && vol -> VolCatName [ 0 ] != 0 ) { dir_update_volume_info ( dcr , false , false ) ; remove_read_volume ( jcr , dcr -> VolumeName ) ; volume_unused ( dcr ) ; } } else if ( dev -> num_writers > 0 ) { dev -> num_writers -- ; Dmsg1 ( 100 , " \n " , dev -> num_writers ) ; if ( dev -> is_labeled ( ) ) { if ( ! dev -> at_weot ( ) ) { Dmsg2 ( 200 , " \n " , dev -> getVolCatName ( ) , dev -> print_name ( ) ) ; } if ( ! dev -> at_weot ( ) && ! dir_create_jobmedia_record ( dcr ) ) { Jmsg2 ( jcr , M_FATAL , 0 , _ ( " \" \" \n " ) , dcr -> getVolCatName ( ) , jcr -> Job ) ; } if ( ! dev -> num_writers && dev -> can_write ( ) && dev -> block_num > 0 ) { dev -> weof ( dcr , 1 ) ; write_ansi_ibm_labels ( dcr , ANSI_EOF_LABEL , dev -> VolHdr . VolumeName ) ; } if ( ! dev -> at_weot ( ) ) { dev -> VolCatInfo . VolCatFiles = dev -> get_file ( ) ; dir_update_volume_info ( dcr , false , false ) ; Dmsg2 ( 200 , " \n " , dev -> getVolCatName ( ) , dev -> print_name ( ) ) ; } if ( dev -> num_writers == 0 ) { volume_unused ( dcr ) ; generate_plugin_event ( jcr , bsdEventDeviceClose , dcr ) ; } } } else { volume_unused ( dcr ) ; generate_plugin_event ( jcr , bsdEventDeviceClose , dcr ) ; } Dmsg3 ( 100 , " \n " , dev -> num_writers , dev -> num_reserved ( ) , dev -> print_name ( ) ) ; if ( dev -> num_writers == 0 && ( ! dev -> is_tape ( ) || ! dev -> has_cap ( CAP_ALWAYSOPEN ) ) ) { generate_plugin_event ( jcr , bsdEventDeviceClose , dcr ) ; if ( ! dev -> close ( dcr ) && dev -> errmsg [ 0 ] ) { Jmsg ( jcr , M_ERROR , 0 , " " , dev -> errmsg ) ; } free_volume ( dev ) ; } unlock_volumes ( ) ; dev -> get_tape_alerts ( dcr ) ; dev -> show_tape_alerts ( dcr , list_long , list_last , alert_callback ) ; pthread_cond_broadcast ( & dev -> wait_next_vol ) ; Dmsg2 ( 100 , " \n " , ( uint32_t ) jcr -> JobId , bstrftimes ( tbuf , sizeof ( tbuf ) , ( utime_t ) time ( NULL ) ) ) ; pthread_cond_broadcast ( & wait_device_release ) ; give_back_device_block ( dev , & holder ) ; if ( pthread_equal ( dev -> no_wait_id , pthread_self ( ) ) ) { dev -> dunblock ( true ) ; } else { dev -> Unlock ( ) ; } dev -> end_of_job ( dcr ) ; if ( dcr -> keep_dcr ) { dev -> detach_dcr_from_dev ( dcr ) ; } else { free_dcr ( dcr ) ; } Dmsg2 ( 100 , " \n " , dev -> print_name ( ) , ( uint32_t ) jcr -> JobId ) ; return ok ; }
This job is done, so release the device.
This job is done so release the device .
/* infinite wait */ /* if device is reserved, job never started, so release the reserve here */ /* clear read bit */ /* send Volume info to Director */ /*
       * Note if WEOT is set, we are at the end of the tape
       *   and may not be positioned correctly, so the
       *   job_media_record and update_vol_info have already been
       *   done, which means we skip them here.
       */ /* If no more writers, and no errors, and wrote something, write an EOF */ /* set number of files */ /* Note! do volume update before close, which zaps VolCatInfo */ /* send Volume info to Director */ /* if not being used */ /*  we obviously are not using the volume */ /*
       * If we reach here, it is most likely because the job
       *   has failed, since the device is not in read mode and
       *   there are no writers. It was probably reserved.
       */ /* If no writers, close if file or !CAP_ALWAYS_OPEN */ /* Do new tape alert code */ /* alert_callback is in tape_alert.c -- show only most recent (last) alert */ /*
    * If we are the thread that blocked the device, then unblock it
    */