]> git.sur5r.net Git - bacula/bacula/commitdiff
03Dec05
authorKern Sibbald <kern@sibbald.com>
Sat, 3 Dec 2005 15:00:04 +0000 (15:00 +0000)
committerKern Sibbald <kern@sibbald.com>
Sat, 3 Dec 2005 15:00:04 +0000 (15:00 +0000)
- Fix font code in gnome2 console user patch. Fixes bug #501.
- Fix malformatted bnet error message that caused seg fault
  fixes bug 502
- Applied user patch to improve README.vc8 in src/win32.
29Nov05
- Add Migrate, Copy, Archive Job types (some where there)
- Correct some more editing of JobId's (for 64 bit compatibility).
- Ensure that StorageId is stored in Media record when ever possible.
- Add Migration Job to Job.
- Add Migration Time, Migration High Bytes, Migration Low Bytes
  Next Pool to Pool resource.
- Add more code to mac.c (migration archive copy).
- Change Start Storage daemon job to require read and write storage
  pointers.
- Pass read storage data to SD as well as write storage data.
- Remove old code from winservice.cpp
- Break on error in scan.
- Fix typo in signal.c
- Separate read/write DCR in SD.  Add jcr->read_dcr.
- Cleanup how find_device() works.
- Add read output to Status in SD.

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

42 files changed:
bacula/kernstodo
bacula/kes-1.39
bacula/projects
bacula/src/dird/backup.c
bacula/src/dird/catreq.c
bacula/src/dird/dird_conf.c
bacula/src/dird/dird_conf.h
bacula/src/dird/job.c
bacula/src/dird/mac.c
bacula/src/dird/msgchan.c
bacula/src/dird/next_vol.c
bacula/src/dird/protos.h
bacula/src/dird/query.sql
bacula/src/dird/recycle.c
bacula/src/dird/restore.c
bacula/src/dird/ua_label.c
bacula/src/dird/ua_select.c
bacula/src/dird/verify.c
bacula/src/filed/job.c
bacula/src/filed/win32/winservice.cpp
bacula/src/jcr.h
bacula/src/lib/bnet.c
bacula/src/lib/jcr.c
bacula/src/lib/scan.c
bacula/src/lib/signal.c
bacula/src/lib/util.c
bacula/src/stored/acquire.c
bacula/src/stored/askdir.c
bacula/src/stored/autochanger.c
bacula/src/stored/bextract.c
bacula/src/stored/bscan.c
bacula/src/stored/butil.c
bacula/src/stored/device.c
bacula/src/stored/dircmd.c
bacula/src/stored/fd_cmds.c
bacula/src/stored/job.c
bacula/src/stored/read.c
bacula/src/stored/reserve.c
bacula/src/stored/spool.c
bacula/src/stored/status.c
bacula/src/stored/stored.c
bacula/src/version.h

index 21af52086af85f6e7eabd0d00ce0d3857aa43141..1093efbd17c4b9c8c3ba3e748b47d6b135c78f17 100644 (file)
@@ -1,5 +1,5 @@
                     Kern's ToDo List
-                     21 November 2005
+                     30 November 2005
 
 Major development:      
 Project                     Developer
@@ -16,8 +16,14 @@ Document:
 - Does WildFile match against full name?  Doc.
 
 For 1.39:
-- Make sure that all do_prompt() calls in Dir check for
-  -1 (error) and -2 (cancel) returns.
+- Queue warning/error messages during restore so that they
+  are reported at the end of the report rather than being
+  hidden in the file listing ...
+- A Volume taken from Scratch should take on the retention period
+  of the new pool.
+- Correct doc for Maximum Changer Wait (and others) accepting only
+  integers.
+- Fix Maximum Changer Wait (and others) to accept qualifiers.
 - Look at -D_FORTIFY_SOURCE=2
 - Add Win32 FileSet definition somewhere
 - Look at fixing restore status stats in SD.
@@ -1252,4 +1258,6 @@ Block Position: 0
 ====
 
 
-=== Done -- see kernsdone
+=== Done
+- Make sure that all do_prompt() calls in Dir check for
+  -1 (error) and -2 (cancel) returns.
index 9daab4d782916396a368509ced1200ff46aa26e9..b1a58fc6dd9e9300f07ca7927f87164727df1efd 100644 (file)
@@ -3,6 +3,29 @@
 
 General:
 
+Changes to 1.39.1:
+03Dec05
+- Fix font code in gnome2 console user patch. Fixes bug #501.
+- Fix malformatted bnet error message that caused seg fault
+  fixes bug 502
+- Applied user patch to improve README.vc8 in src/win32.
+29Nov05
+- Add Migrate, Copy, Archive Job types (some where there)
+- Correct some more editing of JobId's (for 64 bit compatibility).
+- Ensure that StorageId is stored in Media record when ever possible.
+- Add Migration Job to Job.
+- Add Migration Time, Migration High Bytes, Migration Low Bytes
+  Next Pool to Pool resource.
+- Add more code to mac.c (migration archive copy).
+- Change Start Storage daemon job to require read and write storage
+  pointers.
+- Pass read storage data to SD as well as write storage data.
+- Remove old code from winservice.cpp
+- Break on error in scan.
+- Fix typo in signal.c
+- Separate read/write DCR in SD.  Add jcr->read_dcr.
+- Cleanup how find_device() works.
+- Add read output to Status in SD.
 Changes to 1.39.0:
 23Nov05
 - Add red-black btree routines
index 32d851f7d6c2bc6be7c177e8d397cfa417440d4e..6c3450ed3759c59c74825b8a5e4caf184c5b835c 100644 (file)
@@ -4,7 +4,7 @@ Projects:
                        29 November 2005
 
 Summary:
-Item 1:   Implement Migration that  moves Jobs from one Pool to another.
+Item 1:   Implement Migration that moves Jobs from one Pool to another.
 Item 2:   Implement extraction of Win32 BackupWrite data.
 Item 3:   Implement a Bacula GUI/management tool using Python.
 Item 4:   Implement a Python interface to the Bacula catalog.
@@ -718,7 +718,18 @@ Item 25:  Implement creation and maintenance of copy pools
 
   Notes:  I would commit some of my developers' time if we can agree
           on the design and behavior. 
+===============================================
+Not in Dec 2005 Vote:
+Item n:   One line summary ...
+  Date:   29 November 2005
+  Origin: Florian Schnabel <florian.schnabel at docufy dot de>
+  Status:
 
+     What: An easy option to skip a certain job  on a certain date.
+     Why:  You could then easily skip tape backups on holidays.  Especially
+           if you got no autochanger and can only fit one backup on a tape
+           that would be really handy, other jobs could proceed normally
+           and you won't get errors that way.
 
 ============= Empty Feature Request form ===========
 Item n:   One line summary ...
index 0d2b181355db2b9ba9ae26adb33a54189f51f241..f10207a158c8f9d641f94850b829c08371e9cf6b 100644 (file)
@@ -138,11 +138,12 @@ bool do_backup(JCR *jcr)
    int tls_need = BNET_TLS_NONE;
    BSOCK   *fd;
    STORE *store;
+   char ed1[100];
 
 
    /* Print Job Start message */
-   Jmsg(jcr, M_INFO, 0, _("Start Backup JobId %u, Job=%s\n"),
-        jcr->JobId, jcr->Job);
+   Jmsg(jcr, M_INFO, 0, _("Start Backup JobId %s, Job=%s\n"),
+        edit_uint64(jcr->JobId, ed1), jcr->Job);
 
    set_jcr_job_status(jcr, JS_Running);
    Dmsg2(100, "JobId=%d JobLevel=%c\n", jcr->jr.JobId, jcr->jr.JobLevel);
@@ -168,7 +169,7 @@ bool do_backup(JCR *jcr)
    /*
     * Now start a job with the Storage daemon
     */
