On Thursday, June 28, 2012 06:23:05 PM Robert Haas wrote:
> On Tue, Jun 26, 2012 at 7:26 PM, Andres Freund <[email protected]>
wrote:
> > Attached are three patches:
> > 1. embedded list implementation
> > 2. make the list implementation usable without USE_INLINE
> > 3. convert all callers to ilist.h away from dllist.h
>
> This code doesn't follow PostgreSQL coding style guidelines; in a
> function definition, the name must start on its own line.
Hrmpf. Yes.
> Also, stuff like this is grossly unlike what's done elsewhere; use the same
> formatting as e.g. foreach:
> +#define ilist_d_reverse_foreach(name, ptr) for(name =
> (ptr)->head.prev; \
> + name != &(ptr)->head; \
> + name = name->prev)
Its not only unlike the rest its also ugly... Fixed.
> And this is definitely NOT going to survive pgindent:
>
> + for(cur = head->head.prev;
> + cur != &head->head;
> + cur = cur->prev){
> + if(!(cur) ||
> + !(cur->next) ||
> + !(cur->prev) ||
> + !(cur->prev->next == cur) ||
> + !(cur->next->prev == cur))
> + {
> + elog(ERROR, "double linked list is corrupted");
> + }
> + }
I changed the for() contents to one line. I don't think I can write anything
that won't be changed by pgindent for the if()s contents.
> And this is another meme we don't use elsewhere; add an explicit NULL test:
>
> + while ((cur = last->next))
Fixed.
> And then there's stuff like this:
>
> + if(!cur){
> + elog(ERROR, "single linked list is corrupted");
> + }
Fixed the places that I found.
> Aside from the formatting issues, I think it would be sensible to
> preserve the terminology of talking about the "head" and "tail" of a
> list that we use elsewhere, instead of calling them the "front" and
> "back" as you've done here. I would suggest that instead of add_after
> and add_before you use the names insert_after and insert_before, which
> I think is more clear; also instead of remove, I think you should say
> delete, for consistency with pg_list.h.
Heh. Ive been poisoned from using c++ too much (thats partially stl names).
Changed.
> A number of these inlined functions could be rewritten as macros -
> e.g. ilist_d_has_next, ilist_d_has_prev, ilist_d_is_empty. Since some
> things are written as macros anyway maybe it's good to do all the
> one-liners that way, although I guess it doesn't matter that much.
I find inline functions preferrable because of multiple evaluation stuff. The
macros are macros because of the dynamic return type and other similar issues
which cannot be done in plain C.
> I also agree with your XXX comment that ilist_s_remove should probably
> be out of line.
Done.
Looks good now?
Andres
--
Andres Freund http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
From c3c80925e780489351c4de210364e55d223f02a8 Mon Sep 17 00:00:00 2001
From: Andres Freund <[email protected]>
Date: Sun, 6 May 2012 00:26:35 +0200
Subject: [PATCH 1/2] Add embedded list interface
Adds a single and a double linked list which can easily embedded into other
datastructures and can be used without additional memory allocations.
---
src/backend/lib/Makefile | 2 +-
src/backend/lib/ilist.c | 123 ++++++++++++
src/include/lib/ilist.h | 468 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 592 insertions(+), 1 deletion(-)
create mode 100644 src/backend/lib/ilist.c
create mode 100644 src/include/lib/ilist.h
diff --git a/src/backend/lib/Makefile b/src/backend/lib/Makefile
index 2e1061e..c94297a 100644
--- a/src/backend/lib/Makefile
+++ b/src/backend/lib/Makefile
@@ -12,6 +12,6 @@ subdir = src/backend/lib
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
-OBJS = dllist.o stringinfo.o
+OBJS = dllist.o stringinfo.o ilist.o
include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/lib/ilist.c b/src/backend/lib/ilist.c
new file mode 100644
index 0000000..f78ac51
--- /dev/null
+++ b/src/backend/lib/ilist.c
@@ -0,0 +1,123 @@
+/*-------------------------------------------------------------------------
+ *
+ * ilist.c
+ * support for integrated/inline double and single linked lists
+ *
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/lib/ilist.c
+ *
+ * NOTES
+ *
+ * This function only contains testing code for inline single/double linked
+ * lists.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+/*
+ * If inlines aren't available include the function as defined in the header,
+ * but without 'static inline' defined. That way we do not have to duplicate
+ * their functionality.
+ */
+#ifndef USE_INLINE
+#define ILIST_USE_DECLARATION
+#endif
+
+#include "lib/ilist.h"
+
+#ifndef USE_INLINE
+#undef ILIST_USE_DECLARATION
+#endif
+
+/*
+ * removes a node from a list
+ *
+ * Attention: O(n)
+ */
+void
+ilist_s_delete(ilist_s_head *head, ilist_s_node *node)
+{
+ ilist_s_node *last = &head->head;
+ ilist_s_node *cur;
+#ifdef ILIST_DEBUG
+ bool found = false;
+#endif
+ while ((cur = last->next) != NULL)
+ {
+ if (cur == node)
+ {
+ last->next = cur->next;
+#ifdef ILIST_DEBUG
+ found = true;
+#endif
+ break;
+ }
+ last = cur;
+ }
+ ilist_s_check(head);
+
+#ifdef ILIST_DEBUG
+ if(!found)
+ elog(ERROR, "tried to delete nonexisting node");
+#endif
+}
+
+#ifdef ILIST_DEBUG
+void ilist_d_check(ilist_d_head* head)
+{
+ ilist_d_node *cur;
+
+ if(!head || !(&head->head))
+ elog(ERROR, "double linked list head is not properly initialized");
+
+ for(cur = head->head.next; cur != &head->head; cur = cur->next)
+ {
+ if(!(cur) ||
+ !(cur->next) ||
+ !(cur->prev) ||
+ !(cur->prev->next == cur) ||
+ !(cur->next->prev == cur))
+ {
+ elog(ERROR, "double linked list is corrupted");
+ }
+ }
+
+ for(cur = head->head.prev; cur != &head->head; cur = cur->prev)
+ {
+ if(!(cur) ||
+ !(cur->next) ||
+ !(cur->prev) ||
+ !(cur->prev->next == cur) ||
+ !(cur->next->prev == cur))
+ {
+ elog(ERROR, "double linked list is corrupted");
+ }
+ }
+}
+
+void ilist_s_check(ilist_s_head* head)
+{
+ ilist_s_node *cur;
+
+ if(!head ||
+ !(&head->head))
+ elog(ERROR, "single linked list head is not properly initialized");
+
+ /*
+ * there isn't much we can test in a single linked list except that its
+ * really circular
+ */
+ for(cur = head->head.next; cur != &head->head; cur = cur->next)
+ {
+ if(!cur)
+ elog(ERROR, "single linked list is corrupted");
+ }
+}
+
+#endif /* ILIST_DEBUG */
diff --git a/src/include/lib/ilist.h b/src/include/lib/ilist.h
new file mode 100644
index 0000000..ef66d39
--- /dev/null
+++ b/src/include/lib/ilist.h
@@ -0,0 +1,468 @@
+/*-------------------------------------------------------------------------
+ *
+ * ilist.h
+ * integrated/inline double and single linked lists without memory
+ * managment overhead
+ *
+ * This is intended to be used in the following manner:
+ *
+ * #include "lib/ilist.h"
+ *
+ * typedef struct something_in_a_list
+ * {
+ * int value;
+ * int somethingelse;
+ * ilist_d_head values;
+ * } something_in_a_list;
+ *
+ * typedef struct value_in_a_list
+ * {
+ * int data;
+ * int somethingelse;
+ * ilist_d_node list_node;
+ * } value_in_a_list;
+ *
+ * something_in_a_list *somelist = get_blarg();
+ *
+ * ilist_d_push_head(somelist, &get_value_in_a_list()->list_node);
+ * ...
+ * ilist_d_push_head(somelist, &get_value_in_a_list()->list_node);
+ * ...
+ * ...
+ * ilist_d_node *node, *next;
+ *
+ * ilist_d_foreach(node, somelist)
+ * {
+ * value_in_a_list *val = ilist_container(value_in_a_list, list_node, node);
+ * do_something_with_val(val);
+ * }
+ *
+ * ilist_d_foreach_modify(node, next, somelist)
+ * {
+ * ilist_d_delete(node);
+ * }
+ *
+ * This allows somewhat convenient list manipulation with low overhead.
+ *
+ * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/lib/ilist.h
+ *-------------------------------------------------------------------------
+ */
+#ifndef ILIST_H
+#define ILIST_H
+
+/*
+ * enable for extra debugging. This is rather expensive so its not enabled by
+ * default even with --enable-cassert
+*/
+/* #define ILIST_DEBUG */
+
+/*
+ * gcc warns about unused parameters if -Wunused-parameter is specified (part
+ * of -Wextra ). In the cases below its perfectly fine not to use those
+ * parameters because they are just passed to make the interface consistent and
+ * to allow debugging in case of ILIST_DEBUG.
+ *
+ */
+#ifdef __GNUC__
+#define unused_attr __attribute__((unused))
+#else
+#define unused_attr
+#endif
+
+/*
+ * struct to embed in other structs that need to be part of a double linked
+ * list.
+ */
+typedef struct ilist_d_node ilist_d_node;
+struct ilist_d_node
+{
+ ilist_d_node* prev;
+ ilist_d_node* next;
+};
+
+/*
+ * Head of a double linked list. Lists are internally *always* circularly
+ * linked, even when empty. This allows to do many many manipulations without
+ * branches which is beneficial performancewise.
+ */
+typedef struct
+{
+ ilist_d_node head;
+} ilist_d_head;
+
+/*
+ * struct to embed in other structs that need to be part of a single linked
+ * list.
+ */
+typedef struct ilist_s_node ilist_s_node;
+struct ilist_s_node
+{
+ ilist_s_node* next;
+};
+
+/*
+ * Head of a single linked list.
+ */
+typedef struct
+{
+ ilist_s_node head;
+} ilist_s_head;
+
+
+#ifdef USE_INLINE
+#define INLINE_IF_POSSIBLE static inline
+#define ILIST_USE_DECLARATION
+#else
+#define INLINE_IF_POSSIBLE
+#endif
+
+/* Functions we want to be inlined if possible */
+#ifndef USE_INLINE
+extern void ilist_d_check(unused_attr ilist_d_head* head);
+extern void ilist_d_init(ilist_d_head *head);
+extern void ilist_d_push_head(ilist_d_head *head, ilist_d_node *node);
+extern void ilist_d_push_tail(ilist_d_head *head, ilist_d_node *node);
+extern void ilist_d_insert_after(unused_attr ilist_d_head *head,
+ ilist_d_node *after, ilist_d_node *node);
+extern void ilist_d_insert_before(unused_attr ilist_d_head *head,
+ ilist_d_node *before, ilist_d_node *node);
+extern void ilist_d_delete(unused_attr ilist_d_head *head, ilist_d_node *node);
+extern ilist_d_node* ilist_d_pop_head(ilist_d_head *head);
+extern void ilist_d_move_head(ilist_d_head *head, ilist_d_node *node);
+extern bool ilist_d_has_next(ilist_d_head *head, ilist_d_node *node);
+extern bool ilist_d_has_prev(ilist_d_head *head, ilist_d_node *node);
+extern bool ilist_d_is_empty(ilist_d_head *head);
+extern void ilist_d_check(ilist_d_head* head);
+
+extern void ilist_s_init(ilist_s_head *head);
+extern void ilist_s_push_head(ilist_s_head *head, ilist_s_node *node);
+extern ilist_s_node* ilist_s_pop_head(ilist_s_head *head);
+extern void ilist_s_insert_after(unused_attr ilist_s_head *head,
+ ilist_s_node *after, ilist_s_node *node);
+extern bool ilist_s_is_empty(ilist_s_head *head);
+extern bool ilist_s_has_next(unused_attr ilist_s_head* head,
+ ilist_s_node *node);
+
+#endif /* USE_INLINE */
+
+/* Functions which are too big to be inline */
+
+/*
+ * deletes a node from a list
+ *
+ * Attention: O(n)
+ */
+extern void ilist_s_delete(ilist_s_head *head, ilist_s_node *node);
+
+#ifdef ILIST_DEBUG
+extern void ilist_d_check(ilist_d_head* head);
+extern void ilist_s_check(ilist_s_head* head);
+#else
+#define ilist_d_check(head)
+#define ilist_s_check(head)
+#endif /*ILIST_DEBUG*/
+
+
+/*
+ * The following function declarations are only used if inlining is supported
+ * or when included from a file that explicitly declares USE_DECLARATION
+ */
+#ifdef ILIST_USE_DECLARATION
+
+/*
+ * Initialize the head of a list. Previous state will be thrown away without
+ * any cleanup.
+ */
+INLINE_IF_POSSIBLE void
+ilist_d_init(ilist_d_head *head)
+{
+ head->head.next = head->head.prev = &head->head;
+ ilist_d_check(head);
+}
+
+/*
+ * inserts a node at the beginning of the list
+ */
+INLINE_IF_POSSIBLE void
+ilist_d_push_head(ilist_d_head *head, ilist_d_node *node)
+{
+ node->next = head->head.next;
+ node->prev = &head->head;
+ node->next->prev = node;
+ head->head.next = node;
+ ilist_d_check(head);
+}
+
+
+/*
+ * inserts a node at the end of the list
+ */
+INLINE_IF_POSSIBLE void
+ilist_d_push_tail(ilist_d_head *head, ilist_d_node *node)
+{
+ node->next = &head->head;
+ node->prev = head->head.prev;
+ node->prev->next = node;
+ head->head.prev = node;
+ ilist_d_check(head);
+}
+
+
+/*
+ * insert a node after another *in the same list*
+ */
+INLINE_IF_POSSIBLE void
+ilist_d_insert_after(unused_attr ilist_d_head *head, ilist_d_node *after,
+ ilist_d_node *node)
+{
+ ilist_d_check(head);
+ node->prev = after;
+ node->next = after->next;
+ after->next = node;
+ node->next->prev = node;
+ ilist_d_check(head);
+}
+
+/*
+ * insert a node after another *in the same list*
+ */
+INLINE_IF_POSSIBLE void
+ilist_d_insert_before(unused_attr ilist_d_head *head, ilist_d_node *before,
+ ilist_d_node *node)
+{
+ ilist_d_check(head);
+ node->prev = before->prev;
+ node->next = before;
+ before->prev = node;
+ node->prev->next = node;
+ ilist_d_check(head);
+}
+
+
+/*
+ * deletes a node from a list
+ */
+INLINE_IF_POSSIBLE void
+ilist_d_delete(unused_attr ilist_d_head *head, ilist_d_node *node)
+{
+ ilist_d_check(head);
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+ ilist_d_check(head);
+}
+
+/*
+ * deletes the first node from a list or returns NULL
+ */
+INLINE_IF_POSSIBLE ilist_d_node*
+ilist_d_pop_head(ilist_d_head *head)
+{
+ ilist_d_node* ret;
+
+ if (&head->head == head->head.next)
+ return NULL;
+
+ ret = head->head.next;
+ ilist_d_delete(head, head->head.next);
+ return ret;
+}
+
+/*
+ * moves an element that has to be in the list to the head of the list
+ */
+INLINE_IF_POSSIBLE void
+ilist_d_move_head(ilist_d_head *head, ilist_d_node *node)
+{
+ /* fast path if its already at the head */
+ if(&head->head == node)
+ return;
+ ilist_d_delete(head, node);
+ ilist_d_push_head(head, node);
+ ilist_d_check(head);
+}
+
+/*
+ * Check whether the passed node is the last element in the list
+ */
+INLINE_IF_POSSIBLE bool
+ilist_d_has_next(ilist_d_head *head, ilist_d_node *node)
+{
+ return node->next != &head->head;
+}
+
+/*
+ * Check whether the passed node is the first element in the list
+ */
+INLINE_IF_POSSIBLE bool
+ilist_d_has_prev(ilist_d_head *head, ilist_d_node *node)
+{
+ return node->prev != &head->head;
+}
+
+/*
+ * Check whether the list is empty.
+ */
+INLINE_IF_POSSIBLE bool
+ilist_d_is_empty(ilist_d_head *head)
+{
+ return head->head.next == head->head.prev;
+}
+
+#endif /* ILIST_USE_DECLARATION */
+
+/*
+ * Return the value of first element in the list if there is one, return NULL
+ * otherwise.
+ *
+ * ptr *will* be evaluated multiple times.
+ */
+#define ilist_d_head(type, membername, ptr) \
+( \
+ (&((ptr)->head) == (ptr)->head.next) ? \
+ NULL : ilist_container(type, membername, (ptr)->head.next) \
+)
+
+/*
+ * Return the value of the first element. This will corrupt data if there is no
+ * element in the list.
+ */
+#define ilist_d_head_unchecked(type, membername, ptr) \
+ ilist_container(type, membername, (ptr)->head.next)
+
+/*
+ * Return the value of the last element in the list if ther eis one, return
+ * NULL otherwise.
+ *
+ * ptr *will* be evaluated multiple times.
+ */
+#define ilist_d_tail(type, membername, ptr) \
+( \
+ (&((ptr)->head) == (ptr)->head.prev) ? \
+ NULL : ilist_container(type, membername, (ptr)->head.prev) \
+)
+
+/*
+ * Return a pointer to the struct `type` when the passed `ptr` points to the
+ * element `membername`.
+ */
+#define ilist_container(type, membername, ptr) \
+ ((type*)((char*)(ptr) - offsetof(type, membername)))
+
+/*
+ * Iterate through the list storing the current element in the variable
+ * `name`. `ptr` will be evaluated repeatedly.
+ *
+ * It is *not* allowed to manipulate the list during iteration.
+ */
+#define ilist_d_foreach(name, ptr) \
+ for(name = (ptr)->head.next; name != &(ptr)->head; name = name->next)
+
+
+/*
+ * Iterate through the list storing the current element in the variable `name`
+ * and also storing the next list element in the variable `nxt`.
+ *
+ * It is allowed to delete the current element from the list. Every other
+ * manipulation can lead to curruption.
+ */
+#define ilist_d_foreach_modify(name, nxt, ptr) \
+ for(name = (ptr)->head.next, nxt = name->next; name != &(ptr)->head; \
+ name = nxt, nxt = name->next)
+
+/*
+ * Iterate through the list in reverse order storing the current element in the
+ * variable `name`. `ptr` will be evaluated repeatedly.
+ *
+ * It is *not* allowed to manipulate the list during iteration.
+ */
+#define ilist_d_reverse_foreach(name, ptr) \
+ for(name = (ptr)->head.prev; name != &(ptr)->head; name = name->prev)
+
+
+#ifdef ILIST_USE_DECLARATION
+
+/*
+ * Initialize a single linked list element.
+ */
+INLINE_IF_POSSIBLE void
+ilist_s_init(ilist_s_head *head)
+{
+ head->head.next = NULL;
+ ilist_s_check(head);
+}
+
+INLINE_IF_POSSIBLE void
+ilist_s_push_head(ilist_s_head *head, ilist_s_node *node)
+{
+ node->next = head->head.next;
+ head->head.next = node;
+ ilist_s_check(head);
+}
+
+/*
+ * fails if the list is empty
+ */
+INLINE_IF_POSSIBLE ilist_s_node*
+ilist_s_pop_head(ilist_s_head *head)
+{
+ ilist_s_node* node = head->head.next;
+ head->head.next = head->head.next->next;
+ ilist_s_check(head);
+ return node;
+}
+
+INLINE_IF_POSSIBLE void
+ilist_s_insert_after(unused_attr ilist_s_head *head, ilist_s_node *after,
+ ilist_s_node *node)
+{
+ node->next = after->next;
+ after->next = node;
+ ilist_s_check(head);
+}
+
+
+INLINE_IF_POSSIBLE
+bool ilist_s_is_empty(ilist_s_head *head)
+{
+ return head->head.next == NULL;
+}
+
+INLINE_IF_POSSIBLE bool
+ilist_s_has_next(unused_attr ilist_s_head* head,
+ ilist_s_node *node)
+{
+ return node->next != NULL;
+}
+
+#endif /* ILIST_USE_DECLARATION */
+
+#define ilist_s_head(type, membername, ptr) \
+( \
+ ilist_s_is_empty(ptr) ? \
+ ilist_container(type, membername, (ptr).next) \
+ : NULL \
+)
+
+#define ilist_s_head_unchecked(type, membername, ptr) \
+ ilist_container(type, membername, (ptr)->head.next)
+
+#define ilist_s_foreach(name, ptr) \
+ for(name = (ptr)->head.next; name != NULL; name = name->next)
+
+#define ilist_s_foreach_modify(name, nxt, ptr) \
+ for(name = (ptr)->head.next, nxt = name ? name->next : NULL; \
+ name != NULL; \
+ name = nxt, nxt = name ? name->next : NULL)
+
+/*
+ * if we defined ILIST_USE_DECLARATION undef it again, its not interesting
+ * outside this file
+ */
+#ifdef USE_INLINE
+#undef ILIST_USE_DECLARATION
+#endif
+
+#endif /* ILIST_H */
--
1.7.10.rc3.3.g19a6c.dirty
From 5d2e23c6dc346b9f277869f4e4f1e048faaa574d Mon Sep 17 00:00:00 2001
From: Andres Freund <[email protected]>
Date: Tue, 26 Jun 2012 19:53:24 +0200
Subject: [PATCH 2/2] Remove usage of lib/dllist.h and replace it by the new
lib/ilist.h interface
---
src/backend/postmaster/autovacuum.c | 91 +++++++++++++-----------------
src/backend/postmaster/postmaster.c | 54 +++++++++---------
src/backend/utils/cache/catcache.c | 106 +++++++++++++++++------------------
src/include/utils/catcache.h | 14 ++---
4 files changed, 125 insertions(+), 140 deletions(-)
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index dade5cc..1f0886c 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -76,6 +76,7 @@
#include "catalog/pg_database.h"
#include "commands/dbcommands.h"
#include "commands/vacuum.h"
+#include "lib/ilist.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "pgstat.h"
@@ -149,6 +150,7 @@ typedef struct avl_dbase
Oid adl_datid; /* hash key -- must be first */
TimestampTz adl_next_worker;
int adl_score;
+ ilist_d_node adl_node;
} avl_dbase;
/* struct to keep track of databases in worker */
@@ -256,7 +258,7 @@ typedef struct
static AutoVacuumShmemStruct *AutoVacuumShmem;
/* the database list in the launcher, and the context that contains it */
-static Dllist *DatabaseList = NULL;
+static ilist_d_head DatabaseList;
static MemoryContext DatabaseListCxt = NULL;
/* Pointer to my own WorkerInfo, valid on each worker */
@@ -403,6 +405,9 @@ AutoVacLauncherMain(int argc, char *argv[])
/* Identify myself via ps */
init_ps_display("autovacuum launcher process", "", "", "");
+ /* initialize to be empty */
+ ilist_d_init(&DatabaseList);
+
ereport(LOG,
(errmsg("autovacuum launcher started")));
@@ -505,7 +510,7 @@ AutoVacLauncherMain(int argc, char *argv[])
/* don't leave dangling pointers to freed memory */
DatabaseListCxt = NULL;
- DatabaseList = NULL;
+ ilist_d_init(&DatabaseList);
/*
* Make sure pgstat also considers our stat data as gone. Note: we
@@ -573,7 +578,7 @@ AutoVacLauncherMain(int argc, char *argv[])
struct timeval nap;
TimestampTz current_time = 0;
bool can_launch;
- Dlelem *elem;
+ avl_dbase *avdb;
int rc;
/*
@@ -735,11 +740,9 @@ AutoVacLauncherMain(int argc, char *argv[])
/* We're OK to start a new worker */
- elem = DLGetTail(DatabaseList);
- if (elem != NULL)
+ avdb = ilist_d_head(avl_dbase, adl_node, &DatabaseList);
+ if (avdb != NULL)
{
- avl_dbase *avdb = DLE_VAL(elem);
-
/*
* launch a worker if next_worker is right now or it is in the
* past
@@ -780,7 +783,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
@@ -793,9 +796,8 @@ 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 ((avdb = ilist_d_tail(avl_dbase, adl_node, &DatabaseList)) != NULL)
{
- avl_dbase *avdb = DLE_VAL(elem);
TimestampTz current_time = GetCurrentTimestamp();
TimestampTz next_wakeup;
long secs;
@@ -864,6 +866,7 @@ rebuild_database_list(Oid newdb)
int score;
int nelems;
HTAB *dbhash;
+ ilist_d_node *elem;
/* use fresh stats */
autovac_refresh_stats();
@@ -924,36 +927,28 @@ rebuild_database_list(Oid newdb)
}
/* Now insert the databases from the existing list */
- if (DatabaseList != NULL)
+ ilist_d_foreach(elem, &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 = ilist_container(avl_dbase, adl_node, elem);
+ 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 */
}
}
@@ -984,7 +979,7 @@ rebuild_database_list(Oid newdb)
/* from here on, the allocated memory belongs to the new list */
MemoryContextSwitchTo(newcxt);
- DatabaseList = DLNewList();
+ ilist_d_init(&DatabaseList);
if (nelems > 0)
{
@@ -1026,15 +1021,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);
+ ilist_d_push_head(&DatabaseList, &db->adl_node);
}
}
@@ -1144,7 +1137,7 @@ do_start_worker(void)
foreach(cell, dblist)
{
avw_dbase *tmp = lfirst(cell);
- Dlelem *elem;
+ ilist_d_node *elem;
/* Check to see if this one is at risk of wraparound */
if (TransactionIdPrecedes(tmp->adw_frozenxid, xidForceLimit))
@@ -1176,11 +1169,10 @@ do_start_worker(void)
* autovacuum time yet.
*/
skipit = false;
- elem = DatabaseList ? DLGetTail(DatabaseList) : NULL;
- while (elem != NULL)
+ ilist_d_reverse_foreach(elem, &DatabaseList)
{
- avl_dbase *dbp = DLE_VAL(elem);
+ avl_dbase *dbp = ilist_container(avl_dbase, adl_node, elem);
if (dbp->adl_datid == tmp->adw_datid)
{
@@ -1197,7 +1189,6 @@ do_start_worker(void)
break;
}
- elem = DLGetPred(elem);
}
if (skipit)
continue;
@@ -1271,7 +1262,7 @@ static void
launch_worker(TimestampTz now)
{
Oid dbid;
- Dlelem *elem;
+ ilist_d_node *elem;
dbid = do_start_worker();
if (OidIsValid(dbid))
@@ -1280,10 +1271,9 @@ launch_worker(TimestampTz now)
* 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)
+ ilist_d_foreach(elem, &DatabaseList)
{
- avl_dbase *avdb = DLE_VAL(elem);
+ avl_dbase *avdb = ilist_container(avl_dbase, adl_node, elem);
if (avdb->adl_datid == dbid)
{
@@ -1294,10 +1284,9 @@ launch_worker(TimestampTz now)
avdb->adl_next_worker =
TimestampTzPlusMilliseconds(now, autovacuum_naptime * 1000);
- DLMoveToFront(elem);
+ ilist_d_move_head(&DatabaseList, elem);
break;
}
- elem = DLGetSucc(elem);
}
/*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 913734f..36e9b0b 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"
@@ -145,10 +145,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 */
+ ilist_d_node elem; /* list link in BackendList */
} Backend;
-static Dllist *BackendList;
+static ilist_d_head BackendList;
#ifdef EXEC_BACKEND
static Backend *ShmemBackendArray;
@@ -976,7 +976,7 @@ PostmasterMain(int argc, char *argv[])
/*
* Initialize the list of active backends.
*/
- BackendList = DLNewList();
+ ilist_d_init(&BackendList);
/*
* Initialize pipe (or process handle on Windows) that allows children to
@@ -1797,7 +1797,7 @@ processCancelRequest(Port *port, void *pkt)
Backend *bp;
#ifndef EXEC_BACKEND
- Dlelem *curr;
+ ilist_d_node *curr;
#else
int i;
#endif
@@ -1811,9 +1811,9 @@ processCancelRequest(Port *port, void *pkt)
* duplicate array in shared memory.
*/
#ifndef EXEC_BACKEND
- for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
+ ilist_d_foreach(curr, &BackendList)
{
- bp = (Backend *) DLE_VAL(curr);
+ bp = ilist_container(Backend, elem, curr);
#else
for (i = MaxLivePostmasterChildren() - 1; i >= 0; i--)
{
@@ -2591,8 +2591,7 @@ static void
CleanupBackend(int pid,
int exitstatus) /* child's exit status. */
{
- Dlelem *curr;
-
+ ilist_d_node *curr, *next;
LogChildExit(DEBUG2, _("server process"), pid, exitstatus);
/*
@@ -2623,9 +2622,9 @@ CleanupBackend(int pid,
return;
}
- for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
+ ilist_d_foreach_modify(curr, next, &BackendList)
{
- Backend *bp = (Backend *) DLE_VAL(curr);
+ Backend *bp = ilist_container(Backend, elem, curr);
if (bp->pid == pid)
{
@@ -2644,7 +2643,7 @@ CleanupBackend(int pid,
ShmemBackendArrayRemove(bp);
#endif
}
- DLRemove(curr);
+ ilist_d_delete(&BackendList, curr);
free(bp);
break;
}
@@ -2661,7 +2660,7 @@ CleanupBackend(int pid,
static void
HandleChildCrash(int pid, int exitstatus, const char *procname)
{
- Dlelem *curr,
+ ilist_d_node *curr,
*next;
Backend *bp;
@@ -2677,10 +2676,10 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
}
/* Process regular backends */
- for (curr = DLGetHead(BackendList); curr; curr = next)
+ ilist_d_foreach_modify(curr, next, &BackendList)
{
- next = DLGetSucc(curr);
- bp = (Backend *) DLE_VAL(curr);
+ bp = ilist_container(Backend, elem, curr);
+
if (bp->pid == pid)
{
/*
@@ -2693,7 +2692,7 @@ HandleChildCrash(int pid, int exitstatus, const char *procname)
ShmemBackendArrayRemove(bp);
#endif
}
- DLRemove(curr);
+ ilist_d_delete(&BackendList, curr);
free(bp);
/* Keep looping so we can signal remaining backends */
}
@@ -3056,7 +3055,7 @@ PostmasterStateMachine(void)
* normal state transition leading up to PM_WAIT_DEAD_END, or during
* FatalError processing.
*/
- if (DLGetHead(BackendList) == NULL &&
+ if (ilist_d_is_empty(&BackendList) &&
PgArchPID == 0 && PgStatPID == 0)
{
/* These other guys should be dead already */
@@ -3182,12 +3181,12 @@ signal_child(pid_t pid, int signal)
static bool
SignalSomeChildren(int signal, int target)
{
- Dlelem *curr;
+ ilist_d_node *curr;
bool signaled = false;
- for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
+ ilist_d_foreach(curr, &BackendList)
{
- Backend *bp = (Backend *) DLE_VAL(curr);
+ Backend *bp = ilist_container(Backend, elem, curr);
if (bp->dead_end)
continue;
@@ -3325,8 +3324,8 @@ BackendStartup(Port *port)
*/
bn->pid = pid;
bn->is_autovacuum = false;
- DLInitElem(&bn->elem, bn);
- DLAddHead(BackendList, &bn->elem);
+ ilist_d_push_head(&BackendList, &bn->elem);
+
#ifdef EXEC_BACKEND
if (!bn->dead_end)
ShmemBackendArrayAdd(bn);
@@ -4422,12 +4421,12 @@ PostmasterRandom(void)
static int
CountChildren(int target)
{
- Dlelem *curr;
+ ilist_d_node *curr;
int cnt = 0;
- for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
+ ilist_d_foreach(curr, &BackendList)
{
- Backend *bp = (Backend *) DLE_VAL(curr);
+ Backend *bp = ilist_container(Backend, elem, curr);
if (bp->dead_end)
continue;
@@ -4606,8 +4605,7 @@ StartAutovacuumWorker(void)
if (bn->pid > 0)
{
bn->is_autovacuum = true;
- DLInitElem(&bn->elem, bn);
- DLAddHead(BackendList, &bn->elem);
+ ilist_d_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 0307b96..efe34d9 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -353,6 +353,8 @@ CatCachePrintStats(int code, Datum arg)
static void
CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
{
+ Index hashIndex;
+
Assert(ct->refcount == 0);
Assert(ct->my_cache == cache);
@@ -369,7 +371,9 @@ CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
}
/* delink from linked list */
- DLRemove(&ct->cache_elem);
+ hashIndex = HASH_INDEX(ct->hash_value, cache->cc_nbuckets);
+
+ ilist_d_delete(&cache->cc_bucket[hashIndex], &ct->cache_elem);
/* free associated tuple data */
if (ct->tuple.t_data != NULL)
@@ -412,7 +416,7 @@ CatCacheRemoveCList(CatCache *cache, CatCList *cl)
}
/* delink from linked list */
- DLRemove(&cl->cache_elem);
+ ilist_d_delete(&cache->cc_lists, &cl->cache_elem);
/* free associated tuple data */
if (cl->tuple.t_data != NULL)
@@ -452,8 +456,9 @@ CatalogCacheIdInvalidate(int cacheId, uint32 hashValue)
for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next)
{
Index hashIndex;
- Dlelem *elt,
+ ilist_d_node *elt,
*nextelt;
+ ilist_d_head *bucket;
if (cacheId != ccp->id)
continue;
@@ -468,11 +473,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)
+ ilist_d_foreach_modify(elt, nextelt, &ccp->cc_lists)
{
- CatCList *cl = (CatCList *) DLE_VAL(elt);
-
- nextelt = DLGetSucc(elt);
+ CatCList *cl = ilist_container(CatCList, cache_elem, elt);
if (cl->refcount > 0)
cl->dead = true;
@@ -484,12 +487,10 @@ 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)
+ bucket = &ccp->cc_bucket[hashIndex];
+ ilist_d_foreach_modify(elt, nextelt, bucket)
{
- CatCTup *ct = (CatCTup *) DLE_VAL(elt);
-
- nextelt = DLGetSucc(elt);
+ CatCTup *ct = ilist_container(CatCTup, cache_elem, elt);
if (hashValue == ct->hash_value)
{
@@ -561,13 +562,13 @@ AtEOXact_CatCache(bool isCommit)
for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next)
{
- Dlelem *elt;
+ ilist_d_node *elt;
int i;
/* Check CatCLists */
- for (elt = DLGetHead(&ccp->cc_lists); elt; elt = DLGetSucc(elt))
+ ilist_d_foreach(elt, &ccp->cc_lists)
{
- CatCList *cl = (CatCList *) DLE_VAL(elt);
+ CatCList *cl = ilist_container(CatCList, cache_elem, elt);
Assert(cl->cl_magic == CL_MAGIC);
Assert(cl->refcount == 0);
@@ -577,11 +578,10 @@ 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))
+ ilist_d_head *bucket = &ccp->cc_bucket[i];
+ ilist_d_foreach(elt, bucket)
{
- CatCTup *ct = (CatCTup *) DLE_VAL(elt);
+ CatCTup *ct = ilist_container(CatCTup, cache_elem, elt);
Assert(ct->ct_magic == CT_MAGIC);
Assert(ct->refcount == 0);
@@ -604,16 +604,14 @@ AtEOXact_CatCache(bool isCommit)
static void
ResetCatalogCache(CatCache *cache)
{
- Dlelem *elt,
+ ilist_d_node *elt,
*nextelt;
int i;
/* Remove each list in this cache, or at least mark it dead */
- for (elt = DLGetHead(&cache->cc_lists); elt; elt = nextelt)
+ ilist_d_foreach_modify(elt, nextelt, &cache->cc_lists)
{
- CatCList *cl = (CatCList *) DLE_VAL(elt);
-
- nextelt = DLGetSucc(elt);
+ CatCList *cl = ilist_container(CatCList, cache_elem, elt);
if (cl->refcount > 0)
cl->dead = true;
@@ -624,11 +622,10 @@ 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)
+ ilist_d_head *bucket = &cache->cc_bucket[i];
+ ilist_d_foreach_modify(elt, nextelt, bucket)
{
- CatCTup *ct = (CatCTup *) DLE_VAL(elt);
-
- nextelt = DLGetSucc(elt);
+ CatCTup *ct = ilist_container(CatCTup, cache_elem, elt);
if (ct->refcount > 0 ||
(ct->c_list && ct->c_list->refcount > 0))
@@ -770,10 +767,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(ilist_d_node));
/*
* initialize the cache's relation information for the relation
@@ -792,6 +787,12 @@ InitCatCache(int id,
for (i = 0; i < nkeys; ++i)
cp->cc_key[i] = key[i];
+ ilist_d_init(&cp->cc_lists);
+
+ for (i = 0; i < nbuckets; i++){
+ ilist_d_init(&cp->cc_bucket[i]);
+ }
+
/*
* new cache is initialized as far as we can go for now. print some
* debugging information, if appropriate.
@@ -1060,7 +1061,8 @@ SearchCatCache(CatCache *cache,
ScanKeyData cur_skey[CATCACHE_MAXKEYS];
uint32 hashValue;
Index hashIndex;
- Dlelem *elt;
+ ilist_d_node *elt;
+ ilist_d_head *bucket;
CatCTup *ct;
Relation relation;
SysScanDesc scandesc;
@@ -1094,13 +1096,11 @@ 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];
+ ilist_d_foreach(elt, bucket){
bool res;
- ct = (CatCTup *) DLE_VAL(elt);
+ ct = ilist_container(CatCTup, cache_elem, elt);
if (ct->dead)
continue; /* ignore dead entries */
@@ -1125,7 +1125,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);
+ ilist_d_move_head(bucket, &ct->cache_elem);
/*
* If it's a positive entry, bump its refcount and return it. If it's
@@ -1340,7 +1340,7 @@ SearchCatCacheList(CatCache *cache,
{
ScanKeyData cur_skey[CATCACHE_MAXKEYS];
uint32 lHashValue;
- Dlelem *elt;
+ ilist_d_node *elt;
CatCList *cl;
CatCTup *ct;
List *volatile ctlist;
@@ -1382,13 +1382,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))
+ ilist_d_foreach(elt, &cache->cc_lists)
{
bool res;
- cl = (CatCList *) DLE_VAL(elt);
+ cl = ilist_container(CatCList, cache_elem, elt);
if (cl->dead)
continue; /* ignore dead entries */
@@ -1416,7 +1414,7 @@ SearchCatCacheList(CatCache *cache,
* since there's no point in that unless they are searched for
* individually.)
*/
- DLMoveToFront(&cl->cache_elem);
+ ilist_d_move_head(&cache->cc_lists, &cl->cache_elem);
/* Bump the list's refcount and return it */
ResourceOwnerEnlargeCatCacheListRefs(CurrentResourceOwner);
@@ -1468,7 +1466,8 @@ SearchCatCacheList(CatCache *cache,
{
uint32 hashValue;
Index hashIndex;
-
+ bool found = false;
+ ilist_d_head *bucket;
/*
* See if there's an entry for this tuple already.
*/
@@ -1476,11 +1475,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];
+ ilist_d_foreach(elt, bucket)
{
- ct = (CatCTup *) DLE_VAL(elt);
+ ct = ilist_container(CatCTup, cache_elem, elt);
if (ct->dead || ct->negative)
continue; /* ignore dead and negative entries */
@@ -1498,10 +1496,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 +1563,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 +1585,7 @@ SearchCatCacheList(CatCache *cache,
}
Assert(i == nmembers);
- DLAddHead(&cache->cc_lists, &cl->cache_elem);
+ ilist_d_push_head(&cache->cc_lists, &cl->cache_elem);
/* Finally, bump the list's refcount and return it */
cl->refcount++;
@@ -1664,14 +1662,14 @@ CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp,
*/
ct->ct_magic = CT_MAGIC;
ct->my_cache = cache;
- DLInitElem(&ct->cache_elem, (void *) ct);
+
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);
+ ilist_d_push_head(&cache->cc_bucket[hashIndex], &ct->cache_elem);
cache->cc_ntup++;
CacheHdr->ch_ntup++;
diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h
index d91700a..20f2fa8 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"
/*
@@ -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 */
+ ilist_d_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 */
+ ilist_d_head cc_bucket[1]; /* hash buckets --- VARIABLE LENGTH ARRAY */
} CatCache; /* VARIABLE LENGTH STRUCT */
@@ -77,11 +77,11 @@ 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 ilist_d that stores the elements
+ * of its hash bucket. We keep each ilist_d in LRU order to speed repeated
* lookups.
*/
- Dlelem cache_elem; /* list member of per-bucket list */
+ ilist_d_node cache_elem; /* list member of per-bucket list */
/*
* The tuple may also be a member of at most one CatCList. (If a single
@@ -139,7 +139,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 */
+ ilist_d_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? */
--
1.7.10.rc3.3.g19a6c.dirty
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers