]> git.sur5r.net Git - bacula/bacula/commitdiff
- Convert more atoi to str_to_int64() for DB.
authorKern Sibbald <kern@sibbald.com>
Fri, 1 Apr 2005 15:21:46 +0000 (15:21 +0000)
committerKern Sibbald <kern@sibbald.com>
Fri, 1 Apr 2005 15:21:46 +0000 (15:21 +0000)
- Implement filling in NumVols by querying DB rather
  than trying to keep track of it.
- Add storage name to string passed to in use storage=
- Fix newVolume() so that the Python script is always
  called.
- Fix handling of pool,PoolId, and storage in ua_output.
- Same fix in ua_status.c
- Remove required locking of resources
- Replace pthread_cond_signal() by pthread_cond_broadcast()
  hoping to fix the /lib/tls hang problems (lost signal).
- Move resource locking seaching from parse_conf.c to res.c
  in src/lib.
- Modify end of volume handling so that fixup_... does not
  redo what block.c has already done -- writing Vol info to
  DIR. This fixes a bug with bad numbers of files on a tape
  when it filled as reported by Peter.
- In release_device() do not update the DIR on the Volume
  info if the the information was already written at the
  end of the tape.

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

35 files changed:
bacula/kernstodo
bacula/src/cats/sql.c
bacula/src/cats/sql_delete.c
bacula/src/cats/sql_find.c
bacula/src/cats/sql_get.c
bacula/src/dird/catreq.c
bacula/src/dird/dird.c
bacula/src/dird/job.c
bacula/src/dird/jobq.c
bacula/src/dird/msgchan.c
bacula/src/dird/newvol.c
bacula/src/dird/next_vol.c
bacula/src/dird/ua_output.c
bacula/src/dird/ua_run.c
bacula/src/dird/ua_status.c
bacula/src/filed/job.c
bacula/src/findlib/find_one.c
bacula/src/lib/Makefile.in
bacula/src/lib/parse_conf.c
bacula/src/lib/python.c
bacula/src/lib/res.c [new file with mode: 0644]
bacula/src/lib/rwlock.c
bacula/src/lib/workq.c
bacula/src/stored/acquire.c
bacula/src/stored/append.c
bacula/src/stored/block.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/device.c
bacula/src/stored/dircmd.c
bacula/src/stored/dvd.c
bacula/src/stored/job.c
bacula/src/stored/protos.h
bacula/src/stored/stored.c
bacula/src/version.h

index ccc09c81f8ecda845d41b0cc57ab6cc4ff837bed..63f501269795aed32ed281f3b89875b6c343491e 100644 (file)
@@ -26,13 +26,13 @@ Autochangers:
      and possibly manipulating the autochanger (much asked for).
   
 For 1.37:
+- Add disk seeking on restore.  
 - If the user puts "Purge Oldest Volume = yes" or "Recycle Oldest Volume = yes"
   and there is only one volume in the pool, refuse to do it -- otherwise
   he fills the Volume, then immediately starts reusing it.
-- Add disk seeking on restore.  
 - Implement "NewVolumeEachJob = yes|no" in Dir.
 - Make "update slots" when pointing to Autochanger, remove
-  all Volumes from other drives.
+  all Volumes from other drives.  "update slots all-drives"?
 - Add Python writable variable for changing the Priority,
     Client, Storage, JobStatus (error), ...
 - SD Python
@@ -44,7 +44,6 @@ For 1.37:
 - 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
 - 28-Mar 23:19 rufus-sd: acquire.c:379 Device "DDS-4" (/dev/nst0) 
   is busy reading. Job 6 canceled.
@@ -54,7 +53,14 @@ For 1.37:
   Dir next_vol.c
 - Finish implementation of passing all Storage and Device needs to
   the SD.
-
+- Check locking of resources -- be sure to lock devices where previously
+  resources were locked. 
+- Add global lock on all devices when creating a device structure.
+- Remove separate thread for opening devices in SD.  On the other
+  hand, don't block waiting for open() for devices.
+- Make sure that Python has access to Client address/port so that
+  it can check if Clients are alive.
+- Implement copies and stripes.
 
 Maybe in 1.37:
 - By the way: on page http://www.bacula.org/?page=tapedrives , at the 
@@ -1275,3 +1281,4 @@ Block Position: 0
 - 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.
+- Scratch Pool where the volumes can be re-assigned to any Pool.
index e7b09f611507dd6566736b2ca6a71d518ee6e298..e61133530e223ea02298c9f912103e9b1541be7d 100644 (file)
@@ -56,7 +56,7 @@ static int int_handler(void *ctx, int num_fields, char **row)
 
    if (row[0]) {
       Dmsg1(800, "int_handler finds '%s'\n", row[0]);
-      *val = atoi(row[0]);
+      *val = str_to_int64(row[0]);
    } else {
       Dmsg0(800, "int_handler finds zero\n");
       *val = 0;
@@ -209,7 +209,7 @@ int get_sql_record_max(JCR *jcr, B_DB *mdb)
          Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
         stat = -1;
       } else {
-        stat = atoi(row[0]);
+        stat = str_to_int64(row[0]);
       }
       sql_free_result(mdb);
    } else {
index c24c7863178fb02e40e7397f7e46d1254b7a055d..e03cf5cdaf0c670502a140aa6c15d312c4a5a5fc 100644 (file)
@@ -91,7 +91,7 @@ db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
         db_unlock(mdb);
         return 0;
       }
-      pr->PoolId = atoi(row[0]);
+      pr->PoolId = str_to_int64(row[0]);
       sql_free_result(mdb);
    }
 
index 6151fa1502c7118110421d1119d8c49b946d927e..354038280f59f58276e1a35b6207e75ad3dbd647 100644 (file)
@@ -241,7 +241,7 @@ db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr)
       return 0;
    }
 
-   jr->JobId = atoi(row[0]);
+   jr->JobId = str_to_int64(row[0]);
    sql_free_result(mdb);
 
    Dmsg1(100, "db_get_last_jobid: got JobId=%d\n", jr->JobId);
index da17f306955e432bc78b904d12f20fae8fa0d782..78d0f1340093e4d4f2a8c5ef471a9d76ca6e7ed9 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Bacula Catalog Database Get record interface routines
  *  Note, these routines generally get a record by id or
- *        by name.  If more logic is involved, the routine
- *        should be in find.c
+ *       by name.  If more logic is involved, the routine
+ *       should be in find.c
  *
  *    Kern Sibbald, March 2000
  *
@@ -33,7 +33,7 @@
 /* The following is necessary so that we do not include
  * the dummy external definition of DB.
  */
-#define __SQL_C                       /* indicate that this is sql.c */
+#define __SQL_C                      /* indicate that this is sql.c */
 
 #include "bacula.h"
 #include "cats.h"
@@ -65,7 +65,7 @@ extern void split_path_and_file(JCR *jcr, B_DB *mdb, const char *fname);
  * (with attributes) in the database.
  *
  *  Returns: 0 on failure
- *           1 on success with the File record in FILE_DBR
+ *          1 on success with the File record in FILE_DBR
  */
 int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr, FILE_DBR *fdbr)
 {
@@ -90,7 +90,7 @@ int db_get_file_attributes_record(JCR *jcr, B_DB *mdb, char *fname, JOB_DBR *jr,
 /*
  * Get a File record
  * Returns: 0 on failure
- *          1 on success
+ *         1 on success
  *
  *  DO NOT use Jmsg in this routine.
  *
@@ -133,21 +133,21 @@ int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr)
       Dmsg1(050, "get_file_record num_rows=%d\n", (int)mdb->num_rows);
       if (mdb->num_rows > 1) {
          Mmsg1(&mdb->errmsg, _("get_file_record want 1 got rows=%d\n"),
-            mdb->num_rows);
+           mdb->num_rows);
       }
       if (mdb->num_rows >= 1) {
-         if ((row = sql_fetch_row(mdb)) == NULL) {
+        if ((row = sql_fetch_row(mdb)) == NULL) {
             Mmsg1(&mdb->errmsg, _("Error fetching row: %s\n"), sql_strerror(mdb));
-         } else {
-            fdbr->FileId = (FileId_t)str_to_int64(row[0]);
-            bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
-            bstrncpy(fdbr->SIG, row[2], sizeof(fdbr->SIG));
-            stat = 1;
-         }
+        } else {
+           fdbr->FileId = (FileId_t)str_to_int64(row[0]);
+           bstrncpy(fdbr->LStat, row[1], sizeof(fdbr->LStat));
+           bstrncpy(fdbr->SIG, row[2], sizeof(fdbr->SIG));
+           stat = 1;
+        }
       } else {
          Mmsg2(&mdb->errmsg, _("File record for PathId=%s FilenameId=%s not found.\n"),
-            edit_int64(fdbr->PathId, ed1), 
-            edit_int64(fdbr->FilenameId, ed2));
+           edit_int64(fdbr->PathId, ed1), 
+           edit_int64(fdbr->FilenameId, ed2));
       }
       sql_free_result(mdb);
    } else {
@@ -159,7 +159,7 @@ int db_get_file_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr, FILE_DBR *fdbr)
 
 /* Get Filename record
  * Returns: 0 on failure
- *          FilenameId on success
+ *         FilenameId on success
  *
  *   DO NOT use Jmsg in this routine (see notes for get_file_record)
  */
@@ -177,20 +177,20 @@ static int db_get_filename_record(JCR *jcr, B_DB *mdb)
       mdb->num_rows = sql_num_rows(mdb);
       if (mdb->num_rows > 1) {
          Mmsg2(&mdb->errmsg, _("More than one Filename!: %s for file: %s\n"),
-            edit_uint64(mdb->num_rows, ed1), mdb->fname);
+           edit_uint64(mdb->num_rows, ed1), mdb->fname);
          Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
       }
       if (mdb->num_rows >= 1) {
-         if ((row = sql_fetch_row(mdb)) == NULL) {
+        if ((row = sql_fetch_row(mdb)) == NULL) {
             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
-         } else {
-            FilenameId = atoi(row[0]);
-            if (FilenameId <= 0) {
+        } else {
+           FilenameId = str_to_int64(row[0]);
+           if (FilenameId <= 0) {
                Mmsg2(&mdb->errmsg, _("Get DB Filename record %s found bad record: %d\n"),
-                  mdb->cmd, FilenameId);
-               FilenameId = 0;
-            }
-         }
+                 mdb->cmd, FilenameId);
+              FilenameId = 0;
+           }
+        }
       } else {
          Mmsg1(&mdb->errmsg, _("Filename record: %s not found.\n"), mdb->fname);
       }
@@ -203,7 +203,7 @@ static int db_get_filename_record(JCR *jcr, B_DB *mdb)
 
 /* Get path record
  * Returns: 0 on failure
- *          PathId on success
+ *         PathId on success
  *
  *   DO NOT use Jmsg in this routine (see notes for get_file_record)
  */
@@ -227,28 +227,28 @@ static int db_get_path_record(JCR *jcr, B_DB *mdb)
       mdb->num_rows = sql_num_rows(mdb);
       if (mdb->num_rows > 1) {
          Mmsg2(&mdb->errmsg, _("More than one Path!: %s for path: %s\n"),
-            edit_uint64(mdb->num_rows, ed1), mdb->path);
+           edit_uint64(mdb->num_rows, ed1), mdb->path);
          Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
       }
       /* Even if there are multiple paths, take the first one */
       if (mdb->num_rows >= 1) {
-         if ((row = sql_fetch_row(mdb)) == NULL) {
+        if ((row = sql_fetch_row(mdb)) == NULL) {
             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
-         } else {
-            PathId = atoi(row[0]);
-            if (PathId <= 0) {
+        } else {
+           PathId = str_to_int64(row[0]);
+           if (PathId <= 0) {
                Mmsg2(&mdb->errmsg, _("Get DB path record %s found bad record: %s\n"),
-                  mdb->cmd, edit_int64(PathId, ed1));
-               PathId = 0;
-            } else {
-               /* Cache path */
-               if (PathId != mdb->cached_path_id) {
-                  mdb->cached_path_id = PathId;
-                  mdb->cached_path_len = mdb->pnl;
-                  pm_strcpy(&mdb->cached_path, mdb->path);
-               }
-            }
-         }
+                 mdb->cmd, edit_int64(PathId, ed1));
+              PathId = 0;
+           } else {
+              /* Cache path */
+              if (PathId != mdb->cached_path_id) {
+                 mdb->cached_path_id = PathId;
+                 mdb->cached_path_len = mdb->pnl;
+                 pm_strcpy(&mdb->cached_path, mdb->path);
+              }
+           }
+        }
       } else {
          Mmsg1(&mdb->errmsg, _("Path record: %s not found.\n"), mdb->path);
       }
@@ -263,7 +263,7 @@ static int db_get_path_record(JCR *jcr, B_DB *mdb)
 /*
  * Get Job record for given JobId or Job name
  * Returns: 0 on failure
- *          1 on success
+ *         1 on success
  */
 int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
 {
@@ -281,18 +281,18 @@ int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
 "PoolId,StartTime,EndTime,JobFiles,JobBytes,JobTDate,Job,JobStatus,"
 "Type,Level,ClientId "
 "FROM Job WHERE JobId=%s", 
-          edit_int64(jr->JobId, ed1));
+         edit_int64(jr->JobId, ed1));
     }
 
    if (!QUERY_DB(jcr, mdb, mdb->cmd)) {
       db_unlock(mdb);
-      return 0;                       /* failed */
+      return 0;                      /* failed */
    }
    if ((row = sql_fetch_row(mdb)) == NULL) {
       Mmsg1(&mdb->errmsg, _("No Job found for JobId %s\n"), edit_int64(jr->JobId, ed1));
       sql_free_result(mdb);
       db_unlock(mdb);
-      return 0;                       /* failed */
+      return 0;                      /* failed */
    }
 
    jr->VolSessionId = str_to_uint64(row[0]);
@@ -300,7 +300,7 @@ int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
    jr->PoolId = str_to_int64(row[2]);
    bstrncpy(jr->cStartTime, row[3]!=NULL?row[3]:"", sizeof(jr->cStartTime));
    bstrncpy(jr->cEndTime, row[4]!=NULL?row[4]:"", sizeof(jr->cEndTime));
-   jr->JobFiles = atol(row[5]);
+   jr->JobFiles = str_to_int64(row[5]);
    jr->JobBytes = str_to_int64(row[6]);
    jr->JobTDate = str_to_int64(row[7]);
    bstrncpy(jr->Job, row[8]!=NULL?row[8]:"", sizeof(jr->Job));
@@ -317,10 +317,10 @@ int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
 /*
  * Find VolumeNames for a given JobId
  *  Returns: 0 on error or no Volumes found
- *           number of volumes on success
- *              Volumes are concatenated in VolumeNames
- *              separated by a vertical bar (|) in the order
- *              that they were written.
+ *          number of volumes on success
+ *             Volumes are concatenated in VolumeNames
+ *             separated by a vertical bar (|) in the order
+ *             that they were written.
  *
  *  Returns: number of volumes on success
  */
@@ -346,22 +346,22 @@ int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **Volume
       Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
       if (mdb->num_rows <= 0) {
          Mmsg1(&mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
-         stat = 0;
+        stat = 0;
       } else {
-         stat = mdb->num_rows;
-         for (i=0; i < stat; i++) {
-            if ((row = sql_fetch_row(mdb)) == NULL) {
+        stat = mdb->num_rows;
+        for (i=0; i < stat; i++) {
+           if ((row = sql_fetch_row(mdb)) == NULL) {
                Mmsg2(&mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
                Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
-               stat = 0;
-               break;
-            } else {
-               if (*VolumeNames[0] != 0) {
+              stat = 0;
+              break;
+           } else {
+              if (*VolumeNames[0] != 0) {
                   pm_strcat(VolumeNames, "|");
-               }
-               pm_strcat(VolumeNames, row[0]);
-            }
-         }
+              }
+              pm_strcat(VolumeNames, row[0]);
+           }
+        }
       }
       sql_free_result(mdb);
    } else {
@@ -374,8 +374,8 @@ int db_get_job_volume_names(JCR *jcr, B_DB *mdb, JobId_t JobId, POOLMEM **Volume
 /*
  * Find Volume parameters for a give JobId
  *  Returns: 0 on error or no Volumes found
- *           number of volumes on success
- *           List of Volumes and start/end file/blocks (malloced structure!)
+ *          number of volumes on success
+ *          List of Volumes and start/end file/blocks (malloced structure!)
  *
  *  Returns: number of volumes on success
  */
@@ -393,7 +393,7 @@ int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS
 "JobMedia.EndFile,StartBlock,JobMedia.EndBlock"
 " FROM JobMedia,Media WHERE JobMedia.JobId=%s"
 " AND JobMedia.MediaId=Media.MediaId ORDER BY VolIndex,JobMediaId",
-        edit_int64(JobId, ed1));
+       edit_int64(JobId, ed1));
 
    Dmsg1(130, "VolNam=%s\n", mdb->cmd);
    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
@@ -401,29 +401,29 @@ int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS
       Dmsg1(130, "Num rows=%d\n", mdb->num_rows);
       if (mdb->num_rows <= 0) {
          Mmsg1(&mdb->errmsg, _("No volumes found for JobId=%d\n"), JobId);
-         stat = 0;
+        stat = 0;
       } else {
-         stat = mdb->num_rows;
-         if (stat > 0) {
-            *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
-         }
-         for (i=0; i < stat; i++) {
-            if ((row = sql_fetch_row(mdb)) == NULL) {
+        stat = mdb->num_rows;
+        if (stat > 0) {
+           *VolParams = Vols = (VOL_PARAMS *)malloc(stat * sizeof(VOL_PARAMS));
+        }
+        for (i=0; i < stat; i++) {
+           if ((row = sql_fetch_row(mdb)) == NULL) {
                Mmsg2(&mdb->errmsg, _("Error fetching row %d: ERR=%s\n"), i, sql_strerror(mdb));
                Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
-               stat = 0;
-               break;
-            } else {
-               bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
-               bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
-               Vols[i].FirstIndex = str_to_uint64(row[2]);
-               Vols[i].LastIndex = str_to_uint64(row[3]);
-               Vols[i].StartFile = str_to_uint64(row[4]);
-               Vols[i].EndFile = str_to_uint64(row[5]);
-               Vols[i].StartBlock = str_to_uint64(row[6]);
-               Vols[i].EndBlock = str_to_uint64(row[7]);
-            }
-         }
+              stat = 0;
+              break;
+           } else {
+              bstrncpy(Vols[i].VolumeName, row[0], MAX_NAME_LENGTH);
+              bstrncpy(Vols[i].MediaType, row[1], MAX_NAME_LENGTH);
+              Vols[i].FirstIndex = str_to_uint64(row[2]);
+              Vols[i].LastIndex = str_to_uint64(row[3]);
+              Vols[i].StartFile = str_to_uint64(row[4]);
+              Vols[i].EndFile = str_to_uint64(row[5]);
+              Vols[i].StartBlock = str_to_uint64(row[6]);
+              Vols[i].EndBlock = str_to_uint64(row[7]);
+           }
+        }
       }
       sql_free_result(mdb);
    }
@@ -437,7 +437,7 @@ int db_get_job_volume_parameters(JCR *jcr, B_DB *mdb, JobId_t JobId, VOL_PARAMS
  * Get the number of pool records
  *
  * Returns: -1 on failure
- *          number on success
+ *         number on success
  */
 int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
 {
@@ -455,7 +455,7 @@ int db_get_num_pool_records(JCR *jcr, B_DB *mdb)
  *  The caller must free ids if non-NULL.
  *
  *  Returns 0: on failure
- *          1: on success
+ *         1: on success
  */
 int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
 {
@@ -470,11 +470,11 @@ int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
       *num_ids = sql_num_rows(mdb);
       if (*num_ids > 0) {
-         id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
-         while ((row = sql_fetch_row(mdb)) != NULL) {
-            id[i++] = str_to_uint64(row[0]);
-         }
-         *ids = id;
+        id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
+        while ((row = sql_fetch_row(mdb)) != NULL) {
+           id[i++] = str_to_uint64(row[0]);
+        }
+        *ids = id;
       }
       sql_free_result(mdb);
       stat = 1;
@@ -492,7 +492,7 @@ int db_get_pool_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
  *  The caller must free ids if non-NULL.
  *
  *  Returns 0: on failure
- *          1: on success
+ *         1: on success
  */
 int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
 {
@@ -507,11 +507,11 @@ int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
       *num_ids = sql_num_rows(mdb);
       if (*num_ids > 0) {
-         id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
-         while ((row = sql_fetch_row(mdb)) != NULL) {
-            id[i++] = str_to_uint64(row[0]);
-         }
-         *ids = id;
+        id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
+        while ((row = sql_fetch_row(mdb)) != NULL) {
+           id[i++] = str_to_uint64(row[0]);
+        }
+        *ids = id;
       }
       sql_free_result(mdb);
       stat = 1;
@@ -531,7 +531,7 @@ int db_get_client_ids(JCR *jcr, B_DB *mdb, int *num_ids, uint32_t *ids[])
  *  otherwise, we search on the PoolName
  *
  * Returns: false on failure
- *          true on success
+ *         true on success
  */
 bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
 {
@@ -540,51 +540,51 @@ bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
    char ed1[50];
 
    db_lock(mdb);
-   if (pdbr->PoolId != 0) {               /* find by id */
+   if (pdbr->PoolId != 0) {              /* find by id */
       Mmsg(mdb->cmd,
 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.PoolId=%s", 
-         edit_int64(pdbr->PoolId, ed1));
-   } else {                           /* find by name */
+        edit_int64(pdbr->PoolId, ed1));
+   } else {                          /* find by name */
       Mmsg(mdb->cmd,
 "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume,"
 "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
 "MaxVolBytes,PoolType,LabelType,LabelFormat FROM Pool WHERE Pool.Name='%s'", 
-         pdbr->Name);
+        pdbr->Name);
    }
 
    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
       mdb->num_rows = sql_num_rows(mdb);
       if (mdb->num_rows > 1) {
-         char ed1[30];
+        char ed1[30];
          Mmsg1(&mdb->errmsg, _("More than one Pool!: %s\n"),
-            edit_uint64(mdb->num_rows, ed1));
+           edit_uint64(mdb->num_rows, ed1));
          Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
       } else if (mdb->num_rows == 1) {
-         if ((row = sql_fetch_row(mdb)) == NULL) {
+        if ((row = sql_fetch_row(mdb)) == NULL) {
             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
-         } else {
-            pdbr->PoolId = str_to_int64(row[0]);
+        } else {
+           pdbr->PoolId = str_to_int64(row[0]);
             bstrncpy(pdbr->Name, row[1]!=NULL?row[1]:"", sizeof(pdbr->Name));
-            pdbr->NumVols = str_to_int64(row[2]);
-            pdbr->MaxVols = str_to_int64(row[3]);
-            pdbr->UseOnce = str_to_int64(row[4]);
-            pdbr->UseCatalog = str_to_int64(row[5]);
-            pdbr->AcceptAnyVolume = str_to_int64(row[6]);
-            pdbr->AutoPrune = str_to_int64(row[7]);
-            pdbr->Recycle = str_to_int64(row[8]);
-            pdbr->VolRetention = str_to_int64(row[9]);
-            pdbr->VolUseDuration = str_to_int64(row[10]);
-            pdbr->MaxVolJobs = str_to_int64(row[11]);
-            pdbr->MaxVolFiles = str_to_int64(row[12]);
-            pdbr->MaxVolBytes = str_to_uint64(row[13]);
+           pdbr->NumVols = str_to_int64(row[2]);
+           pdbr->MaxVols = str_to_int64(row[3]);
+           pdbr->UseOnce = str_to_int64(row[4]);
+           pdbr->UseCatalog = str_to_int64(row[5]);
+           pdbr->AcceptAnyVolume = str_to_int64(row[6]);
+           pdbr->AutoPrune = str_to_int64(row[7]);
+           pdbr->Recycle = str_to_int64(row[8]);
+           pdbr->VolRetention = str_to_int64(row[9]);
+           pdbr->VolUseDuration = str_to_int64(row[10]);
+           pdbr->MaxVolJobs = str_to_int64(row[11]);
+           pdbr->MaxVolFiles = str_to_int64(row[12]);
+           pdbr->MaxVolBytes = str_to_uint64(row[13]);
             bstrncpy(pdbr->PoolType, row[14]!=NULL?row[14]:"", sizeof(pdbr->PoolType));
-            pdbr->LabelType = str_to_int64(row[15]);
+           pdbr->LabelType = str_to_int64(row[15]);
             bstrncpy(pdbr->LabelFormat, row[16]!=NULL?row[16]:"", sizeof(pdbr->LabelFormat));
-            ok = true;
-         }
+           ok = true;
+        }
       } else {
          Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
       }
@@ -592,6 +592,10 @@ bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
    } else {
       Mmsg(mdb->errmsg, _("Pool record not found in Catalog.\n"));
    }
+   if (ok) {
+      Mmsg(mdb->cmd, "SELECT count(*) from Pool");
+      pdbr->NumVols = get_sql_record_max(jcr, mdb);
+   }
    db_unlock(mdb);
    return ok;
 }
@@ -601,7 +605,7 @@ bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr)
  *  otherwise, we search on the Client Name
  *
  * Returns: 0 on failure
- *          1 on success
+ *         1 on success
  */
 int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
 {
@@ -610,12 +614,12 @@ int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
    char ed1[50];
 
    db_lock(mdb);
-   if (cdbr->ClientId != 0) {               /* find by id */
+   if (cdbr->ClientId != 0) {              /* find by id */
       Mmsg(mdb->cmd,
 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
 "FROM Client WHERE Client.ClientId=%s", 
-        edit_int64(cdbr->ClientId, ed1));
-   } else {                           /* find by name */
+       edit_int64(cdbr->ClientId, ed1));
+   } else {                          /* find by name */
       Mmsg(mdb->cmd,
 "SELECT ClientId,Name,Uname,AutoPrune,FileRetention,JobRetention "
 "FROM Client WHERE Client.Name='%s'", cdbr->Name);
@@ -625,21 +629,21 @@ int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
       mdb->num_rows = sql_num_rows(mdb);
       if (mdb->num_rows > 1) {
          Mmsg1(&mdb->errmsg, _("More than one Client!: %s\n"),
-            edit_uint64(mdb->num_rows, ed1));
+           edit_uint64(mdb->num_rows, ed1));
          Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
       } else if (mdb->num_rows == 1) {
-         if ((row = sql_fetch_row(mdb)) == NULL) {
+        if ((row = sql_fetch_row(mdb)) == NULL) {
             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
-         } else {
-            cdbr->ClientId = str_to_int64(row[0]);
+        } else {
+           cdbr->ClientId = str_to_int64(row[0]);
             bstrncpy(cdbr->Name, row[1]!=NULL?row[1]:"", sizeof(cdbr->Name));
             bstrncpy(cdbr->Uname, row[2]!=NULL?row[1]:"", sizeof(cdbr->Uname));
-            cdbr->AutoPrune = str_to_int64(row[3]);
-            cdbr->FileRetention = str_to_int64(row[4]);
-            cdbr->JobRetention = str_to_int64(row[5]);
-            stat = 1;
-         }
+           cdbr->AutoPrune = str_to_int64(row[3]);
+           cdbr->FileRetention = str_to_int64(row[4]);
+           cdbr->JobRetention = str_to_int64(row[5]);
+           stat = 1;
+        }
       } else {
          Mmsg(mdb->errmsg, _("Client record not found in Catalog.\n"));
       }
@@ -655,7 +659,7 @@ int db_get_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cdbr)
  * Get Counter Record
  *
  * Returns: 0 on failure
