* nscd/cache.c (cache_add): Take additional parameter specifying

whether this is in response of a cache refill.  Check alignment
	of package data.  Revamp waking of pruning thread.
	(prune_cache): Small optimization.
	* nscd/nscd.h: Adjust cache_add prototypes.
	* nscd/aicache.c: Adjust cache_add calls.
	* nscd/grpcache.c: Likewise.
	* nscd/hstcache.c: Likewise.
	* nscd/initgrcache.c: Likewise.
	* nscd/pwdcache.c: Likewise.
	* nscd/servicescache.c: Likewise.
	* nscd/connections.c (restart): Really disable cache use before
	exec attempt.  If it fails, reenable cache.
	(nscd_run_prune): Initialize wakeup_time.  After wakeup, set wakeup
	time to max to be able to notice concurrent cache additions.  Unlock
	prune_lock while performing gc.  Afterwards compute wakeup time with
	current wakeup_time value in mind.
This commit is contained in:
Ulrich Drepper 2008-05-18 21:54:43 +00:00
parent 5811d72b73
commit 528741cb6c
10 changed files with 114 additions and 42 deletions

View file

@ -1,3 +1,23 @@
2008-05-18 Ulrich Drepper <drepper@redhat.com>
* nscd/cache.c (cache_add): Take additional parameter specifying
whether this is in response of a cache refill. Check alignment
of package data. Revamp waking of pruning thread.
(prune_cache): Small optimization.
* nscd/nscd.h: Adjust cache_add prototypes.
* nscd/aicache.c: Adjust cache_add calls.
* nscd/grpcache.c: Likewise.
* nscd/hstcache.c: Likewise.
* nscd/initgrcache.c: Likewise.
* nscd/pwdcache.c: Likewise.
* nscd/servicescache.c: Likewise.
* nscd/connections.c (restart): Really disable cache use before
exec attempt. If it fails, reenable cache.
(nscd_run_prune): Initialize wakeup_time. After wakeup, set wakeup
time to max to be able to notice concurrent cache additions. Unlock
prune_lock while performing gc. Afterwards compute wakeup time with
current wakeup_time value in mind.
2008-05-17 Ulrich Drepper <drepper@redhat.com>
* nscd/mem.c (gc): Avoid stack overflow when allocating move list.

View file

@ -558,7 +558,7 @@ next_nip:
pthread_rwlock_rdlock (&db->lock);
(void) cache_add (req->type, key_copy, req->key_len, &dataset->head,
true, db, uid);
true, db, uid, he == NULL);
pthread_rwlock_unlock (&db->lock);

View file

@ -135,7 +135,7 @@ cache_search (request_type type, void *key, size_t len,
int
cache_add (int type, const void *key, size_t len, struct datahead *packet,
bool first, struct database_dyn *table,
uid_t owner)
uid_t owner, bool prune_wakeup)
{
if (__builtin_expect (debug_level >= 2, 0))
{
@ -180,6 +180,7 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet,
assert (newp->key + newp->len <= table->head->first_free);
newp->owner = owner;
newp->packet = (char *) packet - table->data;
assert ((newp->packet & BLOCK_ALIGN_M1) == 0);
/* Put the new entry in the first position. */
do
@ -211,19 +212,27 @@ cache_add (int type, const void *key, size_t len, struct datahead *packet,
(char *) &table->head->array[hash] - (char *) table->head
+ sizeof (ref_t), MS_ASYNC);
/* Perhaps the prune thread for the data is not running in a long
time. Wake it if necessary. */
time_t next_wakeup = table->wakeup_time;
while (next_wakeup + CACHE_PRUNE_INTERVAL > packet->timeout)
if (atomic_compare_and_exchange_bool_acq (&table->wakeup_time,
packet->timeout,
next_wakeup) == 0)
{
/* We do not have to worry about the pruning thread if we are
re-adding the data since this is done by the pruning thread. We
also do not have to do anything in case this is not the first
time the data is entered since different data heads all have the
same timeout. */
if (first && prune_wakeup)
{
/* Perhaps the prune thread for the table is not running in a long
time. Wake it if necessary. */
pthread_mutex_lock (&table->prune_lock);
time_t next_wakeup = table->wakeup_time;
bool do_wakeup = false;
if (next_wakeup > packet->timeout + CACHE_PRUNE_INTERVAL)
{
table->wakeup_time = packet->timeout;
do_wakeup = true;
}
pthread_mutex_unlock (&table->prune_lock);
if (do_wakeup)
pthread_cond_signal (&table->prune_cond);
break;
}
else
next_wakeup = table->wakeup_time;
}
/* Mark the in-flight memory as unused. */
for (enum in_flight idx = 0; idx < IDX_last; ++idx)
@ -436,7 +445,8 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
ref_t *old = &table->head->array[first];
ref_t run = table->head->array[first];
while (run != ENDREF)
assert (run != ENDREF);
do
{
struct hashentry *runp = (struct hashentry *) (data + run);
struct datahead *dh
@ -462,6 +472,7 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
run = runp->next;
}
}
while (run != ENDREF);
}
++first;

