/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
This program is Free Software; you can redistribute it and/or
- modify it under the terms of version two of the GNU General Public
+ modify it under the terms of version three of the GNU Affero General Public
License as published by the Free Software Foundation and included
in the file LICENSE.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
* Note, this program reads stored.conf, and will only
* talk to devices that are configured.
*
- * Version $Id$
- *
*/
#include "bacula.h"
static uint64_t vol_size;
static uint64_t VolBytes;
static time_t now;
-static double kbs;
static int32_t file_index;
static int end_of_tape = 0;
static uint32_t LastBlock = 0;
bindtextdomain("bacula", LOCALEDIR);
textdomain("bacula");
init_stack_dump();
+ lmgr_init_thread();
/* Sanity checks */
if (TAPE_BSIZE % B_DEV_BSIZE != 0 || TAPE_BSIZE / B_DEV_BSIZE == 0) {
static void terminate_btape(int stat)
{
- sm_check(__FILE__, __LINE__, false);
+ Dsm_check(200);
+ free_jcr(jcr);
+ jcr = NULL;
+
if (configfile) {
free(configfile);
}
free_bsr(bsr);
}
- free_jcr(jcr);
- jcr = NULL;
free_volume_lists();
static void print_total_speed()
{
- char ec1[50];
- kbs = (double)total_size / (1000 * total_time);
- Pmsg2(000, _("TotalVolumeCapacity=%s. Total Write rate = %.1f KB/s\n"),
- edit_uint64_with_commas(total_size, ec1), kbs);
+ char ec1[50], ec2[50];
+ uint64_t rate = total_size / total_time;
+ Pmsg2(000, _("Total Volume bytes=%sB. Total Write rate = %sB/s\n"),
+ edit_uint64_with_suffix(total_size, ec1),
+ edit_uint64_with_suffix(rate, ec2));
}
static void init_speed()
static void print_speed(uint64_t bytes)
{
- char ec1[50];
+ char ec1[50], ec2[50];
+ uint64_t rate;
+
now = time(NULL);
now -= jcr->run_time;
if (now <= 0) {
total_time += now;
total_size += bytes;
- kbs = (double)bytes / (1000 * now);
- Pmsg2(000, _("VolumeCapacity=%s. Write rate = %.1f KB/s\n"),
- edit_uint64_with_commas(bytes, ec1), kbs);
+ rate = bytes / now;
+ Pmsg2(000, _("Volume bytes=%sB. Write rate = %sB/s\n"),
+ edit_uint64_with_suffix(bytes, ec1),
+ edit_uint64_with_suffix(rate, ec2));
}
+/*
+ * Helper that fill a buffer with random data or not
+ */
typedef enum {
FILL_RANDOM,
FILL_ZERO
}
}
+static void mix_buffer(fill_mode_t mode, char *data, uint32_t len)
+{
+ uint32_t i;
+ uint32_t *lp = (uint32_t *)data;
+
+ if (mode == FILL_ZERO) {
+ return;
+ }
+
+ lp[0] += lp[13];
+ for (i=1; i < (len-sizeof(uint32_t))/sizeof(uint32_t)-1; i+=100) {
+ lp[i] += lp[0];
+ }
+}
+
static bool open_the_device()
{
DEV_BLOCK *block;
return;
}
- sm_check(__FILE__, __LINE__, false);
+ Dsm_check(200);
block = new_block(dev);
rec = new_record();
rec->data = check_pool_memory_size(rec->data, i);
memset(rec->data, i & 0xFF, i);
rec->data_len = i;
- sm_check(__FILE__, __LINE__, false);
+ Dsm_check(200);
if (write_record_to_block(block, rec)) {
empty_block(block);
blkno++;
} else {
break;
}
- sm_check(__FILE__, __LINE__, false);
+ Dsm_check(200);
}
free_record(rec);
free_block(block);
- sm_check(__FILE__, __LINE__, false);
+ Dsm_check(200);
}
/*
DEV_BLOCK *block = dcr->block;
int stat;
uint32_t block_num = 0;
- uint32_t *p;
int my_errno;
- uint32_t i;
char ed1[200];
nb_gb *= 1024*1024*1024; /* convert size from nb to GB */
init_total_speed();
fill_buffer(mode, block->buf, block->buf_len);
- p = (uint32_t *)block->buf;
- Pmsg3(0, _("Begin writing %i files of %s raw blocks of %u bytes.\n"),
+ Pmsg3(0, _("Begin writing %i files of %sB with raw blocks of %u bytes.\n"),
nb, edit_uint64_with_suffix(nb_gb, ed1), block->buf_len);
for (uint32_t j=0; j<nb; j++) {
for ( ;jcr->JobBytes < nb_gb; ) {
stat = dev->d_write(dev->fd(), block->buf, block->buf_len);
if (stat == (int)block->buf_len) {
- if ((block_num++ % 1000) == 0) {
+ if ((block_num++ % 500) == 0) {
printf("+");
fflush(stdout);
}
- if (mode == FILL_RANDOM) {
- p[0] += p[13];
- for (i=1;
- i<(block->buf_len-sizeof(uint32_t))/sizeof(uint32_t)-1;
- i+=100)
- {
- p[i] += p[0];
- }
- }
+
+ mix_buffer(mode, block->buf, block->buf_len);
+
jcr->JobBytes += stat;
} else {
}
+static bool speed_test_bacula(fill_mode_t mode, uint64_t nb_gb, uint32_t nb)
+{
+ DEV_BLOCK *block = dcr->block;
+ char ed1[200];
+ DEV_RECORD *rec;
+ uint64_t last_bytes = dev->VolCatInfo.VolCatBytes;
+ uint64_t written=0;
+
+ nb_gb *= 1024*1024*1024; /* convert size from nb to GB */
+
+ init_total_speed();
+
+ empty_block(block);
+ rec = new_record();
+ rec->data = check_pool_memory_size(rec->data, block->buf_len);
+ rec->data_len = block->buf_len-100;
+
+ fill_buffer(mode, rec->data, rec->data_len);
+
+ Pmsg3(0, _("Begin writing %i files of %sB with blocks of %u bytes.\n"),
+ nb, edit_uint64_with_suffix(nb_gb, ed1), block->buf_len);
+
+ for (uint32_t j=0; j<nb; j++) {
+ written = 0;
+ init_speed();
+ for ( ; written < nb_gb; ) {
+
+ if (!write_record_to_block(block, rec)) {
+ Pmsg0(0, _("\nError writing record to block.\n"));
+ goto bail_out;
+ }
+ if (!write_block_to_dev(dcr)) {
+ Pmsg0(0, _("\nError writing block to device.\n"));
+ goto bail_out;
+ }
+
+ if ((block->BlockNumber % 500) == 0) {
+ printf("+");
+ fflush(stdout);
+ }
+ written += dev->VolCatInfo.VolCatBytes - last_bytes;
+ last_bytes = dev->VolCatInfo.VolCatBytes;
+ mix_buffer(mode, rec->data, rec->data_len);
+ }
+ printf("\n");
+ weofcmd();
+ print_speed(written);
+ }
+ print_total_speed();
+ printf("\n");
+ free_record(rec);
+ return true;
+
+bail_out:
+ free_record(rec);
+ return false;
+}
+
+/* TODO: use UAContext */
+static int btape_find_arg(const char *keyword)
+{
+ for (int i=1; i<argc; i++) {
+ if (strcasecmp(keyword, argk[i]) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
#define ok(a) if (!(a)) return
/*
*/
static void speed_test()
{
- dev->rewind(dcr);
- Pmsg0(0, _("Test with random data.\n"));
- ok(speed_test_raw(FILL_RANDOM, 1, 3));
- ok(speed_test_raw(FILL_RANDOM, 2, 3));
- ok(speed_test_raw(FILL_RANDOM, 4, 3));
-
- Pmsg0(0, _("Test with zero data.\n"));
- ok(speed_test_raw(FILL_ZERO, 1, 3));
- ok(speed_test_raw(FILL_ZERO, 2, 3));
- ok(speed_test_raw(FILL_ZERO, 4, 3));
+ bool do_zero=true, do_random=true, do_block=true, do_raw=true;
+ uint32_t file_size=0, nb_file=3;
+ int32_t i;
+
+ i = btape_find_arg("file_size");
+ if (i > 0) {
+ file_size = atoi(argv[i]);
+ if (file_size > 100) {
+ Pmsg0(0, _("The file_size is too big, stop this test with Ctrl-c.\n"));
+ }
+ }
+
+ i = btape_find_arg("nb_file");
+ if (i > 0) {
+ nb_file = atoi(argv[i]);
+ }
+
+ if (btape_find_arg("skip_zero") > 0) {
+ do_zero = false;
+ }
+
+ if (btape_find_arg("skip_random") > 0) {
+ do_random = false;
+ }
+
+ if (btape_find_arg("skip_raw") > 0) {
+ do_raw = false;
+ }
+
+ if (btape_find_arg("skip_block") > 0) {
+ do_block = false;
+ }
+
+ if (do_raw) {
+ dev->rewind(dcr);
+ if (do_zero) {
+ Pmsg0(0, _("Test with zero data, should give the "
+ "maximum throughput.\n"));
+ if (file_size) {
+ ok(speed_test_raw(FILL_ZERO, file_size, nb_file));
+ } else {
+ ok(speed_test_raw(FILL_ZERO, 1, nb_file));
+ ok(speed_test_raw(FILL_ZERO, 2, nb_file));
+ ok(speed_test_raw(FILL_ZERO, 4, nb_file));
+ }
+ }
+
+ if (do_random) {
+ Pmsg0(0, _("Test with random data, should give the minimum "
+ "throughput.\n"));
+ if (file_size) {
+ ok(speed_test_raw(FILL_RANDOM, file_size, nb_file));
+ } else {
+ ok(speed_test_raw(FILL_RANDOM, 1, nb_file));
+ ok(speed_test_raw(FILL_RANDOM, 2, nb_file));
+ ok(speed_test_raw(FILL_RANDOM, 4, nb_file));
+ }
+ }
+ }
+
+ if (do_block) {
+ dev->rewind(dcr);
+ if (do_zero) {
+ Pmsg0(0, _("Test with zero data and bacula block structure.\n"));
+ if (file_size) {
+ ok(speed_test_bacula(FILL_ZERO, file_size, nb_file));
+ } else {
+ ok(speed_test_bacula(FILL_ZERO, 1, nb_file));
+ ok(speed_test_bacula(FILL_ZERO, 2, nb_file));
+ ok(speed_test_bacula(FILL_ZERO, 4, nb_file));
+ }
+ }
+
+ if (do_random) {
+ Pmsg0(0, _("Test with random data, should give the minimum "
+ "throughput.\n"));
+ if (file_size) {
+ ok(speed_test_bacula(FILL_RANDOM, file_size, nb_file));
+ } else {
+ ok(speed_test_bacula(FILL_RANDOM, 1, nb_file));
+ ok(speed_test_bacula(FILL_RANDOM, 2, nb_file));
+ ok(speed_test_bacula(FILL_RANDOM, 4, nb_file));
+ }
+ }
+ }
}
const int num_recs = 10000;
int len, i, j;
int *p;
bool rc = false; /* bad return code */
+ DEVICE *dev = dcr->dev;
+ /*
+ * Set big max_file_size so that write_record_to_block
+ * doesn't insert any additional EOF marks
+ */
+ dev->max_file_size = 2 * num_recs * dev->max_block_size;
Pmsg2(-1, _("\n=== Write, rewind, and re-read test ===\n\n"
"I'm going to write %d records and an EOF\n"
"then write %d records and an EOF, then rewind,\n"
if (!dev->is_open()) {
open_the_device();
}
- sm_check(__FILE__, __LINE__, false);
+ Dsm_check(200);
empty_block(block);
if (verbose > 1) {
dump_block(block, "test");
rec->data = check_pool_memory_size(rec->data, i);
memset(rec->data, i & 0xFF, i);
rec->data_len = i;
- sm_check(__FILE__, __LINE__, false);
+ Dsm_check(200);
if (!write_record_to_block(block, rec)) {
Pmsg0(0, _("Error writing record to block.\n"));
goto bail_out;
Pmsg0(0, _("Wrote block to device.\n"));
bail_out:
- sm_check(__FILE__, __LINE__, false);
- sm_check(__FILE__, __LINE__, false);
+ Dsm_check(200);
}
/*
{
DEV_RECORD rec;
DEV_BLOCK *block = dcr->block;
- char ec1[50];
+ char ec1[50], ec2[50];
char buf1[100], buf2[100];
- uint32_t i;
uint64_t write_eof;
+ uint64_t rate;
uint32_t min_block_size;
int fd;
struct tm tm;
*/
Dmsg0(100, "just before acquire_device\n");
if (!acquire_device_for_append(dcr)) {
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ jcr->setJobStatus(JS_ErrorTerminated);
exit_code = 1;
return;
}
* Write Begin Session Record
*/
if (!write_session_label(dcr, SOS_LABEL)) {
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ jcr->setJobStatus(JS_ErrorTerminated);
Jmsg1(jcr, M_FATAL, 0, _("Write session label failed. ERR=%s\n"),
dev->bstrerror());
ok = false;
rec.VolSessionTime = jcr->VolSessionTime;
rec.FileIndex = ++file_index;
rec.Stream = STREAM_FILE_DATA;
+ rec.maskedStream = STREAM_FILE_DATA;
/* Mix up the data just a bit */
- uint32_t *lp = (uint32_t *)rec.data;
- lp[0] += lp[13];
- for (i=1; i < (rec.data_len-sizeof(uint32_t))/sizeof(uint32_t)-1; i+=100) {
- lp[i] += lp[0];
- }
+ mix_buffer(FILL_RANDOM, rec.data, rec.data_len);
Dmsg4(250, "before write_rec FI=%d SessId=%d Strm=%s len=%d\n",
rec.FileIndex, rec.VolSessionId,
/* Write block to tape */
if (!flush_block(block, 1)) {
+ Pmsg0(000, _("Flush block failed.\n"));
exit_code = 1;
break;
}
if (now <= 0) {
now = 1; /* prevent divide error */
}
- kbs = (double)dev->VolCatInfo.VolCatBytes / (1000.0 * (double)now);
- Pmsg5(-1, _("Wrote block=%u, file,blk=%u,%u VolBytes=%s rate=%.1f KB/s\n"),
+ rate = dev->VolCatInfo.VolCatBytes / now;
+ Pmsg5(-1, _("Wrote block=%u, file,blk=%u,%u VolBytes=%s rate=%sB/s\n"),
block->BlockNumber, dev->file, dev->block_num,
- edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1), (float)kbs);
+ edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1),
+ edit_uint64_with_suffix(rate, ec2));
}
/* Every X blocks (dev->max_file_size) write an EOF.
*/
now = time(NULL);
(void)localtime_r(&now, &tm);
strftime(buf1, sizeof(buf1), "%H:%M:%S", &tm);
- Pmsg1(-1, _("%s\n"), buf1);
-#ifdef needed_xxx
Pmsg1(-1, _("%s Flush block, write EOF\n"), buf1);
flush_block(block, 0);
+#ifdef needed_xxx
dev->weof(1);
#endif
}
- /* Get out after writing 10 blocks to the second tape */
- if (++BlockNumber > 10 && stop != 0) { /* get out */
+ /* Get out after writing 1000 blocks to the second tape */
+ if (++BlockNumber > 1000 && stop != 0) { /* get out */
+ Pmsg0(000, _("Wrote 1000 blocks on second tape. Done.\n"));
break;
}
}
FI_to_ascii(buf1, rec.FileIndex), rec.VolSessionId,
stream_to_ascii(buf2, rec.Stream, rec.FileIndex), rec.data_len);
- /* Get out after writing 10 blocks to the second tape */
- if (BlockNumber > 10 && stop != 0) { /* get out */
+ /* Get out after writing 1000 blocks to the second tape */
+ if (BlockNumber > 1000 && stop != 0) { /* get out */
char ed1[50];
Pmsg1(-1, "Done writing %s records ...\n",
edit_uint64_with_commas(write_count, ed1));
break;
}
- }
+ } /* end big for loop */
+
if (vol_num > 1) {
Dmsg0(100, "Write_end_session_label()\n");
/* Create Job status for end of session label */
if (!job_canceled(jcr) && ok) {
- set_jcr_job_status(jcr, JS_Terminated);
+ jcr->setJobStatus(JS_Terminated);
} else if (!ok) {
- set_jcr_job_status(jcr, JS_ErrorTerminated);
+ Pmsg0(000, _("Job canceled.\n"));
+ jcr->setJobStatus(JS_ErrorTerminated);
exit_code = 1;
}
if (!write_session_label(dcr, EOS_LABEL)) {
write(fd, last_block2->buf, last_block2->buf_len);
write(fd, first_block->buf, first_block->buf_len);
close(fd);
- Pmsg2(-1, _("Wrote state file last_block_num1=%d last_block_num2=%d\n"),
+ Pmsg2(0, _("Wrote state file last_block_num1=%d last_block_num2=%d\n"),
last_block_num1, last_block_num2);
} else {
berrno be;
- Pmsg2(-1, _("Could not create state file: %s ERR=%s\n"), buf,
+ Pmsg2(0, _("Could not create state file: %s ERR=%s\n"), buf,
be.bstrerror());
exit_code = 1;
+ ok = false;
}
now = time(NULL);
(void)localtime_r(&now, &tm);
strftime(buf1, sizeof(buf1), "%H:%M:%S", &tm);
- if (simple) {
- Pmsg3(-1, _("\n\n%s Done filling tape at %d:%d. Now beginning re-read of tape ...\n"),
- buf1, jcr->dcr->dev->file, jcr->dcr->dev->block_num);
- }
- else {
- Pmsg3(-1, _("\n\n%s Done filling tapes at %d:%d. Now beginning re-read of first tape ...\n"),
- buf1, jcr->dcr->dev->file, jcr->dcr->dev->block_num);
- }
+ if (ok) {
+ if (simple) {
+ Pmsg3(0, _("\n\n%s Done filling tape at %d:%d. Now beginning re-read of tape ...\n"),
+ buf1, jcr->dcr->dev->file, jcr->dcr->dev->block_num);
+ } else {
+ Pmsg3(0, _("\n\n%s Done filling tapes at %d:%d. Now beginning re-read of first tape ...\n"),
+ buf1, jcr->dcr->dev->file, jcr->dcr->dev->block_num);
+ }
- jcr->dcr->block = block;
- if (!do_unfill()) {
- exit_code = 1;
+ jcr->dcr->block = block;
+ if (!do_unfill()) {
+ Pmsg0(000, _("do_unfill failed.\n"));
+ exit_code = 1;
+ ok = false;
+ }
+ } else {
+ Pmsg1(000, _("%s: Error during test.\n"), buf1);
}
-
dev->min_block_size = min_block_size;
free_memory(rec.data);
}
this_block = NULL;
}
+/*
+ * This is the second part of the fill command. After the tape or
+ * tapes are written, we are called here to reread parts, particularly
+ * the last block.
+ */
static bool do_unfill()
{
DEV_BLOCK *block = dcr->block;
VolBytes = 0;
LastBlock = 0;
- Dmsg0(20, "Enter do_unfill\n");
+ Pmsg0(000, "Enter do_unfill\n");
dev->set_cap(CAP_ANONVOLS); /* allow reading any volume */
dev->clear_cap(CAP_LABEL); /* don't label anything here */
}
autochanger = autoload_device(dcr, 1, NULL);
if (autochanger != 1) {
+ Pmsg1(100, "Autochanger returned: %d\n", autochanger);
dev->close();
get_cmd(_("Mount first tape. Press enter when ready: "));
+ Pmsg0(000, "\n");
}
}
if (compare_blocks(last_block, block)) {
if (simple) {
Pmsg0(-1, _("\nThe last block on the tape matches. Test succeeded.\n\n"));
+ rc = true;
} else {
Pmsg0(-1, _("\nThe last block of the first tape matches.\n\n"));
}
autochanger = autoload_device(dcr, 1, NULL);
if (autochanger != 1) {
+ Pmsg1(100, "Autochanger returned: %d\n", autochanger);
dev->close();
get_cmd(_("Mount second tape. Press enter when ready: "));
+ Pmsg0(000, "\n");
}
dev->clear_read();
*/
static int flush_block(DEV_BLOCK *block, int dump)
{
- char ec1[50];
+ char ec1[50], ec2[50];
+ uint64_t rate;
DEV_BLOCK *tblock;
uint32_t this_file, this_block_num;
if (now <= 0) {
now = 1; /* don't divide by zero */
}
- kbs = (double)dev->VolCatInfo.VolCatBytes / (1000 * now);
+ rate = dev->VolCatInfo.VolCatBytes / now;
vol_size = dev->VolCatInfo.VolCatBytes;
- Pmsg4(000, _("End of tape %d:%d. VolumeCapacity=%s. Write rate = %.1f KB/s\n"),
+ Pmsg4(000, _("End of tape %d:%d. Volume Bytes=%s. Write rate = %sB/s\n"),
dev->file, dev->block_num,
- edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1), kbs);
+ edit_uint64_with_commas(dev->VolCatInfo.VolCatBytes, ec1),
+ edit_uint64_with_suffix(rate, ec2));
if (simple) {
stop = -1; /* stop, but do simplified test */
count = 1000;
}
- sm_check(__FILE__, __LINE__, false);
+ Dsm_check(200);
i = block->buf_len - 100;
ASSERT (i > 0);
scan_blocks();
bail_out:
- sm_check(__FILE__, __LINE__, false);
+ Dsm_check(200);
}
/*
uint32_t block_num = 0;
uint32_t *p;
int my_errno;
- uint32_t i;
fill_buffer(FILL_RANDOM, block->buf, block->buf_len);
init_speed();
printf("+");
fflush(stdout);
}
- p[0] += p[13];
- for (i=1; i<(block->buf_len-sizeof(uint32_t))/sizeof(uint32_t)-1; i+=100) {
- p[i] += p[0];
- }
+
+ mix_buffer(FILL_RANDOM, block->buf, block->buf_len);
+
jcr->JobBytes += stat;
continue;
}
{NT_("rewind"), rewindcmd, _("rewind the tape")},
{NT_("scan"), scancmd, _("read() tape block by block to EOT and report")},
{NT_("scanblocks"),scan_blocks, _("Bacula read block by block to EOT and report")},
- {NT_("speed"), speed_test, _("try different configuration and report drive speed")},
+ {NT_("speed"), speed_test, _("[file_size=n(GB)|nb_file=3|skip_zero|skip_random|skip_raw|skip_block] report drive speed")},
{NT_("status"), statcmd, _("print tape status")},
{NT_("test"), testcmd, _("General test Bacula tape functions")},
{NT_("weof"), weofcmd, _("write an EOF on the tape")},
bool found;
while (!quit && get_cmd("*")) {
- sm_check(__FILE__, __LINE__, false);
+ Dsm_check(200);
found = false;
parse_args(cmd, &args, &argc, argk, argv, MAX_CMD_ARGS);
for (i=0; i<comsize; i++) /* search for command */
bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing)
{
Dmsg0(20, "Enter dir_get_volume_info\n");
- bstrncpy(dcr->VolCatInfo.VolCatName, dcr->VolumeName, sizeof(dcr->VolCatInfo.VolCatName));
+ dcr->setVolCatName(dcr->VolumeName);
return 1;
}
}
autochanger = autoload_device(dcr, 1, NULL);
if (autochanger != 1) {
+ Pmsg1(100, "Autochanger returned: %d\n", autochanger);
fprintf(stderr, _("Mount blank Volume on device %s and press return when ready: "),
dev->print_name());
dev->close();
getchar();
+ Pmsg0(000, "\n");
}
labelcmd();
VolumeName = NULL;
static bool my_mount_next_read_volume(DCR *dcr)
{
- char ec1[50];
+ char ec1[50], ec2[50];
+ uint64_t rate;
JCR *jcr = dcr->jcr;
DEV_BLOCK *block = dcr->block;
if (now <= 0) {
now = 1;
}
- kbs = (double)VolBytes / (1000.0 * (double)now);
- Pmsg3(-1, _("Read block=%u, VolBytes=%s rate=%.1f KB/s\n"), block->BlockNumber,
- edit_uint64_with_commas(VolBytes, ec1), (float)kbs);
+ rate = VolBytes / now;
+ Pmsg3(-1, _("Read block=%u, VolBytes=%s rate=%sB/s\n"), block->BlockNumber,
+ edit_uint64_with_commas(VolBytes, ec1),
+ edit_uint64_with_suffix(rate, ec2));
if (strcmp(dcr->VolumeName, "TestVolume2") == 0) {
end_of_tape = 1;
DCR *dcr = jcr->dcr;
VolumeName = VolName;
vol_num = volnum;
- bstrncpy(dev->VolCatInfo.VolCatName, VolName, sizeof(dev->VolCatInfo.VolCatName));
- bstrncpy(dcr->VolCatInfo.VolCatName, VolName, sizeof(dcr->VolCatInfo.VolCatName));
+ dev->setVolCatName(VolName);
+ dcr->setVolCatName(VolName);
bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
dcr->VolCatInfo.Slot = volnum;
dcr->VolCatInfo.InChanger = true;