aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/multixact.c
diff options
context:
space:
mode:
authorDavid Rowley <drowley@postgresql.org>2022-11-02 14:06:05 +1300
committerDavid Rowley <drowley@postgresql.org>2022-11-02 14:06:05 +1300
commit7c335b7a20278079e796d62122ef4b821c7fcdf5 (patch)
tree1cfb64fa450e7deb60fa2f8ce933ea1055da024c /src/backend/access/transam/multixact.c
parent451d1164b9d0cce6acd0b3d0790f09db4c56be0a (diff)
downloadpostgresql-7c335b7a20278079e796d62122ef4b821c7fcdf5.tar.gz
postgresql-7c335b7a20278079e796d62122ef4b821c7fcdf5.zip
Add doubly linked count list implementation
We have various requirements when using a dlist_head to keep track of the number of items in the list. This, traditionally, has been done by maintaining a counter variable in the calling code. Here we tidy this up by adding "dclist", which is very similar to dlist but also keeps track of the number of items stored in the list. Callers may use the new dclist_count() function when they need to know how many items are stored. Obtaining the count is an O(1) operation. For simplicity reasons, dclist and dlist both use dlist_node as their node type and dlist_iter/dlist_mutable_iter as their iterator type. dclists have all of the same functionality as dlists except there is no function named dclist_delete(). To remove an item from a list dclist_delete_from() must be used. This requires knowing which dclist the given item is stored in. Additionally, here we also convert some dlists where additional code exists to keep track of the number of items stored and to make these use dclists instead. Author: David Rowley Reviewed-by: Bharath Rupireddy, Aleksander Alekseev Discussion: https://postgr.es/m/CAApHDvrtVxr+FXEX0VbViCFKDGxA3tWDgw9oFewNXCJMmwLjLg@mail.gmail.com
Diffstat (limited to 'src/backend/access/transam/multixact.c')
-rw-r--r--src/backend/access/transam/multixact.c34
1 files changed, 16 insertions, 18 deletions
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 5eff87665be..204aa950456 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -319,8 +319,7 @@ typedef struct mXactCacheEnt
} mXactCacheEnt;
#define MAX_CACHE_ENTRIES 256
-static dlist_head MXactCache = DLIST_STATIC_INIT(MXactCache);
-static int MXactCacheMembers = 0;
+static dclist_head MXactCache = DCLIST_STATIC_INIT(MXactCache);
static MemoryContext MXactContext = NULL;
#ifdef MULTIXACT_DEBUG
@@ -1504,9 +1503,10 @@ mXactCacheGetBySet(int nmembers, MultiXactMember *members)
/* sort the array so comparison is easy */
qsort(members, nmembers, sizeof(MultiXactMember), mxactMemberComparator);
- dlist_foreach(iter, &MXactCache)
+ dclist_foreach(iter, &MXactCache)
{
- mXactCacheEnt *entry = dlist_container(mXactCacheEnt, node, iter.cur);
+ mXactCacheEnt *entry = dclist_container(mXactCacheEnt, node,
+ iter.cur);
if (entry->nmembers != nmembers)
continue;
@@ -1518,7 +1518,7 @@ mXactCacheGetBySet(int nmembers, MultiXactMember *members)
if (memcmp(members, entry->members, nmembers * sizeof(MultiXactMember)) == 0)
{
debug_elog3(DEBUG2, "CacheGet: found %u", entry->multi);
- dlist_move_head(&MXactCache, iter.cur);
+ dclist_move_head(&MXactCache, iter.cur);
return entry->multi;
}
}
@@ -1542,9 +1542,10 @@ mXactCacheGetById(MultiXactId multi, MultiXactMember **members)
debug_elog3(DEBUG2, "CacheGet: looking for %u", multi);
- dlist_foreach(iter, &MXactCache)
+ dclist_foreach(iter, &MXactCache)
{
- mXactCacheEnt *entry = dlist_container(mXactCacheEnt, node, iter.cur);
+ mXactCacheEnt *entry = dclist_container(mXactCacheEnt, node,
+ iter.cur);
if (entry->multi == multi)
{
@@ -1566,7 +1567,7 @@ mXactCacheGetById(MultiXactId multi, MultiXactMember **members)
* This is acceptable only because we exit the iteration
* immediately afterwards.
*/
- dlist_move_head(&MXactCache, iter.cur);
+ dclist_move_head(&MXactCache, iter.cur);
*members = ptr;
return entry->nmembers;
@@ -1610,16 +1611,15 @@ mXactCachePut(MultiXactId multi, int nmembers, MultiXactMember *members)
/* mXactCacheGetBySet assumes the entries are sorted, so sort them */
qsort(entry->members, nmembers, sizeof(MultiXactMember), mxactMemberComparator);
- dlist_push_head(&MXactCache, &entry->node);
- if (MXactCacheMembers++ >= MAX_CACHE_ENTRIES)
+ dclist_push_head(&MXactCache, &entry->node);
+ if (dclist_count(&MXactCache) > MAX_CACHE_ENTRIES)
{
dlist_node *node;
- node = dlist_tail_node(&MXactCache);
- dlist_delete(node);
- MXactCacheMembers--;
+ node = dclist_tail_node(&MXactCache);
+ dclist_delete_from(&MXactCache, node);
- entry = dlist_container(mXactCacheEnt, node, node);
+ entry = dclist_container(mXactCacheEnt, node, node);
debug_elog3(DEBUG2, "CachePut: pruning cached multi %u",
entry->multi);
@@ -1699,8 +1699,7 @@ AtEOXact_MultiXact(void)
* a child of TopTransactionContext, we needn't delete it explicitly.
*/
MXactContext = NULL;
- dlist_init(&MXactCache);
- MXactCacheMembers = 0;
+ dclist_init(&MXactCache);
}
/*
@@ -1766,8 +1765,7 @@ PostPrepare_MultiXact(TransactionId xid)
* Discard the local MultiXactId cache like in AtEOXact_MultiXact.
*/
MXactContext = NULL;
- dlist_init(&MXactCache);
- MXactCacheMembers = 0;
+ dclist_init(&MXactCache);
}
/*