}
if (!mdb->transaction) {
my_sqlite_query(mdb, "BEGIN"); /* begin transaction */
- Dmsg0(000, "Start SQLite transaction\n");
+ Dmsg0(400, "Start SQLite transaction\n");
mdb->transaction = 1;
}
db_unlock(mdb);
if (mdb->transaction) {
my_sqlite_query(mdb, "COMMIT"); /* end transaction */
mdb->transaction = 0;
- Dmsg1(000, "End SQLite transaction changes=%d\n", mdb->changes);
+ Dmsg1(400, "End SQLite transaction changes=%d\n", mdb->changes);
}
mdb->changes = 0;
db_unlock(mdb);
:List where a File is saved:
*Enter Filename (no path):
SELECT Job.JobId as JobId, Client.Name as Client,
- CONCAT(Path.Path,Filename.Name) as Name,
+ Path.Path||Filename.Name as Name,
StartTime,Level,JobFiles,JobBytes
FROM Client,Job,File,Filename,Path WHERE Client.ClientId=Job.ClientId
AND JobStatus='T' AND Job.JobId=File.JobId
/* Forward referenced subroutines */
static void find_runs();
+static void add_job(JOB *job, RUN *run, time_t now, time_t runtime);
/* Imported subroutines */
time_t now, runtime, nexttime;
int jobindex, i;
static int first = TRUE;
+ char dt[MAX_TIME_LENGTH];
Dmsg0(200, "Enter wait_for_next_job\n");
if (first) {
max_runjobs = 10;
runjobs = (RUNJOB *) malloc(sizeof(RUNJOB) * max_runjobs);
num_runjobs = 0;
+ rem_runjobs = 0;
if (job_to_run) { /* one shot */
job = (JOB *)GetResWithName(R_JOB, job_to_run);
if (!job) {
set_jcr_defaults(jcr, job);
return jcr;
}
- find_runs();
}
/* Wait until we have something in the
* next hour or so.
*/
- while (num_runjobs == 0 || rem_runjobs == 0) {
- sleep(60);
+ while (rem_runjobs == 0) {
find_runs();
+ if (rem_runjobs > 0) {
+ break;
+ }
+ sleep(60);
}
+
/*
* Sort through what is to be run in the next
* two hours to find the first job to be run,
time(&now);
nexttime = now + 60 * 60 * 24; /* a much later time */
jobindex = -1;
+ bstrftime(dt, sizeof(dt), now);
+ Dmsg2(400, "jobs=%d. Now is %s\n", rem_runjobs, dt);
for (i=0; i<num_runjobs; i++) {
runtime = runjobs[i].runtime;
if (runtime > 0 && runtime < nexttime) { /* find minimum time job */
nexttime = runtime;
jobindex = i;
}
+#ifdef xxxx_debug
+ if (runtime > 0) {
+ bstrftime(dt, sizeof(dt), runjobs[i].runtime);
+ Dmsg2(000, " %s run %s\n", dt, runjobs[i].job->hdr.name);
+ }
+#endif
}
if (jobindex < 0) { /* we really should have something now */
Emsg0(M_ABORT, 0, _("Scheduler logic error\n"));
twait = nexttime - now;
if (twait <= 0) /* time to run it */
break;
- if (twait > 20) /* sleep max 20 seconds */
- twait = 20;
+ if (twait > 1) /* sleep max 20 seconds */
+ twait--;
sleep(twait);
}
run = runjobs[jobindex].run;
}
for (run=sched->run; run; run=run->next) {
- if (now - run->last_run < 60 * 20)
- continue; /* wait at least 20 minutes */
-
/* Find runs scheduled in this our or in the
* next hour (we may be one second before the next hour).
*/
/* find time (time_t) job is to be run */
localtime_r(&now, &tm);
- if (bit_is_set(next_hour, run->hour))
- tm.tm_hour++;
- if (tm.tm_hour > 23)
- tm.tm_hour = 0;
tm.tm_min = run->minute;
tm.tm_sec = 0;
- runtime = mktime(&tm);
- if (runtime < (now - 5 * 60)) /* give 5 min grace to pickup straglers */
- continue;
- /* Make sure array is big enough */
- if (num_runjobs == max_runjobs) {
- max_runjobs += 10;
- runjobs = (RUNJOB *) realloc(runjobs, sizeof(RUNJOB) * max_runjobs);
- if (!runjobs)
- Emsg0(M_ABORT, 0, _("Out of memory\n"));
+ if (bit_is_set(hour, run->hour)) {
+ runtime = mktime(&tm);
+ add_job(job, run, now, runtime);
+ }
+ if (bit_is_set(next_hour, run->hour)) {
+ tm.tm_hour++;
+ if (tm.tm_hour > 23) {
+ tm.tm_hour = 0;
+ }
+ runtime = mktime(&tm);
+ add_job(job, run, now, runtime);
}
- /* accept to run this job */
- runjobs[num_runjobs].run = run;
- runjobs[num_runjobs].job = job;
- runjobs[num_runjobs++].runtime = runtime; /* when to run it */
-
}
}
}
rem_runjobs = num_runjobs;
Dmsg0(200, "Leave find_runs()\n");
}
+
+static void add_job(JOB *job, RUN *run, time_t now, time_t runtime)
+{
+ /*
+ * Don't run any job that ran less than a minute ago, but
+ * do run any job scheduled less than a minute ago.
+ */
+ if ((runtime - run->last_run < 61) || (runtime+59 < now)) {
+ return;
+ }
+
+ /* Make sure array is big enough */
+ if (num_runjobs == max_runjobs) {
+ max_runjobs += 10;
+ runjobs = (RUNJOB *) realloc(runjobs, sizeof(RUNJOB) * max_runjobs);
+ if (!runjobs)
+ Emsg0(M_ABORT, 0, _("Out of memory\n"));
+ }
+ /* accept to run this job */
+ runjobs[num_runjobs].run = run;
+ runjobs[num_runjobs].job = job;
+ runjobs[num_runjobs++].runtime = runtime; /* when to run it */
+}
return 0;
}
-
/*
* Build the directory tree
*/
"List Jobs where a given File is saved",
"Enter list of JobIds to select",
"Enter SQL list command",
- "Select the most recent backup for a client"
+ "Select the most recent backup for a client",
"Cancel",
NULL };
memset(&jr, 0, sizeof(JOB_DBR));
+ full->TotalFiles = 0;
for (p=full->JobIds; ; ) {
int stat = next_jobid_from_list(&p, &JobId);
if (stat < 0) {
bsendmsg(ua, _("Unable to get Job record. ERR=%s\n"), db_strerror(ua->db));
return 0;
}
- full->TotalFiles = jr.JobFiles;
+ full->TotalFiles += jr.JobFiles;
}
return 1;
}
{
JOB_DBR jr;
char VolumeNames[1000]; /* ****FIXME**** */
+ char *p;
if (bsr) {
memset(&jr, 0, sizeof(jr));
bsendmsg(ua, _("Unable to get Job Volumes. ERR=%s\n"), db_strerror(ua->db));
return 0;
}
+ if ((p = strchr(VolumeNames, '|'))) {
+ *p = 0; /* take first volume */
+ }
bsr->VolumeName = bstrdup(VolumeNames);
return complete_bsr(ua, bsr->next);
}
static void prt_runtime(UAContext *ua, JOB *job, time_t runtime)
{
- char dt[MAX_TIME_LENGTH], *type;
+ char dt[MAX_TIME_LENGTH];
bstrftime(dt, sizeof(dt), runtime);
- switch (job->JobType) {
- case JT_BACKUP:
- type = _("Backup");
- break;
- case JT_VERIFY:
- type = _("Verify");
- break;
- case JT_RESTORE:
- type = _("Restore");
- break;
- default:
- type = _("Unknown type of");
- break;
- }
- bsendmsg(ua, _("%s job \"%s\" scheduled for %s\n"), type, job->hdr.name, dt);
+ bsendmsg(ua, _("%s job \"%s\" scheduled for %s\n"),
+ job_type_to_str(job->JobType), job->hdr.name, dt);
}
/*
TREE_ROOT *root;
uint32_t size;
+ if (count < 1000) { /* minimum tree size */
+ count = 1000;
+ }
root = (TREE_ROOT *)malloc(sizeof(TREE_ROOT));
memset(root, 0, sizeof(TREE_ROOT));
root->type = TN_ROOT;
switch (stat) {
case JS_Terminated:
- str = "OK";
+ str = _("OK");
break;
case JS_ErrorTerminated:
case JS_Error:
- str = "Error";
+ str = _("Error");
break;
case JS_FatalError:
- str = "Fatal Error";
+ str = _("Fatal Error");
break;
case JS_Cancelled:
- str = "Cancelled";
+ str = _("Cancelled");
break;
case JS_Differences:
- str = "Differences";
+ str = _("Differences");
break;
default:
- str = "Unknown term code";
+ str = _("Unknown term code");
break;
}
return str;
switch (type) {
case JT_BACKUP:
- str = "Backup";
+ str = _("Backup");
break;
case JT_VERIFY:
- str = "Verify";
+ str = _("Verify");
break;
case JT_RESTORE:
- str = "Restore";
+ str = _("Restore");
break;
case JT_ADMIN:
- str = "Admin";
+ str = _("Admin");
default:
- str = "Unknown Job Type";
+ str = _("Unknown Type");
break;
}
return str;
switch (level) {
case L_FULL:
- str = "full";
+ str = _("Full");
break;
case L_INCREMENTAL:
- str = "incremental";
+ str = _("Incremental");
break;
case L_DIFFERENTIAL:
- str = "differential";
+ str = _("Differential");
break;
case L_LEVEL:
- str = "level";
+ str = _("Level");
break;
case L_SINCE:
- str = "since";
+ str = _("Since");
break;
case L_VERIFY_CATALOG:
- str = "verify catalog";
+ str = _("Verify Catalog");
break;
case L_VERIFY_INIT:
- str = "verify init";
+ str = _("Verify Init Catalog");
break;
case L_VERIFY_VOLUME_TO_CATALOG:
- str = "verify volume to catalog";
+ str = _("Verify Volume to Catalog");
break;
case L_VERIFY_DATA:
- str = "verify data";
+ str = _("Verify Data");
break;
default:
- str = "Unknown Job level";
+ str = _("Unknown Job Level");
break;
}
return str;
timeout.tv_sec = tv.tv_sec + SLEEP_TIME;
Dmsg1(200, "pthread_cond_timedwait sec=%d\n", timeout.tv_sec);
-#ifdef xxxxxxxxxxxxxxx_was_HAVE_CYGWIN
- /* CYGWIN dies with a page fault the second
- * time that pthread_cond_timedwait() is called
- * so fake it out.
- */
- sleep(SLEEP_TIME);
-#else
stat = pthread_cond_timedwait(&timer, &mutex, &timeout);
Dmsg1(200, "pthread_cond_timedwait stat=%d\n", stat);
-#endif
} /* end of big for loop */
+ pthread_mutex_unlock(&mutex); /* for good form */
Dmsg0(200, "End watchdog\n");
return NULL;
}
/* */
#define VERSION "1.24"
#define VSTRING "1"
-#define DATE "05 August 2002"
-#define LSMDATE "05Aug02"
+#define DATE "06 August 2002"
+#define LSMDATE "06Aug02"
/* Debug flags */
#define DEBUG 1