]> git.sur5r.net Git - bacula/bacula/commitdiff
- Fix Media LabelDate and FirstWritten to be correctly set.
authorKern Sibbald <kern@sibbald.com>
Tue, 15 Feb 2005 22:04:34 +0000 (22:04 +0000)
committerKern Sibbald <kern@sibbald.com>
Tue, 15 Feb 2005 22:04:34 +0000 (22:04 +0000)
- Fix deadlock in multiple simultaneous jobs.
- Fix tape truncation/number of files after restore bug.

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

21 files changed:
bacula/kernstodo
bacula/patches/1.36.1-truncate.patch [new file with mode: 0644]
bacula/patches/patches-1.36.1
bacula/src/cats/cats.h
bacula/src/cats/make_mysql_tables.in
bacula/src/cats/sql_create.c
bacula/src/cats/sql_get.c
bacula/src/cats/sql_update.c
bacula/src/cats/update_mysql_tables.in
bacula/src/dird/catreq.c
bacula/src/dird/jobq.c
bacula/src/dird/recycle.c
bacula/src/dird/sql_cmds.c
bacula/src/dird/ua_label.c
bacula/src/stored/block.c
bacula/src/stored/bls.c
bacula/src/stored/btape.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/read_record.c
bacula/src/stored/status.c

index dade3954dd6a91b7cf24a2c7347b2af7d374473a..f5c584c4132f03823b6a5c4de221bc97c2646233 100644 (file)
@@ -30,6 +30,16 @@ Suggestions for Preben:
 - Optimized bootstrap.
 
 For 1.37:
+- Windows restore:
+  data-fd: RestoreFiles.2004-12-07_15.56.42 Error:
+  > ..\findlib\../../findlib/create_file.c:275 Could not open e:/: ERR=Der
+  > Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen
+  > Prozess verwendet wird.
+  Restore restores all files, but then fails at the end.
+- Add better documentation on how restores can be done
+  from failed jobs.
+- Resolve the problem between Device name and Archive name,
+  and fix SD messages.
 - Make sure SD deletes spool files on error exit.
 - Delete old spool files when SD starts.
 - When Python creates a new label, the tape is immediately
diff --git a/bacula/patches/1.36.1-truncate.patch b/bacula/patches/1.36.1-truncate.patch
new file mode 100644 (file)
index 0000000..a66a1e5
--- /dev/null
@@ -0,0 +1,24 @@
+
+ This patch fixes a bug where a tape gets "truncated" after
+ doing a restore. The number of files in the catalog do not
+ agree with what Bacula thinks is on tape, then the tape is
+ marked in error.
+ Apply this patch to version 1.36.1 with:
+
+ cd <bacula>
+ patch -p0 <1.36.1-truncate.patch
+ make
+ ...
+
+
+--- src/stored/read_record.c.orig      2004-09-29 21:11:17.000000000 +0200
++++ src/stored/read_record.c   2005-02-15 13:22:12.723140229 +0100
+@@ -266,7 +266,7 @@
+       Dmsg2(300, "Current postion (file:block) %d:%d\n",
+        dev->file, dev->block_num);
+       jcr->bsr->mount_next_volume = false;
+-      dev->state |= ST_EOT;
++//    dev->state |= ST_EOT;
+       rec->Block = 0;
+       return 1;
+    }   
index d339716528ffa7b9d894f2709985d60231340e62..1a41d7c87fd7cdef22ee0fa7495d87cadbe65116 100644 (file)
@@ -32,3 +32,9 @@
  in the incorrect name being used for the check.
  This could lead to security problems with unwanted 
  access by restricted consoles.
+
+15Feb05 1.36.1-truncate.patch
+ This patch fixes a bug where a tape gets "truncated" after
+ doing a restore. The number of files in the catalog do not
+ agree with what Bacula thinks is on tape, then the tape is
+ marked in error.
index a912098ce67f0cbd5d1f8544f8a48bfe9d2b0c60..bcbffd527679d01f153f5db9bf15c24d516ed87f 100644 (file)
@@ -728,7 +728,9 @@ struct MEDIA_DBR {
     */
    char    cFirstWritten[MAX_TIME_LENGTH]; /* FirstWritten returned from DB */
    char    cLastWritten[MAX_TIME_LENGTH];  /* LastWritten returned from DB */
-   char    cLabelData[MAX_TIME_LENGTH];    /* LabelData returned from DB */
+   char    cLabelDate[MAX_TIME_LENGTH];    /* LabelData returned from DB */
+   bool    set_first_written;                
+   bool    set_label_date;
 };
 
 /* Client record -- same as the database */
