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.
This commit is contained in:
Tom Lane 1999-05-31 23:48:04 +00:00
parent 2a44383a2d
commit 185b427284
3 changed files with 73 additions and 40 deletions

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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; 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 void
DLFreeList(Dllist *l) DLFreeList(Dllist *l)
{ {
@ -85,7 +87,7 @@ DLGetTail(Dllist *l)
return l ? l->dll_tail : 0; 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 #ifdef NOT_USED
void * void *
DLGetTailVal(Dllist *l) DLGetTailVal(Dllist *l)
@ -112,20 +114,26 @@ DLGetSucc(Dlelem *e) /* get successor */
void void
DLRemove(Dlelem *e) DLRemove(Dlelem *e)
{ {
Dllist *l; Dllist *l = e->dle_list;
if (e->dle_prev) if (e->dle_prev)
e->dle_prev->dle_next = e->dle_next; 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) if (e->dle_next)
e->dle_next->dle_prev = e->dle_prev; 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 */ e->dle_next = 0;
l = e->dle_list; e->dle_prev = 0;
if (e == l->dll_head) e->dle_list = 0;
DLRemHead(l);
if (e == l->dll_tail)
DLRemTail(l);
} }
void void
@ -134,15 +142,13 @@ DLAddHead(Dllist *l, Dlelem *e)
e->dle_list = l; e->dle_list = l;
if (l->dll_head) if (l->dll_head)
{
l->dll_head->dle_prev = e; l->dll_head->dle_prev = e;
e->dle_next = l->dll_head; e->dle_next = l->dll_head;
}
e->dle_prev = 0; e->dle_prev = 0;
l->dll_head = e; l->dll_head = e;
if (l->dll_tail == 0) /* if this is first element added */ if (l->dll_tail == 0) /* if this is first element added */
l->dll_tail = l->dll_head; l->dll_tail = e;
} }
void void
@ -151,31 +157,28 @@ DLAddTail(Dllist *l, Dlelem *e)
e->dle_list = l; e->dle_list = l;
if (l->dll_tail) if (l->dll_tail)
{
l->dll_tail->dle_next = e; l->dll_tail->dle_next = e;
e->dle_prev = l->dll_tail; e->dle_prev = l->dll_tail;
}
e->dle_next = 0; e->dle_next = 0;
l->dll_tail = e; l->dll_tail = e;
if (l->dll_head == 0) /* if this is first element added */ if (l->dll_head == 0) /* if this is first element added */
l->dll_head = l->dll_tail; l->dll_head = e;
} }
Dlelem * Dlelem *
DLRemHead(Dllist *l) DLRemHead(Dllist *l)
{ {
/* remove and return the head */ /* remove and return the head */
Dlelem *result; Dlelem *result = l->dll_head;
if (l->dll_head == 0) if (result == 0)
return 0; return result;
result = l->dll_head; if (result->dle_next)
if (l->dll_head->dle_next) result->dle_next->dle_prev = 0;
l->dll_head->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_next = 0;
result->dle_list = 0; result->dle_list = 0;
@ -190,15 +193,15 @@ Dlelem *
DLRemTail(Dllist *l) DLRemTail(Dllist *l)
{ {
/* remove and return the tail */ /* remove and return the tail */
Dlelem *result; Dlelem *result = l->dll_tail;
if (l->dll_tail == 0) if (result == 0)
return 0; return result;
result = l->dll_tail; if (result->dle_prev)
if (l->dll_tail->dle_prev) result->dle_prev->dle_next = 0;
l->dll_tail->dle_prev->dle_next = 0;
l->dll_tail = l->dll_tail->dle_prev; l->dll_tail = result->dle_prev;
result->dle_prev = 0; result->dle_prev = 0;
result->dle_list = 0; result->dle_list = 0;
@ -208,3 +211,30 @@ DLRemTail(Dllist *l)
return result; 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 */
}

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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: * Notes:
* XXX This needs to use exception.h to handle recovery when * 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 * 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) 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; DLMoveToFront(old_lru_elt);
DLRemove(old_lru_elt); DLMoveToFront(elt);
DLAddHead(cache->cc_lrulist, old_lru_elt);
#ifdef CACHEDEBUG #ifdef CACHEDEBUG
relation = heap_open(cache->relationId); relation = heap_open(cache->relationId);

View File

@ -26,7 +26,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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 DLAddHead(Dllist *list, Dlelem *node);
extern void DLAddTail(Dllist *list, Dlelem *node); extern void DLAddTail(Dllist *list, Dlelem *node);
extern Dlelem *DLRemHead(Dllist *list); /* remove and return the head */ 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) #define DLE_VAL(x) (x->dle_val)