-2003-xx-xx Version 1.31 Beta xxJun03
+2003-xx-xx Version 1.31 Beta 20Jun03
+- Change find_next_volume() for oldest to use LastWritten instead of
+ FirstWritten -- also add Append to volumes slected.
+- Do normal recycling before checking for RecycleOldestVolume.
+- Implemented block rejection on read. This should make restores run
+ much faster. Next release will have block positioning -- even faster.
- Very preliminary support for Gnome-2.0. Text does not yet work.
- Correct buffer corruption in find_one.c with long directory names (Win32).
- Make setting owner on directories M_ERROR rather than M_WARNING.
#
SVRSRCS = dird.c admin.c authenticate.c \
autoprune.c backup.c bsr.c \
- catreq.c dird_conf.c \
+ catreq.c dird_conf.c expand.c \
fd_cmds.c getmsg.c inc_conf.c job.c \
mountreq.c msgchan.c newvol.c \
recycle.c restore.c run_conf.c \
ua_status.c ua_tree.c verify.c
SVROBJS = dird.o admin.o authenticate.o \
autoprune.o backup.o bsr.o \
- catreq.o dird_conf.o \
+ catreq.o dird_conf.o expand.o \
fd_cmds.o getmsg.o inc_conf.o job.o \
mountreq.o msgchan.o newvol.o \
recycle.o restore.o run_conf.o \
/* Forward referenced functions */
-/*
- * The pruning code was written to be referenced by the
- * User Agent (i.e. the console), so to properly access it and
- * to ensure that the Job gets the proper output, we create
- * a User Agent context. This is a sort of mini-kludge.
- */
-void create_ua_context(JCR *jcr, UAContext *ua)
-{
- memset(ua, 0, sizeof(UAContext));
- ua->jcr = jcr;
- ua->db = jcr->db;
- ua->cmd = get_pool_memory(PM_FNAME);
- ua->args = get_pool_memory(PM_FNAME);
- ua->verbose = 1;
-}
-
-void free_ua_context(UAContext *ua)
-{
- if (ua->cmd) {
- free_pool_memory(ua->cmd);
- }
- if (ua->args) {
- free_pool_memory(ua->args);
- }
- if (ua->prompt) {
- free(ua->prompt);
- ua->prompt = NULL;
- ua->max_prompts = 0;
- }
-}
/*
* Auto Prune Jobs and Files. This is called at the end of every
*/
int do_autoprune(JCR *jcr)
{
- UAContext ua;
+ UAContext *ua;
CLIENT *client;
- int pruned;
+ bool pruned;
if (!jcr->client) { /* temp -- remove me */
return 1;
}
- create_ua_context(jcr, &ua);
+ ua = new_ua_context(jcr);
client = jcr->client;
if (jcr->job->PruneJobs || jcr->client->AutoPrune) {
Jmsg(jcr, M_INFO, 0, _("Begin pruning Jobs.\n"));
- prune_jobs(&ua, client, jcr->JobType);
- pruned = TRUE;
+ prune_jobs(ua, client, jcr->JobType);
+ pruned = true;
} else {
- pruned = FALSE;
+ pruned = false;
}
if (jcr->job->PruneFiles || jcr->client->AutoPrune) {
Jmsg(jcr, M_INFO, 0, _("Begin pruning Files.\n"));
- prune_files(&ua, client);
- pruned = TRUE;
+ prune_files(ua, client);
+ pruned = true;
}
if (pruned) {
Jmsg(jcr, M_INFO, 0, _("End auto prune.\n\n"));
}
- free_ua_context(&ua);
+ free_ua_context(ua);
return 1;
}
int num_ids = 0;
MEDIA_DBR mr;
POOL_DBR pr;
- UAContext ua;
+ UAContext *ua;
if (!jcr->job->PruneVolumes && !jcr->pool->AutoPrune) {
Dmsg0(100, "AutoPrune not set in Pool.\n");
}
memset(&mr, 0, sizeof(mr));
memset(&pr, 0, sizeof(pr));
- create_ua_context(jcr, &ua);
+ ua = new_ua_context(jcr);
db_lock(jcr->db);
strcmp(mr.VolStatus, "Append") == 0 ||
strcmp(mr.VolStatus, "Used") == 0) {
Dmsg1(200, "Prune Volume %s\n", mr.VolumeName);
- stat += prune_volume(&ua, &pr, &mr);
+ stat += prune_volume(ua, &pr, &mr);
Dmsg1(200, "Num pruned = %d\n", stat);
}
}
bail_out:
db_unlock(jcr->db);
- free_ua_context(&ua);
+ free_ua_context(ua);
if (ids) {
free(ids);
}
ok = db_find_next_volume(jcr, jcr->db, -1, &mr);
Dmsg1(400, "Find oldest=%d\n", ok);
if (ok) {
- UAContext ua;
+ UAContext *ua;
Dmsg0(400, "Try purge.\n");
/* Try to purge oldest volume */
- create_ua_context(jcr, &ua);
+ ua = new_ua_context(jcr);
Jmsg(jcr, M_INFO, 0, _("Purging oldest volume \"%s\"\n"), mr.VolumeName);
- ok = purge_jobs_from_volume(&ua, &mr);
- free_ua_context(&ua);
+ ok = purge_jobs_from_volume(ua, &mr);
+ free_ua_context(ua);
if (ok) {
ok = recycle_oldest_purged_volume(jcr, &mr);
Dmsg1(400, "Recycle after recycle oldest=%d\n", ok);
return 1;
}
-static int date_item(JCR *jcr, int code,
- const char **val_ptr, int *val_len, int *val_size)
-{
- struct tm tm;
- time_t now = time(NULL);
- localtime_r(&now, &tm);
- int val = 0;
- char buf[10];
-
- switch (code) {
- case 1: /* year */
- val = tm.tm_year + 1900;
- break;
- case 2: /* month */
- val = tm.tm_mon + 1;
- break;
- case 3: /* day */
- val = tm.tm_mday;
- break;
- case 4: /* hour */
- val = tm.tm_hour;
- break;
- case 5: /* minute */
- val = tm.tm_min;
- break;
- case 6: /* second */
- val = tm.tm_sec;
- break;
- case 7: /* Week day */
- val = tm.tm_wday;
- break;
- }
- bsnprintf(buf, sizeof(buf), "%d", val);
- *val_ptr = bstrdup(buf);
- *val_len = strlen(buf);
- *val_size = *val_len;
- return 1;
-}
-
-static int job_item(JCR *jcr, int code,
- const char **val_ptr, int *val_len, int *val_size)
-{
- char *str = " ";
- char buf[20];
-
- switch (code) {
- case 1: /* Job */
- str = jcr->Job;
- break;
- case 2: /* Director's name */
- str = my_name;
- break;
- case 3: /* level */
- str = job_level_to_str(jcr->JobLevel);
- break;
- case 4: /* type */
- str = job_type_to_str(jcr->JobType);
- break;
- case 5: /* JobId */
- bsnprintf(buf, sizeof(buf), "%d", jcr->JobId);
- str = buf;
- break;
- case 6: /* Client */
- str = jcr->client_name;
- if (!str) {
- str = " ";
- }
- break;
- case 7: /* NumVols */
- bsnprintf(buf, sizeof(buf), "%d", jcr->NumVols);
- str = buf;
- break;
- case 8: /* Pool */
- str = jcr->client->hdr.name;
- break;
- }
- *val_ptr = bstrdup(str);
- *val_len = strlen(str);
- *val_size = *val_len;
- return 1;
-}
-
-
-struct s_built_in_vars {char *var_name; int code; int (*func)(JCR *jcr, int code,
- const char **val_ptr, int *val_len, int *val_size);};
-
-static struct s_built_in_vars built_in_vars[] = {
- { N_("Year"), 1, date_item},
- { N_("Month"), 2, date_item},
- { N_("Day"), 3, date_item},
- { N_("Hour"), 4, date_item},
- { N_("Minute"), 5, date_item},
- { N_("Second"), 6, date_item},
- { N_("WeekDay"), 7, date_item},
-
- { N_("Job"), 1, job_item},
- { N_("Dir"), 2, job_item},
- { N_("Level"), 3, job_item},
- { N_("Type"), 4, job_item},
- { N_("JobId"), 5, job_item},
- { N_("Client"), 6, job_item},
- { N_("NumVols"), 7, job_item},
- { N_("Pool"), 8, job_item},
-
- { NULL, 0, NULL}
-};
-
-
-static var_rc_t lookup_built_in_var(var_t *ctx, void *my_ctx,
- const char *var_ptr, int var_len, int var_index,
- const char **val_ptr, int *val_len, int *val_size)
-{
- JCR *jcr = (JCR *)my_ctx;
- int stat;
-
- for (int i=0; _(built_in_vars[i].var_name); i++) {
- if (strncmp(_(built_in_vars[i].var_name), var_ptr, var_len) == 0) {
- stat = (*built_in_vars[i].func)(jcr, built_in_vars[i].code,
- val_ptr, val_len, val_size);
- if (stat) {
- return VAR_OK;
- }
- break;
- }
- }
- return VAR_ERR_UNDEFINED_VARIABLE;
-}
-
-
-/*
- * Search counter variables
- */
-static var_rc_t lookup_counter_var(var_t *ctx, void *my_ctx,
- const char *var_ptr, int var_len, int var_inc, int var_index,
- const char **val_ptr, int *val_len, int *val_size)
-{
- char buf[MAXSTRING];
- var_rc_t stat = VAR_ERR_UNDEFINED_VARIABLE;
-
- if (var_len > (int)sizeof(buf) - 1) {
- return VAR_ERR_OUT_OF_MEMORY;
- }
- memcpy(buf, var_ptr, var_len);
- buf[var_len] = 0;
- LockRes();
- for (COUNTER *counter=NULL; (counter = (COUNTER *)GetNextRes(R_COUNTER, (RES *)counter)); ) {
- if (strcmp(counter->hdr.name, buf) == 0) {
- bsnprintf(buf, sizeof(buf), "%d", counter->CurrentValue);
- *val_ptr = bstrdup(buf);
- *val_len = strlen(buf);
- *val_size = *val_len;
- if (var_inc) {
- COUNTER_DBR cr;
- JCR *jcr = (JCR *)my_ctx;
- memset(&cr, 0, sizeof(cr));
- bstrncpy(cr.Counter, counter->hdr.name, sizeof(cr.Counter));
- cr.MinValue = counter->MinValue;
- cr.MaxValue = counter->MaxValue;
- cr.CurrentValue = ++counter->CurrentValue;
- bstrncpy(cr.WrapCounter, counter->WrapCounter->hdr.name, sizeof(cr.WrapCounter));
- if (!db_update_counter_record(jcr, jcr->db, &cr)) {
- Jmsg(jcr, M_ERROR, 0, _("Count not update counter %s: ERR=%s\n"),
- counter->hdr.name, db_strerror(jcr->db));
- }
- }
- stat = VAR_OK;
- break;
- }
- }
- UnlockRes();
- return stat;
-}
-
-
-/*
- * Called here to look up a variable
- */
-static var_rc_t lookup_var(var_t *ctx, void *my_ctx,
- const char *var_ptr, int var_len, int var_inc, int var_index,
- const char **val_ptr, int *val_len, int *val_size)
-{
- char buf[MAXSTRING], *val, *p, *v;
- var_rc_t stat;
- int count;
-
- if ((stat = lookup_built_in_var(ctx, my_ctx, var_ptr, var_len, var_index,
- val_ptr, val_len, val_size)) == VAR_OK) {
- return VAR_OK;
- }
-
- if ((stat = lookup_counter_var(ctx, my_ctx, var_ptr, var_len, var_inc, var_index,
- val_ptr, val_len, val_size)) == VAR_OK) {
- return VAR_OK;
- }
-
- /* Look in environment */
- if (var_len > (int)sizeof(buf) - 1) {
- return VAR_ERR_OUT_OF_MEMORY;
- }
- memcpy(buf, var_ptr, var_len + 1);
- buf[var_len] = 0;
-// Dmsg1(000, "Var=%s\n", buf);
-
- if ((val = getenv(buf)) == NULL) {
- return VAR_ERR_UNDEFINED_VARIABLE;
- }
- if (var_index == 0) {
- *val_ptr = val;
- *val_len = strlen(val);
- *val_size = 0;
- return VAR_OK;
- }
- /* He wants to index the "array" */
- count = 0;
- /* Find the size of the "array"
- * each element is separated by a |
- */
- for (p = val; *p; p++) {
- if (*p == '|') {
- count++;
- }
- }
- count++;
-// Dmsg3(000, "For %s, reqest index=%d have=%d\n",
-// buf, var_index, count);
- if (var_index < 0 || var_index > count) {
- return VAR_ERR_SUBMATCH_OUT_OF_RANGE;
- }
- /* Now find the particular item (var_index) he wants */
- count = 1;
- for (p=val; *p; ) {
- if (*p == '|') {
- if (count < var_index) {
- val = ++p;
- count++;
- continue;
- }
- break;
- }
- p++;
- }
- if (p-val > (int)sizeof(buf) - 1) {
- return VAR_ERR_OUT_OF_MEMORY;
- }
-// Dmsg2(000, "val=%s len=%d\n", val, p-val);
- /* Make a copy of item, and pass it back */
- v = (char *)malloc(p-val+1);
- memcpy(v, val, p-val);
- v[p-val] = 0;
- *val_ptr = v;
- *val_len = p-val;
- *val_size = p-val;
-// Dmsg1(000, "v=%s\n", v);
- return VAR_OK;
-}
-
-/*
- * Called here to do a special operation on a variable
- * op_ptr points to the special operation code (not EOS terminated)
- * arg_ptr points to argument to special op code
- * val_ptr points to the value string
- * out_ptr points to string to be returned
- */
-static var_rc_t operate_var(var_t *var, void *my_ctx,
- const char *op_ptr, int op_len,
- const char *arg_ptr, int arg_len,
- const char *val_ptr, int val_len,
- char **out_ptr, int *out_len, int *out_size)
-{
- var_rc_t stat = VAR_ERR_UNDEFINED_OPERATION;
- Dmsg0(000, "Enter operate_var\n");
- if (!val_ptr) {
- *out_size = 0;
- return stat;
- }
- if (op_len == 3 && strncmp(op_ptr, "inc", 3) == 0) {
- char buf[MAXSTRING];
- if (val_len > (int)sizeof(buf) - 1) {
- return VAR_ERR_OUT_OF_MEMORY;
- }
- memcpy(buf, arg_ptr, arg_len);
- buf[arg_len] = 0;
- Dmsg1(000, "Arg=%s\n", buf);
- memcpy(buf, val_ptr, val_len);
- buf[val_len] = 0;
- Dmsg1(000, "Val=%s\n", buf);
- LockRes();
- for (COUNTER *counter=NULL; (counter = (COUNTER *)GetNextRes(R_COUNTER, (RES *)counter)); ) {
- if (strcmp(counter->hdr.name, buf) == 0) {
- Dmsg2(000, "counter=%s val=%s\n", counter->hdr.name, buf);
- break;
- }
- }
- UnlockRes();
- return stat;
- }
- *out_size = 0;
- return stat;
-}
-
/*
* Perform full substitution on Label
*/
static int perform_full_name_substitution(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
{
- var_t *var_ctx;
- var_rc_t stat;
- char *inp, *outp;
- int in_len, out_len;
- int rtn_stat = 0;
-
- inp = pr->LabelFormat;
- in_len = strlen(inp);
-
- outp = NULL;
- out_len = 0;
-
+ int stat = 0;
+ POOLMEM *label = get_pool_memory(PM_FNAME);
jcr->NumVols = pr->NumVols;
- /* create context */
- if ((stat = var_create(&var_ctx)) != VAR_OK) {
- Jmsg(jcr, M_ERROR, 0, _("Cannot create var context: ERR=%s\n"), var_strerror(var_ctx, stat));
- goto bail_out;
- }
- /* define callback */
- if ((stat = var_config(var_ctx, VAR_CONFIG_CB_VALUE, lookup_var, (void *)jcr)) != VAR_OK) {
- Jmsg(jcr, M_ERROR, 0, _("Cannot set var callback: ERR=%s\n"), var_strerror(var_ctx, stat));
- goto bail_out;
+ if (variable_expansion(jcr, pr->LabelFormat, &label)) {
+ bstrncpy(mr->VolumeName, label, sizeof(mr->VolumeName));
+ stat = 1;
}
-
-
- /* define special operations */
- if ((stat = var_config(var_ctx, VAR_CONFIG_CB_OPERATION, operate_var, (void *)jcr)) != VAR_OK) {
- Jmsg(jcr, M_ERROR, 0, _("Cannot set var operate: ERR=%s\n"), var_strerror(var_ctx, stat));
- goto bail_out;
- }
-
- /* unescape in place */
- if ((stat = var_unescape(var_ctx, inp, in_len, inp, in_len+1, 0)) != VAR_OK) {
- Jmsg(jcr, M_ERROR, 0, _("Cannot unescape string: ERR=%s\n"), var_strerror(var_ctx, stat));
- goto bail_out;
- }
-
- in_len = strlen(inp);
-
- /* expand variables */
- if ((stat = var_expand(var_ctx, inp, in_len, &outp, &out_len, 1)) != VAR_OK) {
- Jmsg(jcr, M_ERROR, 0, _("Cannot expand LabelFormat \"%s\": ERR=%s\n"),
- inp, var_strerror(var_ctx, stat));
- goto bail_out;
- }
-
- /* unescape once more in place */
- if ((stat = var_unescape(var_ctx, outp, out_len, outp, out_len+1, 1)) != VAR_OK) {
- Jmsg(jcr, M_ERROR, 0, _("Cannot unescape string: ERR=%s\n"), var_strerror(var_ctx, stat));
- goto bail_out;
- }
-
- bstrncpy(mr->VolumeName, outp, sizeof(mr->VolumeName));
-
- rtn_stat = 1;
-
-bail_out:
- /* destroy expansion context */
- if ((stat = var_destroy(var_ctx)) != VAR_OK) {
- Jmsg(jcr, M_ERROR, 0, _("Cannot destroy var context: ERR=%s\n"), var_strerror(var_ctx, stat));
- }
- if (outp) {
- free(outp);
- }
- return rtn_stat;
+ free_pool_memory(label);
+ return stat;
}
/* autoprune.c */
extern int do_autoprune(JCR *jcr);
extern int prune_volumes(JCR *jcr);
-void create_ua_context(JCR *jcr, UAContext *ua);
-void free_ua_context(UAContext *ua);
/* autorecycle.c */
extern int recycle_oldest_purged_volume(JCR *jcr, MEDIA_DBR *mr);
/* dird_conf.c */
extern char *level_to_str(int level);
+/* expand.c */
+int variable_expansion(JCR *jcr, char *inp, POOLMEM **exp);
+
+
/* fd_cmds.c */
extern int connect_to_file_daemon(JCR *jcr, int retry_interval,
- int max_retry_time, int verbose);
+ int max_retry_time, int verbose);
extern int send_include_list(JCR *jcr);
extern int send_exclude_list(JCR *jcr);
extern int send_bootstrap_file(JCR *jcr);
extern int get_attributes_and_put_in_catalog(JCR *jcr);
extern int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId);
extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname,
- char *link, char *attr, int stream);
+ char *link, char *attr, int stream);
/* getmsg.c */
enum e_prtmsg {
/* msgchan.c */
extern int connect_to_storage_daemon(JCR *jcr, int retry_interval,
- int max_retry_time, int verbose);
+ int max_retry_time, int verbose);
extern int start_storage_daemon_job(JCR *jcr);
extern int start_storage_daemon_message_thread(JCR *jcr);
extern int bget_dirmsg(BSOCK *bs);
/* ua_server.c */
void bsendmsg(void *sock, char *fmt, ...);
+UAContext *new_ua_context(JCR *jcr);
+void free_ua_context(UAContext *ua);
/* ua_select.c */
-STORE *select_storage_resource(UAContext *ua);
-JOB *select_job_resource(UAContext *ua);
-JOB *select_restore_job_resource(UAContext *ua);
-CLIENT *select_client_resource(UAContext *ua);
+STORE *select_storage_resource(UAContext *ua);
+JOB *select_job_resource(UAContext *ua);
+JOB *select_restore_job_resource(UAContext *ua);
+CLIENT *select_client_resource(UAContext *ua);
FILESET *select_fileset_resource(UAContext *ua);
-int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
-int select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
-int select_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
-
-void start_prompt(UAContext *ua, char *msg);
-void add_prompt(UAContext *ua, char *prompt);
-int do_prompt(UAContext *ua, char *automsg, char *msg, char *prompt, int max_prompt);
-CAT *get_catalog_resource(UAContext *ua);
+int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+int select_media_dbr(UAContext *ua, MEDIA_DBR *mr);
+int select_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int select_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+
+void start_prompt(UAContext *ua, char *msg);
+void add_prompt(UAContext *ua, char *prompt);
+int do_prompt(UAContext *ua, char *automsg, char *msg, char *prompt, int max_prompt);
+CAT *get_catalog_resource(UAContext *ua);
STORE *get_storage_resource(UAContext *ua, int use_default);
-int get_media_type(UAContext *ua, char *MediaType, int max_media);
-int get_pool_dbr(UAContext *ua, POOL_DBR *pr);
-int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
+int get_media_type(UAContext *ua, char *MediaType, int max_media);
+int get_pool_dbr(UAContext *ua, POOL_DBR *pr);
+int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
POOL *get_pool_resource(UAContext *ua);
POOL *select_pool_resource(UAContext *ua);
CLIENT *get_client_resource(UAContext *ua);
-int get_job_dbr(UAContext *ua, JOB_DBR *jr);
+int get_job_dbr(UAContext *ua, JOB_DBR *jr);
int find_arg_keyword(UAContext *ua, char **list);
int find_arg(UAContext *ua, char *keyword);
/* Forward referenced functions */
static int add_cmd(UAContext *ua, char *cmd), createcmd(UAContext *ua, char *cmd), cancelcmd(UAContext *ua, char *cmd);
static int setdebug_cmd(UAContext *ua, char *cmd);
+static int var_cmd(UAContext *ua, char *cmd);
+static int estimate_cmd(UAContext *ua, char *cmd);
static int help_cmd(UAContext *ua, char *cmd);
static int delete_cmd(UAContext *ua, char *cmd);
static int use_cmd(UAContext *ua, char *cmd), unmount_cmd(UAContext *ua, char *cmd);
{ N_("purge"), purgecmd, _("purge records from catalog")},
{ N_("run"), runcmd, _("run <job-name>")},
{ N_("setdebug"), setdebug_cmd, _("sets debug level")},
+ { N_("estimate"), estimate_cmd, _("performs FileSet estimate debug=1 give full listing")},
+ { N_("var"), var_cmd, _("does variable expansion")},
{ N_("show"), show_cmd, _("show (resource records) [jobs | pools | ... | all]")},
{ N_("sqlquery"), sqlquerycmd, _("use SQL to query catalog")},
{ N_("status"), statuscmd, _("status [storage | client]=<name>")},
return 1;
}
+static int var_cmd(UAContext *ua, char *cmd)
+{
+ POOLMEM *var = get_pool_memory(PM_FNAME);
+ for (int i=1; i<ua->argc; i++) {
+ if (ua->argk[i] && variable_expansion(ua->jcr, ua->argk[i], &var)) {
+ bsendmsg(ua, "%s\n", var);
+ }
+ }
+ free_pool_memory(var);
+ return 1;
+}
+
+static int estimate_cmd(UAContext *ua, char *cmd)
+{
+ bsendmsg(ua, "Not yet implemented\n");
+ return 1;
+}
+
+
/*
* print time
*/
return NULL;
}
+/*
+ * Create a Job Control Record for a console "job"
+ * filling in all the appropriate fields.
+ */
+static JCR *create_console_jcr()
+{
+ JCR *jcr;
+ jcr = new_jcr(sizeof(JCR), dird_free_jcr);
+ jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */
+ create_unique_job_name(jcr, "*Console*");
+ jcr->sched_time = jcr->start_time;
+ jcr->JobType = JT_CONSOLE;
+ jcr->JobLevel = L_FULL;
+ jcr->JobStatus = JS_Running;
+ /* None of these are really defined for the Console, so we
+ * simply take the first of each one. This ensures that there
+ * will be no null pointer references.
+ */
+ LockRes();
+ jcr->job = (JOB *)GetNextRes(R_JOB, NULL);
+ jcr->messages = (MSGS *)GetNextRes(R_MSGS, NULL);
+ jcr->client = (CLIENT *)GetNextRes(R_CLIENT, NULL);
+ jcr->pool = (POOL *)GetNextRes(R_POOL, NULL);
+ jcr->catalog = (CAT *)GetNextRes(R_CATALOG, NULL);
+ jcr->store = (STORE *)GetNextRes(R_STORAGE, NULL);
+ jcr->fileset = (FILESET *)GetNextRes(R_FILESET, NULL);
+ UnlockRes();
+ return jcr;
+}
+
/*
* Handle Director User Agent commands
*
static void *handle_UA_client_request(void *arg)
{
int stat;
- UAContext ua;
- BSOCK *UA_sock = (BSOCK *) arg;
+ UAContext *ua;
+ JCR *jcr;
+ BSOCK *UA_sock = (BSOCK *)arg;
pthread_detach(pthread_self());
- memset(&ua, 0, sizeof(ua));
- ua.automount = TRUE;
- ua.verbose = 1;
- ua.jcr = new_jcr(sizeof(JCR), dird_free_jcr);
- ua.jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */
- ua.UA_sock = UA_sock;
- ua.cmd = get_pool_memory(PM_FNAME);
- ua.args = get_pool_memory(PM_FNAME);
-
- create_unique_job_name(ua.jcr, "*Console*");
- ua.jcr->sched_time = ua.jcr->start_time;
- ua.jcr->JobType = JT_CONSOLE;
-
- bnet_recv(ua.UA_sock); /* Get first message */
- if (!authenticate_user_agent(ua.UA_sock)) {
+ jcr = create_console_jcr();
+
+ ua = new_ua_context(jcr);
+ ua->UA_sock = UA_sock;
+
+ bnet_recv(ua->UA_sock); /* Get first message */
+ if (!authenticate_user_agent(ua->UA_sock)) {
goto getout;
}
- while (!ua.quit) {
- stat = bnet_recv(ua.UA_sock);
+ while (!ua->quit) {
+ stat = bnet_recv(ua->UA_sock);
if (stat >= 0) {
- ua.cmd = check_pool_memory_size(ua.cmd, ua.UA_sock->msglen+1);
- bstrncpy(ua.cmd, ua.UA_sock->msg, ua.UA_sock->msglen+1);
- parse_ua_args(&ua);
- if (ua.argc > 0 && ua.argk[0][0] == '.') {
- do_a_dot_command(&ua, ua.cmd);
+ ua->cmd = check_pool_memory_size(ua->cmd, ua->UA_sock->msglen+1);
+ bstrncpy(ua->cmd, ua->UA_sock->msg, ua->UA_sock->msglen+1);
+ parse_ua_args(ua);
+ if (ua->argc > 0 && ua->argk[0][0] == '.') {
+ do_a_dot_command(ua, ua->cmd);
} else {
- do_a_command(&ua, ua.cmd);
+ do_a_command(ua, ua->cmd);
}
- if (!ua.quit) {
- if (ua.auto_display_messages) {
- strcpy(ua.cmd, "messages");
- qmessagescmd(&ua, ua.cmd);
- ua.user_notified_msg_pending = FALSE;
- } else if (!ua.user_notified_msg_pending && console_msg_pending) {
- bsendmsg(&ua, _("You have messages.\n"));
- ua.user_notified_msg_pending = TRUE;
+ if (!ua->quit) {
+ if (ua->auto_display_messages) {
+ strcpy(ua->cmd, "messages");
+ qmessagescmd(ua, ua->cmd);
+ ua->user_notified_msg_pending = FALSE;
+ } else if (!ua->user_notified_msg_pending && console_msg_pending) {
+ bsendmsg(ua, _("You have messages.\n"));
+ ua->user_notified_msg_pending = TRUE;
}
- bnet_sig(ua.UA_sock, BNET_EOD); /* send end of command */
+ bnet_sig(ua->UA_sock, BNET_EOD); /* send end of command */
}
- } else if (is_bnet_stop(ua.UA_sock)) {
- ua.quit = TRUE;
+ } else if (is_bnet_stop(ua->UA_sock)) {
+ ua->quit = TRUE;
break;
} else { /* signal */
- bnet_sig(ua.UA_sock, BNET_POLL);
+ bnet_sig(ua->UA_sock, BNET_POLL);
}
}
getout:
- if (ua.UA_sock) {
- bnet_close(ua.UA_sock);
- ua.UA_sock = NULL;
- }
- close_db(&ua); /* do this before freeing JCR */
+ close_db(ua); /* do this before freeing JCR */
+ free_ua_context(ua);
+ free_jcr(jcr);
+
+ return NULL;
+}
- if (ua.jcr) {
- free_jcr(ua.jcr);
- ua.jcr = NULL;
+/*
+ * Create a UAContext for a Job that is running so that
+ * it can the User Agent routines and
+ * to ensure that the Job gets the proper output.
+ * This is a sort of mini-kludge, and should be
+ * unified at some point.
+ */
+UAContext *new_ua_context(JCR *jcr)
+{
+ UAContext *ua;
+
+ ua = (UAContext *)malloc(sizeof(UAContext));
+ memset(ua, 0, sizeof(UAContext));
+ ua->jcr = jcr;
+ ua->db = jcr->db;
+ ua->cmd = get_pool_memory(PM_FNAME);
+ ua->args = get_pool_memory(PM_FNAME);
+ ua->verbose = 1;
+ ua->automount = TRUE;
+ return ua;
+}
+
+void free_ua_context(UAContext *ua)
+{
+ if (ua->cmd) {
+ free_pool_memory(ua->cmd);
}
- if (ua.prompt) {
- free(ua.prompt);
+ if (ua->args) {
+ free_pool_memory(ua->args);
}
- if (ua.cmd) {
- free_pool_memory(ua.cmd);
+ if (ua->prompt) {
+ free(ua->prompt);
}
- if (ua.args) {
- free_pool_memory(ua.args);
+
+ if (ua->UA_sock) {
+ bnet_close(ua->UA_sock);
}
- return NULL;
+
+ free(ua);
}
+
/*
* Called from main Bacula thread
*/
*/
if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) {
RBSR *bsr = new_bsr();
- UAContext ua;
+ UAContext *ua;
bsr->JobId = jr.JobId;
- create_ua_context(jcr, &ua);
- complete_bsr(&ua, bsr);
+ ua = new_ua_context(jcr);
+ complete_bsr(ua, bsr);
bsr->fi = new_findex();
bsr->fi->findex = 1;
bsr->fi->findex2 = jr.JobFiles;
- if (!write_bsr_file(&ua, bsr)) {
- free_ua_context(&ua);
+ if (!write_bsr_file(ua, bsr)) {
+ free_ua_context(ua);
free_bsr(bsr);
goto bail_out;
}
- free_ua_context(&ua);
+ free_ua_context(ua);
free_bsr(bsr);
if (jcr->RestoreBootstrap) {
free(jcr->RestoreBootstrap);
/* */
#define VERSION "1.31"
#define VSTRING "1"
-#define BDATE "20 Jun 2003"
-#define LSMDATE "20Jun03"
+#define BDATE "21 Jun 2003"
+#define LSMDATE "21Jun03"
/* Debug flags */
#define DEBUG 1