index 425382102b2807ad41dc8379150f18c34821eb23..8877617421fa32f125003efb822b05aaa70aa4de 100644 (file)
@@ -45,6 +45,8 @@ CREATE TABLE File (
 #  INDEX (FilenameId),
 #  INDEX (JobId, PathId, FilenameId)
 #
+# Adding an index on JobId can speed up pruning
+#
 
 CREATE TABLE Job (
    JobId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
index 4dd809878aafbbbbbc072fb55f25051d532c10d3..1265d78a057e83bb785b157759a4f35ec2bcbd2c 100644 (file)
@@ -415,8 +415,11 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
    } else {
       mr->MediaId = sql_insert_id(mdb, _("Media"));
       stat = 1;
-      if (mr->LabelDate) {
+      if (mr->set_label_date) {
         char dt[MAX_TIME_LENGTH];
+        if (mr->LabelDate == 0) {
+           mr->LabelDate = time(NULL);
+        }
         localtime_r(&mr->LabelDate, &tm);
          strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
          Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' "
index 9d707d71b21143ba0928ee8d8dfed0ca2b208ae6..968ebd865db5c6ecd986f29a9ed8798fb6aba532 100644 (file)
@@ -835,7 +835,7 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
          "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
          "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
          "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
-         "EndFile,EndBlock,VolParts,LabelType "
+         "EndFile,EndBlock,VolParts,LabelType,LabelDate "
          "FROM Media WHERE MediaId=%s", 
         edit_int64(mr->MediaId, ed1));
    } else {                          /* find by name */
@@ -843,7 +843,7 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
          "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes,"
          "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs,"
          "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger,"
-         "EndFile,EndBlock,VolParts,LabelType "
+         "EndFile,EndBlock,VolParts,LabelType,LabelDate "
          "FROM Media WHERE VolumeName='%s'", mr->VolumeName);
    }
 
@@ -889,6 +889,8 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
            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);
            stat = mr->MediaId;
         }
       } else {
index 7557d5f759157253cd4c2a2c003a87f253cc9899..f02578ff05490b30a2c8e8b866c02d7940d4a6f5 100644 (file)
@@ -276,7 +276,7 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
 
    Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten);
    db_lock(mdb);
