]> git.sur5r.net Git - bacula/bacula/commitdiff
- Rework some of the autochanger data so that the DIR has
authorKern Sibbald <kern@sibbald.com>
Mon, 7 Mar 2005 20:50:51 +0000 (20:50 +0000)
committerKern Sibbald <kern@sibbald.com>
Mon, 7 Mar 2005 20:50:51 +0000 (20:50 +0000)
  the number of drives.
- Modify the way the Device info is returned so that it comes
  back as a special message type and can be sent anytime the
  Device status changes.
- Copy the change name and changer command into the device
  record if none is specified.
- Require the change command and changer name to be specified in
  and AutoChanger resource.
- Force all the Media Type records of all devices in an Autochanger
  to be the same.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1873 91ce42f0-d328-0410-95d8-f526ca767f89

12 files changed:
bacula/kernstodo
bacula/src/dird/dird_conf.h
bacula/src/dird/getmsg.c
bacula/src/dird/msgchan.c
bacula/src/lib/jcr.c
bacula/src/stored/askdir.c
bacula/src/stored/job.c
bacula/src/stored/protos.h
bacula/src/stored/stored.c
bacula/src/stored/stored_conf.c
bacula/src/stored/stored_conf.h
bacula/src/version.h

index 34896383e5928e42681b982fe9158f971ad83121..1e772975d3627532d6e6753f9878498adcbffd01 100644 (file)
@@ -1,5 +1,5 @@
                     Kern's ToDo List
-                     22 February 2005
+                     07 March 2005
 
 Major development:      
 Project                     Developer
@@ -12,64 +12,42 @@ Version 1.37                Kern (see below)
 #3   Migration (Move, Copy, Archive Jobs)
 #4   Embedded Python Scripting 
      (Implemented in Dir/SD)
-#5   Events that call a Python program 
-     (Implemented in Dir/SD)
-#6   Select one from among Multiple Storage Devices for Job
 #7   Single Job Writing to Multiple Storage Devices
 
 ##   Integrate web-bacula into a new Bacula project with
      bimagemgr.
 ##   Consider moving docs to their own project.
 
-Suggestions for Preben:
-- Look at adding Client run command that will use the
-  port opened by the client.
-- Optimized bootstrap.
-
 Autochangers:
-- Fix
-   Please use the "label"  command to create a new Volume for:
-       Storage:      DDS-4-changer
-       Media type:   
-       Pool:         Default
-   label
-   The defined Storage resources are:
-- Copy Changer Device and Changer Command from Autochanger
-  to Device resource in SD if none given in Device resource.
-- 3.Prevent two drives requesting the same Volume in any given
+- 3. Prevent two drives requesting the same Volume in any given
      autochanger.
-- 4. Use Changer Device and Changer Command specified in the
-     Autochanger resource, if none is found in the Device resource.
-    You can continue to specify them in the Device resource if you want
-    or need them to be different for each device.
-- 5. Implement a new Device directive (perhaps "Autoselect = yes/no") 
-    that can allow a Device be part of an Autochanger, and hence the changer
-    script protected, but if set to no, will prevent the Device from being 
-    automatically selected from the changer. This allows the device to
-    be directly accessed through its Device name, but not through the
-    AutoChanger name.
+- 3. Check if a Volume is mounted on another drive in an Autochanger.
 - 7. Implement new Console commands to allow offlining/reserving drives,
      and possibly manipulating the autochanger (much asked for).
 - 8. Automatic updating of Drive status from SD to DIR when something
      changes (Volume, offline, append, read, ...).
-- 9. Check if a Volume is mounted on another drive in an Autochanger.
   
-
-Autochangers Done:
-- 1. Automatic use of more than one drive in an autochanger (done)
-- 2. Automatic selection of the correct drive for each Job (i.e.
-     selects a drive with an appropriate Volume for the Job) (done)
-- 6. Allow multiple simultaneous Jobs referencing the same pool write
-    to several tapes (some new directive(s) are are probably needed for
-    this) (done)
-- Locking (done)
-- Key on Storage rather than Pool (done)
-- Allow multiple drives to use same Pool (change jobq.c DIR) (done).
-- Synchronize multiple drives so that not more
-  than one loads a tape and any time (done)
-
-
 For 1.37:
+- Add disk seeking on restore.  
+- Don't start a second file job if one is already running.
+- Add Python writable variable for changing the Priority,
+    Client, Storage, JobStatus (error), ...
+- SD Python
+  - Solicit Events
+- FD Python
+  - Python script to save with Python, not save, save with Bacula.
+  - Python script to do backup.
+- When Python creates a new label, the tape is immediately
+  recycled and no label created. This happens when using   
+  autolabeling -- even when Python doesn't generate the name.
+- Create a new GUI chapter explaining all the GUI programs.
+- Look at Preben's acl.c error handling code.
+- Look at adding full Volume and Pool information to a Volume 
+  label so that bscan can get *all* the info. 
+- Scratch Pool where the volumes can be re-assigned to any Pool.
+- Implement Maximum Job Spool Size
+
+Maybe in 1.37:
 - By the way: on page http://www.bacula.org/?page=tapedrives , at the 
   bottom, the link to "Tape Testing Chapter" is broken. It goes to 
   /html-manual/... while the others point to /rel-manual/...
@@ -88,18 +66,7 @@ For 1.37:
   a small reference.
 - Linux Sony LIB-D81, AIT-3 library works.
 - Device resource needs the "name" of the SD.
-- Add and option to see if the file size changed
-  during backup.
-- Implement "update device" from SD so that DIR will
-  always have current version of device.
-- Add disk seeking on restore.  
-- Add Python writable variable for changing the Priority,
-    Client, Storage, JobStatus (error), ...
-- SD Python
-  - Solicit Events
-- FD Python
-  - Python script to save with Python, not save, save with Bacula.
-  - Python script to do backup.
+- Add and option to see if the file size changed during backup.
 - Windows restore:
   data-fd: RestoreFiles.2004-12-07_15.56.42 Error:
   > ..\findlib\../../findlib/create_file.c:275 Could not open e:/: ERR=Der
@@ -113,17 +80,10 @@ For 1.37:
   and fix SD messages.
 - Make sure SD deletes spool files on error exit.
 - Delete old spool files when SD starts.
-- When Python creates a new label, the tape is immediately
-  recycled and no label created. This happens when using   
-  autolabeling -- even when Python doesn't generate the name.
 - Add a restore directory-x
 - When labeling tapes, if you enter 000026, Bacula uses
   the tape index rather than the Volume name 000026.
 - Max Vols limit in Pool off by one?
-- Look at Preben's acl.c error handling code.
-- See multiple-store.txt for Multiple Storage implementation
-  design.
-- Create a new GUI chapter explaining all the GUI programs.
 - Tell the "restore" user when browsing is no longer possible.
 - Require restore via the restore command or make a restore Job
   get the bootstrap file.
@@ -131,9 +91,6 @@ For 1.37:
 - Add offline tape command to Bacula console.
 - Document that Bootstrap files can be written with cataloging
   turned off.
-- Look at adding full Volume and Pool information to a Volume 
-  label so that bscan can get *all* the info. 
-- Scratch Pool where the volumes can be re-assigned to any Pool.
 - Upgrade to MySQL 4.1.1 See:  
   http://dev.mysql.com/doc/mysql/en/Server_SQL_mode.html
 - Add client version to the Client name line that prints in
@@ -203,24 +160,6 @@ Notes:
   list, also it is maybe a good idea to check for the return value and
   execute different actions based on the return value
 
-2. Priorities also for the Schedule Resource
-
-    Why:
-
-    With this it is possible to run monthly jobs at the end of the month
-    instead of the beginning of the next month, so one could define
-    weekly and monthly pools to be run on Fridays and if there are
-    2 Jobs resulting on the same time, the one with the higher priority
-    takes precedence. This is also helpfull to implement a daily
-    rotation scheme with an additional 2 weeks changing weekly pool
-
-Example:
-         Schedule {
-           Name = "NightlyBackup"
-           Run = Priority = 1,Pool=Weekly friday at 21:00
-           Run = Priority = 2,Pool=Weekly monthly on friday at 21:00
-           Run = Priority = 3,Pool=Weekly yearly on friday at 21:00
-           }
 
 3. offline capability to bconsole
 
@@ -280,7 +219,6 @@ Why:
 ==========
 - Can one write tapes faster with 8192 byte block sizes?
 - Specify a single directory to restore.
-- Implement Maximum Job Spool Size
 - Document security problems with the same password for everyone in
   rpm and Win32 releases.
 - Browse generations of files.