- *          1 on success
+ *         1 on success
  */
 int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
 {
@@ -674,24 +678,24 @@ int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
          Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
       }
       if (mdb->num_rows >= 1) {
-         if ((row = sql_fetch_row(mdb)) == NULL) {
+        if ((row = sql_fetch_row(mdb)) == NULL) {
             Mmsg1(&mdb->errmsg, _("error fetching Counter row: %s\n"), sql_strerror(mdb));
             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
-            sql_free_result(mdb);
-            db_unlock(mdb);
-            return 0;
-         }
-         cr->MinValue = atoi(row[0]);
-         cr->MaxValue = atoi(row[1]);
-         cr->CurrentValue = atoi(row[2]);
-         if (row[3]) {
-            bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
-         } else {
-            cr->WrapCounter[0] = 0;
-         }
-         sql_free_result(mdb);
-         db_unlock(mdb);
-         return 1;
+           sql_free_result(mdb);
+           db_unlock(mdb);
+           return 0;
+        }
+        cr->MinValue = str_to_int64(row[0]);
+        cr->MaxValue = str_to_int64(row[1]);
+        cr->CurrentValue = str_to_int64(row[2]);
+        if (row[3]) {
+           bstrncpy(cr->WrapCounter, row[3], sizeof(cr->WrapCounter));
+        } else {
+           cr->WrapCounter[0] = 0;
+        }
+        sql_free_result(mdb);
+        db_unlock(mdb);
+        return 1;
       }
       sql_free_result(mdb);
    } else {
@@ -707,7 +711,7 @@ int db_get_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
  *  otherwise, we search on the name
  *
  * Returns: 0 on failure
- *          id on success
+ *         id on success
  */
 int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
 {
@@ -716,12 +720,12 @@ int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
    char ed1[50];
 
    db_lock(mdb);
-   if (fsr->FileSetId != 0) {               /* find by id */
+   if (fsr->FileSetId != 0) {              /* find by id */
       Mmsg(mdb->cmd,
            "SELECT FileSetId,FileSet,MD5,CreateTime FROM FileSet "
            "WHERE FileSetId=%s", 
-           edit_int64(fsr->FileSetId, ed1));
-   } else {                           /* find by name */
+          edit_int64(fsr->FileSetId, ed1));
+   } else {                          /* find by name */
       Mmsg(mdb->cmd,
            "SELECT FileSetId,FileSet,CreateTime,MD5 FROM FileSet "
            "WHERE FileSet='%s' ORDER BY CreateTime DESC LIMIT 1", fsr->FileSet);
@@ -730,19 +734,19 @@ int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
       mdb->num_rows = sql_num_rows(mdb);
       if (mdb->num_rows > 1) {
-         char ed1[30];
+        char ed1[30];
          Mmsg1(&mdb->errmsg, _("Error got %s FileSets but expected only one!\n"),
-            edit_uint64(mdb->num_rows, ed1));
-         sql_data_seek(mdb, mdb->num_rows-1);
+           edit_uint64(mdb->num_rows, ed1));
+        sql_data_seek(mdb, mdb->num_rows-1);
       }
       if ((row = sql_fetch_row(mdb)) == NULL) {
          Mmsg1(&mdb->errmsg, _("FileSet record \"%s\" not found.\n"), fsr->FileSet);
       } else {
-         fsr->FileSetId = str_to_int64(row[0]);
+        fsr->FileSetId = str_to_int64(row[0]);
          bstrncpy(fsr->FileSet, row[1]!=NULL?row[1]:"", sizeof(fsr->FileSet));
          bstrncpy(fsr->MD5, row[2]!=NULL?row[2]:"", sizeof(fsr->MD5));
          bstrncpy(fsr->cCreateTime, row[3]!=NULL?row[3]:"", sizeof(fsr->cCreateTime));
-         stat = fsr->FileSetId;
+        stat = fsr->FileSetId;
       }
       sql_free_result(mdb);
    } else {
@@ -757,7 +761,7 @@ int db_get_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
  * Get the number of Media records
  *
  * Returns: -1 on failure
- *          number on success
+ *         number on success
  */
 int db_get_num_media_records(JCR *jcr, B_DB *mdb)
 {
@@ -777,7 +781,7 @@ int db_get_num_media_records(JCR *jcr, B_DB *mdb)
  *  The caller must free ids if non-NULL.
  *
  *  Returns 0: on failure
- *          1: on success
+ *         1: on success
  */
 int db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_t *ids[])
 {
@@ -794,11 +798,11 @@ int db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_
    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
       *num_ids = sql_num_rows(mdb);
       if (*num_ids > 0) {
-         id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
-         while ((row = sql_fetch_row(mdb)) != NULL) {
-            id[i++] = (uint32_t)atoi(row[0]);
-         }
-         *ids = id;
+        id = (uint32_t *)malloc(*num_ids * sizeof(uint32_t));
+        while ((row = sql_fetch_row(mdb)) != NULL) {
+           id[i++] = str_to_uint64(row[0]);
+        }
+        *ids = id;
       }
       sql_free_result(mdb);
       stat = 1;
@@ -815,7 +819,7 @@ int db_get_media_ids(JCR *jcr, B_DB *mdb, uint32_t PoolId, int *num_ids, uint32_
 /* Get Media Record
  *
  * Returns: 0 on failure
- *          id on success
+ *         id on success
  */
 int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
 {
@@ -830,15 +834,15 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
       db_unlock(mdb);
       return 1;
    }
-   if (mr->MediaId != 0) {               /* find by id */
+   if (mr->MediaId != 0) {              /* find by id */
       Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
          "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
          "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
          "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
          "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId "
          "FROM Media WHERE MediaId=%s", 
-         edit_int64(mr->MediaId, ed1));
-   } else {                           /* find by name */
+        edit_int64(mr->MediaId, ed1));
+   } else {                          /* find by name */
       Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks,"
          "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
          "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
@@ -852,65 +856,65 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
       mdb->num_rows = sql_num_rows(mdb);
       if (mdb->num_rows > 1) {
          Mmsg1(&mdb->errmsg, _("More than one Volume!: %s\n"),
-            edit_uint64(mdb->num_rows, ed1));
+           edit_uint64(mdb->num_rows, ed1));
          Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
       } else if (mdb->num_rows == 1) {
-         if ((row = sql_fetch_row(mdb)) == NULL) {
+        if ((row = sql_fetch_row(mdb)) == NULL) {
             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
-         } else {
-            /* return values */
-            mr->MediaId = str_to_int64(row[0]);
+        } else {
+           /* return values */
+           mr->MediaId = str_to_int64(row[0]);
             bstrncpy(mr->VolumeName, row[1]!=NULL?row[1]:"", sizeof(mr->VolumeName));
-            mr->VolJobs = str_to_int64(row[2]);
-            mr->VolFiles = str_to_int64(row[3]);
-            mr->VolBlocks = str_to_int64(row[4]);
-            mr->VolBytes = str_to_uint64(row[5]);
-            mr->VolMounts = str_to_int64(row[6]);
-            mr->VolErrors = str_to_int64(row[7]);
-            mr->VolWrites = str_to_int64(row[8]);
-            mr->MaxVolBytes = str_to_uint64(row[9]);
-            mr->VolCapacityBytes = str_to_uint64(row[10]);
+           mr->VolJobs = str_to_int64(row[2]);
+           mr->VolFiles = str_to_int64(row[3]);
+           mr->VolBlocks = str_to_int64(row[4]);
+           mr->VolBytes = str_to_uint64(row[5]);
+           mr->VolMounts = str_to_int64(row[6]);
+           mr->VolErrors = str_to_int64(row[7]);
+           mr->VolWrites = str_to_int64(row[8]);
+           mr->MaxVolBytes = str_to_uint64(row[9]);
+           mr->VolCapacityBytes = str_to_uint64(row[10]);
             bstrncpy(mr->MediaType, row[11]!=NULL?row[11]:"", sizeof(mr->MediaType));
             bstrncpy(mr->VolStatus, row[12]!=NULL?row[12]:"", sizeof(mr->VolStatus));
-            mr->PoolId = str_to_int64(row[13]);
-            mr->VolRetention = str_to_uint64(row[14]);
-            mr->VolUseDuration = str_to_uint64(row[15]);
-            mr->MaxVolJobs = str_to_int64(row[16]);
-            mr->MaxVolFiles = str_to_int64(row[17]);
-            mr->Recycle = str_to_int64(row[18]);
-            mr->Slot = str_to_int64(row[19]);
+           mr->PoolId = str_to_int64(row[13]);
+           mr->VolRetention = str_to_uint64(row[14]);
+           mr->VolUseDuration = str_to_uint64(row[15]);
+           mr->MaxVolJobs = str_to_int64(row[16]);
+           mr->MaxVolFiles = str_to_int64(row[17]);
+           mr->Recycle = str_to_int64(row[18]);
+           mr->Slot = str_to_int64(row[19]);
             bstrncpy(mr->cFirstWritten, row[20]!=NULL?row[20]:"", sizeof(mr->cFirstWritten));
-            mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
+           mr->FirstWritten = (time_t)str_to_utime(mr->cFirstWritten);
             bstrncpy(mr->cLastWritten, row[21]!=NULL?row[21]:"", sizeof(mr->cLastWritten));
-            mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
-            mr->InChanger = str_to_uint64(row[22]);
-            mr->EndFile = str_to_uint64(row[23]);
-            mr->EndBlock = str_to_uint64(row[24]);
-            mr->VolParts = str_to_int64(row[25]);
-            mr->LabelType = str_to_int64(row[26]);
+           mr->LastWritten = (time_t)str_to_utime(mr->cLastWritten);
+           mr->InChanger = str_to_uint64(row[22]);
+           mr->EndFile = str_to_uint64(row[23]);
+           mr->EndBlock = str_to_uint64(row[24]);
+           mr->VolParts = str_to_int64(row[25]);
+           mr->LabelType = str_to_int64(row[26]);
             bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate));
-            mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
-            mr->StorageId = str_to_int64(row[28]);
-            stat = mr->MediaId;
-         }
+           mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate);
+           mr->StorageId = str_to_int64(row[28]);
+           stat = mr->MediaId;
+        }
       } else {
-         if (mr->MediaId != 0) {
+        if (mr->MediaId != 0) {
             Mmsg1(&mdb->errmsg, _("Media record MediaId=%s not found.\n"), 
-               edit_int64(mr->MediaId, ed1));
-         } else {
+              edit_int64(mr->MediaId, ed1));
+        } else {
             Mmsg1(&mdb->errmsg, _("Media record for Volume \"%s\" not found.\n"),
-                  mr->VolumeName);
-         }
+                 mr->VolumeName);
+        }
       }
       sql_free_result(mdb);
    } else {
       if (mr->MediaId != 0) {
          Mmsg(mdb->errmsg, _("Media record for MediaId=%u not found in Catalog.\n"),
-            mr->MediaId);
+           mr->MediaId);
        } else {
          Mmsg(mdb->errmsg, _("Media record for Vol=%s not found in Catalog.\n"),
-            mr->VolumeName);
+           mr->VolumeName);
    }   }
    db_unlock(mdb);
    return stat;
index c1e499cd2d0fb33d3fc0529b9d58d9134b4fe69f..17ff0a194657b8cf3e69e9dfdf64b1abb266e75f 100644 (file)
@@ -134,13 +134,14 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
         send_volume_info_to_storage_daemon(jcr, bs, &mr);
       } else {
          bnet_fsend(bs, "1901 No Media.\n");
+         Dmsg0(500, "1901 No Media.\n");
       }
 
    /*
     * Request to find specific Volume information
     */
    } else if (sscanf(bs->msg, Get_Vol_Info, &Job, &mr.VolumeName, &writing) == 3) {
-      Dmsg1(400, "CatReq GetVolInfo Vol=%s\n", mr.VolumeName);
+      Dmsg1(500, "CatReq GetVolInfo Vol=%s\n", mr.VolumeName);
       /*
        * Find the Volume
        */
@@ -194,6 +195,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
 
       } else {
          bnet_fsend(bs, "1997 Volume \"%s\" not in catalog.\n", mr.VolumeName);
+         Dmsg1(400, "1997 Volume \"%s\" not in catalog.\n", mr.VolumeName);
       }
 
    /*
index 9fed95bc7afac06e2ff605225f6484815cfe54b9..6d7af10e52db673848ee33006f8c2d9948ab6d1b 100644 (file)
@@ -517,7 +517,7 @@ static int check_resources()
            int64_t *def_lvalue, *lvalue; /* 64 bit values */
            uint32_t offset;
 
-            Dmsg4(400, "Job \"%s\", field \"%s\" bit=%d def=%d\n",
+            Dmsg4(1400, "Job \"%s\", field \"%s\" bit=%d def=%d\n",
                job->hdr.name, job_items[i].name,
                bit_is_set(i, job->hdr.item_present),
                bit_is_set(i, job->jobdefs->hdr.item_present));
index ef9a1d7c58bd99b68b7277d1a6cc1d036969e49c..8175a89258ed14634fcf97cbe1076add0cfb25ee 100644 (file)
@@ -36,8 +36,6 @@ static void job_monitor_destructor(watchdog_t *self);
 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr);
 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr);
 
-/* Exported subroutines */
-
 /* Imported subroutines */
 extern void term_scheduler();
 extern void term_ua_server();
index 984fea3238afa926f05d5ff275994145ec87d1d7..ccc794e92923b6862609f678f84a2ae9b37bba3e 100755 (executable)
@@ -55,7 +55,7 @@ static bool acquire_resources(JCR *jcr);
  * Initialize a job queue
  *
  *  Returns: 0 on success
- *          errno on failure
+ *           errno on failure
  */
 int jobq_init(jobq_t *jq, int threads, void *(*engine)(void *arg))
 {
@@ -85,10 +85,10 @@ int jobq_init(jobq_t *jq, int threads, void *(*engine)(void *arg))
       return stat;
    }
    jq->quit = false;
-   jq->max_workers = threads;        /* max threads to create */
-   jq->num_workers = 0;              /* no threads yet */
-   jq->idle_workers = 0;             /* no idle threads */
-   jq->engine = engine;              /* routine to run */
+   jq->max_workers = threads;         /* max threads to create */
+   jq->num_workers = 0;               /* no threads yet */
+   jq->idle_workers = 0;              /* no idle threads */
+   jq->engine = engine;               /* routine to run */
    jq->valid = JOBQ_VALID;
    /* Initialize the job queues */
    jq->waiting_jobs = New(dlist(item, &item->link));
@@ -101,7 +101,7 @@ int jobq_init(jobq_t *jq, int threads, void *(*engine)(void *arg))
  * Destroy the job queue
  *
  * Returns: 0 on success
- *         errno on failure
+ *          errno on failure
  */
 int jobq_destroy(jobq_t *jq)
 {
@@ -115,7 +115,7 @@ int jobq_destroy(jobq_t *jq)
       Jmsg1(NULL, M_ERROR, 0, "pthread_mutex_lock: ERR=%s\n", be.strerror(stat));
       return stat;
    }
-   jq->valid = 0;                     /* prevent any more operations */
+   jq->valid = 0;                      /* prevent any more operations */
 
    /* 
     * If any threads are active, wake them 
@@ -123,20 +123,20 @@ int jobq_destroy(jobq_t *jq)
    if (jq->num_workers > 0) {
       jq->quit = true;
       if (jq->idle_workers) {
-        if ((stat = pthread_cond_broadcast(&jq->work)) != 0) {
-           berrno be;
+         if ((stat = pthread_cond_broadcast(&jq->work)) != 0) {
+            berrno be;
             Jmsg1(NULL, M_ERROR, 0, "pthread_cond_broadcast: ERR=%s\n", be.strerror(stat));
-           pthread_mutex_unlock(&jq->mutex);
-           return stat;
-        }
+            pthread_mutex_unlock(&jq->mutex);
+            return stat;
+         }
       }
       while (jq->num_workers > 0) {
-        if ((stat = pthread_cond_wait(&jq->work, &jq->mutex)) != 0) {
-           berrno be;
+         if ((stat = pthread_cond_wait(&jq->work, &jq->mutex)) != 0) {
+            berrno be;
             Jmsg1(NULL, M_ERROR, 0, "pthread_cond_wait: ERR=%s\n", be.strerror(stat));
-           pthread_mutex_unlock(&jq->mutex);
-           return stat;
-        }
+            pthread_mutex_unlock(&jq->mutex);
+            return stat;
+         }
       }
    }
    if ((stat = pthread_mutex_unlock(&jq->mutex)) != 0) {
@@ -178,24 +178,24 @@ void *sched_wait(void *arg)
    /* Wait until scheduled time arrives */
    if (wtime > 0) {
       Jmsg(jcr, M_INFO, 0, _("Job %s waiting %d seconds for scheduled start time.\n"),
-        jcr->Job, wtime);
+         jcr->Job, wtime);
    }
    /* Check every 30 seconds if canceled */
    while (wtime > 0) {
       Dmsg2(2300, "Waiting on sched time, jobid=%d secs=%d\n", jcr->JobId, wtime);
       if (wtime > 30) {
-        wtime = 30;
+         wtime = 30;
       }
       bmicrosleep(wtime, 0);
       if (job_canceled(jcr)) {
-        break;
+         break;
       }
       wtime = jcr->sched_time - time(NULL);
    }
-   P(jcr->mutex);                    /* lock jcr */
+   P(jcr->mutex);                     /* lock jcr */
    jobq_add(jq, jcr);
    V(jcr->mutex);
-   free_jcr(jcr);                    /* we are done with jcr */
+   free_jcr(jcr);                     /* we are done with jcr */
    Dmsg0(2300, "Exit sched_wait\n");
    return NULL;
 }
@@ -222,17 +222,17 @@ int jobq_add(jobq_t *jq, JCR *jcr)
       return EINVAL;
    }
 
-   jcr->use_count++;                 /* mark jcr in use by us */
+   jcr->use_count++;                  /* mark jcr in use by us */
    Dmsg3(2300, "jobq_add jobid=%d jcr=0x%x use_count=%d\n", jcr->JobId, jcr, jcr->use_count);
    if (!job_canceled(jcr) && wtime > 0) {
       set_thread_concurrency(jq->max_workers + 2);
       sched_pkt = (wait_pkt *)malloc(sizeof(wait_pkt));
       sched_pkt->jcr = jcr;
       sched_pkt->jq = jq;
-//    jcr->use_count--;           /* release our use of jcr */
-      stat = pthread_create(&id, &jq->attr, sched_wait, (void *)sched_pkt);       
-      if (stat != 0) {               /* thread not created */
-        berrno be;
+//    jcr->use_count--;            /* release our use of jcr */
+      stat = pthread_create(&id, &jq->attr, sched_wait, (void *)sched_pkt);        
+      if (stat != 0) {                /* thread not created */
+         berrno be;
          Jmsg1(jcr, M_ERROR, 0, "pthread_thread_create: ERR=%s\n", be.strerror(stat));
       }
       return stat;
@@ -241,12 +241,12 @@ int jobq_add(jobq_t *jq, JCR *jcr)
    if ((stat = pthread_mutex_lock(&jq->mutex)) != 0) {
       berrno be;
       Jmsg1(jcr, M_ERROR, 0, "pthread_mutex_lock: ERR=%s\n", be.strerror(stat));
-      jcr->use_count--;              /* release jcr */
+      jcr->use_count--;               /* release jcr */
       return stat;
    }
 
    if ((item = (jobq_item_t *)malloc(sizeof(jobq_item_t))) == NULL) {
-      jcr->use_count--;              /* release jcr */
+      jcr->use_count--;               /* release jcr */
       return ENOMEM;
    }
    item->jcr = jcr;
@@ -259,18 +259,18 @@ int jobq_add(jobq_t *jq, JCR *jcr)
       /* Add this job to the wait queue in priority sorted order */
       foreach_dlist(li, jq->waiting_jobs) {
          Dmsg2(2300, "waiting item jobid=%d priority=%d\n",
-           li->jcr->JobId, li->jcr->JobPriority);
-        if (li->jcr->JobPriority > jcr->JobPriority) {
-           jq->waiting_jobs->insert_before(item, li);
+            li->jcr->JobId, li->jcr->JobPriority);
+         if (li->jcr->JobPriority > jcr->JobPriority) {
+            jq->waiting_jobs->insert_before(item, li);
             Dmsg2(2300, "insert_before jobid=%d before waiting job=%d\n",
-              li->jcr->JobId, jcr->JobId);
-           inserted = true;
-           break;
-        }
+               li->jcr->JobId, jcr->JobId);
+            inserted = true;
+            break;
+         }
       }
       /* If not jobs in wait queue, append it */
       if (!inserted) {
-        jq->waiting_jobs->append(item);
+         jq->waiting_jobs->append(item);
          Dmsg1(2300, "Appended item jobid=%d to waiting queue\n", jcr->JobId);
       }
    }
@@ -311,8 +311,8 @@ int jobq_remove(jobq_t *jq, JCR *jcr)
 
    foreach_dlist(item, jq->waiting_jobs) {
       if (jcr == item->jcr) {
-        found = true;
-        break;
+         found = true;
+         break;
       }
    }
    if (!found) {
@@ -342,22 +342,26 @@ static int start_server(jobq_t *jq)
    int stat = 0;
    pthread_t id;
 
-   /* if any threads are idle, wake one */
+   /*
+    * if any threads are idle, wake one --                
+    *   actually we do a broadcast because on /lib/tls 
+    *   these signals seem to get lost from time to time.
+    */
    if (jq->idle_workers > 0) {
       Dmsg0(2300, "Signal worker to wake up\n");
-      if ((stat = pthread_cond_signal(&jq->work)) != 0) {
-        berrno be;
+      if ((stat = pthread_cond_broadcast(&jq->work)) != 0) {
+         berrno be;
          Jmsg1(NULL, M_ERROR, 0, "pthread_cond_signal: ERR=%s\n", be.strerror(stat));
-        return stat;
+         return stat;
       }
    } else if (jq->num_workers < jq->max_workers) {
       Dmsg0(2300, "Create worker thread\n");
       /* No idle threads so create a new one */
       set_thread_concurrency(jq->max_workers + 1);
       if ((stat = pthread_create(&id, &jq->attr, jobq_server, (void *)jq)) != 0) {
-        berrno be;
+         berrno be;
          Jmsg1(NULL, M_ERROR, 0, "pthread_create: ERR=%s\n", be.strerror(stat));
-        return stat;
+         return stat;
       }
    }
    return stat;
@@ -374,7 +378,7 @@ void *jobq_server(void *arg)
 {
    struct timespec timeout;
    jobq_t *jq = (jobq_t *)arg;
-   jobq_item_t *je;                  /* job entry in queue */
+   jobq_item_t *je;                   /* job entry in queue */
    int stat;
    bool timedout = false;
    bool work = true;
@@ -393,138 +397,138 @@ void *jobq_server(void *arg)
 
       Dmsg0(2300, "Top of for loop\n");
       if (!work && !jq->quit) {
-        gettimeofday(&tv, &tz);
-        timeout.tv_nsec = 0;
-        timeout.tv_sec = tv.tv_sec + 4;
-
-        while (!jq->quit) {
-           /*
-            * Wait 4 seconds, then if no more work, exit
-            */
+         gettimeofday(&tv, &tz);
+         timeout.tv_nsec = 0;
+         timeout.tv_sec = tv.tv_sec + 4;
+
+         while (!jq->quit) {
+            /*
+             * Wait 4 seconds, then if no more work, exit
+             */
             Dmsg0(2300, "pthread_cond_timedwait()\n");
-           stat = pthread_cond_timedwait(&jq->work, &jq->mutex, &timeout);
-           if (stat == ETIMEDOUT) {
+            stat = pthread_cond_timedwait(&jq->work, &jq->mutex, &timeout);
+            if (stat == ETIMEDOUT) {
                Dmsg0(2300, "timedwait timedout.\n");
-              timedout = true;
-              break;
-           } else if (stat != 0) {
+               timedout = true;
+               break;
+            } else if (stat != 0) {
                /* This shouldn't happen */
                Dmsg0(2300, "This shouldn't happen\n");
-              jq->num_workers--;
-              pthread_mutex_unlock(&jq->mutex);
-              return NULL;
-           }
-           break;
-        }
+               jq->num_workers--;
+               pthread_mutex_unlock(&jq->mutex);
+               return NULL;
+            }
+            break;
+         }
       }
       /*
        * If anything is in the ready queue, run it
        */
       Dmsg0(2300, "Checking ready queue.\n");
       while (!jq->ready_jobs->empty() && !jq->quit) {
-        JCR *jcr;
-        je = (jobq_item_t *)jq->ready_jobs->first();
-        jcr = je->jcr;
-        jq->ready_jobs->remove(je);
-        if (!jq->ready_jobs->empty()) {
+         JCR *jcr;
+         je = (jobq_item_t *)jq->ready_jobs->first();
+         jcr = je->jcr;
+         jq->ready_jobs->remove(je);
+         if (!jq->ready_jobs->empty()) {
             Dmsg0(2300, "ready queue not empty start server\n");
-           if (start_server(jq) != 0) {
-              jq->num_workers--;
-              pthread_mutex_unlock(&jq->mutex);
-              return NULL;
-           }
-        }
-        jq->running_jobs->append(je);
+            if (start_server(jq) != 0) {
+               jq->num_workers--;
+               pthread_mutex_unlock(&jq->mutex);
+               return NULL;
+            }
+         }
+         jq->running_jobs->append(je);
          Dmsg1(2300, "Took jobid=%d from ready and appended to run\n", jcr->JobId);
 
-        /* Release job queue lock */
-        V(jq->mutex);
+         /* Release job queue lock */
+         V(jq->mutex);
 
          /* Call user's routine here */
          Dmsg1(2300, "Calling user engine for jobid=%d\n", jcr->JobId);
-        jq->engine(je->jcr);
+         jq->engine(je->jcr);
 
          Dmsg1(2300, "Back from user engine jobid=%d.\n", jcr->JobId);
 
-        /* Reacquire job queue lock */
-        P(jq->mutex);
+         /* Reacquire job queue lock */
+         P(jq->mutex);
          Dmsg0(200, "Done lock mutex after running job. Release locks.\n");
-        jq->running_jobs->remove(je);
-        /*
-         * Release locks if acquired. Note, they will not have
-         *  been acquired for jobs canceled before they were
-         *  put into the ready queue.
-         */
-        if (jcr->acquired_resource_locks) {
-           jcr->store->NumConcurrentJobs--;
-           jcr->client->NumConcurrentJobs--;
-           jcr->job->NumConcurrentJobs--;
-        }
-
-        /*
-         * Reschedule the job if necessary and requested
-         */
-        if (jcr->job->RescheduleOnError &&
-            jcr->JobStatus != JS_Terminated &&
-            jcr->JobStatus != JS_Canceled &&
-            jcr->job->RescheduleTimes > 0 &&
-            jcr->reschedule_count < jcr->job->RescheduleTimes) {
-            char dt[50];
-
-            /*
-             * Reschedule this job by cleaning it up, but
-             *  reuse the same JobId if possible.
-             */
-           jcr->reschedule_count++;
-           jcr->sched_time = time(NULL) + jcr->job->RescheduleInterval;
+         jq->running_jobs->remove(je);
+         /*
+          * Release locks if acquired. Note, they will not have
+          *  been acquired for jobs canceled before they were
+          *  put into the ready queue.
+          */
+         if (jcr->acquired_resource_locks) {
+            jcr->store->NumConcurrentJobs--;
+            jcr->client->NumConcurrentJobs--;
+            jcr->job->NumConcurrentJobs--;
+         }
+
+         /*
+          * Reschedule the job if necessary and requested
+          */
+         if (jcr->job->RescheduleOnError &&
+             jcr->JobStatus != JS_Terminated &&
+             jcr->JobStatus != JS_Canceled &&
+             jcr->job->RescheduleTimes > 0 &&
+             jcr->reschedule_count < jcr->job->RescheduleTimes) {
+             char dt[50];
+
+             /*
+              * Reschedule this job by cleaning it up, but
+              *  reuse the same JobId if possible.
+              */
+            jcr->reschedule_count++;
+            jcr->sched_time = time(NULL) + jcr->job->RescheduleInterval;
             Dmsg2(2300, "Rescheduled Job %s to re-run in %d seconds.\n", jcr->Job,
-              (int)jcr->job->RescheduleInterval);
-           bstrftime(dt, sizeof(dt), time(NULL));
+               (int)jcr->job->RescheduleInterval);
+            bstrftime(dt, sizeof(dt), time(NULL));
             Jmsg(jcr, M_INFO, 0, _("Rescheduled Job %s at %s to re-run in %d seconds.\n"),
-              jcr->Job, dt, (int)jcr->job->RescheduleInterval);
-           dird_free_jcr_pointers(jcr);     /* partial cleanup old stuff */
-           jcr->JobStatus = JS_WaitStartTime;
-           jcr->SDJobStatus = 0;
-           if (jcr->JobBytes == 0) {
+               jcr->Job, dt, (int)jcr->job->RescheduleInterval);
+            dird_free_jcr_pointers(jcr);     /* partial cleanup old stuff */
+            jcr->JobStatus = JS_WaitStartTime;
+            jcr->SDJobStatus = 0;
+            if (jcr->JobBytes == 0) {
                Dmsg1(2300, "Requeue job=%d\n", jcr->JobId);
-              jcr->JobStatus = JS_WaitStartTime;
-              V(jq->mutex);
-              jobq_add(jq, jcr);     /* queue the job to run again */
-              P(jq->mutex);
-              free(je);              /* free the job entry */
-              continue;              /* look for another job to run */
-           }
-           /*
-            * Something was actually backed up, so we cannot reuse
-            *   the old JobId or there will be database record
-            *   conflicts.  We now create a new job, copying the
-            *   appropriate fields.
-            */
-           JCR *njcr = new_jcr(sizeof(JCR), dird_free_jcr);
-           set_jcr_defaults(njcr, jcr->job);
-           njcr->reschedule_count = jcr->reschedule_count;
-           njcr->JobLevel = jcr->JobLevel;
-           njcr->JobStatus = jcr->JobStatus;
-           copy_storage(njcr, jcr);
-           njcr->messages = jcr->messages;
+               jcr->JobStatus = JS_WaitStartTime;
+               V(jq->mutex);
+               jobq_add(jq, jcr);     /* queue the job to run again */
+               P(jq->mutex);
+               free(je);              /* free the job entry */
+               continue;              /* look for another job to run */
+            }
+            /*
+             * Something was actually backed up, so we cannot reuse
+             *   the old JobId or there will be database record
+             *   conflicts.  We now create a new job, copying the
+             *   appropriate fields.
+             */
+            JCR *njcr = new_jcr(sizeof(JCR), dird_free_jcr);
+            set_jcr_defaults(njcr, jcr->job);
+            njcr->reschedule_count = jcr->reschedule_count;
+            njcr->JobLevel = jcr->JobLevel;
+            njcr->JobStatus = jcr->JobStatus;
+            copy_storage(njcr, jcr);
+            njcr->messages = jcr->messages;
             Dmsg0(2300, "Call to run new job\n");
-           V(jq->mutex);
+            V(jq->mutex);
             run_job(njcr);            /* This creates a "new" job */
             free_jcr(njcr);           /* release "new" jcr */
-           P(jq->mutex);
+            P(jq->mutex);
             Dmsg0(2300, "Back from running new job.\n");
-        }
-        /* Clean up and release old jcr */
-        if (jcr->db) {
-           db_close_database(jcr, jcr->db);
-           jcr->db = NULL;
-        }
+         }
+         /* Clean up and release old jcr */
+         if (jcr->db) {
+            db_close_database(jcr, jcr->db);
+            jcr->db = NULL;
+         }
          Dmsg2(2300, "====== Termination job=%d use_cnt=%d\n", jcr->JobId, jcr->use_count);
-        jcr->SDJobStatus = 0;
-        V(jq->mutex);                /* release internal lock */
-        free_jcr(jcr);
-        free(je);                    /* release job entry */
-        P(jq->mutex);                /* reacquire job queue lock */
+         jcr->SDJobStatus = 0;
+         V(jq->mutex);                /* release internal lock */
+         free_jcr(jcr);
+         free(je);                    /* release job entry */
+         P(jq->mutex);                /* reacquire job queue lock */
       }
       /*
        * If any job in the wait queue can be run,
@@ -532,48 +536,48 @@ void *jobq_server(void *arg)
        */
       Dmsg0(2300, "Done check ready, now check wait queue.\n");
       if (!jq->waiting_jobs->empty() && !jq->quit) {
-        int Priority;
-        je = (jobq_item_t *)jq->waiting_jobs->first();
-        jobq_item_t *re = (jobq_item_t *)jq->running_jobs->first();
-        if (re) {
-           Priority = re->jcr->JobPriority;
+         int Priority;
+         je = (jobq_item_t *)jq->waiting_jobs->first();
+         jobq_item_t *re = (jobq_item_t *)jq->running_jobs->first();
+         if (re) {
+            Priority = re->jcr->JobPriority;
             Dmsg2(2300, "JobId %d is running. Look for pri=%d\n", re->jcr->JobId, Priority);
-        } else {
-           Priority = je->jcr->JobPriority;
+         } else {
+            Priority = je->jcr->JobPriority;
             Dmsg1(2300, "No job running. Look for Job pri=%d\n", Priority);
-        }
-        /*
-         * Walk down the list of waiting jobs and attempt
-         *   to acquire the resources it needs.
-         */
-        for ( ; je;  ) {
-           /* je is current job item on the queue, jn is the next one */
-           JCR *jcr = je->jcr;
-           jobq_item_t *jn = (jobq_item_t *)jq->waiting_jobs->next(je);
+         }
+         /*
+          * Walk down the list of waiting jobs and attempt
+          *   to acquire the resources it needs.
+          */
+         for ( ; je;  ) {
+            /* je is current job item on the queue, jn is the next one */
+            JCR *jcr = je->jcr;
+            jobq_item_t *jn = (jobq_item_t *)jq->waiting_jobs->next(je);
 
             Dmsg3(2300, "Examining Job=%d JobPri=%d want Pri=%d\n",
-              jcr->JobId, jcr->JobPriority, Priority);
-
-           /* Take only jobs of correct Priority */
-           if (jcr->JobPriority != Priority) {
-              set_jcr_job_status(jcr, JS_WaitPriority);
-              break;
-           }
-
-           if (!acquire_resources(jcr)) {
-              je = jn;            /* point to next waiting job */
-              continue;
-           }
-
-           /* Got all locks, now remove it from wait queue and append it
-            *   to the ready queue
-            */
-           jcr->acquired_resource_locks = true;
-           jq->waiting_jobs->remove(je);
-           jq->ready_jobs->append(je);
+               jcr->JobId, jcr->JobPriority, Priority);
+
+            /* Take only jobs of correct Priority */
+            if (jcr->JobPriority != Priority) {
+               set_jcr_job_status(jcr, JS_WaitPriority);
+               break;
+            }
+
+            if (!acquire_resources(jcr)) {
+               je = jn;            /* point to next waiting job */
+               continue;
+            }
+
+            /* Got all locks, now remove it from wait queue and append it
+             *   to the ready queue
+             */
+            jcr->acquired_resource_locks = true;
+            jq->waiting_jobs->remove(je);
+            jq->ready_jobs->append(je);
             Dmsg1(2300, "moved JobId=%d from wait to ready queue\n", je->jcr->JobId);
-           je = jn;                  /* Point to next waiting job */
-        } /* end for loop */
+            je = jn;                  /* Point to next waiting job */
+         } /* end for loop */
 
       } /* end if */
 