-   if (mr->VolJobs == 1) {
+   if (mr->set_first_written) {
       Dmsg1(400, "Set FirstWritten Vol=%s\n", mr->VolumeName);
       ttime = mr->FirstWritten;
       localtime_r(&ttime, &tm);
@@ -284,11 +284,11 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
       Mmsg(mdb->cmd, "UPDATE Media SET FirstWritten='%s'"
            " WHERE VolumeName='%s'", dt, mr->VolumeName);
       stat = UPDATE_DB(jcr, mdb, mdb->cmd);
-      Dmsg1(400, "Firstwritten stat=%d\n", stat);
+      Dmsg1(400, "Firstwritten=%d\n", mr->FirstWritten);
    }
 
    /* Label just done? */
-   if (mr->VolBytes == 1) {
+   if (mr->set_label_date) {
       ttime = mr->LabelDate;
       if (ttime == 0) {
         ttime = time(NULL);
index 0ff6b4146d8800d3a7f20b3613e97f26e5acb244..d088d834691315323101c417f66c2143cf04094d 100755 (executable)
@@ -17,7 +17,7 @@ ALTER TABLE Pool  ADD COLUMN LabelType INTEGER UNSIGNED NOT NULL DEFAULT 0;
 ALTER TABLE Media ADD COLUMN VolParts INTEGER UNSIGNED NOT NULL DEFAULT 0;
 
 CREATE TABLE MediaType (
-   MediaTypeId INTERGER UNSIGNED NOT NULL AUTO_INCREMENT,
+   MediaTypeId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    MediaType VARCHAR(128) NOT NULL,
    ReadOnly TINYINT DEFAULT 0,
    PRIMARY KEY(MediaTypeId)
@@ -26,7 +26,7 @@ CREATE TABLE MediaType (
 CREATE TABLE Device (
    DeviceId INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
    Name VARCHAR(128) NOT NULL,
-   MediaTypeId INTEGER UNSIGNED REFERENCES MediaType NOT NULL,
+   MediaTypeId INTEGER UNSIGNED NOT NULL REFERENCES MediaType,
    StorageId INTEGER UNSIGNED REFERENCES Storage,
    DevMounts INTEGER UNSIGNED DEFAULT 0,
    DevReadBytes BIGINT UNSIGNED DEFAULT 0,
index 21d759e6e47aa1f7e945526e21f7da9d52af3198..a1eb4fc92684082fe7500ad7979f2a8a464c1403 100644 (file)
@@ -106,6 +106,14 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
     * Request to find next appendable Volume for this Job
     */
    Dmsg1(400, "catreq %s", bs->msg);
+   if (!jcr->db) {
+      omsg = get_memory(bs->msglen+1);
+      pm_strcpy(omsg, bs->msg);
+      bnet_fsend(bs, "1990 Invalid Catalog Request: %s", omsg);    
+      Jmsg1(jcr, M_FATAL, 0, _("Invalid Catalog request; DB not open: %s"), omsg);
+      free_memory(omsg);
+      return;
+   }
    if (sscanf(bs->msg, Find_media, &Job, &index) == 2) {
       ok = find_next_volume_for_append(jcr, &mr, true /*permit create new vol*/);
       /*
@@ -177,7 +185,6 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
          bnet_fsend(bs, "1997 Volume \"%s\" not in catalog.\n", mr.VolumeName);
       }
 
-
    /*
     * Request to update Media record. Comes typically at the end
     *  of a Storage daemon Job Session, when labeling/relabeling a
@@ -203,13 +210,15 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
         return;
       }
       /* Set first written time if this is first job */
-      if (mr.VolJobs == 0 || sdmr.VolJobs == 1) {
+      if (mr.FirstWritten == 0) {
         mr.FirstWritten = jcr->start_time;   /* use Job start time as first write */
+        mr.set_first_written = true;
       }
       /* If we just labeled the tape set time */
-      Dmsg2(400, "label=%d labeldate=%d\n", label, mr.LabelDate);
       if (label || mr.LabelDate == 0) {
-        mr.LabelDate = time(NULL);
+        mr.LabelDate = jcr->start_time;
+        mr.set_label_date = true;
+         Dmsg2(400, "label=%d labeldate=%d\n", label, mr.LabelDate);
       } else {
         /*
          * Insanity check for VolFiles get set to a smaller value
@@ -246,7 +255,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
       } else if (db_update_media_record(jcr, jcr->db, &mr)) {
         send_volume_info_to_storage_daemon(jcr, bs, &mr);
       } else {
-         Jmsg(jcr, M_ERROR, 0, _("Catalog error updating Media record. %s"),
+         Jmsg(jcr, M_FATAL, 0, _("Catalog error updating Media record. %s"),
            db_strerror(jcr->db));
          bnet_fsend(bs, "1992 Update Media error\n");
          Dmsg0(400, "send error\n");
@@ -265,7 +274,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
       Dmsg6(400, "create_jobmedia JobId=%d MediaId=%d SF=%d EF=%d FI=%d LI=%d\n",
         jm.JobId, jm.MediaId, jm.StartFile, jm.EndFile, jm.FirstIndex, jm.LastIndex);
       if (!db_create_jobmedia_record(jcr, jcr->db, &jm)) {
-         Jmsg(jcr, M_ERROR, 0, _("Catalog error creating JobMedia record. %s"),
+         Jmsg(jcr, M_FATAL, 0, _("Catalog error creating JobMedia record. %s"),
            db_strerror(jcr->db));
          bnet_fsend(bs, "1991 Update JobMedia error\n");
       } else {
@@ -277,7 +286,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg)
       omsg = get_memory(bs->msglen+1);
       pm_strcpy(omsg, bs->msg);
       bnet_fsend(bs, "1990 Invalid Catalog Request: %s", omsg);
-      Jmsg1(jcr, M_ERROR, 0, _("Invalid Catalog request: %s"), omsg);
+      Jmsg1(jcr, M_FATAL, 0, _("Invalid Catalog request: %s"), omsg);
       free_memory(omsg);
    }
    Dmsg1(400, ">CatReq response: %s", bs->msg);
index eea66c004acb22c79241d9ee06a0398271949b18..1a9954c8c30d1b8c7d80c43eb5ce48779bdc0785 100755 (executable)
@@ -437,12 +437,7 @@ void *jobq_server(void *arg)
          Dmsg1(2300, "Took jobid=%d from ready and appended to run\n", jcr->JobId);
 
         /* Release job queue lock */
-        if ((stat = pthread_mutex_unlock(&jq->mutex)) != 0) {
-           berrno be;
-            Jmsg1(NULL, M_ERROR, 0, "pthread_mutex_unlock: ERR=%s\n", be.strerror(stat));
-           jq->num_workers--;
-           return NULL;
-        }
+        V(jq->mutex);
 
          /* Call user's routine here */
          Dmsg1(2300, "Calling user engine for jobid=%d\n", jcr->JobId);
@@ -451,13 +446,7 @@ void *jobq_server(void *arg)
          Dmsg1(2300, "Back from user engine jobid=%d.\n", jcr->JobId);
 
         /* Reacquire job queue lock */
-        if ((stat = pthread_mutex_lock(&jq->mutex)) != 0) {
-           berrno be;
-            Jmsg1(NULL, M_ERROR, 0, "pthread_mutex_lock: ERR=%s\n", be.strerror(stat));
-           jq->num_workers--;
-           free(je);                 /* release job entry */
-           return NULL;
-        }
+        P(jq->mutex);
          Dmsg0(200, "Done lock mutex after running job. Release locks.\n");
         jq->running_jobs->remove(je);
         /*
@@ -467,9 +456,6 @@ void *jobq_server(void *arg)
          */
         if (jcr->acquired_resource_locks) {
            jcr->store->NumConcurrentJobs--;
-           if (jcr->JobType == JT_RESTORE || jcr->JobType == JT_VERIFY) {
-              jcr->store->MaxConcurrentJobs = jcr->saveMaxConcurrentJobs;
-           }
            jcr->client->NumConcurrentJobs--;
            jcr->job->NumConcurrentJobs--;
         }
@@ -574,9 +560,7 @@ void *jobq_server(void *arg)
            if (jcr->JobType == JT_RESTORE || jcr->JobType == JT_VERIFY) {
               /* Let only one Restore/verify job run at a time regardless of MaxConcurrentJobs */
               if (jcr->store->NumConcurrentJobs == 0) {
-                 jcr->store->NumConcurrentJobs++;
-                 jcr->saveMaxConcurrentJobs = jcr->store->MaxConcurrentJobs;
-                 jcr->store->MaxConcurrentJobs = 1;
+                 jcr->store->NumConcurrentJobs = 1;
               } else {
                  set_jcr_job_status(jcr, JS_WaitStoreRes);
                  je = jn;            /* point to next waiting job */
@@ -609,6 +593,8 @@ void *jobq_server(void *arg)
                if (!skip_this_jcr) {
                   jcr->store->NumConcurrentJobs++;
                }
+           } else {
+              skip_this_jcr = true;
            }
            if (skip_this_jcr) {
               set_jcr_job_status(jcr, JS_WaitStoreRes);
@@ -621,9 +607,6 @@ void *jobq_server(void *arg)
            } else {
               /* Back out previous locks */
               jcr->store->NumConcurrentJobs--;
-              if (jcr->JobType == JT_RESTORE || jcr->JobType == JT_VERIFY) {
-                 jcr->store->MaxConcurrentJobs = jcr->saveMaxConcurrentJobs;
-              }
               set_jcr_job_status(jcr, JS_WaitClientRes);
               je = jn;               /* point to next waiting job */
               continue;
@@ -633,9 +616,6 @@ void *jobq_server(void *arg)
            } else {
               /* Back out previous locks */
               jcr->store->NumConcurrentJobs--;
-              if (jcr->JobType == JT_RESTORE || jcr->JobType == JT_VERIFY) {
-                 jcr->store->MaxConcurrentJobs = jcr->saveMaxConcurrentJobs;
-              }
               jcr->client->NumConcurrentJobs--;
               set_jcr_job_status(jcr, JS_WaitJobRes);
               je = jn;               /* Point to next waiting job */
index bb6c7987f9e4eab4e1e0a3a80454f2d8e90908a1..a4e15bb9065a9853ee497b888daaa4f0d785df20 100644 (file)
@@ -119,5 +119,6 @@ int recycle_volume(JCR *jcr, MEDIA_DBR *mr)
    mr->VolJobs = mr->VolFiles = mr->VolBlocks = mr->VolErrors = 0;
    mr->VolBytes = 1;
    mr->FirstWritten = mr->LastWritten = 0;
+   mr->set_first_written = true;
    return db_update_media_record(jcr, jcr->db, mr);
 }
index 0aa0720ecde3ce115e9b40b6f3f65bcc8f21515a..b33bbd24d1c7770891ebcfaff4c9cf638da2b614 100644 (file)
@@ -359,7 +359,6 @@ const char *uar_jobids_fileindex =
    "ORDER BY Job.StartTime DESC LIMIT 1";
 
 /* Query to get all files in a directory -- no recursing */
-// cleanup needed -- add client, ...
 const char *uar_jobid_fileindex_from_dir = 
    "SELECT Job.JobId,File.FileIndex FROM Job,File,Path,Filename,Client "
    "WHERE Job.JobId IN (%s) "
index f73e192b6810bdaad402f6b58ef86698dded2a30..423678c9338ca960c72a19afc2d81a96bb5c371e 100644 (file)
@@ -621,6 +621,7 @@ static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
    unbash_spaces(mr->MediaType);
    unbash_spaces(pr->Name);
    mr->LabelDate = time(NULL);
+   mr->set_label_date = true;
    if (ok) {
       if (media_record_exists) {      /* we update it */
         mr->VolBytes = 1;
index c1317da712b4ca0f6f8ada930c98b29be855cd25..47efa0ff00c7627e12bada0d4dc908b1eba8e93a 100644 (file)
@@ -34,6 +34,8 @@
 
 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);
 
 /*
  * Dump the block header, then walk through
@@ -477,99 +479,21 @@ bool write_block_to_dev(DCR *dcr)
        (dev->file_size+block->binbuf) >= dev->max_file_size) {
       dev->file_size = 0;            /* reset file size */
 
-      if (dev->is_tape() && weof_dev(dev, 1) != 0) {           /* write eof */
+      if (weof_dev(dev, 1) != 0) {           /* write eof */
          Dmsg0(190, "WEOF error in max file size.\n");
         terminate_writing_volume(dcr);
         dev->dev_errno = ENOSPC;
         return false;
       }
 
-      /* Create a JobMedia record so restore can seek */
-      if (!dir_create_jobmedia_record(dcr)) {
-         Dmsg0(190, "Error from create_job_media.\n");
-        dev->dev_errno = EIO;
-          Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
-              dcr->VolCatInfo.VolCatName, jcr->Job);
-         terminate_writing_volume(dcr);
-         dev->dev_errno = EIO;
-         return false;
-      }
-      dev->VolCatInfo.VolCatFiles = dev->file;
-      if (!dir_update_volume_info(dcr, false)) {
-         Dmsg0(190, "Error from update_vol_info.\n");
-        terminate_writing_volume(dcr);
-        dev->dev_errno = EIO;
-        return false;
-      }
-      Dmsg0(100, "dir_update_volume_info max file size -- OK\n");
-
-
-      /*
-       * Walk through all attached dcrs setting flag to call
-       * set_new_file_parameters() when that dcr is next used.
-       */
-      DCR *mdcr;
-      foreach_dlist(mdcr, dev->attached_dcrs) {
-        if (mdcr->jcr->JobId == 0) {
-           continue;
-        }
-        mdcr->NewFile = true;        /* set reminder to do set_new_file_params */
-      }
-      /* Set new file/block parameters for current dcr */
-      set_new_file_parameters(dcr);
-   }
-   
-   /* Limit maximum part size to value specified by user (not applicable to tapes/fifos) */
-   if (!(dev->state & (ST_TAPE|ST_FIFO)) && 
-        (dev->max_part_size > 0) &&
-       ((dev->part_size + block->binbuf) >= dev->max_part_size)) {
-      if (dev->part < dev->num_parts) {
-         Jmsg3(dcr->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_name(dev));
-        dev->dev_errno = EIO;
-        return false;
-      }
-      
-      if (open_next_part(dev) < 0) {
-         Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s. ERR=%s\n"),
-               dev_name(dev), strerror_dev(dev));
-        dev->dev_errno = EIO;
-        return false;
-      }
-      
-      dev->VolCatInfo.VolCatParts = dev->num_parts;
-           
-      if (!dir_update_volume_info(dcr, false)) {
-         Dmsg0(190, "Error from update_vol_info.\n");
-        dev->dev_errno = EIO;
+      if (!do_new_file_bookkeeping(dcr)) {
         return false;
       }
    }
    
-   if (dev->free_space_errno < 0) { /* Error while getting free space */
-      char ed1[50], ed2[50];
-      Dmsg1(10, "Cannot get free space on the device ERR=%s.\n", dev->errmsg);
-      Jmsg(jcr, M_FATAL, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d, errmsg=%s).\n"),
-          dev->VolCatInfo.VolCatName,
-          dev->file, dev->block_num, dev->dev_name,
-          edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
-          dev->free_space_errno, dev->errmsg);
-      dev->dev_errno = -dev->free_space_errno;
+   if (!do_dvd_size_checks(dcr)) {
       return false;
    }
-   
-   if (((dev->free_space_errno > 0) && ((dev->part_size + block->binbuf) >= dev->free_space))) {
-      char ed1[50], ed2[50];
-      Dmsg0(10, "==== Just enough free space on the device to write the current part...\n");
-      Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d).\n"),
-           dev->VolCatInfo.VolCatName,
-           dev->file, dev->block_num, dev->dev_name,
-           edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
-           dev->free_space_errno);
-      terminate_writing_volume(dcr);
-      dev->dev_errno = ENOSPC;
-      return false;
-   }   
 
    dev->VolCatInfo.VolCatWrites++;
    Dmsg1(300, "Write block of %u bytes\n", wlen);
@@ -766,12 +690,118 @@ static bool terminate_writing_volume(DCR *dcr)
       Jmsg(dcr->jcr, M_ERROR, 0, "%s", dev->errmsg);
    }
 bail_out:
-   dev->state |= (ST_EOF|ST_EOT|ST_WEOT);
-   dev->state &= ~ST_APPEND;         /* make tape read-only */
+   dev->set_eot();
    Dmsg1(100, "Leave terminate_writing_volume -- %s\n", ok?"OK":"ERROR");
    return ok;
 }
 
+/*
+ * Do bookkeeping when a new file is created on a Volume. This is
+ *  also done for disk files to generate the jobmedia records for
+ *  quick seeking.
+ */
+static bool do_new_file_bookkeeping(DCR *dcr) 
+{
+   DEVICE *dev = dcr->dev;
+   JCR *jcr = dcr->jcr;
+
+   /* Create a JobMedia record so restore can seek */
+   if (!dir_create_jobmedia_record(dcr)) {
+      Dmsg0(190, "Error from create_job_media.\n");
+      dev->dev_errno = EIO;
+       Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
+           dcr->VolCatInfo.VolCatName, jcr->Job);
+       terminate_writing_volume(dcr);
+       dev->dev_errno = EIO;
+       return false;
+   }
+   dev->VolCatInfo.VolCatFiles = dev->file;
+   if (!dir_update_volume_info(dcr, false)) {
+      Dmsg0(190, "Error from update_vol_info.\n");
+      terminate_writing_volume(dcr);
+      dev->dev_errno = EIO;
+      return false;
+   }
+   Dmsg0(100, "dir_update_volume_info max file size -- OK\n");
+
+   /*
+    * Walk through all attached dcrs setting flag to call
+    * set_new_file_parameters() when that dcr is next used.
+    */
+   DCR *mdcr;
+   foreach_dlist(mdcr, dev->attached_dcrs) {
+      if (mdcr->jcr->JobId == 0) {
+        continue;
+      }
+      mdcr->NewFile = true;       /* set reminder to do set_new_file_params */
+   }
+   /* Set new file/block parameters for current dcr */
+   set_new_file_parameters(dcr);
+   return true;
+}
+
+/*
+ * Do all checks for DVD sizes during writing.
+ */
+static bool do_dvd_size_checks(DCR *dcr) 
+{
+   DEVICE *dev = dcr->dev;
+   JCR *jcr = dcr->jcr;
+   DEV_BLOCK *block = dcr->block;
+
+   /* Limit maximum part size to value specified by user (not applicable to tapes/fifos) */
+   if (!(dev->state & (ST_TAPE|ST_FIFO)) && dev->max_part_size > 0 &&
+       (dev->part_size + block->binbuf) >= dev->max_part_size) {
+      if (dev->part < dev->num_parts) {
+         Jmsg3(dcr->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_name(dev));
+        dev->dev_errno = EIO;
+        return false;
+      }
+      
+      if (open_next_part(dev) < 0) {
+         Jmsg2(dcr->jcr, M_FATAL, 0, _("Unable to open device next part %s. ERR=%s\n"),
+               dev_name(dev), strerror_dev(dev));
+        dev->dev_errno = EIO;
+        return false;
+      }
+      
+      dev->VolCatInfo.VolCatParts = dev->num_parts;
+           
+      if (!dir_update_volume_info(dcr, false)) {
+         Dmsg0(190, "Error from update_vol_info.\n");
+        dev->dev_errno = EIO;
+        return false;
+      }
+   }
+   
+   if (dev->free_space_errno < 0) { /* Error while getting free space */
+      char ed1[50], ed2[50];
+      Dmsg1(10, "Cannot get free space on the device ERR=%s.\n", dev->errmsg);
+      Jmsg(jcr, M_FATAL, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d, errmsg=%s).\n"),
+          dev->VolCatInfo.VolCatName,
+          dev->file, dev->block_num, dev->dev_name,
+          edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
+          dev->free_space_errno, dev->errmsg);
+      dev->dev_errno = -dev->free_space_errno;
+      return false;
+   }
+   
+   if ((dev->free_space_errno > 0 && (dev->part_size + block->binbuf) >= dev->free_space)) {
+      char ed1[50], ed2[50];
+      Dmsg0(10, "==== Just enough free space on the device to write the current part...\n");
+      Jmsg(jcr, M_INFO, 0, _("End of Volume \"%s\" at %u:%u on device %s (part_size=%s, free_space=%s, free_space_errno=%d).\n"),
+           dev->VolCatInfo.VolCatName,
+           dev->file, dev->block_num, dev->dev_name,
+           edit_uint64_with_commas(dev->part_size, ed1), edit_uint64_with_commas(dev->free_space, ed2),
+           dev->free_space_errno);
+      terminate_writing_volume(dcr);
+      dev->dev_errno = ENOSPC;
+      return false;
+   }   
+   return true;
+}
+
 
 /*
  * Read block with locking
index 68474d9cb85ddcdb3290af952e44e7328913249b..071125983367177e4dd6f0866f3ad23acb4e64b3 100644 (file)
@@ -257,7 +257,7 @@ static void do_blocks(char *infname)
    for ( ;; ) {
       if (!read_block_from_device(dcr, NO_BLOCK_NUMBER_CHECK)) {
          Dmsg1(100, "!read_block(): ERR=%s\n", dev->strerror());
-        if (dev->at_eom()) {
+        if (dev->at_eot()) {
            if (!mount_next_read_volume(dcr)) {
                Jmsg(jcr, M_INFO, 0, _("Got EOM at file %u on device %s, Volume \"%s\"\n"),
                  dev->file, dev_name(dev), dcr->VolumeName);
index dad98ef73967f8d557639f9fd7887b93ffede686..c59f8dfef2d50eea56d4c6dc9f257acaf732b996 100644 (file)
@@ -562,7 +562,7 @@ static void capcmd()
    printf("%sMALLOC ", dev->state & ST_MALLOC ? "" : "!");
    printf("%sAPPEND ", dev->can_append() ? "" : "!");
    printf("%sREAD ", dev->can_read() ? "" : "!");
-   printf("%sEOT ", dev->at_eom() ? "" : "!");
+   printf("%sEOT ", dev->at_eot() ? "" : "!");
    printf("%sWEOT ", dev->state & ST_WEOT ? "" : "!");
    printf("%sEOF ", dev->at_eof() ? "" : "!");
    printf("%sNEXTVOL ", dev->state & ST_NEXTVOL ? "" : "!");
index 6397ba74513ab152927a066b70cc2566f018df2d..32017d375c02a45b09645ab1033c8da9af2588ab 100644 (file)
@@ -458,7 +458,7 @@ open_dev(DEVICE *dev, char *VolName, int mode)
       }
       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))) {
+         (dev->free_space_errno == 0 || dev->num_parts == dev->part)) {
         update_free_space_dev(dev);
       }
    }
@@ -1102,6 +1102,16 @@ void DEVICE::set_eof()
    block_num = 0;
 }
 
+/*
+ * Called to indicate we are now at the end of the tape, and
+ *   writing is not possible.
+ */
+void DEVICE::set_eot() 
+{
+   state |= (ST_EOF|ST_EOT|ST_WEOT);
+   state &= ~ST_APPEND;         /* make tape read-only */
+}
+
 /*
  * Position device to end of medium (end of data)
  *  Returns: 1 on succes
index abf48beb3f6d285e68217fac91d77e567046ddc9..6c7fde3ff5fb6ba08238d8b146779d6c9ec74456 100644 (file)
@@ -257,6 +257,7 @@ public:
    const char *strerror() const;
    const char *archive_name() const;
    void set_eof();
+   void set_eot();
 };
 
 /* Note, these return int not bool! */
@@ -268,7 +269,6 @@ inline int DEVICE::is_open() const { return state & ST_OPENED; }
 inline int DEVICE::is_labeled() const { return state & ST_LABEL; }
 inline int DEVICE::is_busy() const { return state & ST_READ || num_writers; }
 inline int DEVICE::at_eof() const { return state & ST_EOF; }
-inline int DEVICE::at_eom() const { return state & ST_EOT; }
 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; }
index 4a4d91ef221ecceb40ca2b40bfbb4bd49daeec3a..54d355c165e6fe8b8a4c1c65d01c63e1a6095f18 100644 (file)
@@ -64,7 +64,7 @@ bool read_records(DCR *dcr,
         break;
       }
       if (!read_block_from_device(dcr, CHECK_BLOCK_NUMBERS)) {
-        if (dev_state(dev, ST_EOT)) {
+        if (dev->at_eot()) {
            DEV_RECORD *trec = new_record();
 
             Jmsg(jcr, M_INFO, 0, "End of Volume at file %u on device %s, Volume \"%s\"\n",
@@ -97,7 +97,7 @@ bool read_records(DCR *dcr,
            /* After reading label, we must read first data block */
            continue;
 
-        } else if (dev_state(dev, ST_EOF)) {
+        } else if (dev->at_eof()) {
            if (verbose) {
                Jmsg(jcr, M_INFO, 0, "Got EOF at file %u  on device %s, Volume \"%s\"\n",
                  dev->file, dev_name(dev), dcr->VolumeName);
@@ -259,7 +259,7 @@ static int try_repositioning(JCR *jcr, DEV_RECORD *rec, DEVICE *dev)
       Dmsg2(300, "Current postion (file:block) %d:%d\n",
         dev->file, dev->block_num);
       jcr->bsr->mount_next_volume = false;
-      dev->state |= ST_EOT;
+//    dev->state |= ST_EOT;
       rec->Block = 0;
       return 1;
    }
index 875c32b8afb5d57b1a38d62b023197948a0e0e52..d09b93cf650da26fe6c845955d1e384f692c7437 100644 (file)
@@ -211,7 +211,7 @@ static void send_blocked_status(JCR *jcr, DEVICE *dev)
       bnet_fsend(user, "%sMALLOC ", dev->state & ST_MALLOC ? "" : "!");
       bnet_fsend(user, "%sAPPEND ", dev->can_append() ? "" : "!");
       bnet_fsend(user, "%sREAD ", dev->can_read() ? "" : "!");
-      bnet_fsend(user, "%sEOT ", dev->at_eom() ? "" : "!");
+      bnet_fsend(user, "%sEOT ", dev->at_eot() ? "" : "!");
       bnet_fsend(user, "%sWEOT ", dev->state & ST_WEOT ? "" : "!");
       bnet_fsend(user, "%sEOF ", dev->at_eof() ? "" : "!");
       bnet_fsend(user, "%sNEXTVOL ", dev->state & ST_NEXTVOL ? "" : "!");