@@ -1283,3 +1221,38 @@ Block Position: 0
 - Bootstrap from JobMedia records.
 - Implement WildFile and WildDir to solve problem of 
   saving only *.doc files.
+- Fix
+   Please use the "label"  command to create a new Volume for:
+       Storage:      DDS-4-changer
+       Media type:   
+       Pool:         Default
+   label
+   The defined Storage resources are:
+- Copy Changer Device and Changer Command from Autochanger
+  to Device resource in SD if none given in Device resource.
+- 1. Automatic use of more than one drive in an autochanger (done)
+- 2. Automatic selection of the correct drive for each Job (i.e.
+     selects a drive with an appropriate Volume for the Job) (done)
+- 6. Allow multiple simultaneous Jobs referencing the same pool write
+    to several tapes (some new directive(s) are are probably needed for
+    this) (done)
+- Locking (done)
+- Key on Storage rather than Pool (done)
+- Allow multiple drives to use same Pool (change jobq.c DIR) (done).
+- Synchronize multiple drives so that not more
+  than one loads a tape and any time (done)
+- 4. Use Changer Device and Changer Command specified in the
+     Autochanger resource, if none is found in the Device resource.
+    You can continue to specify them in the Device resource if you want
+    or need them to be different for each device.
+- 5. Implement a new Device directive (perhaps "Autoselect = yes/no") 
+    that can allow a Device be part of an Autochanger, and hence the changer
+    script protected, but if set to no, will prevent the Device from being 
+    automatically selected from the changer. This allows the device to
+    be directly accessed through its Device name, but not through the
+    AutoChanger name.
+#6   Select one from among Multiple Storage Devices for Job
+#5   Events that call a Python program 
+     (Implemented in Dir/SD)
+- Make sure the Device name is in the Query packet returned.
+
index 03b14f2d81d271f8956259b4650a80ed03a220d5..ab4e8d1561fa531b8b993dccd55c43e795bb652b 100644 (file)
@@ -127,11 +127,12 @@ public:
    int num_writers;
    int max_writers;                   /* = 1 for files */
    int reserved;                      /* number of reserves */
+   int num_drives;                    /* for autochanger */
+   bool autochanger;                  /* set if device is autochanger */
    bool open;
    bool append;                       /* in append mode */
    bool read;
    bool labeled;
-   bool autochanger;
    bool offline;
    bool autoselect;
    uint32_t PoolId;
index 79a63117229d4711d2f16e83e59da959bfcabed2..ae961f30118935a47d931b502bd14d53325f606c 100644 (file)
 static char *find_msg_start(char *msg);
 
 static char Job_status[] = "Status Job=%127s JobStatus=%d\n";
+static char Device_update[]   = "DevUpd Job=%127s "
+   "device=%127s "
+   "append=%d read=%d num_writers=%d "
+   "open=%d labeled=%d offline=%d "
+   "reserved=%d max_writers=%d "
+   "autoselect=%d autochanger=%d "
+   "poolid=%lld "
+   "changer_name=%127s media_type=%127s volume_name=%127s\n";
 
 
 static char OK_msg[] = "1000 OK\n";
@@ -63,8 +71,18 @@ static char OK_msg[] = "1000 OK\n";
  *  to the appropriate handler.  If the message is
  *  in any other format, it will be returned.
  *
- *  E.g. any message beginning with a digit will be returned.
- *      any message beginning with Jmsg will be processed.
+ *  E.g. any message beginning with a digit will be passed   
+ *      through to the caller.
+ *  All other messages are expected begin with some identifier
+ *    -- for the moment only the first character is checked, but
+ *    at a later time, the whole identifier (e.g. Jmsg, CatReq, ...)
+ *    could be checked. This is followed by Job=Jobname <user-defined>
+ *    info. The identifier is used to dispatch the message to the right
+ *    place (Job message, catalog request, ...). The Job is used to lookup
+ *    the JCR so that the action is performed on the correct jcr, and
+ *    the rest of the message is up to the user.  Note, DevUpd uses
+ *    *System* for the Job name, and hence no JCR is obtained. This   
+ *    is a *rare* case where a jcr is not really needed.
  *
  */
 int bget_dirmsg(BSOCK *bs)
@@ -134,7 +152,9 @@ int bget_dirmsg(BSOCK *bs)
          Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
         continue;
       }
-      if (!(jcr=get_jcr_by_full_name(Job))) {
+      if (strcmp(Job, "*System*") == 0) {
+        jcr = NULL;                  /* No jcr */
+      } else if (!(jcr=get_jcr_by_full_name(Job))) {
          Emsg1(M_ERROR, 0, _("Job not found: %s\n"), bs->msg);
         continue;
       }
@@ -200,9 +220,61 @@ int bget_dirmsg(BSOCK *bs)
         char Job[MAX_NAME_LENGTH];
         if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) {
            jcr->SDJobStatus = JobStatus; /* current status */
-           free_jcr(jcr);
-           continue;
+        } else {
+            Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
         }
+        free_jcr(jcr);
+        continue;
+      }
+      /* No JCR for Device Updates! */
+      if (bs->msg[0] = 'D') {         /* Device update */
+        DEVICE *dev;
+        POOL_MEM dev_name, changer_name, media_type, volume_name;
+        int dev_open, dev_append, dev_read, dev_labeled;
+        int dev_offline, dev_autochanger, dev_autoselect;
+        int dev_num_writers, dev_max_writers, dev_reserved;
+        uint64_t dev_PoolId;
+         Dmsg1(100, "<stored: %s", bs->msg);
+        if (sscanf(bs->msg, Device_update,
+            &Job, dev_name.c_str(),
+            &dev_append, &dev_read,
+            &dev_num_writers, &dev_open,
+            &dev_labeled, &dev_offline, &dev_reserved,
+            &dev_max_writers, &dev_autoselect, 
+            &dev_autochanger, &dev_PoolId,
+            changer_name.c_str(), media_type.c_str(),
+            volume_name.c_str()) != 16) {
+            Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
+        } else {
+           unbash_spaces(dev_name);
+           dev = (DEVICE *)GetResWithName(R_DEVICE, dev_name.c_str());
+           if (!dev) {
+              continue;
+           }
+           unbash_spaces(changer_name);
+           unbash_spaces(media_type);
+           unbash_spaces(volume_name);
+           bstrncpy(dev->ChangerName, changer_name.c_str(), sizeof(dev->ChangerName));
+           bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType));
+           bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName));
+           /* Note, these are copied because they are boolean rather than
+            *  integer.
+            */
+           dev->open = dev_open;
+           dev->append = dev_append;
+           dev->read = dev_read;
+           dev->labeled = dev_labeled;
+           dev->offline = dev_offline;
+           dev->autoselect = dev_autoselect;
+           dev->autochanger = dev_autochanger > 0;
+           dev->num_drives = dev_autochanger;    /* does double duty */
+           dev->PoolId = dev_PoolId;
+           dev->num_writers = dev_num_writers;
+           dev->max_writers = dev_max_writers;
+           dev->reserved = dev_reserved;
+           dev->found = true;
+        }
+        continue;
       }
       return n;
    }
index 1c49dfc1224d78d5cdedc08892a3287089159a08..233b30fbc1c02a82a3ee312add799ef7eeb8d7e8 100644 (file)
@@ -49,13 +49,6 @@ static char query_device[] = "query device=%s";
 /* Response from Storage daemon */
 static char OKjob[]      = "3000 OK Job SDid=%d SDtime=%d Authorization=%100s\n";
 static char OK_device[]  = "3000 OK use device device=%s\n";
-static char OK_query[]   = "3001 OK query "
-   "append=%d read=%d num_writers=%d "
-   "open=%d labeled=%d offline=%d "
-   "reserved=%d max_writers=%d "
-   "autoselect=%d autochanger=%d "
-   "poolid=%lld "
-   "changer_name=%127s media_type=%127s volume_name=%127s";
 
 /* Storage Daemon requests */
 static char Job_start[]  = "3010 Job %127s start\n";
