a new "dual daemon" operating mode for winbindd
authorAndrew Tridgell <tridge@samba.org>
Wed, 24 Apr 2002 04:11:27 +0000 (04:11 +0000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 24 Apr 2002 04:11:27 +0000 (04:11 +0000)
this mode improves the response time of winbindd by having a
background process update the cache while the forground process
responds to queries from cache.

You can enable this mode using the -B command line option. It is quite
experimental, which is why it is not the default.
(This used to be commit c0feff97eefdf5a70e5973e247b395dbdf5d2ef2)

source3/Makefile.in
source3/nsswitch/winbindd.c
source3/nsswitch/winbindd_cache.c
source3/nsswitch/winbindd_proto.h

index ae897782885f3d1b5e6b4a8d884f89811a225e22..dee2daa6b944606c3fed9a6ffef9322ce77afd4b 100644 (file)
@@ -442,7 +442,8 @@ WINBINDD_OBJ1 = \
                nsswitch/winbindd_cm.o \
                nsswitch/winbindd_wins.o \
                nsswitch/winbindd_rpc.o \
-               nsswitch/winbindd_ads.o
+               nsswitch/winbindd_ads.o \
+               nsswitch/winbindd_dual.o
 
 WINBINDD_OBJ = \
                $(WINBINDD_OBJ1) $(NOPROTO_OBJ) $(PASSDB_OBJ) \
index 479be795744b0b75ff5c034f7f8f155c1c01c651..b198b4a163272396755a2effc8575174fccc044e 100644 (file)
@@ -4,6 +4,7 @@
    Winbind daemon for ntdom nss module
 
    Copyright (C) by Tim Potter 2000, 2001
+   Copyright (C) Andrew Tridgell 2002
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -26,7 +27,8 @@
 
 struct winbindd_cli_state *client_list;
 static int num_clients;
-BOOL opt_nocache;
+BOOL opt_nocache = False;
+BOOL opt_dual_daemon = False;
 
 /* Reload configuration */
 
@@ -365,9 +367,10 @@ static void remove_client(struct winbindd_cli_state *state)
        }
 }
 
+
 /* Process a complete received packet from a client */
 
-static void process_packet(struct winbindd_cli_state *state)
+void winbind_process_packet(struct winbindd_cli_state *state)
 {
        /* Process request */
        
@@ -379,11 +382,16 @@ static void process_packet(struct winbindd_cli_state *state)
        
        state->read_buf_len = 0;
        state->write_buf_len = sizeof(struct winbindd_response);
+
+       /* we might need to send it to the dual daemon */
+       if (opt_dual_daemon) {
+               dual_send_request(state);
+       }
 }
 
 /* Read some data from a client connection */
 
-static void client_read(struct winbindd_cli_state *state)
+void winbind_client_read(struct winbindd_cli_state *state)
 {
        int n;
     
@@ -397,8 +405,11 @@ static void client_read(struct winbindd_cli_state *state)
 
        } while (n == -1 && errno == EINTR);
        
+       DEBUG(10,("client_read: read %d bytes. Need %d more for a full request.\n", n, sizeof(state->request) - n - state->read_buf_len ));
+
+       /* Read failed, kill client */
+       
        if (n == -1 || n == 0) {
-               /* Read failed, kill client */
                DEBUG(5,("read failed on sock %d, pid %d: %s\n",
                         state->sock, state->pid, 
                         (n == -1) ? strerror(errno) : "EOF"));
@@ -407,8 +418,6 @@ static void client_read(struct winbindd_cli_state *state)
                return;
        }
        
-       DEBUG(10,("client_read: read %d bytes. Need %d more for a full request.\n", n, sizeof(state->request) - n - state->read_buf_len ));
-
        /* Update client state */
        
        state->read_buf_len += n;
@@ -528,6 +537,10 @@ static void process_loop(int accept_sock)
                timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
                timeout.tv_usec = 0;
 