@@ -582,39 +586,39 @@ void *jobq_server(void *arg)
        * If no more ready work and we are asked to quit, then do it
        */
       if (jq->ready_jobs->empty() && jq->quit) {
-        jq->num_workers--;
-        if (jq->num_workers == 0) {
+         jq->num_workers--;
+         if (jq->num_workers == 0) {
             Dmsg0(2300, "Wake up destroy routine\n");
-           /* Wake up destroy routine if he is waiting */
-           pthread_cond_broadcast(&jq->work);
-        }
-        break;
+            /* Wake up destroy routine if he is waiting */
+            pthread_cond_broadcast(&jq->work);
+         }
+         break;
       }
       Dmsg0(2300, "Check for work request\n");
       /*
        * If no more work requests, and we waited long enough, quit
        */
       Dmsg2(2300, "timedout=%d read empty=%d\n", timedout,
-        jq->ready_jobs->empty());
+         jq->ready_jobs->empty());
       if (jq->ready_jobs->empty() && timedout) {
          Dmsg0(2300, "break big loop\n");
-        jq->num_workers--;
-        break;
+         jq->num_workers--;
+         break;
       }
 
       work = !jq->ready_jobs->empty() || !jq->waiting_jobs->empty();
       if (work) {
-        /*
+         /*
           * If a job is waiting on a Resource, don't consume all
-         *   the CPU time looping looking for work, and even more
-         *   important, release the lock so that a job that has
-         *   terminated can give us the resource.
-         */
-        V(jq->mutex);
-        bmicrosleep(2, 0);              /* pause for 2 seconds */
-        P(jq->mutex);
-        /* Recompute work as something may have changed in last 2 secs */
-        work = !jq->ready_jobs->empty() || !jq->waiting_jobs->empty();
+          *   the CPU time looping looking for work, and even more
+          *   important, release the lock so that a job that has
+          *   terminated can give us the resource.
+          */
+         V(jq->mutex);
+         bmicrosleep(2, 0);              /* pause for 2 seconds */
+         P(jq->mutex);
+         /* Recompute work as something may have changed in last 2 secs */
+         work = !jq->ready_jobs->empty() || !jq->waiting_jobs->empty();
       }
       Dmsg1(2300, "Loop again. work=%d\n", work);
    } /* end of big for loop */
@@ -629,7 +633,7 @@ void *jobq_server(void *arg)
  * See if we can acquire all the necessary resources for the job (JCR)
  *
  *  Returns: true  if successful
- *          false if resource failure
+ *           false if resource failure
  */
 static bool acquire_resources(JCR *jcr)
 {
@@ -641,14 +645,14 @@ static bool acquire_resources(JCR *jcr)
        *   of MaxConcurrentJobs.
        */ 
       if (jcr->store->NumConcurrentJobs == 0) {
-        jcr->store->NumConcurrentJobs = 1;
+         jcr->store->NumConcurrentJobs = 1;
       } else {
-        set_jcr_job_status(jcr, JS_WaitStoreRes);
-        return false;
+         set_jcr_job_status(jcr, JS_WaitStoreRes);
+         return false;
       }
    /* We are not doing a Restore or Verify */
    } else if (jcr->store->NumConcurrentJobs == 0 &&
-             jcr->store->NumConcurrentJobs < jcr->store->MaxConcurrentJobs) {
+              jcr->store->NumConcurrentJobs < jcr->store->MaxConcurrentJobs) {
        /* Simple case, first job */
        jcr->store->NumConcurrentJobs = 1;
    } else if (jcr->store->NumConcurrentJobs < jcr->store->MaxConcurrentJobs) {
index cd00b7170a155efe9971e980a801acf1fc1511ed..3215f71742206dcbe19f5a8b455ca98522e8d476 100644 (file)
@@ -42,7 +42,7 @@
 static char jobcmd[]     = "JobId=%d job=%s job_name=%s client_name=%s "
    "type=%d level=%d FileSet=%s NoAttr=%d SpoolAttr=%d FileSetMD5=%s "
    "SpoolData=%d WritePartAfterJob=%d NewVol=%d\n";
-static char use_storage[] = "use storage media_type=%s pool_name=%s "
+static char use_storage[] = "use storage=%s media_type=%s pool_name=%s "
    "pool_type=%s append=%d\n";
 static char use_device[] = "use device=%s\n";
 //static char query_device[] = "query device=%s";
@@ -130,7 +130,7 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append)
    STORE *storage;
    BSOCK *sd;
    char auth_key[100];
-   POOL_MEM device_name, pool_name, pool_type, media_type;
+   POOL_MEM store_name, device_name, pool_name, pool_type, media_type;
    char PoolId[50];
 
    sd = jcr->store_bsock;
@@ -187,10 +187,12 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append)
     */
 // foreach_alist(storage, store) {
       storage = (STORE *)store->first();
+      pm_strcpy(store_name, storage->hdr.name);
+      bash_spaces(store_name);
       pm_strcpy(media_type, storage->media_type);
       bash_spaces(media_type);
-      bnet_fsend(sd, use_storage, media_type.c_str(), pool_name.c_str(), 
-                pool_type.c_str(), append);
+      bnet_fsend(sd, use_storage, store_name.c_str(), media_type.c_str(), 
+                pool_name.c_str(), pool_type.c_str(), append);
 
       DEVICE *dev;
       /* Loop over alternative storage Devices until one is OK */
index 831cd93ad33b7ff15c06b09560f22960d140522a..7038aae3a702972253ed5acf631c9d85da5a0c7b 100644 (file)
 #include "dird.h"
 
 /* Forward referenced functions */
-static int create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr);
-static int perform_full_name_substitution(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr);
+static bool create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr);
+static bool perform_full_name_substitution(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr);
 
 
 /*
  * Automatic Volume name creation using the LabelFormat
+ *
+ *  The media record must have the PoolId filled in when
+ *   calling this routine.
  */
 bool newVolume(JCR *jcr, MEDIA_DBR *mr)
 {
@@ -51,18 +54,21 @@ bool newVolume(JCR *jcr, MEDIA_DBR *mr)
 
    /* See if we can create a new Volume */
    db_lock(jcr->db);
-   pr.PoolId = jcr->PoolId;
-   if (db_get_pool_record(jcr, jcr->db, &pr) && pr.LabelFormat[0] &&
-       pr.LabelFormat[0] != '*') {
-      if (pr.MaxVols == 0 || pr.NumVols < pr.MaxVols) {
-        memset(mr, 0, sizeof(MEDIA_DBR));
-        set_pool_dbr_defaults_in_media_dbr(mr, &pr);
-        jcr->VolumeName[0] = 0;
-        bstrncpy(mr->MediaType, jcr->store->media_type, sizeof(mr->MediaType));
-         if (generate_event(jcr, "NewVolume") == 1 && jcr->VolumeName[0]) {
-           bstrncpy(mr->VolumeName, jcr->VolumeName, sizeof(mr->VolumeName));
-        /* Check for special characters */
-        } else if (is_volume_name_legal(NULL, pr.LabelFormat)) {
+   pr.PoolId = mr->PoolId;
+   if (!db_get_pool_record(jcr, jcr->db, &pr)) {
+      goto bail_out;
+   }
+   if (pr.MaxVols == 0 || pr.NumVols < pr.MaxVols) {
+      memset(mr, 0, sizeof(MEDIA_DBR));
+      set_pool_dbr_defaults_in_media_dbr(mr, &pr);
+      jcr->VolumeName[0] = 0;
+      bstrncpy(mr->MediaType, jcr->store->media_type, sizeof(mr->MediaType));
+      if (generate_event(jcr, "NewVolume") == 1 && jcr->VolumeName[0] &&
+         is_volume_name_legal(NULL, jcr->VolumeName)) {
+        bstrncpy(mr->VolumeName, jcr->VolumeName, sizeof(mr->VolumeName));
+      /* Check for special characters */
+      } else if (pr.LabelFormat[0] && pr.LabelFormat[0] != '*') {
+        if (is_volume_name_legal(NULL, pr.LabelFormat)) {
            /* No special characters, so apply simple algorithm */
            if (!create_simple_name(jcr, mr, &pr)) {
               goto bail_out;
@@ -78,16 +84,16 @@ bool newVolume(JCR *jcr, MEDIA_DBR *mr)
               goto bail_out;
            }
         }
-        pr.NumVols++;
-        if (db_create_media_record(jcr, jcr->db, mr) &&
-           db_update_pool_record(jcr, jcr->db, &pr)) {
-           db_unlock(jcr->db);
-            Jmsg(jcr, M_INFO, 0, _("Created new Volume \"%s\" in catalog.\n"), mr->VolumeName);
-            Dmsg1(90, "Created new Volume=%s\n", mr->VolumeName);
-           return true;
-        } else {
-            Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
-        }
+      }
+      pr.NumVols++;
+      if (db_create_media_record(jcr, jcr->db, mr) &&
+        db_update_pool_record(jcr, jcr->db, &pr)) {
+        db_unlock(jcr->db);
+         Jmsg(jcr, M_INFO, 0, _("Created new Volume \"%s\" in catalog.\n"), mr->VolumeName);
+         Dmsg1(90, "Created new Volume=%s\n", mr->VolumeName);
+        return true;
+      } else {
+         Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
       }
    }
 bail_out:
@@ -95,7 +101,7 @@ bail_out:
    return false;
 }
 
-static int create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
+static bool create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
 {
    char name[MAXSTRING];
    char num[20];
@@ -121,23 +127,23 @@ static int create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
    }
    if (mr->VolumeName[0] == 0) {
       Jmsg(jcr, M_ERROR, 0, _("Too many failures. Giving up creating Volume name.\n"));
-      return 0;
+      return false;
    }
-   return 1;
+   return true;
 }
 
 /*
  * Perform full substitution on Label
  */
-static int perform_full_name_substitution(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
+static bool perform_full_name_substitution(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
 {
-   int stat = 0;
+   bool ok = false;
    POOLMEM *label = get_pool_memory(PM_FNAME);
    jcr->NumVols = pr->NumVols;
    if (variable_expansion(jcr, pr->LabelFormat, &label)) {
       bstrncpy(mr->VolumeName, label, sizeof(mr->VolumeName));
-      stat = 1;
+      ok = true;
    }
    free_pool_memory(label);
-   return stat;
+   return ok;
 }
index ccf37a4bfc920f82d71a360c7476c60bfaae4375..7db844bbeaf553243cabca89e2ab2276f50c6024 100644 (file)
@@ -107,7 +107,7 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, bool create)
             * 6. Try pulling a volume from the Scratch pool
             */ 
             memset(&pr, 0, sizeof(pr));
-             bstrncpy(pr.Name, "Scratch", 7);
+             bstrncpy(pr.Name, "Scratch", sizeof(pr.Name));
             if (db_get_pool_record(jcr, jcr->db, &pr)) {
                memset(&smr, 0, sizeof(smr));
                smr.PoolId = pr.PoolId;
index af30220093696ad70955b73140c266e850a1b0bc..3d889fe340347d0a4b023a244b7a290008172281 100644 (file)
@@ -421,7 +421,6 @@ static bool list_nextvol(UAContext *ua)
    MEDIA_DBR mr;
 
    memset(&mr, 0, sizeof(mr));
-   mr.PoolId = jcr->PoolId;
    int i = find_arg_with_value(ua, "job");
    if (i <= 0) {
       if ((job = select_job_resource(ua)) == NULL) {
@@ -437,11 +436,14 @@ static bool list_nextvol(UAContext *ua)
       }
    }
    for (run=NULL; (run = find_next_run(run, job, runtime)); ) {
-      pool = run ? run->pool : NULL;
+      pool = run->pool ? run->pool : NULL;
       if (!complete_jcr_for_job(jcr, job, pool)) {
         return false;
       }
-
+      mr.PoolId = jcr->PoolId;
+      if (run->storage) {
+        jcr->store = run->storage;
+      }
       if (!find_next_volume_for_append(jcr, &mr, 0)) {
          bsendmsg(ua, _("Could not find next Volume.\n"));
       } else {
index 5cd149e20045665a0bdd0f166014d96a898265fe..8b02aeaf4804aa5d7278dcd17f76bfeb6721413d 100644 (file)
@@ -8,7 +8,7 @@
  */
 
 /*
-   Copyright (C) 2001-20054 Kern Sibbald
+   Copyright (C) 2001-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -118,7 +118,7 @@ int run_cmd(UAContext *ua, const char *cmd)
                bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]);
               return 1;
            }
-            Dmsg1(800, "Got keyword=%s\n", kw[j]);
+            Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
            switch (j) {
            case 0: /* job */
               if (job_name) {
@@ -287,7 +287,7 @@ int run_cmd(UAContext *ua, const char *cmd)
           return 0;
        }
    }
-   Dmsg1(800, "Using catalog=%s\n", catalog_name);
+   Dmsg1(800, "Using catalog=%s\n", NPRT(catalog_name));
 
    if (job_name) {
       /* Find Job */
index 3c6c372ea5b0691106dd07af4207a83954a28a5e..9e97944a2cf61c5a095d9f5a9c4b042db700b576 100644 (file)
@@ -371,8 +371,8 @@ static void prt_runtime(UAContext *ua, sched_pkt *sp)
    bool close_db = false;
    JCR *jcr = ua->jcr;
    MEDIA_DBR mr;
+
    memset(&mr, 0, sizeof(mr));
-   mr.PoolId = jcr->PoolId;
    if (sp->job->JobType == JT_BACKUP) {
       jcr->db = NULL;
       ok = complete_jcr_for_job(jcr, sp->job, sp->pool);
@@ -380,6 +380,7 @@ static void prt_runtime(UAContext *ua, sched_pkt *sp)
         close_db = true;             /* new db opened, remember to close it */
       }
       if (ok) {
+         mr.PoolId = jcr->PoolId;
         ok = find_next_volume_for_append(jcr, &mr, 0);
       }
       if (!ok) {
index 56ee2afbe38f5e60713667448e01e4697d88f0b6..a228d29e92bd03f4b4505acd2887a2f02413b836 100644 (file)
@@ -282,8 +282,10 @@ void *handle_client_request(void *dirp)
       fileset->exclude_list.destroy();
       free(fileset);
    }
+   ff->fileset = NULL;
    Dmsg0(100, "Calling term_find_files\n");
    term_find_files((FF_PKT *)jcr->ff);
+   jcr->ff = NULL;
    Dmsg0(100, "Done with term_find_files\n");
    free_jcr(jcr);                    /* destroy JCR record */
    Dmsg0(100, "Done with free_jcr\n");
index eff2a1a945ae6a9b73c11dea442846fefd4046f6..f1bc25f0a1860e25c74377bbb05fe74e9d4e38f3 100755 (executable)
@@ -557,5 +557,6 @@ int term_find_one(FF_PKT *ff)
         count++;
       }
    }
+   ff->linklist = NULL;
    return count;
 }
index fa6349e9bb425aaa4c0daa1f517565d1f62a8660..9aa98beb0d7119d23d6ba85a883e1c465981832c 100644 (file)
@@ -39,7 +39,7 @@ LIBSRCS = alloc.c attr.c base64.c berrno.c bsys.c bget_msg.c \
          cram-md5.c crc32.c daemon.c edit.c fnmatch.c \
          hmac.c idcache.c jcr.c lex.c alist.c dlist.c \
          md5.c message.c mem_pool.c parse_conf.c \
-         queue.c rwlock.c scan.c serial.c sha1.c \
+         queue.c res.c rwlock.c scan.c serial.c sha1.c \
          semlock.c signal.c smartall.c tree.c \
          util.c var.c watchdog.c workq.c btimers.c \
          address_conf.c python.c 
@@ -51,7 +51,7 @@ LIBOBJS = alloc.o attr.o base64.o berrno.o bsys.o bget_msg.o \
          cram-md5.o crc32.o daemon.o edit.o fnmatch.o \
          hmac.o idcache.o jcr.o lex.o alist.o dlist.o \
          md5.o message.o mem_pool.o parse_conf.o \
-         queue.o rwlock.o scan.o serial.o sha1.o \
+         queue.o res.o rwlock.o scan.o serial.o sha1.o \
          semlock.o signal.o smartall.o tree.o \
          util.o var.o watchdog.o workq.o btimers.o \
          address_conf.o python.o
index d5dc130815e7ac8a8360143d43f6e1fcc918f85f..ae9fe194fafd32c83169c6585d62b72642ef9ec6 100755 (executable)
@@ -77,9 +77,8 @@ extern        CURES res_all;
 extern int res_all_size;
 #endif
 
+extern brwlock_t res_lock;           /* resource lock */
 
-static brwlock_t res_lock;           /* resource lock */
-static int res_locked = 0;           /* set when resource chains locked -- for debug */
 
 /* Forward referenced subroutines */
 static void scan_types(LEX *lc, MSGS *msg, int dest, char *where, char *cmd);
@@ -727,82 +726,6 @@ void store_label(LEX *lc, RES_ITEM *item, int index, int pass)
 }
 
 
-/* #define TRACE_RES */
-
-void b_LockRes(const char *file, int line)
-{
-   int errstat;
-#ifdef TRACE_RES
-   Pmsg4(000, "LockRes   %d,%d at %s:%d\n", res_locked, res_lock.w_active,
-        file, line);
-#endif
-   if ((errstat=rwl_writelock(&res_lock)) != 0) {
-      Emsg3(M_ABORT, 0, "rwl_writelock failure at %s:%d:  ERR=%s\n",
-          file, line, strerror(errstat));
-   }
-   res_locked++;
-}
-
-void b_UnlockRes(const char *file, int line)
-{
-   int errstat;
-   res_locked--;
-#ifdef TRACE_RES
-   Pmsg4(000, "UnLockRes %d,%d at %s:%d\n", res_locked, res_lock.w_active,
-        file, line);
-#endif
-   if ((errstat=rwl_writeunlock(&res_lock)) != 0) {
-      Emsg3(M_ABORT, 0, "rwl_writeunlock failure at %s:%d:. ERR=%s\n",
-          file, line, strerror(errstat));
-   }
-}
-
-/*
- * Return resource of type rcode that matches name
- */
-RES *
-GetResWithName(int rcode, char *name)
-{
-   RES *res;
-   int rindex = rcode - r_first;
-
-   LockRes();
-   res = res_head[rindex];
-   while (res) {
-      if (strcmp(res->name, name) == 0) {
-        break;
-      }
-      res = res->next;
-   }
-   UnlockRes();
-   return res;
-
-}
-
-/*
- * Return next resource of type rcode. On first
- * call second arg (res) is NULL, on subsequent
- * calls, it is called with previous value.
- */
-RES *
-GetNextRes(int rcode, RES *res)
-{
-   RES *nres;
-   int rindex = rcode - r_first;
-
-
-   if (!res_locked) {
-      Emsg0(M_ABORT, 0, "Resource chain not locked.\n");
-   }
-   if (res == NULL) {
-      nres = res_head[rindex];
-   } else {
-      nres = res->next;
-   }
-   return nres;
-}
-
-
 /* Parser state */
 enum parse_state {
    p_none,
index aaf71faf8f38baee0a8566fdeb38eb30efe37f13..884bbe79c3cee9e768241d5c970ffd281f833af2 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 /*
-   Copyright (C) 2004 Kern Sibbald
+   Copyright (C) 2004-2005 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -33,6 +33,7 @@
 EVENT_HANDLER *generate_event;
 
 #ifdef HAVE_PYTHON
+
 #undef _POSIX_C_SOURCE
 #include <Python.h>
 
@@ -54,7 +55,7 @@ void init_python_interpreter(const char *progname, const char *scripts)
    PyEval_InitThreads();
    Py_InitModule("bacula", BaculaMethods);
    bsnprintf(buf, sizeof(buf), "import sys\n"
-           "sys.path.append('%s')\n", scripts);
+            "sys.path.append('%s')\n", scripts);
    PyRun_SimpleString(buf);
    PyEval_ReleaseLock();
    generate_event = _generate_event;
@@ -78,7 +79,8 @@ int _generate_event(JCR *jcr, const char *event)
 {
    PyObject *pName, *pModule, *pDict, *pFunc;
    PyObject *pArgs, *pValue;
-
+   
+   Dmsg1(100, "Generate event %s\n", event);
    pName = PyString_FromString(event);
    if (!pName) {
       Jmsg(jcr, M_ERROR, 0, "Could not convert \"%s\" to Python string.\n", event);
@@ -102,7 +104,7 @@ int _generate_event(JCR *jcr, const char *event)
          if (!pValue) {
             Py_DECREF(pArgs);
             Py_DECREF(pModule);
-            Jmsg(jcr, M_ERROR, 0, "Could not convert JCR to Python CObject.\n");
+             Jmsg(jcr, M_ERROR, 0, "Could not convert JCR to Python CObject.\n");
             return -1;               /* Could not convert JCR to CObject */
          }
          /* pValue reference stolen here: */
@@ -116,7 +118,7 @@ int _generate_event(JCR *jcr, const char *event)
          } else {
             Py_DECREF(pModule);
             PyErr_Print();
-            Jmsg(jcr, M_ERROR, 0, "Error running Python module: %s\n", event);
+             Jmsg(jcr, M_ERROR, 0, "Error running Python module: %s\n", event);
             return 0;                /* error running function */
          }
          /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */
@@ -124,13 +126,14 @@ int _generate_event(JCR *jcr, const char *event)
         if (PyErr_Occurred()) {
            PyErr_Print();
         }
-        Jmsg(jcr, M_ERROR, 0, "Python function \"%s\" not found in module.\n", event);
+         Jmsg(jcr, M_ERROR, 0, "Python function \"%s\" not found in module.\n", event);
         return -1;                   /* function not found */
       }
       Py_DECREF(pModule);
    } else {
       return 0;                      /* Module not present */
    }
+   Dmsg0(100, "Generate event OK\n");
    return 1;
 }
 
diff --git a/bacula/src/lib/res.c b/bacula/src/lib/res.c
new file mode 100644 (file)
index 0000000..04dab6b
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ *  This file handles locking and seaching resources
+ *
+ *     Kern Sibbald, January MM
+ *      Split from parse_conf.c April MMV
+ *
+ *   Version $Id$
+ */
+
+/*
+   Copyright (C) 2000-2005 Kern Sibbald
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+
+#include "bacula.h"
+
+extern int debug_level;
+
+/* Each daemon has a slightly different set of
+ * resources, so it will define the following
+ * global values.
+ */
+extern int r_first;
+extern int r_last;
+extern RES_TABLE resources[];
+extern RES **res_head;
+
+#ifdef HAVE_WIN32
+// work around visual studio name manling preventing external linkage since res_all
+// is declared as a different type when instantiated.
+extern "C" CURES res_all;
+extern "C" int res_all_size;
+#else
+extern CURES res_all;
+extern int res_all_size;
+#endif
+
+
+brwlock_t res_lock;                  /* resource lock */
+static int res_locked = 0;           /* set when resource chains locked -- for debug */
+
+
+
+/* #define TRACE_RES */
+
+void b_LockRes(const char *file, int line)
+{
+   int errstat;
+#ifdef TRACE_RES
+   Pmsg4(000, "LockRes  locked=%d w_active=%d at %s:%d\n", 
+        res_locked, res_lock.w_active, file, line);
+    if (res_locked) {
+       Pmsg2(000, "LockRes writerid=%d myid=%d\n", res_lock.writer_id,
+         pthread_self());
+     }
+#endif
+   if ((errstat=rwl_writelock(&res_lock)) != 0) {
+      Emsg3(M_ABORT, 0, "rwl_writelock failure at %s:%d:  ERR=%s\n",
+          file, line, strerror(errstat));
+   }
+   res_locked++;
+}
+
+void b_UnlockRes(const char *file, int line)
+{
+   int errstat;
+   if ((errstat=rwl_writeunlock(&res_lock)) != 0) {
+      Emsg3(M_ABORT, 0, "rwl_writeunlock failure at %s:%d:. ERR=%s\n",
+          file, line, strerror(errstat));
+   }
+   res_locked--;
+#ifdef TRACE_RES
+   Pmsg4(000, "UnLockRes locked=%d wactive=%d at %s:%d\n", 
+        res_locked, res_lock.w_active, file, line);
+#endif
+}
+
+/*
+ * Return resource of type rcode that matches name
+ */
+RES *
+GetResWithName(int rcode, char *name)
+{
+   RES *res;
+   int rindex = rcode - r_first;
+
+   LockRes();
+   res = res_head[rindex];
+   while (res) {
+      if (strcmp(res->name, name) == 0) {
+        break;
+      }
+      res = res->next;
+   }
+   UnlockRes();
+   return res;
+
+}
+
+/*
+ * Return next resource of type rcode. On first
+ * call second arg (res) is NULL, on subsequent
+ * calls, it is called with previous value.
+ */
+RES *
+GetNextRes(int rcode, RES *res)
+{
+   RES *nres;
+   int rindex = rcode - r_first;
+
+
+//   if (!res_locked) {
+//      Emsg0(M_ABORT, 0, "Resource chain not locked.\n");
+//   }
+   if (res == NULL) {
+      nres = res_head[rindex];
+   } else {
+      nres = res->next;
+   }
+   return nres;
+}
+
+
+/* Parser state */
+enum parse_state {
+   p_none,
+   p_resource
+};
index 0b9b352f72bfafb17174f06b00e0754d5ca8f342..16ce457fb043659370e3591d86376d835d82f3ef 100644 (file)
@@ -38,7 +38,7 @@
  * Initialize a read/write lock
  *
  *  Returns: 0 on success
- *          errno on failure
+ *           errno on failure
  */
 int rwl_init(brwlock_t *rwl)
 {
@@ -66,7 +66,7 @@ int rwl_init(brwlock_t *rwl)
  * Destroy a read/write lock
  *
  * Returns: 0 on success
- *         errno on failure
+ *          errno on failure
  */
 int rwl_destroy(brwlock_t *rwl)
 {
@@ -99,7 +99,7 @@ int rwl_destroy(brwlock_t *rwl)
   if ((stat = pthread_mutex_unlock(&rwl->mutex)) != 0) {
      return stat;
   }
-  stat = pthread_mutex_destroy(&rwl->mutex);
+  stat  = pthread_mutex_destroy(&rwl->mutex);
   stat1 = pthread_cond_destroy(&rwl->read);
   stat2 = pthread_cond_destroy(&rwl->write);
   return (stat != 0 ? stat : (stat1 != 0 ? stat1 : stat2));
@@ -143,19 +143,19 @@ int rwl_readlock(brwlock_t *rwl)
       return stat;
    }
    if (rwl->w_active) {
-      rwl->r_wait++;                 /* indicate that we are waiting */
+      rwl->r_wait++;                  /* indicate that we are waiting */
       pthread_cleanup_push(rwl_read_release, (void *)rwl);
       while (rwl->w_active) {
-        stat = pthread_cond_wait(&rwl->read, &rwl->mutex);
-        if (stat != 0) {
-           break;                    /* error, bail out */
-        }
+         stat = pthread_cond_wait(&rwl->read, &rwl->mutex);
+         if (stat != 0) {
+            break;                    /* error, bail out */
+         }
       }
       pthread_cleanup_pop(0);
-      rwl->r_wait--;                 /* we are no longer waiting */
+      rwl->r_wait--;                  /* we are no longer waiting */
    }
    if (stat == 0) {
-      rwl->r_active++;               /* we are running */
+      rwl->r_active++;                /* we are running */
    }
    pthread_mutex_unlock(&rwl->mutex);
    return stat;
@@ -177,7 +177,7 @@ int rwl_readtrylock(brwlock_t *rwl)
    if (rwl->w_active) {
       stat = EBUSY;
    } else {
-      rwl->r_active++;               /* we are running */
+      rwl->r_active++;                /* we are running */
    }
    stat2 = pthread_mutex_unlock(&rwl->mutex);
    return (stat == 0 ? stat2 : stat);
@@ -198,7 +198,7 @@ int rwl_readunlock(brwlock_t *rwl)
    }
    rwl->r_active--;
    if (rwl->r_active == 0 && rwl->w_wait > 0) { /* if writers waiting */
-      stat = pthread_cond_signal(&rwl->write);
+      stat = pthread_cond_broadcast(&rwl->write);
    }
    stat2 = pthread_mutex_unlock(&rwl->mutex);
    return (stat == 0 ? stat2 : stat);