@@ -108,9 +101,7 @@ bool connect_to_storage_daemon(JCR *jcr, int retry_interval,
  */
 bool update_device_res(JCR *jcr, DEVICE *dev)
 {
-   POOL_MEM device_name, changer_name, media_type, volume_name;
-   int dev_open, dev_append, dev_read, dev_labeled;
-   int dev_offline, dev_autochanger, dev_autoselect;
+   POOL_MEM device_name; 
    BSOCK *sd;
    if (!connect_to_storage_daemon(jcr, 5, 30, 0)) {
       return false;
@@ -120,36 +111,8 @@ bool update_device_res(JCR *jcr, DEVICE *dev)
    bash_spaces(device_name);
    bnet_fsend(sd, query_device, device_name.c_str());
    Dmsg1(100, ">stored: %s\n", sd->msg);
-   if (bget_dirmsg(sd) > 0) {
-      Dmsg1(100, "<stored: %s", sd->msg);
-      if (sscanf(sd->msg, OK_query, 
-         &dev_append, &dev_read,
-         &dev->num_writers, &dev_open,
-         &dev_labeled, &dev_offline, &dev->reserved,
-         &dev->max_writers, &dev_autoselect, 
-         &dev_autochanger,  &dev->PoolId,
-         changer_name.c_str(), media_type.c_str(),
-         volume_name.c_str()) != 14) {
-        return false;
-      }
-      unbash_spaces(changer_name);
-      unbash_spaces(media_type);
-      unbash_spaces(volume_name);
-      bstrncpy(dev->ChangerName, changer_name.c_str(), sizeof(dev->ChangerName));
-      bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType));
-      bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName));
-      /* Note, these are copied because they are boolean rather than
-       *  integer.
-       */
-      dev->open = dev_open;
-      dev->append = dev_append;
-      dev->read = dev_read;
-      dev->labeled = dev_labeled;
-      dev->offline = dev_offline;
-      dev->autoselect = dev_autoselect;
-      dev->autochanger = dev_autochanger;
-      dev->found = true;
-   } else {
+   /* The data is returned through Device_update */
+   if (bget_dirmsg(sd) <= 0) {
       return false;
    }
    return true;
index 6b95c321678d74bd7066873198f1d4f763c11320..01b8c85bffe8ea9ff3749a2f4b9dc56817c3423a 100755 (executable)
@@ -204,7 +204,7 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr)
    jcr->errmsg = get_pool_memory(PM_MESSAGE);
    jcr->errmsg[0] = 0;
    /* Setup some dummy values */
-   jcr->Job[0] = 0;                  /* no job name by default */
+   bstrncpy(jcr->Job, "*System*", sizeof(jcr->Job));
    jcr->JobId = 0;
    jcr->JobType = JT_SYSTEM;         /* internal job until defined */
    jcr->JobLevel = L_NONE;
index 461b60b96ab8aa6571ff31e0d2432c95a73b1671..6d7465c482a09d6c076a6e7c8babd7af75e5e344 100644 (file)
@@ -42,6 +42,14 @@ static char Create_job_media[] = "CatReq Job=%s CreateJobMedia"
    " StartBlock=%u EndBlock=%u\n";
 static char FileAttributes[] = "UpdCat Job=%s FileAttributes ";
 static char Job_status[]     = "Status Job=%s JobStatus=%d\n";
+static char Device_update[] = "DevUpd Job=%s device=%s "
+   "append=%d read=%d num_writers=%d "
+   "open=%d labeled=%d offline=%d "
+   "reserved=%d max_writers=%d "
+   "autoselect=%d autochanger=%d "
+   "poolid=%s "
+   "changer_name=%s media_type=%s volume_name=%s\n";
+
 
 
 /* Responses received from the Director */
@@ -58,6 +66,76 @@ static char OK_create[] = "1000 OK CreateJobMedia\n";
 /* Forward referenced functions */
 static int wait_for_sysop(DCR *dcr);
 
+/* Send update information about a device to Director */
+bool dir_update_device(JCR *jcr, DEVICE *dev)
+{
+   BSOCK *dir = jcr->dir_bsock;
+   POOL_MEM dev_name, VolumeName, MediaType, ChangerName;
+   DEVRES *device = dev->device;
+   bool ok;
+   char ed1[50];
+   
+   pm_strcpy(dev_name, device->hdr.name);
+   bash_spaces(dev_name);
+   if (dev->is_labeled()) {
+      pm_strcpy(VolumeName, dev->VolHdr.VolName);
+   } else {
+      pm_strcpy(VolumeName, "*");
+   }
+   bash_spaces(VolumeName);
+   pm_strcpy(MediaType, device->media_type);
+   bash_spaces(MediaType);
+   if (device->changer_res) {
+      pm_strcpy(ChangerName, device->changer_res->hdr.name);
+      bash_spaces(ChangerName);
+   } else {
+      pm_strcpy(ChangerName, "*");
+   }
+   ok =bnet_fsend(dir, Device_update, 
+      jcr->Job,
+      dev_name.c_str(),
+      dev->can_append()!=0,
+      dev->can_read()!=0, dev->num_writers, 
+      dev->is_open()!=0, dev->is_labeled()!=0,
+      dev->is_offline()!=0, dev->reserved_device, 
+      dev->is_tape()?100000:1,
+      dev->autoselect, 0, 
+      edit_uint64(dev->PoolId, ed1),
+      ChangerName.c_str(), MediaType.c_str(), VolumeName.c_str());
+   Dmsg1(100, ">dird: %s\n", dir->msg);
+   return ok;
+}
+
+bool dir_update_changer(JCR *jcr, AUTOCHANGER *changer)
+{
+   BSOCK *dir = jcr->dir_bsock;
+   POOL_MEM dev_name, MediaType;
+   DEVRES *device;
+   bool ok;
+
+   pm_strcpy(dev_name, changer->hdr.name);
+   bash_spaces(dev_name);
+   device = (DEVRES *)changer->device->first();
+   pm_strcpy(MediaType, device->media_type);
+   bash_spaces(MediaType);
+   /* This is mostly to indicate that we are here */
+   ok = bnet_fsend(dir, Device_update,
+      jcr->Job,
+      dev_name.c_str(),        /* Changer name */
+      0, 0, 0,                 /* append, read, num_writers */
+      0, 0, 0,                 /* is_open, is_labeled, offline */
+      0, 0,                    /* reserved, max_writers */
+      0,                       /* Autoselect */
+      changer->device->size(), /* Number of devices */
+      "0",                      /* PoolId */
+      "*",                      /* ChangerName */
+      MediaType.c_str(),       /* MediaType */
+      "*");                     /* VolName */
+   Dmsg1(100, ">dird: %s\n", dir->msg);
+   return ok;
+}
+
+
 /*
  * Send current JobStatus to Director
  */
index a99dbb7b4073e1917982cc1151c8a817e593ecae..a6600c2ab16a2ef6282af8642a0262920b65a1f5 100644 (file)
@@ -54,14 +54,9 @@ static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
 static char NOT_open[]  = "3925 Device \"%s\" could not be opened or does not exist.\n";
 static char BAD_use[]   = "3913 Bad use command: %s\n";
 static char BAD_job[]   = "3915 Bad Job command: %s\n";
-static char OK_query[]  = "3001 OK query "
-   "append=%d read=%d num_writers=%d "
-   "open=%d labeled=%d offline=%d "
-   "reserved=%d max_writers=%d "
-   "autoselect=%d autochanger=%d "
-   "poolid=%s "
-   "changer_name=%s media_type=%s volume_name=%s";
-static char BAD_query[]   = "3917 Bad query command: %s\n";
+static char OK_query[]  = "3001 OK query\n";
+static char NO_query[]  = "3918 Query failed\n";
+static char BAD_query[] = "3917 Bad query command: %s\n";
 
 /*
  * Director requests us to start a job
@@ -425,12 +420,11 @@ static bool use_device_cmd(JCR *jcr)
  */
 bool query_cmd(JCR *jcr)
 {
-   POOL_MEM dev_name;             
+   POOL_MEM dev_name, VolumeName, MediaType, ChangerName;
    BSOCK *dir = jcr->dir_bsock;
    DEVRES *device;
    AUTOCHANGER *changer;
    bool ok;
-   char ed1[50];
 
    Dmsg1(100, "Query_cmd: %s", dir->msg);
    ok = sscanf(dir->msg, query_device, dev_name.c_str()) == 1;
@@ -447,33 +441,13 @@ bool query_cmd(JCR *jcr)
            if (!device->dev) {
               break;
            }  
-           DEVICE *dev = device->dev;
-           POOL_MEM VolumeName, MediaType, ChangerName;
            UnlockRes();
-           if (dev->is_labeled()) {
-              pm_strcpy(VolumeName, dev->VolHdr.VolName);
+           ok = dir_update_device(jcr, device->dev);
+           if (ok) {
+              ok = bnet_fsend(dir, OK_query);
            } else {
-               pm_strcpy(VolumeName, "*");
+              bnet_fsend(dir, NO_query);
            }
-           bash_spaces(VolumeName);
-           pm_strcpy(MediaType, device->media_type);
-           bash_spaces(MediaType);
-           if (device->changer_res) {
-              pm_strcpy(ChangerName, device->changer_res->hdr.name);
-              bash_spaces(ChangerName);
-           } else {
-               pm_strcpy(ChangerName, "*");
-           }
-           ok =bnet_fsend(dir, OK_query, 
-              dev->can_append()!=0,
-              dev->can_read()!=0, dev->num_writers, 
-              dev->is_open()!=0, dev->is_labeled()!=0,
-              dev->is_offline()!=0, dev->reserved_device, 
-              dev->is_tape()?100000:1,
-              dev->autoselect, 0, 
-              edit_uint64(dev->PoolId, ed1),
-              ChangerName.c_str(), MediaType.c_str(), VolumeName.c_str());
-            Dmsg1(100, ">dird: %s\n", dir->msg);
            return ok;
         }
       }
