From 610e58e256ca6240fbfbdc78e527d4f1c4de6882 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 28 Sep 2012 16:42:03 +0200
Subject: [PATCH 3/4] Remove current users of dllist.h

Alvaro, Andres
---
 src/backend/postmaster/autovacuum.c | 128 ++++++++++++++++----------------
 src/backend/postmaster/postmaster.c |  59 +++++++--------
 src/backend/utils/cache/catcache.c  | 144 ++++++++++++++++++------------------
 src/include/utils/catcache.h        |  19 ++---
 4 files changed, 175 insertions(+), 175 deletions(-)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 74db821..c3ac219 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -77,7 +77,7 @@
 #include "catalog/pg_database.h"
 #include "commands/dbcommands.h"
 #include "commands/vacuum.h"
-#include "lib/dllist.h"
+#include "lib/ilist.h"
 #include "libpq/pqsignal.h"
 #include "miscadmin.h"
 #include "pgstat.h"
@@ -152,6 +152,7 @@ typedef struct avl_dbase
 	Oid			adl_datid;		/* hash key -- must be first */
 	TimestampTz adl_next_worker;
 	int			adl_score;
+	dlist_node	adl_node;
 } avl_dbase;
 
 /* struct to keep track of databases in worker */
@@ -258,8 +259,11 @@ typedef struct
 
 static AutoVacuumShmemStruct *AutoVacuumShmem;
 
-/* the database list in the launcher, and the context that contains it */
-static Dllist *DatabaseList = NULL;
+/*
+ * the database list (of avl_dbase elements) in the launcher, and the context
+ * that contains it
+ */
+static dlist_head DatabaseList = DLIST_STATIC_INIT(DatabaseList);
 static MemoryContext DatabaseListCxt = NULL;
 
 /* Pointer to my own WorkerInfo, valid on each worker */
@@ -508,7 +512,7 @@ AutoVacLauncherMain(int argc, char *argv[])
 
 		/* don't leave dangling pointers to freed memory */
 		DatabaseListCxt = NULL;
-		DatabaseList = NULL;
+		dlist_init(&DatabaseList);
 
 		/*
 		 * Make sure pgstat also considers our stat data as gone.  Note: we
@@ -576,7 +580,7 @@ AutoVacLauncherMain(int argc, char *argv[])
 		struct timeval nap;
 		TimestampTz current_time = 0;
 		bool		can_launch;
-		Dlelem	   *elem;
+		avl_dbase  *avdb;
 		int			rc;
 
 		/*
@@ -738,20 +742,7 @@ AutoVacLauncherMain(int argc, char *argv[])
 
 		/* We're OK to start a new worker */
 
-		elem = DLGetTail(DatabaseList);
-		if (elem != NULL)
-		{
-			avl_dbase  *avdb = DLE_VAL(elem);
-
-			/*
-			 * launch a worker if next_worker is right now or it is in the
-			 * past
-			 */
-			if (TimestampDifferenceExceeds(avdb->adl_next_worker,
-										   current_time, 0))
-				launch_worker(current_time);
-		}
-		else
+		if (dlist_is_empty(&DatabaseList))
 		{
 			/*
 			 * Special case when the list is empty: start a worker right away.
@@ -763,6 +754,23 @@ AutoVacLauncherMain(int argc, char *argv[])
 			 */
 			launch_worker(current_time);
 		}
+		else
+		{
+			/*
+			 * because rebuild_database_list constructs a list with most
+			 * distant adl_next_worker first, we obtain our database from the
+			 * tail of the list.
+			 */
+			avdb = dlist_tail_element(avl_dbase, adl_node, &DatabaseList);
+
+			/*
+			 * launch a worker if next_worker is right now or it is in the
+			 * past
+			 */
+			if (TimestampDifferenceExceeds(avdb->adl_next_worker,
+										   current_time, 0))
+				launch_worker(current_time);
+		}
 	}
 
 	/* Normal exit from the autovac launcher is here */
@@ -783,7 +791,7 @@ AutoVacLauncherMain(int argc, char *argv[])
 static void
 launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval * nap)
 {
-	Dlelem	   *elem;
+	avl_dbase  *avdb;
 
 	/*
 	 * We sleep until the next scheduled vacuum.  We trust that when the
@@ -796,14 +804,15 @@ launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval * nap)
 		nap->tv_sec = autovacuum_naptime;
 		nap->tv_usec = 0;
 	}
-	else if ((elem = DLGetTail(DatabaseList)) != NULL)
+	else if (!dlist_is_empty(&DatabaseList))
 	{
-		avl_dbase  *avdb = DLE_VAL(elem);
 		TimestampTz current_time = GetCurrentTimestamp();
 		TimestampTz next_wakeup;
 		long		secs;
 		int			usecs;
 
+		avdb = dlist_tail_element(avl_dbase, adl_node, &DatabaseList);
+
 		next_wakeup = avdb->adl_next_worker;
 		TimestampDifference(current_time, next_wakeup, &secs, &usecs);
 
@@ -867,6 +876,7 @@ rebuild_database_list(Oid newdb)
 	int			score;
 	int			nelems;
 	HTAB	   *dbhash;
+	dlist_iter  iter;
 
 	/* use fresh stats */
 	autovac_refresh_stats();
@@ -927,36 +937,28 @@ rebuild_database_list(Oid newdb)
 	}
 
 	/* Now insert the databases from the existing list */
