/*
* Job management routines for the CUPS scheduler.
*
- * Copyright 2007-2016 by Apple Inc.
+ * Copyright 2007-2017 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/".
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
*/
/*
*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)
+ 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);
else if (job->file_time && job->file_time <= curtime)
{
cupsdLogJob(job, CUPSD_LOG_DEBUG, "Removing document files.");
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "curtime=%ld, job->file_time=%ld", (long)curtime, (long)job->file_time);
remove_job_files(job);
cupsdMarkDirty(CUPSD_DIRTY_JOBS);
* 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...
else
job->file_time = INT_MAX;
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "cupsdLoadJob: job->file_time=%ld, time-at-completed=%ld, JobFiles=%d", (long)job->file_time, (long)attr->values[0].integer, JobFiles);
+
if (job->file_time < JobHistoryUpdate || !JobHistoryUpdate)
JobHistoryUpdate = job->file_time;
* Update the server "busy" state...
*/
- cupsdSetBusyState();
+ cupsdSetBusyState(0);
}
else
job->file_time = INT_MAX;
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "cupsdUpdateJobs: job->file_time=%ld, time-at-completed=%ld, JobFiles=%d", (long)job->file_time, (long)attr->values[0].integer, JobFiles);
+
if (job->file_time < JobHistoryUpdate || !JobHistoryUpdate)
JobHistoryUpdate = job->file_time;
}
}
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdUpdateAllJobs: JobHistoryUpdate=%ld",
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdUpdateJobs: JobHistoryUpdate=%ld",
(long)JobHistoryUpdate);
}
/*
* 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...
*/
pwgppds = NULL;
if (pc &&
- !ippFindAttribute(job->attrs,
- "com.apple.print.DocumentTicket.PMSpoolFormat",
- IPP_TAG_ZERO) &&
+ !ippFindAttribute(job->attrs, "com.apple.print.DocumentTicket.PMSpoolFormat", IPP_TAG_ZERO) &&
!ippFindAttribute(job->attrs, "APPrinterPreset", IPP_TAG_ZERO) &&
- (ippFindAttribute(job->attrs, "print-color-mode", IPP_TAG_ZERO) ||
- ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ZERO)))
+ (ippFindAttribute(job->attrs, "print-color-mode", IPP_TAG_ZERO) || ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ZERO) || ippFindAttribute(job->attrs, "cupsPrintQuality", IPP_TAG_ZERO)))
{
/*
* Map print-color-mode and print-quality to a preset...
else
print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR;
- if ((attr = ippFindAttribute(job->attrs, "print-quality",
- IPP_TAG_ENUM)) != NULL &&
- attr->values[0].integer >= IPP_QUALITY_DRAFT &&
- attr->values[0].integer <= IPP_QUALITY_HIGH)
- print_quality = attr->values[0].integer - IPP_QUALITY_DRAFT;
+ if ((attr = ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ENUM)) != NULL)
+ {
+ ipp_quality_t pq = (ipp_quality_t)ippGetInteger(attr, 0);
+
+ if (pq >= IPP_QUALITY_DRAFT && pq <= IPP_QUALITY_HIGH)
+ print_quality = attr->values[0].integer - IPP_QUALITY_DRAFT;
+ else
+ print_quality = _PWG_PRINT_QUALITY_NORMAL;
+ }
+ else if ((attr = ippFindAttribute(job->attrs, "cupsPrintQuality", IPP_TAG_NAME)) != NULL)
+ {
+ const char *pq = ippGetString(attr, 0, NULL);
+
+ if (!_cups_strcasecmp(pq, "draft"))
+ print_quality = _PWG_PRINT_QUALITY_DRAFT;
+ else if (!_cups_strcasecmp(pq, "high"))
+ print_quality = _PWG_PRINT_QUALITY_HIGH;
+ else
+ print_quality = _PWG_PRINT_QUALITY_NORMAL;
+
+ if (!ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ENUM))
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Mapping cupsPrintQuality=%s to print-quality=%d", pq, print_quality + IPP_QUALITY_DRAFT);
+ num_pwgppds = cupsAddIntegerOption("print-quality", print_quality + IPP_QUALITY_DRAFT, num_pwgppds, &pwgppds);
+ }
+ }
else
+ {
print_quality = _PWG_PRINT_QUALITY_NORMAL;
+ }
if (pc->num_presets[print_color_mode][print_quality] == 0)
{
i --, preset ++)
{
if (!ippFindAttribute(job->attrs, preset->name, IPP_TAG_ZERO))
- num_pwgppds = cupsAddOption(preset->name, preset->value, num_pwgppds,
- &pwgppds);
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Adding preset option %s=%s", preset->name, preset->value);
+
+ num_pwgppds = cupsAddOption(preset->name, preset->value, num_pwgppds, &pwgppds);
+ }
}
}
}
if (pc)
{
+ if ((attr = ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ENUM)) != NULL)
+ {
+ int pq = ippGetInteger(attr, 0);
+ static const char * const pqs[] = { "Draft", "Normal", "High" };
+
+ if (pq >= IPP_QUALITY_DRAFT && pq <= IPP_QUALITY_HIGH)
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Mapping print-quality=%d to cupsPrintQuality=%s", pq, pqs[pq - IPP_QUALITY_DRAFT]);
+
+ num_pwgppds = cupsAddOption("cupsPrintQuality", pqs[pq - IPP_QUALITY_DRAFT], num_pwgppds, &pwgppds);
+ }
+ }
+
if (!ippFindAttribute(job->attrs, "InputSlot", IPP_TAG_ZERO) &&
!ippFindAttribute(job->attrs, "HPPaperSource", IPP_TAG_ZERO))
{
}
if (!ippFindAttribute(job->attrs, "MediaType", IPP_TAG_ZERO) &&
(ppd = _ppdCacheGetMediaType(pc, job->attrs, NULL)) != NULL)
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Mapping media to MediaType=%s", ppd);
+
num_pwgppds = cupsAddOption("MediaType", ppd, num_pwgppds, &pwgppds);
+ }
if (!ippFindAttribute(job->attrs, "PageRegion", IPP_TAG_ZERO) &&
!ippFindAttribute(job->attrs, "PageSize", IPP_TAG_ZERO) &&
(ppd = _ppdCacheGetPageSize(pc, job->attrs, NULL, &exact)) != NULL)
{
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Mapping media to Pagesize=%s", ppd);
+
num_pwgppds = cupsAddOption("PageSize", ppd, num_pwgppds, &pwgppds);
if (!ippFindAttribute(job->attrs, "media", IPP_TAG_ZERO))
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Adding media=%s", ppd);
+
num_pwgppds = cupsAddOption("media", ppd, num_pwgppds, &pwgppds);
+ }
}
if (!ippFindAttribute(job->attrs, "OutputBin", IPP_TAG_ZERO) &&
* Map output-bin to OutputBin option...
*/
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Mapping output-bin to OutputBin=%s", ppd);
+
num_pwgppds = cupsAddOption("OutputBin", ppd, num_pwgppds, &pwgppds);
}
*/
if (!strcmp(attr->values[0].string.text, "one-sided"))
- num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_1sided,
- num_pwgppds, &pwgppds);
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Mapping sizes to Duplex=%s", pc->sides_1sided);
+
+ num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_1sided, num_pwgppds, &pwgppds);
+ }
else if (!strcmp(attr->values[0].string.text, "two-sided-long-edge"))
- num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_2sided_long,
- num_pwgppds, &pwgppds);
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Mapping sizes to Duplex=%s", pc->sides_2sided_long);
+
+ num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_2sided_long, num_pwgppds, &pwgppds);
+ }
else if (!strcmp(attr->values[0].string.text, "two-sided-short-edge"))
- num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_2sided_short,
- num_pwgppds, &pwgppds);
+ {
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "Mapping sizes to Duplex=%s", pc->sides_2sided_short);
+
+ num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_2sided_short, num_pwgppds, &pwgppds);
+ }
}
/*
* Map finishings values...
*/
- num_pwgppds = _ppdCacheGetFinishingOptions(pc, job->attrs,
- IPP_FINISHINGS_NONE, num_pwgppds,
- &pwgppds);
+ num_pwgppds = _ppdCacheGetFinishingOptions(pc, job->attrs, IPP_FINISHINGS_NONE, num_pwgppds, &pwgppds);
+
+ for (i = num_pwgppds, pwgppd = pwgppds; i > 0; i --, pwgppd ++)
+ cupsdLogJob(job, CUPSD_LOG_DEBUG2, "After mapping finishings %s=%s", pwgppd->name, pwgppd->value);
}
/*
JobHistoryUpdate = job->history_time;
if (JobFiles < INT_MAX && attr)
- job->file_time = attr->values[0].integer + JobFiles;
+ job->file_time = curtime + JobFiles;
else
job->file_time = INT_MAX;
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))