@@ -481,15 +455,15 @@ bool query_cmd(JCR *jcr)
         /* Find resource, and make sure we were able to open it */
         if (fnmatch(dev_name.c_str(), changer->hdr.name, 0) == 0) {
            UnlockRes();
-           /* This is mostly to indicate that we are here */
-           ok = bnet_fsend(dir, OK_query, 
-              0, 0, 0,                  /* append, read, num_writers */
-              0, 0, 0,                  /* is_open, is_labeled, offline */
-              0, 0,                     /* reserved, max_writers */
-              0, 1,                     /* autoselect, AutoChanger = 1 */   
-               "0",                      /* PoolId */
-               "*", "*", "*");           /* ChangerName, MediaType, VolName */
-            Dmsg1(100, ">dird: %s\n", dir->msg);
+           if (!changer->device || changer->device->size() == 0) {
+              continue;              /* no devices */
+           }
+           ok = dir_update_changer(jcr, changer);
+           if (ok) {
+              ok = bnet_fsend(dir, OK_query);
+           } else {
+              bnet_fsend(dir, NO_query);
+           }
            return ok;
         }
       }
index 00c1379fb3c084ec9b89ff164a65e7eac69f1683..820fda9bd0b4f3737a9e8ce8bd13a682fb581f41 100644 (file)
 uint32_t new_VolSessionId();
 
 /* From acquire.c */
-bool     reserve_device_for_append(JCR *jcr, DEVICE *dev);
-DCR     *acquire_device_for_append(JCR *jcr, DEVICE *dev);
-bool     reserve_device_for_read(JCR *jcr, DEVICE *dev);
-DCR     *acquire_device_for_read(JCR *jcr, DEVICE *dev);
-bool     release_device(DCR *dcr);
-DCR     *new_dcr(JCR *jcr, DEVICE *dev);
-void     free_dcr(DCR *dcr);
+bool    reserve_device_for_append(JCR *jcr, DEVICE *dev);
+DCR    *acquire_device_for_append(JCR *jcr, DEVICE *dev);
+bool    reserve_device_for_read(JCR *jcr, DEVICE *dev);
+DCR    *acquire_device_for_read(JCR *jcr, DEVICE *dev);
+bool    release_device(DCR *dcr);
+DCR    *new_dcr(JCR *jcr, DEVICE *dev);
+void    free_dcr(DCR *dcr);
 
 /* From askdir.c */
 enum get_vol_info_rw {
    GET_VOL_INFO_FOR_WRITE,
    GET_VOL_INFO_FOR_READ
 };
-bool    dir_get_volume_info(DCR *dcr, enum get_vol_info_rw);
-bool    dir_find_next_appendable_volume(DCR *dcr);
-bool    dir_update_volume_info(DCR *dcr, bool label);
-bool    dir_ask_sysop_to_create_appendable_volume(DCR *dcr);
-bool    dir_ask_sysop_to_mount_volume(DCR *dcr);
-bool    dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec);
-bool    dir_send_job_status(JCR *jcr);
-bool    dir_create_jobmedia_record(DCR *dcr);
+bool   dir_get_volume_info(DCR *dcr, enum get_vol_info_rw);
+bool   dir_find_next_appendable_volume(DCR *dcr);
+bool   dir_update_volume_info(DCR *dcr, bool label);
+bool   dir_ask_sysop_to_create_appendable_volume(DCR *dcr);
+bool   dir_ask_sysop_to_mount_volume(DCR *dcr);
+bool   dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec);
+bool   dir_send_job_status(JCR *jcr);
+bool   dir_create_jobmedia_record(DCR *dcr);
+bool   dir_update_device(JCR *jcr, DEVICE *dev);
+bool   dir_update_changer(JCR *jcr, AUTOCHANGER *changer);
 
 /* authenticate.c */
-int     authenticate_director(JCR *jcr);
-int     authenticate_filed(JCR *jcr);
+int    authenticate_director(JCR *jcr);
+int    authenticate_filed(JCR *jcr);
 
 /* From autochanger.c */
-int      autoload_device(DCR *dcr, int writing, BSOCK *dir);
-bool     autochanger_list(DCR *dcr, BSOCK *dir);
-void     mark_volume_not_inchanger(DCR *dcr);
-char    *edit_device_codes(DCR *dcr, char *omsg, const char *cmd);
+int     autoload_device(DCR *dcr, int writing, BSOCK *dir);
+bool    autochanger_list(DCR *dcr, BSOCK *dir);
+void    mark_volume_not_inchanger(DCR *dcr);
+char   *edit_device_codes(DCR *dcr, char *omsg, const char *cmd);
 
 /* From block.c */
-void    dump_block(DEV_BLOCK *b, const char *msg);
+void   dump_block(DEV_BLOCK *b, const char *msg);
 DEV_BLOCK *new_block(DEVICE *dev);
 DEV_BLOCK *dup_block(DEV_BLOCK *eblock);
-void    init_block_write(DEV_BLOCK *block);
-void    empty_block(DEV_BLOCK *block);
-void    free_block(DEV_BLOCK *block);
-bool    write_block_to_device(DCR *dcr);
-bool    write_block_to_dev(DCR *dcr);
-void    print_block_read_errors(JCR *jcr, DEV_BLOCK *block);
-void    ser_block_header(DEV_BLOCK *block);
+void   init_block_write(DEV_BLOCK *block);
+void   empty_block(DEV_BLOCK *block);
+void   free_block(DEV_BLOCK *block);
+bool   write_block_to_device(DCR *dcr);
+bool   write_block_to_dev(DCR *dcr);
+void   print_block_read_errors(JCR *jcr, DEV_BLOCK *block);
+void   ser_block_header(DEV_BLOCK *block);
 
 #define CHECK_BLOCK_NUMBERS    true
 #define NO_BLOCK_NUMBER_CHECK  false
-bool    read_block_from_device(DCR *dcr, bool check_block_numbers);
-bool    read_block_from_dev(DCR *dcr, bool check_block_numbers);
+bool   read_block_from_device(DCR *dcr, bool check_block_numbers);
+bool   read_block_from_dev(DCR *dcr, bool check_block_numbers);
 
 /* From butil.c -- utilities for SD tool programs */
-void    print_ls_output(const char *fname, const char *link, int type, struct stat *statp);
+void   print_ls_output(const char *fname, const char *link, int type, struct stat *statp);
 JCR    *setup_jcr(const char *name, char *dev_name, BSR *bsr,
-                  const char *VolumeName, int mode);
-void    display_tape_error_status(JCR *jcr, DEVICE *dev);
+                 const char *VolumeName, int mode);
+void   display_tape_error_status(JCR *jcr, DEVICE *dev);
 
 
 /* From dev.c */
