summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2002-04-24 04:11:27 +0000
committerAndrew Tridgell <tridge@samba.org>2002-04-24 04:11:27 +0000
commita67b5ac62fcd3e8bcef668a29094635a548e5744 (patch)
treea8a4ef1f3231dbfb0422620c8cae5b891a0c1339
parent27173b205f05aebd9226fa43fc40424bf8e79a72 (diff)
downloadsamba-a67b5ac62fcd3e8bcef668a29094635a548e5744.tar.gz
samba-a67b5ac62fcd3e8bcef668a29094635a548e5744.tar.bz2
samba-a67b5ac62fcd3e8bcef668a29094635a548e5744.zip
a new "dual daemon" operating mode for winbindd
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)
-rw-r--r--source3/Makefile.in3
-rw-r--r--source3/nsswitch/winbindd.c135
-rw-r--r--source3/nsswitch/winbindd_cache.c16
-rw-r--r--source3/nsswitch/winbindd_proto.h10
4 files changed, 114 insertions, 50 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index ae89778288..dee2daa6b9 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -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) \
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index 479be79574..b198b4a163 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -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 */
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index 9bd95fdd86..f65705e0fb 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -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;
}
diff --git a/source3/nsswitch/winbindd_proto.h b/source3/nsswitch/winbindd_proto.h
index f3830cd63c..8cac542b88 100644
--- a/source3/nsswitch/winbindd_proto.h
+++ b/source3/nsswitch/winbindd_proto.h
@@ -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);