(client_queued): New variable. (nscd_run): Revamp the loop. Don't call poll except for cleanup threads. Keep track of the number of delays caused because of busy worker threads.

This commit is contained in:
Ulrich Drepper 2003-04-28 02:43:30 +00:00
parent bf7725a9bc
commit 0fdb4f42e4

View File

@ -19,6 +19,7 @@
02111-1307 USA. */
#include <assert.h>
#include <atomic.h>
#include <error.h>
#include <errno.h>
#include <grp.h>
@ -130,6 +131,9 @@ int nthreads = -1;
/* Socket for incoming connections. */
static int sock;
/* Number of times clients had to wait. */
unsigned long int client_queued;
/* Initialize database information structures. */
void
@ -435,32 +439,44 @@ nscd_run (void *p)
long int my_number = (long int) p;
struct pollfd conn;
int run_prune = my_number < lastdb && dbs[my_number].enabled;
time_t now = time (NULL);
time_t next_prune = now + CACHE_PRUNE_INTERVAL;
int timeout = run_prune ? 1000 * (next_prune - now) : -1;
time_t next_prune = run_prune ? time (NULL) + CACHE_PRUNE_INTERVAL : 0;
static unsigned long int nready;
conn.fd = sock;
conn.events = POLLRDNORM;
while (1)
{
int nr = poll (&conn, 1, timeout);
int nr;
/* One more thread available. */
atomic_increment (&nready);
no_conn:
if (run_prune)
do
{
time_t now = time (NULL);
int timeout = now < next_prune ? 1000 * (next_prune - now) : 0;
nr = poll (&conn, 1, timeout);
if (nr == 0)
{
/* The `poll' call timed out. It's time to clean up the cache. */
/* The `poll' call timed out. It's time to clean up the
cache. */
atomic_decrement (&nready);
assert (my_number < lastdb);
prune_cache (&dbs[my_number], time(NULL));
now = time (NULL);
prune_cache (&dbs[my_number], now);
next_prune = now + CACHE_PRUNE_INTERVAL;
timeout = 1000 * (next_prune - now);
continue;
goto try_get;
}
}
while ((conn.revents & POLLRDNORM) == 0);
/* We have a new incoming connection. */
if (conn.revents & (POLLRDNORM|POLLERR|POLLHUP|POLLNVAL))
{
/* Accept the connection. */
got_data:;
/* We have a new incoming connection. Accept the connection. */
int fd = TEMP_FAILURE_RETRY (accept (conn.fd, NULL, NULL));
request_header req;
char buf[256];
@ -473,12 +489,14 @@ nscd_run (void *p)
{
dbg_log (_("while accepting connection: %s"),
strerror_r (errno, buf, sizeof (buf)));
continue;
goto no_conn;
}
/* This thread is busy. */
atomic_decrement (&nready);
/* Now read the request. */
if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req,
sizeof (req)))
if (__builtin_expect (TEMP_FAILURE_RETRY (read (fd, &req, sizeof (req)))
!= sizeof (req), 0))
{
if (debug_level > 0)
@ -496,8 +514,7 @@ nscd_run (void *p)
struct ucred caller;
socklen_t optlen = sizeof (caller);
if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED,
&caller, &optlen) < 0)
if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0)
{
dbg_log (_("error getting callers id: %s"),
strerror_r (errno, buf, sizeof (buf)));
@ -516,15 +533,13 @@ nscd_run (void *p)
struct ucred caller;
socklen_t optlen = sizeof (caller);
if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED,
&caller, &optlen) == 0)
if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) == 0)
pid = caller.pid;
}
#endif
/* It should not be possible to crash the nscd with a silly
request (i.e., a terribly large key). We limit the size
to 1kb. */
request (i.e., a terribly large key). We limit the size to 1kb. */
if (__builtin_expect (req.key_len, 1) < 0
|| __builtin_expect (req.key_len, 1) > 1024)
{
@ -568,12 +583,19 @@ handle_request: request received (Version = %d)"), req.version);
/* We are done. */
close (fd);
}
}
if (run_prune)
/* Just determine whether any data is present. We do this to
measure whether clients are queued up. */
try_get:
nr = poll (&conn, 1, 0);
if (nr != 0)
{
now = time (NULL);
timeout = now < next_prune ? 1000 * (next_prune - now) : 0;
if (nready == 0)
++client_queued;
atomic_increment (&nready);
goto got_data;
}
}
}