@@ -225,18 +225,18 @@ int rwl_writelock(brwlock_t *rwl)
       return 0;
    }
    if (rwl->w_active || rwl->r_active > 0) {
-      rwl->w_wait++;                 /* indicate that we are waiting */
+      rwl->w_wait++;                  /* indicate that we are waiting */
       pthread_cleanup_push(rwl_write_release, (void *)rwl);
       while (rwl->w_active || rwl->r_active > 0) {
-        if ((stat = pthread_cond_wait(&rwl->write, &rwl->mutex)) != 0) {
-           break;                    /* error, bail out */
-        }
+         if ((stat = pthread_cond_wait(&rwl->write, &rwl->mutex)) != 0) {
+            break;                    /* error, bail out */
+         }
       }
       pthread_cleanup_pop(0);
-      rwl->w_wait--;                 /* we are no longer waiting */
+      rwl->w_wait--;                  /* we are no longer waiting */
    }
    if (stat == 0) {
-      rwl->w_active++;               /* we are running */
+      rwl->w_active++;                /* we are running */
       rwl->writer_id = pthread_self(); /* save writer thread's id */
    }
    pthread_mutex_unlock(&rwl->mutex);
@@ -264,7 +264,7 @@ int rwl_writetrylock(brwlock_t *rwl)
    if (rwl->w_active || rwl->r_active > 0) {
       stat = EBUSY;
    } else {
-      rwl->w_active = 1;             /* we are running */
+      rwl->w_active = 1;              /* we are running */
       rwl->writer_id = pthread_self(); /* save writer thread's id */
    }
    stat2 = pthread_mutex_unlock(&rwl->mutex);
@@ -293,13 +293,13 @@ int rwl_writeunlock(brwlock_t *rwl)
       Emsg0(M_ABORT, 0, "rwl_writeunlock by non-owner.\n");
    }
    if (rwl->w_active > 0) {
-      stat = 0;                      /* writers still active */
+      stat = 0;                       /* writers still active */
    } else {
       /* No more writers, awaken someone */
-      if (rwl->r_wait > 0) {        /* if readers waiting */
-        stat = pthread_cond_broadcast(&rwl->read);
+      if (rwl->r_wait > 0) {         /* if readers waiting */
+         stat = pthread_cond_broadcast(&rwl->read);
       } else if (rwl->w_wait > 0) {
-        stat = pthread_cond_signal(&rwl->write);
+         stat = pthread_cond_broadcast(&rwl->write);
       }
    }
    stat2 = pthread_mutex_unlock(&rwl->mutex);
@@ -353,43 +353,43 @@ void *thread_routine(void *arg)
        * lock).
        */
       if ((iteration % self->interval) == 0) {
-        status = rwl_writelock(&data[element].lock);
-        if (status != 0) {
-           Emsg1(M_ABORT, 0, "Write lock failed. ERR=%s\n", strerror(status));
-        }
-        data[element].data = self->thread_num;
-        data[element].writes++;
-        self->writes++;
-        status = rwl_writeunlock(&data[element].lock);
-        if (status != 0) {
-           Emsg1(M_ABORT, 0, "Write unlock failed. ERR=%s\n", strerror(status));
-        }
+         status = rwl_writelock(&data[element].lock);
+         if (status != 0) {
+            Emsg1(M_ABORT, 0, "Write lock failed. ERR=%s\n", strerror(status));
+         }
+         data[element].data = self->thread_num;
+         data[element].writes++;
+         self->writes++;
+         status = rwl_writeunlock(&data[element].lock);
+         if (status != 0) {
+            Emsg1(M_ABORT, 0, "Write unlock failed. ERR=%s\n", strerror(status));
+         }
       } else {
-        /*
-         * Look at the current data element to see whether
-         * the current thread last updated it. Count the
-         * times to report later.
-         */
-         status = rwl_readlock(&data[element].lock);
-         if (status != 0) {
-            Emsg1(M_ABORT, 0, "Read lock failed. ERR=%s\n", strerror(status));
-         }
-         self->reads++;
-         if (data[element].data == self->thread_num)
-            repeats++;
-         status = rwl_readunlock(&data[element].lock);
-         if (status != 0) {
-            Emsg1(M_ABORT, 0, "Read unlock failed. ERR=%s\n", strerror(status));
-         }
+         /*
+          * Look at the current data element to see whether
+          * the current thread last updated it. Count the
+          * times to report later.
+          */
+          status = rwl_readlock(&data[element].lock);
+          if (status != 0) {
+             Emsg1(M_ABORT, 0, "Read lock failed. ERR=%s\n", strerror(status));
+          }
+          self->reads++;
+          if (data[element].data == self->thread_num)
+             repeats++;
+          status = rwl_readunlock(&data[element].lock);
+          if (status != 0) {
+             Emsg1(M_ABORT, 0, "Read unlock failed. ERR=%s\n", strerror(status));
+          }
       }
       element++;
       if (element >= DATASIZE) {
-        element = 0;
+         element = 0;
       }
    }
    if (repeats > 0) {
       Pmsg2(000, "Thread %d found unchanged elements %d times\n",
-        self->thread_num, repeats);
+         self->thread_num, repeats);
    }
    return NULL;
 }
@@ -416,27 +416,27 @@ int main (int argc, char *argv[])
      * Initialize the shared data.
      */
     for (data_count = 0; data_count < DATASIZE; data_count++) {
-       data[data_count].data = 0;
-       data[data_count].writes = 0;
-       status = rwl_init (&data[data_count].lock);
-       if (status != 0) {
-          Emsg1(M_ABORT, 0, "Init rwlock failed. ERR=%s\n", strerror(status));
-       }
+        data[data_count].data = 0;
+        data[data_count].writes = 0;
+        status = rwl_init (&data[data_count].lock);
+        if (status != 0) {
+           Emsg1(M_ABORT, 0, "Init rwlock failed. ERR=%s\n", strerror(status));
+        }
     }
 
     /*
      * Create THREADS threads to access shared data.
      */
     for (count = 0; count < THREADS; count++) {
-       threads[count].thread_num = count + 1;
-       threads[count].writes = 0;
-       threads[count].reads = 0;
-       threads[count].interval = rand_r (&seed) % 71;
-       status = pthread_create (&threads[count].thread_id,
-           NULL, thread_routine, (void*)&threads[count]);
-       if (status != 0) {
-          Emsg1(M_ABORT, 0, "Create thread failed. ERR=%s\n", strerror(status));
-       }
+        threads[count].thread_num = count + 1;
+        threads[count].writes = 0;
+        threads[count].reads = 0;
+        threads[count].interval = rand_r (&seed) % 71;
+        status = pthread_create (&threads[count].thread_id,
+            NULL, thread_routine, (void*)&threads[count]);
+        if (status != 0) {
+           Emsg1(M_ABORT, 0, "Create thread failed. ERR=%s\n", strerror(status));
+        }
     }
 
     /*
@@ -444,28 +444,28 @@ int main (int argc, char *argv[])
      * statistics.
      */
     for (count = 0; count < THREADS; count++) {
-       status = pthread_join (threads[count].thread_id, NULL);
-       if (status != 0) {
-          Emsg1(M_ABORT, 0, "Join thread failed. ERR=%s\n", strerror(status));
-       }
-       thread_writes += threads[count].writes;
-       printf ("%02d: interval %d, writes %d, reads %d\n",
-           count, threads[count].interval,
-           threads[count].writes, threads[count].reads);
+        status = pthread_join (threads[count].thread_id, NULL);
+        if (status != 0) {
+           Emsg1(M_ABORT, 0, "Join thread failed. ERR=%s\n", strerror(status));
+        }
+        thread_writes += threads[count].writes;
+        printf ("%02d: interval %d, writes %d, reads %d\n",
+            count, threads[count].interval,
+            threads[count].writes, threads[count].reads);
     }
 
     /*
      * Collect statistics for the data.
      */
     for (data_count = 0; data_count < DATASIZE; data_count++) {
-       data_writes += data[data_count].writes;
-       printf ("data %02d: value %d, %d writes\n",
-           data_count, data[data_count].data, data[data_count].writes);
-       rwl_destroy (&data[data_count].lock);
+        data_writes += data[data_count].writes;
+        printf ("data %02d: value %d, %d writes\n",
+            data_count, data[data_count].data, data[data_count].writes);
+        rwl_destroy (&data[data_count].lock);
     }
 
     printf ("Total: %d thread writes, %d data writes\n",
-       thread_writes, data_writes);
+        thread_writes, data_writes);
     return 0;
 }
 
@@ -485,29 +485,29 @@ int main (int argc, char *argv[])
 #include "rwlock.h"
 #include "errors.h"
 
-#define THREADS        5
-#define ITERATIONS     1000
-#define DATASIZE       15
+#define THREADS         5
+#define ITERATIONS      1000
+#define DATASIZE        15
 
 /*
  * Keep statistics for each thread.
  */
 typedef struct thread_tag {
-    int        thread_num;
-    pthread_t  thread_id;
-    int        r_collisions;
-    int        w_collisions;
-    int        updates;
-    int        interval;
+    int         thread_num;
+    pthread_t   thread_id;
+    int         r_collisions;
+    int         w_collisions;
+    int         updates;
+    int         interval;
 } thread_t;
 
 /*
  * Read-write lock and shared data
  */
 typedef struct data_tag {
-    brwlock_t   lock;
-    int        data;
-    int        updates;
+    brwlock_t    lock;
+    int         data;
+    int         updates;
 } data_t;
 
 thread_t threads[THREADS];
@@ -523,38 +523,38 @@ void *thread_routine (void *arg)
     int element;
     int status;
 
-    element = 0;                       /* Current data element */
+    element = 0;                        /* Current data element */
 
     for (iteration = 0; iteration < ITERATIONS; iteration++) {
-       if ((iteration % self->interval) == 0) {
-           status = rwl_writetrylock (&data[element].lock);
-           if (status == EBUSY)
-               self->w_collisions++;
-           else if (status == 0) {
-               data[element].data++;
-               data[element].updates++;
-               self->updates++;
-               rwl_writeunlock (&data[element].lock);
-           } else
-               err_abort (status, "Try write lock");
-       } else {
-           status = rwl_readtrylock (&data[element].lock);
-           if (status == EBUSY)
-               self->r_collisions++;
-           else if (status != 0) {
-               err_abort (status, "Try read lock");
-           } else {
-               if (data[element].data != data[element].updates)
-                   printf ("%d: data[%d] %d != %d\n",
-                       self->thread_num, element,
-                       data[element].data, data[element].updates);
-               rwl_readunlock (&data[element].lock);
-           }
-       }
-
-       element++;
-       if (element >= DATASIZE)
-           element = 0;
+        if ((iteration % self->interval) == 0) {
+            status = rwl_writetrylock (&data[element].lock);
+            if (status == EBUSY)
+                self->w_collisions++;
+            else if (status == 0) {
+                data[element].data++;
+                data[element].updates++;
+                self->updates++;
+                rwl_writeunlock (&data[element].lock);
+            } else
+                err_abort (status, "Try write lock");
+        } else {
+            status = rwl_readtrylock (&data[element].lock);
+            if (status == EBUSY)
+                self->r_collisions++;
+            else if (status != 0) {
+                err_abort (status, "Try read lock");
+            } else {
+                if (data[element].data != data[element].updates)
+                    printf ("%d: data[%d] %d != %d\n",
+                        self->thread_num, element,
+                        data[element].data, data[element].updates);
+                rwl_readunlock (&data[element].lock);
+            }
+        }
+
+        element++;
+        if (element >= DATASIZE)
+            element = 0;
     }
     return NULL;
 }
@@ -580,24 +580,24 @@ int main (int argc, char *argv[])
      * Initialize the shared data.
      */
     for (data_count = 0; data_count < DATASIZE; data_count++) {
-       data[data_count].data = 0;
-       data[data_count].updates = 0;
-       rwl_init (&data[data_count].lock);
+        data[data_count].data = 0;
+        data[data_count].updates = 0;
+        rwl_init (&data[data_count].lock);
     }
 
     /*
      * Create THREADS threads to access shared data.
      */
     for (count = 0; count < THREADS; count++) {
-       threads[count].thread_num = count;
-       threads[count].r_collisions = 0;
-       threads[count].w_collisions = 0;
-       threads[count].updates = 0;
-       threads[count].interval = rand_r (&seed) % ITERATIONS;
-       status = pthread_create (&threads[count].thread_id,
-           NULL, thread_routine, (void*)&threads[count]);
-       if (status != 0)
-           err_abort (status, "Create thread");
+        threads[count].thread_num = count;
+        threads[count].r_collisions = 0;
+        threads[count].w_collisions = 0;
+        threads[count].updates = 0;
+        threads[count].interval = rand_r (&seed) % ITERATIONS;
+        status = pthread_create (&threads[count].thread_id,
+            NULL, thread_routine, (void*)&threads[count]);
+        if (status != 0)
+            err_abort (status, "Create thread");
     }
 
     /*
@@ -605,25 +605,25 @@ int main (int argc, char *argv[])
      * statistics.
      */
     for (count = 0; count < THREADS; count++) {
-       status = pthread_join (threads[count].thread_id, NULL);
-       if (status != 0)
-           err_abort (status, "Join thread");
-       thread_updates += threads[count].updates;
-       printf ("%02d: interval %d, updates %d, "
-               "r_collisions %d, w_collisions %d\n",
-           count, threads[count].interval,
-           threads[count].updates,
-           threads[count].r_collisions, threads[count].w_collisions);
+        status = pthread_join (threads[count].thread_id, NULL);
+        if (status != 0)
+            err_abort (status, "Join thread");
+        thread_updates += threads[count].updates;
+        printf ("%02d: interval %d, updates %d, "
+                "r_collisions %d, w_collisions %d\n",
+            count, threads[count].interval,
+            threads[count].updates,
+            threads[count].r_collisions, threads[count].w_collisions);
     }
 
     /*
      * Collect statistics for the data.
      */
     for (data_count = 0; data_count < DATASIZE; data_count++) {
-       data_updates += data[data_count].updates;
-       printf ("data %02d: value %d, %d updates\n",
-           data_count, data[data_count].data, data[data_count].updates);
-       rwl_destroy (&data[data_count].lock);
+        data_updates += data[data_count].updates;
+        printf ("data %02d: value %d, %d updates\n",
+            data_count, data[data_count].data, data[data_count].updates);
+        rwl_destroy (&data[data_count].lock);
     }
 
     return 0;
index 91f812bc5fd0176588c399dbbc7c07319e7929e2..a00adbfb3782db9dc0ee883ba70278aad911f573 100755 (executable)
@@ -56,7 +56,7 @@ extern "C" void *workq_server(void *arg);
  * Initialize a work queue
  *
  *  Returns: 0 on success
- *          errno on failure
+ *           errno on failure
  */
 int workq_init(workq_t *wq, int threads, void *(*engine)(void *arg))
 {
@@ -80,10 +80,10 @@ int workq_init(workq_t *wq, int threads, void *(*engine)(void *arg))
    }
    wq->quit = 0;
    wq->first = wq->last = NULL;
-   wq->max_workers = threads;        /* max threads to create */
-   wq->num_workers = 0;              /* no threads yet */
-   wq->idle_workers = 0;             /* no idle threads */
-   wq->engine = engine;              /* routine to run */
+   wq->max_workers = threads;         /* max threads to create */
+   wq->num_workers = 0;               /* no threads yet */
+   wq->idle_workers = 0;              /* no idle threads */
+   wq->engine = engine;               /* routine to run */
    wq->valid = WORKQ_VALID;
    return 0;
 }
@@ -92,7 +92,7 @@ int workq_init(workq_t *wq, int threads, void *(*engine)(void *arg))
  * Destroy a work queue
  *
  * Returns: 0 on success
- *         errno on failure
+ *          errno on failure
  */
 int workq_destroy(workq_t *wq)
 {
@@ -104,7 +104,7 @@ int workq_destroy(workq_t *wq)
   if ((stat = pthread_mutex_lock(&wq->mutex)) != 0) {
      return stat;
   }
-  wq->valid = 0;                     /* prevent any more operations */
+  wq->valid = 0;                      /* prevent any more operations */
 
   /*
    * If any threads are active, wake them
@@ -112,22 +112,22 @@ int workq_destroy(workq_t *wq)
   if (wq->num_workers > 0) {
      wq->quit = 1;
      if (wq->idle_workers) {
-       if ((stat = pthread_cond_broadcast(&wq->work)) != 0) {
-          pthread_mutex_unlock(&wq->mutex);
-          return stat;
-       }
+        if ((stat = pthread_cond_broadcast(&wq->work)) != 0) {
+           pthread_mutex_unlock(&wq->mutex);
+           return stat;
+        }
      }
      while (wq->num_workers > 0) {
-       if ((stat = pthread_cond_wait(&wq->work, &wq->mutex)) != 0) {
-          pthread_mutex_unlock(&wq->mutex);
-          return stat;
-       }
+        if ((stat = pthread_cond_wait(&wq->work, &wq->mutex)) != 0) {
+           pthread_mutex_unlock(&wq->mutex);
+           return stat;
+        }
      }
   }
   if ((stat = pthread_mutex_unlock(&wq->mutex)) != 0) {
      return stat;
   }
-  stat = pthread_mutex_destroy(&wq->mutex);
+  stat  = pthread_mutex_destroy(&wq->mutex);
   stat1 = pthread_cond_destroy(&wq->work);
   stat2 = pthread_attr_destroy(&wq->attr);
   return (stat != 0 ? stat : (stat1 != 0 ? stat1 : stat2));
@@ -138,10 +138,10 @@ int workq_destroy(workq_t *wq)
  *  Add work to a queue
  *    wq is a queue that was created with workq_init
  *    element is a user unique item that will be passed to the
- *       processing routine
+ *        processing routine
  *    work_item will get internal work queue item -- if it is not NULL
  *    priority if non-zero will cause the item to be placed on the
- *       head of the list instead of the tail.
+ *        head of the list instead of the tail.
  */
 int workq_add(workq_t *wq, void *element, workq_ele_t **work_item, int priority)
 {
@@ -168,18 +168,18 @@ int workq_add(workq_t *wq, void *element, workq_ele_t **work_item, int priority)
    if (priority) {
       /* Add to head of queue */
       if (wq->first == NULL) {
-        wq->first = item;
-        wq->last = item;
+         wq->first = item;
+         wq->last = item;
       } else {
-        item->next = wq->first;
-        wq->first = item;
+         item->next = wq->first;
+         wq->first = item;
       }
    } else {
       /* Add to end of queue */
       if (wq->first == NULL) {
-        wq->first = item;
+         wq->first = item;
       } else {
-        wq->last->next = item;
+         wq->last->next = item;
       }
       wq->last = item;
    }
@@ -187,17 +187,17 @@ int workq_add(workq_t *wq, void *element, workq_ele_t **work_item, int priority)
    /* if any threads are idle, wake one */
    if (wq->idle_workers > 0) {
       Dmsg0(1400, "Signal worker\n");
-      if ((stat = pthread_cond_signal(&wq->work)) != 0) {
-        pthread_mutex_unlock(&wq->mutex);
-        return stat;
+      if ((stat = pthread_cond_broadcast(&wq->work)) != 0) {
+         pthread_mutex_unlock(&wq->mutex);
+         return stat;
       }
    } else if (wq->num_workers < wq->max_workers) {
       Dmsg0(1400, "Create worker thread\n");
       /* No idle threads so create a new one */
       set_thread_concurrency(wq->max_workers + 1);
       if ((stat = pthread_create(&id, &wq->attr, workq_server, (void *)wq)) != 0) {
-        pthread_mutex_unlock(&wq->mutex);
-        return stat;
+         pthread_mutex_unlock(&wq->mutex);
+         return stat;
       }
       wq->num_workers++;
    }
@@ -236,8 +236,8 @@ int workq_remove(workq_t *wq, workq_ele_t *work_item)
 
    for (prev=item=wq->first; item; item=item->next) {
       if (item == work_item) {
-        found = 1;
-        break;
+         found = 1;
+         break;
       }
       prev = item;
    }
@@ -249,7 +249,7 @@ int workq_remove(workq_t *wq, workq_ele_t *work_item)
    if (wq->first != work_item) {
       prev->next = work_item->next;
       if (wq->last == work_item) {
-        wq->last = prev;
+         wq->last = prev;
       }
       work_item->next = wq->first;
       wq->first = work_item;
@@ -258,17 +258,17 @@ int workq_remove(workq_t *wq, workq_ele_t *work_item)
    /* if any threads are idle, wake one */
    if (wq->idle_workers > 0) {
       Dmsg0(1400, "Signal worker\n");
-      if ((stat = pthread_cond_signal(&wq->work)) != 0) {
-        pthread_mutex_unlock(&wq->mutex);
-        return stat;
+      if ((stat = pthread_cond_broadcast(&wq->work)) != 0) {
+         pthread_mutex_unlock(&wq->mutex);
+         return stat;
       }
    } else {
       Dmsg0(1400, "Create worker thread\n");
       /* No idle threads so create a new one */
       set_thread_concurrency(wq->max_workers + 1);
       if ((stat = pthread_create(&id, &wq->attr, workq_server, (void *)wq)) != 0) {
-        pthread_mutex_unlock(&wq->mutex);
-        return stat;
+         pthread_mutex_unlock(&wq->mutex);
+         return stat;
       }
       wq->num_workers++;
    }
@@ -307,66 +307,66 @@ void *workq_server(void *arg)
       timeout.tv_sec = tv.tv_sec + 2;
 
       while (wq->first == NULL && !wq->quit) {
-        /*
-         * Wait 2 seconds, then if no more work, exit
-         */
+         /*
+          * Wait 2 seconds, then if no more work, exit
+          */
          Dmsg0(1400, "pthread_cond_timedwait()\n");
 #ifdef xxxxxxxxxxxxxxxx_was_HAVE_CYGWIN
-        /* CYGWIN dies with a page fault the second
-         * time that pthread_cond_timedwait() is called
-         * so fake it out.
-         */
-        pthread_mutex_lock(&wq->mutex);
-        stat = ETIMEDOUT;
+         /* CYGWIN dies with a page fault the second
+          * time that pthread_cond_timedwait() is called
+          * so fake it out.
+          */
+         pthread_mutex_lock(&wq->mutex);
+         stat = ETIMEDOUT;
 #else
-        stat = pthread_cond_timedwait(&wq->work, &wq->mutex, &timeout);
+         stat = pthread_cond_timedwait(&wq->work, &wq->mutex, &timeout);
 #endif
          Dmsg1(1400, "timedwait=%d\n", stat);
-        if (stat == ETIMEDOUT) {
-           timedout = 1;
-           break;
-        } else if (stat != 0) {
+         if (stat == ETIMEDOUT) {
+            timedout = 1;
+            break;
+         } else if (stat != 0) {
             /* This shouldn't happen */
             Dmsg0(1400, "This shouldn't happen\n");
-           wq->num_workers--;
-           pthread_mutex_unlock(&wq->mutex);
-           return NULL;
-        }
+            wq->num_workers--;
+            pthread_mutex_unlock(&wq->mutex);
+            return NULL;
+         }
       }
       we = wq->first;
       if (we != NULL) {
-        wq->first = we->next;
-        if (wq->last == we) {
-           wq->last = NULL;
-        }
-        if ((stat = pthread_mutex_unlock(&wq->mutex)) != 0) {
-           return NULL;
-        }
+         wq->first = we->next;
+         if (wq->last == we) {
+            wq->last = NULL;
+         }
+         if ((stat = pthread_mutex_unlock(&wq->mutex)) != 0) {
+            return NULL;
+         }
          /* Call user's routine here */
          Dmsg0(1400, "Calling user engine.\n");
-        wq->engine(we->data);
+         wq->engine(we->data);
          Dmsg0(1400, "Back from user engine.\n");
-        free(we);                    /* release work entry */
+         free(we);                    /* release work entry */
          Dmsg0(1400, "relock mutex\n");
-        if ((stat = pthread_mutex_lock(&wq->mutex)) != 0) {
-           return NULL;
-        }
+         if ((stat = pthread_mutex_lock(&wq->mutex)) != 0) {
+            return NULL;
+         }
          Dmsg0(1400, "Done lock mutex\n");
       }
       /*
        * If no more work request, and we are asked to quit, then do it
        */
       if (wq->first == NULL && wq->quit) {
-        wq->num_workers--;
-        if (wq->num_workers == 0) {
+         wq->num_workers--;
+         if (wq->num_workers == 0) {
             Dmsg0(1400, "Wake up destroy routine\n");
-           /* Wake up destroy routine if he is waiting */
-           pthread_cond_broadcast(&wq->work);
-        }
+            /* Wake up destroy routine if he is waiting */
+            pthread_cond_broadcast(&wq->work);
+         }
          Dmsg0(1400, "Unlock mutex\n");
-        pthread_mutex_unlock(&wq->mutex);
+         pthread_mutex_unlock(&wq->mutex);
          Dmsg0(1400, "Return from workq_server\n");
-        return NULL;
+         return NULL;
       }
       Dmsg0(1400, "Check for work request\n");
       /*
@@ -376,8 +376,8 @@ void *workq_server(void *arg)
       Dmsg1(1400, "timedout=%d\n", timedout);
       if (wq->first == NULL && timedout) {
          Dmsg0(1400, "break big loop\n");
-        wq->num_workers--;
-        break;
+         wq->num_workers--;
+         break;
       }
       Dmsg0(1400, "Loop again\n");
    } /* end of big for loop */
index 29cdd7b0ec58b0a1593367cf6bac196468ddaa03..4c44872002b6986e44133846371791bacae3f61c 100644 (file)
@@ -55,8 +55,8 @@ DCR *new_dcr(JCR *jcr, DEVICE *dev)
    dcr->max_spool_size = dev->device->max_spool_size;
    /* Attach this dcr only if dev is initialized */
    if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
-      dev->attached_dcrs->append(dcr); /* attach dcr to device */
-//    jcr->dcrs->append(dcr);        /* put dcr in list for Job */
+      dev->attached_dcrs->append(dcr);  /* attach dcr to device */
+//    jcr->dcrs->append(dcr);         /* put dcr in list for Job */
    }
    return dcr;
 }
@@ -75,13 +75,13 @@ static void remove_dcr_from_dcrs(DCR *dcr)
       DCR *ldcr;
       int num = jcr->dcrs->size();
       for (i=0; i < num; i++) {
-        ldcr = (DCR *)jcr->dcrs->get(i);
-        if (ldcr == dcr) {
-           jcr->dcrs->remove(i);
-           if (jcr->dcr == dcr) {
-              jcr->dcr = NULL;
-           }
-        }
+         ldcr = (DCR *)jcr->dcrs->get(i);
+         if (ldcr == dcr) {
+            jcr->dcrs->remove(i);
+            if (jcr->dcr == dcr) {
+               jcr->dcr = NULL;
+            }
+         }
       }
    }
 }
@@ -105,15 +105,15 @@ void free_dcr(DCR *dcr)
       dev->num_writers--;
       if (dev->num_writers < 0) {
          Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
-        dev->num_writers = 0;
-        dcr->reserved_device = false;
+         dev->num_writers = 0;
+         dcr->reserved_device = false;
       }
       unlock_device(dev);
    }
 
    /* Detach this dcr only if the dev is initialized */
    if (dev->fd != 0 && jcr && jcr->JobType != JT_SYSTEM) {
-      dev->attached_dcrs->remove(dcr); /* detach dcr from device */
+      dev->attached_dcrs->remove(dcr);  /* detach dcr from device */
 //    remove_dcr_from_dcrs(dcr);      /* remove dcr from jcr list */
    }
    if (dcr->block) {
@@ -149,21 +149,21 @@ bool reserve_device_for_read(DCR *dcr)
    dev->block(BST_DOING_ACQUIRE);
 
    Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
-       dev->print_name());
+        dev->print_name());
    for (first=true; device_is_unmounted(dev); first=false) {
       dev->unblock();
       if (!wait_for_device(dcr, jcr->errmsg, first))  {
-        return false;
+         return false;
       }
      dev->block(BST_DOING_ACQUIRE);
    }
 
    Mmsg2(jcr->errmsg, _("Device %s is busy. Job %d canceled.\n"),
-        dev->print_name(), jcr->JobId);
+         dev->print_name(), jcr->JobId);
    for (first=true; dev->is_busy(); first=false) {
       dev->unblock();
       if (!wait_for_device(dcr, jcr->errmsg, first)) {
-        return false;
+         return false;
       }
       dev->block(BST_DOING_ACQUIRE);
    }
@@ -182,7 +182,7 @@ bool reserve_device_for_read(DCR *dcr)
  *  leave the block pointers just after the label.
  *
  *  Returns: NULL if failed for any reason
- *          dcr  if successful
+ *           dcr  if successful
  */
 DCR *acquire_device_for_read(DCR *dcr)
 {
@@ -200,7 +200,7 @@ DCR *acquire_device_for_read(DCR *dcr)
 
    if (dev->num_writers > 0) {
       Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"), 
-        dev->num_writers, jcr->JobId);
+         dev->num_writers, jcr->JobId);
       goto get_out;
    }
 
@@ -215,15 +215,15 @@ DCR *acquire_device_for_read(DCR *dcr)
       vol = vol->next;
    }
    if (!vol) {
-      goto get_out;                  /* should not happen */   
+      goto get_out;                   /* should not happen */   
    }
    bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
 
    init_device_wait_timers(dcr);
 
    tape_previously_mounted = dev->can_read() ||
-                            dev->can_append() ||
-                            dev->is_labeled();
+                             dev->can_append() ||
+                             dev->is_labeled();
    tape_initially_mounted = tape_previously_mounted;
 
 
