From cdc4f8f3341161b87a5d11171efb14c98c252ee6 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Thu, 4 Jun 2015 19:38:32 +0200 Subject: [PATCH 1/3] WIP-dontcommit: Add functions to burn multixacts This should live in its own module, but we don't have that yet. --- contrib/pageinspect/heapfuncs.c | 43 ++++++++++++++++++++++++++++++++ contrib/pageinspect/pageinspect--1.3.sql | 6 +++++ src/backend/access/heap/heapam.c | 2 +- src/backend/access/transam/multixact.c | 15 ++++++----- src/include/access/multixact.h | 3 ++- 5 files changed, 61 insertions(+), 8 deletions(-) diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c index 8d1666c..7a3aa14 100644 --- a/contrib/pageinspect/heapfuncs.c +++ b/contrib/pageinspect/heapfuncs.c @@ -29,6 +29,8 @@ #include "funcapi.h" #include "utils/builtins.h" #include "miscadmin.h" +#include "access/multixact.h" +#include "access/transam.h" /* @@ -223,3 +225,44 @@ heap_page_items(PG_FUNCTION_ARGS) else SRF_RETURN_DONE(fctx); } + +extern Datum +pg_burn_multixact(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(pg_burn_multixact); + +Datum +pg_burn_multixact(PG_FUNCTION_ARGS) +{ + int rep = PG_GETARG_INT32(0); + int size = PG_GETARG_INT32(1); + MultiXactMember *members; + MultiXactId ret; + TransactionId id = ReadNewTransactionId() - size; + int i; + + if (rep < 1) + elog(ERROR, "need to burn, burn, burn"); + + members = palloc(size * sizeof(MultiXactMember)); + for (i = 0; i < size; i++) + { + members[i].xid = id++; + members[i].status = MultiXactStatusForShare; + + if (!TransactionIdIsNormal(members[i].xid)) + { + id = FirstNormalTransactionId; + members[i].xid = id++; + } + } + + MultiXactIdSetOldestMember(); + + for (i = 0; i < rep; i++) + { + CHECK_FOR_INTERRUPTS(); + ret = MultiXactIdCreateFromMembers(size, members, true); + } + + PG_RETURN_INT64((int64) ret); +} diff --git a/contrib/pageinspect/pageinspect--1.3.sql b/contrib/pageinspect/pageinspect--1.3.sql index a99e058..22f51bc 100644 --- a/contrib/pageinspect/pageinspect--1.3.sql +++ b/contrib/pageinspect/pageinspect--1.3.sql @@ -187,3 +187,9 @@ CREATE FUNCTION gin_leafpage_items(IN page bytea, RETURNS SETOF record AS 'MODULE_PATHNAME', 'gin_leafpage_items' LANGUAGE C STRICT; + + +CREATE FUNCTION pg_burn_multixact(num int4, size int4) +RETURNS int4 +AS 'MODULE_PATHNAME', 'pg_burn_multixact' +LANGUAGE C STRICT; diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index caacc10..c57f99d 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -6050,7 +6050,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask, * Create a new multixact with the surviving members of the previous * one, to set as new Xmax in the tuple. */ - xid = MultiXactIdCreateFromMembers(nnewmembers, newmembers); + xid = MultiXactIdCreateFromMembers(nnewmembers, newmembers, false); *flags |= FRM_RETURN_IS_MULTI; } diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 377d084..cf43254 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -405,7 +405,7 @@ MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, members[1].xid = xid2; members[1].status = status2; - newMulti = MultiXactIdCreateFromMembers(2, members); + newMulti = MultiXactIdCreateFromMembers(2, members, false); debug_elog3(DEBUG2, "Create: %s", mxid_to_string(newMulti, 2, members)); @@ -471,7 +471,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status) */ member.xid = xid; member.status = status; - newMulti = MultiXactIdCreateFromMembers(1, &member); + newMulti = MultiXactIdCreateFromMembers(1, &member, false); debug_elog4(DEBUG2, "Expand: %u has no members, create singleton %u", multi, newMulti); @@ -523,7 +523,7 @@ MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status) newMembers[j].xid = xid; newMembers[j++].status = status; - newMulti = MultiXactIdCreateFromMembers(j, newMembers); + newMulti = MultiXactIdCreateFromMembers(j, newMembers, false); pfree(members); pfree(newMembers); @@ -742,7 +742,7 @@ ReadNextMultiXactId(void) * NB: the passed members[] array will be sorted in-place. */ MultiXactId -MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members) +MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members, bool nocache) { MultiXactId multi; MultiXactOffset offset; @@ -761,7 +761,9 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members) * corner cases where someone else added us to a MultiXact without our * knowledge, but it's not worth checking for.) */ - multi = mXactCacheGetBySet(nmembers, members); + multi = nocache ? InvalidMultiXactId : + mXactCacheGetBySet(nmembers, members); + if (MultiXactIdIsValid(multi)) { debug_elog2(DEBUG2, "Create: in cache!"); @@ -834,7 +836,8 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members) END_CRIT_SECTION(); /* Store the new MultiXactId in the local cache, too */ - mXactCachePut(multi, nmembers, members); + if (!nocache) + mXactCachePut(multi, nmembers, members); debug_elog2(DEBUG2, "Create: all done"); diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h index f1448fe..6213f8a 100644 --- a/src/include/access/multixact.h +++ b/src/include/access/multixact.h @@ -86,10 +86,11 @@ typedef struct xl_multixact_create extern MultiXactId MultiXactIdCreate(TransactionId xid1, MultiXactStatus status1, TransactionId xid2, MultiXactStatus status2); +extern MultiXactId CreateMultiXactId(int nmembers, MultiXactMember *members, bool nocache); extern MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid, MultiXactStatus status); extern MultiXactId MultiXactIdCreateFromMembers(int nmembers, - MultiXactMember *members); + MultiXactMember *members, bool nocache); extern MultiXactId ReadNextMultiXactId(void); extern bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly); -- 2.4.0.rc2.1.g3d6bc9a