From 185b4272844970a9e1b46eb3d1d16d4e5ecca939 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 31 May 1999 23:48:04 +0000
Subject: [PATCH] Fix some latent bugs in dllist.c (carelessness about setting
 all fields that should be set).  Add a MoveToFront primitive to speed up one
 of the hotspots in SearchSysCache.

---
 src/backend/lib/dllist.c           | 96 ++++++++++++++++++++----------
 src/backend/utils/cache/catcache.c | 14 +++--
 src/include/lib/dllist.h           |  3 +-
 3 files changed, 73 insertions(+), 40 deletions(-)

diff --git a/src/backend/lib/dllist.c b/src/backend/lib/dllist.c
index 9aeb82f266c..3ca7cf03c74 100644
--- a/src/backend/lib/dllist.c
+++ b/src/backend/lib/dllist.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/lib/dllist.c,v 1.12 1999/02/13 23:15:34 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/lib/dllist.c,v 1.13 1999/05/31 23:48:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,7 +30,9 @@ DLNewList(void)
 	return l;
 }
 
- /* free up a list and all the nodes in it */
+/* free up a list and all the nodes in it --- but *not* whatever the nodes
+ * might point to!
+ */
 void
 DLFreeList(Dllist *l)
 {
@@ -85,7 +87,7 @@ DLGetTail(Dllist *l)
 	return l ? l->dll_tail : 0;
 }
 
-/* get the value stored in the first element */
+/* get the value stored in the last element */
 #ifdef NOT_USED
 void *
 DLGetTailVal(Dllist *l)
@@ -112,20 +114,26 @@ DLGetSucc(Dlelem *e)			/* get successor */
 void
 DLRemove(Dlelem *e)
 {
-	Dllist	   *l;
+	Dllist	   *l = e->dle_list;
 
 	if (e->dle_prev)
 		e->dle_prev->dle_next = e->dle_next;
+	else						/* must be the head element */
+	{
+		Assert(e == l->dll_head);
+		l->dll_head = e->dle_next;
+	}
 	if (e->dle_next)
 		e->dle_next->dle_prev = e->dle_prev;
+	else						/* must be the tail element */
+	{
+		Assert(e == l->dll_tail);
+		l->dll_tail = e->dle_prev;
+	}
 
-	/* check to see if we're removing the head or tail */
-	l = e->dle_list;
-	if (e == l->dll_head)
-		DLRemHead(l);
-	if (e == l->dll_tail)
-		DLRemTail(l);
-
+	e->dle_next = 0;
+	e->dle_prev = 0;
+	e->dle_list = 0;
 }
 
 void
@@ -134,15 +142,13 @@ DLAddHead(Dllist *l, Dlelem *e)
 	e->dle_list = l;
 
 	if (l->dll_head)
-	{
 		l->dll_head->dle_prev = e;
-		e->dle_next = l->dll_head;
-	}
+	e->dle_next = l->dll_head;
 	e->dle_prev = 0;
 	l->dll_head = e;
 
 	if (l->dll_tail == 0)		/* if this is first element added */
-		l->dll_tail = l->dll_head;
+		l->dll_tail = e;
 }
 
 void
@@ -151,31 +157,28 @@ DLAddTail(Dllist *l, Dlelem *e)
 	e->dle_list = l;
 
 	if (l->dll_tail)
-	{
 		l->dll_tail->dle_next = e;
-		e->dle_prev = l->dll_tail;
-	}
+	e->dle_prev = l->dll_tail;
 	e->dle_next = 0;
 	l->dll_tail = e;
 
 	if (l->dll_head == 0)		/* if this is first element added */
-		l->dll_head = l->dll_tail;
+		l->dll_head = e;
 }
 
 Dlelem *
 DLRemHead(Dllist *l)
 {
 	/* remove and return the head */
-	Dlelem	   *result;
+	Dlelem	   *result = l->dll_head;
 
-	if (l->dll_head == 0)
-		return 0;
+	if (result == 0)
+		return result;
 
-	result = l->dll_head;
-	if (l->dll_head->dle_next)
-		l->dll_head->dle_next->dle_prev = 0;
+	if (result->dle_next)
+		result->dle_next->dle_prev = 0;
 
-	l->dll_head = l->dll_head->dle_next;
+	l->dll_head = result->dle_next;
 
 	result->dle_next = 0;
 	result->dle_list = 0;
@@ -190,15 +193,15 @@ Dlelem *
 DLRemTail(Dllist *l)
 {
 	/* remove and return the tail */
-	Dlelem	   *result;
+	Dlelem	   *result = l->dll_tail;
 
-	if (l->dll_tail == 0)
-		return 0;
+	if (result == 0)
+		return result;
 
-	result = l->dll_tail;
-	if (l->dll_tail->dle_prev)
-		l->dll_tail->dle_prev->dle_next = 0;
-	l->dll_tail = l->dll_tail->dle_prev;
+	if (result->dle_prev)
+		result->dle_prev->dle_next = 0;
+
+	l->dll_tail = result->dle_prev;
 
 	result->dle_prev = 0;
 	result->dle_list = 0;
@@ -208,3 +211,30 @@ DLRemTail(Dllist *l)
 
 	return result;
 }
+
+/* Same as DLRemove followed by DLAddHead, but faster */
+void
+DLMoveToFront(Dlelem *e)
+{
+	Dllist	   *l = e->dle_list;
+
+	if (l->dll_head == e)
+		return;					/* Fast path if already at front */
+
+	Assert(e->dle_prev != 0);	/* since it's not the head */
+	e->dle_prev->dle_next = e->dle_next;
+
+	if (e->dle_next)
+		e->dle_next->dle_prev = e->dle_prev;
+	else						/* must be the tail element */
+	{
+		Assert(e == l->dll_tail);
+		l->dll_tail = e->dle_prev;
+	}
+
+	l->dll_head->dle_prev = e;
+	e->dle_next = l->dll_head;
+	e->dle_prev = 0;
+	l->dll_head = e;
+	/* We need not check dll_tail, since there must have been > 1 entry */
+}
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 80444d0a143..cc76acdd747 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.41 1999/05/25 16:12:22 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.42 1999/05/31 23:48:04 tgl Exp $
  *
  * Notes:
  *		XXX This needs to use exception.h to handle recovery when
@@ -876,16 +876,18 @@ SearchSysCache(struct catcache * cache,
 
 	/* ----------------
 	 *	if we found a tuple in the cache, move it to the top of the
-	 *	lru list, and return it.
+	 *	lru list, and return it.  We also move it to the front of the
+	 *	list for its hashbucket, in order to speed subsequent searches.
+	 *	(The most frequently accessed elements in any hashbucket will
+	 *	tend to be near the front of the hashbucket's list.)
 	 * ----------------
 	 */
 	if (elt)
 	{
-		Dlelem	   *old_lru_elt;
+		Dlelem	   *old_lru_elt = ((CatCTup *) DLE_VAL(elt))->ct_node;
 
-		old_lru_elt = ((CatCTup *) DLE_VAL(elt))->ct_node;
-		DLRemove(old_lru_elt);
-		DLAddHead(cache->cc_lrulist, old_lru_elt);
+		DLMoveToFront(old_lru_elt);
+		DLMoveToFront(elt);
 
 #ifdef CACHEDEBUG
 		relation = heap_open(cache->relationId);
diff --git a/src/include/lib/dllist.h b/src/include/lib/dllist.h
index 7c3707afcab..a367450185c 100644
--- a/src/include/lib/dllist.h
+++ b/src/include/lib/dllist.h
@@ -26,7 +26,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: dllist.h,v 1.9 1999/02/13 23:21:30 momjian Exp $
+ * $Id: dllist.h,v 1.10 1999/05/31 23:48:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -66,6 +66,7 @@ extern void DLRemove(Dlelem *); /* removes node from list */
 extern void DLAddHead(Dllist *list, Dlelem *node);
 extern void DLAddTail(Dllist *list, Dlelem *node);
 extern Dlelem *DLRemHead(Dllist *list); /* remove and return the head */
+extern void DLMoveToFront(Dlelem *); /* move node to front of its list */
 
 #define DLE_VAL(x)	(x->dle_val)
 
-- 
GitLab