Example #1
0
// assembleJob prepares for printing a job by fetching the job's ticket and payload.
//
// The caller is responsible to remove the returned file.
//
// Errors are returned as a string (last return value), for reporting
// to GCP and local log.
func (gcp *GoogleCloudPrint) assembleJob(job *Job) (*cdd.CloudJobTicket, string, string, *cdd.PrintJobStateDiff) {
	ticket, err := gcp.Ticket(job.GCPJobID)
	if err != nil {
		return nil, "",
			fmt.Sprintf("Failed to get a ticket: %s", err),
			&cdd.PrintJobStateDiff{
				State: &cdd.JobState{
					Type:              cdd.JobStateAborted,
					DeviceActionCause: &cdd.DeviceActionCause{ErrorCode: cdd.DeviceActionCauseInvalidTicket},
				},
			}
	}

	file, err := ioutil.TempFile("", "cups-connector-gcp-")
	if err != nil {
		return nil, "",
			fmt.Sprintf("Failed to create a temporary file: %s", err),
			&cdd.PrintJobStateDiff{
				State: &cdd.JobState{
					Type:              cdd.JobStateAborted,
					DeviceActionCause: &cdd.DeviceActionCause{ErrorCode: cdd.DeviceActionCauseOther},
				},
			}
	}

	gcp.downloadSemaphore.Acquire()
	t := time.Now()
	// Do not check err until semaphore is released and timer is stopped.
	err = gcp.Download(file, job.FileURL)
	dt := time.Since(t)
	gcp.downloadSemaphore.Release()
	if err != nil {
		// Clean up this temporary file so the caller doesn't need extra logic.
		os.Remove(file.Name())
		return nil, "",
			fmt.Sprintf("Failed to download data: %s", err),
			&cdd.PrintJobStateDiff{
				State: &cdd.JobState{
					Type:              cdd.JobStateAborted,
					DeviceActionCause: &cdd.DeviceActionCause{ErrorCode: cdd.DeviceActionCauseDownloadFailure},
				},
			}
	}

	log.InfoJobf(job.GCPJobID, "Downloaded in %s", dt.String())
	defer file.Close()

	log.DebugJobf(job.GCPJobID, "Assembled with file %s: %+v", file.Name(), ticket.Print.Color)

	return ticket, file.Name(), "", &cdd.PrintJobStateDiff{}
}
Example #2
0
// listenNotifications handles the messages found on the channels.
func (pm *PrinterManager) listenNotifications(jobs <-chan *lib.Job, xmppMessages <-chan xmpp.PrinterNotification) {
	go func() {
		for {
			select {
			case <-pm.quit:
				return

			case job := <-jobs:
				log.DebugJobf(job.JobID, "Received job: %+v", job)
				go pm.printJob(job.CUPSPrinterName, job.Filename, job.Title, job.User, job.JobID, job.Ticket, job.UpdateJob)

			case notification := <-xmppMessages:
				log.Debugf("Received XMPP message: %+v", notification)
				if notification.Type == xmpp.PrinterNewJobs {
					if p, exists := pm.printers.GetByGCPID(notification.GCPID); exists {
						go pm.gcp.HandleJobs(&p, func() { pm.incrementJobsProcessed(false) })
					}
				}
			}
		}
	}()
}