-   if (!start_storage_daemon_job(jcr, jcr->storage, SD_APPEND)) {
+   if (!start_storage_daemon_job(jcr, NULL, jcr->storage)) {
       return false;
    }
    /*
index 2f6a34053aae6b4bc95f08e2a22b7aedf174ee6f..41cebc6d29146daf0d54fb4febeaf1f83bf13485 100644 (file)
@@ -258,19 +258,23 @@ void catalog_request(JCR *jcr, BSOCK *bs)
       mr.VolWriteTime = sdmr.VolWriteTime;
       mr.VolParts     = sdmr.VolParts;
       bstrncpy(mr.VolStatus, sdmr.VolStatus, sizeof(mr.VolStatus));
+      if (jcr->store->StorageId) {
+         mr.StorageId = jcr->store->StorageId;
+      }
 
       Dmsg2(400, "db_update_media_record. Stat=%s Vol=%s\n", mr.VolStatus, mr.VolumeName);
       /*
-       * Check if it has expired, and if not update the DB. Note, if
-       *   Volume has expired, has_volume_expired() will update the DB.
+       * Update the database, then before sending the response to the
+       *  SD, check if the Volume has expired.
        */
-      if (has_volume_expired(jcr, &mr) || db_update_media_record(jcr, jcr->db, &mr)) {
-         send_volume_info_to_storage_daemon(jcr, bs, &mr);
-      } else {
+      if (!db_update_media_record(jcr, jcr->db, &mr)) {
          Jmsg(jcr, M_FATAL, 0, _("Catalog error updating Media record. %s"),
             db_strerror(jcr->db));
          bnet_fsend(bs, _("1993 Update Media error\n"));
          Dmsg0(400, "send error\n");
+      } else {
+         (void)has_volume_expired(jcr, &mr);
+         send_volume_info_to_storage_daemon(jcr, bs, &mr);
       }
       db_unlock(jcr->db);
 
index 994f383fdfe793157db6cfa7155cb5f15615efdc..6fd684c206d59b640303d0a6c73b8797fcd118c3 100644 (file)
@@ -236,6 +236,7 @@ RES_ITEM job_items[] = {
    {"fileset",   store_res,     ITEM(res_job.fileset),  R_FILESET, ITEM_REQUIRED, 0},
    {"schedule",  store_res,     ITEM(res_job.schedule), R_SCHEDULE, 0, 0},
    {"verifyjob", store_res,     ITEM(res_job.verify_job), R_JOB, 0, 0},
+   {"migrationjob", store_res,  ITEM(res_job.migration_job), R_JOB, 0, 0},
    {"jobdefs",   store_res,     ITEM(res_job.jobdefs),    R_JOBDEFS, 0, 0},
    {"run",       store_alist_str, ITEM(res_job.run_cmds), 0, 0, 0},
    {"where",    store_dir,      ITEM(res_job.RestoreWhere), 0, 0, 0},
@@ -321,6 +322,10 @@ static RES_ITEM pool_items[] = {
    {"catalogfiles",    store_yesno,   ITEM(res_pool.catalog_files),  1, ITEM_DEFAULT,  1},
    {"volumeretention", store_time,    ITEM(res_pool.VolRetention),   0, ITEM_DEFAULT, 60*60*24*365},
    {"volumeuseduration", store_time,  ITEM(res_pool.VolUseDuration), 0, 0, 0},
+   {"migrationtime",  store_time,     ITEM(res_pool.MigrationTime), 0, 0, 0},
+   {"migrationhighbytes", store_size, ITEM(res_pool.MigrationHighBytes), 0, 0, 0},
+   {"migrationlowbytes", store_size,  ITEM(res_pool.MigrationLowBytes), 0, 0, 0},
+   {"nextpool",       store_res,      ITEM(res_pool.NextPool), R_POOL, 0, 0},
    {"autoprune",       store_yesno,   ITEM(res_pool.AutoPrune), 1, ITEM_DEFAULT, 1},
    {"recycle",         store_yesno,   ITEM(res_pool.Recycle),     1, ITEM_DEFAULT, 1},
    {NULL, NULL, NULL, 0, 0, 0}
@@ -400,6 +405,8 @@ struct s_jt jobtypes[] = {
    {"admin",         JT_ADMIN},
    {"verify",        JT_VERIFY},
    {"restore",       JT_RESTORE},
+   {"copy",          JT_COPY},
+   {"migrate",       JT_MIGRATE},
    {NULL,            0}
 };
 
@@ -434,7 +441,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
 {
    URES *res = (URES *)reshdr;
    bool recurse = true;
-   char ed1[100], ed2[100];
+   char ed1[100], ed2[100], ed3[100];
    DEVICE *dev;
 
    if (res == NULL) {
@@ -460,13 +467,8 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
       }
       break;
    case R_CONSOLE:
-#ifdef HAVE_TLS
       sendit(sock, _("Console: name=%s SSL=%d\n"),
          res->res_con.hdr.name, res->res_con.tls_enable);
-#else
-      sendit(sock, _("Console: name=%s SSL=%d\n"),
-         res->res_con.hdr.name, BNET_TLS_NONE);
-#endif
       break;
    case R_COUNTER:
       if (res->res_counter.WrapCounter) {
@@ -771,6 +773,14 @@ next_run:
               res->res_pool.recycle_oldest_volume,
               res->res_pool.purge_oldest_volume,
               res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles);
+      sendit(sock, _("      MigTime=%s MigHiBytes=%s MigLoBytes=%s\n"),
+              edit_utime(res->res_pool.MigrationTime, ed1, sizeof(ed1)),
+              edit_uint64(res->res_pool.MigrationHighBytes, ed2),
+              edit_uint64(res->res_pool.MigrationLowBytes, ed3));
+      if (res->res_pool.NextPool) {
+         sendit(sock, _("  --> "));
+         dump_resource(-R_POOL, (RES *)res->res_pool.NextPool, sendit, sock);
+      }
       break;
    case R_MSGS:
       sendit(sock, _("Messages: name=%s\n"), res->res_msgs.hdr.name);
@@ -1137,13 +1147,26 @@ void save_resource(int type, RES_ITEM *items, int pass)
       switch (type) {
       /* Resources not containing a resource */
       case R_CATALOG:
-      case R_POOL:
       case R_MSGS:
       case R_FILESET:
       case R_DEVICE:
          break;
 
-      /* Resources containing another resource or alist */
+      /*
+       * Resources containing another resource or alist. First
+       *  look up the resource which contains another resource. It
+       *  was written during pass 1.  Then stuff in the pointers to
+       *  the resources it contains, which were inserted this pass.
+       *  Finally, it will all be stored back.
+       */
+      case R_POOL:
+         /* Find resource saved in pass 1 */
+         if ((res = (URES *)GetResWithName(R_POOL, res_all.res_con.hdr.name)) == NULL) {
+            Emsg1(M_ERROR_TERM, 0, _("Cannot find Pool resource %s\n"), res_all.res_con.hdr.name);
+         }
+         /* Update it with pointer to NextPool from this pass (res_all) */
+         res->res_pool.NextPool = res_all.res_pool.NextPool;
+         break;
       case R_CONSOLE:
          if ((res = (URES *)GetResWithName(R_CONSOLE, res_all.res_con.hdr.name)) == NULL) {
             Emsg1(M_ERROR_TERM, 0, _("Cannot find Console resource %s\n"), res_all.res_con.hdr.name);
index 5d2ef5befcaf8d1c8d8e7c7b3ef1bb10db55d324..8e980d621f567283c464e9b80a54966f494f258c 100644 (file)
@@ -316,7 +316,10 @@ public:
    POOL      *full_pool;              /* Pool for Full backups */
    POOL      *inc_pool;               /* Pool for Incremental backups */
    POOL      *dif_pool;               /* Pool for Differental backups */
-   JOB       *verify_job;             /* Job name to verify */
+   union {
+      JOB       *verify_job;          /* Job name to verify */
+      JOB       *migration_job;       /* Job name to migrate */
+   };
    JOB       *jobdefs;                /* Job defaults */
    alist     *run_cmds;               /* Run commands */
    uint32_t NumConcurrentJobs;        /* number of concurrent jobs running */
@@ -421,6 +424,10 @@ public:
    uint32_t MaxVolJobs;               /* Maximum jobs on the Volume */
    uint32_t MaxVolFiles;              /* Maximum files on the Volume */
    uint64_t MaxVolBytes;              /* Maximum bytes on the Volume */
+   utime_t MigrationTime;             /* Time to migrate to next pool */
+   uint32_t MigrationHighBytes;       /* When migration starts */
+   uint32_t MigrationLowBytes;        /* When migration stops */
+   POOL  *NextPool;                   /* Next pool for migration */
    int   AutoPrune;                   /* default for pool auto prune */
    int   Recycle;                     /* default for media recycle yes/no */
 };
index ecb0d7bf345ecab6789e7047255868e14e13880b..38bc8f9080cb640caba4b8abc4d075617b2108fd 100644 (file)
@@ -218,7 +218,7 @@ static void *job_thread(void *arg)
          admin_cleanup(jcr, JS_ErrorTerminated);
       }
       break;
-   case JT_MIGRATION:
+   case JT_MIGRATE:
    case JT_COPY:
    case JT_ARCHIVE:
       if (!do_mac_init(jcr)) {             /* migration, archive, copy */
@@ -294,7 +294,7 @@ static void *job_thread(void *arg)
             admin_cleanup(jcr, JS_ErrorTerminated);
          }
          break;
-      case JT_MIGRATION:
+      case JT_MIGRATE:
       case JT_COPY:
       case JT_ARCHIVE:
          if (do_mac(jcr)) {              /* migration, archive, copy */
index bd6c1d2dc56f903e773311d1f06f8a4e26aadf05..ecbe8aa013c00f37e899f336a24bab5fd97b7bb9 100644 (file)
@@ -43,6 +43,24 @@ bool do_mac_init(JCR *jcr)
    JOB_DBR jr;
    JobId_t input_jobid;
    char *Name;
+   RESTORE_CTX rx;
+   UAContext *ua;
+   const char *Type;
+
+   switch(jcr->JobType) {
+   case JT_MIGRATE:
+      Type = "Migration";
+      break;
+   case JT_ARCHIVE:
+      Type = "Archive";
+      break;
+   case JT_COPY:
+      Type = "Copy";
+      break;
+   default:
+      Type = "Unknown";
+      break;
+   }
 
    if (!get_or_create_fileset_record(jcr)) {
       return false;
@@ -52,7 +70,7 @@ bool do_mac_init(JCR *jcr)
     * Find JobId of last job that ran.
     */
    memcpy(&jr, &jcr->jr, sizeof(jr));
-   Name = jcr->job->hdr.name;
+   Name = jcr->job->migration_job->hdr.name;
    Dmsg1(100, "find last jobid for: %s\n", NPRT(Name));
    if (!db_find_last_jobid(jcr, jcr->db, Name, &jr)) {
       Jmsg(jcr, M_FATAL, 0, _(
@@ -60,9 +78,23 @@ bool do_mac_init(JCR *jcr)
       return false;
    }
    input_jobid = jr.JobId;
-   jcr->JobLevel = jr.JobLevel;
    Dmsg1(100, "Last jobid=%d\n", input_jobid);
 
+   jcr->target_jr.JobId = input_jobid;
+   if (!db_get_job_record(jcr, jcr->db, &jcr->target_jr)) {
+      Jmsg(jcr, M_FATAL, 0, _("Could not get job record for previous Job. ERR=%s"),
+           db_strerror(jcr->db));
+      return false;
+   }
+   if (jcr->target_jr.JobStatus != 'T') {
+      Jmsg(jcr, M_FATAL, 0, _("Last Job %d did not terminate normally. JobStatus=%c\n"),
+         input_jobid, jcr->target_jr.JobStatus);
+      return false;
+   }
+   Jmsg(jcr, M_INFO, 0, _("%s using JobId=%d Job=%s\n"),
+      Type, jcr->target_jr.JobId, jcr->target_jr.Job);
+
+
    /*
     * Get the Pool record -- first apply any level defined pools
     */
@@ -98,6 +130,32 @@ bool do_mac_init(JCR *jcr)
    }
    jcr->PoolId = pr.PoolId;               /****FIXME**** this can go away */
    jcr->jr.PoolId = pr.PoolId;
+
+   memset(&rx, 0, sizeof(rx));
+   rx.bsr = new_bsr();
+   rx.JobIds = "";                       
+   rx.bsr->JobId = jcr->target_jr.JobId;
+   ua = new_ua_context(jcr);
+   complete_bsr(ua, rx.bsr);
+   rx.bsr->fi = new_findex();
+   rx.bsr->fi->findex = 1;
+   rx.bsr->fi->findex2 = jcr->target_jr.JobFiles;
+   jcr->ExpectedFiles = write_bsr_file(ua, rx);
+   if (jcr->ExpectedFiles == 0) {
+      free_ua_context(ua);
+      free_bsr(rx.bsr);
+      return false;
+   }
+   if (jcr->RestoreBootstrap) {
+      free(jcr->RestoreBootstrap);
+   }
+   POOLMEM *fname = get_pool_memory(PM_MESSAGE);
+   make_unique_restore_filename(ua, &fname);
+   jcr->RestoreBootstrap = bstrdup(fname);
+   free_ua_context(ua);
+   free_bsr(rx.bsr);
+   free_pool_memory(fname);
+
    jcr->needs_sd = true;
    return true;
 }
@@ -112,9 +170,10 @@ bool do_mac(JCR *jcr)
 {
    int stat;
    const char *Type;
+   char ed1[100];
 
    switch(jcr->JobType) {
-   case JT_MIGRATION:
+   case JT_MIGRATE:
       Type = "Migration";
       break;
    case JT_ARCHIVE:
@@ -130,8 +189,8 @@ bool do_mac(JCR *jcr)
 
 
    /* Print Job Start message */
-   Jmsg(jcr, M_INFO, 0, _("Start %s JobId %u, Job=%s\n"),
-        Type, jcr->JobId, jcr->Job);
+   Jmsg(jcr, M_INFO, 0, _("Start %s JobId %s, Job=%s\n"),
+        Type, edit_uint64(jcr->JobId, ed1), jcr->Job);
 
    set_jcr_job_status(jcr, JS_Running);
    Dmsg2(100, "JobId=%d JobLevel=%c\n", jcr->jr.JobId, jcr->jr.JobLevel);
@@ -157,7 +216,7 @@ bool do_mac(JCR *jcr)
    /*
     * Now start a job with the Storage daemon
     */
-   if (!start_storage_daemon_job(jcr, jcr->storage, SD_APPEND)) {
+   if (!start_storage_daemon_job(jcr, jcr->storage, jcr->storage)) {
       return false;
    }
    /*
@@ -203,7 +262,7 @@ void mac_cleanup(JCR *jcr, int TermCode)
    const char *Type;
 
    switch(jcr->JobType) {
-   case JT_MIGRATION:
+   case JT_MIGRATE:
       Type = "Migration";
       break;
    case JT_ARCHIVE:
index fbe9d5e13607daf8986b990705a610f6a75dc3e7..a0b2e0a1bf1f769a0757bcbdf02c8bfc6e884851 100644 (file)
@@ -119,14 +119,13 @@ bool update_device_res(JCR *jcr, DEVICE *dev)
 /*
  * Start a job with the Storage daemon
  */
-int start_storage_daemon_job(JCR *jcr, alist *store, int append)
+bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore)
 {
-   bool ok = false;
+   bool ok = true;
    STORE *storage;
    BSOCK *sd;
    char auth_key[100];
    POOL_MEM store_name, device_name, pool_name, pool_type, media_type;
-   char PoolId[50];
    int copy = 0;
    int stripe = 0;
 
@@ -170,7 +169,6 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append)
    pm_strcpy(pool_name, jcr->pool->hdr.name);
    bash_spaces(pool_type);
    bash_spaces(pool_name);
-   edit_int64(jcr->PoolId, PoolId);
 
    /*
     * We have two loops here. The first comes from the 
@@ -181,36 +179,76 @@ int start_storage_daemon_job(JCR *jcr, alist *store, int append)
     *  available one.
     *
     */
-   foreach_alist(storage, store) {
-      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, store_name.c_str(), media_type.c_str(), 
-                 pool_name.c_str(), pool_type.c_str(), append, copy, stripe);
-
-      DEVICE *dev;
-      /* Loop over alternative storage Devices until one is OK */
-      foreach_alist(dev, storage->device) {
-         pm_strcpy(device_name, dev->hdr.name);
-         bash_spaces(device_name);
-         bnet_fsend(sd, use_device, device_name.c_str());
-         Dmsg1(100, ">stored: %s", sd->msg);
+   /* Do read side of storage daemon */
+   if (ok && rstore) {
+      foreach_alist(storage, rstore) {
+         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, store_name.c_str(), media_type.c_str(), 
+                    pool_name.c_str(), pool_type.c_str(), 0, copy, stripe);
+
+         DEVICE *dev;
+         /* Loop over alternative storage Devices until one is OK */
+         foreach_alist(dev, storage->device) {
+            pm_strcpy(device_name, dev->hdr.name);
+            bash_spaces(device_name);
+            bnet_fsend(sd, use_device, device_name.c_str());
+            Dmsg1(100, ">stored: %s", sd->msg);
+         }
+         bnet_sig(sd, BNET_EOD);            /* end of Devices */
+         bnet_sig(sd, BNET_EOD);            /* end of Storages */
+         if (bget_dirmsg(sd) > 0) {
+            Dmsg1(100, "<stored: %s", sd->msg);
+            /* ****FIXME**** save actual device name */
+            ok = sscanf(sd->msg, OK_device, device_name.c_str()) == 1;
+         } else {
+            POOL_MEM err_msg;
+            pm_strcpy(err_msg, sd->msg); /* save message */
+            Jmsg(jcr, M_FATAL, 0, _("\n"
+               "     Storage daemon didn't accept Device \"%s\" because:\n     %s"),
+               device_name.c_str(), err_msg.c_str()/* sd->msg */);
+            ok = false;
+         }
+         break;
       }
-      bnet_sig(sd, BNET_EOD);            /* end of Devices */
-      bnet_sig(sd, BNET_EOD);            /* end of Storages */
-      if (bget_dirmsg(sd) > 0) {
-         Dmsg1(100, "<stored: %s", sd->msg);
-         /* ****FIXME**** save actual device name */
-         ok = sscanf(sd->msg, OK_device, device_name.c_str()) == 1;
-      } else {
-         POOL_MEM err_msg;
-         pm_strcpy(err_msg, sd->msg); /* save message */
-         Jmsg(jcr, M_FATAL, 0, _("\n"
-            "     Storage daemon didn't accept Device \"%s\" because:\n     %s"),
-            device_name.c_str(), err_msg.c_str()/* sd->msg */);
+   }
+
+   /* Do write side of storage daemon */
+   if (ok && wstore) {
+      foreach_alist(storage, wstore) {
+         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, store_name.c_str(), media_type.c_str(), 
+                    pool_name.c_str(), pool_type.c_str(), 1, copy, stripe);
+
+         DEVICE *dev;
+         /* Loop over alternative storage Devices until one is OK */
+         foreach_alist(dev, storage->device) {
+            pm_strcpy(device_name, dev->hdr.name);
+            bash_spaces(device_name);
+            bnet_fsend(sd, use_device, device_name.c_str());
+            Dmsg1(100, ">stored: %s", sd->msg);
+         }
+         bnet_sig(sd, BNET_EOD);            /* end of Devices */
+         bnet_sig(sd, BNET_EOD);            /* end of Storages */
+         if (bget_dirmsg(sd) > 0) {
+            Dmsg1(100, "<stored: %s", sd->msg);
+            /* ****FIXME**** save actual device name */
+            ok = sscanf(sd->msg, OK_device, device_name.c_str()) == 1;
+         } else {
+            POOL_MEM err_msg;
+            pm_strcpy(err_msg, sd->msg); /* save message */
+            Jmsg(jcr, M_FATAL, 0, _("\n"
+               "     Storage daemon didn't accept Device \"%s\" because:\n     %s"),
+               device_name.c_str(), err_msg.c_str()/* sd->msg */);
+            ok = false;
+         }
+         break;
       }
-      break;
    }
    if (ok) {
       ok = bnet_fsend(sd, "run");
index 52086651a1e2a103d18398b78eda42b889611c38..9a64bf3921cd31da480325f94d24ead8acbb2cf0 100644 (file)
    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
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
+   modify it under the terms of the GNU General Public License
+   version 2 as amended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    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.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
index a7aabf4ec2af5c3da24cd6672067d00e99edbdc1..96b79e52941054bc630fc14007fad968f28a6054 100644 (file)
@@ -111,7 +111,7 @@ extern void mount_request(JCR *jcr, BSOCK *bs, char *buf);
 /* msgchan.c */
 extern bool connect_to_storage_daemon(JCR *jcr, int retry_interval,
                               int max_retry_time, int verbose);
-extern int start_storage_daemon_job(JCR *jcr, alist *store, int append);
+extern bool start_storage_daemon_job(JCR *jcr, alist *rstore, alist *wstore);
 extern int start_storage_daemon_message_thread(JCR *jcr);
 extern int bget_dirmsg(BSOCK *bs);
 extern void wait_for_storage_daemon_termination(JCR *jcr);
index 55101486c9dd3ebaa9f91ad8a86910a2aaa395f3..3b1aff3e0c97f083e3f7b3cedcd45935969250ba 100644 (file)
@@ -176,3 +176,17 @@ SELECT DISTINCT Job.JobId as JobId,Job.Name as Name,Job.StartTime as StartTime,
  AND Media.MediaId=JobMedia.MediaId              
  AND JobMedia.JobId=Job.JobId
  ORDER by Job.StartTime;
+# 16
+:List File record for given Job and File
+*Enter JobId:
+*Enter Full path (no filename) with trailing slash:
+*Enter Filename:
+SELECT File.JobId AS JobId,FileIndex FROM File,Path,Filename 
+  WHERE File.JobId=%1 AND
+  Path.Path='%2' AND Filename.Name='%3' AND
+  File.PathId=Path.PathId AND File.FilenameId=Filename.FilenameId;
+SELECT JobId,Name,VolSessionId,VolsessionTime,JobFiles FROM Job WHERE JobId=%1;
+SELECT JobId,MediaId,FirstIndex,LastIndex,StartFile,EndFile,StartBlock,EndBlock,
+  VolIndex FROM JobMedia WHERE JobId=%1;
+SELECT VolumeName FROM Media,JobMedia WHERE JobMedia.JobId=%1 AND
+  Media.MediaId=JobMedia.MediaId;
index 633cb5d35aa42626bb18cd31be5a34dbd217f1f7..61da3577f7070fe23de3c772d7edd04d567573f8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *
  *   Bacula Director -- Automatic Recycling of Volumes
- *     Recycles Volumes that have been purged
+ *      Recycles Volumes that have been purged
  *
  *     Kern Sibbald, May MMII
  *
@@ -9,22 +9,17 @@
  */
 
 /*
-   Copyright (C) 2002-20054 Kern Sibbald
+   Copyright (C) 2002-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.
+   modify it under the terms of the GNU General Public License
+   version 2 as amended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    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.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
@@ -98,11 +93,11 @@ int recycle_oldest_purged_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr)
    if (oldest.MediaId != 0) {
       mr->MediaId = oldest.MediaId;
       if (db_get_media_record(jcr, jcr->db, mr)) {
-        if (recycle_volume(jcr, mr)) {
+         if (recycle_volume(jcr, mr)) {
             Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\"\n"), mr->VolumeName);
             Dmsg1(100, "return 1  recycle_oldest_purged_volume Vol=%s\n", mr->VolumeName);
-           return 1;
-        }
+            return 1;
+         }
       }
       Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
    }
index 2e1d24fe4beac24a5080fdfb327be1fbde6a3d12..4c442816c87652e6880b212bd6d5262333ce1a08 100644 (file)
@@ -94,7 +94,7 @@ bool do_restore(JCR *jcr)
    /*
     * Now start a job with the Storage daemon
     */
-   if (!start_storage_daemon_job(jcr, jcr->storage, SD_READ)) {
+   if (!start_storage_daemon_job(jcr, jcr->storage, NULL)) {
       restore_cleanup(jcr, JS_ErrorTerminated);
       return false;
    }
index 384315b694e3bb30b42d0a3aadb2009904f1b4d1..a0bdd945adf229792a8302c377881804c06ce6d6 100644 (file)
@@ -535,6 +535,7 @@ static void label_from_barcodes(UAContext *ua, int drive)
             mr.VolBytes = 1;
             bstrncpy(mr.VolStatus, "Cleaning", sizeof(mr.VolStatus));
             mr.MediaType[0] = 0;
+            mr.StorageId = store->StorageId;
             if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
                 bsendmsg(ua, "%s", db_strerror(ua->db));
             }
@@ -659,6 +660,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
       if (media_record_exists) {      /* we update it */
          mr->VolBytes = 1;
          mr->InChanger = 1;
+         mr->StorageId = ua->jcr->store->StorageId;
          if (!db_update_media_record(ua->jcr, ua->db, mr)) {
              bsendmsg(ua, "%s", db_strerror(ua->db));
              ok = false;
@@ -667,6 +669,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
          set_pool_dbr_defaults_in_media_dbr(mr, pr);
          mr->VolBytes = 1;               /* flag indicating Volume labeled */
          mr->InChanger = 1;
+         mr->StorageId = ua->jcr->store->StorageId;
          if (db_create_media_record(ua->jcr, ua->db, mr)) {
             bsendmsg(ua, _("Catalog record for Volume \"%s\", Slot %d  successfully created.\n"),
             mr->VolumeName, mr->Slot);
index 1a5df789aa4da96a7fb368c76dee693c4365e835..41765194a59b1a89e85b3759dc9d6c5c6c5fa2eb 100644 (file)
@@ -837,7 +837,7 @@ STORE *get_storage_resource(UAContext *ua, bool use_default)
       store = NULL;
    }
 
-   if (!store && store_name) {
+   if (!store && store_name && store_name[0] != 0) {
       store = (STORE *)GetResWithName(R_STORAGE, store_name);
       if (!store) {
          bsendmsg(ua, _("Storage resource \"%s\": not found\n"), store_name);
index 6edbf80cadb60883f813f16c85d879dbff150479..f15233465f6ba664d69c712947f99dde1cb55f4a 100644 (file)
@@ -176,6 +176,7 @@ bool do_verify(JCR *jcr)
    const char *level;
    BSOCK   *fd;
    int stat;
+   char ed1[100];
 
    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
@@ -183,8 +184,8 @@ bool do_verify(JCR *jcr)
    }
 
    /* Print Job Start message */
-   Jmsg(jcr, M_INFO, 0, _("Start Verify JobId=%d Level=%s Job=%s\n"),
-      jcr->JobId, level_to_str(jcr->JobLevel), jcr->Job);
+   Jmsg(jcr, M_INFO, 0, _("Start Verify JobId=%s Level=%s Job=%s\n"),
+      edit_uint64(jcr->JobId, ed1), level_to_str(jcr->JobLevel), jcr->Job);
 
    if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) {
       /*
@@ -197,7 +198,7 @@ bool do_verify(JCR *jcr)
       /*
        * Now start a job with the Storage daemon
        */
-      if (!start_storage_daemon_job(jcr, jcr->storage, SD_READ)) {
+      if (!start_storage_daemon_job(jcr, jcr->storage, NULL)) {
          return false;
       }
       /*
index e30ed6720d5fc5d569a0babc16012910e2939ba2..edbac446d9bbdd5931000f36a3e891b23f706914 100644 (file)
@@ -1508,7 +1508,7 @@ static int open_sd_read_session(JCR *jcr)
    /*
     * Open Read Session with Storage daemon
     */
-   bnet_fsend(sd, read_open, jcr->VolumeName,
+   bnet_fsend(sd, read_open, "DummyVolume",
       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
       jcr->StartBlock, jcr->EndBlock);
    Dmsg1(110, ">stored: %s", sd->msg);
index e8dc2811ff9f4edb63b6898863b7d6b0695e6155..186d0a73efc142c01f034609a6f70d374776c7c9 100755 (executable)
@@ -457,32 +457,6 @@ _("Provides file backup and restore services. Bacula -- the network backup solut
       CloseServiceHandle(hsrvmanager);
       CloseServiceHandle(hservice);
 
-#ifdef xxx_needed
-      // Now install the servicehelper registry setting...
-      // Locate the RunService registry entry
-      HKEY runapps;
-      if (RegCreateKey(HKEY_LOCAL_MACHINE, 
-              "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
-              &runapps) != ERROR_SUCCESS) {
-         MessageBox(NULL, "WARNING: Unable to install the ServiceHelper hook\nGlobal user-specific registry settings will not be loaded", 
-            szAppName, MB_ICONEXCLAMATION | MB_OK);
-      } else {
-         char servicehelpercmd[pathlength];
-
-         // Append the service-helper-start flag to the end of the path:
-         if ((int)strlen(path) + 4 + (int)strlen(BaculaRunServiceHelper) < pathlength) {
-            sprintf(servicehelpercmd, "\"%s\" %s", path, BaculaRunServiceHelper);
-
-            // Add the Bacula Service Helper entry
-             if (RegSetValueEx(runapps, szAppName, 0, REG_SZ,
-                 (unsigned char *)servicehelpercmd, strlen(servicehelpercmd)+1) != ERROR_SUCCESS) {
-                MessageBox(NULL, "WARNING:Unable to install the ServiceHelper hook\nGlobal user-specific registry settings will not be loaded", szAppName, MB_ICONEXCLAMATION | MB_OK);
-             }
-             RegCloseKey(runapps);
-         }
-      }
-#endif
-
       // Everything went fine
       MessageBox(NULL,
               _("The Bacula File service was successfully installed.\n"
@@ -548,19 +522,6 @@ bacService::RemoveService()
       SC_HANDLE   hservice;
       SC_HANDLE   hsrvmanager;
 
-#ifdef xxx_needed
-      // Attempt to remove the service-helper hook
-      HKEY runapps;
-      if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run",
-              &runapps) == ERROR_SUCCESS) {
-         // Attempt to delete the Bacula key
-         if (RegDeleteValue(runapps, szAppName) != ERROR_SUCCESS) {
-            MessageBox(NULL, "WARNING:The ServiceHelper hook entry could not be removed from the registry", szAppName, MB_ICONEXCLAMATION | MB_OK);
-         }
-         RegCloseKey(runapps);
-      }
-#endif
-
       // Open the SCM
       hsrvmanager = OpenSCManager(
          NULL,                   // machine (NULL == local)
index 8ee90ca56f8968ab82dba310c9878b4f9d3227c6..4bd623ea726be93d1c122cf4b49e19b3f29c56f8 100644 (file)
 #define JT_BACKUP                'B'  /* Backup Job */
 #define JT_VERIFY                'V'  /* Verify Job */
 #define JT_RESTORE               'R'  /* Restore Job */
-#define JT_CONSOLE               'C'  /* console program */
+#define JT_CONSOLE               'c'  /* console program */
 #define JT_SYSTEM                'I'  /* internal system "job" */
 #define JT_ADMIN                 'D'  /* admin job */
 #define JT_ARCHIVE               'A'  /* Archive Job */
-#define JT_COPY                  'Y'  /* Copy Job */
-#define JT_MIGRATION             'M'  /* Migration Job */
+#define JT_COPY                  'C'  /* Copy Job */
+#define JT_MIGRATE               'M'  /* Migration Job */
 #define JT_SCAN                  'S'  /* Scan Job */
 
 /* Job Status. Some of these are stored in the DB */
@@ -239,6 +239,7 @@ public:
    JCR *prev_dev;                     /* previous JCR attached to device */
    pthread_cond_t job_start_wait;     /* Wait for FD to start Job */
    int type;
+   DCR *read_dcr;                     /* device context for reading */
    DCR *dcr;                          /* device context record */
    alist *dcrs;                       /* list of dcrs open */
    POOLMEM *job_name;                 /* base Job name (not unique) */
index 3f850d1d05c26852785996cbdfdc970e48b0ccdc..74e198220d37fba83753b3bee88806b75b650973 100644 (file)
@@ -394,8 +394,9 @@ bool bnet_send(BSOCK * bsock)
          }
       } else {
          Qmsg5(bsock->jcr, M_ERROR, 0,
-               _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"), bsock->who,
-               bsock->host, bsock->port, bsock->msglen, rc);
+               _("Wrote %d bytes to %s:%s:%d, but only %d accepted.\n"),
+               sizeof(int32_t), bsock->who,
+               bsock->host, bsock->port, rc);
       }
       return false;
    }
index fbb1356ac840a640c49eb8ab0e4ef6087e7e11fe..747ebc7fc9632701809cca7685684069685c4b5c 100755 (executable)
@@ -17,7 +17,7 @@
  *  in the list while traversing it rather than a single lock
  *  at the beginning of a traversal and one at the end.  This
  *  incurs slightly more overhead, but effectively eliminates 
- *  the possibilty of race conditions. In addition, with the
+ *  the possibilty of race conditions.  In addition, with the
  *  exception of the global locking of the list during the
  *  re-reading of the config file, no recursion is needed.
  *
@@ -61,7 +61,7 @@ int num_jobs_run;
 dlist *last_jobs = NULL;
 const int max_last_jobs = 10;
  
-static dlist *jcrs = NULL;           /* JCR chain */
+static dlist *jcrs = NULL;            /* JCR chain */
 static pthread_mutex_t jcr_lock = PTHREAD_MUTEX_INITIALIZER;
 
 static pthread_mutex_t job_start_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -92,9 +92,9 @@ void term_last_jobs_list()
 {
    if (last_jobs) {
       while (!last_jobs->empty()) {
-        void *je = last_jobs->first();
-        last_jobs->remove(je);
-        free(je);
+         void *je = last_jobs->first();
+         last_jobs->remove(je);
+         free(je);
       }
       delete last_jobs;
       last_jobs = NULL;
@@ -124,20 +124,20 @@ void read_last_jobs_list(int fd, uint64_t addr)
    for ( ; num; num--) {
       if (read(fd, &job, sizeof(job)) != sizeof(job)) {
          Dmsg1(000, "Read job entry. ERR=%s\n", strerror(errno));
-        return;
+         return;
       }
       if (job.JobId > 0) {
-        je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
-        memcpy((char *)je, (char *)&job, sizeof(job));
-        if (!last_jobs) {
-           init_last_jobs_list();
-        }
-        last_jobs->append(je);
-        if (last_jobs->size() > max_last_jobs) {
-           je = (struct s_last_job *)last_jobs->first();
-           last_jobs->remove(je);
-           free(je);
-        }
+         je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
+         memcpy((char *)je, (char *)&job, sizeof(job));
+         if (!last_jobs) {
+            init_last_jobs_list();
+         }
+         last_jobs->append(je);
+         if (last_jobs->size() > max_last_jobs) {
+            je = (struct s_last_job *)last_jobs->first();
+            last_jobs->remove(je);
+            free(je);
+         }
       }
    }
 }
@@ -156,13 +156,13 @@ uint64_t write_last_jobs_list(int fd, uint64_t addr)
       num = last_jobs->size();
       if (write(fd, &num, sizeof(num)) != sizeof(num)) {
          Dmsg1(000, "Error writing num_items: ERR=%s\n", strerror(errno));
-        return 0;
+         return 0;
       }
       foreach_dlist(je, last_jobs) {
-        if (write(fd, je, sizeof(struct s_last_job)) != sizeof(struct s_last_job)) {
+         if (write(fd, je, sizeof(struct s_last_job)) != sizeof(struct s_last_job)) {
             Dmsg1(000, "Error writing job: ERR=%s\n", strerror(errno));
-           return 0;
-        }
+            return 0;
+         }
       }
    }
    /* Return current address */
@@ -237,7 +237,7 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr)
    /* Setup some dummy values */
    bstrncpy(jcr->Job, "*System*", sizeof(jcr->Job));
    jcr->JobId = 0;
-   jcr->JobType = JT_SYSTEM;         /* internal job until defined */
+   jcr->JobType = JT_SYSTEM;          /* internal job until defined */
    jcr->JobLevel = L_NONE;
    jcr->JobStatus = JS_Created;
 
@@ -268,7 +268,7 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr)
 /*
  * Remove a JCR from the chain
  * NOTE! The chain must be locked prior to calling
- *      this routine.
+ *       this routine.
  */
 static void remove_jcr(JCR *jcr)
 {
@@ -293,6 +293,8 @@ static void free_common_jcr(JCR *jcr)
    case JT_BACKUP:
    case JT_VERIFY:
    case JT_RESTORE:
+   case JT_MIGRATE:
+   case JT_COPY:
    case JT_ADMIN:
       num_jobs_run++;
       last_job.Errors = jcr->Errors;
@@ -309,17 +311,17 @@ static void free_common_jcr(JCR *jcr)
       last_job.end_time = time(NULL);
       /* Keep list of last jobs, but not Console where JobId==0 */
       if (last_job.JobId > 0) {
-        je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
-        memcpy((char *)je, (char *)&last_job, sizeof(last_job));
-        if (!last_jobs) {
-           init_last_jobs_list();
-        }
-        last_jobs->append(je);
-        if (last_jobs->size() > max_last_jobs) {
-           je = (struct s_last_job *)last_jobs->first();
-           last_jobs->remove(je);
-           free(je);
-        }
+         je = (struct s_last_job *)malloc(sizeof(struct s_last_job));
+         memcpy((char *)je, (char *)&last_job, sizeof(last_job));
+         if (!last_jobs) {
+            init_last_jobs_list();
+         }
+         last_jobs->append(je);
+         if (last_jobs->size() > max_last_jobs) {
+            je = (struct s_last_job *)last_jobs->first();
+            last_jobs->remove(je);
+            free(je);
+         }
       }
       break;
    default:
@@ -328,7 +330,7 @@ static void free_common_jcr(JCR *jcr)
    pthread_mutex_destroy(&jcr->mutex);
 
    delete jcr->msg_queue;
-   close_msg(jcr);                   /* close messages for this job */
+   close_msg(jcr);                    /* close messages for this job */
 
    /* do this after closing messages */
    if (jcr->client_name) {
@@ -391,29 +393,29 @@ void free_jcr(JCR *jcr)
 
    dequeue_messages(jcr);
    lock_jcr_chain();
-   jcr->dec_use_count();             /* decrement use count */
+   jcr->dec_use_count();              /* decrement use count */
    if (jcr->use_count < 0) {
       Emsg2(M_ERROR, 0, _("JCR use_count=%d JobId=%d\n"),
-        jcr->use_count, jcr->JobId);
+         jcr->use_count, jcr->JobId);
    }
    Dmsg3(3400, "Dec free_jcr 0x%x use_count=%d jobid=%d\n", jcr, jcr->use_count, jcr->JobId);
-   if (jcr->use_count > 0) {         /* if in use */
+   if (jcr->use_count > 0) {          /* if in use */
       unlock_jcr_chain();
       Dmsg2(3400, "free_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
       return;
    }
 
-   remove_jcr(jcr);                  /* remove Jcr from chain */
+   remove_jcr(jcr);                   /* remove Jcr from chain */
    unlock_jcr_chain();
 
-   job_end_pop(jcr);                 /* pop and call hooked routines */
+   job_end_pop(jcr);                  /* pop and call hooked routines */
 
    Dmsg1(3400, "End job=%d\n", jcr->JobId);
    if (jcr->daemon_free_jcr) {
       jcr->daemon_free_jcr(jcr);      /* call daemon free routine */
    }
    free_common_jcr(jcr);
-   close_msg(NULL);                  /* flush any daemon messages */
+   close_msg(NULL);                   /* flush any daemon messages */
    Dmsg0(3400, "Exit free_jcr\n");
 }
 
@@ -421,18 +423,18 @@ void free_jcr(JCR *jcr)
 /*
  * Given a JobId, find the JCR
  *   Returns: jcr on success
- *           NULL on failure
+ *            NULL on failure
  */
 JCR *get_jcr_by_id(uint32_t JobId)
 {
    JCR *jcr;
 
-   lock_jcr_chain();                   /* lock chain */
+   lock_jcr_chain();                    /* lock chain */
    foreach_dlist(jcr, jcrs) {
       if (jcr->JobId == JobId) {
-        jcr->inc_use_count();
+         jcr->inc_use_count();
          Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
-        break;
+         break;
       }
    }
    unlock_jcr_chain();
@@ -442,7 +444,7 @@ JCR *get_jcr_by_id(uint32_t JobId)
 /*
  * Given a SessionId and SessionTime, find the JCR
  *   Returns: jcr on success
- *           NULL on failure
+ *            NULL on failure
  */
 JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime)
 {
@@ -451,10 +453,10 @@ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime)
    lock_jcr_chain();
    foreach_dlist(jcr, jcrs) {
       if (jcr->VolSessionId == SessionId &&
-         jcr->VolSessionTime == SessionTime) {
-        jcr->inc_use_count();
+          jcr->VolSessionTime == SessionTime) {
+         jcr->inc_use_count();
          Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
-        break;
+         break;
       }
    }
    unlock_jcr_chain();
@@ -467,7 +469,7 @@ JCR *get_jcr_by_session(uint32_t SessionId, uint32_t SessionTime)
  *  compares on the number of characters in Job
  *  thus allowing partial matches.
  *   Returns: jcr on success
- *           NULL on failure
+ *            NULL on failure
  */
 JCR *get_jcr_by_partial_name(char *Job)
 {
@@ -481,9 +483,9 @@ JCR *get_jcr_by_partial_name(char *Job)
    len = strlen(Job);
    foreach_dlist(jcr, jcrs) {
       if (strncmp(Job, jcr->Job, len) == 0) {
-        jcr->inc_use_count();
+         jcr->inc_use_count();
          Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
-        break;
+         break;
       }
    }
    unlock_jcr_chain();
@@ -495,7 +497,7 @@ JCR *get_jcr_by_partial_name(char *Job)
  * Given a Job, find the JCR
  *  requires an exact match of names.
  *   Returns: jcr on success
- *           NULL on failure
+ *            NULL on failure
  */
 JCR *get_jcr_by_full_name(char *Job)
 {
@@ -507,9 +509,9 @@ JCR *get_jcr_by_full_name(char *Job)
    lock_jcr_chain();
    foreach_dlist(jcr, jcrs) {
       if (strcmp(jcr->Job, Job) == 0) {
-        jcr->inc_use_count();
+         jcr->inc_use_count();
          Dmsg2(3400, "Inc get_jcr 0x%x use_count=%d\n", jcr, jcr->use_count);
-        break;
+         break;
       }
    }
    unlock_jcr_chain();
@@ -590,8 +592,8 @@ bool init_jcr_subsystem(void)
    watchdog_t *wd = new_watchdog();
 
    wd->one_shot = false;
-   wd->interval = 30;  /* FIXME: should be configurable somewhere, even
-                        if only with a #define */
+   wd->interval = 30;   /* FIXME: should be configurable somewhere, even
+                         if only with a #define */
    wd->callback = jcr_timeout_check;
 
    register_watchdog(wd);
@@ -612,44 +614,44 @@ static void jcr_timeout_check(watchdog_t *self)
     */
    foreach_jcr(jcr) {
       if (jcr->JobId == 0) {
-        free_jcr(jcr);
-        continue;
+         free_jcr(jcr);
+         continue;
       }
       fd = jcr->store_bsock;
       if (fd) {
-        timer_start = fd->timer_start;
-        if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
-           fd->timer_start = 0;      /* turn off timer */
-           fd->timed_out = TRUE;
-           Jmsg(jcr, M_ERROR, 0, _(
+         timer_start = fd->timer_start;
+         if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
+            fd->timer_start = 0;      /* turn off timer */
+            fd->timed_out = TRUE;
+            Jmsg(jcr, M_ERROR, 0, _(
 "Watchdog sending kill after %d secs to thread stalled reading Storage daemon.\n"),
-                watchdog_time - timer_start);
-           pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
-        }
+                 watchdog_time - timer_start);
+            pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
+         }
       }
       fd = jcr->file_bsock;
       if (fd) {
-        timer_start = fd->timer_start;
-        if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
-           fd->timer_start = 0;      /* turn off timer */
-           fd->timed_out = TRUE;
-           Jmsg(jcr, M_ERROR, 0, _(
+         timer_start = fd->timer_start;
+         if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
+            fd->timer_start = 0;      /* turn off timer */
+            fd->timed_out = TRUE;
+            Jmsg(jcr, M_ERROR, 0, _(
 "Watchdog sending kill after %d secs to thread stalled reading File daemon.\n"),
-                watchdog_time - timer_start);
-           pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
-        }
+                 watchdog_time - timer_start);
+            pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
+         }
       }
       fd = jcr->dir_bsock;
       if (fd) {
-        timer_start = fd->timer_start;
-        if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
-           fd->timer_start = 0;      /* turn off timer */
-           fd->timed_out = TRUE;
-           Jmsg(jcr, M_ERROR, 0, _(
+         timer_start = fd->timer_start;
+         if (timer_start && (watchdog_time - timer_start) > fd->timeout) {
+            fd->timer_start = 0;      /* turn off timer */
+            fd->timed_out = TRUE;
+            Jmsg(jcr, M_ERROR, 0, _(
 "Watchdog sending kill after %d secs to thread stalled reading Director.\n"),
-                watchdog_time - timer_start);
-           pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
-        }
+                 watchdog_time - timer_start);
+            pthread_kill(jcr->my_thread_id, TIMEOUT_SIGNAL);
+         }
       }
       free_jcr(jcr);
    }
@@ -662,5 +664,5 @@ static void jcr_timeout_check(watchdog_t *self)
  */
 extern "C" void timeout_handler(int sig)
 {
-   return;                           /* thus interrupting the function */
+   return;                            /* thus interrupting the function */
 }
index 3bdc3526fb1d6bb26f2d45b62c263dafc16721cc..cfb5751300de698e97bd015f0090bebdd4a42bf5 100644 (file)
@@ -406,6 +406,7 @@ switch_top:
       } else if (*buf++ != *fmt++) {
 //       Dmsg2(000, "Mismatch buf=%c fmt=%c\n", *--buf, *--fmt);
          error = true;
+         break;
       }
    }
    va_end(ap);
index 3b06e2f08a31df3ff507968dce583740605f1d00..fd55deeeee967288b9166bd59b80e127307c3812 100644 (file)
@@ -245,7 +245,7 @@ void init_signals(void terminate(int sig))
    sig_names[SIGWAITING] = _("No runnable lwp");
 #endif
 #ifdef SIGLWP
-   sig_names[SIGLWP]    = _("SIGLWP special signal used by thread library");
+   sig_names[SIGLWP]     = _("SIGLWP special signal used by thread library");
 #endif
 #ifdef SIGFREEZE
    sig_names[SIGFREEZE] = _("Checkpoint Freeze");
index 1d53dc2e227fc7d7a2da67043579f2cfd3911f34..35cbb4a7e3ed531a96bd1a996bc2fcb9fbaff5d0 100644 (file)
@@ -5,24 +5,18 @@
  *
  *   Version $Id$
  */
-
 /*
-   Copyright (C) 2000-2004 Kern Sibbald and John Walker
+   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.
+   modify it under the terms of the GNU General Public License
+   version 2 as amended with additional clauses defined in the
+   file LICENSE in the main source directory.
 
    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.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
+   the file LICENSE for additional details.
 
  */
 
@@ -50,7 +44,7 @@ int is_buf_zero(char *buf, int len)
    len64 = len / sizeof(uint64_t);
    for (i=0; i < len64; i++) {
       if (ip[i] != 0) {
-        return 0;
+         return 0;
       }
    }
    done = len64 * sizeof(uint64_t);  /* bytes already checked */
@@ -58,7 +52,7 @@ int is_buf_zero(char *buf, int len)
    rem = len - done;
    for (i = 0; i < rem; i++) {
       if (p[i] != 0) {
-        return 0;
+         return 0;
       }
    }
    return 1;
@@ -70,7 +64,7 @@ void lcase(char *str)
 {
    while (*str) {
       if (B_ISUPPER(*str))
-        *str = tolower((int)(*str));
+         *str = tolower((int)(*str));
        str++;
    }
 }
@@ -83,7 +77,7 @@ bash_spaces(char *str)
 {
    while (*str) {
       if (*str == ' ')
-        *str = 0x1;
+         *str = 0x1;
       str++;
    }
 }
@@ -97,7 +91,7 @@ bash_spaces(POOL_MEM &pm)
    char *str = pm.c_str();
    while (*str) {
       if (*str == ' ')
-        *str = 0x1;
+         *str = 0x1;
       str++;
    }
 }
@@ -142,10 +136,10 @@ char *encode_time(time_t time, char *buf)
 #if    HAVE_WIN32 && !HAVE_CONSOLE && !HAVE_WXCONSOLE
     /*
      * Gross kludge to avoid a seg fault in Microsoft's CRT localtime_r(),
-     * which incorrectly references a NULL returned from gmtime() if
-     * the time (adjusted for the current timezone) is invalid.
-     * This could happen if you have a bad date/time, or perhaps if you
-     * moved a file from one timezone to another?
+     *  which incorrectly references a NULL returned from gmtime() if
+     *  the time (adjusted for the current timezone) is invalid.
+     *  This could happen if you have a bad date/time, or perhaps if you
+     *  moved a file from one timezone to another?
      */
     struct tm *gtm;
     time_t gtime;
@@ -157,14 +151,14 @@ char *encode_time(time_t time, char *buf)
     if (_daylight && _isindst(gtm)) {
        gtime -= _dstbias;
        if (!gmtime(&gtime)) {
-         return buf;
+          return buf;
        }
     }
 #endif
    if (localtime_r(&time, &tm)) {
       n = sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
-                  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-                  tm.tm_hour, tm.tm_min, tm.tm_sec);
+                   tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+                   tm.tm_hour, tm.tm_min, tm.tm_sec);
    }
    return buf+n;
 }
@@ -238,7 +232,7 @@ void jobstatus_to_ascii(int JobStatus, char *msg, int maxlen)
 
    default:
       if (JobStatus == 0) {
-        buf[0] = 0;
+         buf[0] = 0;
       } else {
          bsnprintf(buf, sizeof(buf), _("Unknown Job termination status=%d"), JobStatus);
       }
@@ -300,6 +294,12 @@ const char *job_type_to_str(int type)
    case JT_ADMIN:
       str = _("Admin");
       break;
+   case JT_MIGRATE:
+      str = _("Migrate");
+      break;
+   case JT_COPY:
+      str = _("Copy");
+      break;
    default:
       str = _("Unknown Type");
       break;
@@ -399,8 +399,8 @@ int do_shell_expansion(char *name, int name_len)
    len = strlen(meta);
    for (i = 0; i < len; i++) {
       if (strchr(name, meta[i])) {
-        found = true;
-        break;
+         found = true;
+         break;
       }
    }
    if (found) {
@@ -415,27 +415,27 @@ int do_shell_expansion(char *name, int name_len)
       pm_strcat(&cmd, "\"");
       Dmsg1(400, "Send: %s\n", cmd);
       if ((bpipe = open_bpipe(cmd, 0, "r"))) {
-        *line = 0;
-        fgets(line, sizeof(line), bpipe->rfd);
-        strip_trailing_junk(line);
-        stat = close_bpipe(bpipe);
+         *line = 0;
+         fgets(line, sizeof(line), bpipe->rfd);
+         strip_trailing_junk(line);
+         stat = close_bpipe(bpipe);
          Dmsg2(400, "stat=%d got: %s\n", stat, line);
       } else {
-        stat = 1;                    /* error */
+         stat = 1;                    /* error */
       }
       free_pool_memory(cmd);
       if (stat == 0) {
-        bstrncpy(name, line, name_len);
+         bstrncpy(name, line, name_len);
       }
    }
    return 1;
 }
 
 
-/*  MAKESESSIONKEY  -- Generate session key with optional start
-                       key.  If mode is TRUE, the key will be
-                       translated to a string, otherwise it is
-                       returned as 16 binary bytes.
+/*  MAKESESSIONKEY  --  Generate session key with optional start
+                        key.  If mode is TRUE, the key will be
+                        translated to a string, otherwise it is
+                        returned as 16 binary bytes.
 
     from SpeakFreely by John Walker */
 
@@ -448,15 +448,15 @@ void make_session_key(char *key, char *seed, int mode)
 
      s[0] = 0;
      if (seed != NULL) {
-       bstrncat(s, seed, sizeof(s));
+        bstrncat(s, seed, sizeof(s));
      }
 
      /* The following creates a seed for the session key generator
-       based on a collection of volatile and environment-specific
-       information unlikely to be vulnerable (as a whole) to an
+        based on a collection of volatile and environment-specific
+        information unlikely to be vulnerable (as a whole) to an
         exhaustive search attack.  If one of these items isn't
-       available on your machine, replace it with something
-       equivalent or, if you like, just delete it. */
+        available on your machine, replace it with something
+        equivalent or, if you like, just delete it. */
 
      sprintf(s + strlen(s), "%lu", (unsigned long)getpid());
      sprintf(s + strlen(s), "%lu", (unsigned long)getppid());
@@ -481,22 +481,22 @@ void make_session_key(char *key, char *seed, int mode)
      MD5Final(md5key1, &md5c);
 #define nextrand    (md5key[j] ^ md5key1[j])
      if (mode) {
-       for (j = k = 0; j < 16; j++) {
-          unsigned char rb = nextrand;
+        for (j = k = 0; j < 16; j++) {
+           unsigned char rb = nextrand;
 
 #define Rad16(x) ((x) + 'A')
-          key[k++] = Rad16((rb >> 4) & 0xF);
-          key[k++] = Rad16(rb & 0xF);
+           key[k++] = Rad16((rb >> 4) & 0xF);
+           key[k++] = Rad16(rb & 0xF);
 #undef Rad16
-          if (j & 1) {
+           if (j & 1) {
               key[k++] = '-';
-          }
-       }
-       key[--k] = 0;
+           }
+        }
+        key[--k] = 0;
      } else {
-       for (j = 0; j < 16; j++) {
-          key[j] = nextrand;
-       }
+        for (j = 0; j < 16; j++) {
+           key[j] = nextrand;
+        }
      }
 }
 #undef nextrand
@@ -535,102 +535,102 @@ POOLMEM *edit_job_codes(JCR *jcr, char *omsg, char *imsg, const char *to)
    Dmsg1(200, "edit_job_codes: %s\n", imsg);
    for (p=imsg; *p; p++) {
       if (*p == '%') {
-        switch (*++p) {
+         switch (*++p) {
          case '%':
             str = "%";
-           break;
+            break;
          case 'c':
-           if (jcr) {
-              str = jcr->client_name;
-           } else {
+            if (jcr) {
+               str = jcr->client_name;
+            } else {
                str = _("*none*");
-           }
-           break;
+            }
+            break;
          case 'd':
             str = my_name;            /* Director's name */
-           break;
+            break;
          case 'e':
-           if (jcr) {
-              str = job_status_to_str(jcr->JobStatus);
-           } else {
+            if (jcr) {
+               str = job_status_to_str(jcr->JobStatus);
+            } else {
                str = _("*none*");
-           }
-           break;
+            }
+            break;
          case 'i':
-           if (jcr) {
+            if (jcr) {
                bsnprintf(add, sizeof(add), "%d", jcr->JobId);
-              str = add;
-           } else {
+               str = add;
+            } else {
                str = _("*none*");
-           }
-           break;
+            }
+            break;
          case 'j':                    /* Job name */
-           if (jcr) {
-              str = jcr->Job;
-           } else {
+            if (jcr) {
+               str = jcr->Job;
+            } else {
                str = _("*none*");
-           }
-           break;
+            }
+            break;
          case 'l':
-           if (jcr) {
-              str = job_level_to_str(jcr->JobLevel);
-           } else {
+            if (jcr) {
+               str = job_level_to_str(jcr->JobLevel);
+            } else {
                str = _("*none*");
-           }
-           break;
+            }
+            break;
          case 'n':
-            if (jcr) {
-               bstrncpy(name, jcr->Job, sizeof(name));
-               /* There are three periods after the Job name */
-               for (i=0; i<3; i++) {
+             if (jcr) {
+                bstrncpy(name, jcr->Job, sizeof(name));
+                /* There are three periods after the Job name */
+                for (i=0; i<3; i++) {
                    if ((q=strrchr(name, '.')) != NULL) {
-                      *q = 0;
-                  }
-               }
-               str = name;
-            } else {
+                       *q = 0;
+                   }
+                }
+                str = name;
+             } else {
                 str = _("*none*");
-            }
-            break;
+             }
+             break;
          case 'r':
-           str = to;
-           break;
+            str = to;
+            break;
          case 's':                    /* since time */
-           if (jcr && jcr->stime) {
-              str = jcr->stime;
-           } else {
+            if (jcr && jcr->stime) {
+               str = jcr->stime;
+            } else {
                str = _("*none*");
-           }
-           break;
+            }
+            break;
          case 't':
-           if (jcr) {
-              str = job_type_to_str(jcr->JobType);
-           } else {
+            if (jcr) {
+               str = job_type_to_str(jcr->JobType);
+            } else {
                str = _("*none*");
-           }
-           break;
+            }
+            break;
          case 'v':
-           if (jcr) {
-              if (jcr->VolumeName && jcr->VolumeName[0]) {
-                 str = jcr->VolumeName;
-              } else {
+            if (jcr) {
+               if (jcr->VolumeName && jcr->VolumeName[0]) {
+                  str = jcr->VolumeName;
+               } else {
                   str = "";
-              }
-           } else {
+               }
+            } else {
                str = _("*none*");
-           }
-           break;
-        default:
+            }
+            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(1200, "add_str %s\n", str);
       pm_strcat(&omsg, str);
@@ -648,11 +648,11 @@ void set_working_directory(char *wd)
    }
    if (stat(wd, &stat_buf) != 0) {
       Emsg1(M_ERROR_TERM, 0, _("Working Directory: \"%s\" not found. Cannot continue.\n"),
-        wd);
+         wd);
    }
    if (!S_ISDIR(stat_buf.st_mode)) {
       Emsg1(M_ERROR_TERM, 0, _("Working Directory: \"%s\" is not a directory. Cannot continue.\n"),
-        wd);
+         wd);
    }
-   working_directory = wd;           /* set global */
+   working_directory = wd;            /* set global */
 }
index 8c2d9e80cf8785f980de72a5661b7e6e71630dfd..e0ce9c5be3ff54ebcd71d16e3877ac96453a54f1 100644 (file)
  */
 DCR *new_dcr(JCR *jcr, DEVICE *dev)
 {
-   if (jcr && jcr->dcr) {
-      return jcr->dcr;
-   }
    DCR *dcr = (DCR *)malloc(sizeof(DCR));
    memset(dcr, 0, sizeof(DCR));
    dcr->jcr = jcr;
    if (dev) {
-      if (jcr) {
-         jcr->dcr = dcr;
-      }
       dcr->dev = dev;
       dcr->device = dev->device;
       dcr->block = new_block(dev);
@@ -275,7 +269,6 @@ default_path:
 get_out:
    dev->unblock();
    if (!vol_ok) {
-      free_dcr(dcr);
       dcr = NULL;
    }
    return dcr;
@@ -423,6 +416,7 @@ bool release_device(DCR *dcr)
    JCR *jcr = dcr->jcr;
    DEVICE *dev = dcr->dev;
    bool ok = true;
+   bool was_reading = false;
 
    lock_device(dev);
    Dmsg1(100, "release_device device is %s\n", dev->is_tape()?"tape":"disk");
@@ -436,6 +430,7 @@ bool release_device(DCR *dcr)
 
    if (dev->can_read()) {
       dev->clear_read();              /* clear read bit */
+      was_reading = true;
 
       /******FIXME**** send read volume usage statistics to director */
 
@@ -510,7 +505,11 @@ bool release_device(DCR *dcr)
    }
    unlock_device(dev);
    free_dcr(dcr);
-   jcr->dcr = NULL;
+   if (was_reading) {
+      jcr->read_dcr = NULL;
+   } else {
+      jcr->dcr = NULL;
+   }
    pthread_cond_broadcast(&wait_device_release);
    return ok;
 }
index b9f4340b6c500c3d73482b19a4007c4d4ac019f3..248a2116abe3a6f850940d70c569443b65e1f22a 100644 (file)
@@ -503,7 +503,7 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr)
          Jmsg(jcr, M_WARNING, 0, _("pthread error in mount_next_volume stat=%d ERR=%s\n"), stat,
             be.strerror(stat));
       }
-      Dmsg1(000, "Someone woke me for device %s\n", dev->print_name());
+      Dmsg1(100, "Someone woke me for device %s\n", dev->print_name());
 
       /* If no VolumeName, and cannot get one, try again */
       P(dev->mutex);
@@ -531,7 +531,7 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr)
    }
    set_jcr_job_status(jcr, JS_Running);
    dir_send_job_status(jcr);
-   Dmsg0(000, "leave dir_ask_sysop_to_mount_create_appendable_volume\n");
+   Dmsg0(100, "leave dir_ask_sysop_to_mount_create_appendable_volume\n");
    return true;
 }
 
index 63c2feea354c105cf83b594c3eff728186d58277..805aa2e871e1682c20fab0ea6f08a50b256b2633 100644 (file)
@@ -37,7 +37,6 @@ bool init_autochangers()
    /* Ensure that the media_type for each device is the same */
    foreach_res(changer, R_AUTOCHANGER) {
       DEVRES *device;
-      char *media_type = NULL;
       foreach_alist(device, changer->device) {
          /*
           * If the device does not have a changer name or changer command
@@ -62,6 +61,7 @@ bool init_autochangers()
             OK = false;
          }   
 
+#ifdef xxx_needed
          if (media_type == NULL) {
             media_type = device->media_type;     /* get Media Type of first device */
             continue;
@@ -74,6 +74,7 @@ bool init_autochangers()
             OK = false;
             continue;
          }
+#endif
       }
    }
    return OK;
