]> git.sur5r.net Git - bacula/bacula/commitdiff
Convert write_rec_to_block() to a state machine
authorKern Sibbald <kern@sibbald.com>
Sat, 23 Jun 2012 11:40:25 +0000 (13:40 +0200)
committerKern Sibbald <kern@sibbald.com>
Sat, 20 Apr 2013 12:50:51 +0000 (14:50 +0200)
bacula/src/stored/read_record.c
bacula/src/stored/record.c
bacula/src/stored/record.h

index 078045d4accb127461bfd76405604eb968bef5a6..ab77400e1afe16ffb05952cd94c753d5b29e4b1f 100644 (file)
@@ -48,7 +48,7 @@ static void handle_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *s
 static BSR *position_to_first_file(JCR *jcr, DCR *dcr);
 static bool try_repositioning(JCR *jcr, DEV_RECORD *rec, DCR *dcr);
 #ifdef DEBUG
-static char *rec_state_to_str(DEV_RECORD *rec);
+static char *rec_state_bits_to_str(DEV_RECORD *rec);
 #endif
 
 static const int dbglvl = 500;
@@ -189,23 +189,23 @@ bool read_records(DCR *dcr,
          rec = new_record();
          recs->prepend(rec);
          Dmsg3(dbglvl, "New record for state=%s SI=%d ST=%d\n",
-             rec_state_to_str(rec),
+             rec_state_bits_to_str(rec),
              block->VolSessionId, block->VolSessionTime);
       }
