]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/sysman.c
Remove all of the Subversion keywords from various source files.
[thirdparty/cups.git] / scheduler / sysman.c
index 945149f729fd40c58aa02f96b7678c56634f72c2..9f0319a62720badd49d6a3905cc10b568e5e55b6 100644 (file)
@@ -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/".
  */
 
 
  */
 
 #include "cupsd.h"
-#ifdef HAVE_VPROC_TRANSACTION_BEGIN
-#  include <vproc.h>
-#endif /* HAVE_VPROC_TRANSACTION_BEGIN */
 #ifdef __APPLE__
+#  include <vproc.h>
 #  include <IOKit/pwr_mgt/IOPMLib.h>
-#  ifdef HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H
-#    include <IOKit/pwr_mgt/IOPMLibPrivate.h>
-#  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 <notify.h>
 #  include <IOKit/IOKitLib.h>
 #  include <IOKit/IOMessage.h>
+#  include <IOKit/ps/IOPowerSources.h>
 #  include <IOKit/pwr_mgt/IOPMLib.h>
 #  include <SystemConfiguration/SystemConfiguration.h>
 #  include <pthread.h>
@@ -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__ */