X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fcups.git;a=blobdiff_plain;f=scheduler%2Fsysman.c;h=9f0319a62720badd49d6a3905cc10b568e5e55b6;hp=945149f729fd40c58aa02f96b7678c56634f72c2;hb=503b54c9302c8de6207e079a80a89a787eb612ea;hpb=a29fd7ddb5d63688a4d44d08e4ab16428921c321 diff --git a/scheduler/sysman.c b/scheduler/sysman.c index 945149f72..9f0319a62 100644 --- a/scheduler/sysman.c +++ b/scheduler/sysman.c @@ -1,34 +1,14 @@ /* - * "$Id: sysman.c 7928 2008-09-10 22:14:22Z mike $" + * System management functions for the CUPS scheduler. * - * System management functions for the CUPS scheduler. + * Copyright 2007-2014 by Apple Inc. + * Copyright 2006 by Easy Software Products. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 2006 by Easy Software Products. - * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdCleanDirty() - Write dirty config and state files. - * cupsdMarkDirty() - Mark config or state files as needing a - * write. - * cupsdSetBusyState() - Let the system know when we are busy - * doing something. - * cupsdAllowSleep() - Tell the OS it is now OK to sleep. - * cupsdStartSystemMonitor() - Start monitoring for system change. - * cupsdStopSystemMonitor() - Stop monitoring for system change. - * sysEventThreadEntry() - A thread to receive power and computer - * name change notifications. - * sysEventPowerNotifier() - Handle power notification events. - * sysEventConfigurationNotifier() - Computer name changed notification - * callback. - * sysEventTimerNotifier() - Handle delayed event notifications. - * sysUpdate() - Update the current system state. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ @@ -37,42 +17,28 @@ */ #include "cupsd.h" -#ifdef HAVE_VPROC_TRANSACTION_BEGIN -# include -#endif /* HAVE_VPROC_TRANSACTION_BEGIN */ #ifdef __APPLE__ +# include # include -# ifdef HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H -# include -# endif /* HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H */ #endif /* __APPLE__ */ /* * The system management functions cover disk and power management which - * are primarily used on portable computers. + * are primarily used for portable computers. * * Disk management involves delaying the write of certain configuration * and state files to minimize the number of times the disk has to spin - * up. + * up or flash to be written to. * - * Power management support is currently only implemented on MacOS X, but + * Power management support is currently only implemented on OS X, but * essentially we use four functions to let the OS know when it is OK to * put the system to sleep, typically when we are not in the middle of - * printing a job. - * - * Once put to sleep, we invalidate all remote printers since it is common - * to wake up in a new location/on a new wireless network. - */ - -/* - * Local globals... + * printing a job. And on OS X we can also "sleep print" - basically the + * system only wakes up long enough to service network requests and process + * print jobs. */ -#ifdef kIOPMAssertionTypeDenySystemSleep -static IOPMAssertionID dark_wake = 0; /* "Dark wake" assertion for sharing */ -#endif /* kIOPMAssertionTypeDenySystemSleep */ - /* * 'cupsdCleanDirty()' - Write dirty config and state files. @@ -162,9 +128,10 @@ cupsdSetBusyState(void) "Active clients and printing jobs", "Active clients, printing jobs, and dirty files" }; -#ifdef HAVE_VPROC_TRANSACTION_BEGIN +#ifdef __APPLE__ static vproc_transaction_t vtran = 0; /* Current busy transaction */ -#endif /* HAVE_VPROC_TRANSACTION_BEGIN */ + static IOPMAssertionID keep_awake = 0;/* Keep the system awake while printing */ +#endif /* __APPLE__ */ /* @@ -204,7 +171,7 @@ cupsdSetBusyState(void) { busy = newbusy; -#ifdef HAVE_VPROC_TRANSACTION_BEGIN +#ifdef __APPLE__ if (busy && !vtran) vtran = vproc_transaction_begin(NULL); else if (!busy && vtran) @@ -212,24 +179,25 @@ cupsdSetBusyState(void) vproc_transaction_end(NULL, vtran); vtran = 0; } -#endif /* HAVE_VPROC_TRANSACTION_BEGIN */ +#endif /* __APPLE__ */ } -#ifdef kIOPMAssertionTypeDenySystemSleep - if (cupsArrayCount(PrintingJobs) > 0 && !dark_wake) +#ifdef __APPLE__ + if (cupsArrayCount(PrintingJobs) > 0 && !keep_awake) { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Asserting dark wake."); - IOPMAssertionCreateWithName(kIOPMAssertionTypeDenySystemSleep, + cupsdLogMessage(CUPSD_LOG_DEBUG, "Asserting NetworkClientActive."); + + IOPMAssertionCreateWithName(kIOPMAssertNetworkClientActive, kIOPMAssertionLevelOn, - CFSTR("org.cups.cupsd"), &dark_wake); + CFSTR("org.cups.cupsd"), &keep_awake); } - else if (cupsArrayCount(PrintingJobs) == 0 && dark_wake) + else if (cupsArrayCount(PrintingJobs) == 0 && keep_awake) { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Releasing dark wake assertion."); - IOPMAssertionRelease(dark_wake); - dark_wake = 0; + cupsdLogMessage(CUPSD_LOG_DEBUG, "Releasing power assertion."); + IOPMAssertionRelease(keep_awake); + keep_awake = 0; } -#endif /* kIOPMAssertionTypeDenySystemSleep */ +#endif /* __APPLE__ */ } @@ -244,8 +212,10 @@ cupsdSetBusyState(void) * Include MacOS-specific headers... */ +# include # include # include +# include # include # include # include @@ -310,6 +280,8 @@ static CFStringRef ComputerNameKey = NULL, NetworkInterfaceKeyIPv6 = NULL; /* Netowrk interface key */ static cupsd_sysevent_t LastSysEvent; /* Last system event (for delayed sleep) */ +static int NameChanged = 0;/* Did we get a 'name changed' event during sleep? */ +static int PSToken = 0; /* Power source notifications */ /* @@ -325,6 +297,7 @@ static void sysEventConfigurationNotifier(SCDynamicStoreRef store, void *context); static void sysEventTimerNotifier(CFRunLoopTimerRef timer, void *context); static void sysUpdate(void); +static void sysUpdateNames(void); /* @@ -336,6 +309,7 @@ cupsdAllowSleep(void) { cupsdCleanDirty(); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep."); IOAllowPowerChange(LastSysEvent.powerKernelPort, LastSysEvent.powerNotificationID); } @@ -351,6 +325,8 @@ cupsdStartSystemMonitor(void) int flags; /* fcntl flags on pipe */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartSystemMonitor()"); + if (cupsdOpenPipe(SysEventPipes)) { cupsdLogMessage(CUPSD_LOG_ERROR, "System event monitor pipe() failed - %s!", @@ -375,6 +351,15 @@ cupsdStartSystemMonitor(void) pthread_mutex_init(&SysEventThreadMutex, NULL); pthread_cond_init(&SysEventThreadCond, NULL); pthread_create(&SysEventThread, NULL, (void *(*)())sysEventThreadEntry, NULL); + + /* + * Monitor for power source changes via dispatch queue... + */ + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartSystemMonitor: IOPSGetTimeRemainingEstimate=%f", IOPSGetTimeRemainingEstimate()); + ACPower = IOPSGetTimeRemainingEstimate() == kIOPSTimeRemainingUnlimited; + notify_register_dispatch(kIOPSNotifyPowerSource, &PSToken, dispatch_get_main_queue(), ^(int t) { (void)t; + ACPower = IOPSGetTimeRemainingEstimate() == kIOPSTimeRemainingUnlimited; }); } @@ -388,6 +373,8 @@ cupsdStopSystemMonitor(void) CFRunLoopRef rl; /* The event handler runloop */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStopSystemMonitor()"); + if (SysEventThread) { /* @@ -418,6 +405,12 @@ cupsdStopSystemMonitor(void) cupsdRemoveSelect(SysEventPipes[0]); cupsdClosePipe(SysEventPipes); } + + if (PSToken != 0) + { + notify_cancel(PSToken); + PSToken = 0; + } } @@ -658,18 +651,19 @@ sysEventPowerNotifier( switch (messageType) { - case kIOMessageCanSystemPowerOff: - case kIOMessageCanSystemSleep: + case kIOMessageCanSystemPowerOff : + case kIOMessageCanSystemSleep : threadData->sysevent.event |= SYSEVENT_CANSLEEP; break; - case kIOMessageSystemWillRestart: - case kIOMessageSystemWillPowerOff: - case kIOMessageSystemWillSleep: + case kIOMessageSystemWillRestart : + case kIOMessageSystemWillPowerOff : + case kIOMessageSystemWillSleep : threadData->sysevent.event |= SYSEVENT_WILLSLEEP; + threadData->sysevent.event &= ~SYSEVENT_WOKE; break; - case kIOMessageSystemHasPoweredOn: + case kIOMessageSystemHasPoweredOn : /* * Because powered on is followed by a net-changed event, delay * before sending it. @@ -679,16 +673,62 @@ sysEventPowerNotifier( threadData->sysevent.event |= SYSEVENT_WOKE; break; - case kIOMessageSystemWillNotPowerOff: - case kIOMessageSystemWillNotSleep: + case kIOMessageSystemWillNotPowerOff : + case kIOMessageSystemWillNotSleep : # ifdef kIOMessageSystemWillPowerOn - case kIOMessageSystemWillPowerOn: + case kIOMessageSystemWillPowerOn : # endif /* kIOMessageSystemWillPowerOn */ default: sendit = 0; break; } + switch (messageType) + { + case kIOMessageCanSystemPowerOff : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageCanSystemPowerOff message."); + break; + case kIOMessageCanSystemSleep : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageCannSystemSleep message."); + break; + case kIOMessageSystemWillRestart : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillRestart message."); + break; + case kIOMessageSystemWillPowerOff : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillPowerOff message."); + break; + case kIOMessageSystemWillSleep : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillSleep message."); + break; + case kIOMessageSystemHasPoweredOn : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemHasPoweredOn message."); + break; + case kIOMessageSystemWillNotPowerOff : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillNotPowerOff message."); + break; + case kIOMessageSystemWillNotSleep : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillNotSleep message."); + break; +# ifdef kIOMessageSystemWillPowerOn + case kIOMessageSystemWillPowerOn : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillPowerOn message."); + break; +# endif /* kIOMessageSystemWillPowerOn */ + default: + cupsdLogMessage(CUPSD_LOG_DEBUG, "Got unknown power message %d.", + (int)messageType); + break; + } + if (sendit == 0) IOAllowPowerChange(threadData->sysevent.powerKernelPort, (long)messageArgument); @@ -816,8 +856,9 @@ sysUpdate(void) { /* * If there are active printers that don't have the connecting-to-device - * printer-state-reason then cancel the sleep request (i.e. this reason - * indicates a job that is not yet connected to the printer)... + * or cups-waiting-for-job-completed printer-state-reason then cancel the + * sleep request, i.e., these reasons indicate a job that is not actively + * doing anything... */ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); @@ -827,7 +868,8 @@ sysUpdate(void) if (p->job) { for (i = 0; i < p->num_reasons; i ++) - if (!strcmp(p->reasons[i], "connecting-to-device")) + if (!strcmp(p->reasons[i], "connecting-to-device") || + !strcmp(p->reasons[i], "cups-waiting-for-job-completed")) break; if (!p->num_reasons || i >= p->num_reasons) @@ -838,14 +880,14 @@ sysUpdate(void) if (p) { cupsdLogMessage(CUPSD_LOG_INFO, - "System sleep canceled because printer %s is active", + "System sleep canceled because printer %s is active.", p->name); IOCancelPowerChange(sysevent.powerKernelPort, sysevent.powerNotificationID); } else { - cupsdLogMessage(CUPSD_LOG_DEBUG, "System wants to sleep"); + cupsdLogMessage(CUPSD_LOG_DEBUG, "System wants to sleep."); IOAllowPowerChange(sysevent.powerKernelPort, sysevent.powerNotificationID); } @@ -853,50 +895,30 @@ sysUpdate(void) if (sysevent.event & SYSEVENT_WILLSLEEP) { - cupsdLogMessage(CUPSD_LOG_DEBUG, "System going to sleep"); + cupsdLogMessage(CUPSD_LOG_DEBUG, "System going to sleep."); Sleeping = 1; - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Deregistering local printer \"%s\"", p->name); - cupsdDeregisterPrinter(p, 0); - } - cupsdCleanDirty(); -#ifdef kIOPMAssertionTypeDenySystemSleep - /* - * Remove our assertion as needed since the user wants the system to - * sleep (different than idle sleep)... - */ - - if (dark_wake) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Releasing dark wake assertion."); - IOPMAssertionRelease(dark_wake); - dark_wake = 0; - } -#endif /* kIOPMAssertionTypeDenySystemSleep */ - /* * If we have no printing jobs, allow the power change immediately. - * Otherwise set the SleepJobs time to 15 seconds in the future when + * Otherwise set the SleepJobs time to 10 seconds in the future when * we'll take more drastic measures... */ if (cupsArrayCount(PrintingJobs) == 0) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep."); IOAllowPowerChange(sysevent.powerKernelPort, sysevent.powerNotificationID); + } else { /* * If there are active printers that don't have the connecting-to-device - * printer-state-reason then delay the sleep request (i.e. this reason - * indicates a job that is not yet connected to the printer)... + * or cups-waiting-for-job-completed printer-state-reasons then delay the + * sleep request, i.e., these reasons indicate a job is active... */ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); @@ -906,7 +928,8 @@ sysUpdate(void) if (p->job) { for (i = 0; i < p->num_reasons; i ++) - if (!strcmp(p->reasons[i], "connecting-to-device")) + if (!strcmp(p->reasons[i], "connecting-to-device") || + !strcmp(p->reasons[i], "cups-waiting-for-job-completed")) break; if (!p->num_reasons || i >= p->num_reasons) @@ -916,11 +939,16 @@ sysUpdate(void) if (p) { + cupsdLogMessage(CUPSD_LOG_INFO, + "System sleep delayed because printer %s is active.", + p->name); + LastSysEvent = sysevent; SleepJobs = time(NULL) + 10; } else { + cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep."); IOAllowPowerChange(sysevent.powerKernelPort, sysevent.powerNotificationID); } @@ -929,78 +957,113 @@ sysUpdate(void) if (sysevent.event & SYSEVENT_WOKE) { - cupsdLogMessage(CUPSD_LOG_DEBUG, "System woke from sleep"); + cupsdLogMessage(CUPSD_LOG_DEBUG, "System woke from sleep."); IOAllowPowerChange(sysevent.powerKernelPort, sysevent.powerNotificationID); Sleeping = 0; -#ifdef kIOPMAssertionTypeDenySystemSleep - if (cupsArrayCount(PrintingJobs) > 0 && !dark_wake) + /* + * Make sure jobs that were queued prior to the system going to sleep don't + * get canceled right away... + */ + + if (MaxJobTime > 0) { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Asserting dark wake."); - IOPMAssertionCreateWithName(kIOPMAssertionTypeDenySystemSleep, - kIOPMAssertionLevelOn, - CFSTR("org.cups.cupsd"), &dark_wake); + cupsd_job_t *job; /* Current job */ + + for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs); + job; + job = (cupsd_job_t *)cupsArrayNext(ActiveJobs)) + { + if (job->cancel_time) + { + ipp_attribute_t *cancel_after = ippFindAttribute(job->attrs, + "job-cancel-after", + IPP_TAG_INTEGER); + + if (cancel_after) + job->cancel_time = time(NULL) + ippGetInteger(cancel_after, 0); + else + job->cancel_time = time(NULL) + MaxJobTime; + } + } } -#endif /* kIOPMAssertionTypeDenySystemSleep */ + + if (NameChanged) + sysUpdateNames(); cupsdCheckJobs(); } if (sysevent.event & SYSEVENT_NETCHANGED) { - if (!Sleeping) + if (Sleeping) cupsdLogMessage(CUPSD_LOG_DEBUG, - "System network configuration changed"); + "System network configuration changed - " + "ignored while sleeping."); else cupsdLogMessage(CUPSD_LOG_DEBUG, - "System network configuration changed; " - "ignored while sleeping"); + "System network configuration changed."); } if (sysevent.event & SYSEVENT_NAMECHANGED) { - if (!Sleeping) + if (Sleeping) { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Computer name or BTMM domains changed"); - - /* - * De-register the individual printers... - */ - - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - cupsdDeregisterPrinter(p, 1); - -# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - /* - * Update the computer name and BTMM domain list... - */ - - cupsdUpdateDNSSDName(); -# endif /* HAVE_DNSSD || HAVE_AVAHI */ - - /* - * Now re-register them... - */ + NameChanged = 1; - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - cupsdRegisterPrinter(p); + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Computer name or BTMM domains changed - ignored while " + "sleeping."); } else + { cupsdLogMessage(CUPSD_LOG_DEBUG, - "Computer name or BTMM domains changed; ignored while " - "sleeping"); + "Computer name or BTMM domains changed."); + + sysUpdateNames(); + } } } } -#endif /* __APPLE__ */ /* - * End of "$Id: sysman.c 7928 2008-09-10 22:14:22Z mike $". + * 'sysUpdateNames()' - Update computer and/or BTMM domains. */ + +static void +sysUpdateNames(void) +{ + cupsd_printer_t *p; /* Current printer */ + + + NameChanged = 0; + + /* + * De-register the individual printers... + */ + + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); + p; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + cupsdDeregisterPrinter(p, 1); + +# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) + /* + * Update the computer name and BTMM domain list... + */ + + cupsdUpdateDNSSDName(); +# endif /* HAVE_DNSSD || HAVE_AVAHI */ + + /* + * Now re-register them... + */ + + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); + p; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + cupsdRegisterPrinter(p); +} +#endif /* __APPLE__ */