/*
- * "$Id: job.c 181 2006-06-22 20:01:18Z jlovell $"
+ * "$Id: job.c 5974 2006-09-20 18:42:37Z mike $"
*
* Job management routines for the Common UNIX Printing System (CUPS).
*
*/
void
-cupsdCancelJob(cupsd_job_t *job, /* I - Job to cancel */
- int purge) /* I - Purge jobs? */
+cupsdCancelJob(cupsd_job_t *job, /* I - Job to cancel */
+ int purge, /* I - Purge jobs? */
+ ipp_jstate_t newstate) /* I - New job state */
{
int i; /* Looping var */
char filename[1024]; /* Job filename */
+ cupsd_printer_t *printer; /* Printer used by job */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCancelJob: id = %d", job->id);
* Stop any processes that are working on the current job...
*/
+ printer = job->printer;
+
if (job->state_value == IPP_JOB_PROCESSING)
cupsdStopJob(job, 0);
cupsdLoadJob(job);
if (job->attrs)
- job->state->values[0].integer = IPP_JOB_CANCELLED;
+ job->state->values[0].integer = newstate;
- job->state_value = IPP_JOB_CANCELLED;
+ job->state_value = newstate;
set_time(job, "time-at-completed");
+ /*
+ * Send any pending notifications and then expire them...
+ */
+
+ switch (newstate)
+ {
+ default :
+ break;
+
+ case IPP_JOB_CANCELED :
+ cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, printer, job,
+ purge ? "Job purged." : "Job canceled.");
+ break;
+
+ case IPP_JOB_ABORTED :
+ cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, printer, job,
+ "Job aborted; please consult the error_log file "
+ "for details.");
+ break;
+
+ case IPP_JOB_COMPLETED :
+ /*
+ * Clear the printer's state_message and state_reasons and move on...
+ */
+
+ printer->state_message[0] = '\0';
+
+ cupsdSetPrinterReasons(printer, "");
+ cupsdSetPrinterState(printer, IPP_PRINTER_IDLE, 0);
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, printer, job,
+ "Job completed.");
+ break;
+ }
+
cupsdExpireSubscriptions(NULL, job);
/*
* Cancel all jobs matching this destination/user...
*/
- cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job,
- purge ? "Job purged." : "Job canceled.");
-
- cupsdCancelJob(job, purge);
+ cupsdCancelJob(job, purge, IPP_JOB_CANCELED);
}
cupsdCheckJobs();
*/
cupsdLogMessage(CUPSD_LOG_WARN,
- "Printer/class %s has gone away; cancelling job %d!",
+ "Printer/class %s has gone away; canceling job %d!",
job->dest, job->id);
cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job,
"Job canceled because the destination printer/class has "
"gone away.");
- cupsdCancelJob(job, 1);
+ cupsdCancelJob(job, 1, IPP_JOB_ABORTED);
}
else if (printer)
{
for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
job && cupsArrayCount(Jobs) >= MaxJobs;
job = (cupsd_job_t *)cupsArrayNext(Jobs))
- if (job->state_value >= IPP_JOB_CANCELLED)
- cupsdCancelJob(job, 1);
+ if (job->state_value >= IPP_JOB_CANCELED)
+ cupsdCancelJob(job, 1, IPP_JOB_CANCELED);
}
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFinishJob: job->status is %d",
job->status);
- if (job->status_buffer && job->current_file >= job->num_files)
+ if (job->status_buffer &&
+ (job->status < 0 || job->current_file >= job->num_files))
{
/*
* Close the pipe and clear the input bit.
cupsdStopJob(job, 0);
- if (!(printer->type & CUPS_PRINTER_REMOTE) ||
- (printer->type & CUPS_PRINTER_IMPLICIT))
+ if (job->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT))
{
/*
* Mark the job as pending again - we'll retry on another
"after %d tries.",
job->id, JobRetryLimit);
- cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, printer, job,
- "Job canceled since it could not be sent after %d "
- "tries.",
- JobRetryLimit);
-
- cupsdCancelJob(job, 0);
+ cupsdCancelJob(job, 0, IPP_JOB_ABORTED);
}
else
{
*/
set_hold_until(job, time(NULL) + JobRetryInterval);
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_STATE, job->printer, job,
+ "Job held due to fax errors; please consult "
+ "the error_log file for details.");
+ cupsdSetPrinterState(printer, IPP_PRINTER_IDLE, 0);
}
}
else if (!strcmp(printer->error_policy, "abort-job"))
- cupsdCancelJob(job, 0);
+ cupsdCancelJob(job, 0, IPP_JOB_ABORTED);
+ else
+ {
+ cupsdSetPrinterState(printer, IPP_PRINTER_STOPPED, 1);
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job,
+ "Job stopped due to backend errors; please consult "
+ "the error_log file for details.");
+ }
break;
case CUPS_BACKEND_CANCEL :
* Cancel the job...
*/
- cupsdCancelJob(job, 0);
+ cupsdCancelJob(job, 0, IPP_JOB_CANCELED);
break;
case CUPS_BACKEND_HOLD :
*/
cupsdStopJob(job, 0);
+
cupsdSetJobHoldUntil(job, "indefinite");
+
+ job->state->values[0].integer = IPP_JOB_HELD;
+ job->state_value = IPP_JOB_HELD;
+
cupsdSaveJob(job);
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job,
+ "Job held due to backend errors; please consult "
+ "the error_log file for details.");
break;
case CUPS_BACKEND_STOP :
*/
cupsdStopJob(job, 0);
+
+ job->state->values[0].integer = IPP_JOB_PENDING;
+ job->state_value = IPP_JOB_PENDING;
+
cupsdSaveJob(job);
cupsdSetPrinterState(printer, IPP_PRINTER_STOPPED, 1);
+
+ cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job,
+ "Job stopped due to backend errors; please consult "
+ "the error_log file for details.");
break;
case CUPS_BACKEND_AUTH_REQUIRED :
cupsdStopJob(job, 0);
+
cupsdSetJobHoldUntil(job, "authenticated");
+
+ job->state->values[0].integer = IPP_JOB_HELD;
+ job->state_value = IPP_JOB_HELD;
+
cupsdSaveJob(job);
cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job,
* Close out this job...
*/
- cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, printer, job,
- "Job completed successfully.");
-
job_history = JobHistory && !(job->dtype & CUPS_PRINTER_REMOTE);
- cupsdCancelJob(job, 0);
-
- if (job_history)
- {
- job->state->values[0].integer = IPP_JOB_COMPLETED;
- job->state_value = IPP_JOB_COMPLETED;
- cupsdSaveJob(job);
- }
-
- /*
- * Clear the printer's state_message and state_reasons and move on...
- */
-
- printer->state_message[0] = '\0';
-
- cupsdSetPrinterReasons(printer, "");
-
+ cupsdCancelJob(job, 0, IPP_JOB_COMPLETED);
cupsdCheckJobs();
}
}
cupsdHoldSignals();
- cupsdStopAllJobs();
+ cupsdStopAllJobs(1);
cupsdSaveAllJobs();
for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
cups_file_t *fp; /* Job file */
int fileid; /* Current file ID */
ipp_attribute_t *attr; /* Job attribute */
+ char scheme[32], /* Scheme portion of URI */
+ username[64], /* Username portion of URI */
+ host[HTTP_MAX_HOST],
+ /* Host portion of URI */
+ resource[HTTP_MAX_URI];
+ /* Resource portion of URI */
+ int port; /* Port portion of URI */
const char *dest; /* Destination */
mime_type_t **filetypes; /* New filetypes array */
int *compressions; /* New compressions array */
return;
}
- if ((dest = cupsdValidateDest(attr->values[0].string.text, &(job->dtype),
+ httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text, scheme,
+ sizeof(scheme), username, sizeof(username), host,
+ sizeof(host), &port, resource, sizeof(resource));
+
+ if ((dest = cupsdValidateDest(host, resource, &(job->dtype),
NULL)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
if (job->state_value == IPP_JOB_STOPPED || job->num_files)
{
+ ipp_jstate_t old_state; /* Old job state */
+
+
cupsdLoadJob(job);
+ old_state = job->state_value;
+
job->tries = 0;
job->state->values[0].integer = IPP_JOB_PENDING;
job->state_value = IPP_JOB_PENDING;
+
cupsdSaveJob(job);
+
+ if (old_state > IPP_JOB_STOPPED)
+ cupsArrayAdd(ActiveJobs, job);
+
cupsdCheckJobs();
}
}
*/
void
-cupsdStopAllJobs(void)
+cupsdStopAllJobs(int force) /* I - 1 = Force all filters to stop */
{
cupsd_job_t *job; /* Current job */
job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
if (job->state_value == IPP_JOB_PROCESSING)
{
- cupsdStopJob(job, 1);
+ cupsdStopJob(job, force);
job->state->values[0].integer = IPP_JOB_PENDING;
job->state_value = IPP_JOB_PENDING;
}
FilterLevel -= job->cost;
- if (job->status < 0 &&
- !(job->dtype & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT)) &&
- !(job->printer->type & CUPS_PRINTER_FAX) &&
- !strcmp(job->printer->error_policy, "stop-printer"))
- cupsdSetPrinterState(job->printer, IPP_PRINTER_STOPPED, 1);
- else if (job->printer->state != IPP_PRINTER_STOPPED)
+ if (job->printer->state == IPP_PRINTER_PROCESSING)
cupsdSetPrinterState(job->printer, IPP_PRINTER_IDLE, 0);
- cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStopJob: printer state is %d",
- job->printer->state);
-
job->state->values[0].integer = IPP_JOB_STOPPED;
job->state_value = IPP_JOB_STOPPED;
job->printer->job = NULL;
int copies; /* Number of copies printed */
char message[1024], /* Message text */
*ptr; /* Pointer update... */
- int loglevel; /* Log level for message */
+ int loglevel, /* Log level for message */
+ event = 0; /* Events? */
while ((ptr = cupsdStatBufUpdate(job->status_buffer, &loglevel,
{
cupsdSetPrinterReasons(job->printer, message);
cupsdAddPrinterHistory(job->printer);
+ event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
}
else if (loglevel == CUPSD_LOG_ATTR)
{
cupsdSetString(&job->printer->recoverable, ptr);
cupsdAddPrinterHistory(job->printer);
+ event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
}
else if (!strncmp(message, "recovered:", 10))
{
cupsdSetString(&job->printer->recoverable, ptr);
cupsdAddPrinterHistory(job->printer);
+ event |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
}
#endif /* __APPLE__ */
else if (loglevel <= CUPSD_LOG_INFO)
break;
}
- if (ptr == NULL)
+ if ((event & CUPSD_EVENT_PRINTER_STATE_CHANGED))
+ cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE_CHANGED, job->printer, NULL,
+ (job->printer->type & CUPS_PRINTER_CLASS) ?
+ "Class \"%s\" state changed." :
+ "Printer \"%s\" state changed.",
+ job->printer->name);
+
+ if (ptr == NULL && !job->status_buffer->bufused)
{
/*
* See if all of the filters and the backend have returned their
int diff; /* Difference */
- if ((diff = ((cupsd_job_t *)first)->priority -
- ((cupsd_job_t *)second)->priority) != 0)
+ if ((diff = ((cupsd_job_t *)second)->priority -
+ ((cupsd_job_t *)first)->priority) != 0)
return (diff);
else
return (((cupsd_job_t *)first)->id - ((cupsd_job_t *)second)->id);
}
else if (!strcasecmp(line, "State"))
{
- job->state_value = atoi(value);
+ job->state_value = (ipp_jstate_t)atoi(value);
if (job->state_value < IPP_JOB_PENDING)
job->state_value = IPP_JOB_PENDING;
cupsArrayAdd(Jobs, job);
if (job->state_value <= IPP_JOB_STOPPED)
- cupsArrayAdd(ActiveJobs,job);
+ cupsArrayAdd(ActiveJobs, job);
else
unload_job(job);
}
/* PRINTER env variable */
rip_max_cache[255];
/* RIP_MAX_CACHE env variable */
- int remote_job; /* Remote print job? */
static char *options = NULL;/* Full list of options */
static int optlength = 0; /* Length of option buffer */
if (job->num_files == 0)
{
- cupsdLogMessage(CUPSD_LOG_ERROR, "Job ID %d has no files! Cancelling it!",
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Job ID %d has no files! Canceling it!",
job->id);
- cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job,
- "Job canceled because it has no files.");
-
- cupsdCancelJob(job, 0);
+ cupsdCancelJob(job, 0, IPP_JOB_ABORTED);
return;
}
job->current_file ++;
if (job->current_file == job->num_files)
- {
- cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job,
- "Job canceled because it has no files that can be "
- "printed.");
-
- cupsdCancelJob(job, 0);
- }
+ cupsdCancelJob(job, 0, IPP_JOB_ABORTED);
return;
}
FilterLevel += job->cost;
- /*
- * Determine if we are printing to a remote printer...
- */
-
- remote_job = printer->raw && job->num_files > 1 &&
- !strncmp(printer->device_uri, "ipp://", 6);
-
/*
* Add decompression filters, if any...
*/
- if (!remote_job && job->compressions[job->current_file])
+ if (!printer->raw && job->compressions[job->current_file])
{
/*
* Add gziptoany filter to the front of the list...
job->current_file ++;
if (job->current_file == job->num_files)
- {
- cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job,
- "Job canceled because the print file could not be "
- "decompressed.");
-
- cupsdCancelJob(job, 0);
- }
+ cupsdCancelJob(job, 0, IPP_JOB_ABORTED);
return;
}
job->current_file ++;
if (job->current_file == job->num_files)
- {
- cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job,
- "Job canceled because the port monitor could not be "
- "added.");
-
- cupsdCancelJob(job, 0);
- }
+ cupsdCancelJob(job, 0, IPP_JOB_ABORTED);
return;
}
FilterLevel -= job->cost;
- cupsdAddEvent(CUPSD_EVENT_JOB_COMPLETED, job->printer, job,
- "Job canceled because the server ran out of memory.");
-
- cupsdCancelJob(job, 0);
+ cupsdCancelJob(job, 0, IPP_JOB_ABORTED);
return;
}
* For remote jobs, we send all of the files in the argument list.
*/
- if (remote_job)
+ if (printer->remote && job->num_files > 1)
argv = calloc(7 + job->num_files, sizeof(char *));
else
argv = calloc(8, sizeof(char *));
argv[4] = copies;
argv[5] = options;
- if (remote_job)
+ if (printer->remote && job->num_files > 1)
{
for (i = 0; i < job->num_files; i ++)
{
envp[envc ++] = device_uri;
envp[envc ++] = printer_name;
- if ((filter = (mime_filter_t *)cupsArrayLast(filters)) != NULL)
+ if (!printer->remote &&
+ (filter = (mime_filter_t *)cupsArrayLast(filters)) != NULL)
{
snprintf(final_content_type, sizeof(final_content_type),
"FINAL_CONTENT_TYPE=%s/%s",
cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] envp[%d]=\"DEVICE_URI=%s\"",
job->id, i, sani_uri);
- if (remote_job)
+ if (printer->remote)
job->current_file = job->num_files;
else
job->current_file ++;
slot, filterfds[slot][0], filterfds[slot][1]);
cupsdClosePipe(filterfds[slot]);
- if (remote_job)
+ if (printer->remote && job->num_files > 1)
{
for (i = 0; i < job->num_files; i ++)
free(argv[i + 6]);
cupsArrayDelete(filters);
- if (remote_job)
+ if (printer->remote && job->num_files > 1)
{
for (i = 0; i < job->num_files; i ++)
free(argv[i + 6]);
/*
- * End of "$Id: job.c 181 2006-06-22 20:01:18Z jlovell $".
+ * End of "$Id: job.c 5974 2006-09-20 18:42:37Z mike $".
*/