X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=bacula%2Fsrc%2Fdird%2Fua_output.c;h=09190e1e2381d1471e5073c390dcfc63fa61642a;hb=f183afa93772e5f5b3951407bce839b951dede96;hp=05cee1db5912e960575e28cfb7fbadcfbe5005c1;hpb=c9a6fc522de5bca4754f67c304c8646772ca2e6b;p=bacula%2Fbacula diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index 05cee1db59..09190e1e23 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -9,22 +9,17 @@ */ /* - Copyright (C) 2000-2003 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + modify it under the terms of the GNU General Public License + version 2 as ammended with additional clauses defined in the + file LICENSE in the main source directory. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. */ @@ -36,24 +31,25 @@ /* Imported variables */ extern int r_first; extern int r_last; -extern struct s_res resources[]; +extern RES_TABLE resources[]; +extern RES **res_head; extern int console_msg_pending; extern FILE *con_fd; extern brwlock_t con_lock; - /* Imported functions */ /* Forward referenced functions */ -static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist); +static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist); +static bool list_nextvol(UAContext *ua); /* * Turn auto display of console messages on/off */ -int autodisplaycmd(UAContext *ua, char *cmd) +int autodisplay_cmd(UAContext *ua, const char *cmd) { - static char *kw[] = { - N_("on"), + static const char *kw[] = { + N_("on"), N_("off"), NULL}; @@ -68,21 +64,48 @@ int autodisplaycmd(UAContext *ua, char *cmd) bsendmsg(ua, _("ON or OFF keyword missing.\n")); break; } - return 1; + return 1; +} + +/* + * Turn batch processing on/off + */ +int gui_cmd(UAContext *ua, const char *cmd) +{ + static const char *kw[] = { + N_("on"), + N_("off"), + NULL}; + + switch (find_arg_keyword(ua, kw)) { + case 0: + ua->batch = true; + ua->jcr->gui = true; + break; + case 1: + ua->batch = false; + ua->jcr->gui = false; + break; + default: + bsendmsg(ua, _("ON or OFF keyword missing.\n")); + break; + } + return 1; } -struct showstruct {char *res_name; int type;}; + +struct showstruct {const char *res_name; int type;}; static struct showstruct reses[] = { {N_("directors"), R_DIRECTOR}, {N_("clients"), R_CLIENT}, {N_("counters"), R_COUNTER}, + {N_("devices"), R_DEVICE}, {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}, @@ -99,9 +122,9 @@ static struct showstruct reses[] = { * show = e.g. show director=HeadMan * */ -int show_cmd(UAContext *ua, char *cmd) +int show_cmd(UAContext *ua, const char *cmd) { - int i, j, type, len; + int i, j, type, len; int recurse; char *res_name; RES *res = NULL; @@ -109,9 +132,10 @@ int show_cmd(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]; + res_name = ua->argk[i]; if (!ua->argv[i]) { /* was a name given? */ /* No name, dump all resources of specified type */ recurse = 1; @@ -120,13 +144,14 @@ int show_cmd(UAContext *ua, char *cmd) if (strncasecmp(res_name, _(reses[j].res_name), len) == 0) { type = reses[j].type; if (type > 0) { - res = resources[type-r_first].res_head; + res = res_head[type-r_first]; } else { res = NULL; } break; } } + } else { /* Dump a single resource with specified name */ recurse = 0; @@ -146,7 +171,7 @@ int show_cmd(UAContext *ua, char *cmd) switch (type) { case -1: /* all */ for (j=r_first; j<=r_last; j++) { - dump_resource(j, resources[j-r_first].res_head, bsendmsg, ua); + dump_resource(j, res_head[j-r_first], bsendmsg, ua); } break; case -2: @@ -154,18 +179,20 @@ int show_cmd(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; } @@ -193,18 +220,18 @@ int show_cmd(UAContext *ua, char *cmd) */ /* Do long or full listing */ -int llist_cmd(UAContext *ua, char *cmd) +int llist_cmd(UAContext *ua, const char *cmd) { return do_list_cmd(ua, cmd, VERT_LIST); } /* Do short or summary listing */ -int list_cmd(UAContext *ua, char *cmd) +int list_cmd(UAContext *ua, const char *cmd) { return do_list_cmd(ua, cmd, HORZ_LIST); } -static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) +static int do_list_cmd(UAContext *ua, const char *cmd, e_list_type llist) { POOLMEM *VolumeName; int jobid, n; @@ -230,6 +257,11 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) for (i=1; iargc; i++) { /* List JOBS */ if (strcasecmp(ua->argk[i], _("jobs")) == 0) { + /* Apply any limit */ + j = find_arg_with_value(ua, _("limit")); + if (j >= 0) { + jr.limit = atoi(ua->argv[j]); + } db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, llist); /* List JOBTOTALS */ @@ -239,7 +271,7 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) /* List JOBID */ } else if (strcasecmp(ua->argk[i], _("jobid")) == 0) { if (ua->argv[i]) { - jobid = atoi(ua->argv[i]); + jobid = str_to_int64(ua->argv[i]); if (jobid > 0) { jr.JobId = jobid; db_list_job_records(ua->jcr, ua->db, &jr, prtit, ua, llist); @@ -262,7 +294,7 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) db_get_job_record(ua->jcr, ua->db, &jr); jobid = jr.JobId; } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) { - jobid = atoi(ua->argv[j]); + jobid = str_to_int64(ua->argv[j]); } else { continue; } @@ -270,7 +302,7 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) db_list_files_for_job(ua->jcr, ua->db, jobid, prtit, ua); } } - + /* List JOBMEDIA */ } else if (strcasecmp(ua->argk[i], _("jobmedia")) == 0) { int done = FALSE; @@ -281,7 +313,7 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) db_get_job_record(ua->jcr, ua->db, &jr); jobid = jr.JobId; } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) { - jobid = atoi(ua->argv[j]); + jobid = str_to_int64(ua->argv[j]); } else { continue; } @@ -304,7 +336,7 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type 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); @@ -312,7 +344,7 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) db_get_job_record(ua->jcr, ua->db, &jr); jobid = jr.JobId; } else if (strcasecmp(ua->argk[j], _("jobid")) == 0 && ua->argv[j]) { - jobid = atoi(ua->argv[j]); + jobid = str_to_int64(ua->argv[j]); } else { continue; } @@ -320,7 +352,7 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) 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) { @@ -340,7 +372,7 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) } /* 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"), + bsendmsg(ua, _("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db)); return 1; } @@ -368,60 +400,11 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) 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 || + } 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; - } - } - if (jcr->db) { - db_close_database(jcr, jcr->db); - jcr->db = NULL; - } - if (!found) { - bsendmsg(ua, _("Could not find next Volume.\n")); - } - return 1; + list_nextvol(ua); + } else if (strcasecmp(ua->argk[i], _("limit")) == 0) { + /* Ignore it */ } else { bsendmsg(ua, _("Unknown list keyword: %s\n"), NPRT(ua->argk[i])); } @@ -429,7 +412,61 @@ static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist) return 1; } -/* +static bool list_nextvol(UAContext *ua) +{ + JOB *job; + JCR *jcr = ua->jcr; + POOL *pool; + RUN *run; + time_t runtime; + bool found = false; + MEDIA_DBR mr; + + memset(&mr, 0, sizeof(mr)); + int i = find_arg_with_value(ua, "job"); + if (i <= 0) { + if ((job = select_job_resource(ua)) == NULL) { + return false; + } + } 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 false; + } + } + } + for (run=NULL; (run = find_next_run(run, job, runtime)); ) { + pool = run->pool ? run->pool : NULL; + if (!complete_jcr_for_job(jcr, job, pool)) { + return false; + } + mr.PoolId = jcr->PoolId; + if (run->storage) { + jcr->store = run->storage; + } + if (!find_next_volume_for_append(jcr, &mr, 0)) { + bsendmsg(ua, _("Could not find next Volume.\n")); + } 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 && jcr->db != ua->db) { + db_close_database(jcr, jcr->db); + jcr->db = NULL; + } + } + if (!found) { + bsendmsg(ua, _("Could not find next Volume.\n")); + return false; + } + return true; +} + + +/* * For a given job, we examine all his run records * to see if it is scheduled today or tomorrow. */ @@ -438,22 +475,22 @@ RUN *find_next_run(RUN *run, JOB *job, time_t &runtime) time_t now, tomorrow; SCHED *sched; struct tm tm; - int mday, wday, month, wpos, tmday, twday, tmonth, twpos, i, hour; + int mday, wday, month, wom, tmday, twday, tmonth, twom, i; + int woy, twoy; int tod, tom; - Dmsg0(200, "enter find_runs()\n"); - sched = job->schedule; if (sched == NULL) { /* scheduled? */ return NULL; /* no nothing to report */ } - /* Break down current time into components */ + /* 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; - wpos = (tm.tm_mday - 1) / 7; + wom = mday / 7; + woy = tm_woy(now); /* Break down tomorrow into components */ tomorrow = now + 60 * 60 * 24; @@ -461,7 +498,8 @@ RUN *find_next_run(RUN *run, JOB *job, time_t &runtime) tmday = tm.tm_mday - 1; twday = tm.tm_wday; tmonth = tm.tm_mon; - twpos = (tm.tm_mday - 1) / 7; + twom = tmday / 7; + twoy = tm_woy(tomorrow); if (run == NULL) { run = sched->run; @@ -469,27 +507,49 @@ RUN *find_next_run(RUN *run, JOB *job, time_t &runtime) 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(wpos, run->wpos); - - tom = (bit_is_set(tmday, run->mday) || bit_is_set(twday, run->wday)) && - bit_is_set(tmonth, run->month) && bit_is_set(twpos, run->wpos); - - Dmsg2(200, "tod=%d tom=%d\n", tod, tom); + 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); + +#ifdef xxx + Dmsg2(000, "tod=%d tom=%d\n", tod, tom); + Dmsg1(000, "bit_set_mday=%d\n", bit_is_set(mday, run->mday)); + Dmsg1(000, "bit_set_wday=%d\n", bit_is_set(wday, run->wday)); + Dmsg1(000, "bit_set_month=%d\n", bit_is_set(month, run->month)); + Dmsg1(000, "bit_set_wom=%d\n", bit_is_set(wom, run->wom)); + Dmsg1(000, "bit_set_woy=%d\n", bit_is_set(woy, run->woy)); +#endif if (tod) { /* Jobs scheduled today (next 24 hours) */ +#ifdef xxx + char buf[300], num[10]; + bsnprintf(buf, sizeof(buf), "tm.hour=%d hour=", tm.tm_hour); + for (i=0; i<24; i++) { + if (bit_is_set(i, run->hour)) { + bsnprintf(num, sizeof(num), "%d ", i); + bstrncat(buf, num, sizeof(buf)); + } + } + bstrncat(buf, "\n", sizeof(buf)); + Dmsg1(000, "%s", buf); +#endif /* 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); + Dmsg2(200, "now=%d runtime=%d\n", now, runtime); if (runtime > now) { + Dmsg2(200, "Found it level=%d %c\n", run->level, run->level); return run; /* found it, return run resource */ } } @@ -499,27 +559,25 @@ RUN *find_next_run(RUN *run, JOB *job, time_t &runtime) // 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 = i; + tm.tm_min = run->minute; + tm.tm_sec = 0; + runtime = mktime(&tm); + Dmsg2(200, "now=%d runtime=%d\n", now, runtime); + if (runtime < tomorrow) { + Dmsg2(200, "Found it level=%d %c\n", run->level, run->level); + return run; /* found it, return run resource */ + } } } - 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 */ + } /* 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. */ @@ -527,14 +585,15 @@ int complete_jcr_for_job(JCR *jcr, JOB *job, POOL *pool) { POOL_DBR pr; - memset(&pr, 0, sizeof(POOL_DBR)); + 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); + jcr->catalog->db_port, jcr->catalog->db_socket, + jcr->catalog->mult_db_connections); if (!jcr->db || !db_open_database(jcr, jcr->db)) { Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"), jcr->catalog->db_name); @@ -547,7 +606,7 @@ int complete_jcr_for_job(JCR *jcr, JOB *job, POOL *pool) 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, + 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); @@ -558,7 +617,7 @@ int complete_jcr_for_job(JCR *jcr, JOB *job, POOL *pool) Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name); } } - jcr->PoolId = pr.PoolId; + jcr->PoolId = pr.PoolId; jcr->jr.PoolId = pr.PoolId; return 1; } @@ -569,10 +628,10 @@ static void con_lock_release(void *arg) Vw(con_lock); } -void do_messages(UAContext *ua, char *cmd) +void do_messages(UAContext *ua, const char *cmd) { char msg[2000]; - int mlen; + int mlen; int do_truncate = FALSE; Pw(con_lock); @@ -596,7 +655,7 @@ void do_messages(UAContext *ua, char *cmd) } -int qmessagescmd(UAContext *ua, char *cmd) +int qmessagescmd(UAContext *ua, const char *cmd) { if (console_msg_pending && ua->auto_display_messages) { do_messages(ua, cmd); @@ -604,7 +663,7 @@ int qmessagescmd(UAContext *ua, char *cmd) return 1; } -int messagescmd(UAContext *ua, char *cmd) +int messagescmd(UAContext *ua, const char *cmd) { if (console_msg_pending) { do_messages(ua, cmd); @@ -617,21 +676,21 @@ int messagescmd(UAContext *ua, char *cmd) /* * Callback routine for "printing" database file listing */ -void prtit(void *ctx, char *msg) +void prtit(void *ctx, const char *msg) { UAContext *ua = (UAContext *)ctx; - + bnet_fsend(ua->UA_sock, "%s", msg); } -/* - * Format message and send to other end. +/* + * Format message and send to other end. * If the UA_sock is NULL, it means that there is no user * agent, so we are being called from Bacula core. In * that case direct the messages to the Job. */ -void bsendmsg(void *ctx, char *fmt, ...) +void bsendmsg(void *ctx, const char *fmt, ...) { va_list arg_ptr; UAContext *ua = (UAContext *)ctx; @@ -651,11 +710,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 */