-DEVICE  *init_dev(JCR *jcr, DEVICE *dev, DEVRES *device);
-int      open_dev(DEVICE *dev, char *VolName, int mode);
-off_t    lseek_dev(DEVICE *dev, off_t offset, int whence);
-int      open_first_part(DEVICE *dev);
-int      open_next_part(DEVICE *dev);
-int      open_guess_name_dev(DEVICE *dev);
-void     close_dev(DEVICE *dev);
-void     force_close_dev(DEVICE *dev);
-bool     truncate_dev(DEVICE *dev);
-void     term_dev(DEVICE *dev);
-char *   strerror_dev(DEVICE *dev);
-void     clrerror_dev(DEVICE *dev, int func);
-bool     update_pos_dev(DEVICE *dev);
-bool     rewind_dev(DEVICE *dev);
-bool     load_dev(DEVICE *dev);
-bool     offline_dev(DEVICE *dev);
-int      flush_dev(DEVICE *dev);
-int      weof_dev(DEVICE *dev, int num);
-int      write_block(DEVICE *dev);
+DEVICE *init_dev(JCR *jcr, DEVICE *dev, DEVRES *device);
+int     open_dev(DEVICE *dev, char *VolName, int mode);
+off_t   lseek_dev(DEVICE *dev, off_t offset, int whence);
+int     open_first_part(DEVICE *dev);
+int     open_next_part(DEVICE *dev);
+int     open_guess_name_dev(DEVICE *dev);
+void    close_dev(DEVICE *dev);
+void    force_close_dev(DEVICE *dev);
+bool    truncate_dev(DEVICE *dev);
+void    term_dev(DEVICE *dev);
+char *  strerror_dev(DEVICE *dev);
+void    clrerror_dev(DEVICE *dev, int func);
+bool    update_pos_dev(DEVICE *dev);
+bool    rewind_dev(DEVICE *dev);
+bool    load_dev(DEVICE *dev);
+bool    offline_dev(DEVICE *dev);
+int     flush_dev(DEVICE *dev);
+int     weof_dev(DEVICE *dev, int num);
+int     write_block(DEVICE *dev);
 uint32_t status_dev(DEVICE *dev);
-int      eod_dev(DEVICE *dev);
-bool     fsf_dev(DEVICE *dev, int num);
-bool     fsr_dev(DEVICE *dev, int num);
-bool     bsf_dev(DEVICE *dev, int num);
-bool     bsr_dev(DEVICE *dev, int num);
-void     attach_jcr_to_device(DEVICE *dev, JCR *jcr);
-void     detach_jcr_from_device(DEVICE *dev, JCR *jcr);
-JCR     *next_attached_jcr(DEVICE *dev, JCR *jcr);
-bool     dev_can_write(DEVICE *dev);
-bool     offline_or_rewind_dev(DEVICE *dev);
-bool     reposition_dev(DEVICE *dev, uint32_t file, uint32_t block);
-void     init_dev_wait_timers(DEVICE *dev);
-bool     double_dev_wait_time(DEVICE *dev);
+int     eod_dev(DEVICE *dev);
+bool    fsf_dev(DEVICE *dev, int num);
+bool    fsr_dev(DEVICE *dev, int num);
+bool    bsf_dev(DEVICE *dev, int num);
+bool    bsr_dev(DEVICE *dev, int num);
+void    attach_jcr_to_device(DEVICE *dev, JCR *jcr);
+void    detach_jcr_from_device(DEVICE *dev, JCR *jcr);
+JCR    *next_attached_jcr(DEVICE *dev, JCR *jcr);
+bool    dev_can_write(DEVICE *dev);
+bool    offline_or_rewind_dev(DEVICE *dev);
+bool    reposition_dev(DEVICE *dev, uint32_t file, uint32_t block);
+void    init_dev_wait_timers(DEVICE *dev);
+bool    double_dev_wait_time(DEVICE *dev);
 
 /* Get info about device */
-char *   dev_name(DEVICE *dev);
-char *   dev_vol_name(DEVICE *dev);
+char *  dev_name(DEVICE *dev);
+char *  dev_vol_name(DEVICE *dev);
 uint32_t dev_block(DEVICE *dev);
 uint32_t dev_file(DEVICE *dev);
-bool     dev_is_tape(DEVICE *dev);
+bool    dev_is_tape(DEVICE *dev);
 
 /* From device.c */
-bool     open_device(DCR *dcr);
-bool     first_open_device(DEVICE *dev);
-bool     fixup_device_block_write_error(DCR *dcr);
-void     _lock_device(const char *file, int line, DEVICE *dev);
-void     _unlock_device(const char *file, int line, DEVICE *dev);
-void     _block_device(const char *file, int line, DEVICE *dev, int state);
-void     _unblock_device(const char *file, int line, DEVICE *dev);
-void     _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state);
-void     _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold);
-void     set_new_volume_parameters(DCR *dcr);
-void     set_new_file_parameters(DCR *dcr);
-bool     device_is_unmounted(DEVICE *dev);
-void     dev_lock(DEVICE *dev);
-void     dev_unlock(DEVICE *dev);
+bool    open_device(DCR *dcr);
+bool    first_open_device(DEVICE *dev);
+bool    fixup_device_block_write_error(DCR *dcr);
+void    _lock_device(const char *file, int line, DEVICE *dev);
+void    _unlock_device(const char *file, int line, DEVICE *dev);
+void    _block_device(const char *file, int line, DEVICE *dev, int state);
+void    _unblock_device(const char *file, int line, DEVICE *dev);
+void    _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state);
+void    _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold);
+void    set_new_volume_parameters(DCR *dcr);
+void    set_new_file_parameters(DCR *dcr);
+bool    device_is_unmounted(DEVICE *dev);
+void    dev_lock(DEVICE *dev);
+void    dev_unlock(DEVICE *dev);
 const char *edit_blocked_reason(DEVICE *dev);
 
 /* From dircmd.c */
-void     *handle_connection_request(void *arg);
+void    *handle_connection_request(void *arg);
 
 
 /* From fd_cmds.c */
-void     run_job(JCR *jcr);
-bool     bootstrap_cmd(JCR *jcr);
+void    run_job(JCR *jcr);
+bool    bootstrap_cmd(JCR *jcr);
 
 /* From job.c */
-void     stored_free_jcr(JCR *jcr);
-void     connection_from_filed(void *arg);
-void     handle_filed_connection(BSOCK *fd, char *job_name);
+void    stored_free_jcr(JCR *jcr);
+void    connection_from_filed(void *arg);
+void    handle_filed_connection(BSOCK *fd, char *job_name);
 
 /* From label.c */
-int      read_dev_volume_label(DCR *dcr);
-int      read_dev_volume_label_guess(DCR *dcr, bool write);
-void     create_session_label(DCR *dcr, DEV_RECORD *rec, int label);
-void     create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName);
-bool     write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName);
-bool     write_ansi_ibm_label(DCR *dcr, const char *VolName);
-int      read_ansi_ibm_label(DCR *dcr);
-bool     write_session_label(DCR *dcr, int label);
-bool     write_volume_label_to_block(DCR *dcr);
-bool     rewrite_volume_label(DCR *dcr, bool recycle);
-void     dump_volume_label(DEVICE *dev);
-void     dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
-bool     unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
-bool     unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
+int     read_dev_volume_label(DCR *dcr);
+int     read_dev_volume_label_guess(DCR *dcr, bool write);
+void    create_session_label(DCR *dcr, DEV_RECORD *rec, int label);
+void    create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName);
+bool    write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName);
+bool    write_ansi_ibm_label(DCR *dcr, const char *VolName);
+int     read_ansi_ibm_label(DCR *dcr);
+bool    write_session_label(DCR *dcr, int label);
+bool    write_volume_label_to_block(DCR *dcr);
+bool    rewrite_volume_label(DCR *dcr, bool recycle);
+void    dump_volume_label(DEVICE *dev);
+void    dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
+bool    unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
+bool    unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
 
 /* From match_bsr.c */
-int      match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec,
-              SESSION_LABEL *sesrec);
-int      match_bsr_block(BSR *bsr, DEV_BLOCK *block);
-void     position_bsr_block(BSR *bsr, DEV_BLOCK *block);
-BSR     *find_next_bsr(BSR *root_bsr, DEVICE *dev);
-bool     match_set_eof(BSR *bsr, DEV_RECORD *rec);
+int     match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec,
+             SESSION_LABEL *sesrec);
+int     match_bsr_block(BSR *bsr, DEV_BLOCK *block);
+void    position_bsr_block(BSR *bsr, DEV_BLOCK *block);
+BSR    *find_next_bsr(BSR *root_bsr, DEVICE *dev);
+bool    match_set_eof(BSR *bsr, DEV_RECORD *rec);
 
 /* From mount.c */
-bool     mount_next_write_volume(DCR *dcr, bool release);
-bool     mount_next_read_volume(DCR *dcr);
-void     release_volume(DCR *ddr);
-void     mark_volume_in_error(DCR *dcr);
+bool    mount_next_write_volume(DCR *dcr, bool release);
+bool    mount_next_read_volume(DCR *dcr);
+void    release_volume(DCR *ddr);
+void    mark_volume_in_error(DCR *dcr);
 
 /* From parse_bsr.c */
