func NewPrinterManager(cups *cups.CUPS, gcp *gcp.GoogleCloudPrint, privet *privet.Privet, snmp *snmp.SNMPManager, printerPollInterval time.Duration, cupsQueueSize uint, jobFullUsername, ignoreRawPrinters bool, shareScope string, jobs <-chan *lib.Job, xmppNotifications <-chan xmpp.PrinterNotification) (*PrinterManager, error) { var printers *lib.ConcurrentPrinterMap var queuedJobsCount map[string]uint var err error if gcp != nil { // Get all GCP printers. var gcpPrinters []lib.Printer gcpPrinters, queuedJobsCount, err = gcp.ListPrinters() if err != nil { return nil, err } // Organize the GCP printers into a map. for i := range gcpPrinters { gcpPrinters[i].CUPSJobSemaphore = lib.NewSemaphore(cupsQueueSize) } printers = lib.NewConcurrentPrinterMap(gcpPrinters) } else { printers = lib.NewConcurrentPrinterMap(nil) } // Construct. pm := PrinterManager{ cups: cups, gcp: gcp, privet: privet, snmp: snmp, printers: printers, jobStatsMutex: sync.Mutex{}, jobsDone: 0, jobsError: 0, jobsInFlightMutex: sync.Mutex{}, jobsInFlight: make(map[string]struct{}), cupsQueueSize: cupsQueueSize, jobFullUsername: jobFullUsername, ignoreRawPrinters: ignoreRawPrinters, shareScope: shareScope, quit: make(chan struct{}), } // Sync once before returning, to make sure things are working. // Ignore privet updates this first time because Privet always starts // with zero printers. if err = pm.syncPrinters(true); err != nil { return nil, err } // Initialize Privet printers. if privet != nil { for _, printer := range pm.printers.GetAll() { err := privet.AddPrinter(printer, pm.printers.GetByCUPSName) if err != nil { log.WarningPrinterf(printer.Name, "Failed to register locally: %s", err) } else { log.InfoPrinterf(printer.Name, "Registered locally") } } } pm.syncPrintersPeriodically(printerPollInterval) pm.listenNotifications(jobs, xmppNotifications) if gcp != nil { for gcpPrinterID := range queuedJobsCount { p, _ := printers.GetByGCPID(gcpPrinterID) go gcp.HandleJobs(&p, func() { pm.incrementJobsProcessed(false) }) } } return &pm, nil }
func (pm *PrinterManager) applyDiff(diff *lib.PrinterDiff, ch chan<- lib.Printer, ignorePrivet bool) { switch diff.Operation { case lib.RegisterPrinter: if pm.gcp != nil { if err := pm.gcp.Register(&diff.Printer); err != nil { log.ErrorPrinterf(diff.Printer.Name, "Failed to register: %s", err) break } log.InfoPrinterf(diff.Printer.Name+" "+diff.Printer.GCPID, "Registered in the cloud") if pm.gcp.CanShare() { if err := pm.gcp.Share(diff.Printer.GCPID, pm.shareScope); err != nil { log.ErrorPrinterf(diff.Printer.Name, "Failed to share: %s", err) } else { log.InfoPrinterf(diff.Printer.Name, "Shared") } } } diff.Printer.CUPSJobSemaphore = lib.NewSemaphore(pm.cupsQueueSize) if pm.privet != nil && !ignorePrivet { err := pm.privet.AddPrinter(diff.Printer, pm.printers.GetByCUPSName) if err != nil { log.WarningPrinterf(diff.Printer.Name, "Failed to register locally: %s", err) } else { log.InfoPrinterf(diff.Printer.Name, "Registered locally") } } ch <- diff.Printer return case lib.UpdatePrinter: if pm.gcp != nil { if err := pm.gcp.Update(diff); err != nil { log.ErrorPrinterf(diff.Printer.Name+" "+diff.Printer.GCPID, "Failed to update: %s", err) } else { log.InfoPrinterf(diff.Printer.Name+" "+diff.Printer.GCPID, "Updated in the cloud") } } if pm.privet != nil && !ignorePrivet && diff.DefaultDisplayNameChanged { err := pm.privet.UpdatePrinter(diff) if err != nil { log.WarningPrinterf(diff.Printer.Name, "Failed to update locally: %s", err) } else { log.InfoPrinterf(diff.Printer.Name, "Updated locally") } } ch <- diff.Printer return case lib.DeletePrinter: pm.cups.RemoveCachedPPD(diff.Printer.Name) if pm.gcp != nil { if err := pm.gcp.Delete(diff.Printer.GCPID); err != nil { log.ErrorPrinterf(diff.Printer.Name+" "+diff.Printer.GCPID, "Failed to delete from the cloud: %s", err) break } log.InfoPrinterf(diff.Printer.Name+" "+diff.Printer.GCPID, "Deleted from the cloud") } if pm.privet != nil && !ignorePrivet { err := pm.privet.DeletePrinter(diff.Printer.Name) if err != nil { log.WarningPrinterf(diff.Printer.Name, "Failed to delete: %s", err) } else { log.InfoPrinterf(diff.Printer.Name, "Deleted locally") } } case lib.NoChangeToPrinter: ch <- diff.Printer return } ch <- lib.Printer{} }