@@ -236,10 +236,10 @@ DCR *acquire_device_for_read(DCR *dcr)
    dev->num_parts = dcr->VolCatInfo.VolCatParts;
    
    for (i=0; i<5; i++) {
-      dev->clear_labeled();             /* force reread of label */
+      dev->clear_labeled();              /* force reread of label */
       if (job_canceled(jcr)) {
          Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
-        goto get_out;                /* error return */
+         goto get_out;                /* error return */
       }
       /*
        * This code ensures that the device is ready for
@@ -248,91 +248,91 @@ DCR *acquire_device_for_read(DCR *dcr)
        */
       for ( ; !dev->is_open(); ) {
          Dmsg1(120, "bstored: open vol=%s\n", dcr->VolumeName);
-        if (open_dev(dev, dcr->VolumeName, OPEN_READ_ONLY) < 0) {
-           if (dev->dev_errno == EIO) {   /* no tape loaded */
+         if (open_dev(dev, dcr->VolumeName, OPEN_READ_ONLY) < 0) {
+            if (dev->dev_errno == EIO) {   /* no tape loaded */
               Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
-                   dev->print_name(), dcr->VolumeName, strerror_dev(dev));
-              goto default_path;
-           }
-           
-           /* If we have a dvd that requires mount, 
-            * we need to try to open the label, so the info can be reported
-            * if a wrong volume has been mounted. */
-           if (dev->is_dvd() && (dcr->VolCatInfo.VolCatParts > 0)) {
-              break;
-           }
-           
+                    dev->print_name(), dcr->VolumeName, strerror_dev(dev));
+               goto default_path;
+            }
+            
+            /* If we have a dvd that requires mount, 
+             * we need to try to open the label, so the info can be reported
+             * if a wrong volume has been mounted. */
+            if (dev->is_dvd() && (dcr->VolCatInfo.VolCatParts > 0)) {
+               break;
+            }
+            
             Jmsg3(jcr, M_FATAL, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"),
-               dev->print_name(), dcr->VolumeName, strerror_dev(dev));
-           goto get_out;
-        }
+                dev->print_name(), dcr->VolumeName, strerror_dev(dev));
+            goto get_out;
+         }
          Dmsg1(129, "open_dev %s OK\n", dev->print_name());
       }
       
       if (dev->is_dvd()) {
-        vol_label_status = read_dev_volume_label_guess(dcr, 0);
+         vol_label_status = read_dev_volume_label_guess(dcr, 0);
       } else {
-        vol_label_status = read_dev_volume_label(dcr);
+         vol_label_status = read_dev_volume_label(dcr);
       }
       
       Dmsg0(200, "calling read-vol-label\n");
       switch (vol_label_status) {
       case VOL_OK:
-        vol_ok = true;
-        memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
-        break;                    /* got it */
+         vol_ok = true;
+         memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
+         break;                    /* got it */
       case VOL_IO_ERROR:
-        /*
-         * Send error message generated by read_dev_volume_label()
-         *  only we really had a tape mounted. This supresses superfluous
-         *  error messages when nothing is mounted.
-         */
-        if (tape_previously_mounted) {
+         /*
+          * Send error message generated by read_dev_volume_label()
+          *  only we really had a tape mounted. This supresses superfluous
+          *  error messages when nothing is mounted.
+          */
+         if (tape_previously_mounted) {
             Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
-        }
-        goto default_path;
+         }
+         goto default_path;
       case VOL_NAME_ERROR:
-        if (tape_initially_mounted) {
-           tape_initially_mounted = false;
-           goto default_path;
-        }
-        /* Fall through */
+         if (tape_initially_mounted) {
+            tape_initially_mounted = false;
+            goto default_path;
+         }
+         /* Fall through */
       default:
          Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
 default_path:
-        tape_previously_mounted = true;
-        
-        /* If the device requires mount, close it, so the device can be ejected.
-         * FIXME: This should perhaps be done for all devices. */
-        if (dev_cap(dev, CAP_REQMOUNT)) {
-           force_close_dev(dev);
-        }
-        
-        /* Call autochanger only once unless ask_sysop called */
-        if (try_autochanger) {
-           int stat;
+         tape_previously_mounted = true;
+         
+         /* If the device requires mount, close it, so the device can be ejected.
+          * FIXME: This should perhaps be done for all devices. */
+         if (dev_cap(dev, CAP_REQMOUNT)) {
+            force_close_dev(dev);
+         }
+         
+         /* Call autochanger only once unless ask_sysop called */
+         if (try_autochanger) {
+            int stat;
             Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
-              dcr->VolumeName, dcr->VolCatInfo.Slot);
-           stat = autoload_device(dcr, 0, NULL);
-           if (stat > 0) {
-              try_autochanger = false;
-              continue;              /* try reading volume mounted */
-           }
-        }
-        
-        /* Mount a specific volume and no other */
+               dcr->VolumeName, dcr->VolCatInfo.Slot);
+            stat = autoload_device(dcr, 0, NULL);
+            if (stat > 0) {
+               try_autochanger = false;
+               continue;              /* try reading volume mounted */
+            }
+         }
+         
+         /* Mount a specific volume and no other */
          Dmsg0(200, "calling dir_ask_sysop\n");
-        if (!dir_ask_sysop_to_mount_volume(dcr)) {
-           goto get_out;             /* error return */
-        }
-        try_autochanger = true;      /* permit using autochanger again */
-        continue;                    /* try reading again */
+         if (!dir_ask_sysop_to_mount_volume(dcr)) {
+            goto get_out;             /* error return */
+         }
+         try_autochanger = true;      /* permit using autochanger again */
+         continue;                    /* try reading again */
       } /* end switch */
       break;
    } /* end for loop */
    if (!vol_ok) {
       Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
-           dev->print_name());
+            dev->print_name());
       goto get_out;
    }
 
@@ -381,22 +381,22 @@ bool reserve_device_for_append(DCR *dcr)
    dev->block(BST_DOING_ACQUIRE);
 
    Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"),
-        dev->print_name());
+         dev->print_name());
    for (first=true; dev->can_read(); first=false) {
       dev->unblock();
       if (!wait_for_device(dcr, jcr->errmsg, first)) {
-        return false;
+         return false;
       }
       dev->block(BST_DOING_ACQUIRE);
    }
 
 
    Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
-       dev->print_name());
+        dev->print_name());
    for (first=true; device_is_unmounted(dev); first=false) {
-      dev->unblock();     
+      dev->unblock();      
       if (!wait_for_device(dcr, jcr->errmsg, first))  {
-        return false;
+         return false;
       }
      dev->block(BST_DOING_ACQUIRE);
    }
@@ -407,16 +407,16 @@ bool reserve_device_for_append(DCR *dcr)
       switch (can_reserve_drive(dcr)) {
       case 0:
          Mmsg1(jcr->errmsg, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
-        dev->unblock();      
-        if (!wait_for_device(dcr, jcr->errmsg, first))  {
-           return false;
-        }
-        dev->block(BST_DOING_ACQUIRE);
-        continue;
+         dev->unblock();      
+         if (!wait_for_device(dcr, jcr->errmsg, first))  {
+            return false;
+         }
+         dev->block(BST_DOING_ACQUIRE);
+         continue;
       case -1:
-        goto bail_out;               /* error */
+         goto bail_out;               /* error */
       default:
-        break;                       /* OK, reserve drive */
+         break;                       /* OK, reserve drive */
       }
       break;
    }
@@ -433,8 +433,8 @@ bail_out:
 
 /*
  * Returns: 1 if drive can be reserved
- *         0 if we should wait
- *        -1 on error
+ *          0 if we should wait
+ *         -1 on error
  */
 static int can_reserve_drive(DCR *dcr) 
 {
@@ -445,21 +445,21 @@ static int can_reserve_drive(DCR *dcr)
     */
    if (!dev->can_append() && dev->num_writers == 0) {
       /* Now check if there are any reservations on the drive */
-      if (dev->reserved_device) {          
-        /* Yes, now check if we want the same Pool and pool type */
-        if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
-            strcmp(dev->pool_type, dcr->pool_type) == 0) {
-           /* OK, compatible device */
-        } else {
-           /* Drive not suitable for us */
-           return 0;                 /* wait */
-        }
+      if (dev->reserved_device) {           
+         /* Yes, now check if we want the same Pool and pool type */
+         if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
+             strcmp(dev->pool_type, dcr->pool_type) == 0) {
+            /* OK, compatible device */
+         } else {
+            /* Drive not suitable for us */
+            return 0;                 /* wait */
+         }
       } else {
-        /* Device is available but not yet reserved, reserve it for us */
-        bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
-        bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
+         /* Device is available but not yet reserved, reserve it for us */
+         bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
+         bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
       }
-      return 1;                      /* reserve drive */
+      return 1;                       /* reserve drive */
    }
 
    /*
@@ -469,19 +469,19 @@ static int can_reserve_drive(DCR *dcr)
       Dmsg0(190, "device already in append.\n");
       /* Yes, now check if we want the same Pool and pool type */
       if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
-         strcmp(dev->pool_type, dcr->pool_type) == 0) {
-        /* OK, compatible device */
+          strcmp(dev->pool_type, dcr->pool_type) == 0) {
+         /* OK, compatible device */
       } else {
-        /* Drive not suitable for us */
+         /* Drive not suitable for us */
          Jmsg(jcr, M_WARNING, 0, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
-        return 0;                    /* wait */
+         return 0;                    /* wait */
       }
    } else {
       Pmsg0(000, "Logic error!!!! Should not get here.\n");
       Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
-      return -1;                     /* error, should not get here */
+      return -1;                      /* error, should not get here */
    }
-   return 1;                         /* reserve drive */
+   return 1;                          /* reserve drive */
 }
 
 /*
@@ -489,7 +489,7 @@ static int can_reserve_drive(DCR *dcr)
  *  If this is the first one, we read the label.
  *
  *  Returns: NULL if failed for any reason
- *          dcr if successful.
+ *           dcr if successful.
  *   Note, normally reserve_device_for_append() is called
  *   before this routine.
  */
@@ -532,33 +532,34 @@ DCR *acquire_device_for_append(DCR *dcr)
        */
       bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName));
       if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
-         !(dir_find_next_appendable_volume(dcr) &&
-           strcmp(dev->VolHdr.VolName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
+          !(dir_find_next_appendable_volume(dcr) &&
+            strcmp(dev->VolHdr.VolName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
          Dmsg0(190, "Wrong tape mounted.\n");
-        if (dev->num_writers != 0 || dev->reserved_device) {
+         if (dev->num_writers != 0 || dev->reserved_device) {
             Jmsg(jcr, M_FATAL, 0, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
-           goto get_out;
-        }
-        /* Wrong tape mounted, release it, then fall through to get correct one */
+            goto get_out;
+         }
+         /* Wrong tape mounted, release it, then fall through to get correct one */
          Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
-        release = true;
-        do_mount = true;
+         release = true;
+         do_mount = true;
       } else {
-        /*
-         * At this point, the correct tape is already mounted, so
-         *   we do not need to do mount_next_write_volume(), unless
-         *   we need to recycle the tape.
-         */
+         /*
+          * At this point, the correct tape is already mounted, so
+          *   we do not need to do mount_next_write_volume(), unless
+          *   we need to recycle the tape.
+          */
           recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
           Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
-         if (recycle && dev->num_writers != 0) {
+          if (recycle && dev->num_writers != 0) {
              Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
-                  " because it is in use by another job.\n"));
-            goto get_out;
-         }
-         if (dev->num_writers == 0) {
-            memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
-         }
+                  " on device %s because it is in use by another job.\n"),
+                  dev->VolHdr.VolName, dev->print_name());
+             goto get_out;
+          }
+          if (dev->num_writers == 0) {
+             memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
+          }
        }
    } else {
       /* Not already in append mode, so mount the device */
@@ -571,16 +572,16 @@ DCR *acquire_device_for_append(DCR *dcr)
       Dmsg0(190, "Do mount_next_write_vol\n");
       bool mounted = mount_next_write_volume(dcr, release);
       if (!mounted) {
-        if (!job_canceled(jcr)) {
+         if (!job_canceled(jcr)) {
             /* Reduce "noise" -- don't print if job canceled */
             Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
-              dev->print_name());
-        }
-        goto get_out;
+               dev->print_name());
+         }
+         goto get_out;
       }
    }
 
-   dev->num_writers++;               /* we are now a writer */
+   dev->num_writers++;                /* we are now a writer */
    if (jcr->NumVolumes == 0) {
       jcr->NumVolumes = 1;
    }
@@ -605,9 +606,9 @@ ok_out:
  */
 bool release_device(DCR *dcr)
 {
-   bool ok = true;
    JCR *jcr = dcr->jcr;
    DEVICE *dev = dcr->dev;
+   bool ok = true;
 
    lock_device(dev);
    Dmsg1(100, "release_device device is %s\n", dev_is_tape(dev)?"tape":"disk");
@@ -619,38 +620,45 @@ bool release_device(DCR *dcr)
    }
 
    if (dev->can_read()) {
-      dev->clear_read();             /* clear read bit */
+      dev->clear_read();              /* clear read bit */
 
       /******FIXME**** send read volume usage statistics to director */
 
    } 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()) {
          Dmsg0(100, "dir_create_jobmedia_record. Release\n");
-        if (!dir_create_jobmedia_record(dcr)) {
+         if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
             Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
-              dcr->VolCatInfo.VolCatName, jcr->Job);
-           ok = false;
-        }
-        /* If no more writers, write an EOF */
-        if (!dev->num_writers && dev_can_write(dev)) {
-           weof_dev(dev, 1);
-           write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolName);
-        }
-        dev->VolCatInfo.VolCatFiles = dev->file;   /* set number of files */
-        dev->VolCatInfo.VolCatJobs++;              /* increment number of jobs */
-        /* Note! do volume update before close, which zaps VolCatInfo */
-         Dmsg0(100, "dir_update_vol_info. Release0\n");
-        dir_update_volume_info(dcr, false); /* send Volume info to Director */
-         Dmsg0(100, "==== write ansi eof label \n");
+               dcr->VolCatInfo.VolCatName, jcr->Job);
+         }
+         /* If no more writers, write an EOF */
+         if (!dev->num_writers && dev_can_write(dev)) {
+            weof_dev(dev, 1);
+            write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolName);
+            Dmsg0(100, "==== write ansi eof label \n");
+         }
+         if (!dev->at_weot()) {
+            dev->VolCatInfo.VolCatFiles = dev->file;   /* set number of files */
+            dev->VolCatInfo.VolCatJobs++;              /* increment number of jobs */
+            /* Note! do volume update before close, which zaps VolCatInfo */
+            Dmsg0(100, "dir_update_vol_info. Release0\n");
+            dir_update_volume_info(dcr, false); /* send Volume info to Director */
+         }
       }
 
    } else {
-      /*               
-       * If we reach here, it is most likely because the
+      /*                
+       * 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.
+       *   there are no writers. It was probably reserved.
        */
    }
 
@@ -670,17 +678,17 @@ bool release_device(DCR *dcr)
       alert = edit_device_codes(dcr, alert, "");
       bpipe = open_bpipe(alert, 0, "r");
       if (bpipe) {
-        while (fgets(line, sizeof(line), bpipe->rfd)) {
+         while (fgets(line, sizeof(line), bpipe->rfd)) {
             Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
-        }
-        status = close_bpipe(bpipe);
+         }
+         status = close_bpipe(bpipe);
       } else {
-        status = errno;
+         status = errno;
       }
       if (status != 0) {
-        berrno be;
+         berrno be;
          Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
-             alert, be.strerror(status));
+              alert, be.strerror(status));
       }
 
       Dmsg1(400, "alert status=%d\n", status);
index 8904fad7710a19b3f4293ceaa7f00974a5804880..95d9bdf0e505f821eb397062b850d941669412e6 100644 (file)
@@ -86,7 +86,7 @@ bool do_append_data(JCR *jcr)
     */
    if (!write_session_label(dcr, SOS_LABEL)) {
       Jmsg1(jcr, M_FATAL, 0, _("Write session label failed. ERR=%s\n"),
-        strerror_dev(dev));
+         strerror_dev(dev));
       set_jcr_job_status(jcr, JS_ErrorTerminated);
       ok = false;
    }
@@ -98,29 +98,29 @@ bool do_append_data(JCR *jcr)
    if (!bnet_fsend(fd_sock, OK_data)) {
       berrno be;
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to FD. ERR=%s\n"),
-           be.strerror(fd_sock->b_errno));
+            be.strerror(fd_sock->b_errno));
       ok = false;
    }
 
    /*
     * Get Data from File daemon, write to device.  To clarify what is
-    *  going on here.  We expect:
-    *    - A stream header
-    *    - Multiple records of data
-    *    - EOD record
+    *   going on here.  We expect:
+    *     - A stream header
+    *     - Multiple records of data
+    *     - EOD record
     *
-    *   The Stream header is just used to sychronize things, and
-    *   none of the stream header is written to tape.
-    *   The Multiple records of data, contain first the Attributes,
-    *   then after another stream header, the file data, then
-    *   after another stream header, the MD5 data if any.
+    *    The Stream header is just used to sychronize things, and
+    *    none of the stream header is written to tape.
+    *    The Multiple records of data, contain first the Attributes,
+    *    then after another stream header, the file data, then
+    *    after another stream header, the MD5 data if any.
     *
-    *  So we get the (stream header, data, EOD) three time for each
-    *  file. 1. for the Attributes, 2. for the file data if any,
-    *  and 3. for the MD5 if any.
+    *   So we get the (stream header, data, EOD) three time for each
+    *   file. 1. for the Attributes, 2. for the file data if any,
+    *   and 3. for the MD5 if any.
     */
    dcr->VolFirstIndex = dcr->VolLastIndex = 0;
-   jcr->run_time = time(NULL);             /* start counting time for rates */
+   jcr->run_time = time(NULL);              /* start counting time for rates */
    for (last_file_index = 0; ok && !job_canceled(jcr); ) {
 
       /* Read Stream header from the File daemon.
@@ -131,13 +131,13 @@ bool do_append_data(JCR *jcr)
        *       info is not currently used, so is read, but ignored!
        */
      if ((n=bget_msg(ds)) <= 0) {
-        if (n == BNET_SIGNAL && ds->msglen == BNET_EOD) {
-           break;                    /* end of data */
-        }
+         if (n == BNET_SIGNAL && ds->msglen == BNET_EOD) {
+            break;                    /* end of data */
+         }
          Jmsg1(jcr, M_FATAL, 0, _("Error reading data header from FD. ERR=%s\n"),
-              bnet_strerror(ds));
-        ok = false;
-        break;
+               bnet_strerror(ds));
+         ok = false;
+         break;
       }
 
       /*
@@ -149,95 +149,95 @@ bool do_append_data(JCR *jcr)
        */
       char *p = ds->msg;
       while (B_ISSPACE(*p)) {
-        p++;
+         p++;
       }
       file_index = (int32_t)str_to_int64(p);
       while (B_ISDIGIT(*p)) {
-        p++;
+         p++;
       }
       if (!B_ISSPACE(*p) || !B_ISDIGIT(*(p+1))) {
          Jmsg1(jcr, M_FATAL, 0, _("Malformed data header from FD: %s\n"), ds->msg);
-        ok = false;
-        break;
+         ok = false;
+         break;
       }
       stream = (int32_t)str_to_int64(p);
 
       Dmsg2(890, "<filed: Header FilInx=%d stream=%d\n", file_index, stream);
 
       if (!(file_index > 0 && (file_index == last_file_index ||
-         file_index == last_file_index + 1))) {
+          file_index == last_file_index + 1))) {
          Jmsg0(jcr, M_FATAL, 0, _("File index from FD not positive or sequential\n"));
-        ok = false;
-        break;
+         ok = false;
+         break;
       }
       if (file_index != last_file_index) {
-        jcr->JobFiles = file_index;
-        last_file_index = file_index;
+         jcr->JobFiles = file_index;
+         last_file_index = file_index;
       }
 
       /* Read data stream from the File daemon.
        *  The data stream is just raw bytes
        */
       while ((n=bget_msg(ds)) > 0 && !job_canceled(jcr)) {
-        rec.VolSessionId = jcr->VolSessionId;
-        rec.VolSessionTime = jcr->VolSessionTime;
-        rec.FileIndex = file_index;
-        rec.Stream = stream;
-        rec.data_len = ds->msglen;
-        rec.data = ds->msg;            /* use message buffer */
+         rec.VolSessionId = jcr->VolSessionId;
+         rec.VolSessionTime = jcr->VolSessionTime;
+         rec.FileIndex = file_index;
+         rec.Stream = stream;
+         rec.data_len = ds->msglen;
+         rec.data = ds->msg;            /* use message buffer */
 
          Dmsg4(850, "before writ_rec FI=%d SessId=%d Strm=%s len=%d\n",
-           rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream,rec.FileIndex),
-           rec.data_len);
+            rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream,rec.FileIndex),
+            rec.data_len);
 
-        while (!write_record_to_block(dcr->block, &rec)) {
+         while (!write_record_to_block(dcr->block, &rec)) {
             Dmsg2(850, "!write_record_to_block data_len=%d rem=%d\n", rec.data_len,
-                      rec.remainder);
-           if (!write_block_to_device(dcr)) {
+                       rec.remainder);
+            if (!write_block_to_device(dcr)) {
                Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n",
-                 dev->print_name(), strerror_dev(dev));
+                  dev->print_name(), strerror_dev(dev));
                Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
-                    dev->print_name(), strerror_dev(dev));
-              ok = false;
-              break;
-           }
-        }
-        if (!ok) {
+                     dev->print_name(), strerror_dev(dev));
+               ok = false;
+               break;
+            }
+         }
+         if (!ok) {
             Dmsg0(400, "Not OK\n");
-           break;
-        }
-        jcr->JobBytes += rec.data_len;   /* increment bytes this job */
+            break;
+         }
+         jcr->JobBytes += rec.data_len;   /* increment bytes this job */
          Dmsg4(850, "write_record FI=%s SessId=%d Strm=%s len=%d\n",
-           FI_to_ascii(rec.FileIndex), rec.VolSessionId,
-           stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len);
-
-        /* Send attributes and MD5 to Director for Catalog */
-        if (stream == STREAM_UNIX_ATTRIBUTES    || stream == STREAM_MD5_SIGNATURE ||
-            stream == STREAM_UNIX_ATTRIBUTES_EX || stream == STREAM_SHA1_SIGNATURE) {
-           if (!jcr->no_attributes) {
-              if (are_attributes_spooled(jcr)) {
-                 jcr->dir_bsock->spool = true;
-              }
+            FI_to_ascii(rec.FileIndex), rec.VolSessionId,
+            stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len);
+
+         /* Send attributes and MD5 to Director for Catalog */
+         if (stream == STREAM_UNIX_ATTRIBUTES    || stream == STREAM_MD5_SIGNATURE ||
+             stream == STREAM_UNIX_ATTRIBUTES_EX || stream == STREAM_SHA1_SIGNATURE) {
+            if (!jcr->no_attributes) {
+               if (are_attributes_spooled(jcr)) {
+                  jcr->dir_bsock->spool = true;
+               }
                Dmsg0(850, "Send attributes to dir.\n");
-              if (!dir_update_file_attributes(dcr, &rec)) {
-                 jcr->dir_bsock->spool = false;
+               if (!dir_update_file_attributes(dcr, &rec)) {
+                  jcr->dir_bsock->spool = false;
                   Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
-                    bnet_strerror(jcr->dir_bsock));
-                 ok = false;
-                 break;
-              }
-              jcr->dir_bsock->spool = false;
-           }
-        }
+                     bnet_strerror(jcr->dir_bsock));
+                  ok = false;
+                  break;
+               }
+               jcr->dir_bsock->spool = false;
+            }
+         }
          Dmsg0(350, "Enter bnet_get\n");
       }
       Dmsg1(350, "End read loop with FD. Stat=%d\n", n);
       if (is_bnet_error(ds)) {
          Dmsg1(350, "Network read error from FD. ERR=%s\n", bnet_strerror(ds));
          Jmsg1(jcr, M_FATAL, 0, _("Network error on data channel. ERR=%s\n"),
-              bnet_strerror(ds));
-        ok = false;
-        break;
+               bnet_strerror(ds));
+         ok = false;
+         break;
       }
    }
 
@@ -256,9 +256,9 @@ bool do_append_data(JCR *jcr)
    if (ok || dev_can_write(dev)) {
       if (!write_session_label(dcr, EOS_LABEL)) {
          Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
-              strerror_dev(dev));
-        set_jcr_job_status(jcr, JS_ErrorTerminated);
-        ok = false;
+               strerror_dev(dev));
+         set_jcr_job_status(jcr, JS_ErrorTerminated);
+         ok = false;
       }
       if (dev->VolCatInfo.VolCatName[0] == 0) {
          Pmsg0(000, "NULL Volume name. This shouldn't happen!!!\n");
@@ -267,9 +267,9 @@ bool do_append_data(JCR *jcr)
       /* Flush out final partial block of this session */
       if (!write_block_to_device(dcr)) {
          Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"),
-              dev->print_name(), strerror_dev(dev));
+               dev->print_name(), strerror_dev(dev));
          Dmsg0(100, _("Set ok=FALSE after write_block_to_device.\n"));
-        ok = false;
+         ok = false;
       }
    }
    if (dev->VolCatInfo.VolCatName[0] == 0) {
@@ -281,45 +281,21 @@ bool do_append_data(JCR *jcr)
    } else {
       commit_data_spool(dcr);
    }
-   
-   /* If the device is nor a dvd and WritePartAfterJob
-    * is set to yes, open the next part, so, in case of a device
-    * that requires mount, it will be written to the device.
-    */
-   if (ok && dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
-      Dmsg0(100, "Writing last part because write_part_after_job is set.\n");
-      if (dev->part < dev->num_parts) {
-         Jmsg3(jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
-              dev->part, dev->num_parts, dev->print_name());
-        dev->dev_errno = EIO;
-        ok = false;
-      }
-      
-      if (ok && (open_next_part(dev) < 0)) {
-         Jmsg2(jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"),
-              dev->print_name(), strerror_dev(dev));
-        dev->dev_errno = EIO;
-        ok = false;
-      }
-      
-      dev->VolCatInfo.VolCatParts = dev->num_parts;
-   }
 
-   Dmsg1(200, "calling release device JobStatus=%d\n", jcr->JobStatus);
-   /* Release the device */
-   if (!release_device(dcr)) {
-      Pmsg0(000, _("Error in release_device\n"));
-      set_jcr_job_status(jcr, JS_ErrorTerminated);
-      ok = false;
+   if (ok) {
+      ok = dvd_close_job(dcr);  /* do DVD cleanup if any */
    }
+   
+   /* Release the device -- and send final Vol info to DIR */
+   release_device(dcr);
 
-   if (!ok) {
+   if (!ok || job_canceled(jcr)) {
       discard_attribute_spool(jcr);
    } else {
       commit_attribute_spool(jcr);
    }
 
-   dir_send_job_status(jcr);         /* update director */
+   dir_send_job_status(jcr);          /* update director */
 
    Dmsg1(100, "return from do_append_data() stat=%d\n", ok);
    return ok;
index 97844bd1034aed3e62ccd2207c25a39a3619d596..ebbf56a04df3d7e9164f7c3e12fd36eb177fe659 100644 (file)
@@ -36,6 +36,7 @@ extern int debug_level;
 static bool terminate_writing_volume(DCR *dcr);
 static bool do_new_file_bookkeeping(DCR *dcr);
 static bool do_dvd_size_checks(DCR *dcr);
+static void reread_last_block(DCR *dcr);
 
 /*
  * Dump the block header, then walk through
@@ -434,7 +435,7 @@ bool write_block_to_dev(DCR *dcr)
       blen = wlen;
 
       /* Adjust write size to min/max for tapes only */
-      if (dev->state & ST_TAPE) {
+      if (dev->is_tape()) {
         /* check for fixed block size */
         if (dev->min_block_size == dev->max_block_size) {
            wlen = block->buf_len;    /* fixed block size already rounded */
@@ -470,6 +471,7 @@ bool write_block_to_dev(DCR *dcr)
       Jmsg(jcr, M_INFO, 0, _("User defined maximum volume capacity %s exceeded on device %s.\n"),
            edit_uint64_with_commas(max_cap, ed1),  dev->dev_name);
       terminate_writing_volume(dcr);
+      reread_last_block(dcr);  /* DEBUG */
       dev->dev_errno = ENOSPC;
       return false;
    }
@@ -511,6 +513,9 @@ bool write_block_to_dev(DCR *dcr)
    }
 #endif
 
+   /*
+    * Do write here
+    */ 
    stat = write(dev->fd, block->buf, (size_t)wlen);
 
 #ifdef DEBUG_BLOCK_ZEROING
@@ -551,60 +556,9 @@ bool write_block_to_dev(DCR *dcr)
       if (!ok && !forge_on) {
         return false;
       }
-
-#define CHECK_LAST_BLOCK
-#ifdef CHECK_LAST_BLOCK
-      /*
-       * If the device is a tape and it supports backspace record,
-       *   we backspace over one or two eof marks depending on
-       *   how many we just wrote, then over the last record,
-       *   then re-read it and verify that the block number is
-       *   correct.
-       */
-      if (ok && (dev->state & ST_TAPE) && dev_cap(dev, CAP_BSR)) {
-        /* Now back up over what we wrote and read the last block */
-        if (!bsf_dev(dev, 1)) {
-           ok = false;
-            Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), strerror(dev->dev_errno));
-        }
-        if (ok && dev_cap(dev, CAP_TWOEOF) && !bsf_dev(dev, 1)) {
-           ok = false;
-            Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), strerror(dev->dev_errno));
-        }
-        /* Backspace over record */
-        if (ok && !bsr_dev(dev, 1)) {
-           ok = false;
-            Jmsg(jcr, M_ERROR, 0, _("Backspace record at EOT failed. ERR=%s\n"), strerror(dev->dev_errno));
-           /*
-            *  On FreeBSD systems, if the user got here, it is likely that his/her
-             *    tape drive is "frozen".  The correct thing to do is a
-            *    rewind(), but if we do that, higher levels in cleaning up, will
-            *    most likely write the EOS record over the beginning of the
-            *    tape.  The rewind *is* done later in mount.c when another
-            *    tape is requested. Note, the clrerror_dev() call in bsr_dev()
-            *    calls ioctl(MTCERRSTAT), which *should* fix the problem.
-            */
-        }
-        if (ok) {
-           DEV_BLOCK *lblock = new_block(dev);
-           /* Note, this can destroy dev->errmsg */
-           dcr->block = lblock;
-           if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
-               Jmsg(jcr, M_ERROR, 0, _("Re-read last block at EOT failed. ERR=%s"), dev->errmsg);
-           } else {
-              if (lblock->BlockNumber+1 == block->BlockNumber) {
-                  Jmsg(jcr, M_INFO, 0, _("Re-read of last block succeeded.\n"));
-              } else {
-                 Jmsg(jcr, M_ERROR, 0, _(
-"Re-read of last block failed. Last block=%u Current block=%u.\n"),
-                      lblock->BlockNumber, block->BlockNumber);
-              }
-           }
-           free_block(lblock);
-           dcr->block = block;
-        }
+      if (ok) {
+        reread_last_block(dcr);
       }