-BSR     *parse_bsr(JCR *jcr, char *lf);
-void     dump_bsr(BSR *bsr, bool recurse);
-void     free_bsr(BSR *bsr);
+BSR    *parse_bsr(JCR *jcr, char *lf);
+void    dump_bsr(BSR *bsr, bool recurse);
+void    free_bsr(BSR *bsr);
 VOL_LIST *new_vol();
-int      add_vol(JCR *jcr, VOL_LIST *vol);
-void     free_vol_list(JCR *jcr);
-void     create_vol_list(JCR *jcr);
+int     add_vol(JCR *jcr, VOL_LIST *vol);
+void    free_vol_list(JCR *jcr);
+void    create_vol_list(JCR *jcr);
 
 /* From record.c */
 const char *FI_to_ascii(int fi);
 const char *stream_to_ascii(int stream, int fi);
-bool        write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-bool        can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-bool        read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
+bool       write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+bool       can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+bool       read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec);
 DEV_RECORD *new_record();
-void        free_record(DEV_RECORD *rec);
-void        empty_record(DEV_RECORD *rec);
+void       free_record(DEV_RECORD *rec);
+void       empty_record(DEV_RECORD *rec);
 
 /* From read_record.c */
 bool read_records(DCR *dcr,
@@ -211,12 +213,12 @@ bool read_records(DCR *dcr,
        bool mount_cb(DCR *dcr));
 
 /* From spool.c */
-bool    begin_data_spool          (DCR *dcr);
-bool    discard_data_spool        (DCR *dcr);
-bool    commit_data_spool         (DCR *dcr);
-bool    are_attributes_spooled    (JCR *jcr);
-bool    begin_attribute_spool     (JCR *jcr);
-bool    discard_attribute_spool   (JCR *jcr);
-bool    commit_attribute_spool    (JCR *jcr);
-bool    write_block_to_spool_file (DCR *dcr);
-void    list_spool_stats          (BSOCK *bs);
+bool   begin_data_spool          (DCR *dcr);
+bool   discard_data_spool        (DCR *dcr);
+bool   commit_data_spool         (DCR *dcr);
+bool   are_attributes_spooled    (JCR *jcr);
+bool   begin_attribute_spool     (JCR *jcr);
+bool   discard_attribute_spool   (JCR *jcr);
+bool   commit_attribute_spool    (JCR *jcr);
+bool   write_block_to_spool_file (DCR *dcr);
+void   list_spool_stats          (BSOCK *bs);
index a774a46e2f7e85d58bf4b812d92fdc7741ceee35..3bd86b0fbfaf04017d20b070dbe0f396be0667cd 100644 (file)
@@ -249,6 +249,8 @@ uint32_t newVolSessionId()
 /* Check Configuration file for necessary info */
 static void check_config()
 {
+   AUTOCHANGER *changer;
+
    LockRes();
    me = (STORES *)GetNextRes(R_STORAGE, NULL);
    if (!me) {
@@ -256,7 +258,6 @@ static void check_config()
       Jmsg1(NULL, M_ERROR_TERM, 0, _("No Storage resource defined in %s. Cannot continue.\n"),
         configfile);
    }
-
    my_name_is(0, (char **)NULL, me->hdr.name);    /* Set our real name */
 
    if (GetNextRes(R_STORAGE, (RES *)me) != NULL) {
@@ -284,14 +285,40 @@ static void check_config()
    close_msg(NULL);                  /* close temp message handler */
    init_msg(NULL, me->messages);      /* open daemon message handler */
 
-   UnlockRes();
 
    if (!me->working_directory) {
       Jmsg1(NULL, M_ERROR_TERM, 0, _("No Working Directory defined in %s. Cannot continue.\n"),
         configfile);
    }
-
    set_working_directory(me->working_directory);
+
+   /* Ensure that the media_type for each device is the same */
+   foreach_res(changer, R_AUTOCHANGER) {
+      DEVRES *device;
+      char *media_type = NULL;
+      foreach_alist(device, changer->device) {
+        if (media_type == NULL) {
+           media_type = device->media_type;
+           continue;
+        }     
+        if (strcmp(media_type, device->media_type) != 0) {
+           Jmsg(NULL, M_ERROR_TERM, 0, 
+               _("Media Type not the same for all devices in changer %s. Cannot continue.\n"),
+              changer->hdr.name);
+        }
+        /*
+         * If the device does not have a changer name or changer command
+         * defined, used the one from the Autochanger resource 
+         */
+        if (!device->changer_name) {
+           device->changer_name = bstrdup(changer->changer_name);
+        }
+        if (!device->changer_command) {
+           device->changer_command = bstrdup(changer->changer_command);
+        }
+      }
+   }
+   UnlockRes();
 }
 
 /*
index a776b492c10f67c95204d9fec91543a9d9a0fd3b..a1c3d00dc83054f8f9ec4ec2cd1f4534dc4bd240 100644 (file)
@@ -140,8 +140,8 @@ static RES_ITEM changer_items[] = {
    {"name",              store_name,      ITEM(res_changer.hdr.name),        0, ITEM_REQUIRED, 0},
    {"description",       store_str,       ITEM(res_changer.hdr.desc),        0, 0, 0},
    {"device",            store_alist_res, ITEM(res_changer.device),   R_DEVICE, ITEM_REQUIRED, 0},
-   {"changerdevice",     store_strname,   ITEM(res_changer.changer_name),    0, 0, 0},
-   {"changercommand",    store_strname,   ITEM(res_changer.changer_command), 0, 0, 0},
+   {"changerdevice",     store_strname,   ITEM(res_changer.changer_name),    0, ITEM_REQUIRED, 0},
+   {"changercommand",    store_strname,   ITEM(res_changer.changer_command), 0, ITEM_REQUIRED, 0},
    {NULL, NULL, 0, 0, 0, 0}
 };
 
@@ -160,7 +160,7 @@ RES_TABLE resources[] = {
    {"device",        dev_items,     R_DEVICE},
    {"messages",      msgs_items,    R_MSGS},
    {"autochanger",   changer_items, R_AUTOCHANGER},
-   {NULL,            NULL,          0}
+   {NULL,           NULL,          0}
 };
 
 
@@ -178,7 +178,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       return;
    }
    sendit(sock, "dump_resource type=%d\n", type);
-   if (type < 0) {                    /* no recursion */
+   if (type < 0) {                   /* no recursion */
       type = - type;
       recurse = 0;
    }
@@ -188,40 +188,40 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       break;
    case R_STORAGE:
       sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n",
-             res->res_store.hdr.name,
-             NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
-             get_first_port_host_order(res->res_store.sdaddrs),
-             get_first_port_host_order(res->res_store.sddaddrs),
-             edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
+            res->res_store.hdr.name,
+            NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))),
+            get_first_port_host_order(res->res_store.sdaddrs),
+            get_first_port_host_order(res->res_store.sddaddrs),
+            edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf)));
       if (res->res_store.sdaddrs) {
-         foreach_dlist(p, res->res_store.sdaddrs) {
+        foreach_dlist(p, res->res_store.sdaddrs) {
             sendit(sock, "        SDaddr=%s SDport=%d\n",
-                   p->get_address(buf, sizeof(buf)), p->get_port_host_order());
-         }
+                  p->get_address(buf, sizeof(buf)), p->get_port_host_order());
+        }
       }
       if (res->res_store.sddaddrs) {
-         foreach_dlist(p, res->res_store.sddaddrs) {
+        foreach_dlist(p, res->res_store.sddaddrs) {
             sendit(sock, "        SDDaddr=%s SDDport=%d\n",
-                   p->get_address(buf, sizeof(buf)), p->get_port_host_order());
-         }
+                  p->get_address(buf, sizeof(buf)), p->get_port_host_order());
+        }
       }
       break;
    case R_DEVICE:
       sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n",
-         res->res_dev.hdr.name,
-         res->res_dev.media_type, res->res_dev.device_name,
-         res->res_dev.label_type);
+        res->res_dev.hdr.name,
+        res->res_dev.media_type, res->res_dev.device_name,
+        res->res_dev.label_type);
       sendit(sock, "        rew_wait=%d min_bs=%d max_bs=%d\n",
-         res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
-         res->res_dev.max_block_size);
+        res->res_dev.max_rewind_wait, res->res_dev.min_block_size,
+        res->res_dev.max_block_size);
       sendit(sock, "        max_jobs=%d max_files=%" lld " max_size=%" lld "\n",
-         res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
-         res->res_dev.max_volume_size);
+        res->res_dev.max_volume_jobs, res->res_dev.max_volume_files,
+        res->res_dev.max_volume_size);
       sendit(sock, "        max_file_size=%" lld " capacity=%" lld "\n",
-         res->res_dev.max_file_size, res->res_dev.volume_capacity);
+        res->res_dev.max_file_size, res->res_dev.volume_capacity);
       sendit(sock, "         spool_directory=%s\n", NPRT(res->res_dev.spool_directory));
       sendit(sock, "         max_spool_size=%" lld " max_job_spool_size=%" lld "\n",
-         res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
+        res->res_dev.max_spool_size, res->res_dev.max_job_spool_size);
       if (res->res_dev.changer_res) {
          sendit(sock, "         changer=%p\n", res->res_dev.changer_res);
       }
