X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=scheduler%2Fjob.c;h=61cda44e2fea198e32f4d097d0a0ecdb525d6ade;hb=be7581b6e3a6b0b44255ddb533a30db03ad5c337;hp=b18c7ee199315a76dcb58246c028d982a9b23108;hpb=ac7c59abca0c3bff5d189e15720066d6a235a28c;p=thirdparty%2Fcups.git diff --git a/scheduler/job.c b/scheduler/job.c index b18c7ee19..61cda44e2 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -1,16 +1,10 @@ /* - * "$Id$" - * * Job management routines for the CUPS scheduler. * - * Copyright 2007-2015 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. */ /* @@ -229,6 +223,7 @@ cupsdCheckJobs(void) *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); @@ -322,6 +317,25 @@ cupsdCheckJobs(void) ((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... */ @@ -359,7 +373,7 @@ cupsdCheckJobs(void) "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; @@ -369,16 +383,14 @@ cupsdCheckJobs(void) 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); @@ -440,6 +452,7 @@ cupsdCleanJobs(void) 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); @@ -732,8 +745,8 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ * 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... @@ -1727,6 +1740,8 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ 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; @@ -1831,6 +1846,8 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ if (!job->impressions) job->impressions = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-impressions-completed", 0); + if (!job->sheets) + job->sheets = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-media-sheets-completed", 0); if (!job->priority) { @@ -2749,7 +2766,7 @@ cupsdSetJobState( * Update the server "busy" state... */ - cupsdSetBusyState(); + cupsdSetBusyState(0); } @@ -2808,7 +2825,8 @@ cupsdUnloadCompletedJobs(void) if (job->dirty) cupsdSaveJob(job); - unload_job(job); + if (!job->dirty) + unload_job(job); } } @@ -2859,12 +2877,14 @@ cupsdUpdateJobs(void) 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); } @@ -3132,6 +3152,13 @@ finalize_job(cupsd_job_t *job, /* I - Job */ cupsdStatBufDelete(job->status_buffer); job->status_buffer = NULL; + /* + * Log the final impression (page) count... + */ + + snprintf(buffer, sizeof(buffer), "total %d", ippGetInteger(job->impressions, 0)); + cupsdLogPage(job, buffer); + /* * Process the exit status... */ @@ -3189,7 +3216,7 @@ finalize_job(cupsd_job_t *job, /* I - 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... */ @@ -3527,6 +3554,13 @@ finalize_job(cupsd_job_t *job, /* I - Job */ cupsArrayRemove(PrintingJobs, job); + /* + * Clear informational messages... + */ + + if (job->status_level > CUPSD_LOG_ERROR) + job->printer->state_message[0] = '\0'; + /* * Apply any PPD updates... */ @@ -3595,12 +3629,9 @@ get_options(cupsd_job_t *job, /* I - Job */ 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... @@ -3613,13 +3644,36 @@ get_options(cupsd_job_t *job, /* I - Job */ 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) { @@ -3652,14 +3706,30 @@ get_options(cupsd_job_t *job, /* I - Job */ 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)) { @@ -3669,16 +3739,26 @@ get_options(cupsd_job_t *job, /* I - Job */ } 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) && @@ -3692,6 +3772,8 @@ get_options(cupsd_job_t *job, /* I - Job */ * 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); } @@ -3704,23 +3786,33 @@ get_options(cupsd_job_t *job, /* I - Job */ */ 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); } /* @@ -4577,7 +4669,7 @@ set_time(cupsd_job_t *job, /* I - Job to update */ 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; @@ -4866,7 +4958,6 @@ void update_job(cupsd_job_t *job) /* I - Job to check */ { int i; /* Looping var */ - int copies; /* Number of copies printed */ char message[CUPSD_SB_BUFFER_SIZE], /* Message text */ *ptr; /* Pointer update... */ @@ -4904,6 +4995,10 @@ update_job(cupsd_job_t *job) /* I - Job to check */ if (loglevel == CUPSD_LOG_PAGE) { + int impressions = ippGetInteger(job->impressions, 0); + /* Number of impressions printed */ + int delta; /* Number of impressions added */ + /* * Page message; send the message to the page_log file and update the * job sheet count... @@ -4911,51 +5006,57 @@ update_job(cupsd_job_t *job) /* I - Job to check */ cupsdLogJob(job, CUPSD_LOG_DEBUG, "PAGE: %s", message); - if (job->impressions) + if (!_cups_strncasecmp(message, "total ", 6)) { - if (!_cups_strncasecmp(message, "total ", 6)) - { - /* - * Got a total count of pages from a backend or filter... - */ + /* + * Got a total count of pages from a backend or filter... + */ + + int total = atoi(message + 6); /* Total impressions */ - copies = atoi(message + 6); - copies -= ippGetInteger(job->impressions, 0); /* Just track the delta */ + if (total > impressions) + { + delta = total - impressions; + impressions = total; } - else if (!sscanf(message, "%*d%d", &copies)) + else + delta = 0; + } + else + { + /* + * Add the number of copies to the impression count... + */ + + int copies; /* Number of copies */ + + if (!sscanf(message, "%*d%d", &copies) || copies <= 0) copies = 1; - ippSetInteger(job->attrs, &job->impressions, 0, ippGetInteger(job->impressions, 0) + copies); - job->dirty = 1; - cupsdMarkDirty(CUPSD_DIRTY_JOBS); + delta = copies; + impressions += copies; } + if (job->impressions) + ippSetInteger(job->attrs, &job->impressions, 0, impressions); + if (job->sheets) { - if (!_cups_strncasecmp(message, "total ", 6)) - { - /* - * Got a total count of pages from a backend or filter... - */ - - copies = atoi(message + 6); - copies -= ippGetInteger(job->sheets, 0); /* Just track the delta */ - } - else if (!sscanf(message, "%*d%d", &copies)) - copies = 1; + const char *sides = ippGetString(ippFindAttribute(job->attrs, "sides", IPP_TAG_KEYWORD), 0, NULL); - ippSetInteger(job->attrs, &job->sheets, 0, ippGetInteger(job->sheets, 0) + copies); - job->dirty = 1; - cupsdMarkDirty(CUPSD_DIRTY_JOBS); + if (sides && strcmp(sides, "one-sided")) + ippSetInteger(job->attrs, &job->sheets, 0, impressions / 2); + else + ippSetInteger(job->attrs, &job->sheets, 0, impressions); - if (job->printer->page_limit) - cupsdUpdateQuota(job->printer, job->username, copies, 0); + cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job, "Printed %d page(s).", ippGetInteger(job->sheets, 0)); } - cupsdLogPage(job, message); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); - if (job->sheets) - cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job, "Printed %d page(s).", ippGetInteger(job->sheets, 0)); + if (job->printer->page_limit) + cupsdUpdateQuota(job->printer, job->username, delta, 0); } else if (loglevel == CUPSD_LOG_JOBSTATE) { @@ -5166,7 +5267,7 @@ update_job(cupsd_job_t *job) /* I - Job to check */ 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)) @@ -5368,8 +5469,3 @@ update_job_attrs(cupsd_job_t *job, /* I - Job to update */ job->dirty = 1; cupsdMarkDirty(CUPSD_DIRTY_JOBS); } - - -/* - * End of "$Id$". - */