-#endif
       return false;
    }
 
@@ -618,7 +572,7 @@ bool write_block_to_dev(DCR *dcr)
    block->BlockNumber++;
 
    /* Update dcr values */
-   if (dev_state(dev, ST_TAPE)) {
+   if (dev->is_tape()) {
       dcr->EndBlock = dev->EndBlock;
       dcr->EndFile  = dev->EndFile;
    } else {
@@ -642,6 +596,74 @@ bool write_block_to_dev(DCR *dcr)
    return true;
 }
 
+static void reread_last_block(DCR *dcr)
+{
+#define CHECK_LAST_BLOCK
+#ifdef CHECK_LAST_BLOCK
+   bool ok = true;
+   DEVICE *dev = dcr->dev;
+   JCR *jcr = dcr->jcr;
+   DEV_BLOCK *block = dcr->block;
+   /*
+    * If the device is a tape and it supports backspace record,
+    *  we backspace over one or two eof marks depending on
+    *  how many we just wrote, then over the last record,
+    *  then re-read it and verify that the block number is
+    *  correct.
+    */
+   if (dev->is_tape() && dev_cap(dev, CAP_BSR)) {
+      /* Now back up over what we wrote and read the last block */
+      if (!bsf_dev(dev, 1)) {
+        berrno be;
+        ok = false;
+         Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), 
+             be.strerror(dev->dev_errno));
+      }
+      if (ok && dev_cap(dev, CAP_TWOEOF) && !bsf_dev(dev, 1)) {
+        berrno be;
+        ok = false;
+         Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), 
+             be.strerror(dev->dev_errno));
+      }
+      /* Backspace over record */
+      if (ok && !bsr_dev(dev, 1)) {
+        berrno be;
+        ok = false;
+         Jmsg(jcr, M_ERROR, 0, _("Backspace record at EOT failed. ERR=%s\n"), 
+             be.strerror(dev->dev_errno));
+        /*
+         *  On FreeBSD systems, if the user got here, it is likely that his/her
+          *    tape drive is "frozen".  The correct thing to do is a
+         *    rewind(), but if we do that, higher levels in cleaning up, will
+         *    most likely write the EOS record over the beginning of the
+         *    tape.  The rewind *is* done later in mount.c when another
+         *    tape is requested. Note, the clrerror_dev() call in bsr_dev()
+         *    calls ioctl(MTCERRSTAT), which *should* fix the problem.
+         */
+      }
+      if (ok) {
+        DEV_BLOCK *lblock = new_block(dev);
+        /* Note, this can destroy dev->errmsg */
+        dcr->block = lblock;
+        if (!read_block_from_dev(dcr, NO_BLOCK_NUMBER_CHECK)) {
+            Jmsg(jcr, M_ERROR, 0, _("Re-read last block at EOT failed. ERR=%s"), 
+                dev->errmsg);
+        } else {
+           if (lblock->BlockNumber+1 == block->BlockNumber) {
+               Jmsg(jcr, M_INFO, 0, _("Re-read of last block succeeded.\n"));
+           } else {
+              Jmsg(jcr, M_ERROR, 0, _(
+"Re-read of last block failed. Last block=%u Current block=%u.\n"),
+                   lblock->BlockNumber, block->BlockNumber);
+           }
+        }
+        free_block(lblock);
+        dcr->block = block;
+      }
+   }
+#endif
+}
+
 static bool terminate_writing_volume(DCR *dcr)
 {
    DEVICE *dev = dcr->dev;
@@ -668,7 +690,9 @@ static bool terminate_writing_volume(DCR *dcr)
    if (ok) {
       ok = write_ansi_ibm_labels(dcr, ANSI_EOV_LABEL, dev->VolHdr.VolName);
    }
-   dev->VolCatInfo.VolCatFiles = dev->file;
+   bstrncpy(dev->VolCatInfo.VolCatStatus, "Full", sizeof(dev->VolCatInfo.VolCatStatus));
+   dev->VolCatInfo.VolCatFiles = dev->file;   /* set number of files */
+   dev->VolCatInfo.VolCatJobs++;             /* increment number of jobs */
    
    if (dev->is_dvd()) { /* Write the current (and last) part. */
       open_next_part(dev);
@@ -699,7 +723,7 @@ static bool terminate_writing_volume(DCR *dcr)
       Jmsg(dcr->jcr, M_ERROR, 0, "%s", dev->errmsg);
    }
 bail_out:
-   dev->set_eot();
+   dev->set_eot();                   /* no more writing this tape */
    Dmsg1(100, "Leave terminate_writing_volume -- %s\n", ok?"OK":"ERROR");
    return ok;
 }
@@ -954,7 +978,7 @@ reread:
       Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
       Pmsg1(000, "%s", dev->errmsg);
       /* Attempt to reposition to re-read the block */
-      if (dev->state & ST_TAPE) {
+      if (dev->is_tape()) {
          Dmsg0(200, "BSR for reread; block too big for buffer.\n");
         if (!bsr_dev(dev, 1)) {
             Jmsg(jcr, M_ERROR, 0, "%s", strerror_dev(dev));
@@ -1002,7 +1026,7 @@ reread:
    dev->block_num++;
 
    /* Update dcr values */
-   if (dev->state & ST_TAPE) {
+   if (dev->is_tape()) {
       dcr->EndBlock = dev->EndBlock;
       dcr->EndFile  = dev->EndFile;
    } else {
index e7d2e1655dbebb2297234e576089c0e64ecb7f57..bad6ba545e19e357522baa41cadfde94bb477ac7 100644 (file)
 #include "bacula.h"
 #include "stored.h"
 
+#ifndef O_NONBLOCK 
+#define O_NONBLOCK 0
+#endif
+
 /* Functions in dvd.c */ 
 void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name);
 int mount_dev(DEVICE* dev, int timeout);
@@ -90,6 +94,8 @@ void update_free_space_dev(DEVICE* dev);
 /* Forward referenced functions */
 void set_os_device_parameters(DEVICE *dev);
 static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat);
+static void open_tape_device(DEVICE *dev, int mode);
+static void open_file_device(DEVICE *dev, int mode);
 
 /*
  * Allocate and initialize the DEVICE structure
@@ -292,6 +298,8 @@ open_dev(DEVICE *dev, char *VolName, int mode)
    }
    if (VolName) {
       bstrncpy(dev->VolCatInfo.VolCatName, VolName, sizeof(dev->VolCatInfo.VolCatName));
+   } else {
+      dev->VolCatInfo.VolCatName[0] = 0;
    }
 
    Dmsg3(29, "open_dev: tape=%d dev_name=%s vol=%s\n", dev_is_tape(dev),
@@ -299,145 +307,180 @@ open_dev(DEVICE *dev, char *VolName, int mode)
    dev->state &= ~(ST_LABEL|ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF);
    dev->label_type = B_BACULA_LABEL;
    if (dev->is_tape() || dev->is_fifo()) {
-      dev->file_size = 0;
-      int timeout;
-      int ioerrcnt = 10;
-      Dmsg0(29, "open_dev: device is tape\n");
-      if (mode == OPEN_READ_WRITE) {
-        dev->mode = O_RDWR | O_BINARY;
-      } else if (mode == OPEN_READ_ONLY) {
-        dev->mode = O_RDONLY | O_BINARY;
-      } else if (mode == OPEN_WRITE_ONLY) {
-        dev->mode = O_WRONLY | O_BINARY;
-      } else {
-         Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n"));
+      open_tape_device(dev, mode);
+   } else {
+      open_file_device(dev, mode);
+   }
+   return dev->fd;
+}
+
+static void open_tape_device(DEVICE *dev, int mode) 
+{
+   int nonblocking = 0;;
+   dev->file_size = 0;
+   int timeout;
+   int ioerrcnt = 10;
+   Dmsg0(29, "open_dev: device is tape\n");
+   if (mode == OPEN_READ_WRITE) {
+      dev->mode = O_RDWR | O_BINARY;
+   } else if (mode == OPEN_READ_ONLY) {
+      dev->mode = O_RDONLY | O_BINARY;
+   } else if (mode == OPEN_WRITE_ONLY) {
+      dev->mode = O_WRONLY | O_BINARY;
+   } else {
+      Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n"));
+   }
+   timeout = dev->max_open_wait;
+   errno = 0;
+   if (dev->open_nowait) {
+       /* Set wait counters to zero for no wait */
+       timeout = ioerrcnt = 0;
+       /* Open drive in non-block mode */
+       nonblocking = O_NONBLOCK;
+   }
+   if (dev->is_fifo() && timeout) {
+      /* Set open timer */
+      dev->tid = start_thread_timer(pthread_self(), timeout);
+   }
+   /* If busy retry each second for max_open_wait seconds */
+open_again:
+   Dmsg1(500, "Try open %s\n", dev->dev_name);
+   while ((dev->fd = open(dev->dev_name, dev->mode, MODE_RW+nonblocking)) < 0) {
+      berrno be;
+      Dmsg2(500, "Open error errno=%d ERR=%s\n", errno, be.strerror());
+      if (errno == EINTR || errno == EAGAIN) {
+         Dmsg0(500, "Continue open\n");
+        continue;
       }
-      timeout = dev->max_open_wait;
-      errno = 0;
-      if (dev->is_fifo() && timeout) {
-        /* Set open timer */
-        dev->tid = start_thread_timer(pthread_self(), timeout);
+      /* Busy wait for specified time (default = 5 mins) */
+      if (errno == EBUSY && timeout-- > 0) {
+         Dmsg2(100, "Device %s busy. ERR=%s\n", dev->print_name(), be.strerror());
+        bmicrosleep(1, 0);
+        continue;
       }
-      /* If busy retry each second for max_open_wait seconds */
-      while ((dev->fd = open(dev->dev_name, dev->mode, MODE_RW)) < 0) {
-        berrno be;
-        if (errno == EINTR || errno == EAGAIN) {
-           continue;
-        }
-        /* Busy wait for specified time (default = 5 mins) */
-        if (errno == EBUSY && timeout-- > 0) {
-            Dmsg2(100, "Device %s busy. ERR=%s\n", dev->print_name(), be.strerror());
-           bmicrosleep(1, 0);
-           continue;
-        }
-        /* IO error (no volume) try 10 times every 6 seconds */
-        if (errno == EIO && ioerrcnt-- > 0) {
-           bmicrosleep(5, 0);
-           continue;
-        }
-        dev->dev_errno = errno;
-         Mmsg2(&dev->errmsg, _("Unable to open device %s: ERR=%s\n"),
-              dev->print_name(), be.strerror(dev->dev_errno));
-        /* Stop any open timer we set */
-        if (dev->tid) {
-           stop_thread_timer(dev->tid);
-           dev->tid = 0;
-        }
-        Emsg0(M_FATAL, 0, dev->errmsg);
-        break;
+      /* IO error (no volume) try 10 times every 6 seconds */
+      if (errno == EIO && ioerrcnt-- > 0) {
+        bmicrosleep(5, 0);
+         Dmsg0(500, "Continue open\n");
+        continue;
       }
-      if (dev->fd >= 0) {
-        dev->dev_errno = 0;
-        dev->state |= ST_OPENED;
-        dev->use_count = 1;
-        update_pos_dev(dev);             /* update position */
-        set_os_device_parameters(dev);      /* do system dependent stuff */
-      }
-      /* Stop any open() timer we started */
+      dev->dev_errno = errno;
+      Mmsg2(&dev->errmsg, _("Unable to open device %s: ERR=%s\n"),
+           dev->print_name(), be.strerror(dev->dev_errno));
+      /* Stop any open timer we set */
       if (dev->tid) {
         stop_thread_timer(dev->tid);
         dev->tid = 0;
       }
-      Dmsg1(29, "open_dev: tape %d opened\n", dev->fd);
-   } else {
-      POOL_MEM archive_name(PM_FNAME);
-      struct stat filestat;
-      /*
-       * Handle opening of File Archive (not a tape)
-       */     
-      if (dev->part == 0) {
-        dev->file_size = 0;
-      }
-      dev->part_size = 0;
-      
-      /* if num_parts has not been set, but VolCatInfo is available, copy
-       * it from the VolCatInfo.VolCatParts */
-      if (dev->num_parts < dev->VolCatInfo.VolCatParts) {
-        dev->num_parts = dev->VolCatInfo.VolCatParts;
-      }
-      
-      if (VolName == NULL || *VolName == 0) {
-         Mmsg(dev->errmsg, _("Could not open file device %s. No Volume name given.\n"),
-           dev->print_name());
-        return -1;
+      Emsg0(M_FATAL, 0, dev->errmsg);
+      break;
+   }
+   if (dev->fd >= 0) {
+      if (mode != 0) {
+        /* If opened in non-block mode, close it an open it normally */
+        mode = 0;
+        close(dev->fd);
+        goto open_again;
       }
-      get_filename(dev, VolName, archive_name);
+      dev->dev_errno = 0;
+      dev->state |= ST_OPENED;
+      dev->use_count = 1;
+      update_pos_dev(dev);            /* update position */
+      set_os_device_parameters(dev);     /* do system dependent stuff */
+      Dmsg0(500, "Open OK\n");
+   }
+   /* Stop any open() timer we started */
+   if (dev->tid) {
+      stop_thread_timer(dev->tid);
+      dev->tid = 0;
+   }
+   Dmsg1(29, "open_dev: tape %d opened\n", dev->fd);
+}
 
-      if (mount_dev(dev, 1) < 0) {
-         Mmsg(dev->errmsg, _("Could not mount device %s.\n"),
-             dev->print_name());
-        Emsg0(M_FATAL, 0, dev->errmsg);
-        dev->fd = -1;
-        return dev->fd;
-      }
-           
-      Dmsg2(29, "open_dev: device is disk %s (mode:%d)\n", archive_name.c_str(), mode);
-      dev->openmode = mode;
-      
-      /*
-       * If we are not trying to access the last part, set mode to 
-       *   OPEN_READ_ONLY as writing would be an error.
-       */
-      if (dev->part < dev->num_parts) {
-        mode = OPEN_READ_ONLY;
-      }
-      
-      if (mode == OPEN_READ_WRITE) {
-        dev->mode = O_CREAT | O_RDWR | O_BINARY;
-      } else if (mode == OPEN_READ_ONLY) {
-        dev->mode = O_RDONLY | O_BINARY;
-      } else if (mode == OPEN_WRITE_ONLY) {
-        dev->mode = O_WRONLY | O_BINARY;
-      } else {
-         Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n"));
-      }
-      /* If creating file, give 0640 permissions */
-      if ((dev->fd = open(archive_name.c_str(), dev->mode, 0640)) < 0) {
+/*
+ * Open a file or DVD device
+ */
+static void open_file_device(DEVICE *dev, int mode) 
+{
+   POOL_MEM archive_name(PM_FNAME);
+   struct stat filestat;
+   /*
+    * Handle opening of File Archive (not a tape)
+    */    
+   if (dev->part == 0) {
+      dev->file_size = 0;
+   }
+   dev->part_size = 0;
+   
+   /* if num_parts has not been set, but VolCatInfo is available, copy
+    * it from the VolCatInfo.VolCatParts */
+   if (dev->num_parts < dev->VolCatInfo.VolCatParts) {
+      dev->num_parts = dev->VolCatInfo.VolCatParts;
+   }
+   
+   if (dev->VolCatInfo.VolCatName[0] == 0) {
+      Mmsg(dev->errmsg, _("Could not open file device %s. No Volume name given.\n"),
+        dev->print_name());
+      dev->fd = -1;
+      return;
+   }
+   get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
+
+   if (mount_dev(dev, 1) < 0) {
+      Mmsg(dev->errmsg, _("Could not mount device %s.\n"),
+          dev->print_name());
+      Emsg0(M_FATAL, 0, dev->errmsg);
+      dev->fd = -1;
+      return;
+   }
+        
+   Dmsg2(29, "open_dev: device is disk %s (mode:%d)\n", archive_name.c_str(), mode);
+   dev->openmode = mode;
+   
+   /*
+    * If we are not trying to access the last part, set mode to 
+    *  OPEN_READ_ONLY as writing would be an error.
+    */
+   if (dev->part < dev->num_parts) {
+      mode = OPEN_READ_ONLY;
+   }
+   
+   if (mode == OPEN_READ_WRITE) {
+      dev->mode = O_CREAT | O_RDWR | O_BINARY;
+   } else if (mode == OPEN_READ_ONLY) {
+      dev->mode = O_RDONLY | O_BINARY;
+   } else if (mode == OPEN_WRITE_ONLY) {
+      dev->mode = O_WRONLY | O_BINARY;
+   } else {
+      Emsg0(M_ABORT, 0, _("Illegal mode given to open_dev.\n"));
+   }
+   /* If creating file, give 0640 permissions */
+   if ((dev->fd = open(archive_name.c_str(), dev->mode, 0640)) < 0) {
+      berrno be;
+      dev->dev_errno = errno;
+      Mmsg2(&dev->errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), 
+           be.strerror());
+      Emsg0(M_FATAL, 0, dev->errmsg);
+   } else {
+      dev->dev_errno = 0;
+      dev->state |= ST_OPENED;
+      dev->use_count = 1;
+      update_pos_dev(dev);               /* update position */
+      if (fstat(dev->fd, &filestat) < 0) {
         berrno be;
         dev->dev_errno = errno;
-         Mmsg2(&dev->errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), be.strerror());
+         Mmsg2(&dev->errmsg, _("Could not fstat: %s, ERR=%s\n"), archive_name.c_str(), 
+              be.strerror());
         Emsg0(M_FATAL, 0, dev->errmsg);
       } else {
-        dev->dev_errno = 0;
-        dev->state |= ST_OPENED;
-        dev->use_count = 1;
-        update_pos_dev(dev);                /* update position */
-        if (fstat(dev->fd, &filestat) < 0) {
-           berrno be;
-           dev->dev_errno = errno;
-            Mmsg2(&dev->errmsg, _("Could not fstat: %s, ERR=%s\n"), archive_name.c_str(), be.strerror());
-           Emsg0(M_FATAL, 0, dev->errmsg);
-        } else {
-           dev->part_size = filestat.st_size;
-        }
-      }
-      Dmsg4(29, "open_dev: disk fd=%d opened, part=%d/%d, part_size=%u\n", dev->fd, dev->part, dev->num_parts, dev->part_size);
-      if (dev->is_dvd() && (dev->mode != OPEN_READ_ONLY) && 
-         (dev->free_space_errno == 0 || dev->num_parts == dev->part)) {
-        update_free_space_dev(dev);
+        dev->part_size = filestat.st_size;
       }
    }
-   return dev->fd;
+   Dmsg4(29, "open_dev: disk fd=%d opened, part=%d/%d, part_size=%u\n", dev->fd, dev->part, dev->num_parts, dev->part_size);
+   if (dev->is_dvd() && (dev->mode != OPEN_READ_ONLY) && 
+       (dev->free_space_errno == 0 || dev->num_parts == dev->part)) {
+      update_free_space_dev(dev);
+   }
 }
 
 #ifdef debug_tracing
index 545d2b2604b04535a960bad4e3b80d139f6a68bc..bd9df85310e66d0df0f139f9f3d0ae49968d1f38 100644 (file)
@@ -197,6 +197,7 @@ public:
    int mode;                          /* read/write modes */
    int openmode;                      /* parameter passed to open_dev (useful to reopen the device) */
    bool autoselect;                   /* Autoselect in autochanger */
+   bool open_nowait;                  /* If set, don t wait on open */
    int label_type;                    /* Bacula/ANSI/IBM label types */
    uint32_t drive_index;              /* Autochanger drive index */
    POOLMEM *dev_name;                 /* Physical device name */
@@ -239,6 +240,10 @@ public:
    char pool_name[MAX_NAME_LENGTH];   /* pool name */
    char pool_type[MAX_NAME_LENGTH];   /* pool type */
 
+
+
+
+
    /* Device wait times ***FIXME*** look at durations */
    char BadVolName[MAX_NAME_LENGTH];  /* Last wrong Volume mounted */
    bool poll;                         /* set to poll Volume */
@@ -250,19 +255,19 @@ public:
    int num_wait;
 
    /* Methods */
-   int is_tape() const;
-   int is_file() const;
-   int is_fifo() const;
-   int is_dvd() const;
-   int is_open() const;
-   int is_offline() const;
-   int is_labeled() const;
+   int is_tape() const { return state & ST_TAPE; }
+   int is_file() const { return state & ST_FILE; }
+   int is_fifo() const { return state & ST_FIFO; }
+   int is_dvd() const  { return state & ST_DVD; }
+   int is_open() const { return state & ST_OPENED; }
+   int is_offline() const { return state & ST_OFFLINE; }
+   int is_labeled() const { return state & ST_LABEL; }
    int is_busy() const;               /* either reading or writing */
-   int at_eof() const;
-   int at_eom() const;
-   int at_eot() const;
-   int can_append() const;
-   int can_read() const;
+   int at_eof() const { return state & ST_EOF; }
+   int at_eot() const { return state & ST_EOT; }
+   int at_weot() const { return state & ST_WEOT; }
+   int can_append() const { return state & ST_APPEND; }
+   int can_read() const   { return state & ST_READ; }
    bool can_steal_lock() const { return dev_blocked &&
                     (dev_blocked == BST_UNMOUNTED ||
                      dev_blocked == BST_WAITING_FOR_SYSOP ||
@@ -293,18 +298,7 @@ public:
 };
 
 /* Note, these return int not bool! */
-inline int DEVICE::is_tape() const { return state & ST_TAPE; }
-inline int DEVICE::is_file() const { return state & ST_FILE; }
-inline int DEVICE::is_fifo() const { return state & ST_FIFO; }
-inline int DEVICE::is_dvd()  const { return state & ST_DVD; }
-inline int DEVICE::is_open() const { return state & ST_OPENED; }
-inline int DEVICE::is_offline() const { return state & ST_OFFLINE; }
-inline int DEVICE::is_labeled() const { return state & ST_LABEL; }
 inline int DEVICE::is_busy() const { return state & ST_READ || num_writers || reserved_device; }
-inline int DEVICE::at_eof() const { return state & ST_EOF; }
-inline int DEVICE::at_eot() const { return state & ST_EOT; }
-inline int DEVICE::can_append() const { return state & ST_APPEND; }
-inline int DEVICE::can_read() const { return state & ST_READ; }
 inline const char *DEVICE::strerror() const { return errmsg; }
 inline const char *DEVICE::archive_name() const { return dev_name; }
 inline const char *DEVICE::print_name() const { return prt_name; }
index 436c1bd926054e4964e671d545a0699cf2d1bae6..14715689bf07c5866b062afaf1d0887ff7df8d04 100644 (file)
@@ -100,18 +100,6 @@ bool fixup_device_block_write_error(DCR *dcr)
    /* Unlock, but leave BLOCKED */
    unlock_device(dev);
 
-   bstrncpy(dev->VolCatInfo.VolCatStatus, "Full", sizeof(dev->VolCatInfo.VolCatStatus));
-   Dmsg2(100, "Call update_vol_info Stat=%s Vol=%s\n",
-      dev->VolCatInfo.VolCatStatus, dev->VolCatInfo.VolCatName);
-   dev->VolCatInfo.VolCatFiles = dev->file;   /* set number of files */
-   dev->VolCatInfo.VolCatJobs++;             /* increment number of jobs */
-   if (!dir_update_volume_info(dcr, false)) {   /* send Volume info to Director */
-      P(dev->mutex);
-      unblock_device(dev);
-      return false;               /* device locked */
-   }
-   Dmsg0(100, "Back from update_vol_info\n");
-
    bstrncpy(PrevVolName, dev->VolCatInfo.VolCatName, sizeof(PrevVolName));
    bstrncpy(dev->VolHdr.PrevVolName, PrevVolName, sizeof(dev->VolHdr.PrevVolName));
 
@@ -284,14 +272,16 @@ bool first_open_device(DEVICE *dev)
          mode = OPEN_READ_WRITE;
        }
       Dmsg0(129, "Opening device.\n");
+      dev->open_nowait = true;
       if (open_dev(dev, NULL, mode) < 0) {
          Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), dev->errmsg);
+        dev->open_nowait = false;
         unlock_device(dev);
         return false;
       }
    }
    Dmsg1(129, "open_dev %s OK\n", dev->print_name());
-
+   dev->open_nowait = false;
    unlock_device(dev);
    return true;
 }
index 390297d56b13ad06de6916801e3fae6a35a56995..763f47fa4c2eb0ee5c6af08c0fb069f238751fa8 100644 (file)
@@ -7,9 +7,9 @@
  *    in job.c.
  *
  *    N.B. in this file, in general we must use P(dev->mutex) rather
- *     than lock_device(dev) so that we can examine the blocked
+ *      than lock_device(dev) so that we can examine the blocked
  *      state rather than blocking ourselves. In some "safe" cases,
- *     we can do things to a blocked device. CAREFUL!!!!
+ *      we can do things to a blocked device. CAREFUL!!!!
  *
  *    File daemon commands are handled in fdcmd.c
  *
@@ -79,8 +79,8 @@ static bool do_label(JCR *jcr, int relabel);
 static DEVICE *find_device(JCR *jcr, POOL_MEM &dev_name);
 static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot);
 static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
-                              char *newname, char *poolname,
-                              int Slot, int relabel);
+                               char *newname, char *poolname,
+                               int Slot, int relabel);
 static bool try_autoload_device(JCR *jcr, int slot, const char *VolName);
 static void send_dir_busy_message(BSOCK *dir, DEVICE *dev);
 
@@ -107,10 +107,10 @@ static struct s_cmds cmds[] = {
    {"status",      status_cmd,      1},
    {".status",     qstatus_cmd,     1},
    {"unmount",     unmount_cmd,     0},
-   {"use storage", use_cmd,         0},
+   {"use storage=", use_cmd,        0},
    {"run",         run_cmd,         0},
 // {"query",       query_cmd,       0},
-   {NULL,       NULL}                      /* list terminator */
+   {NULL,        NULL}                      /* list terminator */
 };
 
 
@@ -155,7 +155,7 @@ void *handle_connection_request(void *arg)
    }
    /*
     * See if this is a File daemon connection. If so
-    *  call FD handler.
+    *   call FD handler.
     */
    Dmsg1(110, "Conn: %s", bs->msg);
    if (sscanf(bs->msg, "Hello Start Job %127s", name) == 1) {
@@ -168,7 +168,7 @@ void *handle_connection_request(void *arg)
     */
    Dmsg0(110, "Start Dir Job\n");
    jcr = new_jcr(sizeof(JCR), stored_free_jcr); /* create Job Control Record */
-   jcr->dir_bsock = bs;              /* save Director bsock */
+   jcr->dir_bsock = bs;               /* save Director bsock */
    jcr->dir_bsock->jcr = jcr;
    jcr->dcrs = New(alist(10, not_owned_by_alist));
    /* Initialize FD start condition variable */
@@ -192,34 +192,34 @@ void *handle_connection_request(void *arg)
    for (quit=false; !quit;) {
       /* Read command */
       if ((bnet_stat = bnet_recv(bs)) <= 0) {
-        break;               /* connection terminated */
+         break;               /* connection terminated */
       }
       Dmsg1(199, "<dird: %s\n", bs->msg);
       found = false;
       for (i=0; cmds[i].cmd; i++) {
-       if (strncmp(cmds[i].cmd, bs->msg, strlen(cmds[i].cmd)) == 0) {
-          if ((!cmds[i].monitoraccess) && (jcr->director->monitor)) {
+        if (strncmp(cmds[i].cmd, bs->msg, strlen(cmds[i].cmd)) == 0) {
+           if ((!cmds[i].monitoraccess) && (jcr->director->monitor)) {
               Dmsg1(100, "Command %s illegal.\n", cmds[i].cmd);
-             bnet_fsend(bs, illegal_cmd);
-             bnet_sig(bs, BNET_EOD);
-             break;
-          }
+              bnet_fsend(bs, illegal_cmd);
+              bnet_sig(bs, BNET_EOD);
+              break;
+           }
            Dmsg1(200, "Do command: %s\n", cmds[i].cmd);
-          if (!cmds[i].func(jcr)) { /* do command */
-             quit = true; /* error, get out */
+           if (!cmds[i].func(jcr)) { /* do command */
+              quit = true; /* error, get out */
               Dmsg1(190, "Command %s requsts quit\n", cmds[i].cmd);
-          }
-          found = true;             /* indicate command found */
-          break;
-       }
+           }
+           found = true;             /* indicate command found */
+           break;
+        }
       }
-      if (!found) {                  /* command not found */
-       bnet_fsend(bs, derrmsg);
-       break;
+      if (!found) {                   /* command not found */
+        bnet_fsend(bs, derrmsg);
+        break;
       }
    }
 bail_out:
-   dequeue_messages(jcr);            /* send any queued messages */
+   dequeue_messages(jcr);             /* send any queued messages */
    bnet_sig(bs, BNET_TERMINATE);
    free_jcr(jcr);
    return NULL;
@@ -259,23 +259,23 @@ static bool cancel_cmd(JCR *cjcr)
       if (!(jcr=get_jcr_by_full_name(Job))) {
          bnet_fsend(dir, _("3992 Job %s not found.\n"), Job);
       } else {
-        P(jcr->mutex);
-        oldStatus = jcr->JobStatus;
-        set_jcr_job_status(jcr, JS_Canceled);
-        if (!jcr->authenticated && oldStatus == JS_WaitFD) {
-           pthread_cond_signal(&jcr->job_start_wait); /* wake waiting thread */
-        }
-        V(jcr->mutex);
-        if (jcr->file_bsock) {
-           bnet_sig(jcr->file_bsock, BNET_TERMINATE);
-        }
-        /* If thread waiting on mount, wake him */
-        if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->waiting_for_mount()) {
-            pthread_cond_signal(&jcr->dcr->dev->wait_next_vol);
-            pthread_cond_broadcast(&wait_device_release);
-        }
+         P(jcr->mutex);
+         oldStatus = jcr->JobStatus;
+         set_jcr_job_status(jcr, JS_Canceled);
+         if (!jcr->authenticated && oldStatus == JS_WaitFD) {
+            pthread_cond_signal(&jcr->job_start_wait); /* wake waiting thread */
+         }
+         V(jcr->mutex);
+         if (jcr->file_bsock) {
+            bnet_sig(jcr->file_bsock, BNET_TERMINATE);
+         }
+         /* If thread waiting on mount, wake him */
+         if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->waiting_for_mount()) {
+             pthread_cond_signal(&jcr->dcr->dev->wait_next_vol);
+             pthread_cond_broadcast(&wait_device_release);
+         }
          bnet_fsend(dir, _("3000 Job %s marked to be canceled.\n"), jcr->Job);
-        free_jcr(jcr);
+         free_jcr(jcr);
       }
    } else {
       bnet_fsend(dir, _("3993 Error scanning cancel command.\n"));
@@ -313,14 +313,14 @@ static bool do_label(JCR *jcr, int relabel)
    mtype = get_memory(dir->msglen+1);
    if (relabel) {
       if (sscanf(dir->msg, "relabel %127s OldName=%127s NewName=%127s PoolName=%127s MediaType=%127s Slot=%d",
-         dev_name.c_str(), oldname, newname, poolname, mtype, &slot) == 6) {
-        ok = true;
+          dev_name.c_str(), oldname, newname, poolname, mtype, &slot) == 6) {
+         ok = true;
       }
    } else {
       *oldname = 0;
       if (sscanf(dir->msg, "label %127s VolumeName=%127s PoolName=%127s MediaType=%127s Slot=%d",
-         dev_name.c_str(), newname, poolname, mtype, &slot) == 5) {
-        ok = true;
+          dev_name.c_str(), newname, poolname, mtype, &slot) == 5) {
+         ok = true;
       }
    }
    if (ok) {
@@ -330,20 +330,20 @@ static bool do_label(JCR *jcr, int relabel)
       unbash_spaces(mtype);
       dev = find_device(jcr, dev_name);
       if (dev) {
-        /******FIXME**** compare MediaTypes */
-        P(dev->mutex);               /* Use P to avoid indefinite block */
-        if (!dev->is_open()) {
-           label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
-           force_close_dev(dev);
+         /******FIXME**** compare MediaTypes */
+         P(dev->mutex);               /* Use P to avoid indefinite block */
+         if (!dev->is_open()) {
+            label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
+            force_close_dev(dev);
          /* Under certain "safe" conditions, we can steal the lock */
-        } else if (dev->can_steal_lock()) {
-           label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
-        } else if (dev->is_busy()) {
-           send_dir_busy_message(dir, dev);
-        } else {                     /* device not being used */
-           label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
-        }
-        V(dev->mutex);
+         } else if (dev->can_steal_lock()) {
+            label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
+         } else if (dev->is_busy()) {
+            send_dir_busy_message(dir, dev);
+         } else {                     /* device not being used */
+            label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
+         }
+         V(dev->mutex);
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), dev_name.c_str());
       }