index 92fcbd761857fb362f1bfd10e9a39de87215a712..addb74bbdc3c7ed88f51b112ff53828defa602b4 100644 (file)
@@ -214,11 +214,11 @@ static void do_extract(char *devname)
    if (!jcr) {
       exit(1);
    }
-   dev = jcr->dcr->dev;
+   dev = jcr->read_dcr->dev;
    if (!dev) {
       exit(1);
    }
-   dcr = jcr->dcr;
+   dcr = jcr->read_dcr;
 
    /* Make sure where directory exists and that it is a directory */
    if (stat(where, &statp) < 0) {
index b46c66c27328a00ff40302cb09ac308210420a1b..bd9b310e925deb1768660749715fc3ee45b7310d 100644 (file)
@@ -259,7 +259,7 @@ int main (int argc, char *argv[])
    if (!bjcr) {
       exit(1);
    }
-   dev = bjcr->dcr->dev;
+   dev = bjcr->read_dcr->dev;
    if (showProgress) {
       char ed1[50];
       struct stat sb;
@@ -356,7 +356,7 @@ static void do_scan()
 
    /* Detach bscan's jcr as we are not a real Job on the tape */
 
-   read_records(bjcr->dcr, record_cb, bscan_mount_next_read_volume);
+   read_records(bjcr->read_dcr, record_cb, bscan_mount_next_read_volume);
 
    free_attr(attr);
 }
@@ -499,7 +499,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec)
 
          /* process label, if Job record exists don't update db */
          mjcr = create_job_record(db, &jr, &label, rec);
