1.35 Items to do:
- Implement SIGHUP in Dir
-- Implement fast tree insert (doubly linked list?)
+ (Implement resources on a single pointer)
- Do tape alerts -- see tapealert.txt
- When restore started from console, report jobid.
-- Feedback while the tree is being built.
- Win32 inc problem when new directory added.
- On Win95
The error I when I installed 1.34.2 clients:
The BACULA-FD file is
linked to missing export KERNEL32.DLL:GetFileAttributesExA.
- Add link to doc in message when authentication fails.
-- Disallow using Internal database
- Add better error codes to run_program (10000+)
+- When passwords do not match, print message that points the
+ user to the doc.
+- Make Verify jobs require exclusive use of Volume as Restore
+ jobs do.
Documentation to do: (any release a little bit at a time)
non-existent directories will not be restored properly.
Wish list:
+- Sort Scheduled jobs status listing by start time.
+- Add priority to Scheduled jobs status listing.
- Add multiple-media-types.txt
- look at mxt-changer.html
- Document a get out of jail procedure if everything breaks if you lost/broke
mount it.
- Implement Fixed storage LabelFormat test.
- Add reporting in attr despooling.
+
+==== Done in 1.35.0
+- Implement fast tree insert (doubly linked list?)
+- Disallow using Internal database
+- Feedback while the tree is being built.
+
drop(uid, gid); /* reduce priveleges if requested */
- /* signal(SIGHUP, reload_config); */
+ signal(SIGHUP, reload_config);
init_console_msg(working_directory);
term_msg(); /* terminate message handler */
stop_watchdog();
close_memory_pool(); /* release free memory in pool */
- sm_dump(false);
+ sm_dump(false);
exit(sig);
}
{
int num = r_last - r_first + 1;
RES **res_tab = reload_table[table].res_table;
+ if (!res_tab) {
+ Dmsg1(000, "res_tab for table %d already released.\n", table);
+ return;
+ }
Dmsg1(000, "Freeing resources for table %d\n", table);
for (int j=0; j<num; j++) {
free_resource(res_tab[j], r_first + j);
*/
static void reload_job_end_cb(JCR *jcr)
{
-#ifdef working
+ if (jcr->reload_id == 0) {
+ return; /* nothing to do */
+ }
int i = jcr->reload_id - 1;
- Dmsg1(000, "reload job_end JobId=%d\n", jcr->JobId);
+ Dmsg3(000, "reload job_end JobId=%d table=%d cnt=%d\n", jcr->JobId,
+ i, reload_table[i].job_count);
lock_jcr_chain();
LockRes();
if (--reload_table[i].job_count <= 0) {
}
UnlockRes();
unlock_jcr_chain();
-#endif
}
-static int find_free_table()
+static int find_free_reload_table_entry()
{
int table = -1;
for (int i=0; i < max_reloads; i++) {
int njobs = 0;
int table, rtable;
- Jmsg(NULL, M_ERROR, 0, _("Command not implemented\n"));
- return;
-
if (already_here) {
abort(); /* Oops, recursion -> die */
}
already_here = true;
- sigfillset(&set);
+ sigemptyset(&set);
+ sigaddset(&set, SIGHUP);
sigprocmask(SIG_BLOCK, &set, NULL);
+// Jmsg(NULL, M_INFO, 0, "Entering experimental reload config code. Bug reports will not be accepted.\n");
+
lock_jcr_chain();
LockRes();
- table = find_free_table();
+ table = find_free_reload_table_entry();
if (table < 0) {
- Jmsg(NULL, M_ERROR, 0, _("Too many reload requests.\n"));
+ Jmsg(NULL, M_ERROR, 0, _("Too many open reload requests. Request ignored.\n"));
goto bail_out;
}
* reload_id == 0
*/
foreach_jcr(jcr) {
- if (jcr->reload_id == 0) {
+ if (jcr->reload_id == 0 && jcr->JobType != JT_SYSTEM) {
reload_table[table].job_count++;
jcr->reload_id = table + 1;
job_end_push(jcr, reload_job_end_cb);
Dmsg0(000, "Reloaded config file\n");
if (!check_resources()) {
- rtable = find_free_table(); /* save new, bad table */
+ rtable = find_free_reload_table_entry(); /* save new, bad table */
if (rtable < 0) {
- Jmsg(NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile);
+ Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
+ Jmsg(NULL, M_ERROR_TERM, 0, _("Out of reload table entries. Giving up.\n"));
} else {
Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile);
}
resources[i].res_head = res_tab[i];
}
table = rtable; /* release new, bad, saved table below */
+ if (njobs != 0) {
+ foreach_jcr(jcr) {
+ if (jcr->reload_id == table) {
+ jcr->reload_id = 0;
+ }
+ free_locked_jcr(jcr);
+ }
+ }
+ njobs = 0; /* force bad tabel to be released below */
}
/* Reset globals */
SDConnectTimeout = director->SDConnectTimeout;
Dmsg0(0, "Director's configuration file reread.\n");
- /* Now release saved resources */
- free_saved_resources(table);
+ /* Now release saved resources, if no jobs using the resources */
+ if (njobs == 0) {
+ free_saved_resources(table);
+ }
bail_out:
UnlockRes();
memcpy(res, &res_all, size);
if (!resources[rindex].res_head) {
resources[rindex].res_head = (RES *)res; /* store first entry */
- Dmsg3(200, "Inserting first %s res: %s index=%d\n", res_to_str(type),
+ Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
res->res_dir.hdr.name, rindex);
} else {
RES *next;
}
}
next->next = (RES *)res;
- Dmsg4(200, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
+ Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
res->res_dir.hdr.name, rindex, pass);
}
}
if (pass == 1) {
if (((alist **)item->value)[item->code] == NULL) {
((alist **)item->value)[item->code] = new alist(10, owned_by_alist);
-// Dmsg1(400, "Defined new ACL alist at %d\n", item->code);
+// Dmsg1(900, "Defined new ACL alist at %d\n", item->code);
}
((alist **)item->value)[item->code]->append(bstrdup(lc->str));
-// Dmsg2(400, "Appended to %d %s\n", item->code, lc->str);
+// Dmsg2(900, "Appended to %d %s\n", item->code, lc->str);
}
token = lex_get_token(lc, T_ALL);
if (token == T_COMMA) {
while ((token = lex_get_token(lc, T_ALL)) != T_EOL) {
bool found = false;
- Dmsg1(150, "store_backup got token=%s\n", lex_tok_to_str(token));
+ Dmsg1(900, "store_backup got token=%s\n", lex_tok_to_str(token));
if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
scan_err1(lc, "Expected a backup/verify keyword, got: %s", lc->str);
}
- Dmsg1(190, "Got keyword: %s\n", lc->str);
+ Dmsg1(900, "Got keyword: %s\n", lc->str);
for (i=0; BakVerFields[i].name; i++) {
if (strcasecmp(lc->str, BakVerFields[i].name) == 0) {
found = true;
scan_err1(lc, "Expected an equals, got: %s", lc->str);
}
token = lex_get_token(lc, T_NAME);
- Dmsg1(190, "Got value: %s\n", lc->str);
+ Dmsg1(900, "Got value: %s\n", lc->str);
switch (BakVerFields[i].token) {
case 'C':
/* Find Client Resource */
lc->options |= LOPT_NO_IDENT; /* make spaces significant */
- Dmsg0(190, "Enter store_restore()\n");
+ Dmsg0(900, "Enter store_restore()\n");
((JOB *)(item->value))->JobType = item->code;
while ((token = lex_get_token(lc, T_ALL)) != T_EOL) {
scan_err1(lc, "expected a name, got: %s", lc->str);
}
for (i=0; RestoreFields[i].name; i++) {
- Dmsg1(190, "Restore kw=%s\n", lc->str);
+ Dmsg1(900, "Restore kw=%s\n", lc->str);
if (strcasecmp(lc->str, RestoreFields[i].name) == 0) {
found = true;
if (lex_get_token(lc, T_ALL) != T_EQUALS) {
scan_err1(lc, "Expected an equals, got: %s", lc->str);
}
token = lex_get_token(lc, T_ALL);
- Dmsg1(190, "Restore value=%s\n", lc->str);
+ Dmsg1(900, "Restore value=%s\n", lc->str);
switch (RestoreFields[i].token) {
case 'B':
/* Bootstrap */
}
errno = 0;
res_all.res_job.RestoreJobId = strtol(lc->str, NULL, 0);
- Dmsg1(190, "RestorJobId=%d\n", res_all.res_job.RestoreJobId);
+ Dmsg1(900, "RestorJobId=%d\n", res_all.res_job.RestoreJobId);
if (errno != 0) {
scan_err1(lc, "expected an integer number, got: %s", lc->str);
}
} else {
bstrncpy(buf, "0 ", sizeof(buf));
}
- Dmsg1(100, "Opts=%s\n", buf);
+ Dmsg1(500, "Opts=%s\n", buf);
optlen = strlen(buf);
while (fgets(buf+optlen, sizeof(buf)-optlen, bpipe->rfd)) {
fd->msglen = Mmsg(&fd->msg, "%s", buf);
- Dmsg2(200, "Inc/exc len=%d: %s", fd->msglen, fd->msg);
+ Dmsg2(500, "Inc/exc len=%d: %s", fd->msglen, fd->msg);
if (!bnet_send(fd)) {
Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
goto bail_out;
} else {
bstrncpy(buf, "0 ", sizeof(buf));
}
- Dmsg1(100, "Opts=%s\n", buf);
+ Dmsg1(500, "Opts=%s\n", buf);
optlen = strlen(buf);
while (fgets(buf+optlen, sizeof(buf)-optlen, ffd)) {
fd->msglen = Mmsg(&fd->msg, "%s", buf);
/* Note, fall through wanted */
default:
if (ie->num_opts) {
- Dmsg2(100, "numopts=%d opts=%s\n", ie->num_opts, NPRT(ie->opts_list[0]->opts));
+ Dmsg2(500, "numopts=%d opts=%s\n", ie->num_opts, NPRT(ie->opts_list[0]->opts));
pm_strcpy(&fd->msg, ie->opts_list[0]->opts);
pm_strcat(&fd->msg, " ");
} else {
pm_strcpy(&fd->msg, "0 ");
}
fd->msglen = pm_strcat(&fd->msg, p);
- Dmsg1(100, "Inc/Exc name=%s\n", fd->msg);
+ Dmsg1(500, "Inc/Exc name=%s\n", fd->msg);
if (!bnet_send(fd)) {
Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
goto bail_out;
goto bail_out;
}
bstrncpy(buf, "F ", sizeof(buf));
- Dmsg1(100, "Opts=%s\n", buf);
+ Dmsg1(500, "Opts=%s\n", buf);
optlen = strlen(buf);
while (fgets(buf+optlen, sizeof(buf)-optlen, bpipe->rfd)) {
fd->msglen = Mmsg(&fd->msg, "%s", buf);
- Dmsg2(200, "Inc/exc len=%d: %s", fd->msglen, fd->msg);
+ Dmsg2(500, "Inc/exc len=%d: %s", fd->msglen, fd->msg);
if (!bnet_send(fd)) {
Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
goto bail_out;
goto bail_out;
}
bstrncpy(buf, "F ", sizeof(buf));
- Dmsg1(100, "Opts=%s\n", buf);
+ Dmsg1(500, "Opts=%s\n", buf);
optlen = strlen(buf);
while (fgets(buf+optlen, sizeof(buf)-optlen, ffd)) {
fd->msglen = Mmsg(&fd->msg, "%s", buf);
default:
pm_strcpy(&fd->msg, "F ");
fd->msglen = pm_strcat(&fd->msg, p);
- Dmsg1(100, "Inc/Exc name=%s\n", fd->msg);
+ Dmsg1(500, "Inc/Exc name=%s\n", fd->msg);
if (!bnet_send(fd)) {
Jmsg(jcr, M_FATAL, 0, _(">filed: write error on socket\n"));
goto bail_out;
bstrncat(opts, "V", optlen); /* indicate Verify */
bstrncat(opts, lc->str, optlen);
bstrncat(opts, ":", optlen); /* terminate it */
- Dmsg3(100, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
+ Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
/*
* Standard keyword options for Include/Exclude
scan_err1(lc, "Expected a FileSet option keyword, got:%s:", lc->str);
} else { /* add option */
bstrncat(opts, option, optlen);
- Dmsg3(100, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
+ Dmsg3(900, "Catopts=%s option=%s optlen=%d\n", opts, option,optlen);
}
}
}
setup_current_opts();
bstrncpy(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS);
- Dmsg2(100, "old pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts);
+ Dmsg2(900, "old pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts);
/* Create incexe structure */
- Dmsg0(200, "Create INCEXE structure\n");
+ Dmsg0(900, "Create INCEXE structure\n");
incexe = (INCEXE *)malloc(sizeof(INCEXE));
memcpy(incexe, &res_incexe, sizeof(INCEXE));
memset(&res_incexe, 0, sizeof(INCEXE));
sizeof(INCEXE *) * (res_all.res_fs.num_includes + 1));
}
res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe;
- Dmsg1(200, "num_includes=%d\n", res_all.res_fs.num_includes);
+ Dmsg1(900, "num_includes=%d\n", res_all.res_fs.num_includes);
} else { /* exclude */
if (res_all.res_fs.num_excludes == 0) {
res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *));
sizeof(INCEXE *) * (res_all.res_fs.num_excludes + 1));
}
res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe;
- Dmsg1(200, "num_excludes=%d\n", res_all.res_fs.num_excludes);
+ Dmsg1(900, "num_excludes=%d\n", res_all.res_fs.num_excludes);
}
/* Pickup include/exclude names. They are stored in INCEXE
incexe->name_list.init(10, true);
}
incexe->name_list.append(bstrdup(lc->str));
- Dmsg1(200, "Add to name_list %s\n", lc->str);
+ Dmsg1(900, "Add to name_list %s\n", lc->str);
break;
default:
scan_err1(lc, "Expected a filename, got: %s", lc->str);
sizeof(INCEXE *) * (res_all.res_fs.num_includes + 1));
}
res_all.res_fs.include_items[res_all.res_fs.num_includes++] = incexe;
- Dmsg1(200, "num_includes=%d\n", res_all.res_fs.num_includes);
+ Dmsg1(900, "num_includes=%d\n", res_all.res_fs.num_includes);
} else { /* exclude */
if (res_all.res_fs.num_excludes == 0) {
res_all.res_fs.exclude_items = (INCEXE **)malloc(sizeof(INCEXE *));
sizeof(INCEXE *) * (res_all.res_fs.num_excludes + 1));
}
res_all.res_fs.exclude_items[res_all.res_fs.num_excludes++] = incexe;
- Dmsg1(200, "num_excludes=%d\n", res_all.res_fs.num_excludes);
+ Dmsg1(900, "num_excludes=%d\n", res_all.res_fs.num_excludes);
}
}
scan_to_eol(lc);
case T_UNQUOTED_STRING:
case T_QUOTED_STRING:
res_incexe.current_opts->regex.append(bstrdup(lc->str));
- Dmsg3(200, "set regex %p size=%d %s\n",
+ Dmsg3(900, "set regex %p size=%d %s\n",
res_incexe.current_opts, res_incexe.current_opts->regex.size(),lc->str);
break;
default:
case T_UNQUOTED_STRING:
case T_QUOTED_STRING:
res_incexe.current_opts->wild.append(bstrdup(lc->str));
- Dmsg3(200, "set wild %p size=%d %s\n",
+ Dmsg3(900, "set wild %p size=%d %s\n",
res_incexe.current_opts, res_incexe.current_opts->wild.size(),lc->str);
break;
default:
incexe->name_list.init(10, true);
}
incexe->name_list.append(bstrdup(lc->str));
- Dmsg1(200, "Add to name_list %s\n", lc->str);
+ Dmsg1(900, "Add to name_list %s\n", lc->str);
break;
default:
scan_err1(lc, _("Expected a filename, got: %s"), lc->str);
scan_include_options(lc, keyword, inc_opts, sizeof(inc_opts));
if (pass == 1) {
bstrncat(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS);
- Dmsg2(100, "new pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts);
+ Dmsg2(900, "new pass=%d incexe opts=%s\n", pass, res_incexe.current_opts->opts);
}
scan_to_eol(lc);
}
jcr->sd_msg_thread_done = false;
jcr->SD_msg_chan = 0;
V(jcr->mutex);
+ Dmsg0(100, "Start SD msg_thread.\n");
if ((status=pthread_create(&thid, NULL, msg_thread, (void *)jcr)) != 0) {
Jmsg1(jcr, M_ABORT, 0, _("Cannot create message thread: %s\n"), strerror(status));
}
+ Dmsg0(100, "SD msg_thread started.\n");
/* Wait for thread to start */
while (jcr->SD_msg_chan == 0) {
bmicrosleep(0, 50);
pthread_detach(pthread_self());
jcr->SD_msg_chan = pthread_self();
pthread_cleanup_push(msg_thread_cleanup, arg);
- Dmsg0(200, "msg_thread\n");
sd = jcr->store_bsock;
/* Read the Storage daemon's output.
*/
- Dmsg0(200, "Start msg_thread loop\n");
+ Dmsg0(100, "Start msg_thread loop\n");
while ((stat=bget_dirmsg(sd)) >= 0) {
Dmsg1(200, "<stored: %s", sd->msg);
if (sscanf(sd->msg, Job_start, &Job) == 1) {
FROM Client,Job,File,Filename,Path WHERE Client.ClientId=Job.ClientId
AND JobStatus='T' AND Job.JobId=File.JobId
AND Path.PathId=File.PathId AND Filename.FilenameId=File.FilenameId
- AND Filename.Name='%1' ORDER BY Job.StartTime LIMIT 20;
+ AND Filename.Name='%1'
+ GROUP BY Job.JobId
+ ORDER BY Job.StartTime LIMIT 20;
# 3
:List where the most recent copies of a file are saved:
*Enter path with trailing slash:
AND JobMedia.JobId=Job.JobId
AND JobMedia.MediaId=Media.MediaId
AND Client.ClientId=Job.ClientId
+ GROUP BY Job.JobId
ORDER BY Job.StartTime DESC LIMIT 5;
# 4
:List last 20 Full Backups for a Client:
*Enter Client name:
-Select Job.JobId,Client.Name as Client,StartTime,JobFiles,JobBytes,
+SELECT Job.JobId,Client.Name AS Client,StartTime,JobFiles,JobBytes,
JobMedia.StartFile as VolFile,VolumeName
FROM Client,Job,JobMedia,Media
WHERE Client.Name='%1'
AND Client.ClientId=Job.ClientId
AND Level='F' AND JobStatus='T'
AND JobMedia.JobId=Job.JobId AND JobMedia.MediaId=Media.MediaId
+ GROUP BY Job.JobId
ORDER BY Job.StartTime DESC LIMIT 20;
# 5
:List all backups for a Client after a specified time
*Enter Client Name:
*Enter time in YYYY-MM-DD HH:MM:SS format:
-Select Job.JobId,Client.Name as Client,Level,StartTime,JobFiles,JobBytes,VolumeName
+SELECT Job.JobId,Client.Name as Client,Level,StartTime,JobFiles,JobBytes,VolumeName
FROM Client,Job,JobMedia,Media
WHERE Client.Name='%1'
AND Client.ClientId=Job.ClientId
# 6
:List all backups for a Client
*Enter Client Name:
-Select Job.JobId,Client.Name as Client,Level,StartTime,JobFiles,JobBytes,VolumeName
+SELECT Job.JobId,Client.Name as Client,Level,StartTime,JobFiles,JobBytes,VolumeName
FROM Client,Job,JobMedia,Media
WHERE Client.Name='%1'
AND Client.ClientId=Job.ClientId
SELECT Slot,MaxVolBytes,VolCapacityBytes,VolStatus,Recycle,VolRetention,
VolUseDuration,MaxVolJobs,MaxVolFiles
FROM Media
- WHERE Volumename='%1';
+ WHERE VolumeName='%1';
# 8
:List Volumes used by selected JobId:
*Enter JobId:
FROM Job,JobMedia,Media
WHERE Job.JobId=%1
AND Job.JobId=JobMedia.JobId
- AND JobMedia.MediaId=Media.MediaId;
+ AND JobMedia.MediaId=Media.MediaId
+ GROUP BY VolumeName;
# 9
:List Volumes to Restore All Files:
*Enter Client Name:
SELECT Job.JobId,Job.Name,Job.StartTime,Job.Type,
Job.Level,Job.JobFiles,Job.JobBytes,Job.JobStatus
FROM JobMedia,Job
- WHERE JobMedia.JobId = Job.JobId
- AND JobMedia.MediaId = %1;
-SELECT MediaId,VolumeName,VolStatus,VolBytes,VolFiles,
- VolRetention,Recycle,Slot,MediaType,LastWritten
- FROM Media WHERE MediaId = %1;
+ WHERE JobMedia.JobId=Job.JobId
+ AND JobMedia.MediaId=%1
+ GROUP BY Job.JobId;
+# 15
+:List Jobs stored for a given Volume name:
+*Enter Volume name:
+SELECT Job.JobId,Job.Name,Job.StartTime,Job.Type,
+ Job.Level,Job.JobFiles,Job.JobBytes,Job.JobStatus
+ FROM Media,JobMedia,Job
+ WHERE Media.VolumeName='%1'
+ AND Media.MediaId=JobMedia.MediaId
+ AND JobMedia.JobId=Job.JobId
+ GROUP BY Job.JobId;
#endif
#ifdef HAVE_WIN32
-#define socketRead(fd, buf, len) recv(fd, buf, len, 0)
+#define socketRead(fd, buf, len) recv(fd, buf, len, 0)
#define socketWrite(fd, buf, len) send(fd, buf, len, 0)
+#define socketClose(fd) closesocket(fd)
#else
-#define socketRead(fd, buf, len) read(fd, buf, len)
+#define socketRead(fd, buf, len) read(fd, buf, len)
#define socketWrite(fd, buf, len) write(fd, buf, len)
+#define socketClose(fd) close(fd)
#endif
free(addr_list);
if (!connected) {
- close(sockfd);
+ socketClose(sockfd);
return NULL;
}
return init_bsock(jcr, sockfd, name, host, port, &tcp_serv_addr);
if (osock->host) {
bsock->host = bstrdup(osock->host);
}
- bsock->duped = TRUE;
+ bsock->duped = true;
return bsock;
}
if (bsock->timed_out) {
shutdown(bsock->fd, 2); /* discard any pending I/O */
}
- close(bsock->fd); /* normal close */
+ socketClose(bsock->fd); /* normal close */
}
term_bsock(bsock);
}
/* If nothing found, error */
if (i == 0) {
- Dmsg2(200, "error i=%d len=%d\n", i, len);
+ Dmsg2(900, "error i=%d len=%d\n", i, len);
return false;
}
/* Move modifier to its location */
bstrncpy(mod, &str[i], mod_len);
- Dmsg2(200, "in=%s mod=%s:\n", str, mod);
+ Dmsg2(900, "in=%s mod=%s:\n", str, mod);
/* Backup over any spaces in front of modifier */
for ( ; i > 0; i--) {
}
/* The remainder (beginning) should be our number */
if (!is_a_number(str)) {
- Dmsg0(200, "input not a number\n");
+ Dmsg0(900, "input not a number\n");
return false;
}
return true;
if (mod[i] == NULL) {
i = 1; /* no modifier, assume 1 */
}
- Dmsg2(200, "str=%s: mult=%d\n", str, mult[i]);
+ Dmsg2(900, "str=%s: mult=%d\n", str, mult[i]);
errno = 0;
val = strtod(str, NULL);
if (errno != 0 || val < 0) {
if (mod[i] == NULL) {
i = 0; /* no modifier found, assume 1 */
}
- Dmsg2(200, "str=%s: mult=%d\n", str, mult[i]);
+ Dmsg2(900, "str=%s: mult=%d\n", str, mult[i]);
errno = 0;
val = strtod(str, NULL);
if (errno != 0 || val < 0) {
}
}
+#ifdef TRACE_JCR_CHAIN
+static int lock_count = 0;
+#endif
+
/*
* Lock the chain
*/
void lock_jcr_chain()
{
int errstat;
+#ifdef TRACE_JCR_CHAIN
+ Dmsg1(000, "Lock jcr chain %d.\n", ++lock_count);
+#endif
if ((errstat=rwl_writelock(&lock)) != 0) {
Emsg1(M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
strerror(errstat));
void unlock_jcr_chain()
{
int errstat;
+#ifdef TRACE_JCR_CHAIN
+ Dmsg1(000, "Unlock jcr chain %d\n", lock_count--);
+#endif
if ((errstat=rwl_writeunlock(&lock)) != 0) {
Emsg1(M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
strerror(errstat));
} else {
/* Queue message for later sending */
jcr->msg_queue->append(item);
+// Dmsg1(000, "queue item=%lu\n", (long unsigned)item);
}
V(msg_queue_mutex);
free_memory(pool_buf);
P(msg_queue_mutex);
jcr->dequeuing = true;
foreach_dlist(item, jcr->msg_queue) {
+// Dmsg1(000, "dequeue item=%lu\n", (long unsigned)item);
Jmsg(jcr, item->type, item->level, "%s", item->msg);
}
jcr->msg_queue->destroy();
res_all.hdr.refcnt = 1;
for (i=0; items[i].name; i++) {
- Dmsg3(300, "Item=%s def=%s defval=%d\n", items[i].name,
+ Dmsg3(900, "Item=%s def=%s defval=%d\n", items[i].name,
(items[i].flags & ITEM_DEFAULT) ? "yes" : "no",
items[i].default_value);
if (items[i].flags & ITEM_DEFAULT && items[i].default_value != 0) {
POOLMEM *dest;
int dest_len;
- Dmsg2(300, "store_msgs pass=%d code=%d\n", pass, item->code);
+ Dmsg2(900, "store_msgs pass=%d code=%d\n", pass, item->code);
if (pass == 1) {
switch (item->code) {
case MD_STDOUT:
}
pm_strcat(&dest, lc->str);
dest_len += lc->str_len;
- Dmsg2(100, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
+ Dmsg2(900, "store_msgs newdest=%s: dest=%s:\n", lc->str, NPRT(dest));
token = lex_get_token(lc, T_ALL);
if (token == T_COMMA) {
continue; /* get another destination */
}
break;
}
- Dmsg1(300, "mail_cmd=%s\n", NPRT(cmd));
+ Dmsg1(900, "mail_cmd=%s\n", NPRT(cmd));
scan_types(lc, (MSGS *)(item->value), item->code, dest, cmd);
free_pool_memory(dest);
- Dmsg0(300, "done with dest codes\n");
+ Dmsg0(900, "done with dest codes\n");
break;
case MD_FILE: /* file */
case MD_APPEND: /* append */
pm_strcpy(&dest, lc->str);
dest_len = lc->str_len;
token = lex_get_token(lc, T_ALL);
- Dmsg1(300, "store_msgs dest=%s:\n", NPRT(dest));
+ Dmsg1(900, "store_msgs dest=%s:\n", NPRT(dest));
if (token != T_EQUALS) {
scan_err1(lc, _("expected an =, got: %s"), lc->str);
}
scan_types(lc, (MSGS *)(item->value), item->code, dest, NULL);
free_pool_memory(dest);
- Dmsg0(300, "done with dest codes\n");
+ Dmsg0(900, "done with dest codes\n");
break;
default:
}
scan_to_eol(lc);
set_bit(index, res_all.hdr.item_present);
- Dmsg0(300, "Done store_msgs\n");
+ Dmsg0(900, "Done store_msgs\n");
}
/*
if (lc->ch != ',') {
break;
}
- Dmsg0(300, "call lex_get_token() to eat comma\n");
+ Dmsg0(900, "call lex_get_token() to eat comma\n");
lex_get_token(lc, T_ALL); /* eat comma */
}
- Dmsg0(300, "Done scan_types()\n");
+ Dmsg0(900, "Done scan_types()\n");
}
lex_get_token(lc, T_NAME);
if (pass == 2) {
- Dmsg2(300, "Code=%d name=%s\n", item->code, lc->str);
+ Dmsg2(900, "Code=%d name=%s\n", item->code, lc->str);
res = GetResWithName(item->code, lc->str);
if (res == NULL) {
scan_err3(lc, _("Missing config Resource \"%s\" referenced on line %d : %s\n"),
#ifdef xxx
for (int i=0; item->name;; i++, item++) {
if (bit_is_set(i, res->item_present)) {
- Dmsg2(300, "Item %d is present in %s\n", i, res->name);
+ Dmsg2(900, "Item %d is present in %s\n", i, res->name);
} else {
- Dmsg2(300, "Item %d is not present in %s\n", i, res->name);
+ Dmsg2(900, "Item %d is not present in %s\n", i, res->name);
}
}
/* ***FIXME **** add code */
int token;
uint64_t uvalue;
- Dmsg0(400, "Enter store_size\n");
+ Dmsg0(900, "Enter store_size\n");
token = lex_get_token(lc, T_ALL);
errno = 0;
switch (token) {
}
scan_to_eol(lc);
set_bit(index, res_all.hdr.item_present);
- Dmsg0(400, "Leave store_size\n");
+ Dmsg0(900, "Leave store_size\n");
}
/* Make two passes. The first builds the name symbol table,
* and the second picks up the items.
*/
- Dmsg0(300, "Enter parse_config()\n");
+ Dmsg0(900, "Enter parse_config()\n");
for (pass=1; pass <= 2; pass++) {
- Dmsg1(300, "parse_config pass %d\n", pass);
+ Dmsg1(900, "parse_config pass %d\n", pass);
if ((lc = lex_open_file(lc, cf, NULL)) == NULL) {
set_exit_on_error(1); /* Never reached if exit_on_error == 1 */
return 0;
}
while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
- Dmsg1(300, "parse got token=%s\n", lex_tok_to_str(token));
+ Dmsg1(900, "parse got token=%s\n", lex_tok_to_str(token));
switch (state) {
case p_none:
if (token == T_EOL) {
* scan for = after the keyword */
if (!(items[i].flags & ITEM_NO_EQUALS)) {
token = lex_get_token(lc, T_ALL);
- Dmsg1 (300, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
+ Dmsg1 (900, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
if (token != T_EQUALS) {
scan_err1(lc, _("expected an equals, got: %s"), lc->str);
set_exit_on_error(1); /* Never reached if exit_on_error == 1 */
return 0;
}
}
- Dmsg1(300, "calling handler for %s\n", items[i].name);
+ Dmsg1(900, "calling handler for %s\n", items[i].name);
/* Call item handler */
items[i].handler(lc, &items[i], i, pass);
i = -1;
}
}
if (i >= 0) {
- Dmsg2(300, "level=%d id=%s\n", level, lc->str);
- Dmsg1(300, "Keyword = %s\n", lc->str);
+ Dmsg2(900, "level=%d id=%s\n", level, lc->str);
+ Dmsg1(900, "Keyword = %s\n", lc->str);
scan_err1(lc, _("Keyword \"%s\" not permitted in this resource.\n"
"Perhaps you left the trailing brace off of the previous resource."), lc->str);
set_exit_on_error(1); /* Never reached if exit_on_error == 1 */
case T_EOB:
level--;
state = p_none;
- Dmsg0(300, "T_EOB => define new resource\n");
+ Dmsg0(900, "T_EOB => define new resource\n");
save_resource(res_type, items, pass); /* save resource */
break;
set_exit_on_error(1); /* Never reached if exit_on_error == 1 */
return 0;
}
- if (debug_level > 50 && pass == 2) {
+ if (debug_level >= 900 && pass == 2) {
int i;
for (i=r_first; i<=r_last; i++) {
dump_resource(i, resources[i-r_first].res_head, prtmsg, NULL);
}
lc = lex_close_file(lc);
}
- Dmsg0(300, "Leave parse_config()\n");
+ Dmsg0(900, "Leave parse_config()\n");
set_exit_on_error(1);
return 1;
}
#include "jcr.h"
/* Exported globals */
-time_t watchdog_time = 0; /* this has granularity of SLEEP_TIME */
+time_t watchdog_time = 0; /* this has granularity of SLEEP_TIME */
-#define SLEEP_TIME 1 /* examine things every second */
+#define SLEEP_TIME 1 /* examine things every second */
/* Forward referenced functions */
extern "C" void *watchdog_thread(void *arg);
/* Static globals */
static bool quit = false;;
static bool wd_is_init = false;
-static brwlock_t lock; /* watchdog lock */
+static brwlock_t lock; /* watchdog lock */
static pthread_t wd_tid;
static dlist *wd_queue;
* Start watchdog thread
*
* Returns: 0 on success
- * errno on failure
+ * errno on failure
*/
int start_watchdog(void)
{
if ((errstat=rwl_init(&lock)) != 0) {
Emsg1(M_ABORT, 0, _("Unable to initialize watchdog lock. ERR=%s\n"),
- strerror(errstat));
+ strerror(errstat));
}
wd_queue = new dlist(wd_queue, &dummy->link);
wd_inactive = new dlist(wd_inactive, &dummy->link);
* Terminate the watchdog thread
*
* Returns: 0 on success
- * errno on failure
+ * errno on failure
*/
int stop_watchdog(void)
{
return 0;
}
- quit = true; /* notify watchdog thread to stop */
+ quit = true; /* notify watchdog thread to stop */
wd_is_init = false;
stat = pthread_join(wd_tid, NULL);
wd_queue->remove(item);
p = (watchdog_t *)item;
if (p->destructor != NULL) {
- p->destructor(p);
+ p->destructor(p);
}
free(p);
}
wd_inactive->remove(item);
p = (watchdog_t *)item;
if (p->destructor != NULL) {
- p->destructor(p);
+ p->destructor(p);
}
free(p);
}
foreach_dlist(p, wd_queue) {
if (wd == p) {
- wd_queue->remove(wd);
+ wd_queue->remove(wd);
Dmsg1(400, "Unregistered watchdog %p\n", wd);
- return true;
+ return true;
}
}
foreach_dlist(p, wd_inactive) {
if (wd == p) {
- wd_inactive->remove(wd);
+ wd_inactive->remove(wd);
Dmsg1(400, "Unregistered inactive watchdog %p\n", wd);
- return true;
+ return true;
}
}
watchdog_time = time(NULL);
foreach_dlist(p, wd_queue) {
- if (p->next_fire < watchdog_time) {
- /* Run the callback */
- p->callback(p);
+ if (p->next_fire < watchdog_time) {
+ /* Run the callback */
+ p->callback(p);
/* Reschedule (or move to inactive list if it's a one-shot timer) */
- if (p->one_shot) {
- /*
- * Note, when removing an item while walking the list
- * we must get the previous pointer (q) and set the
- * current pointer (p) to this previous pointer after
+ if (p->one_shot) {
+ /*
+ * Note, when removing an item while walking the list
+ * we must get the previous pointer (q) and set the
+ * current pointer (p) to this previous pointer after
* removing the current pointer, otherwise, we won't
- * walk the rest of the list.
- */
- q = (watchdog_t *)wd_queue->prev(p);
- wd_queue->remove(p);
- wd_inactive->append(p);
- p = q;
- } else {
- p->next_fire = watchdog_time + p->interval;
- }
- }
+ * walk the rest of the list.
+ */
+ q = (watchdog_t *)wd_queue->prev(p);
+ wd_queue->remove(p);
+ wd_inactive->append(p);
+ p = q;
+ } else {
+ p->next_fire = watchdog_time + p->interval;
+ }
+ }
}
wd_unlock();
unlock_jcr_chain();
int errstat;
if ((errstat=rwl_writelock(&lock)) != 0) {
Emsg1(M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
- strerror(errstat));
+ strerror(errstat));
}
}
int errstat;
if ((errstat=rwl_writeunlock(&lock)) != 0) {
Emsg1(M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
- strerror(errstat));
+ strerror(errstat));
}
}
Jmsg0(jcr, M_ERROR, 0, _("Attempt to update_volume_info in read mode!!!\n"));
return 0;
}
- if (!dev_state(dev, ST_LABEL)) {
- Jmsg0(jcr, M_ERROR, 0, _("Attempt to update_volume_info on non-labeled Volume!!!\n"));
- return 0;
- }
Dmsg1(100, "Update cat VolFiles=%d\n", dev->file);
/* Just labeled or relabeled the tape */
}
}
rewind_dev(dev);
- write_volume_label_to_dev(jcr, jcr->device, cmd, "Default");
+ write_new_volume_label_to_dev(jcr, jcr->device, cmd, "Default");
Pmsg1(-1, "Wrote Volume label for volume \"%s\".\n", cmd);
}
free_dcr(jcr->dcr);
jcr->dcr = NULL;
}
-
return;
}
* - We execute the command
* - We continue or exit depending on the return status
*/
-void *connection_request(void *arg)
+void *handle_connection_request(void *arg)
{
BSOCK *bs = (BSOCK *)arg;
JCR *jcr;
if (bnet_recv(bs) <= 0) {
Emsg0(M_ERROR, 0, _("Connection request failed.\n"));
+ bnet_close(bs);
return NULL;
}
*/
if (bs->msglen < 25 || bs->msglen > (int)sizeof(name)-25) {
Emsg1(M_ERROR, 0, _("Invalid Dir connection. Len=%d\n"), bs->msglen);
+ bnet_close(bs);
+ return NULL;
}
/*
* See if this is a File daemon connection. If so
jcr = new_jcr(sizeof(JCR), stored_free_jcr); /* create Job Control Record */
jcr->dir_bsock = bs; /* save Director bsock */
jcr->dir_bsock->jcr = jcr;
+ /* Initialize FD start condition variable */
+ int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
+ if (errstat != 0) {
+ Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
+ free_jcr(jcr);
+ return NULL;
+ }
Dmsg0(1000, "stored in start_job\n");
/* Fall through wanted! */
case VOL_IO_ERROR:
case VOL_NO_LABEL:
- if (!write_volume_label_to_dev(jcr, jcr->device, newname, poolname)) {
+ if (!write_new_volume_label_to_dev(jcr, jcr->device, newname, poolname)) {
bnet_fsend(dir, _("3912 Failed to label Volume: ERR=%s\n"), strerror_dev(dev));
break;
}
free_memory(fileset_name);
free_memory(fileset_md5);
- /* Initialize FD start condition variable */
- if ((errstat = pthread_cond_init(&jcr->job_start_wait, NULL)) != 0) {
- Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
- set_jcr_job_status(jcr, JS_ErrorTerminated);
- return 0;
- }
jcr->authenticated = false;
/*
timeout.tv_nsec = tv.tv_usec * 1000;
timeout.tv_sec = tv.tv_sec + 30 * 60; /* wait 30 minutes */
-
Dmsg1(100, "%s waiting on FD to contact SD\n", jcr->Job);
/*
* Wait for the File daemon to contact us to start the Job,
/*
* Put a volume label into the block
*
- * Returns: 0 on failure
- * 1 on success
+ * Returns: false on failure
+ * true on success
*/
-int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
+bool write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
{
DEV_RECORD rec;
free_pool_memory(rec.data);
Jmsg1(jcr, M_FATAL, 0, _("Cannot write Volume label to block for device %s\n"),
dev_name(dev));
- return 0;
+ return false;
} else {
Dmsg1(90, "Wrote label of %d bytes to block\n", rec.data_len);
}
free_pool_memory(rec.data);
- return 1;
+ return true;
}
/*
*
* This routine should be used only when labeling a blank tape.
*/
-int write_volume_label_to_dev(JCR *jcr, DEVRES *device, const char *VolName, const char *PoolName)
+bool write_new_volume_label_to_dev(JCR *jcr, DEVRES *device, const char *VolName, const char *PoolName)
{
DEVICE *dev = device->dev;
DEV_RECORD rec;
DEV_BLOCK *block;
- int stat = 1;
+ bool stat = true;
Dmsg0(99, "write_volume_label()\n");
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
Dmsg2(30, "Bad status on %s from rewind. ERR=%s\n", dev_name(dev), strerror_dev(dev));
if (!forge_on) {
- return 0;
+ return false;
}
}
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
free_block(block);
free_pool_memory(rec.data);
- return 0;
+ return false;
} else {
Dmsg2(30, "Wrote label of %d bytes to %s\n", rec.data_len, dev_name(dev));
}
if (!write_block_to_dev(jcr->dcr, block)) {
memset(&dev->VolHdr, 0, sizeof(dev->VolHdr));
Dmsg2(30, "Bad Label write on %s. ERR=%s\n", dev_name(dev), strerror_dev(dev));
- stat = 9;
+ stat = false;
}
Dmsg0(99, " Wrote block to device\n");
#include "bacula.h" /* pull in global headers */
#include "stored.h" /* pull in Storage Deamon headers */
+static bool rewrite_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *bloc, bool recycle);
+
+
/*
* If release is set, we rewind the current volume,
* which we no longer want, and ask the user (console)
* impossible to get the requested Volume.
*
*/
-int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release)
+int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool release)
{
int retry = 0;
bool ask = false, recycle, autochanger;
/* If not removable, Volume is broken */
if (!dev_cap(dev, CAP_REM)) {
- bstrncpy(jcr->VolCatInfo.VolCatStatus, "Error",
- sizeof(jcr->VolCatInfo.VolCatStatus));
- memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(dev->VolCatInfo));
- dir_update_volume_info(jcr, dev, 1); /* indicate tape labeled */
- Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s. Volume marked in error.\n"),
+ Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
jcr->VolumeName, dev_name(dev));
+ mark_volume_in_error(jcr, dev);
goto mount_next_vol;
}
(!dev_is_tape(dev) && strcmp(jcr->VolCatInfo.VolCatStatus,
"Recycle") == 0))) {
Dmsg0(100, "Create volume label\n");
- if (!write_volume_label_to_dev(jcr, (DEVRES *)dev->device, jcr->VolumeName,
+ /* Create a new Volume label and write it to the device */
+ if (!write_new_volume_label_to_dev(jcr, (DEVRES *)dev->device, jcr->VolumeName,
jcr->pool_name)) {
Dmsg0(100, "!write_vol_label\n");
goto mount_next_vol;
}
/* If not removable, Volume is broken */
if (!dev_cap(dev, CAP_REM)) {
- bstrncpy(jcr->VolCatInfo.VolCatStatus, "Error",
- sizeof(jcr->VolCatInfo.VolCatStatus));
- memcpy(&dev->VolCatInfo, &jcr->VolCatInfo, sizeof(dev->VolCatInfo));
- dir_update_volume_info(jcr, dev, 1); /* indicate tape labeled */
- Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s. Volume marked in error.\n"),
+ Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"),
jcr->VolumeName, dev_name(dev));
+ mark_volume_in_error(jcr, dev);
goto mount_next_vol;
}
/* NOTE! Fall-through wanted. */
* If the tape is marked as Recycle, we rewrite the label.
*/
if (dev->VolHdr.LabelType == PRE_LABEL || recycle) {
- Dmsg1(190, "ready_for_append found freshly labeled volume. dev=%x\n", dev);
- dev->VolHdr.LabelType = VOL_LABEL; /* set Volume label */
- write_volume_label_to_block(jcr, dev, block);
- /*
- * If we are not dealing with a streaming device,
- * write the block now to ensure we have write permission.
- * It is better to find out now rather than later.
- */
- if (!dev_cap(dev, CAP_STREAM)) {
- if (!rewind_dev(dev)) {
- Jmsg2(jcr, M_WARNING, 0, _("Rewind error on device \"%s\". ERR=%s\n"),
- dev_name(dev), strerror_dev(dev));
- }
- if (recycle) {
- if (!truncate_dev(dev)) {
- Jmsg2(jcr, M_WARNING, 0, _("Truncate error on device \"%s\". ERR=%s\n"),
- dev_name(dev), strerror_dev(dev));
- }
- }
- /* Attempt write to check write permission */
- if (!write_block_to_dev(jcr->dcr, block)) {
- Jmsg2(jcr, M_ERROR, 0, _("Unable to write device \"%s\". ERR=%s\n"),
- dev_name(dev), strerror_dev(dev));
- goto mount_next_vol;
- }
- }
- /* Set or reset Volume statistics */
- dev->VolCatInfo.VolCatJobs = 0;
- dev->VolCatInfo.VolCatFiles = 0;
- dev->VolCatInfo.VolCatBytes = 1;
- dev->VolCatInfo.VolCatErrors = 0;
- dev->VolCatInfo.VolCatBlocks = 0;
- dev->VolCatInfo.VolCatRBytes = 0;
- if (recycle) {
- dev->VolCatInfo.VolCatMounts++;
- dev->VolCatInfo.VolCatRecycles++;
- } else {
- dev->VolCatInfo.VolCatMounts = 1;
- dev->VolCatInfo.VolCatRecycles = 0;
- dev->VolCatInfo.VolCatWrites = 1;
- dev->VolCatInfo.VolCatReads = 1;
- }
- Dmsg0(100, "dir_update_vol_info. Set Append\n");
- bstrncpy(dev->VolCatInfo.VolCatStatus, "Append", sizeof(dev->VolCatInfo.VolCatStatus));
- dir_update_volume_info(jcr, dev, 1); /* indicate doing relabel */
- if (recycle) {
- Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\" on device \"%s\", all previous data lost.\n"),
- jcr->VolumeName, dev_name(dev));
- } else {
- Jmsg(jcr, M_INFO, 0, _("Wrote label to prelabeled Volume \"%s\" on device \"%s\"\n"),
- jcr->VolumeName, dev_name(dev));
+ if (!rewrite_volume_label(jcr, dev, block, recycle)) {
+ goto mount_next_vol;
}
- /*
- * End writing real Volume label (from pre-labeled tape), or recycling
- * the volume.
- */
-
} else {
/*
* OK, at this point, we have a valid Bacula label, but
return 1;
}
+/*
+ * Write a volume label.
+ * Returns: true if OK
+ * false if unable to write it
+ */
+static bool rewrite_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool recycle)
+{
+ Dmsg1(190, "ready_for_append found freshly labeled volume. dev=%x\n", dev);
+ dev->VolHdr.LabelType = VOL_LABEL; /* set Volume label */
+ if (!write_volume_label_to_block(jcr, dev, block)) {
+ return false;
+ }
+ /*
+ * If we are not dealing with a streaming device,
+ * write the block now to ensure we have write permission.
+ * It is better to find out now rather than later.
+ */
+ if (!dev_cap(dev, CAP_STREAM)) {
+ if (!rewind_dev(dev)) {
+ Jmsg2(jcr, M_WARNING, 0, _("Rewind error on device \"%s\". ERR=%s\n"),
+ dev_name(dev), strerror_dev(dev));
+ }
+ if (recycle) {
+ if (!truncate_dev(dev)) {
+ Jmsg2(jcr, M_WARNING, 0, _("Truncate error on device \"%s\". ERR=%s\n"),
+ dev_name(dev), strerror_dev(dev));
+ }
+ }
+ /* Attempt write to check write permission */
+ if (!write_block_to_dev(jcr->dcr, block)) {
+ Jmsg2(jcr, M_ERROR, 0, _("Unable to write device \"%s\". ERR=%s\n"),
+ dev_name(dev), strerror_dev(dev));
+ return false;
+ }
+ }
+ /* Set or reset Volume statistics */
+ dev->VolCatInfo.VolCatJobs = 0;
+ dev->VolCatInfo.VolCatFiles = 0;
+ dev->VolCatInfo.VolCatBytes = 1;
+ dev->VolCatInfo.VolCatErrors = 0;
+ dev->VolCatInfo.VolCatBlocks = 0;
+ dev->VolCatInfo.VolCatRBytes = 0;
+ if (recycle) {
+ dev->VolCatInfo.VolCatMounts++;
+ dev->VolCatInfo.VolCatRecycles++;
+ } else {
+ dev->VolCatInfo.VolCatMounts = 1;
+ dev->VolCatInfo.VolCatRecycles = 0;
+ dev->VolCatInfo.VolCatWrites = 1;
+ dev->VolCatInfo.VolCatReads = 1;
+ }
+ Dmsg0(100, "dir_update_vol_info. Set Append\n");
+ bstrncpy(dev->VolCatInfo.VolCatStatus, "Append", sizeof(dev->VolCatInfo.VolCatStatus));
+ dir_update_volume_info(jcr, dev, 1); /* indicate doing relabel */
+ if (recycle) {
+ Jmsg(jcr, M_INFO, 0, _("Recycled volume \"%s\" on device \"%s\", all previous data lost.\n"),
+ jcr->VolumeName, dev_name(dev));
+ } else {
+ Jmsg(jcr, M_INFO, 0, _("Wrote label to prelabeled Volume \"%s\" on device \"%s\"\n"),
+ jcr->VolumeName, dev_name(dev));
+ }
+ /*
+ * End writing real Volume label (from pre-labeled tape), or recycling
+ * the volume.
+ */
+ return true;
+}
+
+
/*
* Mark volume in error in catalog
*/
int device_is_unmounted(DEVICE *dev);
/* From dircmd.c */
-void *connection_request(void *arg);
+void *handle_connection_request(void *arg);
/* From fd_cmds.c */
int read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
void create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName);
-int write_volume_label_to_dev(JCR *jcr, DEVRES *device, const char *VolName, const char *PoolName);
+bool write_new_volume_label_to_dev(JCR *jcr, DEVRES *device, const char *VolName, const char *PoolName);
int write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
-int write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+bool write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
void dump_volume_label(DEVICE *dev);
void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
int unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
bool match_set_eof(BSR *bsr, DEV_RECORD *rec);
/* From mount.c */
-int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release);
+int mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool release);
int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
void release_volume(JCR *jcr, DEVICE *dev);
void mark_volume_in_error(JCR *jcr, DEVICE *dev);
/* Single server used for Director and File daemon */
bnet_thread_server(me->SDaddr, me->SDport, me->max_concurrent_jobs * 2 + 1,
- &dird_workq, connection_request);
+ &dird_workq, handle_connection_request);
exit(1); /* to keep compiler quiet */
}
JCR *jcr;
DCR *dcr;
jcr = new_jcr(sizeof(JCR), stored_free_jcr);
+ jcr->JobType = JT_SYSTEM;
+ /* Initialize FD start condition variable */
+ int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
+ if (errstat != 0) {
+ Jmsg1(jcr, M_ABORT, 0, _("Unable to init job cond variable: ERR=%s\n"), strerror(errstat));
+ }
jcr->device = device;
dcr = new_dcr(jcr, device->dev);
switch (read_dev_volume_label(jcr, device->dev, dcr->block)) {
#undef VERSION
#define VERSION "1.35.0"
#define VSTRING "1"
-#define BDATE "18 June 2004"
-#define LSMDATE "18Jun04"
+#define BDATE "19 June 2004"
+#define LSMDATE "19Jun04"
/* Debug flags */
#undef DEBUG
#define SMCHECK
#define TRACE_FILE 1
+// #define TRACE_JCR_CHAIN 1
+// #define TRACE_RES 1
+
/* #define FULL_DEBUG 1 */ /* normally on for testing only */
/* Turn this on ONLY if you want all Dmsg() to append to the