/*
- * "$Id$"
- *
* Job management routines for the CUPS scheduler.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2016 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
* law. Distribution and use rights are outlined in the file "LICENSE.txt"
* which should have been included with this file. If this file is
- * file is missing or damaged, see the license at "http://www.cups.org/".
+ * missing or damaged, see the license at "http://www.cups.org/".
*/
/*
"Job canceled by user.");
}
}
-
- cupsdCheckJobs();
}
*pclass; /* Printer class destination */
ipp_attribute_t *attr; /* Job attribute */
time_t curtime; /* Current time */
+ const char *reasons; /* job-state-reasons value */
curtime = time(NULL);
((FilterLevel + job->pending_cost) < FilterLimit || FilterLevel == 0))
cupsdContinueJob(job);
+ /*
+ * Skip jobs that where held-on-create
+ */
+
+ reasons = ippGetString(job->reasons, 0, NULL);
+ if (reasons && !strcmp(reasons, "job-held-on-create"))
+ {
+ /*
+ * Check whether the printer is still holding new jobs...
+ */
+
+ printer = cupsdFindDest(job->dest);
+
+ if (printer->holding_new_jobs)
+ continue;
+
+ ippSetString(job->attrs, &job->reasons, 0, "none");
+ }
+
/*
* Start pending jobs if the destination is available...
*/
"Job aborted because the destination printer/class "
"has gone away.");
}
- else if (printer && !printer->holding_new_jobs)
+ else if (printer)
{
/*
* See if the printer is available or remote and not printing a job;
if (pclass)
{
/*
- * Add/update a job-actual-printer-uri attribute for this job
+ * Add/update a job-printer-uri-actual attribute for this job
* so that we know which printer actually printed the job...
*/
- if ((attr = ippFindAttribute(job->attrs, "job-actual-printer-uri",
- IPP_TAG_URI)) != NULL)
- cupsdSetString(&attr->values[0].string.text, printer->uri);
+ if ((attr = ippFindAttribute(job->attrs, "job-printer-uri-actual", IPP_TAG_URI)) != NULL)
+ ippSetString(job->attrs, &attr, 0, printer->uri);
else
- ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI,
- "job-actual-printer-uri", NULL, printer->uri);
+ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri-actual", NULL, printer->uri);
job->dirty = 1;
cupsdMarkDirty(CUPSD_DIRTY_JOBS);
* Start the job...
*/
+ cupsArraySave(ActiveJobs);
start_job(job, printer);
+ cupsArrayRestore(ActiveJobs);
}
}
}
cupsdLogJob(job, CUPSD_LOG_DEBUG, "Removing document files.");
remove_job_files(job);
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
+
if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate)
JobHistoryUpdate = job->history_time;
}
/* Pipes used between filters */
int envc; /* Number of environment variables */
struct stat fileinfo; /* Job file information */
- int argc; /* Number of arguments */
+ int argc = 0; /* Number of arguments */
char **argv = NULL, /* Filter command-line arguments */
filename[1024], /* Job filename */
command[1024], /* Full path to command */
* Add decompression/raw filter as needed...
*/
- if (job->compressions[job->current_file] &&
- (!job->printer->remote || job->num_files == 1))
+ if ((job->compressions[job->current_file] && (!job->printer->remote || job->num_files == 1)) ||
+ (!job->printer->remote && job->printer->raw && job->num_files > 1))
{
/*
* Add gziptoany filter to the front of the list...
cupsdLoadAllJobs(void)
{
char filename[1024]; /* Full filename of job.cache file */
- struct stat fileinfo, /* Information on job.cache file */
- dirinfo; /* Information on RequestRoot dir */
-
+ struct stat fileinfo; /* Information on job.cache file */
+ cups_dir_t *dir; /* RequestRoot dir */
+ cups_dentry_t *dent; /* Entry in RequestRoot */
+ int load_cache = 1; /* Load the job.cache file? */
/*
if (stat(filename, &fileinfo))
{
- fileinfo.st_mtime = 0;
+ /*
+ * No job.cache file...
+ */
+
+ load_cache = 0;
if (errno != ENOENT)
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to get file information for \"%s\" - %s",
filename, strerror(errno));
}
+ else if ((dir = cupsDirOpen(RequestRoot)) == NULL)
+ {
+ /*
+ * No spool directory...
+ */
- if (stat(RequestRoot, &dirinfo))
+ load_cache = 0;
+ }
+ else
{
- dirinfo.st_mtime = 0;
+ while ((dent = cupsDirRead(dir)) != NULL)
+ {
+ if (strlen(dent->filename) >= 6 && dent->filename[0] == 'c' && dent->fileinfo.st_mtime > fileinfo.st_mtime)
+ {
+ /*
+ * Job history file is newer than job.cache file...
+ */
- if (errno != ENOENT)
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to get directory information for \"%s\" - %s",
- RequestRoot, strerror(errno));
+ load_cache = 0;
+ break;
+ }
+ }
+
+ cupsDirClose(dir);
}
/*
* Load the most recent source for job data...
*/
- if (dirinfo.st_mtime > fileinfo.st_mtime)
+ if (load_cache)
{
+ /*
+ * Load the job.cache file...
+ */
+
+ load_job_cache(filename);
+ }
+ else
+ {
+ /*
+ * Load the job history files...
+ */
+
load_request_root();
load_next_job_id(filename);
}
- else
- load_job_cache(filename);
/*
* Clean out old jobs as needed...
ippSetString(job->attrs, &job->reasons, 0, "none");
}
- job->sheets = ippFindAttribute(job->attrs, "job-media-sheets-completed",
- IPP_TAG_INTEGER);
- job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
+ job->impressions = ippFindAttribute(job->attrs, "job-impressions-completed", IPP_TAG_INTEGER);
+ job->sheets = ippFindAttribute(job->attrs, "job-media-sheets-completed", IPP_TAG_INTEGER);
+ job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME);
+
+ if (!job->impressions)
+ job->impressions = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-impressions-completed", 0);
if (!job->priority)
{
if ((attr = ippFindAttribute(job->attrs, "job-printer-uri",
IPP_TAG_URI)) != NULL)
- cupsdSetString(&(attr->values[0].string.text), p->uri);
+ ippSetString(job->attrs, &attr, 0, p->uri);
cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, p, job,
"Job #%d moved from %s to %s.", job->id, olddest,
job;
job = (cupsd_job_t *)cupsArrayNext(Jobs))
{
+ if (job->printer && job->printer->temporary)
+ {
+ /*
+ * Don't save jobs on temporary printers...
+ */
+
+ continue;
+ }
+
cupsFilePrintf(fp, "<Job %d>\n", job->id);
cupsFilePrintf(fp, "State %d\n", job->state_value);
cupsFilePrintf(fp, "Created %ld\n", (long)job->creation_time);
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdSaveJob(job=%p(%d)): job->attrs=%p",
job, job->id, job->attrs);
+ if (job->printer && job->printer->temporary)
+ {
+ /*
+ * Don't save jobs on temporary printers...
+ */
+
+ job->dirty = 0;
+ return;
+ }
+
snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot, job->id);
if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm & 0600)) == NULL)
attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME);
if (attr)
- cupsdSetString(&(attr->values[0].string.text), when);
+ ippSetString(job->attrs, &attr, 0, when);
else
attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD,
"job-hold-until", NULL, when);
}
- ippSetString(job->attrs, &job->reasons, 0, "job-hold-until-specified");
+ if (strcmp(when, "no-hold"))
+ ippSetString(job->attrs, &job->reasons, 0, "job-hold-until-specified");
+ else
+ ippSetString(job->attrs, &job->reasons, 0, "none");
/*
* Update the hold time...
if (attr)
{
- attr->value_tag = IPP_TAG_KEYWORD;
- cupsdSetString(&(attr->values[0].string.text), "no-hold");
+ ippSetValueTag(job->attrs, &attr, IPP_TAG_KEYWORD);
+ ippSetString(job->attrs, &attr, 0, "no-hold");
}
default :
if (job->dirty)
cupsdSaveJob(job);
- unload_job(job);
+ if (!job->dirty)
+ unload_job(job);
}
}
/*
* Convert the status to an exit code. Due to the way the W* macros are
- * implemented on MacOS X (bug?), we have to store the exit status in a
+ * implemented on macOS (bug?), we have to store the exit status in a
* variable first and then convert...
*/
cupsArrayRemove(PrintingJobs, job);
+ /*
+ * Clear informational messages...
+ */
+
+ if (job->status_level > CUPSD_LOG_ERROR)
+ job->printer->state_message[0] = '\0';
+
/*
* Apply any PPD updates...
*/
job->printer->job = NULL;
job->printer = NULL;
-
- /*
- * Try printing another job...
- */
-
- if (printer_state != IPP_PRINTER_STOPPED)
- cupsdCheckJobs();
}
{
if (job)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Missing </Job> directive on line %d.",
- linenum);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Missing </Job> directive on line %d of %s.", linenum, filename);
continue;
}
if (!value)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Missing job ID on line %d.", linenum);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Missing job ID on line %d of %s.", linenum, filename);
continue;
}
if (jobid < 1)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Bad job ID %d on line %d.", jobid,
- linenum);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Bad job ID %d on line %d of %s.", jobid, linenum, filename);
continue;
}
{
cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Files have gone away.",
jobid);
- continue;
+
+ /*
+ * job.cache file is out-of-date compared to spool directory; load
+ * that instead...
+ */
+
+ cupsFileClose(fp);
+ load_request_root();
+ return;
}
}
else if (!job)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Missing <Job #> directive on line %d.", linenum);
+ "Missing <Job #> directive on line %d of %s.", linenum, filename);
continue;
}
else if (!_cups_strcasecmp(line, "</Job>"))
}
else if (!value)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d.", linenum);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d of %s.", linenum, filename);
continue;
}
else if (!_cups_strcasecmp(line, "State"))
if (job->num_files < 0)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Bad NumFiles value %d on line %d.",
- job->num_files, linenum);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Bad NumFiles value %d on line %d of %s.", job->num_files, linenum, filename);
job->num_files = 0;
continue;
}
if (sscanf(value, "%d%*[ \t]%15[^/]/%255s%d", &number, super, type,
&compression) != 4)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File on line %d.", linenum);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File on line %d of %s.", linenum, filename);
continue;
}
if (number < 1 || number > job->num_files)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File number %d on line %d.",
- number, linenum);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File number %d on line %d of %s.", number, linenum, filename);
continue;
}
}
}
else
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown %s directive on line %d.",
- line, linenum);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown %s directive on line %d of %s.", line, linenum, filename);
}
if (job)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
- "Missing </Job> directive on line %d.", linenum);
+ "Missing </Job> directive on line %d of %s.", linenum, filename);
cupsdDeleteJob(job, CUPSD_JOB_PURGE);
}
set_time(cupsd_job_t *job, /* I - Job to update */
const char *name) /* I - Name of attribute */
{
+ char date_name[128]; /* date-time-at-xxx */
ipp_attribute_t *attr; /* Time attribute */
time_t curtime; /* Current time */
attr->values[0].integer = curtime;
}
+ snprintf(date_name, sizeof(date_name), "date-%s", name);
+
+ if ((attr = ippFindAttribute(job->attrs, date_name, IPP_TAG_ZERO)) != NULL)
+ {
+ attr->value_tag = IPP_TAG_DATE;
+ ippSetDate(job->attrs, &attr, 0, ippTimeToDate(curtime));
+ }
+
if (!strcmp(name, "time-at-completed"))
{
job->completed_time = curtime;
"job-printer-state-message",
IPP_TAG_TEXT);
if (job->printer_message)
- cupsdSetString(&(job->printer_message->values[0].string.text), "");
+ ippSetString(job->attrs, &job->printer_message, 0, "");
ippSetString(job->attrs, &job->reasons, 0, "job-printing");
cupsdSetJobState(job, IPP_JOB_PROCESSING, CUPSD_JOB_DEFAULT, NULL);
job->attrs = NULL;
job->state = NULL;
job->reasons = NULL;
+ job->impressions = NULL;
job->sheets = NULL;
job->job_sheets = NULL;
job->printer_message = NULL;
*ptr; /* Pointer update... */
int loglevel, /* Log level for message */
event = 0; /* Events? */
+ cupsd_printer_t *printer = job->printer;
+ /* Printer */
static const char * const levels[] = /* Log levels */
{
"NONE",
cupsdLogJob(job, CUPSD_LOG_DEBUG, "PAGE: %s", message);
+ if (job->impressions)
+ {
+ if (!_cups_strncasecmp(message, "total ", 6))
+ {
+ /*
+ * Got a total count of pages from a backend or filter...
+ */
+
+ copies = atoi(message + 6);
+ copies -= ippGetInteger(job->impressions, 0); /* Just track the delta */
+ }
+ else if (!sscanf(message, "%*d%d", &copies))
+ copies = 1;
+
+ ippSetInteger(job->attrs, &job->impressions, 0, ippGetInteger(job->impressions, 0) + copies);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
+ }
+
if (job->sheets)
{
if (!_cups_strncasecmp(message, "total ", 6))
*/
copies = atoi(message + 6);
- copies -= job->sheets->values[0].integer; /* Just track the delta */
+ copies -= ippGetInteger(job->sheets, 0); /* Just track the delta */
}
else if (!sscanf(message, "%*d%d", &copies))
copies = 1;
- job->sheets->values[0].integer += copies;
+ ippSetInteger(job->attrs, &job->sheets, 0, ippGetInteger(job->sheets, 0) + copies);
+ job->dirty = 1;
+ cupsdMarkDirty(CUPSD_DIRTY_JOBS);
if (job->printer->page_limit)
cupsdUpdateQuota(job->printer, job->username, copies, 0);
cupsdLogPage(job, message);
if (job->sheets)
- cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job,
- "Printed %d page(s).", job->sheets->values[0].integer);
+ cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job, "Printed %d page(s).", ippGetInteger(job->sheets, 0));
}
else if (loglevel == CUPSD_LOG_JOBSTATE)
{
ptr = message;
if (*ptr)
- cupsdLogJob(job, loglevel, "%s", ptr);
+ cupsdLogJob(job, loglevel == CUPSD_LOG_INFO ? CUPSD_LOG_DEBUG : loglevel, "%s", ptr);
if (loglevel < CUPSD_LOG_DEBUG &&
strcmp(job->printer->state_message, ptr))
finalize_job(job, 1);
/*
- * Check for new jobs...
+ * Try printing another job...
*/
- cupsdCheckJobs();
+ if (printer->state != IPP_PRINTER_STOPPED)
+ cupsdCheckJobs();
}
}
if (job->state_value != IPP_JOB_PROCESSING &&
job->status_level == CUPSD_LOG_INFO)
{
- cupsdSetString(&(job->printer_message->values[0].string.text), "");
+ ippSetString(job->attrs, &job->printer_message, 0, "");
job->dirty = 1;
cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
else if (job->printer->state_message[0] && do_message)
{
- cupsdSetString(&(job->printer_message->values[0].string.text),
- job->printer->state_message);
+ ippSetString(job->attrs, &job->printer_message, 0, job->printer->state_message);
job->dirty = 1;
cupsdMarkDirty(CUPSD_DIRTY_JOBS);
job->dirty = 1;
cupsdMarkDirty(CUPSD_DIRTY_JOBS);
}
-
-
-/*
- * End of "$Id$".
- */