-         dcr = mjcr->dcr;
+         dcr = mjcr->read_dcr;
          update_db = save_update_db;
 
          jr.PoolId = pr.PoolId;
@@ -571,7 +571,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec)
 
          /* Create JobMedia record */
          create_jobmedia_record(db, mjcr);
-         dev->attached_dcrs->remove(mjcr->dcr);
+         dev->attached_dcrs->remove(mjcr->read_dcr);
          free_jcr(mjcr);
 
          break;
@@ -603,7 +603,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec)
                if (!db_update_job_end_record(bjcr, db, &jr)) {
                   Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db));
                }
-               mjcr->dcr = NULL;
+               mjcr->read_dcr = NULL;
                free_jcr(mjcr);
             }
          }
@@ -631,7 +631,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec)
       }
       return true;
    }
-   dcr = mjcr->dcr;
+   dcr = mjcr->read_dcr;
    if (dcr->VolFirstIndex == 0) {
       dcr->VolFirstIndex = block->FirstIndex;
    }
@@ -760,6 +760,10 @@ static void bscan_free_jcr(JCR *jcr)
       free_dcr(jcr->dcr);
       jcr->dcr = NULL;
    }
+   if (jcr->read_dcr) {
+      free_dcr(jcr->read_dcr);
+      jcr->read_dcr = NULL;
+   }
    Dmsg0(200, "End bscan free_jcr\n");
 }
 
