/*
Bacula(R) - The Network Backup Solution
- Copyright (C) 2000-2016 Kern Sibbald
+ Copyright (C) 2000-2017 Kern Sibbald
The original author of Bacula is Kern Sibbald, with contributions
from many others, a complete list can be found in the file AUTHORS.
Public License, v3.0 ("AGPLv3") and some additional permissions and
terms pursuant to its AGPLv3 Section 7.
- This notice must be preserved when any source code is
+ This notice must be preserved when any source code is
conveyed and/or propagated.
Bacula(R) is a registered trademark of Kern Sibbald.
*
* Kern Sibbald, April MMI
* added BB02 format October MMII
+ * added aligned format November MMXII
*
*/
};
/*
- * Flush block to disk
- */
-bool flush_block(DCR *dcr)
-{
- bool rtn = false;
-
- if (!is_block_empty(dcr->block)) {
- Dmsg0(dbgep, "=== wpath 53 flush_block\n");
- Dmsg3(190, "Call flush_block BlockAddr=%lld nbytes=%d block=%x\n",
- dcr->block->BlockAddr, dcr->block->binbuf, dcr->block);
- dump_block(dcr->block, "Flush_block");
- if (dcr->jcr->is_canceled() || !dcr->write_block_to_device()) {
- Dmsg0(dbgep, "=== wpath 54 flush_block\n");
- Dmsg0(190, "Failed to write block to device, return false.\n");
- goto get_out;
- }
- empty_block(dcr->block);
- }
- rtn = true;
-
-get_out:
- return rtn;
-}
-
-/*
- * Write a header record to the block.
+ * Write an ameta (normal) header record to the block.
*/
static bool write_header_to_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec)
{
ser_declare;
Dmsg0(dbgep, "=== wpath 11 write_header_to_block\n");
+ ASSERT2(!block->adata, "Attempt to write header to adata block!");
rec->remlen = block->buf_len - block->binbuf;
/* Require enough room to write a full header */
if (rec->remlen < WRITE_RECHDR_LENGTH) {
Dmsg0(dbgep, "=== wpath 12 write_header_to_block\n");
- Dmsg4(190, "Fail remlen=%d<%d reclen buf_len=%d binbuf=%d\n",
- rec->remlen, WRITE_RECHDR_LENGTH, block->buf_len, block->binbuf);
+ Dmsg5(190, "remlen<WRITE_RECHDR_LEN adata=%d remlen=%d<%d reclen buf_len=%d binbuf=%d\n",
+ block->adata, rec->remlen, WRITE_RECHDR_LENGTH, block->buf_len, block->binbuf);
rec->remainder = rec->data_len + WRITE_RECHDR_LENGTH;
return false;
}
block->bufp += WRITE_RECHDR_LENGTH;
block->binbuf += WRITE_RECHDR_LENGTH;
+
+ block->RecNum++;
rec->remlen -= WRITE_RECHDR_LENGTH;
rec->remainder = rec->data_len;
if (rec->FileIndex > 0) {
block->LastIndex = rec->FileIndex;
}
- //dump_block(block, "Add header");
+ //dump_block(dcr->dev, block, "Add header");
return true;
}
/*
- * If the prior block was not big enough to hold the
+ * If the prior ameta block was not big enough to hold the
* whole record, write a continuation header record.
*/
static void write_continue_header_to_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec)
ser_declare;
Dmsg0(dbgep, "=== wpath 17 write_cont_hdr_to_block\n");
+ ASSERT2(!block->adata, "Attempt to write adata header!");
rec->remlen = block->buf_len - block->binbuf;
+
+ /* No space left to write the continue header */
+ if (rec->remlen == 0) {
+ return;
+ }
+
/*
* We have unwritten bytes from a previous
* time. Presumably we have a new buffer (possibly
}
block->LastIndex = rec->FileIndex;
}
- //dump_block(block, "Add cont header");
+ if (block->adata) {
+ Dmsg3(150, "=== write_cont_hdr ptr=%p begin=%p off=%d\n", block->bufp,
+ block->buf, block->bufp-block->buf);
+ }
+ block->RecNum++;
+ //dump_block(dcr->dev, block, "Add cont header");
}
/*
+ * Now write non-aligned data to an ameta block
*/
static bool write_data_to_block(DCR *dcr, DEV_BLOCK *block, DEV_RECORD *rec)
{
Dmsg0(dbgep, "=== wpath 24 write_data_to_block\n");
+ ASSERT2(!block->adata, "Attempt to write adata to metadata file!");
rec->remlen = block->buf_len - block->binbuf;
/* Write as much of data as possible */
if (rec->remlen >= rec->remainder) {
block->binbuf += rec->remainder;
rec->remainder = 0;
} else {
+ if (rec->state_bits & REC_NO_SPLIT) {
+ return false; /* do not split record */
+ }
Dmsg0(dbgep, "=== wpath 26 write_data_to_block\n");
memcpy(block->bufp, rec->data+rec->data_len-rec->remainder,
rec->remlen);
rec->remainder -= rec->remlen;
return false; /* did partial transfer */
}
+ if (block->adata) {
+ /* Adata label data */
+ Dmsg3(190, "write_data adata=%d blkAddr=%lld off=%d\n",
+ block->adata, block->BlockAddr, block->bufp-block->buf);
+ }
+ //dump_block(dcr->dev, block, "Add data/adata");
return true;
}
* non-zero), and 2. The remaining bytes to write may not
* all fit into the block.
*
+ * Ensure we leave with same ameta/adata set as enter.
*/
bool write_record_to_block(DCR *dcr, DEV_RECORD *rec)
{
char buf1[100], buf2[100];
+ bool save_adata = dcr->block->adata;
bool rtn;
Enter(dbgel);
Dmsg0(dbgep, "=== wpath 35 enter write_record_to_block\n");
- Dmsg7(200, "write_record_to_block() state=%d FI=%s SessId=%d"
+ Dmsg7(250, "write_record_to_block() state=%d FI=%s SessId=%d"
" Strm=%s len=%d rem=%d remainder=%d\n", rec->wstate,
FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
rec->remlen, rec->remainder);
- Dmsg4(160, "write_rec Strm=%s len=%d rem=%d remainder=%d\n",
+ Dmsg4(250, "write_rec Strm=%s len=%d rem=%d remainder=%d\n",
stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
rec->remlen, rec->remainder);
+ if (!dcr->dev->do_pre_write_checks(dcr, rec)) {
+ goto fail_out;
+ }
+
for ( ;; ) {
Dmsg0(dbgep, "=== wpath 37 top of for loop\n");
ASSERT(dcr->block->binbuf == (uint32_t) (dcr->block->bufp - dcr->block->buf));
Dmsg0(dbgep, "=== wpath 38 st_none\n");
/* Figure out what to do */
rec->wstate = st_header;
+ /* If labeling adata, special path */
+ if (dcr->adata_label) {
+ Dmsg1(dbgep, "=== wpath adata_label set adata=%d\n", dcr->dev->adata);
+ rec->wstate = st_adata_label;
+ continue;
+ }
if (rec->FileIndex < 0) {
- /* Label record */
+ /* Label record -- ameta label */
+ Dmsg3(dbgep, "=== wpath label adata=%d Strm=%d FI=%d\n",
+ dcr->dev->adata, rec->Stream, rec->FileIndex);
rec->wstate = st_header;
continue;
}
+
+ dcr->dev->select_data_stream(dcr, rec);
continue; /* go to next state */
case st_header:
* that did not previously fit into the block.
*/
Dmsg0(dbgep, "=== wpath 42 st_header\n");
- if (!write_header_to_block(dcr, dcr->block, rec)) {
+ dcr->set_ameta();
+ if (!write_header_to_block(dcr, dcr->ameta_block, rec)) {
Dmsg0(dbgep, "=== wpath 43 st_header\n");
rec->wstate = st_cont_header;
goto fail_out;
case st_cont_header:
Dmsg0(dbgep, "=== wpath 45 st_cont_header\n");
- write_continue_header_to_block(dcr, dcr->block, rec);
+ dcr->set_ameta();
+ write_continue_header_to_block(dcr, dcr->ameta_block, rec);
rec->wstate = st_data;
if (rec->remlen == 0) {
Dmsg0(dbgep, "=== wpath 46 st_cont_header\n");
* may not have enough room to transfer the whole this time.
*/
Dmsg0(dbgep, "=== wpath 47 st_data\n");
+ dcr->set_ameta();
if (rec->remainder > 0) {
Dmsg0(dbgep, "=== wpath 48 st_data\n");
- if (!write_data_to_block(dcr, dcr->block, rec)) {
+ if (!write_data_to_block(dcr, dcr->ameta_block, rec)) {
Dmsg0(dbgep, "=== wpath 49 st_data\n");
- rec->wstate = st_cont_header;
+ if (rec->state_bits & REC_NO_SPLIT) {
+ rec->wstate = st_header;
+ } else {
+ rec->wstate = st_cont_header;
+ }
goto fail_out;
}
}
+ rec->state_bits &= ~REC_NO_SPLIT; /* clear possible no split bit */
rec->remainder = 0; /* did whole transfer */
rec->wstate = st_none;
goto get_out;
+ case st_adata_label:
+ if (!dcr->dev->write_adata_label(dcr, rec)) {
+ goto fail_out;
+ }
+ goto get_out;
+
+ /*
+ * We come here only once for each record
+ */
+ case st_adata:
+ dcr->dev->write_adata(dcr, rec);
+ continue;
+
+ case st_cont_adata:
+ dcr->dev->write_cont_adata(dcr, rec);
+ continue;
+
+ /*
+ * Note, the following two cases are handled differently
+ * in write_adata_record_header() so take care if you want to
+ * eliminate one of them.
+ */
+ case st_cont_adata_rechdr:
+ Dmsg2(200, "=== cont rechdr remainder=%d reclen=%d\n", rec->remainder, dcr->adata_block->reclen);
+ Dmsg0(200, "st_cont_adata_rechdr\n");
+ /* Fall through wanted */
+ case st_adata_rechdr:
+ switch(dcr->dev->write_adata_rechdr(dcr, rec)) {
+ case -1:
+ goto fail_out;
+ case 0:
+ continue;
+ case 1:
+ goto get_out;
+ }
+ break;
+
default:
Dmsg0(dbgep, "=== wpath 67!!!! default\n");
Dmsg0(50, "Something went wrong. Default state.\n");
fail_out:
rtn = false;
out:
+ if (save_adata) {
+ dcr->set_adata();
+ } else {
+ dcr->set_ameta();
+ }
Leave(dbgel);
return rtn;
}