-      Dmsg3(dbglvl, "Before read rec loop. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec),
+      Dmsg3(dbglvl, "Before read rec loop. stat=%s blk=%d rem=%d\n", rec_state_bits_to_str(rec),
             block->BlockNumber, rec->remainder);
       record = 0;
-      rec->state = 0;
+      rec->state_bits = 0;
       lastFileIndex = no_FileIndex;
       Dmsg1(dbglvl, "Block %s empty\n", is_block_empty(rec)?"is":"NOT");
-      for (rec->state=0; ok && !is_block_empty(rec); ) {
+      for (rec->state_bits=0; ok && !is_block_empty(rec); ) {
          if (!read_record_from_block(dcr, block, rec)) {
-            Dmsg3(400, "!read-break. state=%s blk=%d rem=%d\n", rec_state_to_str(rec),
+            Dmsg3(400, "!read-break. state_bits=%s blk=%d rem=%d\n", rec_state_bits_to_str(rec),
                   block->BlockNumber, rec->remainder);
             break;
          }
-         Dmsg5(dbglvl, "read-OK. state=%s blk=%d rem=%d file:block=%u:%u\n",
-                 rec_state_to_str(rec), block->BlockNumber, rec->remainder,
+         Dmsg5(dbglvl, "read-OK. state_bits=%s blk=%d rem=%d file:block=%u:%u\n",
+                 rec_state_bits_to_str(rec), block->BlockNumber, rec->remainder,
                  dev->file, dev->block_num);
          /*
           * At this point, we have at least a record header.
@@ -214,8 +214,8 @@ bool read_records(DCR *dcr,
           *  get all the data.
           */
          record++;
-         Dmsg6(dbglvl, "recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record,
-            rec_state_to_str(rec), block->BlockNumber,
+         Dmsg6(dbglvl, "recno=%d state_bits=%s blk=%d SI=%d ST=%d FI=%d\n", record,
+            rec_state_bits_to_str(rec), block->BlockNumber,
             rec->VolSessionId, rec->VolSessionTime, rec->FileIndex);
 
          if (rec->FileIndex == EOM_LABEL) { /* end of tape? */
@@ -268,7 +268,7 @@ bool read_records(DCR *dcr,
                Dmsg4(dbglvl, "BSR no match: clear rem=%d FI=%d before set_eof pos %u:%u\n",
                   rec->remainder, rec->FileIndex, dev->file, dev->block_num);
                rec->remainder = 0;
-               rec->state &= ~REC_PARTIAL_RECORD;
+               rec->state_bits &= ~REC_PARTIAL_RECORD;
                if (try_repositioning(jcr, rec, dcr)) {
                   break;
                }
@@ -277,14 +277,14 @@ bool read_records(DCR *dcr,
          }
          dcr->VolLastIndex = rec->FileIndex;  /* let caller know where we are */
          if (is_partial_record(rec)) {
-            Dmsg6(dbglvl, "Partial, break. recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record,
-               rec_state_to_str(rec), block->BlockNumber,
+            Dmsg6(dbglvl, "Partial, break. recno=%d state_bits=%s blk=%d SI=%d ST=%d FI=%d\n", record,
+               rec_state_bits_to_str(rec), block->BlockNumber,
                rec->VolSessionId, rec->VolSessionTime, rec->FileIndex);
             break;                    /* read second part of record */
          }
 
-         Dmsg6(dbglvl, "OK callback. recno=%d state=%s blk=%d SI=%d ST=%d FI=%d\n", record,
-               rec_state_to_str(rec), block->BlockNumber,
+         Dmsg6(dbglvl, "OK callback. recno=%d state_bits=%s blk=%d SI=%d ST=%d FI=%d\n", record,
+               rec_state_bits_to_str(rec), block->BlockNumber,
                rec->VolSessionId, rec->VolSessionTime, rec->FileIndex);
          if (lastFileIndex != no_FileIndex && lastFileIndex != rec->FileIndex) {
             if (is_this_bsr_done(jcr->bsr, rec) && try_repositioning(jcr, rec, dcr)) {
@@ -369,7 +369,7 @@ static bool try_repositioning(JCR *jcr, DEV_RECORD *rec, DCR *dcr)
       if (dev_addr > bsr_addr) {
          return false;
       }
-      Dmsg4(10, "Try_Reposition from (file:block) %u:%u to %u:%u\n",
+      Dmsg4(dbglvl, "Try_Reposition from (file:block) %u:%u to %u:%u\n",
             dev->file, dev->block_num, file, block);
       dev->reposition(dcr, file, block);
       rec->Block = 0;
@@ -437,23 +437,23 @@ static void handle_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *s
 }
 
 #ifdef DEBUG
-static char *rec_state_to_str(DEV_RECORD *rec)
+static char *rec_state_bits_to_str(DEV_RECORD *rec)
 {
    static char buf[200];
    buf[0] = 0;
-   if (rec->state & REC_NO_HEADER) {
+   if (rec->state_bits & REC_NO_HEADER) {
       bstrncat(buf, "Nohdr,", sizeof(buf));
    }
    if (is_partial_record(rec)) {
       bstrncat(buf, "partial,", sizeof(buf));
    }
-   if (rec->state & REC_BLOCK_EMPTY) {
+   if (rec->state_bits & REC_BLOCK_EMPTY) {
       bstrncat(buf, "empty,", sizeof(buf));
    }
-   if (rec->state & REC_NO_MATCH) {
+   if (rec->state_bits & REC_NO_MATCH) {
       bstrncat(buf, "Nomatch,", sizeof(buf));
    }
-   if (rec->state & REC_CONTINUATION) {
+   if (rec->state_bits & REC_CONTINUATION) {
       bstrncat(buf, "cont,", sizeof(buf));
    }
    if (buf[0]) {
index a28d9ef936b816c55d8c8d5d7a668107cf6dbc8b..a25abad052d977af09be7917f518186653b92ab9 100644 (file)
@@ -27,7 +27,7 @@
 */
 /*
  *
- *   record.c -- tape record handling functions
+ *   record.c -- Volume (tape/disk) record handling functions
  *
  *              Kern Sibbald, April MMI
  *                added BB02 format October MMII
@@ -246,6 +246,7 @@ DEV_RECORD *new_record(void)
    rec = (DEV_RECORD *)get_memory(sizeof(DEV_RECORD));
    memset(rec, 0, sizeof(DEV_RECORD));
    rec->data = get_pool_memory(PM_MESSAGE);
+   rec->state = st_none;
    return rec;
 }
 
@@ -255,7 +256,8 @@ void empty_record(DEV_RECORD *rec)
    rec->VolSessionId = rec->VolSessionTime = 0;
    rec->FileIndex = rec->Stream = 0;
    rec->data_len = rec->remainder = 0;
-   rec->state &= ~(REC_PARTIAL_RECORD|REC_BLOCK_EMPTY|REC_NO_MATCH|REC_CONTINUATION);
+   rec->state_bits &= ~(REC_PARTIAL_RECORD|REC_BLOCK_EMPTY|REC_NO_MATCH|REC_CONTINUATION);
+   rec->state = st_none;
 }
 
 /*
@@ -273,92 +275,13 @@ void free_record(DEV_RECORD *rec)
    Dmsg0(950, "Leave free_record.\n");
 }
 
-
-/*
- * Write a Record to the block
- *
- *  Returns: false on failure (none or partially written)
- *           true  on success (all bytes written)
- *
- *  and remainder returned in packet.
- *
- *  We require enough room for the header, and we deal with
- *  two special cases. 1. Only part of the record may have
- *  been transferred the last time (when remainder is
- *  non-zero), and 2. The remaining bytes to write may not
- *  all fit into the block.
- */
-bool write_record_to_block(DCR *dcr, DEV_RECORD *rec)
+static bool write_header_to_block(DEV_BLOCK *block, DEV_RECORD *rec)
 {
    ser_declare;
-   uint32_t remlen;
-   char buf1[100], buf2[100];
-   DEV_BLOCK *block;
-
-   block = dcr->block;
-
-   remlen = block->buf_len - block->binbuf;
-
-   ASSERT(block->binbuf == (uint32_t) (block->bufp - block->buf));
-   ASSERT(block->buf_len >= block->binbuf);
-
-   Dmsg6(890, "write_record_to_block() FI=%s SessId=%d Strm=%s len=%d\n"
-      "rem=%d remainder=%d\n",
-      FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
-      stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
-      remlen, rec->remainder);
 
-   /*
-    * If rec->remainder is non-zero, we have been called a
-    *  second (or subsequent) time to finish writing a record
-    *  that did not previously fit into the block.
-    */
-   if (rec->remainder == 0) {
-      /* Require enough room to write a full header */
-      if (remlen >= WRITE_RECHDR_LENGTH) {
-         ser_begin(block->bufp, WRITE_RECHDR_LENGTH);
-         if (BLOCK_VER == 1) {
-            ser_uint32(rec->VolSessionId);
-            ser_uint32(rec->VolSessionTime);
-         } else {
-            block->VolSessionId = rec->VolSessionId;
-            block->VolSessionTime = rec->VolSessionTime;
-         }
-         ser_int32(rec->FileIndex);
-         ser_int32(rec->Stream);
-         ser_uint32(rec->data_len);
-
-         block->bufp += WRITE_RECHDR_LENGTH;
-         block->binbuf += WRITE_RECHDR_LENGTH;
-         remlen -= WRITE_RECHDR_LENGTH;
-         rec->remainder = rec->data_len;
-         if (rec->FileIndex > 0) {
-            /* If data record, update what we have in this block */
-            if (block->FirstIndex == 0) {
-               block->FirstIndex = rec->FileIndex;
-            }
-            block->LastIndex = rec->FileIndex;
-         }
-      } else {
-         rec->remainder = rec->data_len + WRITE_RECHDR_LENGTH;
-         return false;
-      }
-   } else {
-      /*
-       * We are here to write unwritten bytes from a previous
-       * time. Presumably we have a new buffer (possibly
-       * containing a volume label), so the new header
-       * should be able to fit in the block -- otherwise we have
-       * an error.  Note, we have to continue splitting the
-       * data record if it is longer than the block.
-       *
-       * First, write the header, then write as much as
-       * possible of the data record.
-       *
-       * Every time we write a header and it is a continuation
-       * of a previous partially written record, we store the
-       * Stream as -Stream in the record header.
-       */
+   rec->remlen = block->buf_len - block->binbuf;
+   /* Require enough room to write a full header */
+   if (rec->remlen >= WRITE_RECHDR_LENGTH) {
       ser_begin(block->bufp, WRITE_RECHDR_LENGTH);
       if (BLOCK_VER == 1) {
          ser_uint32(rec->VolSessionId);
@@ -368,21 +291,13 @@ bool write_record_to_block(DCR *dcr, DEV_RECORD *rec)
          block->VolSessionTime = rec->VolSessionTime;
       }
       ser_int32(rec->FileIndex);
-      if (rec->remainder > rec->data_len) {
-         ser_int32(rec->Stream);      /* normal full header */
-         ser_uint32(rec->data_len);
-         rec->remainder = rec->data_len; /* must still do data record */
-      } else {
-         ser_int32(-rec->Stream);     /* mark this as a continuation record */
-         ser_uint32(rec->remainder);  /* bytes to do */
-      }
-
-      /* Require enough room to write a full header */
-      ASSERT(remlen >= WRITE_RECHDR_LENGTH);
+      ser_int32(rec->Stream);
+      ser_uint32(rec->data_len);
 
       block->bufp += WRITE_RECHDR_LENGTH;
       block->binbuf += WRITE_RECHDR_LENGTH;
-      remlen -= WRITE_RECHDR_LENGTH;
+      rec->remlen -= WRITE_RECHDR_LENGTH;
+      rec->remainder = rec->data_len;
       if (rec->FileIndex > 0) {
          /* If data record, update what we have in this block */
          if (block->FirstIndex == 0) {
@@ -390,54 +305,186 @@ bool write_record_to_block(DCR *dcr, DEV_RECORD *rec)
          }
          block->LastIndex = rec->FileIndex;
       }
+   } else {
+      rec->remainder = rec->data_len + WRITE_RECHDR_LENGTH;
+      return false;
    }
-   if (remlen == 0) {
-      return false;                   /* partial transfer */
-   }
+   return true;
+}
 
+static void write_continue_header_to_block(DEV_BLOCK *block, DEV_RECORD *rec)
+{
+   ser_declare;
+
+   rec->remlen = block->buf_len - block->binbuf;
    /*
-    * Now deal with data record.
-    * Part of it may have already been transferred, and we
-    * may not have enough room to transfer the whole this time.
+    * We have unwritten bytes from a previous
+    * time. Presumably we have a new buffer (possibly
+    * containing a volume label), so the new header
+    * should be able to fit in the block -- otherwise we have
+    * an error.  Note, we have to continue splitting the
+    * data record if it is longer than the block.
+    *
+    * First, write the header.
+    *
+    * Every time we write a header and it is a continuation
+    * of a previous partially written record, we store the
+    * Stream as -Stream in the record header.
     */
-   if (rec->remainder > 0) {
-      /* Write as much of data as possible */
-      if (remlen >= rec->remainder) {
-         memcpy(block->bufp, rec->data+rec->data_len-rec->remainder,
-                rec->remainder);
-         block->bufp += rec->remainder;
-         block->binbuf += rec->remainder;
-      } else {
-         memcpy(block->bufp, rec->data+rec->data_len-rec->remainder,
-                remlen);
+   ser_begin(block->bufp, WRITE_RECHDR_LENGTH);
+   if (BLOCK_VER == 1) {
+      ser_uint32(rec->VolSessionId);
+      ser_uint32(rec->VolSessionTime);
+   } else {
+      block->VolSessionId = rec->VolSessionId;
+      block->VolSessionTime = rec->VolSessionTime;
+   }
+   ser_int32(rec->FileIndex);
+   if (rec->remainder > rec->data_len) {
+      ser_int32(rec->Stream);      /* normal full header */
+      ser_uint32(rec->data_len);
+      rec->remainder = rec->data_len; /* must still do data record */
+   } else {
+      ser_int32(-rec->Stream);     /* mark this as a continuation record */
+      ser_uint32(rec->remainder);  /* bytes to do */
+   }
+
+   /* Require enough room to write a full header */
+   ASSERT(rec->remlen >= WRITE_RECHDR_LENGTH);
+
+   block->bufp += WRITE_RECHDR_LENGTH;
+   block->binbuf += WRITE_RECHDR_LENGTH;
+   rec->remlen -= WRITE_RECHDR_LENGTH;
+   if (rec->FileIndex > 0) {
+      /* If data record, update what we have in this block */
+      if (block->FirstIndex == 0) {
+         block->FirstIndex = rec->FileIndex;
+      }
+      block->LastIndex = rec->FileIndex;
+   }
+}
+
+static bool write_data_to_block(DEV_BLOCK *block, DEV_RECORD *rec)
+{
+   rec->remlen = block->buf_len - block->binbuf;
+   /* Write as much of data as possible */
+   if (rec->remlen >= rec->remainder) {
+      memcpy(block->bufp, rec->data+rec->data_len-rec->remainder,
+             rec->remainder);
+      block->bufp += rec->remainder;
+      block->binbuf += rec->remainder;
+   } else {
+      memcpy(block->bufp, rec->data+rec->data_len-rec->remainder,
+             rec->remlen);
 #ifdef xxxxxSMCHECK
-         if (!sm_check_rtn(__FILE__, __LINE__, False)) {
-            /* We damaged a buffer */
-            Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n"
-               "rem=%d remainder=%d\n",
-               FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
-               stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
-               remlen, rec->remainder);
-            Dmsg5(0, "Damaged block: bufp=%x binbuf=%d buf_len=%d rem=%d moved=%d\n",
-               block->bufp, block->binbuf, block->buf_len, block->buf_len-block->binbuf,
-               remlen);
-            Dmsg2(0, "Damaged block: buf=%x binbuffrombuf=%d \n",
-               block->buf, block->bufp-block->buf);
-
-               Emsg0(M_ABORT, 0, _("Damaged buffer\n"));
-         }
+      if (!sm_check_rtn(__FILE__, __LINE__, False)) {
+         /* We damaged a buffer */
+         Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n"
+            "rem=%d remainder=%d\n",
+            FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
+            stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
+            rec->remlen, rec->remainder);
+         Dmsg5(0, "Damaged block: bufp=%x binbuf=%d buf_len=%d rem=%d moved=%d\n",
+            block->bufp, block->binbuf, block->buf_len, block->buf_len-block->binbuf,
+            rec->remlen);
+         Dmsg2(0, "Damaged block: buf=%x binbuffrombuf=%d \n",
+            block->buf, block->bufp-block->buf);
+         Emsg0(M_ABORT, 0, _("Damaged buffer\n"));
+      }
 #endif
 
-         block->bufp += remlen;
-         block->binbuf += remlen;
-         rec->remainder -= remlen;
-         return false;                /* did partial transfer */
-      }
+      block->bufp += rec->remlen;
+      block->binbuf += rec->remlen;
+      rec->remainder -= rec->remlen;
+      return false;                /* did partial transfer */
    }
-   rec->remainder = 0;                /* did whole transfer */
    return true;
 }
+/*
+ * Write a Record to the block
+ *
+ *  Returns: false on failure (none or partially written)
+ *           true  on success (all bytes written)
+ *
+ *  and remainder returned in packet.
+ *
+ *  We require enough room for the header, and we deal with
+ *  two special cases. 1. Only part of the record may have
+ *  been transferred the last time (when remainder is
+ *  non-zero), and 2. The remaining bytes to write may not
+ *  all fit into the block.
+ */
+bool write_record_to_block(DCR *dcr, DEV_RECORD *rec)
+{
+   char buf1[100], buf2[100];
+   DEV_BLOCK *block = dcr->block;
 
+   for ( ;; ) {
+      ASSERT(block->binbuf == (uint32_t)(block->bufp - block->buf));
+      ASSERT(block->buf_len >= block->binbuf);
+
+      Dmsg6(890, "write_record_to_block() FI=%s SessId=%d Strm=%s len=%d\n"
+         "rem=%d remainder=%d\n",
+         FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
+         stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
+         rec->remlen, rec->remainder);
+
+      switch (rec->state) {
+      case st_none:
+         /* Figure out what to do */
+         rec->state = st_header;
+         continue;              /* go to next state */
+
+      case st_header:
+         /*
+          * Write header
+          *
+          * If rec->remainder is non-zero, we have been called a
+          *  second (or subsequent) time to finish writing a record
+          *  that did not previously fit into the block.
+          */
+          if (!write_header_to_block(block, rec)) {
+             rec->state = st_header_cont;
+             return false;
+          }
+          rec->state = st_data;
+          continue;
+
+      /* Write continuation header */
+      case st_header_cont:
+         write_continue_header_to_block(block, rec);
+         rec->state = st_data;
+         if (rec->remlen == 0) {
+            return false;                   /* partial transfer */
+         }
+         continue;
+
+      /* Write normal data */
+      case st_data:
+         /*
+          * Write data
+          *
+          * Part of it may have already been transferred, and we
+          * may not have enough room to transfer the whole this time.
+          */
+         if (rec->remainder > 0) {
+            if (!write_data_to_block(block, rec)) {
+               rec->state = st_header_cont;
+               return false;
+            }
+         }
+         rec->remainder = 0;                /* did whole transfer */
+         rec->state = st_none;
+         return true;
+
+      default:
+         Dmsg0(000, "Something went wrong. Default state.\n");
+         rec->state = st_none;
+         return true;
+      }
+   }
+   return true;
+}
 
 /*
  * Test if we can write whole record to the block
@@ -494,9 +541,9 @@ bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec)
    remlen = block->binbuf;
 
    /* Clear state flags */
-   rec->state = 0;
+   rec->state_bits = 0;
    if (block->dev->is_tape()) {
-      rec->state |= REC_ISTAPE;
+      rec->state_bits |= REC_ISTAPE;
    }
    rec->Block = ((DEVICE *)block->dev)->EndBlock;
    rec->File = ((DEVICE *)block->dev)->EndFile;
@@ -537,7 +584,7 @@ bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec)
        */
       if (rec->remainder && (rec->VolSessionId != VolSessionId ||
                              rec->VolSessionTime != VolSessionTime)) {
-         rec->state |= REC_NO_MATCH;
+         rec->state_bits |= REC_NO_MATCH;
          Dmsg0(450, "remainder and VolSession doesn't match\n");
          return false;             /* This is from some other Session */
       }
@@ -548,11 +595,11 @@ bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec)
       if (Stream < 0) {               /* continuation record? */
          Dmsg1(500, "Got negative Stream => continuation. remainder=%d\n",
             rec->remainder);
-         rec->state |= REC_CONTINUATION;
+         rec->state_bits |= REC_CONTINUATION;
          if (!rec->remainder) {       /* if we didn't read previously */
             rec->data_len = 0;        /* return data as if no continuation */
          } else if (rec->Stream != -Stream) {
-            rec->state |= REC_NO_MATCH;
+            rec->state_bits |= REC_NO_MATCH;
             return false;             /* This is from some other Session */
          }
          rec->Stream = -Stream;       /* set correct Stream */
@@ -587,7 +634,7 @@ bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec)
        * then reread.
        */
       Dmsg0(450, "read_record_block: nothing\n");
-      rec->state |= (REC_NO_HEADER | REC_BLOCK_EMPTY);
+      rec->state_bits |= (REC_NO_HEADER | REC_BLOCK_EMPTY);
       empty_block(block);                      /* mark block empty */
       return false;
    }
@@ -598,7 +645,7 @@ bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec)
        * Something is wrong, force read of next block, abort 
        *   continuing with this block.
        */
-      rec->state |= (REC_NO_HEADER | REC_BLOCK_EMPTY);
+      rec->state_bits |= (REC_NO_HEADER | REC_BLOCK_EMPTY);
       empty_block(block);
       Jmsg2(dcr->jcr, M_WARNING, 0, _("Sanity check failed. maxlen=%d datalen=%d. Block discarded.\n"),
          MAX_BLOCK_LENGTH, data_bytes);
@@ -629,7 +676,7 @@ bool read_record_from_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec)
       rec->data_len += remlen;
       rec->remainder = 1;             /* partial record transferred */
       Dmsg1(450, "read_record_block: partial xfered=%d\n", rec->data_len);
-      rec->state |= (REC_PARTIAL_RECORD | REC_BLOCK_EMPTY);
+      rec->state_bits |= (REC_PARTIAL_RECORD | REC_BLOCK_EMPTY);
       return true;
    }
    rec->remainder = 0;
index 92da7d35138a2210f36759eac6a49b220b038aa0..62c245d7d27f3cad3fb0222e32e63f22dbf3c4ae 100644 (file)
@@ -50,6 +50,13 @@ enum {
    VOL_NO_MEDIA                           /* Hard error -- no media present */
 };
 
+enum rec_state {
+   st_none,                               /* No state */
+   st_header,                             /* Write header */
+   st_header_cont,
+   st_data,
+};
+
 
 /*  See block.h for RECHDR_LENGTH */
 
@@ -78,8 +85,8 @@ enum {
 #define REC_CONTINUATION     (1<<4)   /* Continuation record found */
 #define REC_ISTAPE           (1<<5)   /* Set if device is tape */
 
-#define is_partial_record(r) ((r)->state & REC_PARTIAL_RECORD)
-#define is_block_empty(r)    ((r)->state & REC_BLOCK_EMPTY)
+#define is_partial_record(r) ((r)->state_bits & REC_PARTIAL_RECORD)
+#define is_block_empty(r)    ((r)->state_bits & REC_BLOCK_EMPTY)
 
 /*
  * DEV_RECORD for reading and writing records.
@@ -102,7 +109,9 @@ struct DEV_RECORD {
    int32_t  maskedStream;             /* Masked Stream without high bits */
    uint32_t data_len;                 /* current record length */
    uint32_t remainder;                /* remaining bytes to read/write */
-   uint32_t state;                    /* state bits */
+   uint32_t remlen;                   /* temp remainder bytes */
+   uint32_t state_bits;               /* state bits */
+   rec_state state;                   /* state of write_record_to_block */
    BSR *bsr;                          /* pointer to bsr that matched */
    uint8_t  ser_buf[WRITE_RECHDR_LENGTH];   /* serialized record header goes here */
    POOLMEM *data;                     /* Record data. This MUST be a memory pool item */