/*
- * "$Id: sysman.c 5095 2006-02-09 16:22:48Z mike $"
+ * "$Id$"
*
- * System management definitions for the Common UNIX Printing System (CUPS).
+ * System management functions for the CUPS scheduler.
*
+ * Copyright 2007-2013 by Apple Inc.
* Copyright 2006 by Easy Software Products.
*
* These coded instructions, statements, and computer programs are the
- * property of Easy Software Products 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 missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
+ * 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.
- * cupsdUpdateSystemMonitor() - Update the current system state.
* 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.
*/
*/
#include "cupsd.h"
+#ifdef HAVE_VPROC_TRANSACTION_BEGIN
+# include <vproc.h>
+#endif /* HAVE_VPROC_TRANSACTION_BEGIN */
+#ifdef __APPLE__
+# include <IOKit/pwr_mgt/IOPMLib.h>
+# ifdef HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H
+# include <IOKit/pwr_mgt/IOPMLibPrivate.h>
+# else
+# define kIOPMAssertionTypeDenySystemSleep CFSTR("DenySystemSleep")
+# endif /* HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H */
+#endif /* __APPLE__ */
/*
- * Power management is a new addition to CUPS. Right now it is only
- * implemented on MacOS X, but essentially we use these three 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.
+ * The system management functions cover disk and power management which
+ * are primarily used on 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.
+ *
+ * Power management support is currently only implemented on MacOS 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.
+ * 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.
*/
-#ifndef __APPLE__
/*
- * 'cupsdStartSystemMonitor()' - Start monitoring for system change.
+ * Local globals...
+ */
+
+#if defined(kIOPMAssertionTypeDenySystemSleep) || defined(kIOPMAssertNetworkClientActive)
+static IOPMAssertionID keep_awake = 0; /* Keep the system awake while printing */
+#endif /* kIOPMAssertionTypeDenySystemSleep || kIOPMAssertNetworkClientActive */
+
+
+/*
+ * 'cupsdCleanDirty()' - Write dirty config and state files.
*/
void
-cupsdStartSystemMonitor(void)
+cupsdCleanDirty(void)
{
+ if (DirtyFiles & CUPSD_DIRTY_PRINTERS)
+ cupsdSaveAllPrinters();
+
+ if (DirtyFiles & CUPSD_DIRTY_CLASSES)
+ cupsdSaveAllClasses();
+
+ if (DirtyFiles & CUPSD_DIRTY_PRINTCAP)
+ cupsdWritePrintcap();
+
+ if (DirtyFiles & CUPSD_DIRTY_JOBS)
+ {
+ cupsd_job_t *job; /* Current job */
+
+ cupsdSaveAllJobs();
+
+ for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
+ job;
+ job = (cupsd_job_t *)cupsArrayNext(Jobs))
+ if (job->dirty)
+ cupsdSaveJob(job);
+ }
+
+ if (DirtyFiles & CUPSD_DIRTY_SUBSCRIPTIONS)
+ cupsdSaveAllSubscriptions();
+
+ DirtyFiles = CUPSD_DIRTY_NONE;
+ DirtyCleanTime = 0;
+
+ cupsdSetBusyState();
}
/*
- * 'cupsdStopSystemMonitor()' - Stop monitoring for system change.
+ * 'cupsdMarkDirty()' - Mark config or state files as needing a write.
*/
void
-cupsdStopSystemMonitor(void)
+cupsdMarkDirty(int what) /* I - What file(s) are dirty? */
{
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdMarkDirty(%c%c%c%c%c)",
+ (what & CUPSD_DIRTY_PRINTERS) ? 'P' : '-',
+ (what & CUPSD_DIRTY_CLASSES) ? 'C' : '-',
+ (what & CUPSD_DIRTY_PRINTCAP) ? 'p' : '-',
+ (what & CUPSD_DIRTY_JOBS) ? 'J' : '-',
+ (what & CUPSD_DIRTY_SUBSCRIPTIONS) ? 'S' : '-');
+
+ if (what == CUPSD_DIRTY_PRINTCAP && !Printcap)
+ return;
+
+ DirtyFiles |= what;
+
+ if (!DirtyCleanTime)
+ DirtyCleanTime = time(NULL) + DirtyCleanInterval;
+
+ cupsdSetBusyState();
}
/*
- * 'cupsdUpdateSystemMonitor()' - Update the current system state.
+ * 'cupsdSetBusyState()' - Let the system know when we are busy doing something.
*/
void
-cupsdUpdateSystemMonitor(void)
+cupsdSetBusyState(void)
{
+ int i; /* Looping var */
+ cupsd_job_t *job; /* Current job */
+ cupsd_printer_t *p; /* Current printer */
+ int newbusy; /* New busy state */
+ static int busy = 0; /* Current busy state */
+ static const char * const busy_text[] =
+ { /* Text for busy states */
+ "Not busy",
+ "Dirty files",
+ "Printing jobs",
+ "Printing jobs and dirty files",
+ "Active clients",
+ "Active clients and dirty files",
+ "Active clients and printing jobs",
+ "Active clients, printing jobs, and dirty files"
+ };
+#ifdef HAVE_VPROC_TRANSACTION_BEGIN
+ static vproc_transaction_t vtran = 0; /* Current busy transaction */
+#endif /* HAVE_VPROC_TRANSACTION_BEGIN */
+
+
+ /*
+ * Figure out how busy we are...
+ */
+
+ newbusy = (DirtyCleanTime ? 1 : 0) |
+ (cupsArrayCount(ActiveClients) ? 4 : 0);
+
+ for (job = (cupsd_job_t *)cupsArrayFirst(PrintingJobs);
+ job;
+ job = (cupsd_job_t *)cupsArrayNext(PrintingJobs))
+ {
+ if ((p = job->printer) != NULL)
+ {
+ for (i = 0; i < p->num_reasons; i ++)
+ if (!strcmp(p->reasons[i], "connecting-to-device"))
+ break;
+
+ if (!p->num_reasons || i >= p->num_reasons)
+ break;
+ }
+ }
+
+ if (job)
+ newbusy |= 2;
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "cupsdSetBusyState: newbusy=\"%s\", busy=\"%s\"",
+ busy_text[newbusy], busy_text[busy]);
+
+ /*
+ * Manage state changes...
+ */
+
+ if (newbusy != busy)
+ {
+ busy = newbusy;
+
+#ifdef HAVE_VPROC_TRANSACTION_BEGIN
+ if (busy && !vtran)
+ vtran = vproc_transaction_begin(NULL);
+ else if (!busy && vtran)
+ {
+ vproc_transaction_end(NULL, vtran);
+ vtran = 0;
+ }
+#endif /* HAVE_VPROC_TRANSACTION_BEGIN */
+ }
+
+#if defined(kIOPMAssertionTypeDenySystemSleep) || defined(kIOPMAssertNetworkClientActive)
+ if (cupsArrayCount(PrintingJobs) > 0 && !keep_awake)
+ {
+# ifdef kIOPMAssertNetworkClientActive
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Asserting NetworkClientActive.");
+
+ IOPMAssertionCreateWithName(kIOPMAssertNetworkClientActive,
+ kIOPMAssertionLevelOn,
+ CFSTR("org.cups.cupsd"), &keep_awake);
+
+# else
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Asserting DenySystemSleep.");
+
+ IOPMAssertionCreateWithName(kIOPMAssertionTypeDenySystemSleep,
+ kIOPMAssertionLevelOn,
+ CFSTR("org.cups.cupsd"), &keep_awake);
+
+# endif /* kIOPMAssertNetworkClientActive */
+ }
+ else if (cupsArrayCount(PrintingJobs) == 0 && keep_awake)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Releasing power assertion.");
+ IOPMAssertionRelease(keep_awake);
+ keep_awake = 0;
+ }
+#endif /* kIOPMAssertionTypeDenySystemSleep || kIOPMAssertNetworkClientActive */
}
-#endif /* !__APPLE__ */
#ifdef __APPLE__
# define SYSEVENT_NAMECHANGED 0x10 /* Computer name changed */
-/*
- * Structures...
+/*
+ * Structures...
*/
typedef struct cupsd_sysevent_s /*** System event data ****/
} cupsd_thread_data_t;
-/*
- * Local globals...
+/*
+ * Local globals...
*/
static pthread_t SysEventThread = NULL;
/* Thread to host a runloop */
static pthread_mutex_t SysEventThreadMutex = { 0 };
- /* Coordinates access to shared gloabals */
+ /* Coordinates access to shared gloabals */
static pthread_cond_t SysEventThreadCond = { 0 };
/* Thread initialization complete condition */
static CFRunLoopRef SysEventRunloop = NULL;
/* The runloop. Access must be protected! */
static CFStringRef ComputerNameKey = NULL,
/* Computer name key */
- NetworkGlobalKey = NULL,
- /* Network global key */
+ BTMMKey = NULL, /* Back to My Mac key */
+ NetworkGlobalKeyIPv4 = NULL,
+ /* Network global IPv4 key */
+ NetworkGlobalKeyIPv6 = NULL,
+ /* Network global IPv6 key */
+ NetworkGlobalKeyDNS = NULL,
+ /* Network global DNS key */
HostNamesKey = NULL,
/* Host name key */
- NetworkInterfaceKey = NULL;
+ NetworkInterfaceKeyIPv4 = NULL,
+ /* Netowrk interface key */
+ NetworkInterfaceKeyIPv6 = NULL;
/* Netowrk interface key */
+static cupsd_sysevent_t LastSysEvent; /* Last system event (for delayed sleep) */
-/*
- * Local functions...
+/*
+ * Local functions...
*/
static void *sysEventThreadEntry(void);
CFArrayRef changedKeys,
void *context);
static void sysEventTimerNotifier(CFRunLoopTimerRef timer, void *context);
+static void sysUpdate(void);
+
+
+/*
+ * 'cupsdAllowSleep()' - Tell the OS it is now OK to sleep.
+ */
+
+void
+cupsdAllowSleep(void)
+{
+ cupsdCleanDirty();
+
+ IOAllowPowerChange(LastSysEvent.powerKernelPort,
+ LastSysEvent.powerNotificationID);
+}
/*
return;
}
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStartSystemMonitor: Adding fd %d to InputSet...",
- SysEventPipes[0]);
- FD_SET(SysEventPipes[0], InputSet);
+ cupsdAddSelect(SysEventPipes[0], (cupsd_selfunc_t)sysUpdate, NULL, NULL);
/*
* Set non-blocking mode on the descriptor we will be receiving notification
if (SysEventPipes[0] >= 0)
{
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopSystemMonitor: Removing fd %d from InputSet...",
- SysEventPipes[0]);
-
- FD_CLR(SysEventPipes[0], InputSet);
-
+ cupsdRemoveSelect(SysEventPipes[0]);
cupsdClosePipe(SysEventPipes);
}
}
-/*
- * 'cupsdUpdateSystemMonitor()' - Update the current system state.
- */
-
-void
-cupsdUpdateSystemMonitor(void)
-{
- cupsd_sysevent_t sysevent; /* The system event */
- cupsd_printer_t *p; /* Printer information */
-
-
- /*
- * Drain the event pipe...
- */
-
- while (read((int)SysEventPipes[0], &sysevent, sizeof(sysevent))
- == sizeof(sysevent))
- {
- if (sysevent.event & SYSEVENT_CANSLEEP)
- {
- /*
- * If there are any active printers cancel the sleep request...
- */
-
- for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
- p;
- p = (cupsd_printer_t *)cupsArrayNext(Printers))
- if (p->job)
- break;
-
- if (p)
- {
- cupsdLogMessage(CUPSD_LOG_INFO,
- "System sleep canceled because printer %s is active",
- p->name);
- IOCancelPowerChange(sysevent.powerKernelPort,
- sysevent.powerNotificationID);
- }
- else
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG, "System wants to sleep");
- IOAllowPowerChange(sysevent.powerKernelPort,
- sysevent.powerNotificationID);
- }
- }
-
- if (sysevent.event & SYSEVENT_WILLSLEEP)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG, "System going to sleep");
-
- Sleeping = 1;
-
- cupsdStopAllJobs();
- cupsdSaveAllJobs();
-
- for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
- p;
- p = (cupsd_printer_t *)cupsArrayNext(Printers))
- {
- if (p->type & CUPS_PRINTER_REMOTE)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Deleting remote destination \"%s\"", p->name);
- cupsArraySave(Printers);
- cupsdDeletePrinter(p, 0);
- cupsArrayRestore(Printers);
- }
- else
- {
- /* TODO: Possibly update when MDNS support is added? */
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Deregistering local printer \"%s\"", p->name);
- cupsdSendBrowseDelete(p);
- }
- }
-
- IOAllowPowerChange(sysevent.powerKernelPort,
- sysevent.powerNotificationID);
- }
-
- if (sysevent.event & SYSEVENT_WOKE)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG, "System woke from sleep");
- IOAllowPowerChange(sysevent.powerKernelPort,
- sysevent.powerNotificationID);
- Sleeping = 0;
- cupsdCheckJobs();
- }
-
- if (sysevent.event & SYSEVENT_NETCHANGED)
- {
- if (!Sleeping)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "System network configuration changed");
-
- /*
- * Force an update of the list of network interfaces in 2 seconds.
- */
-
- NetIFTime = time(NULL) - 58;
-
- /*
- * Resetting browse_time before calling cupsdSendBrowseList causes
- * browse packets to be sent for local shared printers.
- */
-
- for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
- p;
- p = (cupsd_printer_t *)cupsArrayNext(Printers))
- p->browse_time = 0;
-
- cupsdSendBrowseList();
- }
- else
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "System network configuration changed; "
- "ignored while sleeping");
- }
-
- if (sysevent.event & SYSEVENT_NAMECHANGED)
- {
- if (!Sleeping)
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG, "Computer name changed");
-
- /*
- * De-register the individual printers...
- */
-
- for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
- p;
- p = (cupsd_printer_t *)cupsArrayNext(Printers))
- cupsdSendBrowseDelete(p);
-
- /*
- * Now re-register them...
- *
- * TODO: This might need updating for MDNS.
- */
-
- for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
- p;
- p = (cupsd_printer_t *)cupsArrayNext(Printers))
- p->browse_time = 0;
- }
- else
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Computer name changed; ignored while sleeping");
- }
- }
-}
-
-
/*
* 'sysEventThreadEntry()' - A thread to receive power and computer name
* change notifications.
SCDynamicStoreRef store = NULL;/* System Config dynamic store */
CFRunLoopSourceRef powerRLS = NULL,/* Power runloop source */
storeRLS = NULL;/* System Config runloop source */
- CFStringRef key[3], /* System Config keys */
- pattern[1]; /* System Config patterns */
+ CFStringRef key[6], /* System Config keys */
+ pattern[2]; /* System Config patterns */
CFArrayRef keys = NULL, /* System Config key array*/
patterns = NULL;/* System Config pattern array */
SCDynamicStoreContext storeContext; /* Dynamic store context */
bzero(&storeContext, sizeof(storeContext));
storeContext.info = &threadData;
- store = SCDynamicStoreCreate(NULL, CFSTR("cupsd"),
+ store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"),
sysEventConfigurationNotifier, &storeContext);
if (!ComputerNameKey)
- ComputerNameKey = SCDynamicStoreKeyCreateComputerName(NULL);
+ ComputerNameKey = SCDynamicStoreKeyCreateComputerName(kCFAllocatorDefault);
+
+ if (!BTMMKey)
+ BTMMKey = SCDynamicStoreKeyCreate(kCFAllocatorDefault,
+ CFSTR("Setup:/Network/BackToMyMac"));
- if (!NetworkGlobalKey)
- NetworkGlobalKey =
- SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL,
+ if (!NetworkGlobalKeyIPv4)
+ NetworkGlobalKeyIPv4 =
+ SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault,
kSCDynamicStoreDomainState,
kSCEntNetIPv4);
+ if (!NetworkGlobalKeyIPv6)
+ NetworkGlobalKeyIPv6 =
+ SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault,
+ kSCDynamicStoreDomainState,
+ kSCEntNetIPv6);
+
+ if (!NetworkGlobalKeyDNS)
+ NetworkGlobalKeyDNS =
+ SCDynamicStoreKeyCreateNetworkGlobalEntity(kCFAllocatorDefault,
+ kSCDynamicStoreDomainState,
+ kSCEntNetDNS);
+
if (!HostNamesKey)
- HostNamesKey = SCDynamicStoreKeyCreateHostNames(NULL);
+ HostNamesKey = SCDynamicStoreKeyCreateHostNames(kCFAllocatorDefault);
- if (!NetworkInterfaceKey)
- NetworkInterfaceKey =
- SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
+ if (!NetworkInterfaceKeyIPv4)
+ NetworkInterfaceKeyIPv4 =
+ SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault,
kSCDynamicStoreDomainState,
kSCCompAnyRegex,
kSCEntNetIPv4);
- if (store && ComputerNameKey && NetworkGlobalKey && HostNamesKey &&
- NetworkInterfaceKey)
+ if (!NetworkInterfaceKeyIPv6)
+ NetworkInterfaceKeyIPv6 =
+ SCDynamicStoreKeyCreateNetworkInterfaceEntity(kCFAllocatorDefault,
+ kSCDynamicStoreDomainState,
+ kSCCompAnyRegex,
+ kSCEntNetIPv6);
+
+ if (store && ComputerNameKey && HostNamesKey &&
+ NetworkGlobalKeyIPv4 && NetworkGlobalKeyIPv6 && NetworkGlobalKeyDNS &&
+ NetworkInterfaceKeyIPv4 && NetworkInterfaceKeyIPv6)
{
key[0] = ComputerNameKey;
- key[1] = NetworkGlobalKey;
- key[2] = HostNamesKey;
- pattern[0] = NetworkInterfaceKey;
-
- keys = CFArrayCreate(NULL, (const void **)key,
- sizeof(key) / sizeof(key[0]),
- &kCFTypeArrayCallBacks);
- patterns = CFArrayCreate(NULL, (const void **)pattern,
+ key[1] = BTMMKey;
+ key[2] = NetworkGlobalKeyIPv4;
+ key[3] = NetworkGlobalKeyIPv6;
+ key[4] = NetworkGlobalKeyDNS;
+ key[5] = HostNamesKey;
+
+ pattern[0] = NetworkInterfaceKeyIPv4;
+ pattern[1] = NetworkInterfaceKeyIPv6;
+
+ keys = CFArrayCreate(kCFAllocatorDefault, (const void **)key,
+ sizeof(key) / sizeof(key[0]),
+ &kCFTypeArrayCallBacks);
+
+ patterns = CFArrayCreate(kCFAllocatorDefault, (const void **)pattern,
sizeof(pattern) / sizeof(pattern[0]),
&kCFTypeArrayCallBacks);
if (keys && patterns &&
SCDynamicStoreSetNotificationKeys(store, keys, patterns))
{
- if ((storeRLS = SCDynamicStoreCreateRunLoopSource(NULL, store, 0))
- != NULL)
+ if ((storeRLS = SCDynamicStoreCreateRunLoopSource(kCFAllocatorDefault,
+ store, 0)) != NULL)
{
CFRunLoopAddSource(CFRunLoopGetCurrent(), storeRLS,
kCFRunLoopDefaultMode);
timerContext.info = &threadData;
threadData.timerRef =
- CFRunLoopTimerCreate(NULL,
- CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L),
+ CFRunLoopTimerCreate(kCFAllocatorDefault,
+ CFAbsoluteTimeGetCurrent() + (86400L * 365L * 10L),
86400L * 365L * 10L, 0, 0, sysEventTimerNotifier,
&timerContext);
CFRunLoopAddTimer(CFRunLoopGetCurrent(), threadData.timerRef,
break;
case kIOMessageSystemHasPoweredOn:
- /*
+ /*
* Because powered on is followed by a net-changed event, delay
* before sending it.
*/
case kIOMessageSystemWillNotPowerOff:
case kIOMessageSystemWillNotSleep:
-#ifdef kIOMessageSystemWillPowerOn
+# ifdef kIOMessageSystemWillPowerOn
case kIOMessageSystemWillPowerOn:
-#endif /* kIOMessageSystemWillPowerOn */
+# endif /* kIOMessageSystemWillPowerOn */
default:
sendit = 0;
break;
if (sendit == 1)
{
- /*
+ /*
* Send the event to the main thread now.
*/
}
else
{
- /*
+ /*
* Send the event to the main thread after 1 to 2 seconds.
*/
/*
- * 'sysEventConfigurationNotifier()' - Computer name changed notification
+ * 'sysEventConfigurationNotifier()' - Network configuration change notification
* callback.
*/
threadData = (cupsd_thread_data_t *)context;
-
+
(void)store; /* anti-compiler-warning-code */
CFRange range = CFRangeMake(0, CFArrayGetCount(changedKeys));
- if (CFArrayContainsValue(changedKeys, range, ComputerNameKey))
+ if (CFArrayContainsValue(changedKeys, range, ComputerNameKey) ||
+ CFArrayContainsValue(changedKeys, range, BTMMKey))
threadData->sysevent.event |= SYSEVENT_NAMECHANGED;
-
- if (CFArrayContainsValue(changedKeys, range, NetworkGlobalKey) ||
- CFArrayContainsValue(changedKeys, range, HostNamesKey) ||
- CFArrayContainsValue(changedKeys, range, NetworkInterfaceKey))
+ else
+ {
threadData->sysevent.event |= SYSEVENT_NETCHANGED;
+ /*
+ * Indicate the network interface list needs updating...
+ */
+
+ NetIFUpdate = 1;
+ }
+
/*
- * Because we registered for several different kinds of change notifications
- * this callback usually gets called several times in a row. We use a timer to
+ * Because we registered for several different kinds of change notifications
+ * this callback usually gets called several times in a row. We use a timer to
* de-bounce these so we only end up generating one event for the main thread.
*/
- CFRunLoopTimerSetNextFireDate(threadData->timerRef,
- CFAbsoluteTimeGetCurrent() + 2);
+ CFRunLoopTimerSetNextFireDate(threadData->timerRef,
+ CFAbsoluteTimeGetCurrent() + 5);
}
cupsd_thread_data_t *threadData; /* Thread context data */
+ (void)timer;
+
threadData = (cupsd_thread_data_t *)context;
/*
threadData->sysevent.event = 0;
}
}
+
+
+/*
+ * 'sysUpdate()' - Update the current system state.
+ */
+
+static void
+sysUpdate(void)
+{
+ int i; /* Looping var */
+ cupsd_sysevent_t sysevent; /* The system event */
+ cupsd_printer_t *p; /* Printer information */
+
+
+ /*
+ * Drain the event pipe...
+ */
+
+ while (read((int)SysEventPipes[0], &sysevent, sizeof(sysevent))
+ == sizeof(sysevent))
+ {
+ if (sysevent.event & SYSEVENT_CANSLEEP)
+ {
+ /*
+ * 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)...
+ */
+
+ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+ p;
+ p = (cupsd_printer_t *)cupsArrayNext(Printers))
+ {
+ if (p->job)
+ {
+ for (i = 0; i < p->num_reasons; i ++)
+ if (!strcmp(p->reasons[i], "connecting-to-device"))
+ break;
+
+ if (!p->num_reasons || i >= p->num_reasons)
+ break;
+ }
+ }
+
+ if (p)
+ {
+ cupsdLogMessage(CUPSD_LOG_INFO,
+ "System sleep canceled because printer %s is active",
+ p->name);
+ IOCancelPowerChange(sysevent.powerKernelPort,
+ sysevent.powerNotificationID);
+ }
+ else
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "System wants to sleep");
+ IOAllowPowerChange(sysevent.powerKernelPort,
+ sysevent.powerNotificationID);
+ }
+ }
+
+ if (sysevent.event & SYSEVENT_WILLSLEEP)
+ {
+ 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 (keep_awake)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Releasing dark wake assertion.");
+ IOPMAssertionRelease(keep_awake);
+ keep_awake = 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
+ * we'll take more drastic measures...
+ */
+
+ if (cupsArrayCount(PrintingJobs) == 0)
+ 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)...
+ */
+
+ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+ p;
+ p = (cupsd_printer_t *)cupsArrayNext(Printers))
+ {
+ if (p->job)
+ {
+ for (i = 0; i < p->num_reasons; i ++)
+ if (!strcmp(p->reasons[i], "connecting-to-device"))
+ break;
+
+ if (!p->num_reasons || i >= p->num_reasons)
+ break;
+ }
+ }
+
+ if (p)
+ {
+ LastSysEvent = sysevent;
+ SleepJobs = time(NULL) + 10;
+ }
+ else
+ {
+ IOAllowPowerChange(sysevent.powerKernelPort,
+ sysevent.powerNotificationID);
+ }
+ }
+ }
+
+ if (sysevent.event & SYSEVENT_WOKE)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "System woke from sleep");
+ IOAllowPowerChange(sysevent.powerKernelPort,
+ sysevent.powerNotificationID);
+ Sleeping = 0;
+
+#ifdef kIOPMAssertionTypeDenySystemSleep
+ if (cupsArrayCount(PrintingJobs) > 0 && !keep_awake)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Asserting dark wake.");
+ IOPMAssertionCreateWithName(kIOPMAssertionTypeDenySystemSleep,
+ kIOPMAssertionLevelOn,
+ CFSTR("org.cups.cupsd"), &keep_awake);
+ }
+#endif /* kIOPMAssertionTypeDenySystemSleep */
+
+ cupsdCheckJobs();
+ }
+
+ if (sysevent.event & SYSEVENT_NETCHANGED)
+ {
+ if (!Sleeping)
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "System network configuration changed");
+ else
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "System network configuration changed; "
+ "ignored while sleeping");
+ }
+
+ if (sysevent.event & SYSEVENT_NAMECHANGED)
+ {
+ 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...
+ */
+
+ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+ p;
+ p = (cupsd_printer_t *)cupsArrayNext(Printers))
+ cupsdRegisterPrinter(p);
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "Computer name or BTMM domains changed; ignored while "
+ "sleeping");
+ }
+ }
+}
#endif /* __APPLE__ */
/*
- * End of "$Id: sysman.c 5095 2006-02-09 16:22:48Z mike $".
+ * End of "$Id$".
*/