File cups-filters-f0e1fc43.patch of Package cups-filters.12896
Based on f0e1fc43dc5ec79a783cf2df82d9df827f3ccece Mon Sep 17 00:00:00 2001
From: Till Kamppeter <till.kamppeter@gmail.com>
Date: Fri, 15 Mar 2019 18:35:47 +0100
Subject: [PATCH] cups-browsed: Let distribution of jobs sent to queues with
"implicitclass" backend be done by a "job-state" CUPS notification.
---
NEWS | 9 ++
utils/cups-browsed.c | 162 +++++++++++++++++++++++++++++----------------------
2 files changed, 102 insertions(+), 69 deletions(-)
--- NEWS
+++ NEWS 2019-10-15 09:08:21.159736556 +0000
@@ -1,6 +1,15 @@
NEWS - OpenPrinting CUPS Filters v1.20.3 - 2018-04-12
-----------------------------------------------------
+BACKPORT OF V1.22.2
+ - cups-browsed: Let distribution of jobs sent to queues with
+ "implicitclass" backend (usually clusters) be done by a
+ "job-state" CUPS notification and not by
+ "printer-state-changed" any more. The "job-state"
+ notification already contains the job ID. Before we had to
+ poll the job ID from CUPS via IPP which was sometimes
+ unreliable (Issue #97).
+
CHANGES IN V1.20.3
- braille: Do not remove read permission on cups-brf. Thanks
--- utils/cups-browsed.c
+++ utils/cups-browsed.c 2019-10-15 09:05:53.830475542 +0000
@@ -2805,39 +2805,7 @@ on_printer_state_changed (CupsNotifier *
gboolean printer_is_accepting_jobs,
gpointer user_data)
{
- int i;
- char *ptr, buf[1024];
- remote_printer_t *p, *q;
- http_t *http = NULL;
- ipp_t *request, *response;
- ipp_attribute_t *attr;
- const char *pname = NULL;
- char *remote_cups_queue;
- ipp_pstate_t pstate = IPP_PRINTER_IDLE;
- int paccept = 0;
- int num_jobs, min_jobs = 99999999;
- cups_job_t *jobs = NULL;
- const char *dest_host = NULL;
- int dest_port = 0;
- char dest_name[1024];
- int dest_index = 0;
- int valid_dest_found = 0;
- char uri[HTTP_MAX_URI];
- int job_id = 0;
- int num_options;
- cups_option_t *options;
- static const char *pattrs[] =
- {
- "printer-name",
- "printer-state",
- "printer-is-accepting-jobs"
- };
- static const char *jattrs[] =
- {
- "job-id",
- "job-state"
- };
- http_t *conn = NULL;
+ char *ptr, buf[2048];
debug_printf("on_printer_state_changed() in THREAD %ld\n", pthread_self());
@@ -2916,7 +2884,94 @@ on_printer_state_changed (CupsNotifier *
strncpy(buf, text, ptr - text);
buf[ptr - text] = '\0';
debug_printf("[CUPS Notification] %s not default printer any more.\n", buf);
- } else if ((ptr = strstr(text, " state changed to processing")) != NULL) {
+ }
+}
+
+static void
+on_job_state (CupsNotifier *object,
+ const gchar *text,
+ const gchar *printer_uri,
+ const gchar *printer,
+ guint printer_state,
+ const gchar *printer_state_reasons,
+ gboolean printer_is_accepting_jobs,
+ guint job_id,
+ guint job_state,
+ const gchar *job_state_reasons,
+ const gchar *job_name,
+ guint job_impressions_completed,
+ gpointer user_data)
+{
+ int i;
+ char buf[2048];
+ remote_printer_t *p, *q;
+ http_t *http = NULL;
+ ipp_t *request, *response;
+ ipp_attribute_t *attr;
+ const char *pname = NULL;
+ char *remote_cups_queue;
+ ipp_pstate_t pstate = IPP_PRINTER_IDLE;
+ int paccept = 0;
+ int num_jobs, min_jobs = 99999999;
+ cups_job_t *jobs = NULL;
+ const char *dest_host = NULL;
+ int dest_port = 0;
+ char dest_name[1024];
+ int dest_index = 0;
+ int valid_dest_found = 0;
+ char uri[HTTP_MAX_URI];
+ /*int job_id = 0;*/
+ int num_options;
+ cups_option_t *options;
+ static const char *pattrs[] =
+ {
+ "printer-name",
+ "printer-state",
+ "printer-is-accepting-jobs"
+ };
+ http_t *conn = NULL;
+
+ debug_printf("on_job_state() in THREAD %ld\n", pthread_self());
+
+ debug_printf("[CUPS Notification] Job state changed on printer %s: %s\n",
+ printer, text);
+ debug_printf("[CUPS Notification] Printer state reasons: %s\n",
+ printer_state_reasons);
+ debug_printf("[CUPS Notification] Job ID: %d\n",
+ job_id);
+ debug_printf("[CUPS Notification] Job State: %s\n",
+ job_state_reasons);
+ debug_printf("[CUPS Notification] Job is processing: %s\n",
+ job_state == IPP_JOB_PROCESSING ? "Yes" : "No");
+
+ if (terminating) {
+ debug_printf("[CUPS Notification]: Ignoring because cups-browsed is terminating.\n");
+ return;
+ }
+
+ if (autoshutdown && autoshutdown_on == NO_JOBS) {
+ if (check_jobs() == 0) {
+ /* If auto shutdown is active for triggering on no jobs being left, we
+ schedule the shutdown in autoshutdown_timeout seconds */
+ if (!autoshutdown_exec_id) {
+ debug_printf ("No jobs there any more on printers made available by us, shutting down in %d sec...\n", autoshutdown_timeout);
+ autoshutdown_exec_id =
+ g_timeout_add_seconds (autoshutdown_timeout, autoshutdown_execute,
+ NULL);
+ }
+ } else {
+ /* If auto shutdown is active for triggering on no jobs being left, we
+ cancel a shutdown in autoshutdown_timeout seconds as there are jobs
+ again. */
+ if (autoshutdown_exec_id) {
+ debug_printf ("New jobs there on the printers made available by us, killing auto shutdown timer.\n");
+ g_source_remove(autoshutdown_exec_id);
+ autoshutdown_exec_id = 0;
+ }
+ }
+ }
+
+ if (job_id != 0 && job_state == IPP_JOB_PROCESSING) {
/* Printer started processing a job, check if it uses the implicitclass
backend and if so, we select the remote queue to which to send the job
in a way so that we get load balancing between all remote queues
@@ -3102,46 +3157,13 @@ on_printer_state_changed (CupsNotifier *
if (i == q->last_printer)
break;
}
- /* Find the ID of the current job */
- request = ippNewRequest(IPP_GET_JOBS);
- httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
- "localhost", ippPort(), "/printers/%s", printer);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
- "printer-uri", NULL, uri);
- ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes",
- sizeof(jattrs) / sizeof(jattrs[0]), NULL, jattrs);
- job_id = 0;
- if ((response = cupsDoRequest(conn, request, "/")) != NULL) {
- /* Get the current active job on this queue... */
- ipp_jstate_t jobstate = IPP_JOB_PENDING;
- for (attr = ippFirstAttribute(response); attr != NULL;
- attr = ippNextAttribute(response)) {
- if (!ippGetName(attr)) {
- if (jobstate == IPP_JOB_PROCESSING)
- break;
- else
- continue;
- }
- if (!strcmp(ippGetName(attr), "job-id") &&
- ippGetValueTag(attr) == IPP_TAG_INTEGER)
- job_id = ippGetInteger(attr, 0);
- else if (!strcmp(ippGetName(attr), "job-state") &&
- ippGetValueTag(attr) == IPP_TAG_ENUM)
- jobstate = (ipp_jstate_t)ippGetInteger(attr, 0);
- }
- if (jobstate != IPP_JOB_PROCESSING)
- job_id = 0;
- ippDelete(response);
- }
- if (job_id == 0)
- debug_printf("ERROR: could not determine ID of curremt job on %s\n",
- printer);
/* Write the selected destination host into an option of our implicit
class queue (cups-browsed-dest-printer="<dest>") so that the
implicitclass backend will pick it up */
request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER);
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", ippPort(), "/printers/%s", printer);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, uri);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
@@ -8436,6 +8458,8 @@ int main(int argc, char*argv[]) {
if (cups_notifier != NULL) {
g_signal_connect (cups_notifier, "printer-state-changed",
G_CALLBACK (on_printer_state_changed), NULL);
+ g_signal_connect (cups_notifier, "job-state",
+ G_CALLBACK (on_job_state), NULL);
g_signal_connect (cups_notifier, "printer-deleted",
G_CALLBACK (on_printer_deleted), NULL);
g_signal_connect (cups_notifier, "printer-modified",