+               if (opt_dual_daemon) {
+                       maxfd = dual_select_setup(&w_fds, maxfd);
+               }
+
                /* Set up client readers and writers */
 
                state = client_list;
@@ -582,6 +595,10 @@ static void process_loop(int accept_sock)
 
                if (selret > 0) {
 
+                       if (opt_dual_daemon) {
+                               dual_select(&w_fds);
+                       }
+
                        if (FD_ISSET(accept_sock, &r_fds))
                                new_connection(accept_sock);
             
@@ -595,7 +612,7 @@ static void process_loop(int accept_sock)
                     
                                        /* Read data */
                     
-                                       client_read(state);
+                                       winbind_client_read(state);
 
                                        /* 
                                         * If we have the start of a
@@ -619,7 +636,7 @@ static void process_loop(int accept_sock)
                     
                                        if (state->read_buf_len == 
                                            sizeof(state->request)) {
-                                               process_packet(state);
+                                               winbind_process_packet(state);
                                        }
                                }
                 
@@ -655,6 +672,57 @@ static void process_loop(int accept_sock)
        }
 }
 
+
+/*
+  these are split out from the main winbindd for use by the background daemon
+ */
+int winbind_setup_common(void)
+{
+       load_interfaces();
+
+       secrets_init();
+
+       /* Get list of domains we look up requests for.  This includes the
+          domain which we are a member of as well as any trusted
+          domains. */ 
+
+       init_domain_list();
+
+       ZERO_STRUCT(server_state);
+
+       /* Winbind daemon initialisation */
+
+       if (!winbindd_param_init())
+               return 1;
+
+       if (!winbindd_idmap_init())
+               return 1;
+
+       /* Unblock all signals we are interested in as they may have been
+          blocked by the parent process. */
+
+       BlockSignals(False, SIGINT);
+       BlockSignals(False, SIGQUIT);
+       BlockSignals(False, SIGTERM);
+       BlockSignals(False, SIGUSR1);
+       BlockSignals(False, SIGUSR2);
+       BlockSignals(False, SIGHUP);
+
+       /* Setup signal handlers */
+       
+       CatchSignal(SIGINT, termination_handler);      /* Exit on these sigs */
+       CatchSignal(SIGQUIT, termination_handler);
+       CatchSignal(SIGTERM, termination_handler);
+
+       CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
+
+       CatchSignal(SIGUSR2, sigusr2_handler);         /* Debugging sigs */
+       CatchSignal(SIGHUP, sighup_handler);
+
+       return 0;
+}
+
+
 /* Main function */
 
 struct winbindd_state server_state;   /* Server state information */
@@ -664,6 +732,7 @@ static void usage(void)
 {
        printf("Usage: winbindd [options]\n");
        printf("\t-i                interactive mode\n");
+       printf("\t-B                dual daemon mode\n");
        printf("\t-n                disable cacheing\n");
        printf("\t-d level          set debug level\n");
        printf("\t-s configfile     choose smb.conf location\n");
@@ -708,7 +777,7 @@ int main(int argc, char **argv)
 
        /* Initialise samba/rpc client stuff */
 
-       while ((opt = getopt(argc, argv, "id:s:nh")) != EOF) {
+       while ((opt = getopt(argc, argv, "id:s:nhB")) != EOF) {
                switch (opt) {
 
                        /* Don't become a daemon */
@@ -716,6 +785,11 @@ int main(int argc, char **argv)
                        interactive = True;
                        break;
 
+                       /* dual daemon system */
+               case 'B':
+                       opt_dual_daemon = True;
+                       break;
+
                        /* disable cacheing */
                case 'n':
                        opt_nocache = True;
@@ -782,46 +856,13 @@ int main(int argc, char **argv)
                setpgid( (pid_t)0, (pid_t)0);
 #endif
 
-       load_interfaces();
-
-       secrets_init();
-
-       /* Get list of domains we look up requests for.  This includes the
-          domain which we are a member of as well as any trusted
-          domains. */ 
-
-       init_domain_list();
-
-       ZERO_STRUCT(server_state);
-
-       /* Winbind daemon initialisation */
-
-       if (!winbindd_param_init())
-               return 1;
+       if (opt_dual_daemon) {
+               do_dual_daemon();
+       }
 
-       if (!winbindd_idmap_init())
+       if (winbind_setup_common() != 0) {
                return 1;
-
-       /* Unblock all signals we are interested in as they may have been
-          blocked by the parent process. */
-
-       BlockSignals(False, SIGINT);
-       BlockSignals(False, SIGQUIT);
-       BlockSignals(False, SIGTERM);
-       BlockSignals(False, SIGUSR1);
-       BlockSignals(False, SIGUSR2);
-       BlockSignals(False, SIGHUP);
-
-       /* Setup signal handlers */
-       
-       CatchSignal(SIGINT, termination_handler);      /* Exit on these sigs */
-       CatchSignal(SIGQUIT, termination_handler);
-       CatchSignal(SIGTERM, termination_handler);
-
-       CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
-
-       CatchSignal(SIGUSR2, sigusr2_handler);         /* Debugging sigs */
-       CatchSignal(SIGHUP, sighup_handler);
+       }
 
        /* Initialise messaging system */
 
index 9bd95fdd861bdf68a0a4d45eabbda338850506db..f65705e0fb0c1837b9925cbe228a1b912226eaee 100644 (file)
@@ -51,7 +51,7 @@ void wcache_flush_cache(void)
        if (opt_nocache) return;
 
        wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000, 
-                                  TDB_DEFAULT, O_RDWR | O_CREAT | O_TRUNC, 0600);
+                                  TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0600);
 
        if (!wcache->tdb) {
                DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
@@ -205,11 +205,17 @@ static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force)
 {
        NTSTATUS status;
        unsigned time_diff;
+       unsigned cache_time = lp_winbind_cache_time();
+
+       /* trying to reconnect is expensive, don't do it too often */
+       if (domain->sequence_number == DOM_SEQUENCE_NONE) {
+               cache_time *= 8;
+       }
 
        time_diff = time(NULL) - domain->last_seq_check;
 
        /* see if we have to refetch the domain sequence number */
-       if (!force && (time_diff < lp_winbind_cache_time())) {
+       if (!force && (time_diff < cache_time)) {
                return;
        }
 
@@ -289,9 +295,15 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
        centry->sequence_number = centry_uint32(centry);
 
        if (centry_expired(domain, centry)) {
+               extern BOOL opt_dual_daemon;
+               if (opt_dual_daemon) {
+                       extern BOOL backgroud_process;
+                       backgroud_process = True;
+               } else {
                centry_free(centry);
                return NULL;
        }
+       }
 
        return centry;
 }
index f3830cd63c66b2b325525042ea93ad7128a78772..8cac542b88bb43b94275077ce92eee0f525e6669 100644 (file)
@@ -6,6 +6,9 @@
 
 /* The following definitions come from nsswitch/winbindd.c  */
 
+void winbind_process_packet(struct winbindd_cli_state *state);
+void winbind_client_read(struct winbindd_cli_state *state);
+int winbind_setup_common(void);
 int main(int argc, char **argv);
 
 /* The following definitions come from nsswitch/winbindd_ads.c  */
@@ -39,6 +42,13 @@ NTSTATUS cm_get_netlogon_cli(char *domain, unsigned char *trust_passwd,
                             struct cli_state **cli);
 void winbindd_cm_status(void);
 
+/* The following definitions come from nsswitch/winbindd_dual.c  */
+
+int dual_select_setup(fd_set *fds, int maxfd);
+void dual_select(fd_set *fds);
+void dual_send_request(struct winbindd_cli_state *state);
+void do_dual_daemon(void);
+
 /* The following definitions come from nsswitch/winbindd_group.c  */
 
 enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state);