Major Changes this Release:
- Fixed gnome-console to compile with RH9 (Gnome 2.0)
-- Implemented a single routine to read_records.
+- Implemented a single routine to read_records. It also returns
+ a different record packet for each session. This means
+ that multiple simultaneous jobs should work.
- Implemented forward space file/block whenever possible.
- Added SDConnectTimeout to FD.
- Figure out how to use ssh or stunnel to protect Bacula communications.
For 1.32:
+- Is a pool specification really needed for a restore? Yes, and
+ you may want to exclude archive Pools.
- Look at libkse (man kse) for FreeBSD threading.
- Look into Microsoft Volume Shadowcopy Service VSS for backing
up system state components (Active Directory, System Volume, ...)
- Add ExhautiveRestoreSearch and use repositioning at the beginning
- of the tape.
-- Add Machine type (Linux/Windows) to Status report for daemons.
-- Document "status" in the console.
-- Document driving console from shell script.
+ of the tape.
- Specify list of files to restore
- Implement ClientRunBeforeJob and ClientRunAfterJob.
-- Restore file list.
-- Write JobMedia records with max file size is reached on tape.
- Look at the possibility of loading only the necessary
data into the restore tree (i.e. do it one directory at a
time as the user walks through the tree).
-- Possibly use the hash code if the user selects all.
-- Handle the case of multiple JobMedia records pending (i.e. the
- thread is slow and multiple situations requiring a JobMedia
- record occur).
-- Fix maximum file size (block.c) to generate JobMedia records.
-- Do performance analysis on the restore tree routines.
-- Implement forward spacing between files.
-- Make the default file size 1GB on the tape.
+- Possibly use the hash code if the user selects all for a restore command.
- Orphaned Dir buffer at parse_conf.c:373 => store_dir
- Implement some way for the File daemon to contact the Director
to start a job or pass its DHCP obtained IP number.
- Implement List Volume Job=xxx or List scheduled volumes or Status Director
- Allow a slot or range of slots on the label barcodes command.
- Implement a PostgreSQL driver.
-- Is a pool specification really needed for a restore?
- Bacula needs to propagate SD errors.
> > cluster-dir: Start Backup JobId 252, Job=REUTERS.2003-08-11_15.04.12
> > prod4-sd: REUTERS.2003-08-11_15.04.12 Error: Write error on device
- Fix read_record to handle multiple sessions.
- Tip from Steve Allam
mt -f /dev/nst0 defblksize 0
+- Document "status" in the console.
+- Document driving console from shell script.
+- Write JobMedia records with max file size is reached on tape.
+- Handle the case of multiple JobMedia records pending (i.e. the
+ thread is slow and multiple situations requiring a JobMedia
+ record occur).
+- Do performance analysis on the restore tree routines.
+- Fix maximum file size (block.c) to generate JobMedia records.
+- Make the default file size 1GB on the tape.
+- Implement forward spacing between files.
+- Add Machine type (Linux/Windows) to Status report for daemons.
+ Look at src/host.h
+
static void usage()
{
fprintf(stderr, _(
-"\nVersion: " VERSION " (" BDATE ")\n\n"
+"\nVersion: " VERSION " (" BDATE ") %s %s %s\n\n"
"Usage: console [-s] [-c config_file] [-d debug_level] [config_file]\n"
" -c <file> set configuration file to file\n"
" -dnn set debug level to nn\n"
" -s no signals\n"
" -t test - read configuration and exit\n"
" -? print this message.\n"
-"\n"));
+"\n"), HOST_OS, DISTNAME, DISTVER);
exit(1);
}
static int versioncmd(FILE *input, BSOCK *UA_sock)
{
- sendit("Version: " VERSION " (" BDATE ")\n");
+ sendit("Version: " VERSION " (" BDATE ") %s %s %s\n",
+ HOST_OS, DISTNAME, DISTVER);
return 1;
}
char **out_ptr, int *out_len, int *out_size)
{
var_rc_t stat = VAR_ERR_UNDEFINED_OPERATION;
- Dmsg0(000, "Enter operate_var\n");
+// Dmsg0(000, "Enter operate_var\n");
if (!val_ptr) {
*out_size = 0;
return stat;
}
memcpy(buf, arg_ptr, arg_len);
buf[arg_len] = 0;
- Dmsg1(000, "Arg=%s\n", buf);
+// Dmsg1(000, "Arg=%s\n", buf);
memcpy(buf, val_ptr, val_len);
buf[val_len] = 0;
- Dmsg1(000, "Val=%s\n", buf);
+// Dmsg1(000, "Val=%s\n", buf);
LockRes();
for (COUNTER *counter=NULL; (counter = (COUNTER *)GetNextRes(R_COUNTER, (RES *)counter)); ) {
if (strcmp(counter->hdr.name, buf) == 0) {
- Dmsg2(000, "counter=%s val=%s\n", counter->hdr.name, buf);
+// Dmsg2(000, "counter=%s val=%s\n", counter->hdr.name, buf);
break;
}
}
extern char *list_pool;
/* Imported functions */
-extern int statuscmd(UAContext *ua, char *cmd);
+extern int status_cmd(UAContext *ua, char *cmd);
extern int listcmd(UAContext *ua, char *cmd);
extern int llistcmd(UAContext *ua, char *cmd);
extern int show_cmd(UAContext *ua, char *cmd);
extern int update_slots(UAContext *ua); /* ua_label.c */
/* Forward referenced functions */
-static int add_cmd(UAContext *ua, char *cmd), createcmd(UAContext *ua, char *cmd), cancelcmd(UAContext *ua, char *cmd);
+static int add_cmd(UAContext *ua, char *cmd);
+static int create_cmd(UAContext *ua, char *cmd);
+static int cancel_cmd(UAContext *ua, char *cmd);
static int setdebug_cmd(UAContext *ua, char *cmd);
static int var_cmd(UAContext *ua, char *cmd);
static int estimate_cmd(UAContext *ua, char *cmd);
{ N_("add"), add_cmd, _("add media to a pool")},
{ N_("autodisplay"), autodisplaycmd, _("autodisplay [on/off] -- console messages")},
{ N_("automount"), automount_cmd, _("automount [on/off] -- after label")},
- { N_("cancel"), cancelcmd, _("cancel job=nnn -- cancel a job")},
- { N_("create"), createcmd, _("create DB Pool from resource")},
+ { N_("cancel"), cancel_cmd, _("cancel job=nnn -- cancel a job")},
+ { N_("create"), create_cmd, _("create DB Pool from resource")},
{ N_("delete"), delete_cmd, _("delete [pool=<pool-name> | media volume=<volume-name>]")},
{ N_("estimate"), estimate_cmd, _("performs FileSet estimate, listing gives full listing")},
{ N_("exit"), quit_cmd, _("exit = quit")},
{ N_("setdebug"), setdebug_cmd, _("sets debug level")},
{ N_("show"), show_cmd, _("show (resource records) [jobs | pools | ... | all]")},
{ N_("sqlquery"), sqlquerycmd, _("use SQL to query catalog")},
- { N_("status"), statuscmd, _("status [storage | client]=<name>")},
+ { N_("status"), status_cmd, _("status [storage | client]=<name>")},
{ N_("time"), time_cmd, _("print current time")},
{ N_("unmount"), unmount_cmd, _("unmount <storage-name>")},
{ N_("update"), update_cmd, _("update Volume or Pool")},
/*
* Cancel a job
*/
-static int cancelcmd(UAContext *ua, char *cmd)
+static int cancel_cmd(UAContext *ua, char *cmd)
{
int i;
int njobs = 0;
* Create a Pool Record in the database.
* It is always created from the Resource record.
*/
-static int createcmd(UAContext *ua, char *cmd)
+static int create_cmd(UAContext *ua, char *cmd)
{
POOL *pool;
/*
* status command
*/
-int statuscmd(UAContext *ua, char *cmd)
+int status_cmd(UAContext *ua, char *cmd)
{
STORE *store;
CLIENT *client;
int pool_mem = FALSE;
Dmsg0(200, "Doing status\n");
- bsendmsg(ua, "%s Version: " VERSION " (" BDATE ")\n", my_name);
+ bsendmsg(ua, "%s Version: " VERSION " (" BDATE ") %s %s %s\n", my_name,
+ HOST_OS, DISTNAME, DISTVER);
bstrftime(dt, sizeof(dt), daemon_start_time);
bsendmsg(ua, _("Daemon started %s, %d Job%s run.\n"), dt, last_job.NumJobs,
last_job.NumJobs == 1 ? "" : "s");
msg = (char *)get_pool_memory(PM_MESSAGE);
found = 0;
- len = Mmsg(&msg, "%s Version: " VERSION " (" BDATE ")\n", my_name);
+ len = Mmsg(&msg, "%s Version: " VERSION " (" BDATE ") %s %s %s\n", my_name,
+ HOST_OS, DISTNAME, DISTVER);
sendit(msg, len, arg);
bstrftime(dt, sizeof(dt), daemon_start_time);
len = Mmsg(&msg, _("Daemon started %s, %d Job%s run.\n"), dt, last_job.NumJobs,
void htable::grow_table()
{
- Dmsg1(000, "Grow called old size = %d\n", buckets);
+ Dmsg1(100, "Grow called old size = %d\n", buckets);
/* Setup a bigger table */
htable *big = (htable *)malloc(sizeof(htable));
big->loffset = loffset;
}
if (!(bpipe=open_mail_pipe(jcr, &cmd, d))) {
- Dmsg0(000, "open mail pipe failed.\n");
+ Pmsg0(000, "open mail pipe failed.\n");
goto rem_temp_file;
}
Dmsg0(150, "Opened mail pipe\n");
fputs(line, bpipe->wfd);
}
if (!close_wpipe(bpipe)) { /* close write pipe sending mail */
- Dmsg1(000, "close error: ERR=%s\n", strerror(errno));
+ Pmsg1(000, "close error: ERR=%s\n", strerror(errno));
}
/*
}
}
if (repeats > 0) {
- Dmsg2(000, "Thread %d found unchanged elements %d times\n",
+ Pmsg2(000, "Thread %d found unchanged elements %d times\n",
self->thread_num, repeats);
}
return NULL;
}
#ifdef xxxx
for (int i=0; i < *argc; i++) {
- Dmsg3(000, "Arg %d: kw=%s val=%s\n", i, argk[i], argv[i]?argv[i]:"NULL");
+ Pmsg3(000, "Arg %d: kw=%s val=%s\n", i, argk[i], argv[i]?argv[i]:"NULL");
}
#endif
return 1;
}
}
if (repeats > 0) {
- Dmsg2(000, "Thread %d found unchanged elements %d times\n",
+ Pmsg2(000, "Thread %d found unchanged elements %d times\n",
self->thread_num, repeats);
}
return NULL;
attach_jcr_to_device(dev, jcr); /* attach jcr to device */
Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
jcr->VolumeName, dev_name(dev));
- if (jcr->bsr) {
- BSR *bsr;
-
- jcr->bsr->reposition = true;
- bsr = find_next_bsr(jcr->bsr, dev);
- if (bsr) {
- Jmsg(jcr, M_INFO, 0, _("Forward spacing to file:block %u:%u.\n"),
- bsr->volfile->sfile, bsr->volblock->sblock);
- reposition_dev(dev, bsr->volfile->sfile, bsr->volblock->sblock);
- } else if ((dev->state & ST_TAPE) && vol->start_file > 0) {
- Dmsg1(200, "====== Got start_file = %d\n", vol->start_file);
- Jmsg(jcr, M_INFO, 0, _("Forward spacing to file %d.\n"), vol->start_file);
- fsf_dev(dev, vol->start_file);
- }
- }
get_out:
P(dev->mutex);
int
reposition_dev(DEVICE *dev, uint32_t file, uint32_t block)
{
-
if (dev->fd < 0) {
dev->dev_errno = EBADF;
Mmsg0(&dev->errmsg, _("Bad call to reposition_dev. Archive not open\n"));
return 0;
}
}
+ if (block < dev->block_num) {
+ bsf_dev(dev, 1);
+ fsf_dev(dev, 1);
+ }
if (block > dev->block_num) {
/* Ignore errors as Bacula can read to the correct block */
Dmsg1(100, "fsr %d\n", block-dev->block_num);
if (!root_bsr || !root_bsr->use_positioning ||
!root_bsr->reposition || !dev_is_tape(dev)) {
- Dmsg2(000, "use_pos=%d repos=%d\n", root_bsr->use_positioning,
+ Dmsg2(100, "use_pos=%d repos=%d\n", root_bsr->use_positioning,
root_bsr->reposition);
return NULL;
}
#include "bacula.h"
#include "stored.h"
-static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec);
+static void handle_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec);
#ifdef DEBUG
static char *rec_state_to_str(DEV_RECORD *rec);
#endif
*/
read_block_from_device(jcr, dev, block, NO_BLOCK_NUMBER_CHECK);
read_record_from_block(block, trec);
- get_session_record(dev, trec, &sessrec);
+ handle_session_record(dev, trec, &sessrec);
ok = record_cb(jcr, dev, block, trec);
free_record(trec);
/*
* Now find and position to first file and block
* on this tape.
*/
- BSR *bsr = find_next_bsr(jcr->bsr, dev);
- if (bsr == NULL && jcr->bsr->mount_next_volume) {
- Dmsg0(100, "Would mount next volume here\n");
- }
- if (bsr) {
- Dmsg4(100, "Reposition new tape from (file:block) %d:%d to %d:%d\n",
- dev->file, dev->block_num, bsr->volfile->sfile,
- bsr->volblock->sblock);
- reposition_dev(dev, bsr->volfile->sfile, bsr->volblock->sblock);
- Dmsg2(100, "Now at (file:block) %d:%d\n",
- dev->file, dev->block_num);
+ if (jcr->bsr) {
+ BSR *bsr;
+
+ jcr->bsr->reposition = true;
+ bsr = find_next_bsr(jcr->bsr, dev);
+ if (bsr) {
+ Jmsg(jcr, M_INFO, 0, _("Forward spacing to file:block %u:%u.\n"),
+ bsr->volfile->sfile, bsr->volblock->sblock);
+ Dmsg4(100, "Reposition new from (file:block) %d:%d to %d:%d\n",
+ dev->file, dev->block_num, bsr->volfile->sfile,
+ bsr->volblock->sblock);
+ reposition_dev(dev, bsr->volfile->sfile, bsr->volblock->sblock);
+ Dmsg2(100, "Now at (file:block) %d:%d\n",
+ dev->file, dev->block_num);
+ }
}
+ /* After reading label, we must read first data block */
+ continue;
+
} else if (dev_state(dev, ST_EOF)) {
Jmsg(jcr, M_INFO, 0, "Got EOF at file %u on device %s, Volume \"%s\"\n",
dev->file, dev_name(dev), jcr->VolumeName);
rec->Block+1, block->BlockNumber);
}
}
+ Dmsg3(100, "After mount next vol. stat=%s blk=%d rem=%d\n", rec_state_to_str(rec),
+ block->BlockNumber, rec->remainder);
record = 0;
for (rec->state=0; !is_block_empty(rec); ) {
if (!read_record_from_block(block, rec)) {
/* Some sort of label? */
if (rec->FileIndex < 0) {
- get_session_record(dev, rec, &sessrec);
+ handle_session_record(dev, rec, &sessrec);
ok = record_cb(jcr, dev, block, rec);
if (rec->FileIndex == EOS_LABEL) {
Dmsg2(100, "Remove rec. SI=%d ST=%d\n", rec->VolSessionId,
Dmsg0(100, "Would mount next volume here\n");
Dmsg2(100, "Current postion (file:block) %d:%d\n",
dev->file, dev->block_num);
+ jcr->bsr->mount_next_volume = false;
dev->state |= ST_EOT;
rec->Block = 0;
break;
Dmsg2(100, "Now at (file:block) %d:%d\n",
dev->file, dev->block_num);
}
- Dmsg5(10, "BSR no match rec=%d block=%d SessId=%d SessTime=%d FI=%d\n",
+ Dmsg5(100, "BSR no match rec=%d block=%d SessId=%d SessTime=%d FI=%d\n",
record, block->BlockNumber, rec->VolSessionId, rec->VolSessionTime,
rec->FileIndex);
continue; /* we don't want record, read next one */
}
-static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec)
+static void handle_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec)
{
char *rtype;
+ char buf[100];
memset(sessrec, 0, sizeof(sessrec));
switch (rec->FileIndex) {
case PRE_LABEL:
rtype = "End of Media";
break;
default:
- rtype = "Unknown";
+ bsnprintf(buf, sizeof(buf), "Unknown code %d\n", rec->FileIndex);
+ rtype = buf;
break;
}
- Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
+ Dmsg5(100, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
}
char dt[MAX_TIME_LENGTH];
char b1[30], b2[30], b3[30];
- bnet_fsend(user, "\n%s Version: " VERSION " (" BDATE ")\n", my_name);
+ bnet_fsend(user, "\n%s Version: " VERSION " (" BDATE ") %s %s %s\n", my_name,
+ HOST_OS, DISTNAME, DISTVER);
bstrftime(dt, sizeof(dt), daemon_start_time);
bnet_fsend(user, _("Daemon started %s, %d Job%s run.\n"), dt, last_job.NumJobs,
last_job.NumJobs == 1 ? "" : "s");
bnet_fsend(user, _("%s %s job %s using Volume \"%s\" on device %s\n"),
job_level_to_str(jcr->JobLevel),
job_type_to_str(jcr->JobType),
+ jcr->Job,
jcr->VolumeName,
- jcr->Job, jcr->device->device_name);
+ jcr->device->device_name);
sec = time(NULL) - jcr->run_time;
if (sec <= 0) {
sec = 1;
{"minimumblocksize", store_pint, ITEM(res_dev.min_block_size), 0, 0, 0},
{"maximumblocksize", store_pint, ITEM(res_dev.max_block_size), 0, 0, 0},
{"maximumvolumesize", store_size, ITEM(res_dev.max_volume_size), 0, 0, 0},
- {"maximumfilesize", store_size, ITEM(res_dev.max_file_size), 0, 0, 0},
+ {"maximumfilesize", store_size, ITEM(res_dev.max_file_size), 0, ITEM_DEFAULT, 1000000000},
{"volumecapacity", store_size, ITEM(res_dev.volume_capacity), 0, 0, 0},
{NULL, NULL, 0, 0, 0, 0}
};
#undef VERSION
#define VERSION "1.32"
#define VSTRING "1"
-#define BDATE "1 Sep 2003"
-#define LSMDATE "01Sep03"
+#define BDATE "02 Sep 2003"
+#define LSMDATE "02Sep03"
/* Debug flags */
#undef DEBUG