]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/sysman.c
Merge changes from CUPS 1.4svn-r7961.
[thirdparty/cups.git] / scheduler / sysman.c
index a67b4fa7f06a6b34650547e0c93399fcf028c9ef..25ffc6f3f13d24ecf4d1d6cb23d8930efcd5a5b5 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * "$Id: sysman.c 6649 2007-07-11 21:46:42Z mike $"
+ * "$Id: sysman.c 7928 2008-09-10 22:14:22Z mike $"
  *
  *   System management definitions for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
  *
  * 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.
  *   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.
  */
 
 
 
 
 /*
- * 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.
  *
- * Once put to sleep, we invalidate all remote printers since it is
- * common to wake up in a new location.
+ * 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 idle 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.
+ */
+
+
+/*
+ * 'cupsdCleanDirty()' - Write dirty config and state files.
+ */
+
+void
+cupsdCleanDirty(void)
+{
+  if (DirtyFiles & CUPSD_DIRTY_PRINTERS)
+    cupsdSaveAllPrinters();
+
+  if (DirtyFiles & CUPSD_DIRTY_CLASSES)
+    cupsdSaveAllClasses();
+
+  if (DirtyFiles & CUPSD_DIRTY_REMOTE)
+    cupsdSaveRemoteCache();
+
+  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();
+}
+
+
+/*
+ * 'cupsdMarkDirty()' - Mark config or state files as needing a write.
  */
 
+void
+cupsdMarkDirty(int what)               /* I - What file(s) are dirty? */
+{
+  if (what == CUPSD_DIRTY_PRINTCAP && !Printcap)
+    return;
+
+  DirtyFiles |= what;
+
+  if (!DirtyCleanTime)
+    DirtyCleanTime = time(NULL) + DirtyCleanInterval;
+
+  cupsdSetBusyState();
+}
+
+
+/*
+ * 'cupsdSetBusyState()' - Let the system know when we are busy doing something.
+ */
+
+void
+cupsdSetBusyState(void)
+{
+  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"
+  };
+
+
+  newbusy = (DirtyCleanTime ? 1 : 0) |
+            (cupsArrayCount(PrintingJobs) ? 2 : 0) |
+           (cupsArrayCount(ActiveClients) ? 4 : 0);
+
+  if (newbusy != busy)
+  {
+    busy = newbusy;
+
+    cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdSetBusyState: %s", busy_text[busy]);
+  }
+}
+
+
 #ifdef __APPLE__
 /*
  * This is the Apple-specific system event code.  It works by creating
@@ -132,6 +241,7 @@ static void sysEventConfigurationNotifier(SCDynamicStoreRef store,
                                              CFArrayRef changedKeys,
                                              void *context);
 static void    sysEventTimerNotifier(CFRunLoopTimerRef timer, void *context);
+static void    sysUpdate(void);
 
 
 /*
@@ -151,8 +261,7 @@ cupsdStartSystemMonitor(void)
     return;
   }
 
-  cupsdAddSelect(SysEventPipes[0], (cupsd_selfunc_t)cupsdUpdateSystemMonitor,
-                 NULL, NULL);
+  cupsdAddSelect(SysEventPipes[0], (cupsd_selfunc_t)sysUpdate, NULL, NULL);
 
  /*
   * Set non-blocking mode on the descriptor we will be receiving notification
@@ -215,167 +324,6 @@ cupsdStopSystemMonitor(void)
 }
 
 
-/*
- * 'cupsdUpdateSystemMonitor()' - Update the current system state.
- */
-
-void
-cupsdUpdateSystemMonitor(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;
-
-      cupsdStopAllJobs(0);
-      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
-       {
-         cupsdLogMessage(CUPSD_LOG_DEBUG,
-                         "Deregistering local printer \"%s\"", p->name);
-         cupsdDeregisterPrinter(p, 0);
-       }
-      }
-
-      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");
-
-       /*
-        * 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();
-       cupsdRestartPolling();
-      }
-      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))
-         cupsdDeregisterPrinter(p, 1);
-
-       /*
-       * Now re-register them...
-       */
-
-       for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
-            p;
-            p = (cupsd_printer_t *)cupsArrayNext(Printers))
-       {
-         p->browse_time = 0;
-         cupsdRegisterPrinter(p);
-       }
-      }
-      else
-        cupsdLogMessage(CUPSD_LOG_DEBUG,
-                       "Computer name changed; ignored while sleeping");
-    }
-  }
-}
-
-
 /*
  * 'sysEventThreadEntry()' - A thread to receive power and computer name
  *                           change notifications.
@@ -738,9 +686,177 @@ sysEventTimerNotifier(
     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;
+
+      cupsdStopAllJobs(0);
+
+      for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+           p;
+          p = (cupsd_printer_t *)cupsArrayNext(Printers))
+      {
+       if (p->type & CUPS_PRINTER_DISCOVERED)
+       {
+         cupsdLogMessage(CUPSD_LOG_DEBUG,
+                         "Deleting remote destination \"%s\"", p->name);
+         cupsArraySave(Printers);
+         cupsdDeletePrinter(p, 0);
+         cupsArrayRestore(Printers);
+       }
+       else
+       {
+         cupsdLogMessage(CUPSD_LOG_DEBUG,
+                         "Deregistering local printer \"%s\"", p->name);
+         cupsdDeregisterPrinter(p, 0);
+       }
+      }
+
+      cupsdCleanDirty();
+
+      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");
+
+       /*
+        * 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();
+       cupsdRestartPolling();
+      }
+      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))
+         cupsdDeregisterPrinter(p, 1);
+
+       /*
+        * Update the computer name...
+       */
+
+       cupsdUpdateDNSSDName();
+
+       /*
+       * Now re-register them...
+       */
+
+       for (p = (cupsd_printer_t *)cupsArrayFirst(Printers);
+            p;
+            p = (cupsd_printer_t *)cupsArrayNext(Printers))
+       {
+         p->browse_time = 0;
+         cupsdRegisterPrinter(p);
+       }
+      }
+      else
+        cupsdLogMessage(CUPSD_LOG_DEBUG,
+                       "Computer name changed; ignored while sleeping");
+    }
+  }
+}
 #endif /* __APPLE__ */
 
 
 /*
- * End of "$Id: sysman.c 6649 2007-07-11 21:46:42Z mike $".
+ * End of "$Id: sysman.c 7928 2008-09-10 22:14:22Z mike $".
  */