src/stored/autochanger.c
int autoload_device(DCR *dcr, bool writing, BSOCK *dir)
{
   JCR *jcr = dcr->jcr;
   DEVICE * volatile dev = dcr->dev;
   char *new_vol_name = dcr->VolumeName;
   int slot;
   int drive = dev->drive_index;
   int rtn_stat = -1;                 /* error status */
   POOLMEM *changer;

   if (!dev->is_autochanger()) {
      Dmsg1(dbglvl, "Device %s is not an autochanger\n", dev->print_name());
      return 0;
   }

   /* An empty ChangerCommand => virtual disk autochanger */
   if (dcr->is_virtual_autochanger()) {
      Dmsg0(dbglvl, "ChangerCommand=0, virtual disk changer\n");
      return 1;                       /* nothing to load */
   }

   slot = dcr->VolCatInfo.InChanger ? dcr->VolCatInfo.Slot : 0;
   /*
    * Handle autoloaders here.  If we cannot autoload it, we
    *  will return 0 so that the sysop will be asked to load it.
    */
   if (writing && slot <= 0) {
      if (dir) {
         return 0;                    /* For user, bail out right now */
      }
      /* ***FIXME*** this really should not be here */
      if (dir_find_next_appendable_volume(dcr)) {
         slot = dcr->VolCatInfo.InChanger ? dcr->VolCatInfo.Slot : 0;
      } else {
         slot = 0;
         dev->clear_wait();
      }
   }
   Dmsg4(dbglvl, "Want slot=%d drive=%d InChgr=%d Vol=%s\n",
         dcr->VolCatInfo.Slot, drive,
         dcr->VolCatInfo.InChanger, dcr->getVolCatName());

   changer = get_pool_memory(PM_FNAME);
   if (slot <= 0) {
      /* Suppress info when polling */
      if (!dev->poll) {
         Jmsg(jcr, M_INFO, 0, _("No slot defined in catalog (slot=%d) for Volume \"%s\" on %s.\n"),
              slot, dcr->getVolCatName(), dev->print_name());
         Jmsg(jcr, M_INFO, 0, _("Cartridge change or \"update slots\" may be required.\n"));
      }
      rtn_stat = 0;
   } else if (!dcr->device->changer_name) {
      /* Suppress info when polling */
      if (!dev->poll) {
         Jmsg(jcr, M_INFO, 0, _("No \"Changer Device\" for %s. Manual load of Volume may be required.\n"),
              dev->print_name());
      }
      rtn_stat = 0;
  } else if (!dcr->device->changer_command) {
      /* Suppress info when polling */
      if (!dev->poll) {
         Jmsg(jcr, M_INFO, 0, _("No \"Changer Command\" for %s. Manual load of Volume may be requird.\n"),
              dev->print_name());
      }
      rtn_stat = 0;
  } else {
      /* Attempt to load the Volume */
      uint32_t timeout = dcr->device->max_changer_wait;
      int loaded, status;

      loaded = get_autochanger_loaded_slot(dcr);
      if (loaded < 0) {   /* Autochanger error, try again */
         loaded = get_autochanger_loaded_slot(dcr);
      }
      Dmsg2(dbglvl, "Found loaded=%d drive=%d\n", loaded, drive);

      if (loaded <= 0 || loaded != slot) {
         POOL_MEM results(PM_MESSAGE);

         /* Unload anything in our drive */
         if (!unload_autochanger(dcr, loaded)) {
            goto bail_out;
         }

         /* Make sure desired slot is unloaded */
         if (!unload_other_drive(dcr, slot, writing)) {
            goto bail_out;
         }

         /*
          * Load the desired cassette
          */
         lock_changer(dcr);
         Dmsg2(dbglvl, "Doing changer load slot %d %s\n", slot, dev->print_name());
         Jmsg(jcr, M_INFO, 0,
            _("3304 Issuing autochanger \"load Volume %s, Slot %d, Drive %d\" command.\n"),
            new_vol_name, slot, drive);
         Dmsg3(dbglvl,
            "3304 Issuing autochanger \"load Volume %s, Slot %d, Drive %d\" command.\n",
            new_vol_name, slot, drive);

         dcr->VolCatInfo.Slot = slot;    /* slot to be loaded */
         changer = edit_device_codes(dcr, changer, dcr->device->changer_command, "load");
         dev->close(dcr);
         Dmsg1(dbglvl, "Run program=%s\n", changer);
         status = run_program_full_output(changer, timeout, results.addr());
         if (status == 0) {
            Jmsg(jcr, M_INFO, 0, _("3305 Autochanger \"load Volume %s, Slot %d, Drive %d\", status is OK.\n"),
                    new_vol_name, slot, drive);
            Dmsg3(dbglvl, "OK: load volume %s, slot %d, drive %d.\n", new_vol_name,  slot, drive);
            bstrncpy(dev->LoadedVolName, new_vol_name, sizeof(dev->LoadedVolName));
            dev->set_slot(slot);      /* set currently loaded slot */
            if (dev->vol) {
               /* We just swapped this Volume so it cannot be swapping any more */
               dev->vol->clear_swapping();
            }
         } else {
            berrno be;
            be.set_errno(status);
            Dmsg5(dbglvl, "Error: load Volume %s, Slot %d, Drive %d, bad stats=%s.\nResults=%s\n",
                new_vol_name, slot, drive,
               be.bstrerror(), results.c_str());
            Jmsg(jcr, M_FATAL, 0, _("3992 Bad autochanger \"load Volume %s Slot %d, Drive %d\": "
                 "ERR=%s.\nResults=%s\n"),
                    new_vol_name, slot, drive, be.bstrerror(), results.c_str());
            rtn_stat = -1;            /* hard error */
            dev->clear_slot();        /* mark unknown */
         }
         unlock_changer(dcr);
      } else {
         status = 0;                  /* we got what we want */
         dev->set_slot(slot);         /* set currently loaded slot */
         bstrncpy(dev->LoadedVolName, new_vol_name, sizeof(dev->LoadedVolName));
      }
      Dmsg1(dbglvl, "After changer, status=%d\n", status);
      if (status == 0) {              /* did we succeed? */
         rtn_stat = 1;                /* tape loaded by changer */
      }
   }
   free_pool_memory(changer);
   return rtn_stat;

bail_out:
   free_pool_memory(changer);
   return -1;

}
/*
 * Called here to do an autoload using the autochanger, if
 *  configured, and if a Slot has been defined for this Volume.
 *  On success this routine loads the indicated tape, but the
 *  label is not read, so it must be verified.
 *
 *  Note if dir is not NULL, it is the console requesting the
 *   autoload for labeling, so we respond directly to the
 *   dir bsock.
 *
 *  Returns: 1 on success
 *           0 on failure (no changer available)
 *          -1 on error on autochanger
 */