@@ -367,8 +367,8 @@ static bool do_label(JCR *jcr, int relabel)
  *  Enter with the mutex set
  */
 static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
-                              char *newname, char *poolname,
-                              int slot, int relabel)
+                               char *newname, char *poolname,
+                               int slot, int relabel)
 {
    BSOCK *dir = jcr->dir_bsock;
    bsteal_lock_t hold;
@@ -379,7 +379,7 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
    steal_device_lock(dev, &hold, BST_WRITING_LABEL);
 
    if (!try_autoload_device(jcr, slot, newname)) {
-      goto bail_out;                 /* error */
+      goto bail_out;                  /* error */
    }
 
    /* See what we have for a Volume */
@@ -395,31 +395,31 @@ static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
    case VOL_LABEL_ERROR:
    case VOL_OK:
       if (!relabel) {
-        bnet_fsend(dir, _(
+         bnet_fsend(dir, _(
             "3920 Cannot label Volume because it is already labeled: \"%s\"\n"),
-            dev->VolHdr.VolName);
-        break;
+             dev->VolHdr.VolName);
+         break;
       }
       /* Relabel request. If oldname matches, continue */
       if (strcmp(oldname, dev->VolHdr.VolName) != 0) {
          bnet_fsend(dir, _("3921 Wrong volume mounted.\n"));
-        break;
+         break;
       }
       if (dev->label_type != B_BACULA_LABEL) {
          bnet_fsend(dir, _("3922 Cannot relabel an ANSI/IBM labeled Volume.\n"));
-        break;
+         break;
       }
       /* Fall through wanted! */
    case VOL_IO_ERROR:
    case VOL_NO_LABEL:
       if (!write_new_volume_label_to_dev(dcr, newname, poolname)) {
          bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), strerror_dev(dev));
-        break;
+         break;
       }
       bstrncpy(dcr->VolumeName, newname, sizeof(dcr->VolumeName));
       /* The following 3000 OK label. string is scanned in ua_label.c */
       bnet_fsend(dir, "3000 OK label. Volume=%s Device=%s\n",
-        newname, dev->print_name());
+         newname, dev->print_name());
       break;
    case VOL_NO_MEDIA:
       bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), strerror_dev(dev));
@@ -452,7 +452,7 @@ static bool read_label(DCR *dcr)
    steal_device_lock(dev, &hold, BST_DOING_ACQUIRE);
 
    dcr->VolumeName[0] = 0;
-   dev->clear_labeled();             /* force read of label */
+   dev->clear_labeled();              /* force read of label */
    switch (read_dev_volume_label(dcr)) {
    case VOL_OK:
       bnet_fsend(dir, _("3001 Mounted Volume: %s\n"), dev->VolHdr.VolName);
@@ -460,7 +460,7 @@ static bool read_label(DCR *dcr)
       break;
    default:
       bnet_fsend(dir, _("3902 Cannot mount Volume on Storage Device %s because:\n%s"),
-        dev->print_name(), jcr->errmsg);
+         dev->print_name(), jcr->errmsg);
       ok = false;
       break;
    }
@@ -479,44 +479,44 @@ static DEVICE *find_device(JCR *jcr, POOL_MEM &devname)
    foreach_res(device, R_DEVICE) {
       /* Find resource, and make sure we were able to open it */
       if (fnmatch(device->hdr.name, devname.c_str(), 0) == 0) {
-        if (!device->dev) {
-           device->dev = init_dev(jcr, NULL, device);
-        }
-        if (!device->dev) {
+         if (!device->dev) {
+            device->dev = init_dev(jcr, NULL, device);
+         }
+         if (!device->dev) {
             Jmsg(jcr, M_WARNING, 0, _("\n"
                "     Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
-                devname.c_str());
-           continue;
-        }
+                 devname.c_str());
+            continue;
+         }
          Dmsg1(20, "Found device %s\n", device->hdr.name);
-        found = true;
-        break;
+         found = true;
+         break;
       }
    }
    foreach_res(changer, R_AUTOCHANGER) {
       /* Find resource, and make sure we were able to open it */
       if (fnmatch(devname.c_str(), changer->hdr.name, 0) == 0) {
-        /* Try each device in this AutoChanger */
-        foreach_alist(device, changer->device) {
+         /* Try each device in this AutoChanger */
+         foreach_alist(device, changer->device) {
             Dmsg1(100, "Try changer device %s\n", device->hdr.name);
-           if (!device->dev) {
-              device->dev = init_dev(jcr, NULL, device);
-           }
-           if (!device->dev) {
+            if (!device->dev) {
+               device->dev = init_dev(jcr, NULL, device);
+            }
+            if (!device->dev) {
                Dmsg1(100, "Device %s could not be opened. Skipped\n", devname.c_str());
                Jmsg(jcr, M_WARNING, 0, _("\n"
                   "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
-                   device->hdr.name, devname.c_str());
-              continue;
-           }
-           if (!device->dev->autoselect) {
-              continue;              /* device is not available */
-           }
+                    device->hdr.name, devname.c_str());
+               continue;
+            }
+            if (!device->dev->autoselect) {
+               continue;              /* device is not available */
+            }
             Dmsg1(20, "Found changer device %s\n", device->hdr.name);
-           found = true;
-           break;
-        }
-        break;                    /* we found it but could not open a device */
+            found = true;
+            break;
+         }
+         break;                    /* we found it but could not open a device */
       }
    }
 
@@ -545,96 +545,96 @@ static bool mount_cmd(JCR *jcr)
       dev = find_device(jcr, devname);
       dcr = jcr->dcr;
       if (dev) {
-        P(dev->mutex);               /* Use P to avoid indefinite block */
-        switch (dev->dev_blocked) {         /* device blocked? */
-        case BST_WAITING_FOR_SYSOP:
-           /* Someone is waiting, wake him */
+         P(dev->mutex);               /* Use P to avoid indefinite block */
+         switch (dev->dev_blocked) {         /* device blocked? */
+         case BST_WAITING_FOR_SYSOP:
+            /* Someone is waiting, wake him */
             Dmsg0(100, "Waiting for mount. Attempting to wake thread\n");
-           dev->dev_blocked = BST_MOUNT;
+            dev->dev_blocked = BST_MOUNT;
             bnet_fsend(dir, "3001 OK mount. Device=%s\n", 
-              dev->print_name());
-           pthread_cond_signal(&dev->wait_next_vol);
-           pthread_cond_broadcast(&wait_device_release);
-           break;
-
-        /* In both of these two cases, we (the user) unmounted the Volume */
-        case BST_UNMOUNTED_WAITING_FOR_SYSOP:
-        case BST_UNMOUNTED:
-           /* We freed the device, so reopen it and wake any waiting threads */
-           if (open_dev(dev, NULL, OPEN_READ_WRITE) < 0) {
+               dev->print_name());
+            pthread_cond_broadcast(&dev->wait_next_vol);
+            pthread_cond_broadcast(&wait_device_release);
+            break;
+
+         /* In both of these two cases, we (the user) unmounted the Volume */
+         case BST_UNMOUNTED_WAITING_FOR_SYSOP:
+         case BST_UNMOUNTED:
+            /* We freed the device, so reopen it and wake any waiting threads */
+            if (open_dev(dev, NULL, OPEN_READ_WRITE) < 0) {
                bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
-                 strerror_dev(dev));
-              break;
-           }
-           read_dev_volume_label(dcr);
-           if (dev->dev_blocked == BST_UNMOUNTED) {
-              /* We blocked the device, so unblock it */
+                  strerror_dev(dev));
+               break;
+            }
+            read_dev_volume_label(dcr);
+            if (dev->dev_blocked == BST_UNMOUNTED) {
+               /* We blocked the device, so unblock it */
                Dmsg0(100, "Unmounted. Unblocking device\n");
-              read_label(dcr);       /* this should not be necessary */
-              unblock_device(dev);
-           } else {
+               read_label(dcr);       /* this should not be necessary */
+               unblock_device(dev);
+            } else {
                Dmsg0(100, "Unmounted waiting for mount. Attempting to wake thread\n");
-              dev->dev_blocked = BST_MOUNT;
-           }
-           if (dev->is_labeled()) {
+               dev->dev_blocked = BST_MOUNT;
+            }
+            if (dev->is_labeled()) {
                bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"),
-                 dev->print_name(), dev->VolHdr.VolName);
-           } else {
+                  dev->print_name(), dev->VolHdr.VolName);
+            } else {
                bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
                                  "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
-                         dev->print_name());
-           }
-           pthread_cond_signal(&dev->wait_next_vol);
-           pthread_cond_broadcast(&wait_device_release);
-           break;
+                          dev->print_name());
+            }
+            pthread_cond_broadcast(&dev->wait_next_vol);
+            pthread_cond_broadcast(&wait_device_release);
+            break;
 
-        case BST_DOING_ACQUIRE:
+         case BST_DOING_ACQUIRE:
             bnet_fsend(dir, _("3001 Device %s is mounted; doing acquire.\n"),
-                      dev->print_name());
-           break;
+                       dev->print_name());
+            break;
 
-        case BST_WRITING_LABEL:
+         case BST_WRITING_LABEL:
             bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), 
-              dev->print_name());
-           break;
+               dev->print_name());
+            break;
 
-        case BST_NOT_BLOCKED:
-           if (dev->is_open()) {
-              if (dev->is_labeled()) {
+         case BST_NOT_BLOCKED:
+            if (dev->is_open()) {
+               if (dev->is_labeled()) {
                   bnet_fsend(dir, _("3001 Device %s is mounted with Volume \"%s\"\n"),
-                    dev->print_name(), dev->VolHdr.VolName);
-              } else {
+                     dev->print_name(), dev->VolHdr.VolName);
+               } else {
                   bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
                                  "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
-                            dev->print_name());
-              }
-           } else {
-              if (!dev_is_tape(dev)) {
+                             dev->print_name());
+               }
+            } else {
+               if (!dev_is_tape(dev)) {
                   bnet_fsend(dir, _("3906 cannot mount non-tape.\n"));
-                 break;
-              }
-              if (open_dev(dev, NULL, OPEN_READ_WRITE) < 0) {
+                  break;
+               }
+               if (open_dev(dev, NULL, OPEN_READ_WRITE) < 0) {
                   bnet_fsend(dir, _("3901 open device failed: ERR=%s\n"),
-                    strerror_dev(dev));
-                 break;
-              }
-              read_label(dcr);
-              if (dev->is_labeled()) {
+                     strerror_dev(dev));
+                  break;
+               }
+               read_label(dcr);
+               if (dev->is_labeled()) {
                   bnet_fsend(dir, _("3001 Device %s is already mounted with Volume \"%s\"\n"),
-                    dev->print_name(), dev->VolHdr.VolName);
-              } else {
+                     dev->print_name(), dev->VolHdr.VolName);
+               } else {
                   bnet_fsend(dir, _("3905 Device %s open but no Bacula volume is mounted.\n"
                                     "If this is not a blank tape, try unmounting and remounting the Volume.\n"),
-                            dev->print_name());
-              }
-           }
-           break;
+                             dev->print_name());
+               }
+            }
+            break;
 
-        default:
+         default:
             bnet_fsend(dir, _("3905 Bizarre wait state %d\n"), dev->dev_blocked);
-           break;
-        }
-        V(dev->mutex);
+            break;
+         }
+         V(dev->mutex);
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str());
       }
@@ -658,49 +658,49 @@ static bool unmount_cmd(JCR *jcr)
    if (sscanf(dir->msg, "unmount %127s", devname.c_str()) == 1) {
       dev = find_device(jcr, devname);
       if (dev) {
-        P(dev->mutex);               /* Use P to avoid indefinite block */
-        if (!dev->is_open()) {
+         P(dev->mutex);               /* Use P to avoid indefinite block */
+         if (!dev->is_open()) {
             Dmsg0(90, "Device already unmounted\n");
             bnet_fsend(dir, _("3901 Device %s is already unmounted.\n"), 
-              dev->print_name());
+               dev->print_name());
 
-        } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) {
+         } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP) {
             Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
-              dev->dev_blocked);
-           open_dev(dev, NULL, 0);     /* fake open for close */
-           offline_or_rewind_dev(dev);
-           force_close_dev(dev);
-           dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP;
+               dev->dev_blocked);
+            open_dev(dev, NULL, 0);     /* fake open for close */
+            offline_or_rewind_dev(dev);
+            force_close_dev(dev);
+            dev->dev_blocked = BST_UNMOUNTED_WAITING_FOR_SYSOP;
             bnet_fsend(dir, _("3001 Device %s unmounted.\n"), 
-              dev->print_name());
+               dev->print_name());
 
-        } else if (dev->dev_blocked == BST_DOING_ACQUIRE) {
+         } else if (dev->dev_blocked == BST_DOING_ACQUIRE) {
             bnet_fsend(dir, _("3902 Device %s is busy in acquire.\n"), 
-              dev->print_name());
+               dev->print_name());
 
-        } else if (dev->dev_blocked == BST_WRITING_LABEL) {
+         } else if (dev->dev_blocked == BST_WRITING_LABEL) {
             bnet_fsend(dir, _("3903 Device %s is being labeled.\n"), 
-              dev->print_name());
+               dev->print_name());
 
-        } else if (dev->is_busy()) {
-           send_dir_busy_message(dir, dev);
-        } else {                     /* device not being used */
+         } else if (dev->is_busy()) {
+            send_dir_busy_message(dir, dev);
+         } else {                     /* device not being used */
             Dmsg0(90, "Device not in use, unmounting\n");
-           /* On FreeBSD, I am having ASSERT() failures in block_device()
-            * and I can only imagine that the thread id that we are
-            * leaving in no_wait_id is being re-used. So here,
-            * we simply do it by hand.  Gross, but a solution.
-            */
-           /*  block_device(dev, BST_UNMOUNTED); replace with 2 lines below */
-           dev->dev_blocked = BST_UNMOUNTED;
-           dev->no_wait_id = 0;
-           open_dev(dev, NULL, 0);     /* fake open for close */
-           offline_or_rewind_dev(dev);
-           force_close_dev(dev);
+            /* On FreeBSD, I am having ASSERT() failures in block_device()
+             * and I can only imagine that the thread id that we are
+             * leaving in no_wait_id is being re-used. So here,
+             * we simply do it by hand.  Gross, but a solution.
+             */
+            /*  block_device(dev, BST_UNMOUNTED); replace with 2 lines below */
+            dev->dev_blocked = BST_UNMOUNTED;
+            dev->no_wait_id = 0;
+            open_dev(dev, NULL, 0);     /* fake open for close */
+            offline_or_rewind_dev(dev);
+            force_close_dev(dev);
             bnet_fsend(dir, _("3002 Device %s unmounted.\n"), 
-              dev->print_name());
-        }
-        V(dev->mutex);
+               dev->print_name());
+         }
+         V(dev->mutex);
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str());
       }
@@ -729,36 +729,36 @@ static bool release_cmd(JCR *jcr)
    if (sscanf(dir->msg, "release %127s", devname.c_str()) == 1) {
       dev = find_device(jcr, devname);
       if (dev) {
-        P(dev->mutex);               /* Use P to avoid indefinite block */
-        if (!dev->is_open()) {
+         P(dev->mutex);               /* Use P to avoid indefinite block */
+         if (!dev->is_open()) {
             Dmsg0(90, "Device already released\n");
             bnet_fsend(dir, _("3911 Device %s already released.\n"), 
-              dev->print_name());
+               dev->print_name());
 
-        } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
-                   dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP) {
+         } else if (dev->dev_blocked == BST_WAITING_FOR_SYSOP ||
+                    dev->dev_blocked == BST_UNMOUNTED_WAITING_FOR_SYSOP) {
             Dmsg2(90, "%d waiter dev_block=%d. doing unmount\n", dev->num_waiting,
-              dev->dev_blocked);
+               dev->dev_blocked);
             bnet_fsend(dir, _("3912 Device %s waiting for mount.\n"), 
-              dev->print_name());
+               dev->print_name());
 
-        } else if (dev->dev_blocked == BST_DOING_ACQUIRE) {
+         } else if (dev->dev_blocked == BST_DOING_ACQUIRE) {
             bnet_fsend(dir, _("3913 Device %s is busy in acquire.\n"), 
-              dev->print_name());
+               dev->print_name());
 
-        } else if (dev->dev_blocked == BST_WRITING_LABEL) {
+         } else if (dev->dev_blocked == BST_WRITING_LABEL) {
             bnet_fsend(dir, _("3914 Device %s is being labeled.\n"), 
-              dev->print_name());
+               dev->print_name());
 
-        } else if (dev->is_busy()) {
-           send_dir_busy_message(dir, dev);
-        } else {                     /* device not being used */
+         } else if (dev->is_busy()) {
+            send_dir_busy_message(dir, dev);
+         } else {                     /* device not being used */
             Dmsg0(90, "Device not in use, unmounting\n");
-           release_volume(jcr->dcr);
+            release_volume(jcr->dcr);
             bnet_fsend(dir, _("3012 Device %s released.\n"), 
-              dev->print_name());
-        }
-        V(dev->mutex);
+               dev->print_name());
+         }
+         V(dev->mutex);
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str());
       }
@@ -796,28 +796,28 @@ static bool autochanger_cmd(JCR *jcr)
       dev = find_device(jcr, devname);
       dcr = jcr->dcr;
       if (dev) {
-        P(dev->mutex);               /* Use P to avoid indefinite block */
-        if (!dev_is_tape(dev)) {
+         P(dev->mutex);               /* Use P to avoid indefinite block */
+         if (!dev_is_tape(dev)) {
             bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), 
-              dev->print_name());
-        } else if (!dev->is_open()) {
-           autochanger_cmd(dcr, dir, cmd);
+               dev->print_name());
+         } else if (!dev->is_open()) {
+            autochanger_cmd(dcr, dir, cmd);
          /* Under certain "safe" conditions, we can steal the lock */
-        } else if (dev->can_steal_lock()) {
-           autochanger_cmd(dcr, dir, cmd);
-        } else if (dev->is_busy()) {
-           send_dir_busy_message(dir, dev);
-        } else {                     /* device not being used */
-           autochanger_cmd(dcr, dir, cmd);
-        }
-        V(dev->mutex);
+         } else if (dev->can_steal_lock()) {
+            autochanger_cmd(dcr, dir, cmd);
+         } else if (dev->is_busy()) {
+            send_dir_busy_message(dir, dev);
+         } else {                     /* device not being used */
+            autochanger_cmd(dcr, dir, cmd);
+         }
+         V(dev->mutex);
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str());
       }
    } else {  /* error on scanf */
       pm_strcpy(jcr->errmsg, dir->msg);
       bnet_fsend(dir, _("3908 Error scanning autocharger list/slots command: %s\n"),
-        jcr->errmsg);
+         jcr->errmsg);
    }
    bnet_sig(dir, BNET_EOD);
    return true;
@@ -836,19 +836,19 @@ static bool readlabel_cmd(JCR *jcr)
    if (sscanf(dir->msg, "readlabel %127s Slot=%d", devname.c_str(), &Slot) == 2) {
       dev = find_device(jcr, devname);
       if (dev) {
-        P(dev->mutex);               /* Use P to avoid indefinite block */
-        if (!dev->is_open()) {
-           read_volume_label(jcr, dev, Slot);
-           force_close_dev(dev);
+         P(dev->mutex);               /* Use P to avoid indefinite block */
+         if (!dev->is_open()) {
+            read_volume_label(jcr, dev, Slot);
+            force_close_dev(dev);
          /* Under certain "safe" conditions, we can steal the lock */
-        } else if (dev->can_steal_lock()) {
-           read_volume_label(jcr, dev, Slot);
-        } else if (dev->is_busy()) {
-           send_dir_busy_message(dir, dev);
-        } else {                     /* device not being used */
-           read_volume_label(jcr, dev, Slot);
-        }
-        V(dev->mutex);
+         } else if (dev->can_steal_lock()) {
+            read_volume_label(jcr, dev, Slot);
+         } else if (dev->is_busy()) {
+            send_dir_busy_message(dir, dev);
+         } else {                     /* device not being used */
+            read_volume_label(jcr, dev, Slot);
+         }
+         V(dev->mutex);
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found\n"), devname.c_str());
       }
@@ -875,10 +875,10 @@ static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot)
    steal_device_lock(dev, &hold, BST_WRITING_LABEL);
 
    if (!try_autoload_device(jcr, Slot, "")) {
-      goto bail_out;                 /* error */
+      goto bail_out;                  /* error */
    }
 
-   dev->clear_labeled();             /* force read of label */
+   dev->clear_labeled();              /* force read of label */
    switch (read_dev_volume_label(dcr)) {
    case VOL_OK:
       /* DO NOT add quotes around the Volume name. It is scanned in the DIR */
@@ -887,7 +887,7 @@ static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot)
       break;
    default:
       bnet_fsend(dir, _("3902 Cannot mount Volume on Storage Device %s because:\n%s"),
-                dev->print_name(), jcr->errmsg);
+                 dev->print_name(), jcr->errmsg);
       break;
    }
 
@@ -913,8 +913,8 @@ static bool try_autoload_device(JCR *jcr, int slot, const char *VolName)
    for ( ; !dev->is_open(); ) {
       if (open_dev(dev, dcr->VolumeName, OPEN_READ_WRITE) < 0) {
          bnet_fsend(dir, _("3910 Unable to open device %s: ERR=%s\n"),
-           dev->print_name(), dev->strerror());
-        return false;
+            dev->print_name(), dev->strerror());
+         return false;
       }
    }
    return true;
@@ -924,9 +924,9 @@ static void send_dir_busy_message(BSOCK *dir, DEVICE *dev)
 {
    if (dev->can_read()) {
        bnet_fsend(dir, _("3911 Device %s is busy reading.\n"),
-                  dev->print_name());;
+                   dev->print_name());;
    } else {
        bnet_fsend(dir, _("3912 Device %s is busy with %d writer(s).\n"),
-         dev->print_name(), dev->num_writers);
+          dev->print_name(), dev->num_writers);
    }
 }
index 495ecefa89592228ff909f000002578d201cd01d..47a7ba2bb989dda050a278d203fc564cc9aedbfd 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *
  *   dvd.c  -- Routines specific to DVD devices (and
- *            possibly other removable hard media). 
+ *             possibly other removable hard media). 
  *
  *    Nicolas Boichat, MMV
  *
@@ -38,7 +38,7 @@ void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name);
 /* Forward referenced functions */
 static char *edit_device_codes_dev(DEVICE *dev, char *omsg, const char *imsg);
 static int do_mount_dev(DEVICE* dev, int mount, int dotimeout);
-static int write_part(DEVICE *dev);
+static int dvd_write_part(DEVICE *dev);
 
 
 /* 
@@ -49,17 +49,17 @@ void get_filename(DEVICE *dev, char *VolName, POOL_MEM& archive_name)
    char partnumber[20];
    
    if (dev->is_dvd()) {
-        /* If we try to open the last part, just open it from disk, 
-        * otherwise, open it from the spooling directory */
+         /* If we try to open the last part, just open it from disk, 
+         * otherwise, open it from the spooling directory */
       if (dev->part < dev->num_parts) {
-        pm_strcpy(archive_name, dev->device->mount_point);
+         pm_strcpy(archive_name, dev->device->mount_point);
       } else {
-        /* Use the working directory if spool directory is not defined */
-        if (dev->device->spool_directory) {
-           pm_strcpy(archive_name, dev->device->spool_directory);
-        } else {
-           pm_strcpy(archive_name, working_directory);
-        }
+         /* Use the working directory if spool directory is not defined */
+         if (dev->device->spool_directory) {
+            pm_strcpy(archive_name, dev->device->spool_directory);
+         } else {
+            pm_strcpy(archive_name, working_directory);
+         }
       }
    } else {
       pm_strcpy(archive_name, dev->dev_name);
@@ -88,7 +88,7 @@ int mount_dev(DEVICE* dev, int timeout)
       return 0;
    } else if (dev_cap(dev, CAP_REQMOUNT)) {
       return do_mount_dev(dev, 1, timeout);
-   }      
+   }       
    return 0;
 }
 
@@ -135,14 +135,14 @@ static int do_mount_dev(DEVICE* dev, int mount, int dotimeout) {
    while ((status = run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results)) != 0) {
       if (--timeout > 0) {
          Dmsg2(40, "Device %s cannot be (un)mounted. Retrying... ERR=%s\n", dev->dev_name, results);
-        /* Sometimes the device cannot be mounted because it is already mounted.
-         * Try to unmount it, then remount it */
-        if (mount) {
+         /* Sometimes the device cannot be mounted because it is already mounted.
+          * Try to unmount it, then remount it */
+         if (mount) {
             Dmsg1(40, "Trying to unmount the device %s...\n", dev->dev_name);
-           do_mount_dev(dev, 0, 0);
-        }
-        bmicrosleep(1, 0);
-        continue;
+            do_mount_dev(dev, 0, 0);
+         }
+         bmicrosleep(1, 0);
+         continue;
       }
       free_pool_memory(results);
       Dmsg2(40, "Device %s cannot be mounted. ERR=%s\n", dev->dev_name, results);
@@ -207,11 +207,11 @@ int open_guess_name_dev(DEVICE *dev)
       /* If the device cannot be mounted, check if it is writable */
       if (dev->free_space_errno >= 0) {
          Dmsg1(100, "open_guess_name_dev: device cannot be mounted, but it seems to be writable, returning 0. dev=%s\n", dev->dev_name);
-        return 0;
+         return 0;
       } else {
          Dmsg1(100, "open_guess_name_dev: device cannot be mounted, and is not writable, returning 0. dev=%s\n", dev->dev_name);
-        /* read_dev_volume_label_guess must now check dev->free_space_errno to understand that the media is not writable. */
-        return 0;
+         /* read_dev_volume_label_guess must now check dev->free_space_errno to understand that the media is not writable. */
+         return 0;
       }
    }
       
@@ -230,16 +230,16 @@ int open_guess_name_dev(DEVICE *dev)
    entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 100);
    while (1) {
       if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
-        dev->dev_errno = ENOENT;
+         dev->dev_errno = ENOENT;
          Dmsg2(29, "open_guess_name_dev: failed to find suitable file in dir %s (dev=%s)\n", dev->device->mount_point, dev->dev_name);
-        closedir(dp);
-        return -1;
+         closedir(dp);
+         return -1;
       }
       
       ASSERT(name_max+1 > (int)sizeof(struct dirent) + (int)NAMELEN(entry));
       
       if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
-        continue;
+         continue;
       }
       
       pm_strcpy(guessedname, dev->device->mount_point);
@@ -249,16 +249,16 @@ int open_guess_name_dev(DEVICE *dev)
       pm_strcat(guessedname, entry->d_name);
       
       if (stat(guessedname.c_str(), &statp) < 0) {
-        berrno be;
+         berrno be;
          Dmsg3(29, "open_guess_name_dev: failed to stat %s (dev=%s), ERR=%s\n",
-              guessedname.c_str(), dev->dev_name, be.strerror());
-        continue;
+               guessedname.c_str(), dev->dev_name, be.strerror());
+         continue;
       }
       
       if (!S_ISREG(statp.st_mode) || (statp.st_size < 500)) {
          Dmsg2(100, "open_guess_name_dev: %s is not a regular file, or less than 500 bytes (dev=%s)\n", 
-              guessedname.c_str(), dev->dev_name);
-        continue;
+               guessedname.c_str(), dev->dev_name);
+         continue;
       }
       
       /* Ok, we found a good file, remove the part extension if possible. */
