X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fua_output.c;h=27ac0357724db8a02d1f72641842518a7dfb64ee;hb=fa1cad6e368a3c7d0a1ac4ad25176b7043b1310f;hp=f862dad02407e069347f3a2692be18dbcca1440f;hpb=1f3edf3a27024df37e6de3d9b63b6d744808f628;p=bacula%2Fbacula diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index f862dad024..27ac035772 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -30,15 +30,13 @@ #include "bacula.h" #include "dird.h" -#include "ua.h" /* Imported subroutines */ -extern void run_job(JCR *jcr); /* Imported variables */ extern int r_first; extern int r_last; -extern struct s_res resources[]; +extern RES_TABLE resources[]; extern int console_msg_pending; extern FILE *con_fd; extern brwlock_t con_lock; @@ -47,12 +45,12 @@ extern brwlock_t con_lock; /* Imported functions */ /* Forward referenced functions */ - +static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist); /* * Turn auto display of console messages on/off */ -int autodisplaycmd(UAContext *ua, char *cmd) +int autodisplay_cmd(UAContext *ua, char *cmd) { static char *kw[] = { N_("on"), @@ -60,30 +58,55 @@ int autodisplaycmd(UAContext *ua, char *cmd) NULL}; switch (find_arg_keyword(ua, kw)) { - case 0: - ua->auto_display_messages = 1; - break; - case 1: - ua->auto_display_messages = 0; - break; - default: - bsendmsg(ua, _("ON or OFF keyword missing.\n")); - break; + case 0: + ua->auto_display_messages = 1; + break; + case 1: + ua->auto_display_messages = 0; + break; + default: + bsendmsg(ua, _("ON or OFF keyword missing.\n")); + break; } return 1; } +/* + * Turn gui processing on/off + */ +int gui_cmd(UAContext *ua, char *cmd) +{ + static char *kw[] = { + N_("on"), + N_("off"), + NULL}; + + switch (find_arg_keyword(ua, kw)) { + case 0: + ua->jcr->gui = true; + break; + case 1: + ua->jcr->gui = false; + break; + default: + bsendmsg(ua, _("ON or OFF keyword missing.\n")); + break; + } + return 1; +} + + struct showstruct {char *res_name; int type;}; static struct showstruct reses[] = { {N_("directors"), R_DIRECTOR}, {N_("clients"), R_CLIENT}, + {N_("counters"), R_COUNTER}, {N_("jobs"), R_JOB}, {N_("storages"), R_STORAGE}, {N_("catalogs"), R_CATALOG}, {N_("schedules"), R_SCHEDULE}, {N_("filesets"), R_FILESET}, - {N_("groups"), R_GROUP}, {N_("pools"), R_POOL}, {N_("messages"), R_MSGS}, {N_("all"), -1}, @@ -100,7 +123,7 @@ static struct showstruct reses[] = { * show = e.g. show director=HeadMan * */ -int showcmd(UAContext *ua, char *cmd) +int show_cmd(UAContext *ua, char *cmd) { int i, j, type, len; int recurse; @@ -110,6 +133,7 @@ int showcmd(UAContext *ua, char *cmd) Dmsg1(20, "show: %s\n", ua->UA_sock->msg); + LockRes(); for (i=1; iargc; i++) { type = 0; res_name = ua->argk[i]; @@ -128,6 +152,7 @@ int showcmd(UAContext *ua, char *cmd) break; } } + } else { /* Dump a single resource with specified name */ recurse = 0; @@ -155,18 +180,20 @@ int showcmd(UAContext *ua, char *cmd) for (j=0; reses[j].res_name; j++) { bsendmsg(ua, "%s\n", _(reses[j].res_name)); } - return 1; + goto bail_out; case -3: bsendmsg(ua, _("%s resource %s not found.\n"), res_name, ua->argv[i]); - return 1; + goto bail_out; case 0: bsendmsg(ua, _("Resource %s not found\n"), res_name); - return 1; + goto bail_out; default: dump_resource(recurse?type:-type, res, bsendmsg, ua); break; } } +bail_out: + UnlockRes(); return 1; } @@ -185,11 +212,27 @@ int showcmd(UAContext *ua, char *cmd) * list files job=name * list pools - list pool records * list jobtotals - list totals for all jobs - * list media - list media for given pool + * list media - list media for given pool (deprecated) + * list volumes - list Volumes * list clients - list clients + * list nextvol job=xx - list the next vol to be used by job + * list nextvolume job=xx - same as above. * */ -int listcmd(UAContext *ua, char *cmd) + +/* Do long or full listing */ +int llist_cmd(UAContext *ua, char *cmd) +{ + return do_list_cmd(ua, cmd, VERT_LIST); +} + +/* Do short or summary listing */ +int list_cmd(UAContext *ua, char *cmd) +{ + return do_list_cmd(ua, cmd, HORZ_LIST); +} + +static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) { POOLMEM *VolumeName; int jobid, n; @@ -215,7 +258,7 @@ int listcmd(UAContext *ua, char *cmd) for (i=1; iargc; i++) { /* List JOBS */ if (strcasecmp(ua->argk[i], _("jobs")) == 0) { - db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua); + db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, llist); /* List JOBTOTALS */ } else if (strcasecmp(ua->argk[i], _("jobtotals")) == 0) { @@ -227,7 +270,7 @@ int listcmd(UAContext *ua, char *cmd) jobid = atoi(ua->argv[i]); if (jobid > 0) { jr.JobId = jobid; - db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua); + db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, llist); } } @@ -235,7 +278,7 @@ int listcmd(UAContext *ua, char *cmd) } else if (strcasecmp(ua->argk[i], _("job")) == 0 && ua->argv[i]) { bstrncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH); jr.JobId = 0; - db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua); + db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, llist); /* List FILES */ } else if (strcasecmp(ua->argk[i], _("files")) == 0) { @@ -270,26 +313,26 @@ int listcmd(UAContext *ua, char *cmd) } else { continue; } - db_list_jobmedia_records(ua->jcr, ua->db, jobid, prtit, ua); + db_list_jobmedia_records(ua->jcr, ua->db, jobid, prtit, ua, llist); done = TRUE; } if (!done) { /* List for all jobs (jobid=0) */ - db_list_jobmedia_records(ua->jcr, ua->db, 0, prtit, ua); + db_list_jobmedia_records(ua->jcr, ua->db, 0, prtit, ua, llist); } /* List POOLS */ } else if (strcasecmp(ua->argk[i], _("pools")) == 0) { - db_list_pool_records(ua->jcr, ua->db, prtit, ua); + db_list_pool_records(ua->jcr, ua->db, prtit, ua, llist); } else if (strcasecmp(ua->argk[i], _("clients")) == 0) { - db_list_client_records(ua->jcr, ua->db, prtit, ua); + db_list_client_records(ua->jcr, ua->db, prtit, ua, llist); /* List MEDIA or VOLUMES */ } else if (strcasecmp(ua->argk[i], _("media")) == 0 || strcasecmp(ua->argk[i], _("volumes")) == 0) { - int done = FALSE; + bool done = false; for (j=i+1; jargc; j++) { if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) { bstrncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH); @@ -305,16 +348,108 @@ int listcmd(UAContext *ua, char *cmd) n = db_get_job_volume_names(ua->jcr, ua->db, jobid, &VolumeName); bsendmsg(ua, _("Jobid %d used %d Volume(s): %s\n"), jobid, n, VolumeName); free_pool_memory(VolumeName); - done = TRUE; + done = true; } /* if no job or jobid keyword found, then we list all media */ if (!done) { - if (!get_pool_dbr(ua, &pr)) { + int num_pools; + uint32_t *ids; + /* Is a specific pool wanted? */ + for (i=1; iargc; i++) { + if (strcasecmp(ua->argk[i], _("pool")) == 0) { + if (!get_pool_dbr(ua, &pr)) { + bsendmsg(ua, _("No Pool specified.\n")); + return 1; + } + mr.PoolId = pr.PoolId; + db_list_media_records(ua->jcr, ua->db, &mr, prtit, ua, llist); + return 1; + } + } + /* List Volumes in all pools */ + if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) { + bsendmsg(ua, _("Error obtaining pool ids. ERR=%s\n"), + db_strerror(ua->db)); + return 1; + } + if (num_pools <= 0) { + return 1; + } + for (i=0; i < num_pools; i++) { + pr.PoolId = ids[i]; + if (db_get_pool_record(ua->jcr, ua->db, &pr)) { + bsendmsg(ua, _("Pool: %s\n"), pr.Name); + } + mr.PoolId = ids[i]; + db_list_media_records(ua->jcr, ua->db, &mr, prtit, ua, llist); + } + free(ids); + return 1; + } + /* List a specific volume */ + } else if (strcasecmp(ua->argk[i], _("volume")) == 0) { + if (!ua->argv[i]) { + bsendmsg(ua, _("No Volume Name specified.\n")); + return 1; + } + bstrncpy(mr.VolumeName, ua->argv[i], sizeof(mr.VolumeName)); + db_list_media_records(ua->jcr, ua->db, &mr, prtit, ua, llist); + return 1; + /* List next volume */ + } else if (strcasecmp(ua->argk[i], _("nextvol")) == 0 || + strcasecmp(ua->argk[i], _("nextvolume")) == 0) { + JOB *job; + JCR *jcr = ua->jcr; + POOL *pool; + RUN *run; + time_t runtime; + bool found = false; + + i = find_arg_with_value(ua, "job"); + if (i <= 0) { + if ((job = select_job_resource(ua)) == NULL) { + return 1; + } + } else { + job = (JOB *)GetResWithName(R_JOB, ua->argv[i]); + if (!job) { + Jmsg(jcr, M_ERROR, 0, _("%s is not a job name.\n"), ua->argv[i]); + if ((job = select_job_resource(ua)) == NULL) { + return 1; + } + } + } + for (run=NULL; (run = find_next_run(run, job, runtime)); ) { + pool = run ? run->pool : NULL; + if (!complete_jcr_for_job(jcr, job, pool)) { + return 1; + } + + if (!find_next_volume_for_append(jcr, &mr, 0)) { + bsendmsg(ua, _("Could not find next Volume.\n")); + if (jcr->db) { + db_close_database(jcr, jcr->db); + jcr->db = NULL; + } return 1; + } else { + bsendmsg(ua, _("The next Volume to be used by Job \"%s\" will be %s\n"), + job->hdr.name, mr.VolumeName); + found = true; + } + if (jcr->db) { + db_close_database(jcr, jcr->db); + jcr->db = NULL; } - mr.PoolId = pr.PoolId; - db_list_media_records(ua->jcr, ua->db, &mr, prtit, ua); } + if (jcr->db) { + db_close_database(jcr, jcr->db); + jcr->db = NULL; + } + if (!found) { + bsendmsg(ua, _("Could not find next Volume.\n")); + } + return 1; } else { bsendmsg(ua, _("Unknown list keyword: %s\n"), NPRT(ua->argk[i])); } @@ -322,6 +457,147 @@ int listcmd(UAContext *ua, char *cmd) return 1; } +/* + * For a given job, we examine all his run records + * to see if it is scheduled today or tomorrow. + */ +RUN *find_next_run(RUN *run, JOB *job, time_t &runtime) +{ + time_t now, tomorrow; + SCHED *sched; + struct tm tm; + int mday, wday, month, wom, tmday, twday, tmonth, twom, i, hour; + int woy, twoy; + int tod, tom; + + sched = job->schedule; + if (sched == NULL) { /* scheduled? */ + return NULL; /* no nothing to report */ + } + /* Break down current time into components */ + now = time(NULL); + localtime_r(&now, &tm); + mday = tm.tm_mday - 1; + wday = tm.tm_wday; + month = tm.tm_mon; + wom = mday / 7; + woy = tm_woy(now); + + /* Break down tomorrow into components */ + tomorrow = now + 60 * 60 * 24; + localtime_r(&tomorrow, &tm); + tmday = tm.tm_mday - 1; + twday = tm.tm_wday; + tmonth = tm.tm_mon; + twom = tmday / 7; + twoy = tm_woy(tomorrow); + + if (run == NULL) { + run = sched->run; + } else { + run = run->next; + } + for ( ; run; run=run->next) { + /* + * Find runs in next 24 hours + */ + tod = (bit_is_set(mday, run->mday) || bit_is_set(wday, run->wday)) && + bit_is_set(month, run->month) && bit_is_set(wom, run->wom) && + bit_is_set(woy, run->woy); + + tom = (bit_is_set(tmday, run->mday) || bit_is_set(twday, run->wday)) && + bit_is_set(tmonth, run->month) && bit_is_set(twom, run->wom) && + bit_is_set(twoy, run->woy); + +// Dmsg2(200, "tod=%d tom=%d\n", tod, tom); +// Dmsg2(200, "wom=%d twom=%d\n", wom, twom); +// Dmsg1(200, "bit_set_wom=%d\n", bit_is_set(wom, run->wom)); + if (tod) { /* Jobs scheduled today (next 24 hours) */ + /* find time (time_t) job is to be run */ + localtime_r(&now, &tm); + hour = 0; + for (i=tm.tm_hour; i < 24; i++) { + if (bit_is_set(i, run->hour)) { + tm.tm_hour = i; + tm.tm_min = run->minute; + tm.tm_sec = 0; + runtime = mktime(&tm); + if (runtime > now) { + Dmsg2(000, "Found it level=%d %c\n", run->level, run->level); + return run; /* found it, return run resource */ + } + } + } + } + +// Dmsg2(200, "runtime=%d now=%d\n", runtime, now); + if (tom) { /* look at jobs scheduled tomorrow */ + localtime_r(&tomorrow, &tm); + hour = 0; + for (i=0; i < 24; i++) { + if (bit_is_set(i, run->hour)) { + hour = i; + break; + } + } + tm.tm_hour = hour; + tm.tm_min = run->minute; + tm.tm_sec = 0; + runtime = mktime(&tm); +// Dmsg2(200, "truntime=%d now=%d\n", runtime, now); + if (runtime < tomorrow) { + return run; /* found it, return run resource */ + } + } + } /* end for loop over runs */ + /* Nothing found */ + return NULL; +} +/* + * Fill in the remaining fields of the jcr as if it + * is going to run the job. + */ +int complete_jcr_for_job(JCR *jcr, JOB *job, POOL *pool) +{ + POOL_DBR pr; + + memset(&pr, 0, sizeof(POOL_DBR)); + set_jcr_defaults(jcr, job); + if (pool) { + jcr->pool = pool; /* override */ + } + jcr->db = jcr->db=db_init_database(jcr, jcr->catalog->db_name, jcr->catalog->db_user, + jcr->catalog->db_password, jcr->catalog->db_address, + jcr->catalog->db_port, jcr->catalog->db_socket); + if (!jcr->db || !db_open_database(jcr, jcr->db)) { + Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"), + jcr->catalog->db_name); + if (jcr->db) { + Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); + } + return 0; + } + bstrncpy(pr.Name, jcr->pool->hdr.name, sizeof(pr.Name)); + while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */ + /* Try to create the pool */ + if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) { + Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name, + db_strerror(jcr->db)); + if (jcr->db) { + db_close_database(jcr, jcr->db); + jcr->db = NULL; + } + return 0; + } else { + Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name); + } + } + jcr->PoolId = pr.PoolId; + jcr->jr.PoolId = pr.PoolId; + return 1; +} + + static void con_lock_release(void *arg) { Vw(con_lock); @@ -409,11 +685,12 @@ again: len = bvsnprintf(msg, maxlen, fmt, arg_ptr); va_end(arg_ptr); if (len < 0 || len >= maxlen) { - msg = realloc_pool_memory(msg, maxlen + 200); + msg = realloc_pool_memory(msg, maxlen + maxlen/2); goto again; } if (bs) { + bs->msg = msg; bs->msglen = len; bnet_send(bs); } else { /* No UA, send to Job */