@@ -271,8 +271,8 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
    case R_AUTOCHANGER:
       DEVRES *dev;
       sendit(sock, "Changer: name=%s Changer_devname=%s\n      Changer_cmd=%s\n",
-         res->res_changer.hdr.name,
-         res->res_changer.changer_name, res->res_changer.changer_command);
+        res->res_changer.hdr.name,
+        res->res_changer.changer_name, res->res_changer.changer_command);
       foreach_alist(dev, res->res_changer.device) {
          sendit(sock, "   --->Device: name=%s\n", dev->hdr.name);
       }
@@ -322,81 +322,81 @@ void free_resource(RES *sres, int type)
    switch (type) {
    case R_DIRECTOR:
       if (res->res_dir.password) {
-         free(res->res_dir.password);
+        free(res->res_dir.password);
       }
       if (res->res_dir.address) {
-         free(res->res_dir.address);
+        free(res->res_dir.address);
       }
       break;
    case R_AUTOCHANGER:
       if (res->res_changer.changer_name) {
-         free(res->res_changer.changer_name);
+        free(res->res_changer.changer_name);
       }
       if (res->res_changer.changer_command) {
-         free(res->res_changer.changer_command);
+        free(res->res_changer.changer_command);
       }
       if (res->res_changer.device) {
-         delete res->res_changer.device;
+        delete res->res_changer.device;
       }
       break; 
    case R_STORAGE:
       if (res->res_store.sdaddrs) {
-         free_addresses(res->res_store.sdaddrs);
+        free_addresses(res->res_store.sdaddrs);
       }
       if (res->res_store.sddaddrs) {
-         free_addresses(res->res_store.sddaddrs);
+        free_addresses(res->res_store.sddaddrs);
       }
       if (res->res_store.working_directory) {
-         free(res->res_store.working_directory);
+        free(res->res_store.working_directory);
       }
       if (res->res_store.pid_directory) {
-         free(res->res_store.pid_directory);
+        free(res->res_store.pid_directory);
       }
       if (res->res_store.subsys_directory) {
-         free(res->res_store.subsys_directory);
+        free(res->res_store.subsys_directory);
       }
       break;
    case R_DEVICE:
       if (res->res_dev.media_type) {
-         free(res->res_dev.media_type);
+        free(res->res_dev.media_type);
       }
       if (res->res_dev.device_name) {
-         free(res->res_dev.device_name);
+        free(res->res_dev.device_name);
       }
       if (res->res_dev.changer_name) {
-         free(res->res_dev.changer_name);
+        free(res->res_dev.changer_name);
       }
       if (res->res_dev.changer_command) {
-         free(res->res_dev.changer_command);
+        free(res->res_dev.changer_command);
       }
       if (res->res_dev.alert_command) {
-         free(res->res_dev.alert_command);
+        free(res->res_dev.alert_command);
       }
       if (res->res_dev.spool_directory) {
-         free(res->res_dev.spool_directory);
+        free(res->res_dev.spool_directory);
       }
       if (res->res_dev.mount_point) {
-         free(res->res_dev.mount_point);
+        free(res->res_dev.mount_point);
       }
       if (res->res_dev.mount_command) {
-         free(res->res_dev.mount_command);
+        free(res->res_dev.mount_command);
       }
       if (res->res_dev.unmount_command) {
-         free(res->res_dev.unmount_command);
+        free(res->res_dev.unmount_command);
       }
       if (res->res_dev.write_part_command) {
-         free(res->res_dev.write_part_command);
+        free(res->res_dev.write_part_command);
       }
       if (res->res_dev.free_space_command) {
-         free(res->res_dev.free_space_command);
+        free(res->res_dev.free_space_command);
       }
       break;
    case R_MSGS:
       if (res->res_msgs.mail_cmd) {
-         free(res->res_msgs.mail_cmd);
+        free(res->res_msgs.mail_cmd);
       }
       if (res->res_msgs.operator_cmd) {
-         free(res->res_msgs.operator_cmd);
+        free(res->res_msgs.operator_cmd);
       }
       free_msgs_res((MSGS *)res);  /* free message resource */
       res = NULL;
@@ -430,10 +430,10 @@ void save_resource(int type, RES_ITEM *items, int pass)
     */
    for (i=0; items[i].name; i++) {
       if (items[i].flags & ITEM_REQUIRED) {
-         if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
+        if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {
             Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"),
-              items[i].name, resources[rindex]);
-          }
+             items[i].name, resources[rindex]);
+         }
       }
       /* If this triggers, take a look at lib/parse_conf.h */
       if (i >= MAX_RES_ITEMS) {
@@ -454,49 +454,49 @@ void save_resource(int type, RES_ITEM *items, int pass)
       case R_DIRECTOR:
       case R_DEVICE:
       case R_MSGS:
-         break;
+        break;
 
       /* Resources containing a resource or an alist */
       case R_STORAGE:
-         if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
+        if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) {
             Emsg1(M_ERROR_TERM, 0, "Cannot find Storage resource \"%s\"\n", res_all.res_dir.hdr.name);
-         }
-         res->res_store.messages = res_all.res_store.messages;
-         break;
+        }
+        res->res_store.messages = res_all.res_store.messages;
+        break;
       case R_AUTOCHANGER:
-         if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
+        if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) {
             Emsg1(M_ERROR_TERM, 0, "Cannot find AutoChanger resource %s\n",
-                  res_all.res_changer.hdr.name);
-         }
-         /* we must explicitly copy the device alist pointer */
-         res->res_changer.device   = res_all.res_changer.device;
-         /*
-          * Now update each device in this resource to point back 
-          *  to the changer resource.
-          */
-         foreach_alist(dev, res->res_changer.device) {
-            dev->changer_res = (AUTOCHANGER *)&res->res_changer;
-         }
-         if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) {
-            berrno be;
+                 res_all.res_changer.hdr.name);
+        }
+        /* we must explicitly copy the device alist pointer */
+        res->res_changer.device   = res_all.res_changer.device;
+        /*
+         * Now update each device in this resource to point back 
+         *  to the changer resource.
+         */
+        foreach_alist(dev, res->res_changer.device) {
+           dev->changer_res = (AUTOCHANGER *)&res->res_changer;
+        }
+        if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) {
+           berrno be;
             Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"), 
-                  be.strerror(errstat));
-         }
-         break;
+                 be.strerror(errstat));
+        }
+        break;
       default:
          printf("Unknown resource type %d\n", type);
-         error = 1;
-         break;
+        error = 1;
+        break;
       }
 
 
       if (res_all.res_dir.hdr.name) {
-         free(res_all.res_dir.hdr.name);
-         res_all.res_dir.hdr.name = NULL;
+        free(res_all.res_dir.hdr.name);
+        res_all.res_dir.hdr.name = NULL;
       }
       if (res_all.res_dir.hdr.desc) {
-         free(res_all.res_dir.hdr.desc);
-         res_all.res_dir.hdr.desc = NULL;
+        free(res_all.res_dir.hdr.desc);
+        res_all.res_dir.hdr.desc = NULL;
       }
       return;
    }