@@ -266,25 +266,25 @@ int open_guess_name_dev(DEVICE *dev)
          if ((guessedname.c_str()[index] == '/') || 
              (guessedname.c_str()[index] < '0') || 
              (guessedname.c_str()[index] > '9')) {
-           break;
-        }
+            break;
+         }
          if (guessedname.c_str()[index] == '.') {
             guessedname.c_str()[index] = '\0';
-           break;
-        }
+            break;
+         }
       }
       
       if ((stat(guessedname.c_str(), &statp) < 0) || (statp.st_size < 500)) {
-        /* The file with extension truncated does not exists or is too small, so use it with its extension. */
-        berrno be;
+         /* The file with extension truncated does not exists or is too small, so use it with its extension. */
+         berrno be;
          Dmsg3(100, "open_guess_name_dev: failed to stat %s (dev=%s), using the file with its extension, ERR=%s\n", 
-              guessedname.c_str(), dev->dev_name, be.strerror());
-        pm_strcpy(guessedname, dev->device->mount_point);
+               guessedname.c_str(), dev->dev_name, be.strerror());
+         pm_strcpy(guessedname, dev->device->mount_point);
          if (guessedname.c_str()[strlen(guessedname.c_str())-1] != '/') {
             pm_strcat(guessedname, "/");
-        }
-        pm_strcat(guessedname, entry->d_name);
-        continue;
+         }
+         pm_strcat(guessedname, entry->d_name);
+         continue;
       }
       break;
    }
@@ -299,12 +299,12 @@ int open_guess_name_dev(DEVICE *dev)
       berrno be;
       dev->dev_errno = errno;
       Dmsg3(29, "open_guess_name_dev: failed to open %s (dev=%s), ERR=%s\n", 
-           guessedname.c_str(), dev->dev_name, be.strerror());
+            guessedname.c_str(), dev->dev_name, be.strerror());
       if (open_first_part(dev) < 0) {
-        berrno be;
-        dev->dev_errno = errno;
+         berrno be;
+         dev->dev_errno = errno;
          Mmsg1(&dev->errmsg, _("Could not open_first_part, ERR=%s\n"), be.strerror());
-        Emsg0(M_FATAL, 0, dev->errmsg);         
+         Emsg0(M_FATAL, 0, dev->errmsg);         
       }
       return -1;
    }
@@ -351,13 +351,13 @@ void update_free_space_dev(DEVICE* dev)
       char ed1[50];
       if (run_program_full_output(ocmd.c_str(), dev->max_open_wait/2, results) == 0) {
          Dmsg1(100, "Free space program run : %s\n", results);
-        free = str_to_int64(results);
-        if (free >= 0) {
-           dev->free_space = free;
-           dev->free_space_errno = 1;
+         free = str_to_int64(results);
+         if (free >= 0) {
+            dev->free_space = free;
+            dev->free_space_errno = 1;
             Mmsg0(dev->errmsg, "");
-           break;
-        }
+            break;
+         }
       }
       dev->free_space = 0;
       dev->free_space_errno = -EPIPE;
@@ -366,17 +366,17 @@ void update_free_space_dev(DEVICE* dev)
       if (--timeout > 0) {
          Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
             "free_space_errno=%d ERR=%s\n", dev->dev_name, 
-              edit_uint64(dev->free_space, ed1), dev->free_space_errno, 
-              dev->errmsg);
-        bmicrosleep(1, 0);
-        continue;
+               edit_uint64(dev->free_space, ed1), dev->free_space_errno, 
+               dev->errmsg);
+         bmicrosleep(1, 0);
+         continue;
       }
 
       dev->dev_errno = -dev->free_space_errno;
       Dmsg4(40, "Cannot get free space on device %s. free_space=%s, "
          "free_space_errno=%d ERR=%s\n",
-           dev->dev_name, edit_uint64(dev->free_space, ed1),
-           dev->free_space_errno, dev->errmsg);
+            dev->dev_name, edit_uint64(dev->free_space, ed1),
+            dev->free_space_errno, dev->errmsg);
       break;
    }
    
@@ -385,12 +385,12 @@ void update_free_space_dev(DEVICE* dev)
    return;
 }
 
-static int write_part(DEVICE *dev) 
+static int dvd_write_part(DEVICE *dev) 
 {
-   Dmsg1(29, "write_part: device is %s\n", dev->dev_name);
+   Dmsg1(29, "dvd_write_part: device is %s\n", dev->dev_name);
    
    if (unmount_dev(dev, 1) < 0) {
-      Dmsg0(29, "write_part: unable to unmount the device\n");
+      Dmsg0(29, "dvd_write_part: unable to unmount the device\n");
    }
    
    POOL_MEM ocmd(PM_FNAME);
@@ -409,7 +409,7 @@ static int write_part(DEVICE *dev)
     */
    timeout = dev->max_open_wait + (dev->max_part_size/(1350*1024/2));
    
-   Dmsg2(29, "write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
+   Dmsg2(29, "dvd_write_part: cmd=%s timeout=%d\n", ocmd.c_str(), timeout);
       
    status = run_program_full_output(ocmd.c_str(), timeout, results);
    if (status != 0) {
@@ -419,7 +419,7 @@ static int write_part(DEVICE *dev)
       return -1;
    }
    else {
-      Dmsg1(29, "write_part: command output=%s\n", results);
+      Dmsg1(29, "dvd_write_part: command output=%s\n", results);
       POOL_MEM archive_name(PM_FNAME);
       get_filename(dev, dev->VolCatInfo.VolCatName, archive_name);
       unlink(archive_name.c_str());
@@ -454,8 +454,8 @@ int open_next_part(DEVICE *dev) {
    dev->state &= ~ST_OPENED;
    
    if (dev->is_dvd() && (dev->part == dev->num_parts) && dev->can_append()) {
-      if (write_part(dev) < 0) {
-        return -1;
+      if (dvd_write_part(dev) < 0) {
+         return -1;
       }
    }
      
@@ -476,25 +476,25 @@ int open_next_part(DEVICE *dev) {
       /* Check if the next part exists. */
       if ((stat(archive_name.c_str(), &buf) == 0) || (errno != ENOENT)) {
          Dmsg1(29, "open_next_part %s is in the way, moving it away...\n", archive_name.c_str());
-        pm_strcpy(archive_bkp_name, archive_name.c_str());
+         pm_strcpy(archive_bkp_name, archive_name.c_str());
          pm_strcat(archive_bkp_name, ".bak");
-        unlink(archive_bkp_name.c_str()); 
-        
-        /* First try to rename it */
-        if (rename(archive_name.c_str(), archive_bkp_name.c_str()) < 0) {
-           berrno be;
+         unlink(archive_bkp_name.c_str()); 
+         
+         /* First try to rename it */
+         if (rename(archive_name.c_str(), archive_bkp_name.c_str()) < 0) {
+            berrno be;
             Dmsg3(29, "open_next_part can't rename %s to %s, ERR=%s\n", 
-                 archive_name.c_str(), archive_bkp_name.c_str(), be.strerror());
-           /* Then try to unlink it */
-           if (unlink(archive_name.c_str()) < 0) {
-              berrno be;
-              dev->dev_errno = errno;
+                  archive_name.c_str(), archive_bkp_name.c_str(), be.strerror());
+            /* Then try to unlink it */
+            if (unlink(archive_name.c_str()) < 0) {
+               berrno be;
+               dev->dev_errno = errno;
                Mmsg2(&dev->errmsg, _("open_next_part can't unlink existing part %s, ERR=%s\n"), 
-                     archive_name.c_str(), be.strerror());
-              Emsg0(M_FATAL, 0, dev->errmsg);
-              return -1;
-           }
-        }
+                      archive_name.c_str(), be.strerror());
+               Emsg0(M_FATAL, 0, dev->errmsg);
+               return -1;
+            }
+         }
       }
    }
    
@@ -547,84 +547,84 @@ off_t lseek_dev(DEVICE *dev, off_t offset, int whence)
    case SEEK_SET:
       Dmsg1(100, "lseek_dev SEEK_SET called %d\n", offset);
       if ((uint64_t)offset >= dev->part_start) {
-        if ((uint64_t)(offset - dev->part_start) < dev->part_size) {
-           /* We are staying in the current part, just seek */
-           if ((pos = lseek(dev->fd, (off_t)(offset-dev->part_start), SEEK_SET)) < 0) {
-              return pos;   
-           } else {
-              return pos + dev->part_start;
-           }
-        } else {
-           /* Load next part, and start again */
-           if (open_next_part(dev) < 0) {
+         if ((uint64_t)(offset - dev->part_start) < dev->part_size) {
+            /* We are staying in the current part, just seek */
+            if ((pos = lseek(dev->fd, (off_t)(offset-dev->part_start), SEEK_SET)) < 0) {
+               return pos;   
+            } else {
+               return pos + dev->part_start;
+            }
+         } else {
+            /* Load next part, and start again */
+            if (open_next_part(dev) < 0) {
                Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
-              return -1;
-           }
-           return lseek_dev(dev, offset, SEEK_SET);
-        }
+               return -1;
+            }
+            return lseek_dev(dev, offset, SEEK_SET);
+         }
       } else {
-        /* pos < dev->part_start :
-         * We need to access a previous part, 
-         * so just load the first one, and seek again
-         * until the right one is loaded */
-        if (open_first_part(dev) < 0) {
+         /* pos < dev->part_start :
+          * We need to access a previous part, 
+          * so just load the first one, and seek again
+          * until the right one is loaded */
+         if (open_first_part(dev) < 0) {
             Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
-           return -1;
-        }
-        return lseek_dev(dev, offset, SEEK_SET);
+            return -1;
+         }
+         return lseek_dev(dev, offset, SEEK_SET);
       }
       break;
    case SEEK_CUR:
       Dmsg1(100, "lseek_dev SEEK_CUR called %d\n", offset);
       if ((pos = lseek(dev->fd, (off_t)0, SEEK_CUR)) < 0) {
-        return pos;   
+         return pos;   
       }
       pos += dev->part_start;
       if (offset == 0) {
-        return pos;
+         return pos;
       }
       else { /* Not used in Bacula, but should work */
-        return lseek_dev(dev, pos, SEEK_SET);
+         return lseek_dev(dev, pos, SEEK_SET);
       }
       break;
    case SEEK_END:
       Dmsg1(100, "lseek_dev SEEK_END called %d\n", offset);
       if (offset > 0) { /* Not used by bacula */
          Dmsg1(100, "lseek_dev SEEK_END called with an invalid offset %d\n", offset);
-        errno = EINVAL;
-        return -1;
+         errno = EINVAL;
+         return -1;
       }
       
       if (dev->part == dev->num_parts) { /* The right part is already loaded */
-        if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
-           return pos;   
-        } else {
-           return pos + dev->part_start;
-        }
+         if ((pos = lseek(dev->fd, (off_t)0, SEEK_END)) < 0) {
+            return pos;   
+         } else {
+            return pos + dev->part_start;
+         }
       } else {
-        /* Load the first part, then load the next until we reach the last one.
-         * This is the only way to be sure we compute the right file address. */
-        /* Save previous openmode, and open all but last part read-only (useful for DVDs) */
-        openmode = dev->openmode;
-        dev->openmode = OPEN_READ_ONLY;
-        
-        /* Works because num_parts > 0. */
-        if (open_first_part(dev) < 0) {
+         /* Load the first part, then load the next until we reach the last one.
+          * This is the only way to be sure we compute the right file address. */
+         /* Save previous openmode, and open all but last part read-only (useful for DVDs) */
+         openmode = dev->openmode;
+         dev->openmode = OPEN_READ_ONLY;
+         
+         /* Works because num_parts > 0. */
+         if (open_first_part(dev) < 0) {
             Dmsg0(100, "lseek_dev failed while trying to open the first part\n");
-           return -1;
-        }
-        while (dev->part < (dev->num_parts-1)) {
-           if (open_next_part(dev) < 0) {
+            return -1;
+         }
+         while (dev->part < (dev->num_parts-1)) {
+            if (open_next_part(dev) < 0) {
                Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
-              return -1;
-           }
-        }
-        dev->openmode = openmode;
-        if (open_next_part(dev) < 0) {
+               return -1;
+            }
+         }
+         dev->openmode = openmode;
+         if (open_next_part(dev) < 0) {
             Dmsg0(100, "lseek_dev failed while trying to open the next part\n");
-           return -1;
-        }
-        return lseek_dev(dev, 0, SEEK_END);
+            return -1;
+         }
+         return lseek_dev(dev, 0, SEEK_END);
       }
       break;
    default:
@@ -633,6 +633,37 @@ off_t lseek_dev(DEVICE *dev, off_t offset, int whence)
    }
 }
 
+bool dvd_close_job(DCR *dcr)
+{
+   DEVICE *dev = dcr->dev;
+   JCR *jcr = dcr->jcr;
+   bool ok = true;
+
+   /* If the device is a dvd and WritePartAfterJob
+    * is set to yes, open the next part, so, in case of a device
+    * that requires mount, it will be written to the device.
+    */
+   if (dev->is_dvd() && jcr->write_part_after_job && (dev->part_size > 0)) {
+      Dmsg0(100, "Writing last part because write_part_after_job is set.\n");
+      if (dev->part < dev->num_parts) {
+         Jmsg3(jcr, M_FATAL, 0, _("Error while writing, current part number is less than the total number of parts (%d/%d, device=%s)\n"),
+               dev->part, dev->num_parts, dev->print_name());
+         dev->dev_errno = EIO;
+         ok = false;
+      }
+      
+      if (ok && (open_next_part(dev) < 0)) {
+         Jmsg2(jcr, M_FATAL, 0, _("Unable to open device next part %s: ERR=%s\n"),
+               dev->print_name(), strerror_dev(dev));
+         dev->dev_errno = EIO;
+         ok = false;
+      }
+      
+      dev->VolCatInfo.VolCatParts = dev->num_parts;
+   }
+   return ok;
+}
+
 
 /*
  * Edit codes into (Un)MountCommand, Write(First)PartCommand
@@ -658,34 +689,34 @@ static char *edit_device_codes_dev(DEVICE* dev, char *omsg, const char *imsg)
    Dmsg1(800, "edit_device_codes: %s\n", imsg);
    for (p=imsg; *p; p++) {
       if (*p == '%') {
-        switch (*++p) {
+         switch (*++p) {
             case '%':
                str = "%";
-              break;
+               break;
             case 'n':
                bsnprintf(add, sizeof(add), "%d", dev->part);
-              str = add;
-              break;
+               str = add;
+               break;
             case 'a':
-              str = dev->dev_name;
-              break;
+               str = dev->dev_name;
+               break;
             case 'm':
-              str = dev->device->mount_point;
-              break;
+               str = dev->device->mount_point;
+               break;
             case 'v':
-              str = archive_name.c_str();
-              break;
-           default:
+               str = archive_name.c_str();
+               break;
+            default:
                add[0] = '%';
-              add[1] = *p;
-              add[2] = 0;
-              str = add;
-              break;
-        }
+               add[1] = *p;
+               add[2] = 0;
+               str = add;
+               break;
+         }
       } else {
-        add[0] = *p;
-        add[1] = 0;
-        str = add;
+         add[0] = *p;
+         add[1] = 0;
+         str = add;
       }
       Dmsg1(900, "add_str %s\n", str);
       pm_strcat(&omsg, (char *)str);
index 8d6ab2e414873300c9b74a39eb1704a8f1e4853e..4dc568b35e170ea1750cde4b6c66b92a2da8b74d 100644 (file)
@@ -42,7 +42,7 @@ static bool use_storage_cmd(JCR *jcr);
 static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s "
       "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s "
       "SpoolData=%d WritePartAfterJob=%d NewVol=%d\n";
-static char use_storage[]  = "use storage media_type=%127s "
+static char use_storage[]  = "use storage=%127s media_type=%127s "
    "pool_name=%127s pool_type=%127s append=%d\n";
 static char use_device[]  = "use device=%127s\n";
 //static char query_device[] = "query device=%127s";
@@ -261,9 +261,22 @@ void handle_filed_connection(BSOCK *fd, char *job_name)
  *    Ensure that the device exists and is opened, then store
  *     the media and pool info in the JCR.
  */
+class DIRSTORE {
+public:
+   alist *device;
+   char name[MAX_NAME_LENGTH];
+   char media_type[MAX_NAME_LENGTH];
+   char pool_name[MAX_NAME_LENGTH];
+   char pool_type[MAX_NAME_LENGTH];
+};
+
+class DIRDEVICE {
+   alist *device;
+};
+   
 static bool use_storage_cmd(JCR *jcr)
 {
-   POOL_MEM dev_name, media_type, pool_name, pool_type;
+   POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
    BSOCK *dir = jcr->dir_bsock;
    DEVRES *device;
    AUTOCHANGER *changer;
@@ -275,9 +288,11 @@ static bool use_storage_cmd(JCR *jcr)
     *  use_device for each device that it wants to use.
     */
    Dmsg1(100, "<dird: %s", dir->msg);
-   ok = sscanf(dir->msg, use_storage, media_type.c_str(),
-              pool_name.c_str(), pool_type.c_str(), &append) == 4;
+   ok = sscanf(dir->msg, use_storage, store_name.c_str(), 
+               media_type.c_str(), pool_name.c_str(), 
+              pool_type.c_str(), &append) == 5;
    if (ok) {
+      unbash_spaces(store_name);
       unbash_spaces(media_type);
       unbash_spaces(pool_name);
       unbash_spaces(pool_type);
index 4e64cc54c71a0a9122ebed9832ec16660ec182c5..784923a89909ccaa2eade74ca29fd20cc91d20e0 100644 (file)
@@ -127,6 +127,10 @@ uint32_t dev_block(DEVICE *dev);
 uint32_t dev_file(DEVICE *dev);
 bool     dev_is_tape(DEVICE *dev);
 
+/* From dvd.c */
+bool dvd_close_job(DCR *dcr);
+
+
 /* From device.c */
 bool     open_device(DCR *dcr);
 bool     first_open_device(DEVICE *dev);
index 818cfe9a704fa55911efe279953466d0edcb93cc..e6149b4a49361b566351c1d06dad6da5cb5ffbc6 100644 (file)
 void terminate_stored(int sig);
 static void check_config();
 
-extern "C" void *device_allocation(void *arg);
+extern "C" void *device_initialization(void *arg);
 
 #define CONFIG_FILE "bacula-sd.conf"  /* Default config file */
 
 /* Global variables exported */
 char OK_msg[]   = "3000 OK\n";
 char TERM_msg[] = "3999 Terminate\n";
-STORES *me = NULL;                   /* our Global resource */
-bool forge_on = false;               /* proceed inspite of I/O errors */
+STORES *me = NULL;                    /* our Global resource */
+bool forge_on = false;                /* proceed inspite of I/O errors */
 pthread_mutex_t device_release_mutex = PTHREAD_MUTEX_INITIALIZER;
 pthread_cond_t wait_device_release = PTHREAD_COND_INITIALIZER;
 
@@ -59,7 +59,7 @@ char *configfile;
 /* Global static variables */
 static int foreground = 0;
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-static workq_t dird_workq;           /* queue for processing connections */
+static workq_t dird_workq;            /* queue for processing connections */
 
 
 static void usage()
@@ -105,7 +105,7 @@ int main (int argc, char *argv[])
    /* Sanity checks */
    if (TAPE_BSIZE % B_DEV_BSIZE != 0 || TAPE_BSIZE / B_DEV_BSIZE == 0) {
       Emsg2(M_ABORT, 0, "Tape block size (%d) not multiple of system size (%d)\n",
-        TAPE_BSIZE, B_DEV_BSIZE);
+         TAPE_BSIZE, B_DEV_BSIZE);
    }
    if (TAPE_BSIZE != (1 << (ffs(TAPE_BSIZE)-1))) {
       Emsg1(M_ABORT, 0, "Tape block size (%d) is not a power of 2\n", TAPE_BSIZE);
@@ -114,51 +114,51 @@ int main (int argc, char *argv[])
    while ((ch = getopt(argc, argv, "c:d:fg:pstu:v?")) != -1) {
       switch (ch) {
       case 'c':                    /* configuration file */
-        if (configfile != NULL) {
-           free(configfile);
-        }
-        configfile = bstrdup(optarg);
-        break;
+         if (configfile != NULL) {
+            free(configfile);
+         }
+         configfile = bstrdup(optarg);
+         break;
 
       case 'd':                    /* debug level */
-        debug_level = atoi(optarg);
-        if (debug_level <= 0) {
-           debug_level = 1;
-        }
-        break;
+         debug_level = atoi(optarg);
+         if (debug_level <= 0) {
+            debug_level = 1;
+         }
+         break;
 
       case 'f':                    /* run in foreground */
-        foreground = TRUE;
-        break;
+         foreground = TRUE;
+         break;
 
       case 'g':                    /* set group id */
-        gid = optarg;
-        break;
+         gid = optarg;
+         break;
 
       case 'p':                    /* proceed in spite of I/O errors */
-        forge_on = true;
-        break;
+         forge_on = true;
+         break;
 
       case 's':                    /* no signals */
-        no_signals = TRUE;
-        break;
+         no_signals = TRUE;
+         break;
 
       case 't':
-        test_config = TRUE;
-        break;
+         test_config = TRUE;
+         break;
 
       case 'u':                    /* set uid */
-        uid = optarg;
-        break;
+         uid = optarg;
+         break;
 
       case 'v':                    /* verbose */
-        verbose++;
-        break;
+         verbose++;
+         break;
 
       case '?':
       default:
-        usage();
-        break;
+         usage();
+         break;
       }
    }
    argc -= optind;
@@ -166,7 +166,7 @@ int main (int argc, char *argv[])
 
    if (argc) {
       if (configfile != NULL) {
-        free(configfile);
+         free(configfile);
       }
       configfile = bstrdup(*argv);
       argc--;
@@ -191,8 +191,8 @@ int main (int argc, char *argv[])
    }
 
    if (!foreground) {
-      daemon_start();                /* become daemon */
-      init_stack_dump();             /* pick up new pid */
+      daemon_start();                 /* become daemon */
+      init_stack_dump();              /* pick up new pid */
    }
 
    create_pid_file(me->pid_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
@@ -217,13 +217,13 @@ int main (int argc, char *argv[])
     /*
      * Start the device allocation thread
      */
-   if (pthread_create(&thid, NULL, device_allocation, NULL) != 0) {
+   if (pthread_create(&thid, NULL, device_initialization, NULL) != 0) {
       Emsg1(M_ABORT, 0, _("Unable to create thread. ERR=%s\n"), strerror(errno));
    }
 
-   start_watchdog();                 /* start watchdog thread */
+   start_watchdog();                  /* start watchdog thread */
 
-   init_jcr_subsystem();             /* start JCR watchdogs etc. */
+   init_jcr_subsystem();              /* start JCR watchdogs etc. */
 
    /*
     * Sleep a bit to give device thread a chance to lock the resource
@@ -233,8 +233,8 @@ int main (int argc, char *argv[])
 
    /* Single server used for Director and File daemon */
    bnet_thread_server(me->sdaddrs, me->max_concurrent_jobs * 2 + 1,
-                     &dird_workq, handle_connection_request);
-   exit(1);                          /* to keep compiler quiet */
+                      &dird_workq, handle_connection_request);
+   exit(1);                           /* to keep compiler quiet */
 }
 
 /* Return a new Session Id */
@@ -259,39 +259,39 @@ static void check_config()
    if (!me) {
       UnlockRes();
       Jmsg1(NULL, M_ERROR_TERM, 0, _("No Storage resource defined in %s. Cannot continue.\n"),
-        configfile);
+         configfile);
    }
-   my_name_is(0, (char **)NULL, me->hdr.name);    /* Set our real name */
+   my_name_is(0, (char **)NULL, me->hdr.name);     /* Set our real name */
 
    if (GetNextRes(R_STORAGE, (RES *)me) != NULL) {
       UnlockRes();
       Jmsg1(NULL, M_ERROR_TERM, 0, _("Only one Storage resource permitted in %s\n"),
-        configfile);
+         configfile);
    }
    if (GetNextRes(R_DIRECTOR, NULL) == NULL) {
       UnlockRes();
       Jmsg1(NULL, M_ERROR_TERM, 0, _("No Director resource defined in %s. Cannot continue.\n"),
-        configfile);
+         configfile);
    }
    if (GetNextRes(R_DEVICE, NULL) == NULL){
       UnlockRes();
       Jmsg1(NULL, M_ERROR_TERM, 0, _("No Device resource defined in %s. Cannot continue.\n"),
-          configfile);
+           configfile);
    }
    if (!me->messages) {
       me->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
       if (!me->messages) {
          Jmsg1(NULL, M_ERROR_TERM, 0, _("No Messages resource defined in %s. Cannot continue.\n"),
-           configfile);
+            configfile);
       }
    }
-   close_msg(NULL);                  /* close temp message handler */
+   close_msg(NULL);                   /* close temp message handler */
    init_msg(NULL, me->messages);      /* open daemon message handler */
 
 
    if (!me->working_directory) {
       Jmsg1(NULL, M_ERROR_TERM, 0, _("No Working Directory defined in %s. Cannot continue.\n"),
-        configfile);
+         configfile);
    }
    set_working_directory(me->working_directory);
 
@@ -300,25 +300,25 @@ static void check_config()
       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, 
+         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);
-        }
+               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();
@@ -329,7 +329,7 @@ static void check_config()
  *  once at startup in a separate thread.
  */
 extern "C"
-void *device_allocation(void *arg)
+void *device_initialization(void *arg)
 {
    DEVRES *device;
 
@@ -342,36 +342,36 @@ void *device_allocation(void *arg)
       Dmsg1(10, "SD init done %s\n", device->device_name);
       if (!device->dev) {
          Jmsg1(NULL, M_ERROR, 0, _("Could not initialize %s\n"), device->device_name);
-        continue;
+         continue;
       }
 
       if (device->cap_bits & CAP_ALWAYSOPEN) {
          Dmsg1(20, "calling first_open_device %s\n", device->device_name);
-        if (!first_open_device(device->dev)) {
+         if (!first_open_device(device->dev)) {
             Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), device->device_name);
-        }
+         }
       }
       if (device->cap_bits & CAP_AUTOMOUNT && device->dev &&
-         device->dev->is_open()) {
-        JCR *jcr;
-        DCR *dcr;
-        jcr = new_jcr(sizeof(JCR), stored_free_jcr);
-        jcr->JobType = JT_SYSTEM;
-        /* Initialize FD start condition variable */
-        int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
-        if (errstat != 0) {
+          device->dev->is_open()) {
+         JCR *jcr;
+         DCR *dcr;
+         jcr = new_jcr(sizeof(JCR), stored_free_jcr);
+         jcr->JobType = JT_SYSTEM;
+         /* Initialize FD start condition variable */
+         int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
+         if (errstat != 0) {
             Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
-        }
-        dcr = new_dcr(jcr, device->dev);
-        switch (read_dev_volume_label(dcr)) {
-        case VOL_OK:
-           memcpy(&dcr->dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dcr->dev->VolCatInfo));
-           break;
-        default:
+         }
+         dcr = new_dcr(jcr, device->dev);
+         switch (read_dev_volume_label(dcr)) {
+         case VOL_OK:
+            memcpy(&dcr->dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dcr->dev->VolCatInfo));
+            break;
+         default:
             Jmsg1(NULL, M_WARNING, 0, _("Could not mount device %s\n"), device->device_name);
-           break;
-        }
-        free_jcr(jcr);
+            break;
+         }
+         free_jcr(jcr);
       }
    }
    UnlockRes();
@@ -386,12 +386,12 @@ void terminate_stored(int sig)
    DEVRES *device;
    JCR *jcr;
 
-   if (in_here) {                    /* prevent loops */
+   if (in_here) {                     /* prevent loops */
       exit(1);
    }
    in_here = true;
 
-   if (sig == SIGTERM) {             /* normal shutdown request? */
+   if (sig == SIGTERM) {              /* normal shutdown request? */
       /*
        * This is a normal shutdown request. We wiffle through
        *   all open jobs canceling them and trying to wake
@@ -400,27 +400,27 @@ void terminate_stored(int sig)
        */
       lock_jcr_chain();
       foreach_jcr(jcr) {
-        BSOCK *fd;
-        free_locked_jcr(jcr);
-        if (jcr->JobId == 0) {
-           continue;                 /* ignore console */
-        }
-        set_jcr_job_status(jcr, JS_Canceled);
-        fd = jcr->file_bsock;
-        if (fd) {
-           fd->timed_out = true;
+         BSOCK *fd;
+         free_locked_jcr(jcr);
+         if (jcr->JobId == 0) {
+            continue;                 /* ignore console */
+         }
+         set_jcr_job_status(jcr, JS_Canceled);
+         fd = jcr->file_bsock;
+         if (fd) {
+            fd->timed_out = true;
             Dmsg1(100, "term_stored killing JobId=%d\n", jcr->JobId);
-           pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
-           /* ***FIXME*** wiffle through all dcrs */
-           if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->dev_blocked) {
-              pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol);
-              pthread_cond_broadcast(&wait_device_release);
-           }
-           bmicrosleep(0, 50000);
-         }
+            pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
+            /* ***FIXME*** wiffle through all dcrs */
+            if (jcr->dcr && jcr->dcr->dev && jcr->dcr->dev->dev_blocked) {
+               pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol);
+               pthread_cond_broadcast(&wait_device_release);
+            }
+            bmicrosleep(0, 50000);
+          }
       }
       unlock_jcr_chain();
-      bmicrosleep(0, 500000);        /* give them 1/2 sec to clean up */
+      bmicrosleep(0, 500000);         /* give them 1/2 sec to clean up */
    }
 
    write_state_file(me->working_directory, "bacula-sd", get_first_port_host_order(me->sdaddrs));
@@ -431,7 +431,7 @@ void terminate_stored(int sig)
    LockRes();
    foreach_res(device, R_DEVICE) {
       if (device->dev) {
-        term_dev(device->dev);
+         term_dev(device->dev);
       }
    }
    UnlockRes();
@@ -447,6 +447,6 @@ void terminate_stored(int sig)
    stop_watchdog();
    close_memory_pool();
 
-   sm_dump(false);                   /* dump orphaned buffers */
+   sm_dump(false);                    /* dump orphaned buffers */
    exit(sig);
 }
index 67af8ce40d7001b18b3bec2f3f57df01fb2acb8e..df1bd94f5ab9b6a39021f662d7e3a809618d0d64 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #undef  VERSION
-#define VERSION "1.37.10"
-#define BDATE   "28 March 2005"
-#define LSMDATE "29Mar05"
+#define VERSION "1.37.11"
+#define BDATE   "31 March 2005"
+#define LSMDATE "31Mar05"
 
 /* Debug flags */
 #undef  DEBUG