#include "bacula.h"
#include "stored.h"
-extern int FiledDataChan; /* File daemon data channel (port) */
-extern int BaculaTapeVersion; /* Version number */
-extern char BaculaId[]; /* Id string */
/* Responses sent to the File daemon */
static char OK_data[] = "3000 OK data\n";
sm_check(__FILE__, __LINE__, False);
+ if (!jcr->no_attributes && jcr->spool_attributes) {
+ open_spool_file(jcr, jcr->dir_bsock);
+ }
+
ds = fd_sock;
if (!bnet_set_buffer_size(ds, MAX_NETWORK_BUFFER_SIZE, BNET_SETBUF_WRITE)) {
memset(&rec, 0, sizeof(rec));
/*
- * Get Data from File daemon, write to device
+ * Get Data from File daemon, write to device. To clarify what is
+ * going on here. We expect:
+ * - A stream header
+ * - Multiple records of data
+ * - EOD record
+ *
+ * The Stream header is just used to sychronize things, and
+ * none of the stream header is written to tape.
+ * The Multiple records of data, contain first the Attributes,
+ * then after another stream header, the file data, then
+ * after another stream header, the MD5 data if any.
+ *
+ * So we get the (stream header, data, EOD) three time for each
+ * file. 1. for the Attributes, 2. for the file data if any,
+ * and 3. for the MD5 if any.
*/
jcr->VolFirstFile = 0;
time(&jcr->run_time); /* start counting time for rates */
char info[100];
/* Read Stream header from the File daemon.
- * The stream header consists of the
- *
- * file_index (sequential Bacula file index)
- * stream (arbitrary Bacula number to distinguish parts of data)
- * info (Info for Storage daemon -- compressed, encryped, ...)
+ * The stream header consists of the following:
+ * file_index (sequential Bacula file index)
+ * stream (arbitrary Bacula number to distinguish parts of data)
+ * info (Info for Storage daemon -- compressed, encryped, ...)
+ * info is not currently used, so is read, but ignored!
*/
- if ((n=bget_msg(ds)) < 0) {
+ if ((n=bget_msg(ds)) <= 0) {
+ if (n == BNET_SIGNAL && ds->msglen == BNET_EOD) {
+ break; /* end of data */
+ }
Jmsg1(jcr, M_FATAL, 0, _("Error reading data header from FD. ERR=%s\n"),
bnet_strerror(ds));
ok = FALSE;
break;
}
- if (n == 0) { /* End of conversation */
- break; /* all done */
- }
sm_check(__FILE__, __LINE__, False);
ds->msg[ds->msglen] = 0;
if (sscanf(ds->msg, "%ld %ld %100s", &file_index, &stream, info) != 3) {
*/
sm_check(__FILE__, __LINE__, False);
while ((n=bget_msg(ds)) > 0 && !job_cancelled(jcr)) {
- char *dsmsg = ds->msg;
sm_check(__FILE__, __LINE__, False);
rec.VolSessionId = jcr->VolSessionId;
rec.data = ds->msg; /* use message buffer */
Dmsg4(250, "before writ_rec FI=%d SessId=%d Strm=%s len=%d\n",
- rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream),
+ rec.FileIndex, rec.VolSessionId, stream_to_ascii(rec.Stream,rec.FileIndex),
rec.data_len);
while (!write_record_to_block(block, &rec)) {
}
sm_check(__FILE__, __LINE__, False);
if (!ok) {
+ Dmsg0(400, "Not OK\n");
break;
}
jcr->JobBytes += rec.data_len; /* increment bytes this job */
- Dmsg4(190, "write_record FI=%s SessId=%d Strm=%s len=%d\n",
+ Dmsg4(200, "write_record FI=%s SessId=%d Strm=%s len=%d\n",
FI_to_ascii(rec.FileIndex), rec.VolSessionId,
- stream_to_ascii(rec.Stream), rec.data_len);
+ stream_to_ascii(rec.Stream, rec.FileIndex), rec.data_len);
+
/* Send attributes and MD5 to Director for Catalog */
- if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_MD5_SIGNATURE) {
- if (!dir_update_file_attributes(jcr, &rec)) {
- ok = FALSE;
- break;
+ if (stream == STREAM_UNIX_ATTRIBUTES || stream == STREAM_MD5_SIGNATURE ||
+ stream == STREAM_WIN32_ATTRIBUTES) {
+ if (!jcr->no_attributes) {
+ if (jcr->spool_attributes && jcr->dir_bsock->spool_fd) {
+ jcr->dir_bsock->spool = 1;
+ }
+ Dmsg0(200, "Send attributes.\n");
+ if (!dir_update_file_attributes(jcr, &rec)) {
+ Jmsg(jcr, M_FATAL, 0, _("Error updating file attributes. ERR=%s\n"),
+ bnet_strerror(jcr->dir_bsock));
+ ok = FALSE;
+ jcr->dir_bsock->spool = 0;
+ break;
+ }
+ jcr->dir_bsock->spool = 0;
}
}
- ASSERT(dsmsg == ds->msg);
- ASSERT(dsmsg == rec.data);
sm_check(__FILE__, __LINE__, False);
}
- if (n < 0) {
+ if (is_bnet_error(ds)) {
Jmsg1(jcr, M_FATAL, 0, _("Network error on data channel. ERR=%s\n"),
bnet_strerror(ds));
ok = FALSE;
}
}
/*
- *******FIXME***** we should put the ok status in the End of
- * session label
- *
* We probably need a new flag that says "Do not attempt
* to write because there is no tape".
*/
sm_check(__FILE__, __LINE__, False);
Dmsg0(90, "Write_end_session_label()\n");
+ /* Create Job status for end of session label */
+ if (!job_cancelled(jcr) && ok) {
+ jcr->JobStatus = JS_Terminated;
+ } else if (!ok) {
+ jcr->JobStatus = JS_ErrorTerminated;
+ }
if (!write_session_label(jcr, block, EOS_LABEL)) {
Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
strerror_dev(dev));
}
/* Write out final block of this session */
if (!write_block_to_device(jcr, dev, block)) {
- Dmsg0(0, "Set ok=FALSE after write_block_to_device.\n");
+ Pmsg0(000, "Set ok=FALSE after write_block_to_device.\n");
ok = FALSE;
}
/* Release the device */
- if (!release_device(jcr, dev, block)) {
- Dmsg0(0, "Error in release_device\n");
+ if (!release_device(jcr, dev)) {
+ Pmsg0(000, "Error in release_device\n");
ok = FALSE;
}
free_block(block);
+
+ if (jcr->spool_attributes && jcr->dir_bsock->spool_fd) {
+ bnet_despool(jcr->dir_bsock);
+ close_spool_file(jcr, jcr->dir_bsock);
+ }
+
Dmsg0(90, "return from do_append_data()\n");
return ok ? 1 : 0;
}