Called here to do an autoload using the autochanger, if
configured, and if a Slot has been defined for this Volume.
On success this routine loads the indicated tape, but the
label is not read, so it must be verified.

Note if dir is not NULL, it is the console requesting the
autoload for labeling, so we respond directly to the
dir bsock.

1 on success
0 on failure (no changer available)
-1 on error on autochanger
Called here to do an autoload using the autochanger if configured and if a Slot has been defined for this Volume . On success this routine loads the indicated tape but the label is not read so it must be verified . Note if dir is not NULL it is the console requesting the autoload for labeling so we respond directly to the dir bsock . 1 on success 0 on failure ( no changer available ) - 1 on error on autochanger
int autoload_device(DCR *dcr, bool writing, BSOCK *dir)
{
   JCR *jcr = dcr->jcr;
   DEVICE * volatile dev = dcr->dev;
   char *new_vol_name = dcr->VolumeName;
   int slot;
   int drive = dev->drive_index;
   int rtn_stat = -1;                 
   POOLMEM *changer;
   if (!dev->is_autochanger()) {
      Dmsg1(dbglvl, "Device %s is not an autochanger\n", dev->print_name());
      return 0;
   }
   if (dcr->is_virtual_autochanger()) {
      Dmsg0(dbglvl, "ChangerCommand=0, virtual disk changer\n");
      return 1;                       
   }
   slot = dcr->VolCatInfo.InChanger ? dcr->VolCatInfo.Slot : 0;
   if (writing && slot <= 0) {
      if (dir) {
         return 0;                    
      }
      if (dir_find_next_appendable_volume(dcr)) {
         slot = dcr->VolCatInfo.InChanger ? dcr->VolCatInfo.Slot : 0;
      } else {
         slot = 0;
         dev->clear_wait();
      }
   }
   Dmsg4(dbglvl, "Want slot=%d drive=%d InChgr=%d Vol=%s\n",
         dcr->VolCatInfo.Slot, drive,
         dcr->VolCatInfo.InChanger, dcr->getVolCatName());
   changer = get_pool_memory(PM_FNAME);
   if (slot <= 0) {
      if (!dev->poll) {
         Jmsg(jcr, M_INFO, 0, _("No slot defined in catalog (slot=%d) for Volume \"%s\" on %s.\n"),
              slot, dcr->getVolCatName(), dev->print_name());
         Jmsg(jcr, M_INFO, 0, _("Cartridge change or \"update slots\" may be required.\n"));
      }
      rtn_stat = 0;
   } else if (!dcr->device->changer_name) {
      if (!dev->poll) {
         Jmsg(jcr, M_INFO, 0, _("No \"Changer Device\" for %s. Manual load of Volume may be required.\n"),
              dev->print_name());
      }
      rtn_stat = 0;
  } else if (!dcr->device->changer_command) {
      if (!dev->poll) {
         Jmsg(jcr, M_INFO, 0, _("No \"Changer Command\" for %s. Manual load of Volume may be requird.\n"),
              dev->print_name());
      }
      rtn_stat = 0;
  } else {
      uint32_t timeout = dcr->device->max_changer_wait;
      int loaded, status;
      loaded = get_autochanger_loaded_slot(dcr);
      if (loaded < 0) {   
         loaded = get_autochanger_loaded_slot(dcr);
      }
      Dmsg2(dbglvl, "Found loaded=%d drive=%d\n", loaded, drive);
      if (loaded <= 0 || loaded != slot) {
         POOL_MEM results(PM_MESSAGE);
         if (!unload_autochanger(dcr, loaded)) {
            goto bail_out;
         }
         if (!unload_other_drive(dcr, slot, writing)) {
            goto bail_out;
         }
         lock_changer(dcr);
         Dmsg2(dbglvl, "Doing changer load slot %d %s\n", slot, dev->print_name());
         Jmsg(jcr, M_INFO, 0,
            _("3304 Issuing autochanger \"load Volume %s, Slot %d, Drive %d\" command.\n"),
            new_vol_name, slot, drive);
         Dmsg3(dbglvl,
            "3304 Issuing autochanger \"load Volume %s, Slot %d, Drive %d\" command.\n",
            new_vol_name, slot, drive);
         dcr->VolCatInfo.Slot = slot;    
         changer = edit_device_codes(dcr, changer, dcr->device->changer_command, "load");
         dev->close(dcr);
         Dmsg1(dbglvl, "Run program=%s\n", changer);
         status = run_program_full_output(changer, timeout, results.addr());
         if (status == 0) {
            Jmsg(jcr, M_INFO, 0, _("3305 Autochanger \"load Volume %s, Slot %d, Drive %d\", status is OK.\n"),
                    new_vol_name, slot, drive);
            Dmsg3(dbglvl, "OK: load volume %s, slot %d, drive %d.\n", new_vol_name,  slot, drive);
            bstrncpy(dev->LoadedVolName, new_vol_name, sizeof(dev->LoadedVolName));
            dev->set_slot(slot);      
            if (dev->vol) {
               dev->vol->clear_swapping();
            }
         } else {
            berrno be;
            be.set_errno(status);
            Dmsg5(dbglvl, "Error: load Volume %s, Slot %d, Drive %d, bad stats=%s.\nResults=%s\n",
                new_vol_name, slot, drive,
               be.bstrerror(), results.c_str());
            Jmsg(jcr, M_FATAL, 0, _("3992 Bad autochanger \"load Volume %s Slot %d, Drive %d\": "
                 "ERR=%s.\nResults=%s\n"),
                    new_vol_name, slot, drive, be.bstrerror(), results.c_str());
            rtn_stat = -1;            
            dev->clear_slot();        
         }
         unlock_changer(dcr);
      } else {
         status = 0;                  
         dev->set_slot(slot);         
         bstrncpy(dev->LoadedVolName, new_vol_name, sizeof(dev->LoadedVolName));
      }
      Dmsg1(dbglvl, "After changer, status=%d\n", status);
      if (status == 0) {              
         rtn_stat = 1;                
      }
   }
   free_pool_memory(changer);
   return rtn_stat;
bail_out:
   free_pool_memory(changer);
   return -1;
}
int autoload_device ( DCR * dcr , bool writing , BSOCK * dir ) { JCR * jcr = dcr -> jcr ; DEVICE * volatile dev = dcr -> dev ; char * new_vol_name = dcr -> VolumeName ; int slot ; int drive = dev -> drive_index ; int rtn_stat = -1 ; POOLMEM * changer ; if ( ! dev -> is_autochanger ( ) ) { Dmsg1 ( dbglvl , " \n " , dev -> print_name ( ) ) ; return 0 ; } if ( dcr -> is_virtual_autochanger ( ) ) { Dmsg0 ( dbglvl , " \n " ) ; return 1 ; } slot = dcr -> VolCatInfo . InChanger ? dcr -> VolCatInfo . Slot : 0 ; if ( writing && slot <= 0 ) { if ( dir ) { return 0 ; } if ( dir_find_next_appendable_volume ( dcr ) ) { slot = dcr -> VolCatInfo . InChanger ? dcr -> VolCatInfo . Slot : 0 ; } else { slot = 0 ; dev -> clear_wait ( ) ; } } Dmsg4 ( dbglvl , " \n " , dcr -> VolCatInfo . Slot , drive , dcr -> VolCatInfo . InChanger , dcr -> getVolCatName ( ) ) ; changer = get_pool_memory ( PM_FNAME ) ; if ( slot <= 0 ) { if ( ! dev -> poll ) { Jmsg ( jcr , M_INFO , 0 , _ ( " \" \" \n " ) , slot , dcr -> getVolCatName ( ) , dev -> print_name ( ) ) ; Jmsg ( jcr , M_INFO , 0 , _ ( " \" \" \n " ) ) ; } rtn_stat = 0 ; } else if ( ! dcr -> device -> changer_name ) { if ( ! dev -> poll ) { Jmsg ( jcr , M_INFO , 0 , _ ( " \" \" \n " ) , dev -> print_name ( ) ) ; } rtn_stat = 0 ; } else if ( ! dcr -> device -> changer_command ) { if ( ! dev -> poll ) { Jmsg ( jcr , M_INFO , 0 , _ ( " \" \" \n " ) , dev -> print_name ( ) ) ; } rtn_stat = 0 ; } else { uint32_t timeout = dcr -> device -> max_changer_wait ; int loaded , status ; loaded = get_autochanger_loaded_slot ( dcr ) ; if ( loaded < 0 ) { loaded = get_autochanger_loaded_slot ( dcr ) ; } Dmsg2 ( dbglvl , " \n " , loaded , drive ) ; if ( loaded <= 0 || loaded != slot ) { POOL_MEM results ( PM_MESSAGE ) ; if ( ! unload_autochanger ( dcr , loaded ) ) { goto bail_out ; } if ( ! unload_other_drive ( dcr , slot , writing ) ) { goto bail_out ; } lock_changer ( dcr ) ; Dmsg2 ( dbglvl , " \n " , slot , dev -> print_name ( ) ) ; Jmsg ( jcr , M_INFO , 0 , _ ( " \" \" \n " ) , new_vol_name , slot , drive ) ; Dmsg3 ( dbglvl , " \" \" \n " , new_vol_name , slot , drive ) ; dcr -> VolCatInfo . Slot = slot ; changer = edit_device_codes ( dcr , changer , dcr -> device -> changer_command , " " ) ; dev -> close ( dcr ) ; Dmsg1 ( dbglvl , " \n " , changer ) ; status = run_program_full_output ( changer , timeout , results . addr ( ) ) ; if ( status == 0 ) { Jmsg ( jcr , M_INFO , 0 , _ ( " \" \" \n " ) , new_vol_name , slot , drive ) ; Dmsg3 ( dbglvl , " \n " , new_vol_name , slot , drive ) ; bstrncpy ( dev -> LoadedVolName , new_vol_name , sizeof ( dev -> LoadedVolName ) ) ; dev -> set_slot ( slot ) ; if ( dev -> vol ) { dev -> vol -> clear_swapping ( ) ; } } else { berrno be ; be . set_errno ( status ) ; Dmsg5 ( dbglvl , " \n \n " , new_vol_name , slot , drive , be . bstrerror ( ) , results . c_str ( ) ) ; Jmsg ( jcr , M_FATAL , 0 , _ ( " \" \" " " \n \n " ) , new_vol_name , slot , drive , be . bstrerror ( ) , results . c_str ( ) ) ; rtn_stat = -1 ; dev -> clear_slot ( ) ; } unlock_changer ( dcr ) ; } else { status = 0 ; dev -> set_slot ( slot ) ; bstrncpy ( dev -> LoadedVolName , new_vol_name , sizeof ( dev -> LoadedVolName ) ) ; } Dmsg1 ( dbglvl , " \n " , status ) ; if ( status == 0 ) { rtn_stat = 1 ; } } free_pool_memory ( changer ) ; return rtn_stat ; bail_out : free_pool_memory ( changer ) ; return -1 ; }
Called here to do an autoload using the autochanger, if
  configured, and if a Slot has been defined for this Volume.
Called here to do an autoload using the autochanger if configured and if a Slot has been defined for this Volume .
/* error status */ /* An empty ChangerCommand => virtual disk autochanger */ /* nothing to load */ /*
    * Handle autoloaders here.  If we cannot autoload it, we
    *  will return 0 so that the sysop will be asked to load it.
    */ /* For user, bail out right now */ /* ***FIXME*** this really should not be here */ /* Suppress info when polling */ /* Suppress info when polling */ /* Suppress info when polling */ /* Attempt to load the Volume */ /* Autochanger error, try again */ /* Unload anything in our drive */ /* Make sure desired slot is unloaded */ /*
          * Load the desired cassette
          */ /* slot to be loaded */ /* set currently loaded slot */ /* We just swapped this Volume so it cannot be swapping any more */ /* hard error */ /* mark unknown */ /* we got what we want */ /* set currently loaded slot */ /* did we succeed? */ /* tape loaded by changer */