@@ -504,45 +504,45 @@ void save_resource(int type, RES_ITEM *items, int pass)
    /* The following code is only executed on pass 1 */
    switch (type) {
       case R_DIRECTOR:
-         size = sizeof(DIRRES);
-         break;
+        size = sizeof(DIRRES);
+        break;
       case R_STORAGE:
-         size = sizeof(STORES);
-         break;
+        size = sizeof(STORES);
+        break;
       case R_DEVICE:
-         size = sizeof(DEVRES);
-         break;
+        size = sizeof(DEVRES);
+        break;
       case R_MSGS:
-         size = sizeof(MSGS);
-         break;
+        size = sizeof(MSGS);
+        break;
       case R_AUTOCHANGER:
-         size = sizeof(AUTOCHANGER);
-         break;
+        size = sizeof(AUTOCHANGER);
+        break;
       default:
          printf("Unknown resource type %d\n", type);
-         error = 1;
-         size = 1;
-         break;
+        error = 1;
+        size = 1;
+        break;
    }
    /* Common */
    if (!error) {
       res = (URES *)malloc(size);
       memcpy(res, &res_all, size);
       if (!res_head[rindex]) {
-         res_head[rindex] = (RES *)res; /* store first entry */
+        res_head[rindex] = (RES *)res; /* store first entry */
       } else {
-         RES *next;
-         /* Add new res to end of chain */
-         for (next=res_head[rindex]; next->next; next=next->next) {
-            if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
-               Emsg2(M_ERROR_TERM, 0,
+        RES *next;
+        /* Add new res to end of chain */
+        for (next=res_head[rindex]; next->next; next=next->next) {
+           if (strcmp(next->name, res->res_dir.hdr.name) == 0) {
+              Emsg2(M_ERROR_TERM, 0,
                   _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"),
-                  resources[rindex].name, res->res_dir.hdr.name);
-            }
-         }
-         next->next = (RES *)res;
+                 resources[rindex].name, res->res_dir.hdr.name);
+           }
+        }
+        next->next = (RES *)res;
          Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
-               res->res_dir.hdr.name);
+              res->res_dir.hdr.name);
       }
    }
 }
index 8ac96e14cdbea8686835ad2dd92ded166571acc1..9ea5d71bad4fd65f4bc80c554951a281d7a0a3bc 100644 (file)
@@ -30,7 +30,7 @@ enum {
    R_MSGS,
    R_AUTOCHANGER,
    R_FIRST = R_DIRECTOR,
-   R_LAST  = R_AUTOCHANGER            /* keep this updated */
+   R_LAST  = R_AUTOCHANGER           /* keep this updated */
 };
 
 enum {
@@ -45,29 +45,29 @@ enum {
 /* Definition of the contents of each Resource */
 class DIRRES {
 public:
-   RES   hdr;
+   RES  hdr;
 
-   char *password;                    /* Director password */
-   char *address;                     /* Director IP address or zero */
-   int enable_ssl;                    /* Use SSL with this Director */
-   int monitor;                       /* Have only access to status and .status functions */
+   char *password;                   /* Director password */
+   char *address;                    /* Director IP address or zero */
+   int enable_ssl;                   /* Use SSL with this Director */
+   int monitor;                      /* Have only access to status and .status functions */
 };
 
 
 /* Storage daemon "global" definitions */
 class s_res_store {
 public:
-   RES   hdr;
+   RES  hdr;
 
    dlist *sdaddrs;
    dlist *sddaddrs;
-   char *working_directory;           /* working directory for checkpoints */
+   char *working_directory;          /* working directory for checkpoints */
    char *pid_directory;
    char *subsys_directory;
-   int require_ssl;                   /* Require SSL on all connections */
+   int require_ssl;                  /* Require SSL on all connections */
    uint32_t max_concurrent_jobs;      /* maximum concurrent jobs to run */
-   MSGS *messages;                    /* Daemon message handler */
-   utime_t heartbeat_interval;        /* Interval to send hb to FD */
+   MSGS *messages;                   /* Daemon message handler */
+   utime_t heartbeat_interval;       /* Interval to send hb to FD */
 };
 typedef struct s_res_store STORES;
 
@@ -75,52 +75,52 @@ class AUTOCHANGER {
 public:
    RES hdr;
    alist *device;
-   char *changer_name;                /* Changer device name */
-   char *changer_command;             /* Changer command  -- external program */
+   char *changer_name;               /* Changer device name */
+   char *changer_command;            /* Changer command  -- external program */
    pthread_mutex_t changer_mutex;     /* One changer operation at a time */
 };
 
 /* Device specific definitions */
 class DEVRES {
 public:
-   RES   hdr;
-
-   char *media_type;                  /* User assigned media type */
-   char *device_name;                 /* Archive device name */
-   char *changer_name;                /* Changer device name */
-   char *changer_command;             /* Changer command  -- external program */
-   char *alert_command;               /* Alert command -- external program */
-   char *spool_directory;             /* Spool file directory */
-   int   label_type;                  /* label type */
-   int   autoselect;                  /* Automatically select from AutoChanger */
-   uint32_t drive_index;              /* Autochanger drive index */
-   uint32_t cap_bits;                 /* Capabilities of this device */
-   uint32_t max_changer_wait;         /* Changer timeout */
-   uint32_t max_rewind_wait;          /* maximum secs to wait for rewind */
-   uint32_t max_open_wait;            /* maximum secs to wait for open */
-   uint32_t max_open_vols;            /* maximum simultaneous open volumes */
-   uint32_t min_block_size;           /* min block size */
-   uint32_t max_block_size;           /* max block size */
-   uint32_t max_volume_jobs;          /* max jobs to put on one volume */
+   RES  hdr;
+
+   char *media_type;                 /* User assigned media type */
+   char *device_name;                /* Archive device name */
+   char *changer_name;               /* Changer device name */
+   char *changer_command;            /* Changer command  -- external program */
+   char *alert_command;              /* Alert command -- external program */
+   char *spool_directory;            /* Spool file directory */
+   int  label_type;                  /* label type */
+   int  autoselect;                  /* Automatically select from AutoChanger */
+   uint32_t drive_index;             /* Autochanger drive index */
+   uint32_t cap_bits;                /* Capabilities of this device */
+   uint32_t max_changer_wait;        /* Changer timeout */
+   uint32_t max_rewind_wait;         /* maximum secs to wait for rewind */
+   uint32_t max_open_wait;           /* maximum secs to wait for open */
+   uint32_t max_open_vols;           /* maximum simultaneous open volumes */
+   uint32_t min_block_size;          /* min block size */
+   uint32_t max_block_size;          /* max block size */
+   uint32_t max_volume_jobs;         /* max jobs to put on one volume */
    uint32_t max_network_buffer_size;  /* max network buf size */
-   utime_t  vol_poll_interval;        /* interval between polling volume during mount */
-   int64_t max_volume_files;          /* max files to put on one volume */
-   int64_t max_volume_size;           /* max bytes to put on one volume */
-   int64_t max_file_size;             /* max file size in bytes */
-   int64_t volume_capacity;           /* advisory capacity */
-   int64_t max_spool_size;            /* Max spool size for all jobs */
-   int64_t max_job_spool_size;        /* Max spool size for any single job */
+   utime_t  vol_poll_interval;       /* interval between polling volume during mount */
+   int64_t max_volume_files;         /* max files to put on one volume */
+   int64_t max_volume_size;          /* max bytes to put on one volume */
+   int64_t max_file_size;            /* max file size in bytes */
+   int64_t volume_capacity;          /* advisory capacity */
+   int64_t max_spool_size;           /* Max spool size for all jobs */
+   int64_t max_job_spool_size;       /* Max spool size for any single job */
    
-   int64_t max_part_size;             /* Max part size */
-   char *mount_point;                 /* Mount point for require mount devices */
-   char *mount_command;               /* Mount command */
-   char *unmount_command;             /* Unmount command */
-   char *write_part_command;          /* Write part command */
-   char *free_space_command;          /* Free space command */
+   int64_t max_part_size;            /* Max part size */
+   char *mount_point;                /* Mount point for require mount devices */
+   char *mount_command;              /* Mount command */
+   char *unmount_command;            /* Unmount command */
+   char *write_part_command;         /* Write part command */
+   char *free_space_command;         /* Free space command */
    
    /* The following are set at runtime */
-   DEVICE *dev;                       /* Pointer to phyical dev -- set at runtime */
-   AUTOCHANGER *changer_res;          /* pointer to changer res if any */
+   DEVICE *dev;                      /* Pointer to phyical dev -- set at runtime */
+   AUTOCHANGER *changer_res;         /* pointer to changer res if any */
 };
 
 
@@ -130,5 +130,5 @@ union URES {
    DEVRES      res_dev;
    MSGS        res_msgs;
    AUTOCHANGER res_changer;
-   RES         hdr;
+   RES        hdr;
 };
index c1c4f7f1179109063e83474722e98cd203acc486..b5103f49b669eb5e8e1ed548ef91c498f9876a05 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #undef  VERSION
 #define VERSION "1.37.6"
-#define BDATE   "06 March 2005"
-#define LSMDATE "06Mar05"
+#define BDATE   "07 March 2005"
+#define LSMDATE "07Mar05"
 
 /* Debug flags */
 #undef  DEBUG