Blob Blame Raw
diff -up cups-1.7.5/CHANGES.txt.str4396 cups-1.7.5/CHANGES.txt
diff -up cups-1.7.5/scheduler/ipp.c.str4396 cups-1.7.5/scheduler/ipp.c
--- cups-1.7.5/scheduler/ipp.c.str4396	2014-08-20 16:56:29.012022421 +0100
+++ cups-1.7.5/scheduler/ipp.c	2014-08-20 16:56:38.535084011 +0100
@@ -6595,6 +6595,7 @@ get_jobs(cupsd_client_t  *con,		/* I - C
   cupsd_job_t	*job;			/* Current job pointer */
   cupsd_printer_t *printer;		/* Printer */
   cups_array_t	*list;			/* Which job list... */
+  int		delete_list = 0;	/* Delete the list afterwards? */
   cups_array_t	*ra,			/* Requested attributes array */
 		*exclude;		/* Private attributes array */
   cupsd_policy_t *policy;		/* Current policy */
@@ -6694,13 +6695,15 @@ get_jobs(cupsd_client_t  *con,		/* I - C
   {
     job_comparison = 1;
     job_state      = IPP_JOB_CANCELED;
-    list           = Jobs;
+    list           = cupsdGetCompletedJobs(printer);
+    delete_list    = 1;
   }
   else if (!strcmp(attr->values[0].string.text, "aborted"))
   {
     job_comparison = 0;
     job_state      = IPP_JOB_ABORTED;
-    list           = Jobs;
+    list           = cupsdGetCompletedJobs(printer);
+    delete_list    = 1;
   }
   else if (!strcmp(attr->values[0].string.text, "all"))
   {
@@ -6712,7 +6715,8 @@ get_jobs(cupsd_client_t  *con,		/* I - C
   {
     job_comparison = 0;
     job_state      = IPP_JOB_CANCELED;
-    list           = Jobs;
+    list           = cupsdGetCompletedJobs(printer);
+    delete_list    = 1;
   }
   else if (!strcmp(attr->values[0].string.text, "pending"))
   {
@@ -6919,6 +6923,9 @@ get_jobs(cupsd_client_t  *con,		/* I - C
 
   cupsArrayDelete(ra);
 
+  if (delete_list)
+    cupsArrayDelete(list);
+
   con->response->request.status.status_code = IPP_OK;
 }
 
diff -up cups-1.7.5/scheduler/job.c.str4396 cups-1.7.5/scheduler/job.c
--- cups-1.7.5/scheduler/job.c.str4396	2014-08-20 16:56:29.013022427 +0100
+++ cups-1.7.5/scheduler/job.c	2014-08-20 16:56:38.537084024 +0100
@@ -130,6 +130,7 @@ static mime_filter_t	gziptoany_filter =
  */
 
 static int	compare_active_jobs(void *first, void *second, void *data);
+static int	compare_completed_jobs(void *first, void *second, void *data);
 static int	compare_jobs(void *first, void *second, void *data);
 static void	dump_job_history(cupsd_job_t *job);
 static void	finalize_job(cupsd_job_t *job, int set_job_state);
@@ -1568,6 +1569,30 @@ cupsdFindJob(int id)			/* I - Job ID */
 
 
 /*
+ * 'cupsdGetCompletedJobs()'- Generate a completed jobs list.
+ */
+
+cups_array_t *				/* O - Array of jobs */
+cupsdGetCompletedJobs(
+    cupsd_printer_t *p)			/* I - Printer */
+{
+  cups_array_t	*list;			/* Array of jobs */
+  cupsd_job_t	*job;			/* Current job */
+
+
+  list = cupsArrayNew(compare_completed_jobs, NULL);
+
+  for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
+       job;
+       job = (cupsd_job_t *)cupsArrayNext(Jobs))
+    if ((!p || !_cups_strcasecmp(p->name, job->dest)) && job->state_value >= IPP_JOB_STOPPED && job->completed_time)
+      cupsArrayAdd(list, job);
+
+  return (list);
+}
+
+
+/*
  * 'cupsdGetPrinterJobCount()' - Get the number of pending, processing,
  *                               or held jobs in a printer or class.
  */
@@ -1766,6 +1791,8 @@ cupsdLoadJob(cupsd_job_t *job)		/* I - J
       (attr = ippFindAttribute(job->attrs, "time-at-completed",
 			       IPP_TAG_INTEGER)) != NULL)
   {
+    job->completed_time = attr->values[0].integer;
+
     if (JobHistory < INT_MAX)
       job->history_time = attr->values[0].integer + JobHistory;
     else
@@ -2257,8 +2284,11 @@ cupsdSaveAllJobs(void)
   {
     cupsFilePrintf(fp, "<Job %d>\n", job->id);
     cupsFilePrintf(fp, "State %d\n", job->state_value);
+    if (job->completed_time)
+      cupsFilePrintf(fp, "Completed %ld\n", (long)job->completed_time);
     cupsFilePrintf(fp, "Priority %d\n", job->priority);
-    cupsFilePrintf(fp, "HoldUntil %d\n", (int)job->hold_until);
+    if (job->hold_until)
+      cupsFilePrintf(fp, "HoldUntil %ld\n", (long)job->hold_until);
     cupsFilePrintf(fp, "Username %s\n", job->username);
     cupsFilePrintf(fp, "Destination %s\n", job->dest);
     cupsFilePrintf(fp, "DestType %d\n", job->dtype);
@@ -2993,6 +3023,28 @@ compare_active_jobs(void *first,	/* I -
 
 
 /*
+ * 'compare_completed_jobs()' - Compare the job IDs and completion times of two jobs.
+ */
+
+static int				/* O - Difference */
+compare_completed_jobs(void *first,	/* I - First job */
+                       void *second,	/* I - Second job */
+		       void *data)	/* I - App data (not used) */
+{
+  int	diff;				/* Difference */
+
+
+  (void)data;
+
+  if ((diff = ((cupsd_job_t *)second)->completed_time -
+              ((cupsd_job_t *)first)->completed_time) != 0)
+    return (diff);
+  else
+    return (((cupsd_job_t *)first)->id - ((cupsd_job_t *)second)->id);
+}
+
+
+/*
  * 'compare_jobs()' - Compare the job IDs of two jobs.
  */
 
@@ -4268,6 +4320,14 @@ load_job_cache(const char *filename)	/*
 
       if (job->state_value <= IPP_JOB_STOPPED && cupsdLoadJob(job))
 	cupsArrayAdd(ActiveJobs, job);
+      else if (job->state_value > IPP_JOB_STOPPED)
+      {
+        if (!job->completed_time)
+	{
+	  cupsdLoadJob(job);
+	  unload_job(job);
+	}
+      }
 
       job = NULL;
     }
@@ -4285,9 +4345,13 @@ load_job_cache(const char *filename)	/*
       else if (job->state_value > IPP_JOB_COMPLETED)
         job->state_value = IPP_JOB_COMPLETED;
     }
+    else if (!_cups_strcasecmp(line, "Completed"))
+    {
+      job->completed_time = strtol(value, NULL, 10);
+    }
     else if (!_cups_strcasecmp(line, "HoldUntil"))
     {
-      job->hold_until = atoi(value);
+      job->hold_until = strtol(value, NULL, 10);
     }
     else if (!_cups_strcasecmp(line, "Priority"))
     {
@@ -4625,6 +4689,8 @@ set_time(cupsd_job_t *job,		/* I - Job t
 
   if (!strcmp(name, "time-at-completed"))
   {
+    job->completed_time = curtime;
+
     if (JobHistory < INT_MAX && attr)
       job->history_time = attr->values[0].integer + JobHistory;
     else
diff -up cups-1.7.5/scheduler/job.h.str4396 cups-1.7.5/scheduler/job.h
--- cups-1.7.5/scheduler/job.h.str4396	2014-08-20 16:56:29.013022427 +0100
+++ cups-1.7.5/scheduler/job.h	2014-08-20 16:56:38.538084031 +0100
@@ -54,6 +54,7 @@ struct cupsd_job_s			/**** Job request *
   ipp_attribute_t	*sheets;	/* job-media-sheets-completed */
   time_t		access_time,	/* Last access time */
 			cancel_time,	/* When to cancel/send SIGTERM */
+			completed_time,	/* When job was completed (0 if not) */
 			file_time,	/* Job file retain time */
 			history_time,	/* Job history retain time */
 			hold_until,	/* Hold expiration date/time */
@@ -156,6 +157,7 @@ extern void		cupsdDeleteJob(cupsd_job_t
 			               cupsd_jobaction_t action);
 extern cupsd_job_t	*cupsdFindJob(int id);
 extern void		cupsdFreeAllJobs(void);
+extern cups_array_t	*cupsdGetCompletedJobs(cupsd_printer_t *p);
 extern int		cupsdGetPrinterJobCount(const char *dest);
 extern int		cupsdGetUserJobCount(const char *username);
 extern void		cupsdLoadAllJobs(void);
diff -up cups-1.7.5/systemv/lpstat.c.str4396 cups-1.7.5/systemv/lpstat.c
--- cups-1.7.5/systemv/lpstat.c.str4396	2014-05-22 14:59:21.000000000 +0100
+++ cups-1.7.5/systemv/lpstat.c	2014-08-20 16:56:38.539084037 +0100
@@ -1316,7 +1316,8 @@ show_jobs(const char *dests,		/* I - Des
   const char	*dest,			/* Pointer into job-printer-uri */
 		*username,		/* Pointer to job-originating-user-name */
 		*title,			/* Pointer to job-name */
-		*message;		/* Pointer to job-printer-state-message */
+		*message,		/* Pointer to job-printer-state-message */
+		*time_at;		/* time-at-xxx attribute name to use */
   int		rank,			/* Rank in queue */
 		jobid,			/* job-id */
 		size;			/* job-k-octets */
@@ -1332,7 +1333,8 @@ show_jobs(const char *dests,		/* I - Des
 		  "job-printer-state-message",
 		  "job-printer-uri",
 		  "job-state-reasons",
-		  "time-at-creation"
+		  "time-at-creation",
+		  "time-at-completed"
 		};
 
 
@@ -1398,6 +1400,13 @@ show_jobs(const char *dests,		/* I - Des
     * Loop through the job list and display them...
     */
 
+    if (!strcmp(which, "aborted") ||
+        !strcmp(which, "canceled") ||
+        !strcmp(which, "completed"))
+      time_at = "time-at-completed";
+    else
+      time_at = "time-at-creation";
+
     rank = -1;
 
     for (attr = response->attrs; attr != NULL; attr = attr->next)
@@ -1433,8 +1442,7 @@ show_jobs(const char *dests,		/* I - Des
         else if (!strcmp(attr->name, "job-k-octets") &&
 		 attr->value_tag == IPP_TAG_INTEGER)
 	  size = attr->values[0].integer;
-        else if (!strcmp(attr->name, "time-at-creation") &&
-		 attr->value_tag == IPP_TAG_INTEGER)
+        else if (!strcmp(attr->name, time_at) && attr->value_tag == IPP_TAG_INTEGER)
 	  jobtime = attr->values[0].integer;
         else if (!strcmp(attr->name, "job-printer-state-message") &&
 	         attr->value_tag == IPP_TAG_TEXT)
diff -up cups-1.7.5/test/5.5-lp.sh.str4396 cups-1.7.5/test/5.5-lp.sh
--- cups-1.7.5/test/5.5-lp.sh.str4396	2013-11-06 20:09:03.000000000 +0000
+++ cups-1.7.5/test/5.5-lp.sh	2014-08-20 16:56:38.540084044 +0100
@@ -79,6 +79,19 @@ echo ""
 
 ./waitjobs.sh
 
+echo "LPSTAT Completed Jobs Order Test"
+echo ""
+echo "    lpstat -W completed -o"
+$VALGRIND ../systemv/lpstat -W completed -o | tee $BASE/lpstat-completed.txt
+if test "`uniq -d $BASE/lpstat-completed.txt`" != ""; then
+	echo "    FAILED"
+	exit 1
+else
+	echo "    PASSED"
+fi
+echo ""
+
+
 #
 # End of "$Id: 5.5-lp.sh 11396 2013-11-06 20:09:03Z msweet $".
 #