/* ****FIXME***** implement 64 bit file addresses ! */
#define faddr_t long
+#define POOLMEM char
+
/* Types */
/* If sys/types.h does not supply intXX_t, supply them ourselves */
localtime_r(&ttime, &tm);
strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
- Dmsg1(000, "update_media: FirstWritte=%d\n", mr->FirstWritten);
+ Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten);
P(mdb->mutex);
if (mr->VolMounts == 1) {
Mmsg(&mdb->cmd, "UPDATE Media SET FirstWritten=\"%s\"\
<widget>
<class>GtkHBox</class>
<name>hbox19</name>
+ <height>22</height>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
- <fill>True</fill>
+ <fill>False</fill>
</child>
<widget>
init_stack_dump();
my_name_is(argc, argv, "console");
+ init_msg(NULL, NULL);
working_directory = "/tmp";
- /*
- * Ensure that every message is always printed
- */
- for (i=1; i<=M_MAX; i++) {
- add_msg_dest(NULL, MD_STDOUT, i, NULL, NULL);
- }
-
-
while ((ch = getopt(argc, argv, "bc:d:r:st?")) != -1) {
switch (ch) {
case 'c': /* configuration file */
int stat;
BSOCK *fd;
POOL_DBR pr;
-#ifdef needed
- MEDIA_DBR mr;
-#endif
- CLIENT_DBR cr;
FILESET_DBR fsr;
since[0] = 0;
- /*
- * Get or Create client record
- */
- memset(&cr, 0, sizeof(cr));
- strcpy(cr.Name, jcr->client->hdr.name);
- cr.AutoPrune = jcr->client->AutoPrune;
- cr.FileRetention = jcr->client->FileRetention;
- cr.JobRetention = jcr->client->JobRetention;
- if (jcr->client_name) {
- free(jcr->client_name);
- }
- jcr->client_name = bstrdup(jcr->client->hdr.name);
- if (!db_create_client_record(jcr->db, &cr)) {
- Jmsg(jcr, M_ERROR, 0, _("Could not create Client record. %s"),
- db_strerror(jcr->db));
+
+ if (!get_or_create_client_record(jcr)) {
backup_cleanup(jcr, JS_ErrorTerminated, since);
- return 0;
}
- jcr->jr.ClientId = cr.ClientId;
- Dmsg2(9, "Created Client %s record %d\n", jcr->client->hdr.name,
- jcr->jr.ClientId);
+
/*
* Get or Create FileSet record
int msg_type;
MEDIA_DBR mr;
- memset(&mr, 0, sizeof(mr));
Dmsg0(100, "Enter backup_cleanup()\n");
- if (jcr->jr.EndTime == 0) {
- jcr->jr.EndTime = time(NULL);
- }
- jcr->end_time = jcr->jr.EndTime;
- jcr->jr.JobId = jcr->JobId;
- jcr->jr.JobStatus = jcr->JobStatus = TermCode;
- jcr->jr.JobFiles = jcr->JobFiles;
- jcr->jr.JobBytes = jcr->JobBytes;
- jcr->jr.VolSessionId = jcr->VolSessionId;
- jcr->jr.VolSessionTime = jcr->VolSessionTime;
- if (!db_update_job_end_record(jcr->db, &jcr->jr)) {
- Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
- db_strerror(jcr->db));
- }
+ memset(&mr, 0, sizeof(mr));
+ jcr->JobStatus = TermCode;
+
+ update_job_end_record(jcr); /* update database */
+
if (!db_get_job_record(jcr->db, &jcr->jr)) {
Jmsg(jcr, M_WARNING, 0, _("Error getting job record for stats: %s"),
db_strerror(jcr->db));
SubSysDirectory = "@subsysdir@"
Maximum Concurrent Jobs = 1
Password = "@dir_password@" # Console password
+ Messages = Standard
}
# Define the backup Job
Name = Standard
mailcommand = "@sbindir@/smtp -h @smtp_host@ -f \"Bacula <%r>\" -s \"Bacula: %t %e of %c %l\" %r"
operatorcommand = "@sbindir@/smtp -h @smtp_host@ -f \"Bacula <%r>\" -s \"Bacula: Intervention needed for %j\" %r"
- mail = @job_email@ = all, !skipped, !terminate
+ mail = @job_email@ = all, !skipped
operator = @job_email@ = mount
console = all, !skipped, !saved
}
init_stack_dump();
my_name_is(argc, argv, "bacula-dir");
+ init_msg(NULL, NULL); /* initialize message handler */
daemon_start_time = time(NULL);
memset(&last_job, 0, sizeof(last_job));
configfile = bstrdup(CONFIG_FILE);
}
- init_msg(NULL, NULL); /* initialize message handler */
parse_config(configfile);
if (!check_resources()) {
Emsg1(M_ABORT, 0, "Please correct configuration file: %s\n", configfile);
}
- my_name_is(0, (char **)NULL, director->hdr.name); /* set user defined name */
-
- FDConnectTimeout = director->FDConnectTimeout;
- SDConnectTimeout = director->SDConnectTimeout;
-
-
if (test_config) {
terminate_dird(0);
- exit(0);
}
+ my_name_is(0, NULL, director->hdr.name); /* set user defined name */
+
+ FDConnectTimeout = director->FDConnectTimeout;
+ SDConnectTimeout = director->SDConnectTimeout;
+
if (background) {
daemon_start();
init_stack_dump(); /* grab new pid */
}
+ /* Create pid must come after we are a daemon -- so we have our final pid */
+ create_pid_file(director->pid_directory, "bacula-dir", director->DIRport);
+
signal(SIGHUP, reload_config);
init_console_msg(working_directory);
}
terminate_dird(0);
- exit(0); /* for compiler */
}
/* Cleanup and then exit */
exit(1);
}
already_here = TRUE;
+ delete_pid_file(director->pid_directory, "bacula-dir",
+ director->DIRport);
stop_watchdog();
signal(SIGCHLD, SIG_IGN); /* don't worry about children now */
term_scheduler();
}
free_config_resources();
term_ua_server();
- close_memory_pool(); /* free memory in pool */
term_msg(); /* terminate message handler */
+ close_memory_pool(); /* release free memory in pool */
sm_dump(False);
- exit(0);
+ exit(sig != 0);
}
/*
job = (JOB *)GetNextRes(R_JOB, NULL);
director = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
if (!director) {
- Emsg1(M_WARNING, 0, _("No Director resource defined in %s\n\
+ Emsg1(M_FATAL, 0, _("No Director resource defined in %s\n\
Without that I don't know who I am :-(\n"), configfile);
OK = FALSE;
+ } else {
+ if (!director->working_directory) {
+ Emsg0(M_FATAL, 0, _("No working directory specified. Cannot continue.\n"));
+ OK = FALSE;
+ }
+ working_directory = director->working_directory;
+ if (!director->messages) { /* If message resource not specified */
+ director->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
+ if (!director->messages) {
+ Emsg1(M_FATAL, 0, _("No Messages resource defined in %s\n"), configfile);
+ OK = FALSE;
+ }
+ }
+ if (GetNextRes(R_DIRECTOR, (RES *)director) != NULL) {
+ Emsg1(M_FATAL, 0, _("Only one Director resource permitted in %s\n"),
+ configfile);
+ OK = FALSE;
+ }
}
- if (GetNextRes(R_DIRECTOR, (RES *)director) != NULL) {
- Emsg1(M_WARNING, 0, _("Only one Director resource permitted in %s\n"),
- configfile);
- OK = FALSE;
- }
- if (!director->working_directory) {
- Emsg0(M_WARNING, 0, _("No working directory specified. Cannot continue.\n"));
- OK = FALSE;
- }
- working_directory = director->working_directory;
+
if (!job) {
- Emsg1(M_WARNING, 0, _("No Job records defined in %s\n"), configfile);
+ Emsg1(M_FATAL, 0, _("No Job records defined in %s\n"), configfile);
OK = FALSE;
}
for (job=NULL; (job = (JOB *)GetNextRes(R_JOB, (RES *)job)); ) {
if (!job->client) {
- Emsg1(M_WARNING, 0, _("No Client record defined for job %s\n"), job->hdr.name);
+ Emsg1(M_FATAL, 0, _("No Client record defined for job %s\n"), job->hdr.name);
OK = FALSE;
}
if (!job->fs) {
- Emsg1(M_WARNING, 0, _("No FileSet record defined for job %s\n"), job->hdr.name);
+ Emsg1(M_FATAL, 0, _("No FileSet record defined for job %s\n"), job->hdr.name);
OK = FALSE;
}
if (!job->storage && job->JobType != JT_VERIFY) {
- Emsg1(M_WARNING, 0, _("No Storage resource defined for job %s\n"), job->hdr.name);
+ Emsg1(M_FATAL, 0, _("No Storage resource defined for job %s\n"), job->hdr.name);
OK = FALSE;
}
if (!job->pool) {
- Emsg1(M_WARNING, 0, _("No Pool resource defined for job %s\n"), job->hdr.name);
+ Emsg1(M_FATAL, 0, _("No Pool resource defined for job %s\n"), job->hdr.name);
OK = FALSE;
}
if (job->client->catalog) {
db = db_init_database(catalog->db_name, catalog->db_user,
catalog->db_password);
if (!db_open_database(db)) {
- Emsg1(M_WARNING, 0, "%s", db_strerror(db));
+ Emsg1(M_FATAL, 0, "%s", db_strerror(db));
}
db_close_database(db);
} else {
- Emsg1(M_WARNING, 0, _("No Catalog resource defined for client %s\n"),
+ Emsg1(M_FATAL, 0, _("No Catalog resource defined for client %s\n"),
job->client->hdr.name);
OK = FALSE;
}
}
UnlockRes();
+ if (OK) {
+ close_msg(NULL); /* close temp message handler */
+ init_msg(NULL, director->messages); /* open daemon message handler */
+ }
return OK;
}
*
* Kern Sibbald, January MM
*
- * $Id:
+ * $Id$
*/
/*
Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
static void store_inc(LEX *lc, struct res_items *item, int index, int pass);
static void store_backup(LEX *lc, struct res_items *item, int index, int pass);
static void store_restore(LEX *lc, struct res_items *item, int index, int pass);
+static void store_jobtype(LEX *lc, struct res_items *item, int index, int pass);
+static void store_level(LEX *lc, struct res_items *item, int index, int pass);
/* We build the current resource here as we are
* name handler value code flags default_value
*/
static struct res_items job_items[] = {
- {"name", store_name, ITEM(res_job.hdr.name), 0, ITEM_REQUIRED, 0},
- {"description", store_str, ITEM(res_job.hdr.desc), 0, 0, 0},
- {"backup", store_backup, ITEM(res_job), JT_BACKUP, 0, 0},
- {"verify", store_backup, ITEM(res_job), JT_VERIFY, 0, 0},
- {"restore", store_restore, ITEM(res_job), JT_RESTORE, 0, 0},
- {"schedule", store_res, ITEM(res_job.schedule), R_SCHEDULE, 0, 0},
- {"messages", store_res, ITEM(res_job.messages), R_MSGS, 0, 0},
- {"storage", store_res, ITEM(res_job.storage), R_STORAGE, 0, 0},
- {"pool", store_res, ITEM(res_job.pool), R_POOL, 0, 0},
- {"maxruntime", store_time, ITEM(res_job.MaxRunTime), 0, 0, 0},
+ {"name", store_name, ITEM(res_job.hdr.name), 0, ITEM_REQUIRED, 0},
+ {"description", store_str, ITEM(res_job.hdr.desc), 0, 0, 0},
+ {"backup", store_backup, ITEM(res_job), JT_BACKUP, 0, 0},
+ {"verify", store_backup, ITEM(res_job), JT_VERIFY, 0, 0},
+ {"restore", store_restore, ITEM(res_job), JT_RESTORE, 0, 0},
+ {"schedule", store_res, ITEM(res_job.schedule), R_SCHEDULE, 0, 0},
+ {"type", store_jobtype, ITEM(res_job), 0, 0, 0},
+ {"level", store_level, ITEM(res_job), 0, 0, 0},
+ {"messages", store_res, ITEM(res_job.messages), R_MSGS, 0, 0},
+ {"storage", store_res, ITEM(res_job.storage), R_STORAGE, 0, 0},
+ {"pool", store_res, ITEM(res_job.pool), R_POOL, 0, 0},
+ {"client", store_res, ITEM(res_job.client), R_CLIENT, 0, 0},
+ {"fileset", store_res, ITEM(res_job.fs), R_FILESET, 0, 0},
+ {"maxruntime", store_time, ITEM(res_job.MaxRunTime), 0, 0, 0},
{"maxstartdelay", store_time, ITEM(res_job.MaxStartDelay), 0, 0, 0},
{NULL, NULL, NULL, 0, 0, 0}
};
/* Keywords (RHS) permitted in Job Level records
*
- * level_name level level_class
+ * level_name level job_type
*/
struct s_jl joblevels[] = {
{"Full", L_FULL, JT_BACKUP},
{NULL, 0}
};
+/* Keywords (RHS) permitted in Job type records
+ *
+ * type_name job_type
+ */
+struct s_jt jobtypes[] = {
+ {"backup", JT_BACKUP},
+ {"verify", JT_VERIFY},
+ {"restore", JT_RESTORE},
+ {NULL, 0}
+};
+
+
/* Keywords (RHS) permitted in Backup and Verify records */
static struct s_kw BakVerFields[] = {
{"client", 'C'},
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;
case R_GROUP:
break;
printf("Unknown resource type %d\n", type);
}
/* Common stuff again -- free the resource, recurse to next one */
- free(res);
+ if (res) {
+ free(res);
+ }
resources[rindex].res_head = nres;
- if (nres)
+ if (nres) {
free_resource(type);
+ }
}
-/* Save the new resource by chaining it into the head list for
+/*
+ * Save the new resource by chaining it into the head list for
* the resource. If this is pass 2, we update any resource
* pointers (currently only in the Job resource).
*/
res->res_job.fs = res_all.res_job.fs;
res->res_job.storage = res_all.res_job.storage;
res->res_job.pool = res_all.res_job.pool;
+ if (res->res_job.JobType == 0) {
+ Emsg1(M_ABORT, 0, "Job Type not defined for Job resource %s\n", res_all.res_dir.hdr.name);
+ }
+ if (res->res_job.level != 0) {
+ int i;
+ for (i=0; joblevels[i].level_name; i++) {
+ if (joblevels[i].level == res->res_job.level &&
+ joblevels[i].job_type == res->res_job.JobType) {
+ i = 0;
+ break;
+ }
+ }
+ if (i != 0) {
+ Emsg1(M_ABORT, 0, "Inappropriate level specified in Job resource %s\n",
+ res_all.res_dir.hdr.name);
+ }
+ }
break;
case R_CLIENT:
if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_client.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;
+ }
return;
}
}
+/*
+ * Store JobType (backup, verify, restore)
+ *
+ */
+static void store_jobtype(LEX *lc, struct res_items *item, int index, int pass)
+{
+ int token, i;
+
+ token = lex_get_token(lc);
+ if (token != T_IDENTIFIER && token != T_STRING && token != T_QUOTED_STRING) {
+ scan_err1(lc, "expected an identifier or string, got: %s", lc->str);
+ } else {
+ /* Store the type both pass 1 and pass 2 */
+ for (i=0; jobtypes[i].type_name; i++) {
+ if (strcasecmp(lc->str, jobtypes[i].type_name) == 0) {
+ ((JOB *)(item->value))->JobType = jobtypes[i].job_type;
+ i = 0;
+ break;
+ }
+ }
+ if (i != 0) {
+ scan_err1(lc, "Expected a Job Type keyword, got: %s", lc->str);
+ }
+ }
+ scan_to_eol(lc);
+ set_bit(index, res_all.hdr.item_present);
+}
+
+/*
+ * Store Job Level (Full, Incremental, ...)
+ *
+ */
+static void store_level(LEX *lc, struct res_items *item, int index, int pass)
+{
+ int token, i;
+
+ token = lex_get_token(lc);
+ if (token != T_IDENTIFIER && token != T_STRING && token != T_QUOTED_STRING) {
+ scan_err1(lc, "expected an identifier or string, got: %s", lc->str);
+ } else {
+ /* Store the level pass 2 so that type is defined */
+ for (i=0; joblevels[i].level_name; i++) {
+ if (strcasecmp(lc->str, joblevels[i].level_name) == 0) {
+ ((JOB *)(item->value))->level = joblevels[i].level;
+ i = 0;
+ break;
+ }
+ }
+ if (i != 0) {
+ scan_err1(lc, "Expected a Job Level keyword, got: %s", lc->str);
+ }
+ }
+ scan_to_eol(lc);
+ set_bit(index, res_all.hdr.item_present);
+}
+
+
+
/*
* Store backup/verify info for Job record
*
if (token != T_IDENTIFIER && token != T_STRING && token != T_QUOTED_STRING) {
scan_err1(lc, "Expected a backup/verify keyword, got: %s", lc->str);
} else {
- lcase(lc->str);
Dmsg1(190, "Got keyword: %s\n", lc->str);
found = FALSE;
for (i=0; BakVerFields[i].name; i++) {
break;
case 'L':
/* Get level */
- lcase(lc->str);
for (i=0; joblevels[i].level_name; i++) {
- if (joblevels[i].job_class == item->code &&
+ if (joblevels[i].job_type == item->code &&
strcasecmp(lc->str, joblevels[i].level_name) == 0) {
((JOB *)(item->value))->level = joblevels[i].level;
i = 0;
if (token != T_IDENTIFIER && token != T_STRING && token != T_QUOTED_STRING) {
scan_err1(lc, "Expected a Restore keyword, got: %s", lc->str);
} else {
- lcase(lc->str);
found = FALSE;
for (i=0; RestoreFields[i].name; i++) {
Dmsg1(190, "Restore kw=%s\n", lc->str);
- if (strcmp(lc->str, RestoreFields[i].name) == 0) {
+ if (strcasecmp(lc->str, RestoreFields[i].name) == 0) {
found = TRUE;
if (lex_get_token(lc) != T_EQUALS) {
scan_err1(lc, "Expected an equals, got: %s", lc->str);
if (token != T_IDENTIFIER && token != T_STRING && token != T_QUOTED_STRING) {
scan_err1(lc, "Expected a keyword name, got: %s", lc->str);
}
- lcase(lc->str);
/* Fix to scan Replacement options */
for (i=0; ReplaceOptions[i].name; i++) {
- if (strcmp(lc->str, ReplaceOptions[i].name) == 0) {
+ if (strcasecmp(lc->str, ReplaceOptions[i].name) == 0) {
((JOB *)(item->value))->RestoreOptions = ReplaceOptions[i].token;
i = 0;
break;
if (token != T_IDENTIFIER && token != T_STRING && token != T_QUOTED_STRING) {
scan_err1(lc, "expected a FileSet option, got: %s", lc->str);
}
- lcase(lc->str);
if (keyword == FS_KW_VERIFY) { /* special case */
/* ***FIXME**** ensure these are in permitted set */
strcpy(option, "V"); /* indicate Verify */
strcat(option, ":"); /* terminate it */
} else {
for (i=0; FS_options[i].name; i++) {
- if (strcmp(lc->str, FS_options[i].name) == 0 && FS_options[i].keyword == keyword) {
+ if (strcasecmp(lc->str, FS_options[i].name) == 0 && FS_options[i].keyword == keyword) {
option[0] = FS_options[i].option;
i = 0;
break;
scan_err1(lc, "expected a FileSet option keyword, got: %s", lc->str);
} else {
keyword = FS_KW_NONE;
- lcase(lc->str);
for (i=0; FS_option_kw[i].name; i++) {
- if (strcmp(lc->str, FS_option_kw[i].name) == 0) {
+ if (strcasecmp(lc->str, FS_option_kw[i].name) == 0) {
keyword = FS_option_kw[i].token;
break;
}
/* Job Level keyword structure */
struct s_jl {
- char *level_name;
- int level;
- int job_class;
+ char *level_name; /* level keyword */
+ int level; /* level */
+ int job_type; /* JobType permitting this level */
};
+/* Job Type keyword structure */
+struct s_jt {
+ char *type_name;
+ int job_type;
+};
/* Definition of the contents of each Resource */
char *working_directory; /* WorkingDirectory */
char *pid_directory; /* PidDirectory */
char *subsys_directory; /* SubsysDirectory */
- struct s_res_msgs *messages;
+ struct s_res_msgs *messages; /* Daemon message handler */
int MaxConcurrentJobs;
btime_t FDConnectTimeout; /* timeout for connect in seconds */
btime_t SDConnectTimeout; /* timeout in seconds */
struct s_run {
struct s_run *next; /* points to next run record */
int level;
- int job_class;
+ int job_type;
char *since;
int level_no;
int minute; /* minute to run job */
}
/*
- * Run a job
+ * Run a job -- typically called by the scheduler, but may also
+ * be called by the UA (Console program).
*
*/
void run_job(JCR *jcr)
Dmsg0(200, "Done run_job()\n");
}
-/* This is the engine called by workq_add() */
+/*
+ * This is the engine called by workq_add() when we were pulled
+ * from the work queue.
+ * At this point, we are running in our own thread
+ */
static void job_thread(void *arg)
{
time_t now;
if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
(btime_t)(jcr->start_time - jcr->sched_time)) {
Jmsg(jcr, M_FATAL, 0, _("Job cancelled because max delay time exceeded.\n"));
- free_jcr(jcr);
- }
- jcr->JobStatus = JS_Running;
+ jcr->JobStatus = JS_ErrorTerminated;
+ update_job_end_record(jcr);
+ } else {
- switch (jcr->JobType) {
- case JT_BACKUP:
- do_backup(jcr);
- break;
- case JT_VERIFY:
- do_verify(jcr);
- break;
- case JT_RESTORE:
- do_restore(jcr);
- break;
- default:
- Dmsg1(0, "Unimplemented job type: %d\n", jcr->JobType);
- break;
+ /* Run Job */
+ jcr->JobStatus = JS_Running;
+
+ switch (jcr->JobType) {
+ case JT_BACKUP:
+ do_backup(jcr);
+ break;
+ case JT_VERIFY:
+ do_verify(jcr);
+ break;
+ case JT_RESTORE:
+ do_restore(jcr);
+ break;
+ case JT_ADMIN:
+ /* No actual job */
+ break;
+ default:
+ Dmsg1(0, "Unimplemented job type: %d\n", jcr->JobType);
+ break;
+ }
}
Dmsg0(50, "Before free jcr\n");
free_jcr(jcr);
Dmsg0(50, "======== End Job ==========\n");
}
+/*
+ * Get or create a Client record for this Job
+ */
+int get_or_create_client_record(JCR *jcr)
+{
+ CLIENT_DBR cr;
+
+ memset(&cr, 0, sizeof(cr));
+ strcpy(cr.Name, jcr->client->hdr.name);
+ cr.AutoPrune = jcr->client->AutoPrune;
+ cr.FileRetention = jcr->client->FileRetention;
+ cr.JobRetention = jcr->client->JobRetention;
+ if (jcr->client_name) {
+ free(jcr->client_name);
+ }
+ jcr->client_name = bstrdup(jcr->client->hdr.name);
+ if (!db_create_client_record(jcr->db, &cr)) {
+ Jmsg(jcr, M_ERROR, 0, _("Could not create Client record. %s"),
+ db_strerror(jcr->db));
+ return 0;
+ }
+ jcr->jr.ClientId = cr.ClientId;
+ Dmsg2(9, "Created Client %s record %d\n", jcr->client->hdr.name,
+ jcr->jr.ClientId);
+ return 1;
+}
+
+
+/*
+ * Write status and such in DB
+ */
+void update_job_end_record(JCR *jcr)
+{
+ if (jcr->jr.EndTime == 0) {
+ jcr->jr.EndTime = time(NULL);
+ }
+ jcr->end_time = jcr->jr.EndTime;
+ jcr->jr.JobId = jcr->JobId;
+ jcr->jr.JobStatus = jcr->JobStatus;
+ jcr->jr.JobFiles = jcr->JobFiles;
+ jcr->jr.JobBytes = jcr->JobBytes;
+ jcr->jr.VolSessionId = jcr->VolSessionId;
+ jcr->jr.VolSessionTime = jcr->VolSessionTime;
+ if (!db_update_job_end_record(jcr->db, &jcr->jr)) {
+ Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
+ db_strerror(jcr->db));
+ }
+}
+
/*
* Takes base_name and appends (unique) current
* date and time to form unique job name.
extern void free_jcr(JCR *jcr);
extern void set_jcr_defaults(JCR *jcr, JOB *job);
extern void create_unique_job_name(JCR *jcr, char *base_name);
+extern void update_job_end_record(JCR *jcr);
+extern int get_or_create_client_record(JCR *jcr);
/* mountreq.c */
extern void mount_request(JCR *jcr, BSOCK *bs, char *buf);
char dt[MAX_TIME_LENGTH];
BSOCK *fd;
JOB_DBR rjr; /* restore job record */
- CLIENT_DBR cr;
- /*
- * Get or Create a client record
- */
- memset(&cr, 0, sizeof(cr));
- strcpy(cr.Name, jcr->client->hdr.name);
- cr.AutoPrune = jcr->client->AutoPrune;
- cr.FileRetention = jcr->client->FileRetention;
- cr.JobRetention = jcr->client->JobRetention;
- if (jcr->client_name) {
- free(jcr->client_name);
- }
- jcr->client_name = bstrdup(jcr->client->hdr.name);
- if (!db_create_client_record(jcr->db, &cr)) {
- Jmsg(jcr, M_ERROR, 0, _("Could not create Client record. %s"),
- db_strerror(jcr->db));
+
+ if (!get_or_create_client_record(jcr)) {
restore_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
- jcr->jr.ClientId = cr.ClientId;
memset(&rjr, 0, sizeof(rjr));
jcr->jr.Level = 'F'; /* Full restore */
char dt[MAX_TIME_LENGTH];
Dmsg0(20, "In restore_cleanup\n");
- if (jcr->jr.EndTime == 0) {
- jcr->jr.EndTime = time(NULL);
- }
- jcr->jr.JobStatus = jcr->JobStatus = status;
- if (!db_update_job_end_record(jcr->db, &jcr->jr)) {
- Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
- db_strerror(jcr->db));
- }
+ jcr->JobStatus = status;
+
+ update_job_end_record(jcr);
bstrftime(dt, sizeof(dt), jcr->jr.EndTime);
Jmsg(jcr, M_INFO, 0, _("%s End Restore Job %s.\n"),
if (token != T_STRING) {
scan_err1(lc, _("Expected a Job level identifier, got: %s"), lc->str);
} else {
- lcase(lc->str);
+ if (strcasecmp(lc->str, "level")) {
+ if (lex_get_token(lc) != T_EQUALS) {
+ scan_err1(lc, "Expected an equals, got: %s", lc->str);
+ }
+ token = lex_get_token(lc);
+ }
for (i=0; joblevels[i].level_name; i++) {
if (strcasecmp(lc->str, joblevels[i].level_name) == 0) {
lrun.level = joblevels[i].level;
- lrun.job_class = joblevels[i].job_class;
+ lrun.job_type = joblevels[i].job_type;
i = 0;
break;
}
*
* Kern Sibbald, February MMII
*
- * $Id:
+ * $Id$
*/
/*
/*
- * Called here to count entries to be deleted
+ * Called here to count the number of Jobs to be pruned
*/
static int file_count_handler(void *ctx, int num_fields, char **row)
{
int i;
btime_t now, period;
CLIENT_DBR cr;
- char ed1[50];
+ char ed1[50], ed2[50];
memset(&cr, 0, sizeof(cr));
memset(&del, 0, sizeof(del));
db_sql_query(ua->db, query, file_delete_handler, (void *)&del);
for (i=0; i < del.num_ids; i++) {
+ struct s_count_ctx cnt;
Dmsg1(050, "Delete JobId=%d\n", del.JobId[i]);
+ Mmsg(&query, "SELECT count(*) FROM File WHERE JobId=%d", del.JobId[i]);
+ cnt.count = 0;
+ db_sql_query(ua->db, query, count_handler, (void *)&cnt);
+ del.tot_ids += cnt.count;
Mmsg(&query, "DELETE FROM File WHERE JobId=%d", del.JobId[i]);
db_sql_query(ua->db, query, NULL, (void *)NULL);
/*
db_sql_query(ua->db, query, NULL, (void *)NULL);
Dmsg1(050, "Del sql=%s\n", query);
}
- bsendmsg(ua, _("Pruned %d Files for client %s from %s catalog.\n"), del.num_ids,
- client->hdr.name, client->catalog->hdr.name);
+ edit_uint64_with_commas(del.tot_ids, ed1);
+ edit_uint64_with_commas(del.num_ids, ed2);
+ bsendmsg(ua, _("Pruned %s Files from %s Jobs for client %s from %s catalog.\n"),
+ ed1, ed2, client->hdr.name, client->catalog->hdr.name);
bail_out:
if (del.JobId) {
*
* Kern Sibbald, February MMII
*
- * $Id:
+ * $Id$
*/
/*
*
* Kern Sibbald, October MMI
*
- * $Id:
+ * $Id$
*/
/*
static char OKlevel[] = "2000 OK level\n";
/* Forward referenced functions */
-static void verify_cleanup(JCR *jcr);
+static void verify_cleanup(JCR *jcr, int TermCode);
static void prt_fname(JCR *jcr);
static int missing_handler(void *ctx, int num_fields, char **row);
BSOCK *fd;
JOB_DBR jr;
int last_full_id;
- CLIENT_DBR cr;
-
- memset(&cr, 0, sizeof(cr));
- cr.AutoPrune = jcr->client->AutoPrune;
- cr.FileRetention = jcr->client->FileRetention;
- cr.JobRetention = jcr->client->JobRetention;
- strcpy(cr.Name, jcr->client->hdr.name);
- if (jcr->client_name) {
- free(jcr->client_name);
- }
- jcr->client_name = bstrdup(jcr->client->hdr.name);
- if (!db_create_client_record(jcr->db, &cr)) {
- Jmsg(jcr, M_ERROR, 0, _("Could not create Client record. %s"),
- db_strerror(jcr->db));
- jcr->JobStatus = JS_ErrorTerminated;
- verify_cleanup(jcr);
+
+ if (!get_or_create_client_record(jcr)) {
+ verify_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
- jcr->jr.ClientId = cr.ClientId;
Dmsg1(9, "bdird: created client %s record\n", jcr->client->hdr.name);
if (!db_find_last_full_verify(jcr->db, &jr)) {
Jmsg(jcr, M_FATAL, 0, _("Unable to find last full verify. %s"),
db_strerror(jcr->db));
- jcr->JobStatus = JS_ErrorTerminated;
- verify_cleanup(jcr);
+ verify_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
last_full_id = jr.JobId;
jcr->jr.Level = jcr->level;
if (!db_update_job_start_record(jcr->db, &jcr->jr)) {
Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
- jcr->JobStatus = JS_ErrorTerminated;
- verify_cleanup(jcr);
+ verify_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
jr.JobId = last_full_id;
if (!db_get_job_record(jcr->db, &jr)) {
Jmsg(jcr, M_ERROR, 0, _("Could not get job record. %s"), db_strerror(jcr->db));
- jcr->JobStatus = JS_ErrorTerminated;
- verify_cleanup(jcr);
+ verify_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
Jmsg(jcr, M_INFO, 0, _("Verifying against Init JobId %d run %s\n"),
*/
jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */
if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
- jcr->JobStatus = JS_ErrorTerminated;
- verify_cleanup(jcr);
+ verify_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
Dmsg0(30, ">filed: Send include list\n");
if (!send_include_list(jcr)) {
- jcr->JobStatus = JS_ErrorTerminated;
- verify_cleanup(jcr);
+ verify_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
Dmsg0(30, ">filed: Send exclude list\n");
if (!send_exclude_list(jcr)) {
- jcr->JobStatus = JS_ErrorTerminated;
- verify_cleanup(jcr);
+ verify_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
break;
default:
Emsg1(M_FATAL, 0, _("Unimplemented save level %d\n"), jcr->level);
- jcr->JobStatus = JS_ErrorTerminated;
- verify_cleanup(jcr);
+ verify_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
Dmsg1(20, ">filed: %s", fd->msg);
bnet_fsend(fd, levelcmd, level, " ");
if (!response(fd, OKlevel, "Level")) {
- jcr->JobStatus = JS_ErrorTerminated;
- verify_cleanup(jcr);
+ verify_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
*/
bnet_fsend(fd, verifycmd);
if (!response(fd, OKverify, "Verify")) {
- jcr->JobStatus = JS_ErrorTerminated;
- verify_cleanup(jcr);
+ verify_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
} else {
Emsg1(M_FATAL, 0, _("Unimplemented save level %d\n"), jcr->level);
- jcr->JobStatus = JS_ErrorTerminated;
- verify_cleanup(jcr);
+ verify_cleanup(jcr, JS_ErrorTerminated);
return 0;
}
- verify_cleanup(jcr);
+ verify_cleanup(jcr, JS_Terminated);
return 1;
}
* Release resources allocated during backup.
*
*/
-static void verify_cleanup(JCR *jcr)
+static void verify_cleanup(JCR *jcr, int TermCode)
{
char sdt[50], edt[50];
char ec1[30];
char term_code[100];
char *term_msg;
int msg_type;
- int TermCode;
int last_full_id;
Dmsg0(100, "Enter verify_cleanup()\n");
last_full_id = jcr->jr.JobId;
+ jcr->JobStatus = TermCode;
-
- if (jcr->jr.EndTime == 0) {
- jcr->jr.EndTime = time(NULL);
- }
- jcr->end_time = jcr->jr.EndTime;
- jcr->jr.JobId = jcr->JobId;
- jcr->jr.JobStatus = jcr->JobStatus;
- TermCode = jcr->JobStatus;
-
- if (!db_update_job_end_record(jcr->db, &jcr->jr)) {
- Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
- db_strerror(jcr->db));
- }
+ update_job_end_record(jcr);
msg_type = M_INFO; /* by default INFO message */
switch (TermCode) {
case JS_Terminated:
term_msg = _("Verify OK");
break;
- case JS_Errored:
+ case JS_ErrorTerminated:
term_msg = _("*** Verify Error ***");
msg_type = M_ERROR; /* Generate error message */
break;
static char *configfile = NULL;
static int foreground = 0;
static workq_t dir_workq; /* queue of work from Director */
+static CLIENT *me; /* my resource */
static void usage()
{
int ch;
int no_signals = FALSE;
int test_config = FALSE;
- CLIENT *me; /* my resource */
DIRRES *director;
init_stack_dump();
my_name_is(argc, argv, "filed");
+ init_msg(NULL, NULL);
daemon_start_time = time(NULL);
memset(&last_job, 0, sizeof(last_job));
configfile = bstrdup(CONFIG_FILE);
}
-
- init_msg(NULL, NULL);
parse_config(configfile);
LockRes();
Emsg1(M_ABORT, 0, _("No File daemon resource defined in %s\n\
Without that I don't know who I am :-(\n"), configfile);
} else {
- my_name_is(0, (char **)NULL, me->hdr.name);
+ my_name_is(0, NULL, me->hdr.name);
+ if (!me->messages) {
+ LockRes();
+ me->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
+ UnlockRes();
+ if (!me->messages) {
+ Emsg1(M_ABORT, 0, _("No Messages resource defined in %s\n"), configfile);
+ }
+ }
+ close_msg(NULL); /* close temp message handler */
+ init_msg(NULL, me->messages); /* open user specified message handler */
}
working_directory = me->working_directory;
init_stack_dump(); /* set new pid */
}
+ create_pid_file(me->pid_directory, "bacula-fd", me->FDport);
+
#ifdef BOMB
me += 1000000;
#endif
if (debug_level > 5) {
print_memory_pool_stats();
}
+ delete_pid_file(me->pid_directory, "bacula-fd", me->FDport);
free_config_resources();
- close_memory_pool(); /* free memory in pool */
term_msg();
+ close_memory_pool(); /* release free memory in pool */
sm_dump(False); /* dump orphaned buffers */
exit(1);
}
{"name", store_name, ITEM(res_client.hdr.name), 0, ITEM_REQUIRED, 0},
{"description", store_str, ITEM(res_client.hdr.desc), 0, 0, 0},
{"fdport", store_pint, ITEM(res_client.FDport), 0, ITEM_REQUIRED, 0},
- {"workingdirectory", store_dir, ITEM(res_client.working_directory), 0, ITEM_REQUIRED, 0},
- {"piddirectory", store_dir, ITEM(res_client.pid_directory), 0, ITEM_REQUIRED, 0},
+ {"workingdirectory", store_dir, ITEM(res_client.working_directory), 0, ITEM_REQUIRED, 0},
+ {"piddirectory", store_dir, ITEM(res_client.pid_directory), 0, ITEM_REQUIRED, 0},
{"subsysdirectory", store_dir, ITEM(res_client.subsys_directory), 0, ITEM_REQUIRED, 0},
+ {"messages", store_res, ITEM(res_client.messages), R_MSGS, 0, 0},
{NULL, NULL, NULL, 0, 0, 0}
};
break;
case R_MSGS:
sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
+ if (res->res_msgs.mail_cmd)
+ sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
+ if (res->res_msgs.operator_cmd)
+ sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
break;
default:
sendit(sock, "Unknown resource type %d\n", type);
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:
printf("Unknown resource type %d\n", type);
}
/* Common stuff again -- free the resource, recurse to next one */
- free(res);
+ if (res) {
+ free(res);
+ }
resources[rindex].res_head = nres;
if (nres) {
free_resource(type);
/* Resources not containing a resource */
case R_MSGS:
case R_DIRECTOR:
- case R_CLIENT:
break;
+ /* Resources containing another resource */
+ case R_CLIENT:
+ if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_dir.hdr.name)) == NULL) {
+ Emsg1(M_ABORT, 0, "Cannot find Client resource %s\n", res_all.res_dir.hdr.name);
+ }
+ res->res_client.messages = res_all.res_client.messages;
+ break;
default:
Emsg1(M_ERROR, 0, _("Unknown resource type %d\n"), type);
error = 1;
}
/* Common */
if (!error) {
- res = (URES *) malloc(size);
+ res = (URES *)malloc(size);
memcpy(res, &res_all, size);
res->res_dir.hdr.next = resources[rindex].res_head;
resources[rindex].res_head = (RES *)res;
/*
* Resource codes -- they must be sequential for indexing
*/
-#define R_FIRST 1001
+#define R_FIRST 1001
-#define R_DIRECTOR 1001
-#define R_CLIENT 1002
-#define R_MSGS 1003
+#define R_DIRECTOR 1001
+#define R_CLIENT 1002
+#define R_MSGS 1003
-#define R_LAST R_MSGS
+#define R_LAST R_MSGS
/*
* Some resource attributes
*/
-#define R_NAME 1020
-#define R_ADDRESS 1021
-#define R_PASSWORD 1022
-#define R_TYPE 1023
+#define R_NAME 1020
+#define R_ADDRESS 1021
+#define R_PASSWORD 1022
+#define R_TYPE 1023
/* Definition of the contents of each Resource */
struct s_res_dir {
- RES hdr;
- char *password; /* Director password */
- char *address; /* Director address or zero */
+ RES hdr;
+ char *password; /* Director password */
+ char *address; /* Director address or zero */
};
typedef struct s_res_dir DIRRES;
struct s_res_client {
- RES hdr;
- int FDport; /* where we listen for Directors */
+ RES hdr;
+ int FDport; /* where we listen for Directors */
char *working_directory;
char *pid_directory;
char *subsys_directory;
+ struct s_res_msgs *messages; /* daemon message handler */
};
typedef struct s_res_client CLIENT;
* resource structure definitions.
*/
union u_res {
- struct s_res_dir res_dir;
- struct s_res_client res_client;
- struct s_res_msgs res_msgs;
+ struct s_res_dir res_dir;
+ struct s_res_client res_client;
+ struct s_res_msgs res_msgs;
RES hdr;
};
}
- // Now enter the message handling loop until told to quit!
+ // Now enter the Windows message handling loop until told to quit!
MSG msg;
while (GetMessage(&msg, NULL, 0,0) ) {
TranslateMessage(&msg);
// Tell the service manager that we've stopped.
ReportStatus(SERVICE_STOPPED, g_error, 0);
}
- kill(main_pid, SIGTERM);
+ kill(main_pid, SIGTERM); /* ask main thread to terminate */
_exit(0);
}
#define JT_VERIFY 'V'
#define JT_RESTORE 'R'
#define JT_CONSOLE 'C' /* console program */
+#define JT_ADMIN 'D' /* admin job */
+#define JT_ARCHIVE 'A'
/* Job Status */
#define JS_Created 'C'
time_t start_time; /* when job actually started */
time_t run_time; /* used for computing speed */
time_t end_time; /* job end time */
- char *VolumeName; /* Volume name desired -- pool_memory */
+ POOLMEM *VolumeName; /* Volume name desired -- pool_memory */
char *client_name; /* client name */
char *sd_auth_key; /* SD auth key */
MSGS *msgs; /* Message resource */
- DEST *dest_chain; /* Job message destination chain */
- char send_msg[nbytes_for_bits(M_MAX+1)]; /* message bit mask */
/* Daemon specific part of JCR */
/* This should be empty in the library */
#define HEAD_SIZE BALIGN(sizeof(struct abufhead))
-extern void *sm_malloc(char *fname, int lineno, int nbytes);
+extern POOLMEM *sm_malloc(char *fname, int lineno, int nbytes);
-void *sm_get_pool_memory(char *fname, int lineno, int pool)
+POOLMEM *sm_get_pool_memory(char *fname, int lineno, int pool)
{
struct abufhead *buf;
V(mutex);
Dmsg3(150, "sm_get_pool_memory reuse %x to %s:%d\n", buf, fname, lineno);
sm_new_owner(fname, lineno, (char *)buf);
- return (void *)((char *)buf+HEAD_SIZE);
+ return (POOLMEM *)((char *)buf+HEAD_SIZE);
}
if ((buf = (struct abufhead *) sm_malloc(fname, lineno, pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
}
V(mutex);
Dmsg3(150, "sm_get_pool_memory give %x to %s:%d\n", buf, fname, lineno);
- return (void *)((char *)buf+HEAD_SIZE);
+ return (POOLMEM *)((char *)buf+HEAD_SIZE);
}
/* Get nonpool memory of size requested */
-void *sm_get_memory(char *fname, int lineno, size_t size)
+POOLMEM *sm_get_memory(char *fname, int lineno, size_t size)
{
struct abufhead *buf;
int pool = 0;
pool_ctl[pool].in_use++;
if (pool_ctl[pool].in_use > pool_ctl[pool].max_used)
pool_ctl[pool].max_used = pool_ctl[pool].in_use;
- return (void *)(((char *)buf)+HEAD_SIZE);
+ return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
}
#else
-void *get_pool_memory(int pool)
+POOLMEM *get_pool_memory(int pool)
{
struct abufhead *buf;
buf = pool_ctl[pool].free_buf;
pool_ctl[pool].free_buf = buf->next;
V(mutex);
- return (void *)((char *)buf+HEAD_SIZE);
+ return (POOLMEM *)((char *)buf+HEAD_SIZE);
}
if ((buf=malloc(pool_ctl[pool].size+HEAD_SIZE)) == NULL) {
pool_ctl[pool].max_used = pool_ctl[pool].in_use;
}
V(mutex);
- return (void *)(((char *)buf)+HEAD_SIZE);
+ return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
}
/* Get nonpool memory of size requested */
-void *get_memory(size_t size)
+POOLMEM *get_memory(size_t size)
{
struct abufhead *buf;
int pool = 0;
if (pool_ctl[pool].in_use > pool_ctl[pool].max_used) {
pool_ctl[pool].max_used = pool_ctl[pool].in_use;
}
- return (void *)(((char *)buf)+HEAD_SIZE);
+ return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
}
#endif /* SMARTALLOC */
/* Free a memory buffer */
-void free_pool_memory(void *obuf)
+void free_pool_memory(POOLMEM *obuf)
{
struct abufhead *buf;
int pool;
/* Return the size of a memory buffer */
-size_t sizeof_pool_memory(void *obuf)
+size_t sizeof_pool_memory(POOLMEM *obuf)
{
char *cp = (char *)obuf;
}
/* Realloc pool memory buffer */
-void *realloc_pool_memory(void *obuf, size_t size)
+POOLMEM *realloc_pool_memory(POOLMEM *obuf, size_t size)
{
char *cp = (char *)obuf;
void *buf;
}
V(mutex);
sm_check(__FILE__, __LINE__, False);
- return (void *)(((char *)buf)+HEAD_SIZE);
+ return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
}
-void *check_pool_memory_size(void *obuf, size_t size)
+POOLMEM *check_pool_memory_size(POOLMEM *obuf, size_t size)
{
sm_check(__FILE__, __LINE__, False);
ASSERT(obuf);
free((char *)buf);
buf = next;
}
+ pool_ctl[i].free_buf = NULL;
}
V(mutex);
}
#ifdef SMARTALLOC
#define get_pool_memory(pool) sm_get_pool_memory(__FILE__, __LINE__, pool)
-extern void *sm_get_pool_memory(char *file, int line, int pool);
+extern POOLMEM *sm_get_pool_memory(char *file, int line, int pool);
#define get_memory(size) sm_get_memory(__FILE__, __LINE__, size)
-extern void *sm_get_memory(char *fname, int line, size_t size);
+extern POOLMEM *sm_get_memory(char *fname, int line, size_t size);
#else
-extern void *get_pool_memory(int pool);
-extern void *get_memory(size_t size);
+extern POOLMEM *get_pool_memory(int pool);
+extern POOLMEM *get_memory(size_t size);
#endif
#define free_memory(x) free_pool_memory(x)
-extern void free_pool_memory(void *buf);
-extern size_t sizeof_pool_memory(void *buf);
-extern void *realloc_pool_memory(void *buf, size_t size);
-extern void *check_pool_memory_size(void *buf, size_t size);
+extern void free_pool_memory(POOLMEM *buf);
+extern size_t sizeof_pool_memory(POOLMEM *buf);
+extern POOLMEM *realloc_pool_memory(POOLMEM *buf, size_t size);
+extern POOLMEM *check_pool_memory_size(POOLMEM *buf, size_t size);
extern void close_memory_pool();
extern void print_memory_pool_stats();
/* Imported functions */
-static MSGS daemon_msg; /* global messages */
+
+/* Static storage */
+
+static MSGS *daemon_msgs; /* global messages */
/*
* Set daemon name. Also, find canonical execution
}
}
-/* Initialize message handler */
+/*
+ * Initialize message handler for a daemon or a Job
+ *
+ * NULL for jcr -> initialize global messages for daemon
+ * non-NULL -> initialize jcr using Message resource
+ */
void
init_msg(void *vjcr, MSGS *msg)
{
DEST *d, *dnew, *temp_chain = NULL;
JCR *jcr = (JCR *)vjcr;
- if (!msg) { /* If nothing specified, use */
- msg = &daemon_msg; /* daemon global message resource */
+ /*
+ * If msg is NULL, initialize global chain for STDOUT and syslog
+ */
+ if (msg == NULL) {
+ int i;
+ daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
+ memset(daemon_msgs, 0, sizeof(MSGS));
+ for (i=1; i<=M_MAX; i++) {
+ add_msg_dest(daemon_msgs, MD_STDOUT, i, NULL, NULL);
+ add_msg_dest(daemon_msgs, MD_SYSLOG, i, NULL, NULL);
+ }
+ Dmsg1(050, "Create daemon global message resource 0x%x\n", daemon_msgs);
+ return;
}
- if (!jcr) {
- memset(msg, 0, sizeof(msg)); /* init daemon global message */
- } else { /* init for job */
- /* Walk down the global chain duplicating it
- * for the current Job. No need to duplicate
- * the attached strings.
- */
- for (d=daemon_msg.dest_chain; d; d=d->next) {
- dnew = (DEST *) malloc(sizeof(DEST));
- memcpy(dnew, d, sizeof(DEST));
- dnew->next = temp_chain;
- dnew->fd = NULL;
- dnew->mail_filename = NULL;
- temp_chain = dnew;
+
+ /*
+ * Walk down the message resource chain duplicating it
+ * for the current Job.
+ */
+ for (d=msg->dest_chain; d; d=d->next) {
+ dnew = (DEST *) malloc(sizeof(DEST));
+ memcpy(dnew, d, sizeof(DEST));
+ dnew->next = temp_chain;
+ dnew->fd = NULL;
+ dnew->mail_filename = NULL;
+ if (d->mail_cmd) {
+ dnew->mail_cmd = bstrdup(d->mail_cmd);
+ }
+ if (d->where) {
+ dnew->where = bstrdup(d->where);
}
+ temp_chain = dnew;
+ }
- jcr->dest_chain = temp_chain;
- memcpy(jcr->send_msg, daemon_msg.send_msg, sizeof(daemon_msg.send_msg));
+ if (jcr) {
+ jcr->msgs = (MSGS *)malloc(sizeof(MSGS));
+ memset(jcr->msgs, 0, sizeof(MSGS));
+ jcr->msgs->dest_chain = temp_chain;
+ memcpy(jcr->msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
+ } else {
+ daemon_msgs = (MSGS *)malloc(sizeof(MSGS));
+ memset(daemon_msgs, 0, sizeof(MSGS));
+ daemon_msgs->dest_chain = temp_chain;
+ memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
}
+ Dmsg2(050, "Copy message resource 0x%x to 0x%x\n", msg, temp_chain);
}
/* Initialize so that the console (User Agent) can
void add_msg_dest(MSGS *msg, int dest_code, int msg_type, char *where, char *mail_cmd)
{
DEST *d;
-
- /* First search the existing chain and see if we
+ /*
+ * First search the existing chain and see if we
* can simply add this msg_type to an existing entry.
*/
- for (d=daemon_msg.dest_chain; d; d=d->next) {
+ for (d=msg->dest_chain; d; d=d->next) {
if (dest_code == d->dest_code && ((where == NULL && d->where == NULL) ||
(strcmp(where, d->where) == 0))) {
Dmsg4(200, "Add to existing d=%x msgtype=%d destcode=%d where=%s\n",
d, msg_type, dest_code, where);
set_bit(msg_type, d->msg_types);
- set_bit(msg_type, daemon_msg.send_msg); /* set msg_type bit in our local */
+ set_bit(msg_type, msg->send_msg); /* set msg_type bit in our local */
return;
}
}
/* Not found, create a new entry */
- d = (DEST *) malloc(sizeof(DEST));
+ d = (DEST *)malloc(sizeof(DEST));
memset(d, 0, sizeof(DEST));
- d->next = daemon_msg.dest_chain;
+ d->next = msg->dest_chain;
d->dest_code = dest_code;
set_bit(msg_type, d->msg_types); /* set type bit in structure */
- set_bit(msg_type, daemon_msg.send_msg); /* set type bit in our local */
+ set_bit(msg_type, msg->send_msg); /* set type bit in our local */
if (where) {
d->where = bstrdup(where);
}
Dmsg5(200, "add new d=%x msgtype=%d destcode=%d where=%s mailcmd=%s\n",
d, msg_type, dest_code, where?where:"(null)",
d->mail_cmd?d->mail_cmd:"(null)");
- daemon_msg.dest_chain = d;
+ msg->dest_chain = d;
}
/*
{
DEST *d;
- for (d=daemon_msg.dest_chain; d; d=d->next) {
+ for (d=msg->dest_chain; d; d=d->next) {
Dmsg2(200, "Remove_msg_dest d=%x where=%s\n", d, d->where);
if (bit_is_set(msg_type, d->msg_types) && (dest_code == d->dest_code) &&
((where == NULL && d->where == NULL) ||
Dmsg1(200, "mailcmd=%s\n", cmd);
pfd = popen(*cmd, "w");
if (!pfd) {
- Emsg2(M_ERROR, 0, "popen %s failed: ERR=%s\n", cmd, strerror(errno));
- if (jcr) {
- Jmsg(jcr, M_ERROR, 0, "mail popen %s failed: ERR=%s\n", cmd, strerror(errno));
- }
+ Jmsg(jcr, M_ERROR, 0, "mail popen %s failed: ERR=%s\n", cmd, strerror(errno));
}
return pfd;
}
/*
- * Close the messages for this job, which means to close
+ * Close the messages for this Messages resource, which means to close
* any open files, and dispatch any pending email messages.
- *
- * This closes messages only for this job, other jobs can
- * still send messages.
- *
- * Note, we free our local message destination chain, but
- * the global chain remains allowing other jobs to
- * start.
*/
void close_msg(void *vjcr)
{
- DEST *d, *old;
+ MSGS *msgs;
+ JCR *jcr = (JCR *)vjcr;
+ DEST *d;
FILE *pfd;
- char *cmd, *line;
+ POOLMEM *cmd, *line;
int len;
- JCR *jcr = (JCR *)vjcr;
- Dmsg0(200, "Close_msg\n");
- cmd = (char *)get_pool_memory(PM_MESSAGE);
- for (d=jcr->dest_chain; d; ) {
+ Dmsg1(050, "Close_msg jcr=0x%x\n", jcr);
+
+ if (jcr == NULL) { /* NULL -> global chain */
+ msgs = daemon_msgs;
+ daemon_msgs = NULL;
+ } else {
+ msgs = jcr->msgs;
+ jcr->msgs = NULL;
+ }
+ if (msgs == NULL) {
+ return;
+ }
+ Dmsg1(050, "close msg resource at 0x%x\n", msgs);
+ cmd = get_pool_memory(PM_MESSAGE);
+ for (d=msgs->dest_chain; d; ) {
if (d->fd) {
switch (d->dest_code) {
case MD_FILE:
if (!d->fd) {
break;
}
- if (d->dest_code == MD_MAIL_ON_ERROR &&
+ if (d->dest_code == MD_MAIL_ON_ERROR && jcr &&
jcr->JobStatus == JS_Terminated) {
goto rem_temp_file;
}
goto rem_temp_file;
}
len = d->max_len+10;
- line = (char *)get_memory(len);
+ line = get_memory(len);
rewind(d->fd);
while (fgets(line, len, d->fd)) {
fputs(line, pfd);
}
d->fd = NULL;
}
+ d = d->next; /* point to next buffer */
+ }
+ free_pool_memory(cmd);
+
+ free_msgs_res(msgs);
+}
+
+/*
+ * Free memory associated with Messages resource
+ */
+void free_msgs_res(MSGS *msgs)
+{
+ DEST *d, *old;
+
+ for (d=msgs->dest_chain; d; ) {
+ if (d->where) {
+ free(d->where);
+ }
+ if (d->mail_cmd) {
+ free(d->mail_cmd);
+ }
old = d; /* save pointer to release */
d = d->next; /* point to next buffer */
free(old); /* free the destination item */
}
- free_pool_memory(cmd);
- jcr->dest_chain = NULL;
+ msgs->dest_chain = NULL;
+ free(msgs);
}
/*
* Terminate the message handler for good.
* Release the global destination chain.
+ *
+ * Also, clean up a few other items (cons, exepath). Note,
+ * these really should be done elsewhere.
*/
void term_msg()
{
- DEST *d, *n;
-
- for (d=daemon_msg.dest_chain; d; d=n) {
- if (d->fd) {
- if (d->dest_code == MD_FILE || d->dest_code == MD_APPEND) {
- fclose(d->fd); /* close open file descriptor */
- d->fd = NULL;
- } else if (d->dest_code == MD_MAIL || d->dest_code == MD_MAIL_ON_ERROR) {
- fclose(d->fd);
- d->fd = NULL;
- unlink(d->mail_filename);
- free_pool_memory(d->mail_filename);
- d->mail_filename = NULL;
- }
- }
- n = d->next;
- if (d->where)
- free(d->where); /* free destination address */
- if (d->mail_cmd)
- free(d->mail_cmd);
- free(d);
- }
+ Dmsg0(100, "Enter term_msg\n");
+ close_msg(NULL); /* close global chain */
+ daemon_msgs = NULL;
if (con_fd) {
fflush(con_fd);
fclose(con_fd);
void dispatch_message(void *vjcr, int type, int level, char *buf)
{
DEST *d;
- char cmd[MAXSTRING], *mcmd;
+ char cmd[MAXSTRING];
+ POOLMEM *mcmd;
JCR *jcr = (JCR *) vjcr;
int len;
+ MSGS *msgs;
Dmsg2(200, "Enter dispatch_msg type=%d msg=%s\n", type, buf);
}
/* Now figure out where to send the message */
+ msgs = NULL;
if (jcr) {
- d = jcr->dest_chain; /* use job message chain */
- } else {
- d = daemon_msg.dest_chain; /* use global chain */
+ msgs = jcr->msgs;
+ }
+ if (msgs == NULL) {
+ msgs = daemon_msgs;
}
- for ( ; d; d=d->next) {
+ for (d=msgs->dest_chain; d; d=d->next) {
if (bit_is_set(type, d->msg_types)) {
switch (d->dest_code) {
case MD_CONSOLE:
break;
case MD_OPERATOR:
Dmsg1(200, "OPERATOR for following err: %s\n", buf);
- mcmd = (char *) get_pool_memory(PM_MESSAGE);
+ mcmd = get_pool_memory(PM_MESSAGE);
d->fd = open_mail_pipe(jcr, &mcmd, d);
free_pool_memory(mcmd);
if (d->fd) {
void
e_msg(char *file, int line, int type, int level, char *fmt,...)
{
- char buf[1000];
+ char buf[2000];
va_list arg_ptr;
int i;
* Check if we have a message destination defined.
* We always report M_ABORT
*/
- if (type != M_ABORT && !bit_is_set(type, daemon_msg.send_msg))
+ if (!daemon_msgs || (type != M_ABORT &&
+ !bit_is_set(type, daemon_msgs->send_msg)))
return; /* no destination */
switch (type) {
case M_ABORT:
* Check if we have a message destination defined.
* We always report M_ABORT
*/
- if (type != M_ABORT && !bit_is_set(type, jcr->send_msg)) {
+ if (type != M_ABORT && jcr->msgs && !bit_is_set(type, jcr->msgs->send_msg)) {
Dmsg1(200, "No bit set for type %d\n", type);
return; /* no destination */
}
*/
/* base64.c */
-void base64_init __PROTO((void));
-int to_base64 __PROTO((intmax_t value, char *where));
-int from_base64 __PROTO((intmax_t *value, char *where));
-void encode_stat __PROTO((char *buf, struct stat *statp));
-void decode_stat __PROTO((char *buf, struct stat *statp));
-int bin_to_base64 __PROTO((char *buf, char *bin, int len));
+void base64_init __PROTO((void));
+int to_base64 __PROTO((intmax_t value, char *where));
+int from_base64 __PROTO((intmax_t *value, char *where));
+void encode_stat __PROTO((char *buf, struct stat *statp));
+void decode_stat __PROTO((char *buf, struct stat *statp));
+int bin_to_base64 __PROTO((char *buf, char *bin, int len));
/* bmisc.c */
-void *b_malloc (char *file, int line, size_t size);
+void *b_malloc (char *file, int line, size_t size);
#ifndef DEBUG
-void *bmalloc (size_t size);
+void *bmalloc (size_t size);
#endif
-void *brealloc (void *buf, size_t size);
-void *bcalloc (size_t size1, size_t size2);
-int bsnprintf (char *str, size_t size, const char *format, ...);
-int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
-int pool_sprintf (char *pool_buf, char *fmt, ...);
-int create_pid_file (char *dir, char *progname, int port, char *errmsg);
-int delete_pid_file (char *dir, char *progname, int port);
+void *brealloc (void *buf, size_t size);
+void *bcalloc (size_t size1, size_t size2);
+int bsnprintf (char *str, size_t size, const char *format, ...);
+int bvsnprintf (char *str, size_t size, const char *format, va_list ap);
+int pool_sprintf (char *pool_buf, char *fmt, ...);
+void create_pid_file (char *dir, char *progname, int port);
+int delete_pid_file (char *dir, char *progname, int port);
/* bnet.c */
-int32_t bnet_recv __PROTO((BSOCK *bsock));
-int bnet_send __PROTO((BSOCK *bsock));
-int bnet_fsend (BSOCK *bs, char *fmt, ...);
-int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
-int bnet_sig (BSOCK *bs, int sig);
-BSOCK * bnet_connect (void *jcr, int retry_interval,
- int max_retry_time, char *name, char *host, char *service,
- int port, int verbose);
-int bnet_wait_data (BSOCK *bsock, int sec);
-void bnet_close __PROTO((BSOCK *bsock));
-BSOCK * init_bsock __PROTO((int sockfd, char *who, char *ip, int port));
-BSOCK * dup_bsock __PROTO((BSOCK *bsock));
-void term_bsock __PROTO((BSOCK *bsock));
-char * bnet_strerror __PROTO((BSOCK *bsock));
-char * bnet_sig_to_ascii __PROTO((BSOCK *bsock));
-int bnet_wait_data __PROTO((BSOCK *bsock, int sec));
+int32_t bnet_recv __PROTO((BSOCK *bsock));
+int bnet_send __PROTO((BSOCK *bsock));
+int bnet_fsend (BSOCK *bs, char *fmt, ...);
+int bnet_set_buffer_size (BSOCK *bs, uint32_t size, int rw);
+int bnet_sig (BSOCK *bs, int sig);
+BSOCK * bnet_connect (void *jcr, int retry_interval,
+ int max_retry_time, char *name, char *host, char *service,
+ int port, int verbose);
+int bnet_wait_data (BSOCK *bsock, int sec);
+void bnet_close __PROTO((BSOCK *bsock));
+BSOCK * init_bsock __PROTO((int sockfd, char *who, char *ip, int port));
+BSOCK * dup_bsock __PROTO((BSOCK *bsock));
+void term_bsock __PROTO((BSOCK *bsock));
+char * bnet_strerror __PROTO((BSOCK *bsock));
+char * bnet_sig_to_ascii __PROTO((BSOCK *bsock));
+int bnet_wait_data __PROTO((BSOCK *bsock, int sec));
/* cram-md5.c */
int cram_md5_get_auth(BSOCK *bs, char *password);
int cram_md5_auth(BSOCK *bs, char *password);
void hmac_md5(uint8_t* text, int text_len, uint8_t* key,
- int key_len, uint8_t *hmac);
+ int key_len, uint8_t *hmac);
/* create_file.c */
int create_file(void *jcr, char *fname, char *ofile, char *lname,
- int type, struct stat *statp, int *ofd);
+ int type, struct stat *statp, int *ofd);
int set_statp(void *jcr, char *fname, char *ofile, char *lname, int type,
- struct stat *statp);
+ struct stat *statp);
/* crc32.c */
uint32_t bcrc32(uint8_t *buf, int len);
/* daemon.c */
-void daemon_start __PROTO(());
+void daemon_start __PROTO(());
/* lex.c */
-LEX * lex_close_file __PROTO((LEX *lf));
-LEX * lex_open_file __PROTO((LEX *lf, char *fname));
-int lex_get_char __PROTO((LEX *lf));
-void lex_unget_char __PROTO((LEX *lf));
-char * lex_tok_to_str __PROTO((int token));
-int lex_get_token __PROTO((LEX *lf));
+LEX * lex_close_file __PROTO((LEX *lf));
+LEX * lex_open_file __PROTO((LEX *lf, char *fname));
+int lex_get_char __PROTO((LEX *lf));
+void lex_unget_char __PROTO((LEX *lf));
+char * lex_tok_to_str __PROTO((int token));
+int lex_get_token __PROTO((LEX *lf));
/* makepath.c */
int make_path(
- void *jcr,
- const char *argpath,
- int mode,
- int parent_mode,
- uid_t owner,
- gid_t group,
- int preserve_existing,
- char *verbose_fmt_string);
+ void *jcr,
+ const char *argpath,
+ int mode,
+ int parent_mode,
+ uid_t owner,
+ gid_t group,
+ int preserve_existing,
+ char *verbose_fmt_string);
/* message.c */
-void my_name_is __PROTO((int argc, char *argv[], char *name));
-void init_msg __PROTO((void *jcr, MSGS *msg));
-void term_msg __PROTO((void));
-void close_msg __PROTO((void *jcr));
-void add_msg_dest __PROTO((MSGS *msg, int dest, int type, char *where, char *dest_code));
-void rem_msg_dest __PROTO((MSGS *msg, int dest, int type, char *where));
-void Jmsg (void *jcr, int type, int level, char *fmt, ...);
-void dispatch_message __PROTO((void *jcr, int type, int level, char *buf));
-void init_console_msg __PROTO((char *wd));
+void my_name_is __PROTO((int argc, char *argv[], char *name));
+void init_msg __PROTO((void *jcr, MSGS *msg));
+void term_msg __PROTO((void));
+void close_msg __PROTO((void *jcr));
+void add_msg_dest __PROTO((MSGS *msg, int dest, int type, char *where, char *dest_code));
+void rem_msg_dest __PROTO((MSGS *msg, int dest, int type, char *where));
+void Jmsg (void *jcr, int type, int level, char *fmt, ...);
+void dispatch_message __PROTO((void *jcr, int type, int level, char *buf));
+void init_console_msg __PROTO((char *wd));
+void free_msgs_res(MSGS *msgs);
/* bnet_server.c */
-void bnet_thread_server(int port, int max_clients, workq_t *client_wq,
- void handle_client_request(void *bsock));
-void bnet_server __PROTO((int port, void handle_client_request(BSOCK *bsock)));
-int net_connect __PROTO((int port));
-BSOCK * bnet_bind __PROTO((int port));
-BSOCK * bnet_accept __PROTO((BSOCK *bsock, char *who));
+void bnet_thread_server(int port, int max_clients, workq_t *client_wq,
+ void handle_client_request(void *bsock));
+void bnet_server __PROTO((int port, void handle_client_request(BSOCK *bsock)));
+int net_connect __PROTO((int port));
+BSOCK * bnet_bind __PROTO((int port));
+BSOCK * bnet_accept __PROTO((BSOCK *bsock, char *who));
/* signal.c */
-void init_signals __PROTO((void terminate(int sig)));
-void init_stack_dump (void);
+void init_signals __PROTO((void terminate(int sig)));
+void init_stack_dump (void);
/* util.c */
-void lcase __PROTO((char *str));
-void bash_spaces __PROTO((char *str));
-void unbash_spaces __PROTO((char *str));
-void strip_trailing_junk __PROTO((char *str));
-void strip_trailing_slashes __PROTO((char *dir));
-int skip_spaces __PROTO((char **msg));
-int skip_nonspaces __PROTO((char **msg));
-int fstrsch __PROTO((char *a, char *b));
-char * encode_time __PROTO((time_t time, char *buf));
-char * encode_mode __PROTO((mode_t mode, char *buf));
-char * edit_uint64_with_commas __PROTO((uint64_t val, char *buf));
-char * add_commas __PROTO((char *val, char *buf));
-char * edit_uint64 (uint64_t val, char *buf);
-int do_shell_expansion (char *name);
-int is_a_number (const char *num);
-int string_to_btime(char *str, btime_t *value);
-char *edit_btime(btime_t val, char *buf);
+void lcase __PROTO((char *str));
+void bash_spaces __PROTO((char *str));
+void unbash_spaces __PROTO((char *str));
+void strip_trailing_junk __PROTO((char *str));
+void strip_trailing_slashes __PROTO((char *dir));
+int skip_spaces __PROTO((char **msg));
+int skip_nonspaces __PROTO((char **msg));
+int fstrsch __PROTO((char *a, char *b));
+char * encode_time __PROTO((time_t time, char *buf));
+char * encode_mode __PROTO((mode_t mode, char *buf));
+char * edit_uint64_with_commas __PROTO((uint64_t val, char *buf));
+char * add_commas __PROTO((char *val, char *buf));
+char * edit_uint64 (uint64_t val, char *buf);
+int do_shell_expansion (char *name);
+int is_a_number (const char *num);
+int string_to_btime(char *str, btime_t *value);
+char *edit_btime(btime_t val, char *buf);
/*
- *void print_ls_output __PROTO((char *fname, char *lname, int type, struct stat *statp));
+ *void print_ls_output __PROTO((char *fname, char *lname, int type, struct stat *statp));
*/
/* watchdog.c */
if (already_dead) {
_exit(1);
}
- already_dead = TRUE;
+ already_dead = sig;
if (sig == SIGTERM) {
Emsg1(M_TERM, -1, "Shutting down Bacula service: %s ...\n", my_name);
} else {
static char btpath[400];
pid_t pid;
- Dmsg1(000, "Kaboom! Got signal %d. Attempting traceback\n", sig);
+ fprintf(stderr, "Kaboom! Got signal %d. Attempting traceback.\n", sig);
if (strlen(exepath) + 12 > (int)sizeof(btpath)) {
strcpy(btpath, "btraceback");
} else {
Dmsg1(300, "exepath=%s\n", exepath);
switch (pid = fork()) {
case -1: /* error */
+ fprintf(stderr, "Fork error: ERR=%s\n", strerror(errno));
break;
case 0: /* child */
argv[0] = btpath; /* path to btraceback */
if (pid > 0) {
Dmsg0(500, "Doing waitpid\n");
waitpid(pid, NULL, 0); /* wait for child to produce dump */
+ fprintf(stderr, "Traceback complete, attempting cleanup ...\n");
Dmsg0(500, "Done waitpid\n");
exit_handler(1); /* clean up if possible */
Dmsg0(500, "Done exit_handler\n");
Dmsg0(500, "Doing sleep\n");
sleep(30);
}
+ fprintf(stderr, "It looks like the traceback worked ...\n");
}
#endif
#undef malloc
#undef free
-#define FULL_SM_CHECK 1
-
/*LINTLIBRARY*/
buf[nbytes - 1] = (((long) buf) & 0xFF) ^ 0xC5;
buf += HEAD_SIZE; /* Increment to user data start */
}
-#ifdef FULL_SM_CHECK
sm_check(fname, lineno, True);
-#endif
Dmsg4(1150, "smalloc %d at %x from %s:%d\n", nbytes, buf, fname, lineno);
return (void *) buf;
}
char *cp = (char *) fp;
struct b_queue *qp;
-#ifdef FULL_SM_CHECK
sm_check(__FILE__, __LINE__, True);
-#endif
if (cp == NULL) {
Emsg2(M_ABORT, 0, "Attempt to free NULL called from %s:%d\n", file, line);
}
void *buf;
char *cp = (char *) ptr;
-#ifdef FULL_SM_CHECK
sm_check(fname, lineno, True);
-#endif
if (size <= 0) {
e_msg(fname, lineno, M_ABORT, 0, "sm_realloc size: %d\n", size);
}
sm_free(__FILE__, __LINE__, ptr);
}
Dmsg4(150, "sm_realloc %d at %x from %s:%d\n", size, buf, fname, lineno);
-#ifdef FULL_SM_CHECK
sm_check(fname, lineno, True);
-#endif
return buf;
}
}
/* SM_DUMP -- Print orphaned buffers (and dump them if BUFDUMP is
- True). */
-
+ * True).
+ * N.B. DO NOT USE any Bacula print routines (Dmsg, Jmsg, Emsg, ...)
+ * as they have all been shut down at this point.
+ */
void sm_dump(Boolean bufdump)
{
struct abufhead *ap = (struct abufhead *) abqueue.qnext;
}
}
+#undef sm_check
/* SM_CHECK -- Check the buffers and dump if any damage exists. */
void sm_check(char *fname, int lineno, Boolean bufdump)
{
}
}
+#undef sm_check_rtn
/* SM_CHECK_RTN -- Check the buffers and return 1 if OK otherwise 0 */
int sm_check_rtn(char *fname, int lineno, Boolean bufdump)
{
*
* Kern E. Sibbald
*
+ * $Id$
+ *
*/
/*
Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
int main (int argc, char *argv[])
{
- int ch, i;
+ int ch;
FILE *fd;
char line[1000];
my_name_is(argc, argv, "bextract");
+ init_msg(NULL, NULL); /* setup message handler */
memset(ff, 0, sizeof(FF_PKT));
init_include_exclude_files(ff);
usage();
}
- /*
- * Ensure that every message is always printed
- */
- for (i=1; i<=M_MAX; i++) {
- add_msg_dest(NULL, MD_STDOUT, i, NULL, NULL);
- }
-
jcr = new_jcr(sizeof(JCR), my_free_jcr);
jcr->VolSessionId = 1;
jcr->VolSessionTime = (uint32_t)time(NULL);
Dmsg1(199, "free_block buffer %x\n", block->buf);
free_memory(block->buf);
Dmsg1(199, "free_block block %x\n", block);
- free_memory(block);
+ free_memory((POOLMEM *)block);
}
/* Empty the block -- for writing */
*
* Dumb program to do an "ls" of a Bacula 1.0 mortal file.
*
+ * $Id$
*/
/*
Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
char line[1000];
my_name_is(argc, argv, "bls");
+ init_msg(NULL, NULL); /* initialize message handler */
memset(&ff, 0, sizeof(ff));
init_include_exclude_files(&ff);
add_fname_to_include_list(&ff, 0, "/");
}
- /*
- * Ensure that every message is always printed
- */
- for (i=1; i<=M_MAX; i++) {
- add_msg_dest(NULL, MD_STDOUT, i, NULL, NULL);
- }
-
/* Try default device */
if (default_tape) {
do_ls(DEFAULT_TAPE_DRIVE);
return 0;
}
-
for (i=0; i < argc; i++) {
if (list_blocks) {
do_blocks(argv[i]);
*
* Kern E. Sibbald, December 2001
*
+ *
+ * $Id$
*/
/*
Copyright (C) 2001, 2002 Kern Sibbald and John Walker
int main (int argc, char *argv[])
{
- int ch, i;
+ int ch;
my_name_is(argc, argv, "bscan");
+ init_msg(NULL, NULL);
while ((ch = getopt(argc, argv, "d:?")) != -1) {
usage();
}
- /*
- * Ensure that every message is always printed
- */
- for (i=1; i<=M_MAX; i++) {
- add_msg_dest(NULL, MD_STDOUT, i, NULL, NULL);
- }
-
jcr = new_jcr(sizeof(JCR), my_free_jcr);
jcr->VolSessionId = 1;
jcr->VolSessionTime = (uint32_t)time(NULL);
* Note, this program reads stored.conf, and will only
* talk to devices that are configured.
*
+ * $Id$
+ *
*/
/*
Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
*/
int main(int argc, char *argv[])
{
- int ch, i;
+ int ch;
/* Sanity checks */
if (TAPE_BSIZE % DEV_BSIZE != 0 || TAPE_BSIZE / DEV_BSIZE == 0) {
my_name_is(argc, argv, "btape");
+ init_msg(NULL, NULL);
if (signals) {
init_signals(terminate_btape);
parse_config(configfile);
- /*
- * Ensure that every message is always printed
- */
- for (i=1; i<=M_MAX; i++) {
- add_msg_dest(NULL, MD_STDOUT, i, NULL, NULL);
- }
-
/* See if we can open a device */
if (argc) {
dev->dev_name = NULL;
}
if (dev->errmsg) {
- free_memory(dev->errmsg);
+ free_pool_memory(dev->errmsg);
dev->errmsg = NULL;
}
pthread_mutex_destroy(&dev->mutex);
pthread_cond_destroy(&dev->wait);
pthread_cond_destroy(&dev->wait_next_vol);
if (dev->state & ST_MALLOC) {
- free_memory(dev);
+ free_pool_memory((POOLMEM *)dev);
}
}
Dmsg0(150, "Enter free_record.\n");
free_pool_memory(rec->data);
Dmsg0(150, "Data buf is freed.\n");
- free_pool_memory(rec);
+ free_pool_memory((POOLMEM *)rec);
Dmsg0(150, "Leave free_record.\n");
}
init_stack_dump();
my_name_is(argc, argv, "stored");
+ init_msg(NULL, NULL);
daemon_start_time = time(NULL);
memset(&last_job, 0, sizeof(last_job));
configfile = bstrdup(CONFIG_FILE);
}
- init_msg(NULL, NULL);
parse_config(configfile);
check_config();
init_stack_dump(); /* pick up new pid */
}
+ create_pid_file(me->pid_directory, "bacula-sd", me->SDport);
+
/* ****FIXME**** clean this up */
/* Create and attach to shared memory. This is a
* hold over from the days of child processes.
Emsg1(M_ABORT, 0, _("No Device resource defined in %s. Cannot continue.\n"),
configfile);
}
+ if (!me->messages) {
+ me->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
+ if (!me->messages) {
+ Emsg1(M_ABORT, 0, _("No Messages resource defined in %s. Cannot continue.\n"),
+ configfile);
+ }
+ }
+ close_msg(NULL); /* close temp message handler */
+ init_msg(NULL, me->messages); /* open daemon message handler */
UnlockRes();
}
in_here = TRUE;
+ delete_pid_file(me->pid_directory, "bacula-sd", me->SDport);
stop_watchdog();
Dmsg0(200, "In terminate_stored()\n");
free(configfile);
free_config_resources();
- if (debug_level > 10)
+ if (debug_level > 10) {
print_memory_pool_stats();
+ }
+ term_msg();
close_memory_pool();
- if (shm)
- free(shm);
- term_msg();
+ if (shm) {
+ free(shm);
+ }
sm_dump(False); /* dump orphaned buffers */
exit(1);
{"name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0},
{"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
{"address", store_str, ITEM(res_store.address), 0, ITEM_REQUIRED, 0},
+ {"messages", store_res, ITEM(res_store.messages), 0, R_MSGS, 0},
{"sdport", store_int, ITEM(res_store.SDport), 0, ITEM_REQUIRED, 0},
{"sddport", store_int, ITEM(res_store.SDDport), 0, 0, 0}, /* depricated */
{"workingdirectory", store_dir, ITEM(res_store.working_directory), 0, ITEM_REQUIRED, 0},
break;
case R_MSGS:
sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
+ if (res->res_msgs.mail_cmd)
+ sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd);
+ if (res->res_msgs.operator_cmd)
+ sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd);
break;
default:
sendit(sock, _("Warning: unknown resource type %d\n"), type);
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;
}
/* Common stuff again -- free the resource, recurse to next one */
- free(res);
+ if (res) {
+ free(res);
+ }
resources[rindex].res_head = (RES *)nres;
- if (nres)
+ if (nres) {
free_resource(type);
+ }
}
/* Save the new resource by chaining it into the head list for
*/
if (pass == 2) {
switch (type) {
+ /* Resources not containing a resource */
case R_DIRECTOR:
- case R_STORAGE:
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:
printf("Unknown resource type %d\n", type);
error = 1;
break;
}
+
+
if (res_all.res_dir.hdr.name) {
free(res_all.res_dir.hdr.name);
res_all.res_dir.hdr.name = NULL;
*/
-#define R_FIRST 3001
+#define R_FIRST 3001
-#define R_DIRECTOR 3001
-#define R_STORAGE 3002
-#define R_DEVICE 3003
-#define R_MSGS 3004
+#define R_DIRECTOR 3001
+#define R_STORAGE 3002
+#define R_DEVICE 3003
+#define R_MSGS 3004
-#define R_LAST R_MSGS
+#define R_LAST R_MSGS
-#define R_NAME 3020
-#define R_ADDRESS 3021
-#define R_PASSWORD 3022
-#define R_TYPE 3023
-#define R_BACKUP 3024
+#define R_NAME 3020
+#define R_ADDRESS 3021
+#define R_PASSWORD 3022
+#define R_TYPE 3023
+#define R_BACKUP 3024
#define STORAGE_DAEMON 1
/* Definition of the contents of each Resource */
struct s_res_dir {
- RES hdr;
+ RES hdr;
- char *password; /* Director password */
- char *address; /* Director IP address or zero */
+ char *password; /* Director password */
+ char *address; /* Director IP address or zero */
};
typedef struct s_res_dir DIRRES;
/* Storage daemon "global" definitions */
struct s_res_store {
- RES hdr;
+ RES hdr;
char *address;
- int SDport; /* Where we listen for Directors */
+ int SDport; /* Where we listen for Directors */
int SDDport; /* "Data" port where we listen for File daemons */
- char *working_directory; /* working directory for checkpoints */
+ char *working_directory; /* working directory for checkpoints */
char *pid_directory;
char *subsys_directory;
uint32_t max_concurrent_jobs; /* maximum concurrent jobs to run */
+ struct s_res_msgs *messages; /* Daemon message handler */
};
typedef struct s_res_store STORES;
/* Device specific definitions */
struct s_res_dev {
- RES hdr;
+ RES hdr;
char *media_type;
char *device_name;
- int cap_bits;
- uint32_t max_rewind_wait; /* maximum secs to wait for rewind */
- uint32_t min_block_size; /* min block size */
- uint32_t max_block_size; /* max block size */
- uint32_t max_volume_jobs; /* max jobs to put on one volume */
- int64_t max_volume_files; /* max files to put on one volume */
- int64_t max_volume_size; /* max bytes to put on one volume */
- int64_t max_file_size; /* max file size in bytes */
- int64_t volume_capacity; /* advisory capacity */
+ int cap_bits;
+ uint32_t max_rewind_wait; /* maximum secs to wait for rewind */
+ uint32_t min_block_size; /* min block size */
+ uint32_t max_block_size; /* max block size */
+ uint32_t max_volume_jobs; /* max jobs to put on one volume */
+ int64_t max_volume_files; /* max files to put on one volume */
+ int64_t max_volume_size; /* max bytes to put on one volume */
+ int64_t max_file_size; /* max file size in bytes */
+ int64_t volume_capacity; /* advisory capacity */
DEVICE *dev;
};
typedef struct s_res_dev DEVRES;
union u_res {
- struct s_res_dir res_dir;
- struct s_res_store res_store;
- struct s_res_dev res_dev;
- struct s_res_msgs res_msgs;
+ struct s_res_dir res_dir;
+ struct s_res_store res_store;
+ struct s_res_dev res_dev;
+ struct s_res_msgs res_msgs;
RES hdr;
};
typedef union u_res URES;
/* */
-#define VERSION "1.19"
+#define VERSION "1.20"
#define VSTRING "1"
-#define DATE "10 May 2002"
-#define LSMDATE "10May02"
+#define DATE "16 May 2002"
+#define LSMDATE "16May02"
/* Debug flags */
#define DEBUG 1