Skip to content

Commit

Permalink
Save work: send Update-Active-Jobs to update the list of proxy jobs, …
Browse files Browse the repository at this point in the history
…add _papplJobCancelNoLock
  • Loading branch information
michaelrsweet committed Sep 25, 2024
1 parent 565f04e commit db5c315
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 8 deletions.
2 changes: 0 additions & 2 deletions pappl/job-accessors.c
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,4 @@ _papplJobSetStateNoLock(
if (job->state_reasons & PAPPL_JREASON_WARNINGS_DETECTED)
job->state_reasons |= PAPPL_JREASON_JOB_COMPLETED_WITH_WARNINGS;
}

_papplRWUnlock(job);
}
1 change: 1 addition & 0 deletions pappl/job-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ struct _pappl_job_s // Job data
// Functions...
//

extern void _papplJobCancelNoLock(pappl_job_t *job) _PAPPL_PRIVATE;
extern int _papplJobCompareActive(pappl_job_t *a, pappl_job_t *b) _PAPPL_PRIVATE;
extern int _papplJobCompareAll(pappl_job_t *a, pappl_job_t *b) _PAPPL_PRIVATE;
extern int _papplJobCompareCompleted(pappl_job_t *a, pappl_job_t *b) _PAPPL_PRIVATE;
Expand Down
19 changes: 15 additions & 4 deletions pappl/job.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@ papplJobCancel(pappl_job_t *job) // I - Job
_papplRWLockWrite(job->printer);
_papplRWLockWrite(job);

_papplJobCancelNoLock(job);

_papplRWUnlock(job);
_papplRWUnlock(job->printer);
}


//
// '_papplJobCancelNoLock()' - Cancel a job without locking.
//

