about summary refs log tree commit diff
path: root/nscd/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'nscd/cache.c')
-rw-r--r--nscd/cache.c60
1 files changed, 42 insertions, 18 deletions
diff --git a/nscd/cache.c b/nscd/cache.c
index 6492092bdd..10b04c3c02 100644
--- a/nscd/cache.c
+++ b/nscd/cache.c
@@ -44,11 +44,14 @@ cache_search (request_type type, void *key, size_t len, struct database *table,
 {
   unsigned long int hash = __nis_hash (key, len) % table->module;
   struct hashentry *work;
+  unsigned long int nsearched = 0;
 
   work = table->array[hash];
 
   while (work != NULL)
     {
+      ++nsearched;
+
       if (type == work->type && len == work->len
 	  && memcmp (key, work->key, len) == 0 && work->owner == owner)
 	{
@@ -58,13 +61,16 @@ cache_search (request_type type, void *key, size_t len, struct database *table,
 	  else
 	    ++table->poshit;
 
-	  return work;
+	  break;
 	}
 
       work = work->next;
     }
 
-  return NULL;
+  if (nsearched > table->maxnsearched)
+    table->maxnsearched = nsearched;
+
+  return work;
 }
 
 /* Add a new entry to the cache.  The return value is zero if the function
@@ -109,6 +115,12 @@ cache_add (int type, void *key, size_t len, const void *packet, size_t total,
     ++table->negmiss;
   else if (last)
     ++table->posmiss;
+
+  /* Instead of slowing down the normal process for statistics
+     collection we accept living with some incorrect data.  */
+  unsigned long int nentries = ++table->nentries;
+  if (nentries > table->maxnentries)
+    table->maxnentries = nentries;
 }
 
 /* Walk through the table and remove all entries which lifetime ended.
@@ -165,10 +177,10 @@ prune_cache (struct database *table, time_t now)
 
   /* We run through the table and find values which are not valid anymore.
 
-   Note that for the initial step, finding the entries to be removed,
-   we don't need to get any lock.  It is at all timed assured that the
-   linked lists are set up correctly and that no second thread prunes
-   the cache.  */
+     Note that for the initial step, finding the entries to be removed,
+     we don't need to get any lock.  It is at all timed assured that the
+     linked lists are set up correctly and that no second thread prunes
+     the cache.  */
   do
     {
       struct hashentry *runp = table->array[--cnt];
@@ -195,7 +207,11 @@ prune_cache (struct database *table, time_t now)
 
       /* Now we have to get the write lock since we are about to modify
 	 the table.  */
-      pthread_rwlock_wrlock (&table->lock);
+      if (__builtin_expect (pthread_rwlock_trywrlock (&table->lock) != 0, 0))
+	{
+	  ++table->wrlockdelayed;
+	  pthread_rwlock_wrlock (&table->lock);
+	}
 
       while (first <= last)
 	{
@@ -208,6 +224,7 @@ prune_cache (struct database *table, time_t now)
 		  table->array[first]->dellist = head;
 		  head = table->array[first];
 		  table->array[first] = head->next;
+		  --table->nentries;
 		  if (--mark[first] == 0)
 		    break;
 		}
@@ -221,6 +238,7 @@ prune_cache (struct database *table, time_t now)
 		      head = runp->next;
 		      runp->next = head->next;
 		      --mark[first];
+		      --table->nentries;
 		    }
 		  else
 		    runp = runp->next;
@@ -232,29 +250,35 @@ prune_cache (struct database *table, time_t now)
       /* It's all done.  */
       pthread_rwlock_unlock (&table->lock);
 
-      /* And another run to free the data.  */
-      do
+      /* One extra pass if we do debugging.  */
+      if (__builtin_expect (debug_level > 0, 0))
 	{
-	  struct hashentry *old = head;
+	  struct hashentry *runp = head;
 
-	  if (debug_level > 0)
+	  while (runp != NULL)
 	    {
 	      char buf[INET6_ADDRSTRLEN];
 	      const char *str;
 
-	      if ((old->type == GETHOSTBYADDR || old->type == GETHOSTBYADDRv6)
-		  && (old->last || old->data == (void *) -1))
+	      if (runp->type == GETHOSTBYADDR || runp->type == GETHOSTBYADDRv6)
 		{
-		  inet_ntop (old->type == GETHOSTBYADDR ? AF_INET : AF_INET6,
-			     old->key, buf, sizeof (buf));
+		  inet_ntop (runp->type == GETHOSTBYADDR ? AF_INET : AF_INET6,
+			     runp->key, buf, sizeof (buf));
 		  str = buf;
 		}
 	      else
-		str = old->last ? old->key : (old->data == (void *) -1
-					      ? old->key : "???");
+		str = runp->key;
 
-	      dbg_log ("remove %s entry \"%s\"", serv2str[old->type], str);
+	      dbg_log ("remove %s entry \"%s\"", serv2str[runp->type], str);
+
+	      runp = runp->next;
 	    }
+	}
+
+      /* And another run to free the data.  */
+      do
+	{
+	  struct hashentry *old = head;
 
 	  /* Free the data structures.  */
 	  if (old->data == (void *) -1)