s3-smbd: Move housekeeping to the background process.
authorAndreas Schneider <asn@samba.org>
Thu, 27 Sep 2012 15:20:25 +0000 (17:20 +0200)
committerKarolin Seeger <kseeger@samba.org>
Tue, 2 Oct 2012 07:00:36 +0000 (09:00 +0200)
If you add 200 printers using lpadmin. Then you wait for the printcap
cache to expire. As soon as this expires we notify all deamons that they
should reload the printers. This mean we need to create the default
registry keys for each printer. If you do e.g. a 'smbclient -L' during
that time you will get a lot of timeouts.

This moves the housekeeping of the printcap cache to the background
queue process and lets the background process reload the printers first.
So the background process creates the default registry keys. When it is
done with the task it will tell all smbd childs to reload the printers
and the 200 printers appear.

Signed-off-by: Andreas Schneider <asn@samba.org>
Fix bug #9231 - NT_STATUS_IO_TIMEOUT during slow import of printers into
registry.

source3/printing/printing.c
source3/smbd/server.c
source3/smbd/server_reload.c

index ba739182f949b8ba5ede5a996d0cbc8a10e41763..a5b36c725d06213574d5f10aeba06b243862ff78 100644 (file)
@@ -1656,6 +1656,28 @@ static void add_child_pid(pid_t pid)
         num_children += 1;
 }
 
+static bool printer_housekeeping_fn(const struct timeval *now,
+                                   void *private_data)
+{
+       static time_t last_pcap_reload_time = 0;
+       time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
+       time_t t = time_mono(NULL);
+
+       DEBUG(5, ("printer housekeeping\n"));
+
+       /* if periodic printcap rescan is enabled, see if it's time to reload */
+       if ((printcap_cache_time != 0)
+        && (t >= (last_pcap_reload_time + printcap_cache_time))) {
+               DEBUG( 3,( "Printcap cache time expired.\n"));
+               pcap_cache_reload(server_event_context(),
+                                 smbd_messaging_context(),
+                                 &reload_pcap_change_notify);
+               last_pcap_reload_time = t;
+       }
+
+       return true;
+}
+
 static pid_t background_lpq_updater_pid = -1;
 
 /****************************************************************************
@@ -1729,6 +1751,15 @@ void start_background_queue(struct tevent_context *ev,
                        smb_panic("tevent_add_fd() failed for pause_pipe");
                }
 
+               if (!(event_add_idle(ev, NULL,
+                                    timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0),
+                                    "printer_housekeeping",
+                                    printer_housekeeping_fn,
+                                    NULL))) {
+                       DEBUG(0, ("Could not add printing housekeeping event\n"));
+                       exit(1);
+               }
+
                DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
                ret = tevent_loop_wait(ev);
                /* should not be reached */
index c699d3b76822e7bb3152da476c64aa6db0d98be4..4b6114a7f9e2aabe160191b22736cc1264e2f3ca 100644 (file)
@@ -619,26 +619,6 @@ static bool smbd_open_one_socket(struct smbd_parent_context *parent,
        return true;
 }
 
-static bool smbd_parent_housekeeping(const struct timeval *now, void *private_data)
-{
-       time_t printcap_cache_time = (time_t)lp_printcap_cache_time();
-       time_t t = time_mono(NULL);
-
-       DEBUG(5, ("parent housekeeping\n"));
-
-       /* if periodic printcap rescan is enabled, see if it's time to reload */
-       if ((printcap_cache_time != 0)
-        && (t >= (last_printer_reload_time + printcap_cache_time))) {
-               DEBUG( 3,( "Printcap cache time expired.\n"));
-               pcap_cache_reload(server_event_context(),
-                                 smbd_messaging_context(),
-                                 &reload_pcap_change_notify);
-               last_printer_reload_time = t;
-       }
-
-       return true;
-}
-
 /****************************************************************************
  Open the socket communication.
 ****************************************************************************/
@@ -781,14 +761,6 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
                return false;
        }
 
-       if (!(event_add_idle(smbd_event_context(), NULL,
-                            timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0),
-                            "parent_housekeeping", smbd_parent_housekeeping,
-                            NULL))) {
-               DEBUG(0, ("Could not add parent_housekeeping event\n"));
-               return false;
-       }
-
         /* Listen to messages */
 
        messaging_register(msg_ctx, NULL, MSG_SMB_SAM_SYNC, msg_sam_sync);
index b88d994d03cda1b0575fd39c60c6b89990ba1f8f..bda5d08a6375ea42fc2f9f533d8efc3480e0cd0e 100644 (file)
@@ -167,5 +167,14 @@ bool reload_services(struct messaging_context *msg_ctx, int smb_sock,
 void reload_pcap_change_notify(struct tevent_context *ev,
                               struct messaging_context *msg_ctx)
 {
+       /*
+        * Reload the printers first in the background process so that
+        * newly added printers get default values created in the registry.
+        *
+        * This will block the process for some time (~1 sec per printer), but
+        * it doesn't block smbd's servering clients.
+        */
+       reload_printers(ev, msg_ctx);
+
        message_send_all(msg_ctx, MSG_PRINTER_PCAP, NULL, 0, NULL);
 }