extern void
_papplJobCancelNoLock(pappl_job_t *job) // I - Job
{
if (job->state == IPP_JSTATE_PROCESSING || (job->state == IPP_JSTATE_HELD && job->fd >= 0))
{
job->is_canceled = true;
Expand All @@ -46,10 +60,7 @@ papplJobCancel(pappl_job_t *job) // I - Job
if (!job->system->clean_time)
job->system->clean_time = time(NULL) + 60;

_papplRWUnlock(job);
_papplRWUnlock(job->printer);

papplSystemAddEvent(job->system, job->printer, job, PAPPL_EVENT_JOB_COMPLETED, NULL);
_papplSystemAddEventNoLock(job->system, job->printer, job, PAPPL_EVENT_JOB_COMPLETED, /*message*/NULL);
}


Expand Down
126 changes: 124 additions & 2 deletions pappl/printer-proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ _papplPrinterRunProxy(
{
http_t *http = NULL; // Connection to server
char resource[1024]; // Resource path
// ipp_t *request, // IPP request
// *response; // IPP response
ipp_t *request, // IPP request
*response; // IPP response
// ipp_attribute_t *attr; // Current IPP attribute
int sub_id = 0; // Event subscription ID
// int seq_number = 0; // Event sequence number
Expand Down Expand Up @@ -79,8 +79,124 @@ _papplPrinterRunProxy(
continue;
}

// If we need to update the list of proxied jobs, do so now...
if (update_jobs)
{
size_t i, // Looping var
count; // Number of values
_pappl_proxy_job_t *job, // Current proxy job
key; // Search key for proxy job
ipp_attribute_t *job_ids, // "job-ids" attribute
*job_states; // "output-device-job-states" attribute
bool check_jobs = false;
// Check for new jobs to print?

// Create an Update-Active-Jobs request...
_papplRWLockRead(printer);

request = ippNewRequest(IPP_OP_UPDATE_ACTIVE_JOBS);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", /*language*/NULL, printer->proxy_uri);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "output-device-uuid", /*language*/NULL, printer->proxy_uuid);

if ((count = cupsArrayGetCount(printer->proxy_jobs)) > 0)
{
job_ids = ippAddIntegers(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-ids", count, /*values*/NULL);
job_states = ippAddIntegers(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "output-device-job-states", count, /*values*/NULL);

for (i = 0; i < count; i ++)
{
job = (_pappl_proxy_job_t *)cupsArrayGetElement(printer->proxy_jobs, i);
ippSetInteger(request, &job_ids, i, job->parent_job_id);
ippSetInteger(request, &job_states, i, (int)papplJobGetState(job->job));
}
}

_papplRWUnlock(printer);

// Send the request...
response = cupsDoRequest(http, request, resource);

if (ippGetStatusCode(response) >= IPP_STATUS_ERROR_BAD_REQUEST)
{
papplLogPrinter(printer, PAPPL_LOGLEVEL_ERROR, "Update-Active-Jobs request failed with status %s: %s", ippErrorString(ippGetStatusCode(response)), cupsGetErrorString());
sleep(1);
continue;
}

// Parse the successful response...
update_jobs = false;

job_ids = ippFindAttribute(response, "job-ids", IPP_TAG_INTEGER);
job_states = ippFindAttribute(response, "output-device-job-states", IPP_TAG_ENUM);

// Get the jobs that have different states...
if (ippGetGroupTag(job_ids) == IPP_TAG_OPERATION && ippGetGroupTag(job_states) == IPP_TAG_OPERATION && ippGetCount(job_ids) == ippGetCount(job_states))
{
// Got a list of jobs with different states...
ipp_jstate_t local_state, // Local job state
remote_state; // Remote job state

_papplRWLockWrite(printer);

for (i = 0, count = ippGetCount(job_ids); i < count; i ++)
{
key.parent_job_id = ippGetInteger(job_ids, i);
remote_state = (ipp_jstate_t)ippGetInteger(job_states, i);

if ((job = (_pappl_proxy_job_t *)cupsArrayFind(printer->proxy_jobs, &key)) != NULL)
{
local_state = papplJobGetState(job->job);

if (remote_state >= IPP_JSTATE_CANCELED && local_state < IPP_JSTATE_CANCELED)
{
// Cancel local job
_papplRWLockWrite(job->job);
_papplJobCancelNoLock(job->job);
_papplRWUnlock(job->job);
}
else if (remote_state == IPP_JSTATE_PENDING && local_state == IPP_JSTATE_HELD)
{
// Release held job
_papplRWLockWrite(job->job);
_papplJobReleaseNoLock(job->job, /*username*/NULL);
check_jobs = true;
_papplRWUnlock(job->job);
}
}
}

// Get the jobs that no longer exist on the Infrastructure Printer...
if ((job_ids = ippFindNextAttribute(response, "job-ids", IPP_TAG_INTEGER)) != NULL && ippGetGroupTag(job_ids) == IPP_TAG_UNSUPPORTED_GROUP)
{
for (i = 0, count = ippGetCount(job_ids); i < count; i ++)
{
key.parent_job_id = ippGetInteger(job_ids, i);

if ((job = (_pappl_proxy_job_t *)cupsArrayFind(printer->proxy_jobs, &key)) != NULL)
{
// Make sure the local job is canceled so it doesn't show up again...
_papplRWLockWrite(job->job);
_papplJobCancelNoLock(job->job);
_papplRWUnlock(job->job);

// Remove the proxy job that no longer exists...
cupsArrayRemove(printer->proxy_jobs, job);
}
}
}

// If any jobs were released, see if they can be started now...
if (check_jobs)
_papplPrinterCheckJobsNoLock(printer);

_papplRWUnlock(printer);
}

// Free response from Update-Active-Jobs...
ippDelete(response);
}

// TODO: Poll for new jobs
sleep(1);
}

Expand Down Expand Up @@ -150,6 +266,7 @@ static bool // O - `true` on success, `false` on error
update_proxy_jobs(
pappl_printer_t *printer) // I - Printer
{
// Build a local list of proxied jobs, if any...
if (!printer->proxy_jobs)
{
pappl_job_t *job; // Current job
Expand All @@ -162,10 +279,14 @@ update_proxy_jobs(
// Scan existing jobs for parent-job-xxx attributes...
for (job = (pappl_job_t *)cupsArrayGetFirst(printer->all_jobs); job; job = (pappl_job_t *)cupsArrayGetNext(printer->all_jobs))
{
if (papplJobGetState(job) >= IPP_JSTATE_CANCELED)
continue;

if ((attr = ippFindAttribute(job->attrs, "parent-job-id", IPP_TAG_INTEGER)) != NULL)
{
pj.job = job;
pj.parent_job_id = ippGetInteger(attr, 0);

if ((attr = ippFindAttribute(job->attrs, "parent-job-uuid", IPP_TAG_URI)) != NULL)
{
// Saw parent-job-id and parent-job-uuid, add it...
Expand All @@ -176,6 +297,7 @@ update_proxy_jobs(
}
}


return (printer->proxy_jobs != NULL);
}

0 comments on commit db5c315

Please sign in to comment.