@@ -771,7 +775,7 @@ static int create_file_attributes_record(B_DB *db, JCR *mjcr,
                                char *fname, char *lname, int type,
                                char *ap, DEV_RECORD *rec)
 {
-   DCR *dcr = mjcr->dcr;
+   DCR *dcr = mjcr->read_dcr;
    ar.fname = fname;
    ar.link = lname;
    ar.ClientId = mjcr->ClientId;
@@ -1103,7 +1107,7 @@ static int update_job_record(B_DB *db, JOB_DBR *jr, SESSION_LABEL *elabel,
 static int create_jobmedia_record(B_DB *db, JCR *mjcr)
 {
    JOBMEDIA_DBR jmr;
-   DCR *dcr = mjcr->dcr;
+   DCR *dcr = mjcr->read_dcr;
 
    if (dev->is_tape()) {
       dcr->EndBlock = dev->EndBlock;
@@ -1198,7 +1202,8 @@ static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId)
    jobjcr->VolSessionId = rec->VolSessionId;
    jobjcr->VolSessionTime = rec->VolSessionTime;
    jobjcr->ClientId = jr->ClientId;
-   new_dcr(jobjcr, dev);
+   jobjcr->read_dcr = new_dcr(jobjcr, dev);
+
    return jobjcr;
 }
 
index 92923e03e647be89fc41b00e5ed90f8767928265..7a8da3571c60c9f5681510db1e31d4b046eafca2 100644 (file)
@@ -171,11 +171,13 @@ static DCR *setup_to_access_device(JCR *jcr, char *dev_name,
       if (!acquire_device_for_read(dcr)) {
          return NULL;
       }
+      jcr->read_dcr = dcr;
    } else {
       if (!first_open_device(dcr)) {
          Jmsg1(jcr, M_FATAL, 0, _("Cannot open %s\n"), dev->print_name());
          return NULL;
       }
+      jcr->dcr = dcr;        /* write dcr */
    }
    return dcr;
 }
index 17d1803c1d872ed1497b2daee63054c3c53cdb21..d516a6d0e79401fb92dcbd86c7d380eef3841dec 100644 (file)
@@ -136,8 +136,7 @@ bool fixup_device_block_write_error(DCR *dcr)
    /*
     * Walk through all attached jcrs indicating the volume has changed
     */
-   Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
-// for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+   Dmsg1(100, "Walk attached dcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
    DCR *mdcr;
    foreach_dlist(mdcr, dev->attached_dcrs) {
       JCR *mjcr = mdcr->jcr;
index 5a06eeba48f43546d22a274b8724105e898afbcc..71c9bb959c55145ad78aecfd609c33b7874a03f1 100644 (file)
@@ -73,9 +73,9 @@ static bool mount_cmd(JCR *jcr);
 static bool unmount_cmd(JCR *jcr);
 static bool changer_cmd(JCR *sjcr);
 static bool do_label(JCR *jcr, int relabel);
-static DEVICE *find_device(JCR *jcr, POOL_MEM &dev_name, int drive);
+static DCR *find_device(JCR *jcr, POOL_MEM &dev_name, int drive);
 static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot);
-static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
+static void label_volume_if_ok(DCR *dcr, char *oldname,
                                char *newname, char *poolname,
                                int Slot, int relabel);
 static bool try_autoload_device(JCR *jcr, int slot, const char *VolName);
@@ -276,6 +276,10 @@ static bool cancel_cmd(JCR *cjcr)
              pthread_cond_signal(&jcr->dcr->dev->wait_next_vol);
              pthread_cond_broadcast(&wait_device_release);
          }