-	if (DatabaseList != NULL)
+	dlist_foreach(iter, &DatabaseList)
 	{
-		Dlelem	   *elem;
-
-		elem = DLGetHead(DatabaseList);
-		while (elem != NULL)
-		{
-			avl_dbase  *avdb = DLE_VAL(elem);
-			avl_dbase  *db;
-			bool		found;
-			PgStat_StatDBEntry *entry;
-
-			elem = DLGetSucc(elem);
+		avl_dbase  *avdb = dlist_container(avl_dbase, adl_node, iter.cur);
+		avl_dbase  *db;
+		bool		found;
+		PgStat_StatDBEntry *entry;
 
-			/*
-			 * skip databases with no stat entries -- in particular, this gets
-			 * rid of dropped databases
-			 */
-			entry = pgstat_fetch_stat_dbentry(avdb->adl_datid);
-			if (entry == NULL)
-				continue;
+		/*
+		 * skip databases with no stat entries -- in particular, this gets
+		 * rid of dropped databases
+		 */
+		entry = pgstat_fetch_stat_dbentry(avdb->adl_datid);
+		if (entry == NULL)
+			continue;
 
-			db = hash_search(dbhash, &(avdb->adl_datid), HASH_ENTER, &found);
+		db = hash_search(dbhash, &(avdb->adl_datid), HASH_ENTER, &found);
 
-			if (!found)
-			{
-				/* hash_search already filled in the key */
-				db->adl_score = score++;
-				/* next_worker is filled in later */
-			}
+		if (!found)
+		{
+			/* hash_search already filled in the key */
+			db->adl_score = score++;
+			/* next_worker is filled in later */
 		}
 	}
 
@@ -987,7 +989,7 @@ rebuild_database_list(Oid newdb)
 
 	/* from here on, the allocated memory belongs to the new list */
 	MemoryContextSwitchTo(newcxt);
-	DatabaseList = DLNewList();
+	dlist_init(&DatabaseList);
 
 	if (nelems > 0)
 	{
@@ -1029,15 +1031,13 @@ rebuild_database_list(Oid newdb)
 		for (i = 0; i < nelems; i++)
 		{
 			avl_dbase  *db = &(dbary[i]);
-			Dlelem	   *elem;
 
 			current_time = TimestampTzPlusMilliseconds(current_time,
 													   millis_increment);
 			db->adl_next_worker = current_time;
 
-			elem = DLNewElem(db);
 			/* later elements should go closer to the head of the list */
-			DLAddHead(DatabaseList, elem);
+			dlist_push_head(&DatabaseList, &db->adl_node);
 		}
 	}
 
@@ -1147,7 +1147,7 @@ do_start_worker(void)
 	foreach(cell, dblist)
 	{
 		avw_dbase  *tmp = lfirst(cell);
-		Dlelem	   *elem;
+		dlist_iter iter;
 
 		/* Check to see if this one is at risk of wraparound */
 		if (TransactionIdPrecedes(tmp->adw_frozenxid, xidForceLimit))
@@ -1179,11 +1179,10 @@ do_start_worker(void)
 		 * autovacuum time yet.
 		 */
 		skipit = false;
-		elem = DatabaseList ? DLGetTail(DatabaseList) : NULL;
 
-		while (elem != NULL)
+		dlist_reverse_foreach(iter, &DatabaseList)
 		{
-			avl_dbase  *dbp = DLE_VAL(elem);
+			avl_dbase  *dbp = dlist_container(avl_dbase, adl_node, iter.cur);
 
 			if (dbp->adl_datid == tmp->adw_datid)
 			{
@@ -1200,7 +1199,6 @@ do_start_worker(void)
 
 				break;
 			}
-			elem = DLGetPred(elem);
 		}
 		if (skipit)
 			continue;
@@ -1274,22 +1272,25 @@ static void
 launch_worker(TimestampTz now)
 {
 	Oid			dbid;
-	Dlelem	   *elem;
+	dlist_iter  iter;
 
 	dbid = do_start_worker();
 	if (OidIsValid(dbid))
 	{
+		bool found = false;
+
 		/*
 		 * Walk the database list and update the corresponding entry.  If the
 		 * database is not on the list, we'll recreate the list.
 		 */
-		elem = (DatabaseList == NULL) ? NULL : DLGetHead(DatabaseList);
-		while (elem != NULL)
+		dlist_foreach(iter, &DatabaseList)
 		{
-			avl_dbase  *avdb = DLE_VAL(elem);
+			avl_dbase  *avdb = dlist_container(avl_dbase, adl_node, iter.cur);
 
 			if (avdb->adl_datid == dbid)
 			{
+				found = true;
+
 				/*
 				 * add autovacuum_naptime seconds to the current time, and use
 				 * that as the new "next_worker" field for this database.
@@ -1297,10 +1298,9 @@ launch_worker(TimestampTz now)
 				avdb->adl_next_worker =
 					TimestampTzPlusMilliseconds(now, autovacuum_naptime * 1000);
 
-				DLMoveToFront(elem);
+				dlist_move_head(&DatabaseList, iter.cur);
 				break;
 			}
-			elem = DLGetSucc(elem);
 		}
 
 		/*
@@ -1310,7 +1310,7 @@ launch_worker(TimestampTz now)
 		 * pgstat entry, but this is not a problem because we don't want to
 		 * schedule workers regularly into those in any case.
 		 */
-		if (elem == NULL)
+		if (!found)
 			rebuild_database_list(dbid);
 	}
 }
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index dff4c71..7060a1f 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -95,7 +95,7 @@
 #include "access/xlog.h"
 #include "bootstrap/bootstrap.h"
 #include "catalog/pg_control.h"
-#include "lib/dllist.h"
+#include "lib/ilist.h"
 #include "libpq/auth.h"
 #include "libpq/ip.h"
 #include "libpq/libpq.h"
@@ -146,10 +146,10 @@ typedef struct bkend
 	int			child_slot;		/* PMChildSlot for this backend, if any */
 	bool		is_autovacuum;	/* is it an autovacuum process? */
 	bool		dead_end;		/* is it going to send an error and quit? */
-	Dlelem		elem;			/* list link in BackendList */
+	dlist_node	elem;			/* list link in BackendList */
 } Backend;
 
-static Dllist *BackendList;
+static dlist_head BackendList = DLIST_STATIC_INIT(BackendList);
 
 #ifdef EXEC_BACKEND
 static Backend *ShmemBackendArray;
@@ -157,8 +157,10 @@ static Backend *ShmemBackendArray;
 
 /* The socket number we are listening for connections on */
 int			PostPortNumber;
+
 /* The directory names for Unix socket(s) */
 char	   *Unix_socket_directories;
+
 /* The TCP listen address(es) */
 char	   *ListenAddresses;
 
@@ -1028,11 +1030,6 @@ PostmasterMain(int argc, char *argv[])
 	set_stack_base();
 
 	/*
-	 * Initialize the list of active backends.
-	 */
-	BackendList = DLNewList();
-
-	/*
 	 * Initialize pipe (or process handle on Windows) that allows children to
 	 * wake up from sleep on postmaster death.
 	 */
@@ -1872,7 +1869,7 @@ processCancelRequest(Port *port, void *pkt)
 	Backend    *bp;
 
 #ifndef EXEC_BACKEND
-	Dlelem	   *curr;
+	dlist_iter  iter;
 #else
 	int			i;
 #endif
@@ -1886,9 +1883,9 @@ processCancelRequest(Port *port, void *pkt)
 	 * duplicate array in shared memory.
 	 */
 #ifndef EXEC_BACKEND
-	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
+	dlist_foreach(iter, &BackendList)
 	{
-		bp = (Backend *) DLE_VAL(curr);
+		bp = dlist_container(Backend, elem, iter.cur);
 #else
 	for (i = MaxLivePostmasterChildren() - 1; i >= 0; i--)
 	{
@@ -2648,7 +2645,7 @@ static void
 CleanupBackend(int pid,
 			   int exitstatus)	/* child's exit status. */
 {
-	Dlelem	   *curr;
+	dlist_mutable_iter iter;
 
 	LogChildExit(DEBUG2, _("server process"), pid, exitstatus);
 
@@ -2680,9 +2677,9 @@ CleanupBackend(int pid,
 		return;
 	}
 
-	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
+	dlist_foreach_modify(iter, &BackendList)
 	{
-		Backend    *bp = (Backend *) DLE_VAL(curr);
+		Backend    *bp = dlist_container(Backend, elem, iter.cur);
 
 		if (bp->pid == pid)
 		{
@@ -2701,7 +2698,7 @@ CleanupBackend(int pid,
 				ShmemBackendArrayRemove(bp);
 #endif
 			}
-			DLRemove(curr);
+			dlist_delete(&BackendList, iter.cur);
 			free(bp);
 			break;
 		}
@@ -2718,8 +2715,7 @@ CleanupBackend(int pid,
 static void
 HandleChildCrash(int pid, int exitstatus, const char *procname)
 {
-	Dlelem	   *curr,
-			   *next;
+	dlist_mutable_iter iter;
 	Backend    *bp;
 
 	/*
@@ -2734,10 +2730,10 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
 	}
 
 	/* Process regular backends */
-	for (curr = DLGetHead(BackendList); curr; curr = next)
+	dlist_foreach_modify(iter, &BackendList)
 	{
-		next = DLGetSucc(curr);
-		bp = (Backend *) DLE_VAL(curr);
+		bp = dlist_container(Backend, elem, iter.cur);
+
 		if (bp->pid == pid)
 		{
 			/*
@@ -2750,7 +2746,7 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
 				ShmemBackendArrayRemove(bp);
 #endif
 			}
-			DLRemove(curr);
+			dlist_delete(&BackendList, iter.cur);
 			free(bp);
 			/* Keep looping so we can signal remaining backends */
 		}
@@ -3113,7 +3109,7 @@ PostmasterStateMachine(void)
 		 * normal state transition leading up to PM_WAIT_DEAD_END, or during
 		 * FatalError processing.
 		 */
-		if (DLGetHead(BackendList) == NULL &&
+		if (dlist_is_empty(&BackendList) &&
 			PgArchPID == 0 && PgStatPID == 0)
 		{
 			/* These other guys should be dead already */
@@ -3239,12 +3235,12 @@ signal_child(pid_t pid, int signal)
 static bool
 SignalSomeChildren(int signal, int target)
 {
-	Dlelem	   *curr;
+	dlist_iter  iter;
 	bool		signaled = false;
 
-	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
+	dlist_foreach(iter, &BackendList)
 	{
-		Backend    *bp = (Backend *) DLE_VAL(curr);
+		Backend    *bp = dlist_container(Backend, elem, iter.cur);
 
 		if (bp->dead_end)
 			continue;
@@ -3382,8 +3378,8 @@ BackendStartup(Port *port)
 	 */
 	bn->pid = pid;
 	bn->is_autovacuum = false;
-	DLInitElem(&bn->elem, bn);
-	DLAddHead(BackendList, &bn->elem);
+	dlist_push_head(&BackendList, &bn->elem);
+
 #ifdef EXEC_BACKEND
 	if (!bn->dead_end)
 		ShmemBackendArrayAdd(bn);
@@ -4498,12 +4494,12 @@ PostmasterRandom(void)
 static int
 CountChildren(int target)
 {
-	Dlelem	   *curr;
+	dlist_iter  iter;
 	int			cnt = 0;
 
-	for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
+	dlist_foreach(iter, &BackendList)
 	{
-		Backend    *bp = (Backend *) DLE_VAL(curr);
+		Backend    *bp = dlist_container(Backend, elem, iter.cur);
 
 		if (bp->dead_end)
 			continue;
@@ -4682,8 +4678,7 @@ StartAutovacuumWorker(void)
 			if (bn->pid > 0)
 			{
 				bn->is_autovacuum = true;
-				DLInitElem(&bn->elem, bn);
-				DLAddHead(BackendList, &bn->elem);
+				dlist_push_head(&BackendList, &bn->elem);
 #ifdef EXEC_BACKEND
 				ShmemBackendArrayAdd(bn);
 #endif
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index d6f6b1c..230ddf4 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -291,7 +291,7 @@ CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple)
 static void
 CatCachePrintStats(int code, Datum arg)
 {
-	CatCache   *cache;
+	slist_iter  iter;
 	long		cc_searches = 0;
 	long		cc_hits = 0;
 	long		cc_neg_hits = 0;
@@ -300,8 +300,10 @@ CatCachePrintStats(int code, Datum arg)
 	long		cc_lsearches = 0;
 	long		cc_lhits = 0;
 
-	for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next)
+	slist_foreach(iter, &CacheHdr->ch_caches)
 	{
+		CatCache   *cache = slist_container(CatCache, cc_next, iter.cur);
+
 		if (cache->cc_ntup == 0 && cache->cc_searches == 0)
 			continue;			/* don't print unused caches */
 		elog(DEBUG2, "catcache %s/%u: %d tup, %ld srch, %ld+%ld=%ld hits, %ld+%ld=%ld loads, %ld invals, %ld lsrch, %ld lhits",
@@ -368,8 +370,7 @@ CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
 		return;					/* nothing left to do */
 	}
 
-	/* delink from linked list */
-	DLRemove(&ct->cache_elem);
+	dlist_delete(ct->cache_bucket, &ct->cache_elem);
 
 	/* free associated tuple data */
 	if (ct->tuple.t_data != NULL)
@@ -412,7 +413,7 @@ CatCacheRemoveCList(CatCache *cache, CatCList *cl)
 	}
 
 	/* delink from linked list */
-	DLRemove(&cl->cache_elem);
+	dlist_delete(&cache->cc_lists, &cl->cache_elem);
 
 	/* free associated tuple data */
 	if (cl->tuple.t_data != NULL)
@@ -442,18 +443,18 @@ CatCacheRemoveCList(CatCache *cache, CatCList *cl)
 void
 CatalogCacheIdInvalidate(int cacheId, uint32 hashValue)
 {
-	CatCache   *ccp;
+	slist_iter cache_iter;
 
 	CACHE1_elog(DEBUG2, "CatalogCacheIdInvalidate: called");
 
 	/*
 	 * inspect caches to find the proper cache
 	 */
-	for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next)
+	slist_foreach(cache_iter, &CacheHdr->ch_caches)
 	{
 		Index		hashIndex;
-		Dlelem	   *elt,
-				   *nextelt;
+		dlist_mutable_iter iter;
+		CatCache   *ccp = slist_container(CatCache, cc_next, cache_iter.cur);
 
 		if (cacheId != ccp->id)
 			continue;
@@ -468,11 +469,9 @@ CatalogCacheIdInvalidate(int cacheId, uint32 hashValue)
 		 * Invalidate *all* CatCLists in this cache; it's too hard to tell
 		 * which searches might still be correct, so just zap 'em all.
 		 */
-		for (elt = DLGetHead(&ccp->cc_lists); elt; elt = nextelt)
+		dlist_foreach_modify(iter, &ccp->cc_lists)
 		{
-			CatCList   *cl = (CatCList *) DLE_VAL(elt);
-
-			nextelt = DLGetSucc(elt);
+			CatCList   *cl = dlist_container(CatCList, cache_elem, iter.cur);
 
 			if (cl->refcount > 0)
 				cl->dead = true;
@@ -484,12 +483,9 @@ CatalogCacheIdInvalidate(int cacheId, uint32 hashValue)
 		 * inspect the proper hash bucket for tuple matches
 		 */
 		hashIndex = HASH_INDEX(hashValue, ccp->cc_nbuckets);
-
-		for (elt = DLGetHead(&ccp->cc_bucket[hashIndex]); elt; elt = nextelt)
+		dlist_foreach_modify(iter, &ccp->cc_bucket[hashIndex])
 		{
-			CatCTup    *ct = (CatCTup *) DLE_VAL(elt);
-
-			nextelt = DLGetSucc(elt);
+			CatCTup    *ct = dlist_container(CatCTup, cache_elem, iter.cur);
 
 			if (hashValue == ct->hash_value)
 			{
@@ -557,17 +553,18 @@ AtEOXact_CatCache(bool isCommit)
 #ifdef USE_ASSERT_CHECKING
 	if (assert_enabled)
 	{
-		CatCache   *ccp;
+		slist_iter  cache_iter;
 
-		for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next)
+		slist_foreach(cache_iter, &(CacheHdr->ch_caches))
 		{
-			Dlelem	   *elt;
+			CatCache   *ccp = slist_container(CatCache, cc_next, cache_iter.cur);
+			dlist_iter  iter;
 			int			i;
 
 			/* Check CatCLists */
-			for (elt = DLGetHead(&ccp->cc_lists); elt; elt = DLGetSucc(elt))
+			dlist_foreach(iter, &ccp->cc_lists)
 			{
-				CatCList   *cl = (CatCList *) DLE_VAL(elt);
+				CatCList   *cl = dlist_container(CatCList, cache_elem, iter.cur);
 
 				Assert(cl->cl_magic == CL_MAGIC);
 				Assert(cl->refcount == 0);
@@ -577,11 +574,11 @@ AtEOXact_CatCache(bool isCommit)
 			/* Check individual tuples */
 			for (i = 0; i < ccp->cc_nbuckets; i++)
 			{
-				for (elt = DLGetHead(&ccp->cc_bucket[i]);
-					 elt;
-					 elt = DLGetSucc(elt))
+				dlist_head *bucket = &ccp->cc_bucket[i];
+
+				dlist_foreach(iter, bucket)
 				{
-					CatCTup    *ct = (CatCTup *) DLE_VAL(elt);
+					CatCTup    *ct = dlist_container(CatCTup, cache_elem, iter.cur);
 
 					Assert(ct->ct_magic == CT_MAGIC);
 					Assert(ct->refcount == 0);
@@ -604,16 +601,13 @@ AtEOXact_CatCache(bool isCommit)
 static void
 ResetCatalogCache(CatCache *cache)
 {
-	Dlelem	   *elt,
-			   *nextelt;
+	dlist_mutable_iter iter;
 	int			i;
 
 	/* Remove each list in this cache, or at least mark it dead */
-	for (elt = DLGetHead(&cache->cc_lists); elt; elt = nextelt)
+	dlist_foreach_modify(iter, &cache->cc_lists)
 	{
-		CatCList   *cl = (CatCList *) DLE_VAL(elt);
-
-		nextelt = DLGetSucc(elt);
+		CatCList   *cl = dlist_container(CatCList, cache_elem, iter.cur);
 
 		if (cl->refcount > 0)
 			cl->dead = true;
@@ -624,11 +618,11 @@ ResetCatalogCache(CatCache *cache)
 	/* Remove each tuple in this cache, or at least mark it dead */
 	for (i = 0; i < cache->cc_nbuckets; i++)
 	{
-		for (elt = DLGetHead(&cache->cc_bucket[i]); elt; elt = nextelt)
-		{
-			CatCTup    *ct = (CatCTup *) DLE_VAL(elt);
+		dlist_head *bucket = &cache->cc_bucket[i];
 
-			nextelt = DLGetSucc(elt);
+		dlist_foreach_modify(iter, bucket)
+		{
+			CatCTup    *ct = dlist_container(CatCTup, cache_elem, iter.cur);
 
 			if (ct->refcount > 0 ||
 				(ct->c_list && ct->c_list->refcount > 0))
@@ -654,12 +648,16 @@ ResetCatalogCache(CatCache *cache)
 void
 ResetCatalogCaches(void)
 {
-	CatCache   *cache;
+	slist_iter    iter;
 
 	CACHE1_elog(DEBUG2, "ResetCatalogCaches called");
 
-	for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next)
+	slist_foreach(iter, &CacheHdr->ch_caches)
+	{
+		CatCache   *cache = slist_container(CatCache, cc_next, iter.cur);
+
 		ResetCatalogCache(cache);
+	}
 
 	CACHE1_elog(DEBUG2, "end of ResetCatalogCaches call");
 }
@@ -680,12 +678,14 @@ ResetCatalogCaches(void)
 void
 CatalogCacheFlushCatalog(Oid catId)
 {
-	CatCache   *cache;
+	slist_iter  iter;
 
 	CACHE2_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
 
-	for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next)
+	slist_foreach(iter, &(CacheHdr->ch_caches))
 	{
+		CatCache   *cache = slist_container(CatCache, cc_next, iter.cur);
+
 		/* Does this cache store tuples of the target catalog? */
 		if (cache->cc_reloid == catId)
 		{
@@ -760,7 +760,7 @@ InitCatCache(int id,
 	if (CacheHdr == NULL)
 	{
 		CacheHdr = (CatCacheHeader *) palloc(sizeof(CatCacheHeader));
-		CacheHdr->ch_caches = NULL;
+		slist_init(&CacheHdr->ch_caches);
 		CacheHdr->ch_ntup = 0;
 #ifdef CATCACHE_STATS
 		/* set up to dump stats at backend exit */
@@ -770,10 +770,8 @@ InitCatCache(int id,
 
 	/*
 	 * allocate a new cache structure
-	 *
-	 * Note: we assume zeroing initializes the Dllist headers correctly
 	 */
-	cp = (CatCache *) palloc0(sizeof(CatCache) + nbuckets * sizeof(Dllist));
+	cp = (CatCache *) palloc0(sizeof(CatCache) + nbuckets * sizeof(dlist_node));
 
 	/*
 	 * initialize the cache's relation information for the relation
@@ -792,6 +790,11 @@ InitCatCache(int id,
 	for (i = 0; i < nkeys; ++i)
 		cp->cc_key[i] = key[i];
 
+	dlist_init(&cp->cc_lists);
+
+	for (i = 0; i < nbuckets; i++)
+		dlist_init(&cp->cc_bucket[i]);
+
 	/*
 	 * new cache is initialized as far as we can go for now. print some
 	 * debugging information, if appropriate.
@@ -801,8 +804,7 @@ InitCatCache(int id,
 	/*
 	 * add completed cache to top of group header's list
 	 */
-	cp->cc_next = CacheHdr->ch_caches;
-	CacheHdr->ch_caches = cp;
+	slist_push_head(&CacheHdr->ch_caches, &cp->cc_next);
 
 	/*
 	 * back to the old context before we return...
@@ -1060,7 +1062,8 @@ SearchCatCache(CatCache *cache,
 	ScanKeyData cur_skey[CATCACHE_MAXKEYS];
 	uint32		hashValue;
 	Index		hashIndex;
-	Dlelem	   *elt;
+	dlist_mutable_iter  iter;
+	dlist_head *bucket;
 	CatCTup    *ct;
 	Relation	relation;
 	SysScanDesc scandesc;
@@ -1094,13 +1097,13 @@ SearchCatCache(CatCache *cache,
 	/*
 	 * scan the hash bucket until we find a match or exhaust our tuples
 	 */
-	for (elt = DLGetHead(&cache->cc_bucket[hashIndex]);
-		 elt;
-		 elt = DLGetSucc(elt))
+	bucket = &cache->cc_bucket[hashIndex];
+
+	dlist_foreach_modify(iter, bucket)
 	{
 		bool		res;
 
-		ct = (CatCTup *) DLE_VAL(elt);
+		ct = dlist_container(CatCTup, cache_elem, iter.cur);
 
 		if (ct->dead)
 			continue;			/* ignore dead entries */
@@ -1125,7 +1128,7 @@ SearchCatCache(CatCache *cache,
 		 * most frequently accessed elements in any hashbucket will tend to be
 		 * near the front of the hashbucket's list.)
 		 */
-		DLMoveToFront(&ct->cache_elem);
+		dlist_move_head(bucket, &ct->cache_elem);
 
 		/*
 		 * If it's a positive entry, bump its refcount and return it. If it's
@@ -1340,7 +1343,7 @@ SearchCatCacheList(CatCache *cache,
 {
 	ScanKeyData cur_skey[CATCACHE_MAXKEYS];
 	uint32		lHashValue;
-	Dlelem	   *elt;
+	dlist_iter  iter;
 	CatCList   *cl;
 	CatCTup    *ct;
 	List	   *volatile ctlist;
@@ -1382,13 +1385,11 @@ SearchCatCacheList(CatCache *cache,
 	/*
 	 * scan the items until we find a match or exhaust our list
 	 */
-	for (elt = DLGetHead(&cache->cc_lists);
-		 elt;
-		 elt = DLGetSucc(elt))
+	dlist_foreach(iter, &cache->cc_lists)
 	{
 		bool		res;
 
-		cl = (CatCList *) DLE_VAL(elt);
+		cl = dlist_container(CatCList, cache_elem, iter.cur);
 
 		if (cl->dead)
 			continue;			/* ignore dead entries */
@@ -1416,7 +1417,7 @@ SearchCatCacheList(CatCache *cache,
 		 * since there's no point in that unless they are searched for
 		 * individually.)
 		 */
-		DLMoveToFront(&cl->cache_elem);
+		dlist_move_head(&cache->cc_lists, &cl->cache_elem);
 
 		/* Bump the list's refcount and return it */
 		ResourceOwnerEnlargeCatCacheListRefs(CurrentResourceOwner);
@@ -1468,6 +1469,8 @@ SearchCatCacheList(CatCache *cache,
 		{
 			uint32		hashValue;
 			Index		hashIndex;
+			bool		found = false;
+			dlist_head *bucket;
 
 			/*
 			 * See if there's an entry for this tuple already.
@@ -1476,11 +1479,10 @@ SearchCatCacheList(CatCache *cache,
 			hashValue = CatalogCacheComputeTupleHashValue(cache, ntp);
 			hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets);
 
-			for (elt = DLGetHead(&cache->cc_bucket[hashIndex]);
-				 elt;
-				 elt = DLGetSucc(elt))
+			bucket = &cache->cc_bucket[hashIndex];
+			dlist_foreach(iter, bucket)
 			{
-				ct = (CatCTup *) DLE_VAL(elt);
+				ct = dlist_container(CatCTup, cache_elem, iter.cur);
 
 				if (ct->dead || ct->negative)
 					continue;	/* ignore dead and negative entries */
@@ -1498,10 +1500,11 @@ SearchCatCacheList(CatCache *cache,
 				if (ct->c_list)
 					continue;
 
+				found = true;
 				break;			/* A-OK */
 			}
 
-			if (elt == NULL)
+			if (!found)
 			{
 				/* We didn't find a usable entry, so make a new one */
 				ct = CatalogCacheCreateEntry(cache, ntp,
@@ -1564,7 +1567,6 @@ SearchCatCacheList(CatCache *cache,
 
 	cl->cl_magic = CL_MAGIC;
 	cl->my_cache = cache;
-	DLInitElem(&cl->cache_elem, cl);
 	cl->refcount = 0;			/* for the moment */
 	cl->dead = false;
 	cl->ordered = ordered;
@@ -1587,7 +1589,7 @@ SearchCatCacheList(CatCache *cache,
 	}
 	Assert(i == nmembers);
 
-	DLAddHead(&cache->cc_lists, &cl->cache_elem);
+	dlist_push_head(&cache->cc_lists, &cl->cache_elem);
 
 	/* Finally, bump the list's refcount and return it */
 	cl->refcount++;
@@ -1664,14 +1666,15 @@ CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp,
 	 */
 	ct->ct_magic = CT_MAGIC;
 	ct->my_cache = cache;
-	DLInitElem(&ct->cache_elem, (void *) ct);
+	ct->cache_bucket = &cache->cc_bucket[hashIndex];
+
 	ct->c_list = NULL;
 	ct->refcount = 0;			/* for the moment */
 	ct->dead = false;
 	ct->negative = negative;
 	ct->hash_value = hashValue;
 
-	DLAddHead(&cache->cc_bucket[hashIndex], &ct->cache_elem);
+	dlist_push_head(ct->cache_bucket, &ct->cache_elem);
 
 	cache->cc_ntup++;
 	CacheHdr->ch_ntup++;
@@ -1785,7 +1788,7 @@ PrepareToInvalidateCacheTuple(Relation relation,
 							  HeapTuple newtuple,
 							  void (*function) (int, uint32, Oid))
 {
-	CatCache   *ccp;
+	slist_iter  iter;
 	Oid			reloid;
 
 	CACHE1_elog(DEBUG2, "PrepareToInvalidateCacheTuple: called");
@@ -1808,10 +1811,11 @@ PrepareToInvalidateCacheTuple(Relation relation,
 	 * ----------------
 	 */
 
-	for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next)
+	slist_foreach(iter, &(CacheHdr->ch_caches))
 	{
 		uint32		hashvalue;
 		Oid			dbid;
+		CatCache   *ccp = slist_container(CatCache, cc_next, iter.cur);
 
 		if (ccp->cc_reloid != reloid)
 			continue;
diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h
index d91700a..cc6dab2 100644
--- a/src/include/utils/catcache.h
+++ b/src/include/utils/catcache.h
@@ -22,7 +22,7 @@
 
 #include "access/htup.h"
 #include "access/skey.h"
-#include "lib/dllist.h"
+#include "lib/ilist.h"
 #include "utils/relcache.h"
 
 /*
@@ -37,7 +37,7 @@
 typedef struct catcache
 {
 	int			id;				/* cache identifier --- see syscache.h */
-	struct catcache *cc_next;	/* link to next catcache */
+	slist_node	cc_next;		/* list link */
 	const char *cc_relname;		/* name of relation the tuples come from */
 	Oid			cc_reloid;		/* OID of relation the tuples come from */
 	Oid			cc_indexoid;	/* OID of index matching cache keys */
@@ -51,7 +51,7 @@ typedef struct catcache
 	ScanKeyData cc_skey[CATCACHE_MAXKEYS];		/* precomputed key info for
 												 * heap scans */
 	bool		cc_isname[CATCACHE_MAXKEYS];	/* flag "name" key columns */
-	Dllist		cc_lists;		/* list of CatCList structs */
+	dlist_head	cc_lists;		/* list of CatCList structs */
 #ifdef CATCACHE_STATS
 	long		cc_searches;	/* total # searches against this cache */
 	long		cc_hits;		/* # of matches against existing entry */
@@ -66,7 +66,7 @@ typedef struct catcache
 	long		cc_lsearches;	/* total # list-searches */
 	long		cc_lhits;		/* # of matches against existing lists */
 #endif
-	Dllist		cc_bucket[1];	/* hash buckets --- VARIABLE LENGTH ARRAY */
+	dlist_head	cc_bucket[1];	/* hash buckets --- VARIABLE LENGTH ARRAY */
 } CatCache;						/* VARIABLE LENGTH STRUCT */
 
 
@@ -77,11 +77,12 @@ typedef struct catctup
 	CatCache   *my_cache;		/* link to owning catcache */
 
 	/*
-	 * Each tuple in a cache is a member of a Dllist that stores the elements
-	 * of its hash bucket.	We keep each Dllist in LRU order to speed repeated
+	 * Each tuple in a cache is a member of a dlist that stores the elements
+	 * of its hash bucket.	We keep each dlist in LRU order to speed repeated
 	 * lookups.
 	 */
-	Dlelem		cache_elem;		/* list member of per-bucket list */
+	dlist_node	cache_elem;		/* list member of per-bucket list */
+	dlist_head *cache_bucket;	/* containing bucket dlist */
 
 	/*
 	 * The tuple may also be a member of at most one CatCList.	(If a single
@@ -139,7 +140,7 @@ typedef struct catclist
 	 * might not be true during bootstrap or recovery operations. (namespace.c
 	 * is able to save some cycles when it is true.)
 	 */
-	Dlelem		cache_elem;		/* list member of per-catcache list */
+	dlist_node	cache_elem;		/* list member of per-catcache list */
 	int			refcount;		/* number of active references */
 	bool		dead;			/* dead but not yet removed? */
 	bool		ordered;		/* members listed in index order? */
@@ -153,7 +154,7 @@ typedef struct catclist
 
 typedef struct catcacheheader
 {
-	CatCache   *ch_caches;		/* head of list of CatCache structs */
+	slist_head	ch_caches;		/* head of list of CatCache structs */
 	int			ch_ntup;		/* # of tuples in all caches */
 } CatCacheHeader;
 
-- 
1.7.12.289.g0ce9864.dirty