View file

@ -1330,11 +1330,14 @@ cannot change to old working directory: %s; disabling paranoia mode"),
}
/* Synchronize memory. */
int32_t certainly[lastdb];
for (int cnt = 0; cnt < lastdb; ++cnt)
if (dbs[cnt].enabled)
{
/* Make sure nobody keeps using the database. */
dbs[cnt].head->timestamp = 0;
certainly[cnt] = dbs[cnt].head->nscd_certainly_running;
dbs[cnt].head->nscd_certainly_running = 0;
if (dbs[cnt].persistent)
// XXX async OK?
@ -1357,6 +1360,15 @@ cannot change to old working directory: %s; disabling paranoia mode"),
dbg_log (_("cannot change current working directory to \"/\": %s"),
strerror (errno));
paranoia = 0;
/* Reenable the databases. */
time_t now = time (NULL);
for (int cnt = 0; cnt < lastdb; ++cnt)
if (dbs[cnt].enabled)
{
dbs[cnt].head->timestamp = now;
dbs[cnt].head->nscd_certainly_running = certainly[cnt];
}
}
@ -1394,42 +1406,68 @@ nscd_run_prune (void *p)
int dont_need_update = setup_thread (&dbs[my_number]);
time_t now = time (NULL);
/* We are running. */
dbs[my_number].head->timestamp = time (NULL);
dbs[my_number].head->timestamp = now;
struct timespec prune_ts;
if (clock_gettime (timeout_clock, &prune_ts) == -1)
if (__builtin_expect (clock_gettime (timeout_clock, &prune_ts) == -1, 0))
/* Should never happen. */
abort ();
/* Compute the initial timeout time. Prevent all the timers to go
off at the same time by adding a db-based value. */
prune_ts.tv_sec += CACHE_PRUNE_INTERVAL + my_number;
dbs[my_number].wakeup_time = now + CACHE_PRUNE_INTERVAL + my_number;
pthread_mutex_lock (&dbs[my_number].prune_lock);
pthread_mutex_t *prune_lock = &dbs[my_number].prune_lock;
pthread_cond_t *prune_cond = &dbs[my_number].prune_cond;
pthread_mutex_lock (prune_lock);
while (1)
{
/* Wait, but not forever. */
int e = pthread_cond_timedwait (&dbs[my_number].prune_cond,
&dbs[my_number].prune_lock,
&prune_ts);
assert (e == 0 || e == ETIMEDOUT);
int e = pthread_cond_timedwait (prune_cond, prune_lock, &prune_ts);
assert (__builtin_expect (e == 0 || e == ETIMEDOUT, 1));
time_t next_wait;
time_t now = time (NULL);
now = time (NULL);
if (e == ETIMEDOUT || now >= dbs[my_number].wakeup_time)
{
/* We will determine the new timout values based on the
cache content. Should there be concurrent additions to
the cache which are not accounted for in the cache
pruning we want to know about it. Therefore set the
timeout to the maximum. It will be descreased when adding
new entries to the cache, if necessary. */
if (sizeof (time_t) == sizeof (long int))
dbs[my_number].wakeup_time = LONG_MAX;
else
dbs[my_number].wakeup_time = INT_MAX;
pthread_mutex_unlock (prune_lock);
next_wait = prune_cache (&dbs[my_number], now, -1);
next_wait = MAX (next_wait, CACHE_PRUNE_INTERVAL);
/* If clients cannot determine for sure whether nscd is running
we need to wake up occasionally to update the timestamp.
Wait 90% of the update period. */
#define UPDATE_MAPPING_TIMEOUT (MAPPING_TIMEOUT * 9 / 10)
if (__builtin_expect (! dont_need_update, 0))
next_wait = MIN (UPDATE_MAPPING_TIMEOUT, next_wait);
{
next_wait = MIN (UPDATE_MAPPING_TIMEOUT, next_wait);
dbs[my_number].head->timestamp = now;
}
pthread_mutex_lock (prune_lock);
/* Make it known when we will wake up again. */
dbs[my_number].wakeup_time = now + next_wait;
if (now + next_wait < dbs[my_number].wakeup_time)
dbs[my_number].wakeup_time = now + next_wait;
else
next_wait = dbs[my_number].wakeup_time - now;
}
else
/* The cache was just pruned. Do not do it again now. Just

View file

@ -147,7 +147,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
pthread_rwlock_rdlock (&db->lock);
(void) cache_add (req->type, &dataset->strdata, req->key_len,
&dataset->head, true, db, owner);
&dataset->head, true, db, owner, he == NULL);
pthread_rwlock_unlock (&db->lock);
@ -353,7 +353,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
if (req->type == GETGRBYGID)
{
if (cache_add (GETGRBYGID, cp, key_offset, &dataset->head, true,
db, owner) < 0)
db, owner, he == NULL) < 0)
goto out;
first = false;
@ -362,7 +362,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
else if (strcmp (key_copy, gr_name) != 0)
{
if (cache_add (GETGRBYNAME, key_copy, key_len + 1,
&dataset->head, true, db, owner) < 0)
&dataset->head, true, db, owner, he == NULL) < 0)
goto out;
first = false;
@ -372,12 +372,13 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
if ((req->type == GETGRBYNAME || db->propagate)
&& __builtin_expect (cache_add (GETGRBYNAME, gr_name,
gr_name_len,
&dataset->head, first, db, owner)
&dataset->head, first, db, owner,
he == NULL)
== 0, 1))
{
if (req->type == GETGRBYNAME && db->propagate)
(void) cache_add (GETGRBYGID, cp, key_offset, &dataset->head,
false, db, owner);
false, db, owner, false);
}
out:

View file

@ -156,7 +156,7 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
pthread_rwlock_rdlock (&db->lock);
(void) cache_add (req->type, &dataset->strdata, req->key_len,
&dataset->head, true, db, owner);
&dataset->head, true, db, owner, he == NULL);
pthread_rwlock_unlock (&db->lock);
@ -408,7 +408,7 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req,
|| req->type == GETHOSTBYADDRv6);
(void) cache_add (req->type, key_copy, req->key_len,
&dataset->head, true, db, owner);
&dataset->head, true, db, owner, he == NULL);
pthread_rwlock_unlock (&db->lock);
}

View file

@ -231,7 +231,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req,
pthread_rwlock_rdlock (&db->lock);
(void) cache_add (req->type, key_copy, req->key_len,
&dataset->head, true, db, uid);
&dataset->head, true, db, uid, he == NULL);
pthread_rwlock_unlock (&db->lock);
@ -398,7 +398,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req,
pthread_rwlock_rdlock (&db->lock);
(void) cache_add (INITGROUPS, cp, req->key_len, &dataset->head, true,
db, uid);
db, uid, he == NULL);
pthread_rwlock_unlock (&db->lock);
}

View file

@ -231,7 +231,8 @@ extern struct datahead *cache_search (request_type, void *key, size_t len,
uid_t owner);
extern int cache_add (int type, const void *key, size_t len,
struct datahead *packet, bool first,
struct database_dyn *table, uid_t owner);
struct database_dyn *table, uid_t owner,
bool prune_wakeup);
extern time_t prune_cache (struct database_dyn *table, time_t now, int fd);
/* pwdcache.c */

View file

@ -154,7 +154,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
pthread_rwlock_rdlock (&db->lock);
(void) cache_add (req->type, key_copy, req->key_len,
&dataset->head, true, db, owner);
&dataset->head, true, db, owner, he == NULL);
pthread_rwlock_unlock (&db->lock);
@ -348,7 +348,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
if (req->type == GETPWBYUID)
{
if (cache_add (GETPWBYUID, cp, key_offset, &dataset->head, true,
db, owner) < 0)
db, owner, he == NULL) < 0)
goto out;
first = false;
@ -357,7 +357,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
else if (strcmp (key_copy, dataset->strdata) != 0)
{
if (cache_add (GETPWBYNAME, key_copy, key_len + 1,
&dataset->head, true, db, owner) < 0)
&dataset->head, true, db, owner, he == NULL) < 0)
goto out;
first = false;
@ -367,11 +367,12 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
if ((req->type == GETPWBYNAME || db->propagate)
&& __builtin_expect (cache_add (GETPWBYNAME, dataset->strdata,
pw_name_len, &dataset->head,
first, db, owner) == 0, 1))
first, db, owner, he == NULL)
== 0, 1))
{
if (req->type == GETPWBYNAME && db->propagate)
(void) cache_add (GETPWBYUID, cp, key_offset, &dataset->head,
false, db, owner);
false, db, owner, false);
}
out:

View file

@ -137,7 +137,7 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req,
pthread_rwlock_rdlock (&db->lock);
(void) cache_add (req->type, &dataset->strdata, req->key_len,
&dataset->head, true, db, owner);
&dataset->head, true, db, owner, he == NULL);
pthread_rwlock_unlock (&db->lock);
@ -331,7 +331,7 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req,
pthread_rwlock_rdlock (&db->lock);
(void) cache_add (req->type, key_copy, req->key_len,
&dataset->head, true, db, owner);
&dataset->head, true, db, owner, he == NULL);
pthread_rwlock_unlock (&db->lock);
}