+         if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->waiting_for_mount()) {
+             pthread_cond_signal(&jcr->read_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);
       }
@@ -305,6 +309,7 @@ static bool do_label(JCR *jcr, int relabel)
    POOLMEM *newname, *oldname, *poolname, *mtype;
    POOL_MEM dev_name;
    BSOCK *dir = jcr->dir_bsock;
+   DCR *dcr;
    DEVICE *dev;
    bool ok = false;
    int slot;
@@ -334,24 +339,27 @@ static bool do_label(JCR *jcr, int relabel)
       unbash_spaces(oldname);
       unbash_spaces(poolname);
       unbash_spaces(mtype);
-      dev = find_device(jcr, dev_name, drive);
-      if (dev) {
+      dcr = find_device(jcr, dev_name, drive);
+      if (dcr) {
+         dev = dcr->dev;
          P(dev->mutex);               /* Use P to avoid indefinite block */
          if (!dev->is_open()) {
             Dmsg0(400, "Can relabel. Device is not open\n");
-            label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
+            label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel);
             force_close_device(dev);
          /* Under certain "safe" conditions, we can steal the lock */
          } else if (dev->can_steal_lock()) {
             Dmsg0(400, "Can relabel. can_steal_lock\n");
-            label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
+            label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel);
          } else if (dev->is_busy() || dev->is_blocked()) {
             send_dir_busy_message(dir, dev);
          } else {                     /* device not being used */
             Dmsg0(400, "Can relabel. device not used\n");
-            label_volume_if_ok(jcr, dev, oldname, newname, poolname, slot, relabel);
+            label_volume_if_ok(dcr, oldname, newname, poolname, slot, relabel);
          }
          V(dev->mutex);
