+static bool list_nextvol(UAContext *ua, int ndays)
+{
+ JOB *job;
+ JCR *jcr = ua->jcr;
+ USTORE store;
+ RUN *run;
+ time_t runtime;
+ bool found = false;
+ MEDIA_DBR mr;
+ POOL_DBR pr;
+
+ 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, ndays)); ) {
+ if (!complete_jcr_for_job(jcr, job, run->pool)) {
+ return false;
+ }
+ if (!jcr->jr.PoolId) {
+ ua->error_msg(_("Could not Pool Job %s\n"), job->name());
+ continue;
+ }
+ memset(&pr, 0, sizeof(pr));
+ pr.PoolId = jcr->jr.PoolId;
+ if (!db_get_pool_record(ua->jcr, ua->db, &pr)) {
+ bstrncpy(pr.Name, "*UnknownPool*", sizeof(pr.Name));
+ }
+ mr.PoolId = jcr->jr.PoolId;
+ get_job_storage(&store, job, run);
+ mr.StorageId = store.store->StorageId;
+ if (!find_next_volume_for_append(jcr, &mr, 1, fnv_no_create_vol, fnv_prune)) {
+ ua->error_msg(_("Could not find next Volume for Job %s (Pool=%s, Level=%s).\n"),
+ job->name(), pr.Name, level_to_str(run->level));
+ } else {
+ ua->send_msg(
+ _("The next Volume to be used by Job \"%s\" (Pool=%s, Level=%s) will be %s\n"),
+ job->name(), pr.Name, level_to_str(run->level), mr.VolumeName);
+ found = true;
+ }
+ if (jcr->db && jcr->db != ua->db) {
+ db_close_database(jcr, jcr->db);
+ jcr->db = NULL;
+ }
+ }
+ if (!found) {
+ ua->error_msg(_("Could not find next Volume for Job %s.\n"),
+ job->hdr.name);
+ return false;
+ }
+ return true;
+}
+
+
+/*
+ * 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, int ndays)
+{
+ time_t now, future, endtime;
+ SCHED *sched;
+ struct tm tm, runtm;
+ int mday, wday, month, wom, i;
+ int woy;
+ int day;
+ int is_scheduled;
+
+ sched = job->schedule;
+ if (sched == NULL) { /* scheduled? */
+ return NULL; /* no nothing to report */
+ }
+
+ /* Break down the time into components */
+ now = time(NULL);
+ endtime = now + (ndays * 60 * 60 * 24);
+
+ if (run == NULL) {
+ run = sched->run;
+ } else {
+ run = run->next;
+ }
+ for ( ; run; run=run->next) {
+ /*
+ * Find runs in next 24 hours. Day 0 is today, so if
+ * ndays=1, look at today and tomorrow.
+ */
+ for (day = 0; day <= ndays; day++) {
+ future = now + (day * 60 * 60 * 24);
+
+ /* Break down the time into components */
+ (void)localtime_r(&future, &tm);
+ mday = tm.tm_mday - 1;
+ wday = tm.tm_wday;
+ month = tm.tm_mon;
+ wom = mday / 7;
+ woy = tm_woy(future);
+
+ is_scheduled = 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);
+
+#ifdef xxx
+ Pmsg2(000, "day=%d is_scheduled=%d\n", day, is_scheduled);
+ Pmsg1(000, "bit_set_mday=%d\n", bit_is_set(mday, run->mday));
+ Pmsg1(000, "bit_set_wday=%d\n", bit_is_set(wday, run->wday));
+ Pmsg1(000, "bit_set_month=%d\n", bit_is_set(month, run->month));
+ Pmsg1(000, "bit_set_wom=%d\n", bit_is_set(wom, run->wom));
+ Pmsg1(000, "bit_set_woy=%d\n", bit_is_set(woy, run->woy));
+#endif
+
+ if (is_scheduled) { /* Jobs scheduled on that day */
+#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));
+ Pmsg1(000, "%s", buf);
+#endif
+ /* find time (time_t) job is to be run */
+ (void)localtime_r(&future, &runtm);
+ for (i= 0; i < 24; i++) {
+ if (bit_is_set(i, run->hour)) {
+ runtm.tm_hour = i;
+ runtm.tm_min = run->minute;
+ runtm.tm_sec = 0;
+ runtime = mktime(&runtm);
+ Dmsg2(200, "now=%d runtime=%d\n", now, runtime);
+ if ((runtime > now) && (runtime < endtime)) {
+ Dmsg2(200, "Found it level=%d %c\n", run->level, run->level);
+ 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.
+ */
+bool 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 */
+ }
+ if (jcr->db) {
+ Dmsg0(100, "complete_jcr close db\n");
+ db_close_database(jcr, jcr->db);
+ jcr->db = NULL;
+ }
+
+ Dmsg0(100, "complete_jcr open db\n");
+ jcr->db = jcr->db=db_init(jcr, jcr->catalog->db_driver, 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->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);
+ if (jcr->db) {
+ Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
+ db_close_database(jcr, jcr->db);
+ jcr->db = NULL;
+ }
+ return false;
+ }
+ bstrncpy(pr.Name, jcr->pool->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 false;
+ } else {
+ Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
+ }
+ }
+ jcr->jr.PoolId = pr.PoolId;
+ return true;
+}
+
+
+static void con_lock_release(void *arg)
+{
+ Vw(con_lock);
+}
+
+void do_messages(UAContext *ua, const char *cmd)