From: Kern Sibbald Date: Sun, 23 Nov 2003 09:17:44 +0000 (+0000) Subject: Add TwoEOF directive + enhance fill command X-Git-Tag: Release-1.34.0~334 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=5be61a56caa85960928992648bf180c0d3926e2a;p=bacula%2Fbacula Add TwoEOF directive + enhance fill command git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@813 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/cats/sql_update.c b/bacula/src/cats/sql_update.c index b0bf2462bf..5ab98254d6 100644 --- a/bacula/src/cats/sql_update.c +++ b/bacula/src/cats/sql_update.c @@ -304,7 +304,7 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) void db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) { - if (mr->InChanger != 0) { + if (mr->InChanger != 0 && mr->Slot != 0) { Mmsg(&mdb->cmd, "UPDATE Media SET InChanger=0 WHERE PoolId=%u " "AND Slot=%d\n", mr->PoolId, mr->Slot); Dmsg1(400, "%s\n", mdb->cmd); diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index c319f7c2cc..c5eda8b876 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -61,7 +61,7 @@ static int32_t read_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes) errno = 0; nread = read(bsock->fd, ptr, nleft); if (bsock->timed_out || bsock->terminated) { - Dmsg1(000, "timed_out = %d\n", bsock->timed_out); + Dmsg1(400, "timed_out = %d\n", bsock->timed_out); return nread; } } while (nread == -1 && (errno == EINTR || errno == EAGAIN)); diff --git a/bacula/src/stored/block.c b/bacula/src/stored/block.c index cecb013f57..23bc1b4e89 100644 --- a/bacula/src/stored/block.c +++ b/bacula/src/stored/block.c @@ -410,11 +410,15 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) Jmsg(jcr, M_INFO, 0, _("User defined maximum volume capacity %s exceeded on device %s.\n"), edit_uint64(max_cap, ed1), dev->dev_name); block->write_failed = true; - weof_dev(dev, 1); /* end the tape */ + if (weof_dev(dev, 1) != 0) { /* end tape */ + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + } /* Don't do update after second EOF or file count will be wrong */ Dmsg0(100, "dir_update_volume_info\n"); dir_update_volume_info(jcr, dev, 0); - weof_dev(dev, 1); + if (dev_cap(dev, CAP_TWOEOF) && weof_dev(dev, 1) != 0) { /* write eof */ + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + } dev->state |= (ST_EOF | ST_EOT | ST_WEOT); return 0; } @@ -491,10 +495,12 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) wlen, stat, dev->block_num, block->BlockNumber, dev->dev_errno, strerror(dev->dev_errno)); block->write_failed = true; - weof_dev(dev,1); + if (weof_dev(dev, 1) != 0) { /* end the tape */ + Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); + } Dmsg0(100, "dir_update_volume_info\n"); dir_update_volume_info(jcr, dev, 0); - if (weof_dev(dev, 1) != 0) { /* end the tape */ + if (dev_cap(dev, CAP_TWOEOF) && weof_dev(dev, 1) != 0) { /* end the tape */ Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); } dev->state |= (ST_EOF | ST_EOT | ST_WEOT); @@ -504,14 +510,19 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block) #ifdef CHECK_LAST_BLOCK /* * If the device is a tape and it supports backspace record, - * we backspace over two eof marks and over the last record, + * we backspace over one or two eof marks depending on + * how many we just wrote, then over the last record, * then re-read it and verify that the block number is * correct. */ if (dev->state & ST_TAPE && dev_cap(dev, CAP_BSR)) { /* Now back up over what we wrote and read the last block */ - if (!bsf_dev(dev, 1) || !bsf_dev(dev, 1)) { + if (!bsf_dev(dev, 1)) { + ok = false; + Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), strerror(dev->dev_errno)); + } + if (ok && dev_cap(dev, CAP_TWOEOF) && !bsf_dev(dev, 1)) { ok = false; Jmsg(jcr, M_ERROR, 0, _("Backspace file at EOT failed. ERR=%s\n"), strerror(dev->dev_errno)); } diff --git a/bacula/src/stored/btape.c b/bacula/src/stored/btape.c index 8adcdc0e0b..4cd158d7b7 100644 --- a/bacula/src/stored/btape.c +++ b/bacula/src/stored/btape.c @@ -559,8 +559,8 @@ static int re_read_block_test() } Pmsg0(-1, _("\n=== Write, backup, and re-read test ===\n\n" - "I'm going to write three records and two eof's\n" - "then backup over the eof's and re-read the last record.\n" + "I'm going to write three records and an eof\n" + "then backup over the eof and re-read the last record.\n" "Bacula does this after writing the last block on the\n" "tape to verify that the block was written correctly.\n" "It is not an *essential* feature ...\n\n")); @@ -603,16 +603,20 @@ static int re_read_block_test() Pmsg1(0, _("Wrote third record of %d bytes.\n"), rec->data_len); } weofcmd(); - weofcmd(); - if (!bsf_dev(dev, 1)) { - Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev)); - goto bail_out; + if (dev_cap(dev, CAP_TWOEOF)) { + weofcmd(); } if (!bsf_dev(dev, 1)) { Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev)); goto bail_out; } - Pmsg0(0, "Backspaced over two EOFs OK.\n"); + if (dev_cap(dev, CAP_TWOEOF)) { + if (!bsf_dev(dev, 1)) { + Pmsg1(0, _("Backspace file failed! ERR=%s\n"), strerror_dev(dev)); + goto bail_out; + } + } + Pmsg0(0, "Backspaced over EOF OK.\n"); if (!bsr_dev(dev, 1)) { Pmsg1(0, _("Backspace record failed! ERR=%s\n"), strerror_dev(dev)); goto bail_out; @@ -1486,6 +1490,7 @@ This may take a long time -- hours! ...\n\n"); static void unfillcmd() { DEV_BLOCK *block; + uint32_t i; dumped = 0; VolBytes = 0; @@ -1543,7 +1548,7 @@ static void unfillcmd() Pmsg1(-1, _("Forward space to file %u complete. Reading blocks ...\n"), last_file); Pmsg1(-1, _("Now reading to block %u.\n"), last_block_num); - for (uint32_t i=0; i <= last_block_num; i++) { + for (i=0; i <= last_block_num; i++) { if (!read_block_from_device(jcr, dev, block, NO_BLOCK_NUMBER_CHECK)) { Pmsg1(-1, _("Error reading blocks: ERR=%s\n"), strerror_dev(dev)); Pmsg2(-1, _("Wanted block %u error at block %u\n"), last_block_num, i); @@ -1554,11 +1559,32 @@ static void unfillcmd() } } if (last_block) { - dump_block(last_block, _("Last block written")); - dump_block(block, _("Block read back")); - Pmsg0(-1, _("Except for the buffer address, the contents of\n" - "the above two block dumps should be the same.\n" - "If not you have a problem ...\n")); + char *p, *q; + uint32_t CheckSum, block_len; + ser_declare; + p = last_block->buf; + q = block->buf; + unser_begin(q, BLKHDR1_LENGTH); + unser_uint32(CheckSum); + unser_uint32(block_len); + while (q < (block->buf+block_len+BLKHDR2_LENGTH)) { + if (*p++ == *q++) { + continue; + } + Pmsg0(-1, "\n"); + dump_block(last_block, _("Last block written")); + dump_block(block, _("Block read back")); + Pmsg0(-1, "\n\n!!!! The last block written and the block\n" + "that was read back differ. The test FAILED !!!!\n" + "This must be corrected before you use Bacula\n" + "to write multi-tape Volumes.!!!!\n"); + goto bail_out; + } + Pmsg0(-1, _("\nThe blocks are identical. Test succeeded.\n")); + if (verbose) { + dump_block(last_block, _("Last block written")); + dump_block(block, _("Block read back")); + } } } @@ -1694,7 +1720,6 @@ static int flush_block(DEV_BLOCK *block, int dump) free_memory(this_block->buf); memcpy(this_block, block, sizeof(DEV_BLOCK)); this_block->buf = get_memory(block->buf_len); - memcpy(this_block->buf, block->buf, this_block->buf_len); this_file = dev->file; this_block_num = dev->block_num; if (!write_block_to_dev(jcr, dev, block)) { @@ -1736,6 +1761,8 @@ static int flush_block(DEV_BLOCK *block, int dump) unlock_device(dev); return 1; /* end of tape reached */ } + /* Save contents after write so that the header is serialized */ + memcpy(this_block->buf, block->buf, this_block->buf_len); /* * Toggle between two allocated blocks for efficiency. @@ -1799,7 +1826,9 @@ static void qfillcmd() } printf("\n"); weofcmd(); - weofcmd(); + if (dev_cap(dev, CAP_TWOEOF)) { + weofcmd(); + } rewindcmd(); scan_blocks(); diff --git a/bacula/src/stored/dev.h b/bacula/src/stored/dev.h index 61e7703035..3f27bd8170 100644 --- a/bacula/src/stored/dev.h +++ b/bacula/src/stored/dev.h @@ -83,6 +83,7 @@ #define CAP_STREAM (1<<14) /* Stream device */ #define CAP_BSFATEOM (1<<15) /* Backspace file at EOM */ #define CAP_FASTFSF (1<<16) /* Fast forward space file */ +#define CAP_TWOEOF (1<<17) /* Write two eofs for EOM */ /* Test state */ #define dev_state(dev, st_state) ((dev)->state & (st_state)) diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index fd26b51be2..d9f2cfa40c 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -90,6 +90,7 @@ static struct res_items dev_items[] = { {"backwardspacerecord", store_yesno, ITEM(res_dev.cap_bits), CAP_BSR, ITEM_DEFAULT, 1}, {"backwardspacefile", store_yesno, ITEM(res_dev.cap_bits), CAP_BSF, ITEM_DEFAULT, 1}, {"bsfateom", store_yesno, ITEM(res_dev.cap_bits), CAP_BSFATEOM, ITEM_DEFAULT, 0}, + {"twoeof", store_yesno, ITEM(res_dev.cap_bits), CAP_TWOEOF, ITEM_DEFAULT, 0}, {"forwardspacerecord", store_yesno, ITEM(res_dev.cap_bits), CAP_FSR, ITEM_DEFAULT, 1}, {"forwardspacefile", store_yesno, ITEM(res_dev.cap_bits), CAP_FSF, ITEM_DEFAULT, 1}, {"fastforwardspacefile", store_yesno, ITEM(res_dev.cap_bits), CAP_FASTFSF, ITEM_DEFAULT, 1}, @@ -127,7 +128,7 @@ struct s_res resources[] = { {"storage", store_items, R_STORAGE, NULL}, {"device", dev_items, R_DEVICE, NULL}, {"messages", msgs_items, R_MSGS, NULL}, - {NULL, NULL, 0, NULL} + {NULL, NULL, 0, NULL} }; @@ -143,82 +144,82 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ... return; } sendit(sock, "dump_resource type=%d\n", type); - if (type < 0) { /* no recursion */ + if (type < 0) { /* no recursion */ type = - type; recurse = 0; } switch (type) { case R_DIRECTOR: sendit(sock, "Director: name=%s\n", res->res_dir.hdr.name); - break; + break; case R_STORAGE: sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n", - res->res_store.hdr.name, NPRT(res->res_store.SDaddr), - res->res_store.SDport, res->res_store.SDDport, - edit_utime(res->res_store.heartbeat_interval, buf)); - break; + res->res_store.hdr.name, NPRT(res->res_store.SDaddr), + res->res_store.SDport, res->res_store.SDDport, + edit_utime(res->res_store.heartbeat_interval, buf)); + break; case R_DEVICE: sendit(sock, "Device: name=%s MediaType=%s Device=%s\n", - res->res_dev.hdr.name, - res->res_dev.media_type, res->res_dev.device_name); + res->res_dev.hdr.name, + res->res_dev.media_type, res->res_dev.device_name); sendit(sock, " rew_wait=%d min_bs=%d max_bs=%d\n", - res->res_dev.max_rewind_wait, res->res_dev.min_block_size, - res->res_dev.max_block_size); + res->res_dev.max_rewind_wait, res->res_dev.min_block_size, + res->res_dev.max_block_size); sendit(sock, " max_jobs=%d max_files=%" lld " max_size=%" lld "\n", - res->res_dev.max_volume_jobs, res->res_dev.max_volume_files, - res->res_dev.max_volume_size); + res->res_dev.max_volume_jobs, res->res_dev.max_volume_files, + res->res_dev.max_volume_size); sendit(sock, " max_file_size=%" lld " capacity=%" lld "\n", - res->res_dev.max_file_size, res->res_dev.volume_capacity); + res->res_dev.max_file_size, res->res_dev.volume_capacity); strcpy(buf, " "); - if (res->res_dev.cap_bits & CAP_EOF) { + if (res->res_dev.cap_bits & CAP_EOF) { strcat(buf, "CAP_EOF "); - } - if (res->res_dev.cap_bits & CAP_BSR) { + } + if (res->res_dev.cap_bits & CAP_BSR) { strcat(buf, "CAP_BSR "); - } - if (res->res_dev.cap_bits & CAP_BSF) { + } + if (res->res_dev.cap_bits & CAP_BSF) { strcat(buf, "CAP_BSF "); - } - if (res->res_dev.cap_bits & CAP_FSR) { + } + if (res->res_dev.cap_bits & CAP_FSR) { strcat(buf, "CAP_FSR "); - } - if (res->res_dev.cap_bits & CAP_FSF) { + } + if (res->res_dev.cap_bits & CAP_FSF) { strcat(buf, "CAP_FSF "); - } - if (res->res_dev.cap_bits & CAP_EOM) { + } + if (res->res_dev.cap_bits & CAP_EOM) { strcat(buf, "CAP_EOM "); - } - if (res->res_dev.cap_bits & CAP_REM) { + } + if (res->res_dev.cap_bits & CAP_REM) { strcat(buf, "CAP_REM "); - } - if (res->res_dev.cap_bits & CAP_RACCESS) { + } + if (res->res_dev.cap_bits & CAP_RACCESS) { strcat(buf, "CAP_RACCESS "); - } - if (res->res_dev.cap_bits & CAP_AUTOMOUNT) { + } + if (res->res_dev.cap_bits & CAP_AUTOMOUNT) { strcat(buf, "CAP_AUTOMOUNT "); - } - if (res->res_dev.cap_bits & CAP_LABEL) { + } + if (res->res_dev.cap_bits & CAP_LABEL) { strcat(buf, "CAP_LABEL "); - } - if (res->res_dev.cap_bits & CAP_ANONVOLS) { + } + if (res->res_dev.cap_bits & CAP_ANONVOLS) { strcat(buf, "CAP_ANONVOLS "); - } - if (res->res_dev.cap_bits & CAP_ALWAYSOPEN) { + } + if (res->res_dev.cap_bits & CAP_ALWAYSOPEN) { strcat(buf, "CAP_ALWAYSOPEN "); - } + } strcat(buf, "\n"); - sendit(sock, buf); - break; + sendit(sock, buf); + break; case R_MSGS: sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name); - if (res->res_msgs.mail_cmd) + if (res->res_msgs.mail_cmd) sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd); - if (res->res_msgs.operator_cmd) + if (res->res_msgs.operator_cmd) sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd); - break; + break; default: sendit(sock, _("Warning: unknown resource type %d\n"), type); - break; + break; } if (recurse && res->res_dir.hdr.next) dump_resource(type, (RES *)res->res_dir.hdr.next, sendit, sock); @@ -253,57 +254,57 @@ void free_resource(int type) switch (type) { case R_DIRECTOR: - if (res->res_dir.password) { - free(res->res_dir.password); - } - if (res->res_dir.address) { - free(res->res_dir.address); - } - break; + if (res->res_dir.password) { + free(res->res_dir.password); + } + if (res->res_dir.address) { + free(res->res_dir.address); + } + break; case R_STORAGE: - if (res->res_store.address) { /* ***FIXME*** deprecated */ - free(res->res_store.address); - } - if (res->res_store.SDaddr) { - free(res->res_store.SDaddr); - } - if (res->res_store.working_directory) { - free(res->res_store.working_directory); - } - if (res->res_store.pid_directory) { - free(res->res_store.pid_directory); - } - if (res->res_store.subsys_directory) { - free(res->res_store.subsys_directory); - } - break; + if (res->res_store.address) { /* ***FIXME*** deprecated */ + free(res->res_store.address); + } + if (res->res_store.SDaddr) { + free(res->res_store.SDaddr); + } + if (res->res_store.working_directory) { + free(res->res_store.working_directory); + } + if (res->res_store.pid_directory) { + free(res->res_store.pid_directory); + } + if (res->res_store.subsys_directory) { + free(res->res_store.subsys_directory); + } + break; case R_DEVICE: - if (res->res_dev.media_type) { - free(res->res_dev.media_type); - } - if (res->res_dev.device_name) { - free(res->res_dev.device_name); - } - if (res->res_dev.changer_name) { - free(res->res_dev.changer_name); - } - if (res->res_dev.changer_command) { - free(res->res_dev.changer_command); - } - break; + if (res->res_dev.media_type) { + free(res->res_dev.media_type); + } + if (res->res_dev.device_name) { + free(res->res_dev.device_name); + } + if (res->res_dev.changer_name) { + free(res->res_dev.changer_name); + } + if (res->res_dev.changer_command) { + free(res->res_dev.changer_command); + } + break; case R_MSGS: - if (res->res_msgs.mail_cmd) { - free(res->res_msgs.mail_cmd); - } - if (res->res_msgs.operator_cmd) { - free(res->res_msgs.operator_cmd); - } - free_msgs_res((MSGS *)res); /* free message resource */ - res = NULL; - break; + if (res->res_msgs.mail_cmd) { + free(res->res_msgs.mail_cmd); + } + if (res->res_msgs.operator_cmd) { + free(res->res_msgs.operator_cmd); + } + free_msgs_res((MSGS *)res); /* free message resource */ + res = NULL; + break; default: Dmsg1(0, "Unknown resource type %d\n", type); - break; + break; } /* Common stuff again -- free the resource, recurse to next one */ if (res) { @@ -331,10 +332,10 @@ void save_resource(int type, struct res_items *items, int pass) */ for (i=0; items[i].name; i++) { if (items[i].flags & ITEM_REQUIRED) { - if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) { + if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) { Emsg2(M_ABORT, 0, _("%s item is required in %s resource, but not found.\n"), - items[i].name, resources[rindex]); - } + items[i].name, resources[rindex]); + } } /* If this triggers, take a look at lib/parse_conf.h */ if (i >= MAX_RES_ITEMS) { @@ -349,33 +350,33 @@ void save_resource(int type, struct res_items *items, int pass) */ if (pass == 2) { switch (type) { - /* Resources not containing a resource */ - case R_DIRECTOR: - case R_DEVICE: - case R_MSGS: - break; - - /* Resources containing a resource */ - case R_STORAGE: - if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) { + /* Resources not containing a resource */ + case R_DIRECTOR: + case R_DEVICE: + case R_MSGS: + break; + + /* Resources containing a resource */ + case R_STORAGE: + if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) { Emsg1(M_ABORT, 0, "Cannot find Storage resource %s\n", res_all.res_dir.hdr.name); - } - res->res_store.messages = res_all.res_store.messages; - break; - default: + } + res->res_store.messages = res_all.res_store.messages; + break; + default: printf("Unknown resource type %d\n", type); - error = 1; - break; + error = 1; + break; } if (res_all.res_dir.hdr.name) { - free(res_all.res_dir.hdr.name); - res_all.res_dir.hdr.name = NULL; + free(res_all.res_dir.hdr.name); + res_all.res_dir.hdr.name = NULL; } if (res_all.res_dir.hdr.desc) { - free(res_all.res_dir.hdr.desc); - res_all.res_dir.hdr.desc = NULL; + free(res_all.res_dir.hdr.desc); + res_all.res_dir.hdr.desc = NULL; } return; } @@ -383,42 +384,42 @@ void save_resource(int type, struct res_items *items, int pass) /* The following code is only executed on pass 1 */ switch (type) { case R_DIRECTOR: - size = sizeof(DIRRES); - break; + size = sizeof(DIRRES); + break; case R_STORAGE: - size = sizeof(STORES); - break; + size = sizeof(STORES); + break; case R_DEVICE: - size = sizeof(DEVRES); - break; + size = sizeof(DEVRES); + break; case R_MSGS: - size = sizeof(MSGS); - break; + size = sizeof(MSGS); + break; default: printf("Unknown resource type %d\n", type); - error = 1; - size = 1; - break; + error = 1; + size = 1; + break; } /* Common */ if (!error) { res = (URES *)malloc(size); memcpy(res, &res_all, size); if (!resources[rindex].res_head) { - resources[rindex].res_head = (RES *)res; /* store first entry */ + resources[rindex].res_head = (RES *)res; /* store first entry */ } else { - RES *next; - /* Add new res to end of chain */ - for (next=resources[rindex].res_head; next->next; next=next->next) { - if (strcmp(next->name, res->res_dir.hdr.name) == 0) { - Emsg2(M_ERROR_TERM, 0, + RES *next; + /* Add new res to end of chain */ + for (next=resources[rindex].res_head; next->next; next=next->next) { + if (strcmp(next->name, res->res_dir.hdr.name) == 0) { + Emsg2(M_ERROR_TERM, 0, _("Attempt to define second %s resource named \"%s\" is not permitted.\n"), - resources[rindex].name, res->res_dir.hdr.name); - } - } - next->next = (RES *)res; + resources[rindex].name, res->res_dir.hdr.name); + } + } + next->next = (RES *)res; Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type), - res->res_dir.hdr.name); + res->res_dir.hdr.name); } } } diff --git a/bacula/src/version.h b/bacula/src/version.h index 2c7f9eb13b..37a20c933d 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -2,8 +2,8 @@ #undef VERSION #define VERSION "1.33" #define VSTRING "1" -#define BDATE "20 Nov 2003" -#define LSMDATE "20Nov03" +#define BDATE "22 Nov 2003" +#define LSMDATE "22Nov03" /* Debug flags */ #undef DEBUG