+         free_dcr(dcr);
+         jcr->dcr = NULL;
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), dev_name.c_str());
       }
@@ -374,21 +382,20 @@ 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,
+static void label_volume_if_ok(DCR *dcr, char *oldname,
                                char *newname, char *poolname,
                                int slot, int relabel)
 {
-   BSOCK *dir = jcr->dir_bsock;
+   BSOCK *dir = dcr->jcr->dir_bsock;
    bsteal_lock_t hold;
-   DCR *dcr = jcr->dcr;
+   DEVICE *dev = dcr->dev;
    int label_status;
 
-   dcr->dev = dev;
    steal_device_lock(dev, &hold, BST_WRITING_LABEL);
    Dmsg1(100, "Stole device %s lock, writing label.\n", dev->print_name());
 
    /* Note, try_autoload_device() opens the device */
-   if (!try_autoload_device(jcr, slot, newname)) {
+   if (!try_autoload_device(dcr->jcr, slot, newname)) {
       goto bail_out;                  /* error */
    }
 
@@ -479,11 +486,16 @@ static bool read_label(DCR *dcr)
    return ok;
 }
 
-static DEVICE *find_device(JCR *jcr, POOL_MEM &devname, int drive)
+/* 
+ * Searches for device by name, and if found, creates a dcr and
+ *  returns it.
+ */
+static DCR *find_device(JCR *jcr, POOL_MEM &devname, int drive)
 {
    DEVRES *device;
    AUTOCHANGER *changer;
    bool found = false;
+   DCR *dcr = NULL;
 
    unbash_spaces(devname);
    foreach_res(device, R_DEVICE) {
@@ -537,11 +549,11 @@ static DEVICE *find_device(JCR *jcr, POOL_MEM &devname, int drive)
 
    if (found) {
       Dmsg1(100, "Found changer device %s\n", device->hdr.name);
-      jcr->dcr = new_dcr(jcr, device->dev);
-      jcr->dcr->device = device;
-      return jcr->dcr->dev;
+      dcr = new_dcr(jcr, device->dev);
+      dcr->device = device;
+      jcr->dcr = dcr;
    }
-   return NULL;
+   return dcr;
 }
 
 
@@ -557,9 +569,9 @@ static bool mount_cmd(JCR *jcr)
    int drive;
 
    if (sscanf(dir->msg, "mount %127s drive=%d", devname.c_str(), &drive) == 2) {
-      dev = find_device(jcr, devname, drive);
-      dcr = jcr->dcr;
-      if (dev) { 
+      dcr = find_device(jcr, devname, drive);
+      if (dcr) {
+         dev = dcr->dev;
          P(dev->mutex);               /* Use P to avoid indefinite block */
          switch (dev->dev_blocked) {         /* device blocked? */
          case BST_WAITING_FOR_SYSOP:
@@ -667,6 +679,8 @@ static bool mount_cmd(JCR *jcr)
             break;
          }
          V(dev->mutex);
+         free_dcr(dcr);
+         jcr->dcr = NULL;
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
       }
@@ -686,11 +700,13 @@ static bool unmount_cmd(JCR *jcr)
    POOL_MEM devname;
    BSOCK *dir = jcr->dir_bsock;
    DEVICE *dev;
+   DCR *dcr;
    int drive;
 
    if (sscanf(dir->msg, "unmount %127s drive=%d", devname.c_str(), &drive) == 2) {
-      dev = find_device(jcr, devname, drive);
-      if (dev) {
+      dcr = find_device(jcr, devname, drive);
+      if (dcr) {
+         dev = dcr->dev;
          P(dev->mutex);               /* Use P to avoid indefinite block */
          if (!dev->is_open()) {
             if (!dev->is_busy()) {
@@ -739,6 +755,8 @@ static bool unmount_cmd(JCR *jcr)
                dev->print_name());
          }
          V(dev->mutex);
+         free_dcr(dcr);
+         jcr->dcr = NULL;
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
       }
@@ -763,11 +781,13 @@ static bool release_cmd(JCR *jcr)
    POOL_MEM devname;
    BSOCK *dir = jcr->dir_bsock;
    DEVICE *dev;
+   DCR *dcr;
    int drive;
 
    if (sscanf(dir->msg, "release %127s drive=%d", devname.c_str(), &drive) == 2) {
-      dev = find_device(jcr, devname, drive);
-      if (dev) {
+      dcr = find_device(jcr, devname, drive);
+      if (dcr) {
+         dev = dcr->dev;
          P(dev->mutex);               /* Use P to avoid indefinite block */
          if (!dev->is_open()) {
             Dmsg0(90, "Device already released\n");
@@ -798,6 +818,8 @@ static bool release_cmd(JCR *jcr)
                dev->print_name());
          }
          V(dev->mutex);
+         free_dcr(dcr);
+         jcr->dcr = NULL;
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
       }
@@ -835,9 +857,9 @@ static bool changer_cmd(JCR *jcr)
       ok = true;
    }
    if (ok) {
-      dev = find_device(jcr, devname, -1);
-      dcr = jcr->dcr;
-      if (dev) {
+      dcr = find_device(jcr, devname, -1);
+      if (dcr) {
+         dev = dcr->dev;
          P(dev->mutex);               /* Use P to avoid indefinite block */
          if (!dev->is_tape()) {
             bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"), 
@@ -851,6 +873,8 @@ static bool changer_cmd(JCR *jcr)
             autochanger_cmd(dcr, dir, cmd);
          }
          V(dev->mutex);
+         free_dcr(dcr);
+         jcr->dcr = NULL;
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
       }
@@ -871,13 +895,15 @@ static bool readlabel_cmd(JCR *jcr)
    POOL_MEM devname;
    BSOCK *dir = jcr->dir_bsock;
    DEVICE *dev;
+   DCR *dcr;
    int Slot;
    int drive;
 
    if (sscanf(dir->msg, "readlabel %127s Slot=%d drive=%d", devname.c_str(), 
        &Slot, &drive) == 3) {
-      dev = find_device(jcr, devname, drive);
-      if (dev) {
+      dcr = find_device(jcr, devname, drive);
+      if (dcr) {
+         dev = dcr->dev;
          P(dev->mutex);               /* Use P to avoid indefinite block */
          if (!dev->is_open()) {
             read_volume_label(jcr, dev, Slot);
@@ -891,6 +917,8 @@ static bool readlabel_cmd(JCR *jcr)
             read_volume_label(jcr, dev, Slot);
          }
          V(dev->mutex);
+         free_dcr(dcr);
+         jcr->dcr = NULL;
       } else {
          bnet_fsend(dir, _("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
       }
index 330ee30b9a15910c51f800c1e4d6ffc9a743ff5b..fbb609e085efa0acf713e4b3e06a111f1dc780ca 100644 (file)
@@ -284,7 +284,7 @@ static bool read_open_session(JCR *jcr)
       return false;
    }
 
-   if (sscanf(fd->msg, read_open, jcr->dcr->VolumeName, &jcr->read_VolSessionId,
+   if (sscanf(fd->msg, read_open, jcr->read_dcr->VolumeName, &jcr->read_VolSessionId,
          &jcr->read_VolSessionTime, &jcr->read_StartFile, &jcr->read_EndFile,
          &jcr->read_StartBlock, &jcr->read_EndBlock) == 7) {
       if (jcr->session_opened) {
@@ -292,7 +292,7 @@ static bool read_open_session(JCR *jcr)
          return false;
       }
       Dmsg4(100, "read_open_session got: JobId=%d Vol=%s VolSessId=%ld VolSessT=%ld\n",
-         jcr->JobId, jcr->dcr->VolumeName, jcr->read_VolSessionId,
+         jcr->JobId, jcr->read_dcr->VolumeName, jcr->read_VolSessionId,
          jcr->read_VolSessionTime);
       Dmsg4(100, "  StartF=%ld EndF=%ld StartB=%ld EndB=%ld\n",
          jcr->read_StartFile, jcr->read_EndFile, jcr->read_StartBlock,
index 9eb1d6780c5cf565b3182ec58ca2f3a038cbb4b1..5faac87ba3be40f5f6ce935fb2f3a016de7e623e 100644 (file)
@@ -137,7 +137,7 @@ bool run_cmd(JCR *jcr)
    Dmsg1(100, "Run_cmd: %s\n", jcr->dir_bsock->msg);
    /* The following jobs don't need the FD */
    switch (jcr->JobType) {
-   case JT_MIGRATION:
+   case JT_MIGRATE:
    case JT_COPY:
    case JT_ARCHIVE:
       jcr->authenticated = true;
@@ -346,5 +346,9 @@ void stored_free_jcr(JCR *jcr)
       free_dcr(jcr->dcr);
       jcr->dcr = NULL;
    }
+   if (jcr->read_dcr) {
+      free_dcr(jcr->read_dcr);
+      jcr->read_dcr = NULL;
+   }
    return;
 }
index 6becec33771c3103425a0a03a1ce14d6c60a2b6b..2eb35186655f1390907607a4d528f77e33c180ff 100644 (file)
@@ -41,7 +41,7 @@ bool do_read_data(JCR *jcr)
 {
    BSOCK *fd = jcr->file_bsock;
    bool ok = true;
-   DCR *dcr = jcr->dcr;
+   DCR *dcr = jcr->read_dcr;
 
    Dmsg0(20, "Start read data.\n");
 
index ccd8527da65269ec1712d4f5b78ac8a7886c8b59..55a903a3f1be887cf62f0125105b26ef904fb931 100644 (file)
@@ -450,7 +450,6 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
 {
    bool first = true;
    bool ok;
-   DCR *dcr = NULL;
    DIRSTORE *store;
    char *device_name;
 
@@ -496,9 +495,6 @@ bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
       }
 #endif
    }
-   if (dcr) {
-      free_dcr(dcr);
-   }
    return ok;
 }
 
@@ -539,10 +535,7 @@ static int search_res_for_device(RCTX &rctx)
          foreach_alist(rctx.device, changer->device) {
             Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
             stat = reserve_device(rctx);
-            if (stat == -1) {            /* hard error */
-               return -1;
-            }
-            if (stat == 0) {             /* must wait, try next one */
+            if (stat != 1) {             /* try another device */
                continue;
             }
             POOL_MEM dev_name;
@@ -599,7 +592,6 @@ static int reserve_device(RCTX &rctx)
       Dmsg1(100, ">dird: %s", dir->msg);
       return -1;
    }
-   rctx.jcr->dcr = dcr;
    bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
    bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
    bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
@@ -617,12 +609,18 @@ static int reserve_device(RCTX &rctx)
         }
       }
       ok = reserve_device_for_append(dcr, rctx);
+      if (ok) {
+         rctx.jcr->dcr = dcr;
+      }
       Dmsg3(200, "dev_name=%s mediatype=%s ok=%d\n", dcr->dev_name, dcr->media_type, ok);
    } else {
       ok = reserve_device_for_read(dcr);
+      if (ok) {
+         rctx.jcr->read_dcr = dcr;
+      }
    }
    if (!ok) {
-      free_dcr(rctx.jcr->dcr);
+      free_dcr(dcr);
       return 0;
    }
    return 1;
index c4fd2641ba515279d2f54d0c95e2fbb024ad3f4d..cd73dea27b6df7b41a0e040d8df0c1cfd43f6054 100644 (file)
@@ -196,7 +196,8 @@ static bool despool_data(DCR *dcr, bool commit)
 
    Dmsg0(100, "Despooling data\n");
    if (commit) {
-      Jmsg(jcr, M_INFO, 0, _("Committing spooled data to Volume. Despooling %s bytes ...\n"),
+      Jmsg(jcr, M_INFO, 0, _("Committing spooled data to Volume \"%s\". Despooling %s bytes ...\n"),
+         jcr->dcr->VolumeName,
          edit_uint64_with_commas(jcr->dcr->job_spool_size, ec1));
    }
    else {
index de80fd34b048d93cbee6311e11defd7956e5ca7c..6be4e9a6cd0f6ad162d9e789229ed61bd30f781d 100644 (file)
@@ -264,7 +264,7 @@ static void list_running_jobs(BSOCK *user)
    bool found = false;
    int bps, sec;
    JCR *jcr;
-   DCR *dcr;
+   DCR *dcr, *rdcr;
    char JobName[MAX_NAME_LENGTH];
    char b1[30], b2[30], b3[30];
 
@@ -275,7 +275,8 @@ static void list_running_jobs(BSOCK *user)
             job_type_to_str(jcr->JobType), jcr->Job);
       }
       dcr = jcr->dcr;
-      if (dcr && dcr->device) {
+      rdcr = jcr->read_dcr;
+      if ((dcr && dcr->device) || rdcr && rdcr->device) {
          bstrncpy(JobName, jcr->Job, sizeof(JobName));
          /* There are three periods after the Job name */
          char *p;
@@ -284,7 +285,20 @@ static void list_running_jobs(BSOCK *user)
                *p = 0;
             }
          }
-         bnet_fsend(user, _("%s %s job %s JobId=%d Volume=\"%s\"\n"
+         if (rdcr && rdcr->device) {
+            bnet_fsend(user, _("Reading: %s %s job %s JobId=%d Volume=\"%s\"\n"
+                            "    pool=\"%s\" device=\"%s\"\n"),
+                   job_level_to_str(jcr->JobLevel),
+                   job_type_to_str(jcr->JobType),
+                   JobName,
+                   jcr->JobId,
+                   rdcr->VolumeName,
+                   rdcr->pool_name,
+                   rdcr->dev?rdcr->dev->print_name(): 
+                            rdcr->device->device_name);
+         }
+         if (dcr && dcr->device) {
+            bnet_fsend(user, _("Writing: %s %s job %s JobId=%d Volume=\"%s\"\n"
                             "    pool=\"%s\" device=\"%s\"\n"),
                    job_level_to_str(jcr->JobLevel),
                    job_type_to_str(jcr->JobType),
@@ -294,6 +308,7 @@ static void list_running_jobs(BSOCK *user)
                    dcr->pool_name,
                    dcr->dev?dcr->dev->print_name(): 
                             dcr->device->device_name);
+         }
          sec = time(NULL) - jcr->run_time;
          if (sec <= 0) {
             sec = 1;
index 11f31b2209c232262b802214b104aae087e2be03..9b0ab92f4f3e88682ff4e0e3587688dfd0741730 100644 (file)
@@ -468,6 +468,7 @@ void *device_initialization(void *arg)
             Jmsg1(NULL, M_ERROR, 0, _("Could not open device %s\n"), dev->print_name());
             Dmsg1(20, "Could not open device %s\n", dev->print_name());
             free_dcr(dcr);
+            jcr->dcr = NULL;
             continue;
          }
       }
@@ -482,6 +483,7 @@ void *device_initialization(void *arg)
          }
       }
       free_dcr(dcr);
+      jcr->dcr = NULL;
    }
    free_jcr(jcr); 
    init_done = true;
@@ -526,6 +528,10 @@ void terminate_stored(int sig)
                pthread_cond_broadcast(&jcr->dcr->dev->wait_next_vol);
                pthread_cond_broadcast(&wait_device_release);
             }
+            if (jcr->read_dcr && jcr->read_dcr->dev && jcr->read_dcr->dev->dev_blocked) {
+               pthread_cond_broadcast(&jcr->read_dcr->dev->wait_next_vol);
+               pthread_cond_broadcast(&wait_device_release);
+            }
             bmicrosleep(0, 50000);
          }
          free_jcr(jcr);
index c308c8273e62e4f6c93b43f2908411d89ac9375a..4058a040e2d8abac4ef0924aa02f7d0767d7fdb1 100644 (file)
@@ -3,9 +3,9 @@
  */
 
 #undef  VERSION
-#define VERSION "1.39.0"
-#define BDATE   "20 November 2005"
-#define LSMDATE "20Nov05"
+#define VERSION "1.39.1"
+#define BDATE   "29 November 2005"
+#define LSMDATE "29Nov05"
 
 /* Debug flags */
 #undef  DEBUG