PostgreSQL Source Code git master
Data Structures | Macros | Typedefs | Enumerations | Functions
multixact.h File Reference
#include "access/transam.h"
#include "access/xlogreader.h"
#include "lib/stringinfo.h"
#include "storage/sync.h"
Include dependency graph for multixact.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct   MultiXactMember
 
 
 

Macros

#define  InvalidMultiXactId   ((MultiXactId) 0)
 
#define  FirstMultiXactId   ((MultiXactId) 1)
 
#define  MaxMultiXactId   ((MultiXactId) 0xFFFFFFFF)
 
#define  MultiXactIdIsValid(multi)   ((multi) != InvalidMultiXactId)
 
#define  MaxMultiXactOffset   ((MultiXactOffset) 0xFFFFFFFF)
 
 
#define  ISUPDATE_from_mxstatus(status)    ((status) > MultiXactStatusForUpdate)
 
#define  XLOG_MULTIXACT_ZERO_OFF_PAGE   0x00
 
#define  XLOG_MULTIXACT_ZERO_MEM_PAGE   0x10
 
#define  XLOG_MULTIXACT_CREATE_ID   0x20
 
#define  XLOG_MULTIXACT_TRUNCATE_ID   0x30
 
#define  SizeOfMultiXactCreate   (offsetof(xl_multixact_create, members))
 
 

Typedefs

typedef struct MultiXactMember  MultiXactMember
 
 
 

Enumerations

 

Functions

 
 
 
 
 
bool  MultiXactIdIsRunning (MultiXactId multi, bool isLockOnly)
 
 
int  GetMultiXactIdMembers (MultiXactId multi, MultiXactMember **members, bool from_pgupgrade, bool isLockOnly)
 
bool  GetMultiXactInfo (uint32 *multixacts, MultiXactOffset *members, MultiXactId *oldestMultiXactId, MultiXactOffset *oldestOffset)
 
 
 
int  multixactoffsetssyncfiletag (const FileTag *ftag, char *path)
 
int  multixactmemberssyncfiletag (const FileTag *ftag, char *path)
 
void  AtEOXact_MultiXact (void)
 
void  AtPrepare_MultiXact (void)
 
 
 
void  MultiXactShmemInit (void)
 
void  BootStrapMultiXact (void)
 
void  StartupMultiXact (void)
 
void  TrimMultiXact (void)
 
void  SetMultiXactIdLimit (MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
 
void  MultiXactGetCheckptMulti (bool is_shutdown, MultiXactId *nextMulti, MultiXactOffset *nextMultiOffset, MultiXactId *oldestMulti, Oid *oldestMultiDB)
 
void  CheckPointMultiXact (void)
 
 
void  TruncateMultiXact (MultiXactId newOldestMulti, Oid newOldestMultiDB)
 
void  MultiXactSetNextMXact (MultiXactId nextMulti, MultiXactOffset nextMultiOffset)
 
void  MultiXactAdvanceNextMXact (MultiXactId minMulti, MultiXactOffset minMultiOffset)
 
void  MultiXactAdvanceOldest (MultiXactId oldestMulti, Oid oldestMultiDB)
 
 
void  multixact_twophase_recover (FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
 
void  multixact_twophase_postcommit (FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
 
void  multixact_twophase_postabort (FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
 
 
 
const char *  multixact_identify (uint8 info)
 
char *  mxid_to_string (MultiXactId multi, int nmembers, MultiXactMember *members)
 
 

Macro Definition Documentation

FirstMultiXactId

#define FirstMultiXactId   ((MultiXactId) 1)

Definition at line 26 of file multixact.h.

InvalidMultiXactId

#define InvalidMultiXactId   ((MultiXactId) 0)

Definition at line 25 of file multixact.h.

ISUPDATE_from_mxstatus

#define ISUPDATE_from_mxstatus (   status )     ((status) > MultiXactStatusForUpdate)

Definition at line 53 of file multixact.h.

MaxMultiXactId

#define MaxMultiXactId   ((MultiXactId) 0xFFFFFFFF)

Definition at line 27 of file multixact.h.

MaxMultiXactOffset

#define MaxMultiXactOffset   ((MultiXactOffset) 0xFFFFFFFF)

Definition at line 31 of file multixact.h.

MaxMultiXactStatus

#define MaxMultiXactStatus   MultiXactStatusUpdate

Definition at line 50 of file multixact.h.

MultiXactIdIsValid

#define MultiXactIdIsValid (   multi )    ((multi) != InvalidMultiXactId)

Definition at line 29 of file multixact.h.

SizeOfMultiXactCreate

#define SizeOfMultiXactCreate   (offsetof(xl_multixact_create, members))

Definition at line 82 of file multixact.h.

SizeOfMultiXactTruncate

#define SizeOfMultiXactTruncate   (sizeof(xl_multixact_truncate))

Definition at line 97 of file multixact.h.

XLOG_MULTIXACT_CREATE_ID

#define XLOG_MULTIXACT_CREATE_ID   0x20

Definition at line 71 of file multixact.h.

XLOG_MULTIXACT_TRUNCATE_ID

#define XLOG_MULTIXACT_TRUNCATE_ID   0x30

Definition at line 72 of file multixact.h.

XLOG_MULTIXACT_ZERO_MEM_PAGE

#define XLOG_MULTIXACT_ZERO_MEM_PAGE   0x10

Definition at line 70 of file multixact.h.

XLOG_MULTIXACT_ZERO_OFF_PAGE

#define XLOG_MULTIXACT_ZERO_OFF_PAGE   0x00

Definition at line 69 of file multixact.h.

Typedef Documentation

MultiXactMember

xl_multixact_create

xl_multixact_truncate

Enumeration Type Documentation

MultiXactStatus

Enumerator
MultiXactStatusForKeyShare 
MultiXactStatusForShare 
MultiXactStatusForNoKeyUpdate 
MultiXactStatusForUpdate 
MultiXactStatusNoKeyUpdate 
MultiXactStatusUpdate 

Definition at line 38 of file multixact.h.

39{
44 /* an update that doesn't touch "key" columns */
46 /* other updates, and delete */
MultiXactStatus
Definition: multixact.h:39
@ MultiXactStatusForShare
Definition: multixact.h:41
@ MultiXactStatusForNoKeyUpdate
Definition: multixact.h:42
@ MultiXactStatusNoKeyUpdate
Definition: multixact.h:45
@ MultiXactStatusUpdate
Definition: multixact.h:47
@ MultiXactStatusForUpdate
Definition: multixact.h:43
@ MultiXactStatusForKeyShare
Definition: multixact.h:40

Function Documentation

AtEOXact_MultiXact()

void AtEOXact_MultiXact ( void  )

Definition at line 1799 of file multixact.c.

1800{
1801 /*
1802 * Reset our OldestMemberMXactId and OldestVisibleMXactId values, both of
1803 * which should only be valid while within a transaction.
1804 *
1805 * We assume that storing a MultiXactId is atomic and so we need not take
1806 * MultiXactGenLock to do this.
1807 */
1810
1811 /*
1812 * Discard the local MultiXactId cache. Since MXactContext was created as
1813 * a child of TopTransactionContext, we needn't delete it explicitly.
1814 */
1815 MXactContext = NULL;
1817}
ProcNumber MyProcNumber
Definition: globals.c:90
static void dclist_init(dclist_head *head)
Definition: ilist.h:671
static MemoryContext MXactContext
Definition: multixact.c:368
static MultiXactId * OldestVisibleMXactId
Definition: multixact.c:338
static dclist_head MXactCache
Definition: multixact.c:367
static MultiXactId * OldestMemberMXactId
Definition: multixact.c:337
#define InvalidMultiXactId
Definition: multixact.h:25

References dclist_init(), InvalidMultiXactId, MXactCache, MXactContext, MyProcNumber, OldestMemberMXactId, and OldestVisibleMXactId.

Referenced by AbortTransaction(), CommitTransaction(), and test_read_multixact().

AtPrepare_MultiXact()

void AtPrepare_MultiXact ( void  )

Definition at line 1827 of file multixact.c.

1828{
1830
1831 if (MultiXactIdIsValid(myOldestMember))
1833 &myOldestMember, sizeof(MultiXactId));
1834}
TransactionId MultiXactId
Definition: c.h:667
#define MultiXactIdIsValid(multi)
Definition: multixact.h:29
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1271
#define TWOPHASE_RM_MULTIXACT_ID
Definition: twophase_rmgr.h:29

References MultiXactIdIsValid, MyProcNumber, OldestMemberMXactId, RegisterTwoPhaseRecord(), and TWOPHASE_RM_MULTIXACT_ID.

Referenced by PrepareTransaction().

BootStrapMultiXact()

void BootStrapMultiXact ( void  )

Definition at line 2025 of file multixact.c.

2026{
2027 /* Zero the initial pages and flush them to disk */
2030}
#define MultiXactMemberCtl
Definition: multixact.c:229
#define MultiXactOffsetCtl
Definition: multixact.c:228
void SimpleLruZeroAndWritePage(SlruCtl ctl, int64 pageno)
Definition: slru.c:444

References MultiXactMemberCtl, MultiXactOffsetCtl, and SimpleLruZeroAndWritePage().

Referenced by BootStrapXLOG().

CheckPointMultiXact()

void CheckPointMultiXact ( void  )

Definition at line 2234 of file multixact.c.

2235{
2236 TRACE_POSTGRESQL_MULTIXACT_CHECKPOINT_START(true);
2237
2238 /*
2239 * Write dirty MultiXact pages to disk. This may result in sync requests
2240 * queued for later handling by ProcessSyncRequests(), as part of the
2241 * checkpoint.
2242 */
2245
2246 TRACE_POSTGRESQL_MULTIXACT_CHECKPOINT_DONE(true);
2247}
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1347

References MultiXactMemberCtl, MultiXactOffsetCtl, and SimpleLruWriteAll().

Referenced by CheckPointGuts().

GetMultiXactIdMembers()

int GetMultiXactIdMembers ( MultiXactId  multi,
MultiXactMember **  members,
bool  from_pgupgrade,
bool  isLockOnly 
)

Definition at line 1290 of file multixact.c.

1292{
1293 int64 pageno;
1294 int64 prev_pageno;
1295 int entryno;
1296 int slotno;
1297 MultiXactOffset *offptr;
1298 MultiXactOffset offset;
1299 int length;
1300 int truelength;
1301 MultiXactId oldestMXact;
1302 MultiXactId nextMXact;
1303 MultiXactId tmpMXact;
1304 MultiXactOffset nextOffset;
1305 MultiXactMember *ptr;
1306 LWLock *lock;
1307 bool slept = false;
1308
1309 debug_elog3(DEBUG2, "GetMembers: asked for %u", multi);
1310
1311 if (!MultiXactIdIsValid(multi) || from_pgupgrade)
1312 {
1313 *members = NULL;
1314 return -1;
1315 }
1316
1317 /* See if the MultiXactId is in the local cache */
1318 length = mXactCacheGetById(multi, members);
1319 if (length >= 0)
1320 {
1321 debug_elog3(DEBUG2, "GetMembers: found %s in the cache",
1322 mxid_to_string(multi, length, *members));
1323 return length;
1324 }
1325
1326 /* Set our OldestVisibleMXactId[] entry if we didn't already */
1328
1329 /*
1330 * If we know the multi is used only for locking and not for updates, then
1331 * we can skip checking if the value is older than our oldest visible
1332 * multi. It cannot possibly still be running.
1333 */
1334 if (isLockOnly &&
1336 {
1337 debug_elog2(DEBUG2, "GetMembers: a locker-only multi is too old");
1338 *members = NULL;
1339 return -1;
1340 }
1341
1342 /*
1343 * We check known limits on MultiXact before resorting to the SLRU area.
1344 *
1345 * An ID older than MultiXactState->oldestMultiXactId cannot possibly be
1346 * useful; it has already been removed, or will be removed shortly, by
1347 * truncation. If one is passed, an error is raised.
1348 *
1349 * Also, an ID >= nextMXact shouldn't ever be seen here; if it is seen, it
1350 * implies undetected ID wraparound has occurred. This raises a hard
1351 * error.
1352 *
1353 * Shared lock is enough here since we aren't modifying any global state.
1354 * Acquire it just long enough to grab the current counter values. We may
1355 * need both nextMXact and nextOffset; see below.
1356 */
1357 LWLockAcquire(MultiXactGenLock, LW_SHARED);
1358
1359 oldestMXact = MultiXactState->oldestMultiXactId;
1360 nextMXact = MultiXactState->nextMXact;
1361 nextOffset = MultiXactState->nextOffset;
1362
1363 LWLockRelease(MultiXactGenLock);
1364
1365 if (MultiXactIdPrecedes(multi, oldestMXact))
1366 ereport(ERROR,
1367 (errcode(ERRCODE_INTERNAL_ERROR),
1368 errmsg("MultiXactId %u does no longer exist -- apparent wraparound",
1369 multi)));
1370
1371 if (!MultiXactIdPrecedes(multi, nextMXact))
1372 ereport(ERROR,
1373 (errcode(ERRCODE_INTERNAL_ERROR),
1374 errmsg("MultiXactId %u has not been created yet -- apparent wraparound",
1375 multi)));
1376
1377 /*
1378 * Find out the offset at which we need to start reading MultiXactMembers
1379 * and the number of members in the multixact. We determine the latter as
1380 * the difference between this multixact's starting offset and the next
1381 * one's. However, there are some corner cases to worry about:
1382 *
1383 * 1. This multixact may be the latest one created, in which case there is
1384 * no next one to look at. In this case the nextOffset value we just
1385 * saved is the correct endpoint.
1386 *
1387 * 2. The next multixact may still be in process of being filled in: that
1388 * is, another process may have done GetNewMultiXactId but not yet written
1389 * the offset entry for that ID. In that scenario, it is guaranteed that
1390 * the offset entry for that multixact exists (because GetNewMultiXactId
1391 * won't release MultiXactGenLock until it does) but contains zero
1392 * (because we are careful to pre-zero offset pages). Because
1393 * GetNewMultiXactId will never return zero as the starting offset for a
1394 * multixact, when we read zero as the next multixact's offset, we know we
1395 * have this case. We handle this by sleeping on the condition variable
1396 * we have just for this; the process in charge will signal the CV as soon
1397 * as it has finished writing the multixact offset.
1398 *
1399 * 3. Because GetNewMultiXactId increments offset zero to offset one to
1400 * handle case #2, there is an ambiguity near the point of offset
1401 * wraparound. If we see next multixact's offset is one, is that our
1402 * multixact's actual endpoint, or did it end at zero with a subsequent
1403 * increment? We handle this using the knowledge that if the zero'th
1404 * member slot wasn't filled, it'll contain zero, and zero isn't a valid
1405 * transaction ID so it can't be a multixact member. Therefore, if we
1406 * read a zero from the members array, just ignore it.
1407 *
1408 * This is all pretty messy, but the mess occurs only in infrequent corner
1409 * cases, so it seems better than holding the MultiXactGenLock for a long
1410 * time on every multixact creation.
1411 */
1412retry:
1413 pageno = MultiXactIdToOffsetPage(multi);
1414 entryno = MultiXactIdToOffsetEntry(multi);
1415
1416 /* Acquire the bank lock for the page we need. */
1419
1420 slotno = SimpleLruReadPage(MultiXactOffsetCtl, pageno, true, multi);
1421 offptr = (MultiXactOffset *) MultiXactOffsetCtl->shared->page_buffer[slotno];
1422 offptr += entryno;
1423 offset = *offptr;
1424
1425 Assert(offset != 0);
1426
1427 /*
1428 * Use the same increment rule as GetNewMultiXactId(), that is, don't
1429 * handle wraparound explicitly until needed.
1430 */
1431 tmpMXact = multi + 1;
1432
1433 if (nextMXact == tmpMXact)
1434 {
1435 /* Corner case 1: there is no next multixact */
1436 length = nextOffset - offset;
1437 }
1438 else
1439 {
1440 MultiXactOffset nextMXOffset;
1441
1442 /* handle wraparound if needed */
1443 if (tmpMXact < FirstMultiXactId)
1444 tmpMXact = FirstMultiXactId;
1445
1446 prev_pageno = pageno;
1447
1448 pageno = MultiXactIdToOffsetPage(tmpMXact);
1449 entryno = MultiXactIdToOffsetEntry(tmpMXact);
1450
1451 if (pageno != prev_pageno)
1452 {
1453 LWLock *newlock;
1454
1455 /*
1456 * Since we're going to access a different SLRU page, if this page
1457 * falls under a different bank, release the old bank's lock and
1458 * acquire the lock of the new bank.
1459 */
1460 newlock = SimpleLruGetBankLock(MultiXactOffsetCtl, pageno);
1461 if (newlock != lock)
1462 {
1463 LWLockRelease(lock);
1464 LWLockAcquire(newlock, LW_EXCLUSIVE);
1465 lock = newlock;
1466 }
1467 slotno = SimpleLruReadPage(MultiXactOffsetCtl, pageno, true, tmpMXact);
1468 }
1469
1470 offptr = (MultiXactOffset *) MultiXactOffsetCtl->shared->page_buffer[slotno];
1471 offptr += entryno;
1472 nextMXOffset = *offptr;
1473
1474 if (nextMXOffset == 0)
1475 {
1476 /* Corner case 2: next multixact is still being filled in */
1477 LWLockRelease(lock);
1479
1480 INJECTION_POINT("multixact-get-members-cv-sleep", NULL);
1481
1483 WAIT_EVENT_MULTIXACT_CREATION);
1484 slept = true;
1485 goto retry;
1486 }
1487
1488 length = nextMXOffset - offset;
1489 }
1490
1491 LWLockRelease(lock);
1492 lock = NULL;
1493
1494 /*
1495 * If we slept above, clean up state; it's no longer needed.
1496 */
1497 if (slept)
1499
1500 ptr = (MultiXactMember *) palloc(length * sizeof(MultiXactMember));
1501
1502 truelength = 0;
1503 prev_pageno = -1;
1504 for (int i = 0; i < length; i++, offset++)
1505 {
1506 TransactionId *xactptr;
1507 uint32 *flagsptr;
1508 int flagsoff;
1509 int bshift;
1510 int memberoff;
1511
1512 pageno = MXOffsetToMemberPage(offset);
1513 memberoff = MXOffsetToMemberOffset(offset);
1514
1515 if (pageno != prev_pageno)
1516 {
1517 LWLock *newlock;
1518
1519 /*
1520 * Since we're going to access a different SLRU page, if this page
1521 * falls under a different bank, release the old bank's lock and
1522 * acquire the lock of the new bank.
1523 */
1524 newlock = SimpleLruGetBankLock(MultiXactMemberCtl, pageno);
1525 if (newlock != lock)
1526 {
1527 if (lock)
1528 LWLockRelease(lock);
1529 LWLockAcquire(newlock, LW_EXCLUSIVE);
1530 lock = newlock;
1531 }
1532
1533 slotno = SimpleLruReadPage(MultiXactMemberCtl, pageno, true, multi);
1534 prev_pageno = pageno;
1535 }
1536
1537 xactptr = (TransactionId *)
1538 (MultiXactMemberCtl->shared->page_buffer[slotno] + memberoff);
1539
1540 if (!TransactionIdIsValid(*xactptr))
1541 {
1542 /* Corner case 3: we must be looking at unused slot zero */
1543 Assert(offset == 0);
1544 continue;
1545 }
1546
1547 flagsoff = MXOffsetToFlagsOffset(offset);
1548 bshift = MXOffsetToFlagsBitShift(offset);
1549 flagsptr = (uint32 *) (MultiXactMemberCtl->shared->page_buffer[slotno] + flagsoff);
1550
1551 ptr[truelength].xid = *xactptr;
1552 ptr[truelength].status = (*flagsptr >> bshift) & MXACT_MEMBER_XACT_BITMASK;
1553 truelength++;
1554 }
1555
1556 LWLockRelease(lock);
1557
1558 /* A multixid with zero members should not happen */
1559 Assert(truelength > 0);
1560
1561 /*
1562 * Copy the result into the local cache.
1563 */
1564 mXactCachePut(multi, truelength, ptr);
1565
1566 debug_elog3(DEBUG2, "GetMembers: no cache for %s",
1567 mxid_to_string(multi, truelength, ptr));
1568 *members = ptr;
1569 return truelength;
1570}
int64_t int64
Definition: c.h:535
uint32 MultiXactOffset
Definition: c.h:669
uint32_t uint32
Definition: c.h:538
uint32 TransactionId
Definition: c.h:657
bool ConditionVariableCancelSleep(void)
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define DEBUG2
Definition: elog.h:29
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
Assert(PointerIsAligned(start, uint64))
#define INJECTION_POINT(name, arg)
i
int i
Definition: isn.c:77
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1174
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1894
@ LW_SHARED
Definition: lwlock.h:113
@ LW_EXCLUSIVE
Definition: lwlock.h:112
void * palloc(Size size)
Definition: mcxt.c:1365
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
static int mXactCacheGetById(MultiXactId multi, MultiXactMember **members)
Definition: multixact.c:1653
static int64 MXOffsetToMemberPage(MultiXactOffset offset)
Definition: multixact.c:169
#define MXACT_MEMBER_XACT_BITMASK
Definition: multixact.c:141
bool MultiXactIdPrecedes(MultiXactId multi1, MultiXactId multi2)
Definition: multixact.c:3265
static void MultiXactIdSetOldestVisible(void)
Definition: multixact.c:721
static int MultiXactIdToOffsetEntry(MultiXactId multi)
Definition: multixact.c:115
static void mXactCachePut(MultiXactId multi, int nmembers, MultiXactMember *members)
Definition: multixact.c:1700
static int MXOffsetToMemberOffset(MultiXactOffset offset)
Definition: multixact.c:202
static int64 MultiXactIdToOffsetPage(MultiXactId multi)
Definition: multixact.c:109
#define debug_elog3(a, b, c)
Definition: multixact.c:378
char * mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *members)
Definition: multixact.c:1768
static int MXOffsetToFlagsOffset(MultiXactOffset offset)
Definition: multixact.c:182
static MultiXactStateData * MultiXactState
Definition: multixact.c:336
static int MXOffsetToFlagsBitShift(MultiXactOffset offset)
Definition: multixact.c:192
#define debug_elog2(a, b)
Definition: multixact.c:377
#define FirstMultiXactId
Definition: multixact.h:26
int SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok, TransactionId xid)
Definition: slru.c:527
static LWLock * SimpleLruGetBankLock(SlruCtl ctl, int64 pageno)
Definition: slru.h:175
Definition: lwlock.h:42
TransactionId xid
Definition: multixact.h:59
MultiXactStatus status
Definition: multixact.h:60
MultiXactOffset nextOffset
Definition: multixact.c:244
MultiXactId nextMXact
Definition: multixact.c:241
MultiXactId oldestMultiXactId
Definition: multixact.c:254
ConditionVariable nextoff_cv
Definition: multixact.c:278
#define TransactionIdIsValid(xid)
Definition: transam.h:41

References Assert(), CHECK_FOR_INTERRUPTS, ConditionVariableCancelSleep(), ConditionVariableSleep(), DEBUG2, debug_elog2, debug_elog3, ereport, errcode(), errmsg(), ERROR, FirstMultiXactId, i, if(), INJECTION_POINT, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MultiXactIdIsValid, MultiXactIdPrecedes(), MultiXactIdSetOldestVisible(), MultiXactIdToOffsetEntry(), MultiXactIdToOffsetPage(), MultiXactMemberCtl, MultiXactOffsetCtl, MultiXactState, MXACT_MEMBER_XACT_BITMASK, mXactCacheGetById(), mXactCachePut(), mxid_to_string(), MXOffsetToFlagsBitShift(), MXOffsetToFlagsOffset(), MXOffsetToMemberOffset(), MXOffsetToMemberPage(), MyProcNumber, MultiXactStateData::nextMXact, MultiXactStateData::nextoff_cv, MultiXactStateData::nextOffset, MultiXactStateData::oldestMultiXactId, OldestVisibleMXactId, palloc(), SimpleLruGetBankLock(), SimpleLruReadPage(), MultiXactMember::status, TransactionIdIsValid, and MultiXactMember::xid.

Referenced by Do_MultiXactIdWait(), DoesMultiXactIdConflict(), FreezeMultiXactId(), GetMultiXactIdHintBits(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_tuple_should_freeze(), MultiXactIdExpand(), MultiXactIdGetUpdateXid(), MultiXactIdIsRunning(), pg_get_multixact_members(), pgrowlocks(), and test_read_multixact().

GetMultiXactInfo()

bool GetMultiXactInfo ( uint32multixacts,
MultiXactOffsetmembers,
MultiXactIdoldestMultiXactId,
MultiXactOffsetoldestOffset 
)

Definition at line 2867 of file multixact.c.

2869{
2870 MultiXactOffset nextOffset;
2871 MultiXactId nextMultiXactId;
2872 bool oldestOffsetKnown;
2873
2874 LWLockAcquire(MultiXactGenLock, LW_SHARED);
2875 nextOffset = MultiXactState->nextOffset;
2876 *oldestMultiXactId = MultiXactState->oldestMultiXactId;
2877 nextMultiXactId = MultiXactState->nextMXact;
2878 *oldestOffset = MultiXactState->oldestOffset;
2879 oldestOffsetKnown = MultiXactState->oldestOffsetKnown;
2880 LWLockRelease(MultiXactGenLock);
2881
2882 if (!oldestOffsetKnown)
2883 {
2884 *members = 0;
2885 *multixacts = 0;
2886 *oldestMultiXactId = InvalidMultiXactId;
2887 *oldestOffset = 0;
2888 return false;
2889 }
2890
2891 *members = nextOffset - *oldestOffset;
2892 *multixacts = nextMultiXactId - *oldestMultiXactId;
2893 return true;
2894}
bool oldestOffsetKnown
Definition: multixact.c:263
MultiXactOffset oldestOffset
Definition: multixact.c:262

References InvalidMultiXactId, LW_SHARED, LWLockAcquire(), LWLockRelease(), MultiXactState, MultiXactStateData::nextMXact, MultiXactStateData::nextOffset, MultiXactStateData::oldestMultiXactId, MultiXactStateData::oldestOffset, and MultiXactStateData::oldestOffsetKnown.

Referenced by MultiXactMemberFreezeThreshold().

GetOldestMultiXactId()

MultiXactId GetOldestMultiXactId ( void  )

Definition at line 2594 of file multixact.c.

2595{
2596 MultiXactId oldestMXact;
2597 MultiXactId nextMXact;
2598 int i;
2599
2600 /*
2601 * This is the oldest valid value among all the OldestMemberMXactId[] and
2602 * OldestVisibleMXactId[] entries, or nextMXact if none are valid.
2603 */
2604 LWLockAcquire(MultiXactGenLock, LW_SHARED);
2605
2606 /*
2607 * We have to beware of the possibility that nextMXact is in the
2608 * wrapped-around state. We don't fix the counter itself here, but we
2609 * must be sure to use a valid value in our calculation.
2610 */
2611 nextMXact = MultiXactState->nextMXact;
2612 if (nextMXact < FirstMultiXactId)
2613 nextMXact = FirstMultiXactId;
2614
2615 oldestMXact = nextMXact;
2616 for (i = 0; i < MaxOldestSlot; i++)
2617 {
2618 MultiXactId thisoldest;
2619
2620 thisoldest = OldestMemberMXactId[i];
2621 if (MultiXactIdIsValid(thisoldest) &&
2622 MultiXactIdPrecedes(thisoldest, oldestMXact))
2623 oldestMXact = thisoldest;
2624 thisoldest = OldestVisibleMXactId[i];
2625 if (MultiXactIdIsValid(thisoldest) &&
2626 MultiXactIdPrecedes(thisoldest, oldestMXact))
2627 oldestMXact = thisoldest;
2628 }
2629
2630 LWLockRelease(MultiXactGenLock);
2631
2632 return oldestMXact;
2633}
#define MaxOldestSlot
Definition: multixact.c:333

References FirstMultiXactId, i, LW_SHARED, LWLockAcquire(), LWLockRelease(), MaxOldestSlot, MultiXactIdIsValid, MultiXactIdPrecedes(), MultiXactState, MultiXactStateData::nextMXact, OldestMemberMXactId, and OldestVisibleMXactId.

Referenced by heapam_relation_set_new_filelocator(), vac_update_datfrozenxid(), and vacuum_get_cutoffs().

multixact_desc()

void multixact_desc ( StringInfo  buf,
XLogReaderStaterecord 
)

Definition at line 50 of file mxactdesc.c.

51{
52 char *rec = XLogRecGetData(record);
53 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
54
55 if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE ||
57 {
58 int64 pageno;
59
60 memcpy(&pageno, rec, sizeof(pageno));
61 appendStringInfo(buf, "%" PRId64, pageno);
62 }
63 else if (info == XLOG_MULTIXACT_CREATE_ID)
64 {
66 int i;
67
68 appendStringInfo(buf, "%u offset %u nmembers %d: ", xlrec->mid,
69 xlrec->moff, xlrec->nmembers);
70 for (i = 0; i < xlrec->nmembers; i++)
71 out_member(buf, &xlrec->members[i]);
72 }
73 else if (info == XLOG_MULTIXACT_TRUNCATE_ID)
74 {
76
77 appendStringInfo(buf, "offsets [%u, %u), members [%u, %u)",
78 xlrec->startTruncOff, xlrec->endTruncOff,
79 xlrec->startTruncMemb, xlrec->endTruncMemb);
80 }
81}
uint8_t uint8
Definition: c.h:536
#define XLOG_MULTIXACT_ZERO_MEM_PAGE
Definition: multixact.h:70
#define XLOG_MULTIXACT_ZERO_OFF_PAGE
Definition: multixact.h:69
#define XLOG_MULTIXACT_TRUNCATE_ID
Definition: multixact.h:72
#define XLOG_MULTIXACT_CREATE_ID
Definition: multixact.h:71
static void out_member(StringInfo buf, MultiXactMember *member)
Definition: mxactdesc.c:20
static char * buf
Definition: pg_test_fsync.c:72
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
MultiXactId mid
Definition: multixact.h:76
MultiXactMember members[FLEXIBLE_ARRAY_MEMBER]
Definition: multixact.h:79
MultiXactOffset moff
Definition: multixact.h:77
MultiXactId endTruncOff
Definition: multixact.h:90
MultiXactOffset startTruncMemb
Definition: multixact.h:93
MultiXactOffset endTruncMemb
Definition: multixact.h:94
MultiXactId startTruncOff
Definition: multixact.h:89
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415

References appendStringInfo(), buf, xl_multixact_truncate::endTruncMemb, xl_multixact_truncate::endTruncOff, i, xl_multixact_create::members, xl_multixact_create::mid, xl_multixact_create::moff, xl_multixact_create::nmembers, out_member(), xl_multixact_truncate::startTruncMemb, xl_multixact_truncate::startTruncOff, XLOG_MULTIXACT_CREATE_ID, XLOG_MULTIXACT_TRUNCATE_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE, XLOG_MULTIXACT_ZERO_OFF_PAGE, XLogRecGetData, and XLogRecGetInfo.

multixact_identify()

const char * multixact_identify ( uint8  info )

Definition at line 84 of file mxactdesc.c.

85{
86 const char *id = NULL;
87
88 switch (info & ~XLR_INFO_MASK)
89 {
91 id = "ZERO_OFF_PAGE";
92 break;
94 id = "ZERO_MEM_PAGE";
95 break;
97 id = "CREATE_ID";
98 break;
100 id = "TRUNCATE_ID";
101 break;
102 }
103
104 return id;
105}
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

References XLOG_MULTIXACT_CREATE_ID, XLOG_MULTIXACT_TRUNCATE_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE, XLOG_MULTIXACT_ZERO_OFF_PAGE, and XLR_INFO_MASK.

multixact_redo()

void multixact_redo ( XLogReaderStaterecord )

Definition at line 3330 of file multixact.c.

3331{
3332 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
3333
3334 /* Backup blocks are not used in multixact records */
3336
3337 if (info == XLOG_MULTIXACT_ZERO_OFF_PAGE)
3338 {
3339 int64 pageno;
3340
3341 memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
3343 }
3344 else if (info == XLOG_MULTIXACT_ZERO_MEM_PAGE)
3345 {
3346 int64 pageno;
3347
3348 memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
3350 }
3351 else if (info == XLOG_MULTIXACT_CREATE_ID)
3352 {
3353 xl_multixact_create *xlrec =
3355 TransactionId max_xid;
3356 int i;
3357
3358 /* Store the data back into the SLRU files */
3359 RecordNewMultiXact(xlrec->mid, xlrec->moff, xlrec->nmembers,
3360 xlrec->members);
3361
3362 /* Make sure nextMXact/nextOffset are beyond what this record has */
3363 MultiXactAdvanceNextMXact(xlrec->mid + 1,
3364 xlrec->moff + xlrec->nmembers);
3365
3366 /*
3367 * Make sure nextXid is beyond any XID mentioned in the record. This
3368 * should be unnecessary, since any XID found here ought to have other
3369 * evidence in the XLOG, but let's be safe.
3370 */
3371 max_xid = XLogRecGetXid(record);
3372 for (i = 0; i < xlrec->nmembers; i++)
3373 {
3374 if (TransactionIdPrecedes(max_xid, xlrec->members[i].xid))
3375 max_xid = xlrec->members[i].xid;
3376 }
3377
3379 }
3380 else if (info == XLOG_MULTIXACT_TRUNCATE_ID)
3381 {
3383 int64 pageno;
3384
3385 memcpy(&xlrec, XLogRecGetData(record),
3387
3388 elog(DEBUG1, "replaying multixact truncation: "
3389 "offsets [%u, %u), offsets segments [%" PRIx64 ", %" PRIx64 "), "
3390 "members [%u, %u), members segments [%" PRIx64 ", %" PRIx64 ")",
3391 xlrec.startTruncOff, xlrec.endTruncOff,
3394 xlrec.startTruncMemb, xlrec.endTruncMemb,
3397
3398 /* should not be required, but more than cheap enough */
3399 LWLockAcquire(MultiXactTruncationLock, LW_EXCLUSIVE);
3400
3401 /*
3402 * Advance the horizon values, so they're current at the end of
3403 * recovery.
3404 */
3405 SetMultiXactIdLimit(xlrec.endTruncOff, xlrec.oldestMultiDB, false);
3406
3408
3409 /*
3410 * During XLOG replay, latest_page_number isn't necessarily set up
3411 * yet; insert a suitable value to bypass the sanity test in
3412 * SimpleLruTruncate.
3413 */
3414 pageno = MultiXactIdToOffsetPage(xlrec.endTruncOff);
3415 pg_atomic_write_u64(&MultiXactOffsetCtl->shared->latest_page_number,
3416 pageno);
3418
3419 LWLockRelease(MultiXactTruncationLock);
3420 }
3421 else
3422 elog(PANIC, "multixact_redo: unknown op code %u", info);
3423}
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:483
#define PANIC
Definition: elog.h:42
#define DEBUG1
Definition: elog.h:30
#define elog(elevel,...)
Definition: elog.h:226
static int64 MultiXactIdToOffsetSegment(MultiXactId multi)
Definition: multixact.c:121
static void PerformOffsetsTruncation(MultiXactId oldestMulti, MultiXactId newOldestMulti)
Definition: multixact.c:3025
static void PerformMembersTruncation(MultiXactOffset oldestOffset, MultiXactOffset newOldestOffset)
Definition: multixact.c:2996
void SetMultiXactIdLimit(MultiXactId oldest_datminmxid, Oid oldest_datoid, bool is_startup)
Definition: multixact.c:2292
static void RecordNewMultiXact(MultiXactId multi, MultiXactOffset offset, int nmembers, MultiXactMember *members)
Definition: multixact.c:907
static int64 MXOffsetToMemberSegment(MultiXactOffset offset)
Definition: multixact.c:175
void MultiXactAdvanceNextMXact(MultiXactId minMulti, MultiXactOffset minMultiOffset)
Definition: multixact.c:2441
#define SizeOfMultiXactTruncate
Definition: multixact.h:97
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:280
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:304
#define XLogRecGetXid(decoder)
Definition: xlogreader.h:412
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:417

References AdvanceNextFullTransactionIdPastXid(), Assert(), DEBUG1, elog, xl_multixact_truncate::endTruncMemb, xl_multixact_truncate::endTruncOff, i, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), xl_multixact_create::members, xl_multixact_create::mid, xl_multixact_create::moff, MultiXactAdvanceNextMXact(), MultiXactIdToOffsetPage(), MultiXactIdToOffsetSegment(), MultiXactMemberCtl, MultiXactOffsetCtl, MXOffsetToMemberSegment(), xl_multixact_create::nmembers, xl_multixact_truncate::oldestMultiDB, PANIC, PerformMembersTruncation(), PerformOffsetsTruncation(), pg_atomic_write_u64(), RecordNewMultiXact(), SetMultiXactIdLimit(), SimpleLruZeroAndWritePage(), SizeOfMultiXactTruncate, xl_multixact_truncate::startTruncMemb, xl_multixact_truncate::startTruncOff, TransactionIdPrecedes(), MultiXactMember::xid, XLOG_MULTIXACT_CREATE_ID, XLOG_MULTIXACT_TRUNCATE_ID, XLOG_MULTIXACT_ZERO_MEM_PAGE, XLOG_MULTIXACT_ZERO_OFF_PAGE, XLogRecGetData, XLogRecGetInfo, XLogRecGetXid, and XLogRecHasAnyBlockRefs.

multixact_twophase_postabort()

void multixact_twophase_postabort ( FullTransactionId  fxid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 1926 of file multixact.c.

1928{
1929 multixact_twophase_postcommit(fxid, info, recdata, len);
1930}
void multixact_twophase_postcommit(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition: multixact.c:1911
const void size_t len

References len, and multixact_twophase_postcommit().

multixact_twophase_postcommit()

void multixact_twophase_postcommit ( FullTransactionId  fxid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 1911 of file multixact.c.

1913{
1914 ProcNumber dummyProcNumber = TwoPhaseGetDummyProcNumber(fxid, true);
1915
1916 Assert(len == sizeof(MultiXactId));
1917
1918 OldestMemberMXactId[dummyProcNumber] = InvalidMultiXactId;
1919}
int ProcNumber
Definition: procnumber.h:24
ProcNumber TwoPhaseGetDummyProcNumber(FullTransactionId fxid, bool lock_held)
Definition: twophase.c:908

References Assert(), InvalidMultiXactId, len, OldestMemberMXactId, and TwoPhaseGetDummyProcNumber().

Referenced by multixact_twophase_postabort().

multixact_twophase_recover()

void multixact_twophase_recover ( FullTransactionId  fxid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 1890 of file multixact.c.

1892{
1893 ProcNumber dummyProcNumber = TwoPhaseGetDummyProcNumber(fxid, false);
1894 MultiXactId oldestMember;
1895
1896 /*
1897 * Get the oldest member XID from the state file record, and set it in the
1898 * OldestMemberMXactId slot reserved for this prepared transaction.
1899 */
1900 Assert(len == sizeof(MultiXactId));
1901 oldestMember = *((MultiXactId *) recdata);
1902
1903 OldestMemberMXactId[dummyProcNumber] = oldestMember;
1904}

References Assert(), len, OldestMemberMXactId, and TwoPhaseGetDummyProcNumber().

MultiXactAdvanceNextMXact()

void MultiXactAdvanceNextMXact ( MultiXactId  minMulti,
MultiXactOffset  minMultiOffset 
)

Definition at line 2441 of file multixact.c.

2443{
2444 LWLockAcquire(MultiXactGenLock, LW_EXCLUSIVE);
2446 {
2447 debug_elog3(DEBUG2, "MultiXact: setting next multi to %u", minMulti);
2448 MultiXactState->nextMXact = minMulti;
2449 }
2451 {
2452 debug_elog3(DEBUG2, "MultiXact: setting next offset to %u",
2453 minMultiOffset);
2454 MultiXactState->nextOffset = minMultiOffset;
2455 }
2456 LWLockRelease(MultiXactGenLock);
2457}
static bool MultiXactOffsetPrecedes(MultiXactOffset offset1, MultiXactOffset offset2)
Definition: multixact.c:3291

References DEBUG2, debug_elog3, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MultiXactIdPrecedes(), MultiXactOffsetPrecedes(), MultiXactState, MultiXactStateData::nextMXact, and MultiXactStateData::nextOffset.

Referenced by multixact_redo(), and xlog_redo().

MultiXactAdvanceOldest()

void MultiXactAdvanceOldest ( MultiXactId  oldestMulti,
Oid  oldestMultiDB 
)

Definition at line 2466 of file multixact.c.

2467{
2469
2471 SetMultiXactIdLimit(oldestMulti, oldestMultiDB, false);
2472}
bool InRecovery
Definition: xlogutils.c:50

References Assert(), InRecovery, MultiXactIdPrecedes(), MultiXactState, MultiXactStateData::oldestMultiXactId, and SetMultiXactIdLimit().

Referenced by xlog_redo().

MultiXactGetCheckptMulti()

void MultiXactGetCheckptMulti ( bool  is_shutdown,
MultiXactIdnextMulti,
MultiXactOffsetnextMultiOffset,
MultiXactIdoldestMulti,
OidoldestMultiDB 
)

Definition at line 2212 of file multixact.c.

2217{
2218 LWLockAcquire(MultiXactGenLock, LW_SHARED);
2219 *nextMulti = MultiXactState->nextMXact;
2220 *nextMultiOffset = MultiXactState->nextOffset;
2221 *oldestMulti = MultiXactState->oldestMultiXactId;
2222 *oldestMultiDB = MultiXactState->oldestMultiXactDB;
2223 LWLockRelease(MultiXactGenLock);
2224
2226 "MultiXact: checkpoint is nextMulti %u, nextOffset %u, oldestMulti %u in DB %u",
2227 *nextMulti, *nextMultiOffset, *oldestMulti, *oldestMultiDB);
2228}
#define debug_elog6(a, b, c, d, e, f)
Definition: multixact.c:381
Oid oldestMultiXactDB
Definition: multixact.c:255

References DEBUG2, debug_elog6, LW_SHARED, LWLockAcquire(), LWLockRelease(), MultiXactState, MultiXactStateData::nextMXact, MultiXactStateData::nextOffset, MultiXactStateData::oldestMultiXactDB, and MultiXactStateData::oldestMultiXactId.

Referenced by CreateCheckPoint().

MultiXactIdCreate()

MultiXactId MultiXactIdCreate ( TransactionId  xid1,
MultiXactStatus  status1,
TransactionId  xid2,
MultiXactStatus  status2 
)

Definition at line 425 of file multixact.c.

427{
428 MultiXactId newMulti;
429 MultiXactMember members[2];
430
433
434 Assert(!TransactionIdEquals(xid1, xid2) || (status1 != status2));
435
436 /* MultiXactIdSetOldestMember() must have been called already. */
438
439 /*
440 * Note: unlike MultiXactIdExpand, we don't bother to check that both XIDs
441 * are still running. In typical usage, xid2 will be our own XID and the
442 * caller just did a check on xid1, so it'd be wasted effort.
443 */
444
445 members[0].xid = xid1;
446 members[0].status = status1;
447 members[1].xid = xid2;
448 members[1].status = status2;
449
450 newMulti = MultiXactIdCreateFromMembers(2, members);
451
452 debug_elog3(DEBUG2, "Create: %s",
453 mxid_to_string(newMulti, 2, members));
454
455 return newMulti;
456}
MultiXactId MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
Definition: multixact.c:806
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43

References Assert(), DEBUG2, debug_elog3, MultiXactIdCreateFromMembers(), MultiXactIdIsValid, mxid_to_string(), MyProcNumber, OldestMemberMXactId, MultiXactMember::status, TransactionIdEquals, TransactionIdIsValid, and MultiXactMember::xid.

Referenced by compute_new_xmax_infomask(), and test_create_multixact().

MultiXactIdCreateFromMembers()

MultiXactId MultiXactIdCreateFromMembers ( int  nmembers,
MultiXactMembermembers 
)

Definition at line 806 of file multixact.c.

807{
808 MultiXactId multi;
809 MultiXactOffset offset;
811
812 debug_elog3(DEBUG2, "Create: %s",
813 mxid_to_string(InvalidMultiXactId, nmembers, members));
814
815 /*
816 * See if the same set of members already exists in our cache; if so, just
817 * re-use that MultiXactId. (Note: it might seem that looking in our
818 * cache is insufficient, and we ought to search disk to see if a
819 * duplicate definition already exists. But since we only ever create
820 * MultiXacts containing our own XID, in most cases any such MultiXacts
821 * were in fact created by us, and so will be in our cache. There are
822 * corner cases where someone else added us to a MultiXact without our
823 * knowledge, but it's not worth checking for.)
824 */
825 multi = mXactCacheGetBySet(nmembers, members);
826 if (MultiXactIdIsValid(multi))
827 {
828 debug_elog2(DEBUG2, "Create: in cache!");
829 return multi;
830 }
831
832 /* Verify that there is a single update Xid among the given members. */
833 {
834 int i;
835 bool has_update = false;
836
837 for (i = 0; i < nmembers; i++)
838 {
839 if (ISUPDATE_from_mxstatus(members[i].status))
840 {
841 if (has_update)
842 elog(ERROR, "new multixact has more than one updating member: %s",
843 mxid_to_string(InvalidMultiXactId, nmembers, members));
844 has_update = true;
845 }
846 }
847 }
848
849 /* Load the injection point before entering the critical section */
850 INJECTION_POINT_LOAD("multixact-create-from-members");
851
852 /*
853 * Assign the MXID and offsets range to use, and make sure there is space
854 * in the OFFSETs and MEMBERs files. NB: this routine does
855 * START_CRIT_SECTION().
856 *
857 * Note: unlike MultiXactIdCreate and MultiXactIdExpand, we do not check
858 * that we've called MultiXactIdSetOldestMember here. This is because
859 * this routine is used in some places to create new MultiXactIds of which
860 * the current backend is not a member, notably during freezing of multis
861 * in vacuum. During vacuum, in particular, it would be unacceptable to
862 * keep OldestMulti set, in case it runs for long.
863 */
864 multi = GetNewMultiXactId(nmembers, &offset);
865
866 INJECTION_POINT_CACHED("multixact-create-from-members", NULL);
867
868 /* Make an XLOG entry describing the new MXID. */
869 xlrec.mid = multi;
870 xlrec.moff = offset;
871 xlrec.nmembers = nmembers;
872
873 /*
874 * XXX Note: there's a lot of padding space in MultiXactMember. We could
875 * find a more compact representation of this Xlog record -- perhaps all
876 * the status flags in one XLogRecData, then all the xids in another one?
877 * Not clear that it's worth the trouble though.
878 */
881 XLogRegisterData(members, nmembers * sizeof(MultiXactMember));
882
883 (void) XLogInsert(RM_MULTIXACT_ID, XLOG_MULTIXACT_CREATE_ID);
884
885 /* Now enter the information into the OFFSETs and MEMBERs logs */
886 RecordNewMultiXact(multi, offset, nmembers, members);
887
888 /* Done with critical section */
890
891 /* Store the new MultiXactId in the local cache, too */
892 mXactCachePut(multi, nmembers, members);
893
894 debug_elog2(DEBUG2, "Create: all done");
895
896 return multi;
897}
#define INJECTION_POINT_CACHED(name, arg)
#define INJECTION_POINT_LOAD(name)
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
static MultiXactId GetNewMultiXactId(int nmembers, MultiXactOffset *offset)
Definition: multixact.c:1023
static MultiXactId mXactCacheGetBySet(int nmembers, MultiXactMember *members)
Definition: multixact.c:1610
#define ISUPDATE_from_mxstatus(status)
Definition: multixact.h:53
#define SizeOfMultiXactCreate
Definition: multixact.h:82
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterData(const void *data, uint32 len)
Definition: xloginsert.c:364
void XLogBeginInsert(void)
Definition: xloginsert.c:149

References DEBUG2, debug_elog2, debug_elog3, elog, END_CRIT_SECTION, ERROR, GetNewMultiXactId(), i, INJECTION_POINT_CACHED, INJECTION_POINT_LOAD, InvalidMultiXactId, ISUPDATE_from_mxstatus, xl_multixact_create::mid, xl_multixact_create::moff, MultiXactIdIsValid, mXactCacheGetBySet(), mXactCachePut(), mxid_to_string(), xl_multixact_create::nmembers, RecordNewMultiXact(), SizeOfMultiXactCreate, XLOG_MULTIXACT_CREATE_ID, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by FreezeMultiXactId(), MultiXactIdCreate(), and MultiXactIdExpand().

MultiXactIdExpand()

MultiXactId MultiXactIdExpand ( MultiXactId  multi,
TransactionId  xid,
MultiXactStatus  status 
)

Definition at line 478 of file multixact.c.

479{
480 MultiXactId newMulti;
481 MultiXactMember *members;
482 MultiXactMember *newMembers;
483 int nmembers;
484 int i;
485 int j;
486
489
490 /* MultiXactIdSetOldestMember() must have been called already. */
492
493 debug_elog5(DEBUG2, "Expand: received multi %u, xid %u status %s",
494 multi, xid, mxstatus_to_string(status));
495
496 /*
497 * Note: we don't allow for old multis here. The reason is that the only
498 * caller of this function does a check that the multixact is no longer
499 * running.
500 */
501 nmembers = GetMultiXactIdMembers(multi, &members, false, false);
502
503 if (nmembers < 0)
504 {
505 MultiXactMember member;
506
507 /*
508 * The MultiXactId is obsolete. This can only happen if all the
509 * MultiXactId members stop running between the caller checking and
510 * passing it to us. It would be better to return that fact to the
511 * caller, but it would complicate the API and it's unlikely to happen
512 * too often, so just deal with it by creating a singleton MultiXact.
513 */
514 member.xid = xid;
515 member.status = status;
516 newMulti = MultiXactIdCreateFromMembers(1, &member);
517
518 debug_elog4(DEBUG2, "Expand: %u has no members, create singleton %u",
519 multi, newMulti);
520 return newMulti;
521 }
522
523 /*
524 * If the TransactionId is already a member of the MultiXactId with the
525 * same status, just return the existing MultiXactId.
526 */
527 for (i = 0; i < nmembers; i++)
528 {
529 if (TransactionIdEquals(members[i].xid, xid) &&
530 (members[i].status == status))
531 {
532 debug_elog4(DEBUG2, "Expand: %u is already a member of %u",
533 xid, multi);
534 pfree(members);
535 return multi;
536 }
537 }
538
539 /*
540 * Determine which of the members of the MultiXactId are still of
541 * interest. This is any running transaction, and also any transaction
542 * that grabbed something stronger than just a lock and was committed. (An
543 * update that aborted is of no interest here; and having more than one
544 * update Xid in a multixact would cause errors elsewhere.)
545 *
546 * Removing dead members is not just an optimization: freezing of tuples
547 * whose Xmax are multis depends on this behavior.
548 *
549 * Note we have the same race condition here as above: j could be 0 at the
550 * end of the loop.
551 */
552 newMembers = (MultiXactMember *)
553 palloc(sizeof(MultiXactMember) * (nmembers + 1));
554
555 for (i = 0, j = 0; i < nmembers; i++)
556 {
557 if (TransactionIdIsInProgress(members[i].xid) ||
558 (ISUPDATE_from_mxstatus(members[i].status) &&
559 TransactionIdDidCommit(members[i].xid)))
560 {
561 newMembers[j].xid = members[i].xid;
562 newMembers[j++].status = members[i].status;
563 }
564 }
565
566 newMembers[j].xid = xid;
567 newMembers[j++].status = status;
568 newMulti = MultiXactIdCreateFromMembers(j, newMembers);
569
570 pfree(members);
571 pfree(newMembers);
572
573 debug_elog3(DEBUG2, "Expand: returning new multi %u", newMulti);
574
575 return newMulti;
576}
j
int j
Definition: isn.c:78
void pfree(void *pointer)
Definition: mcxt.c:1594
char * mxstatus_to_string(MultiXactStatus status)
Definition: multixact.c:1745
#define debug_elog5(a, b, c, d, e)
Definition: multixact.c:380
#define debug_elog4(a, b, c, d)
Definition: multixact.c:379
int GetMultiXactIdMembers(MultiXactId multi, MultiXactMember **members, bool from_pgupgrade, bool isLockOnly)
Definition: multixact.c:1290
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:1402
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:126

References Assert(), DEBUG2, debug_elog3, debug_elog4, debug_elog5, GetMultiXactIdMembers(), i, ISUPDATE_from_mxstatus, j, MultiXactIdCreateFromMembers(), MultiXactIdIsValid, mxstatus_to_string(), MyProcNumber, OldestMemberMXactId, palloc(), pfree(), MultiXactMember::status, TransactionIdDidCommit(), TransactionIdEquals, TransactionIdIsInProgress(), TransactionIdIsValid, and MultiXactMember::xid.

Referenced by compute_new_xmax_infomask().

MultiXactIdIsRunning()

bool MultiXactIdIsRunning ( MultiXactId  multi,
bool  isLockOnly 
)

Definition at line 590 of file multixact.c.

591{
592 MultiXactMember *members;
593 int nmembers;
594 int i;
595
596 debug_elog3(DEBUG2, "IsRunning %u?", multi);
597
598 /*
599 * "false" here means we assume our callers have checked that the given
600 * multi cannot possibly come from a pg_upgraded database.
601 */
602 nmembers = GetMultiXactIdMembers(multi, &members, false, isLockOnly);
603
604 if (nmembers <= 0)
605 {
606 debug_elog2(DEBUG2, "IsRunning: no members");
607 return false;
608 }
609
610 /*
611 * Checking for myself is cheap compared to looking in shared memory;
612 * return true if any live subtransaction of the current top-level
613 * transaction is a member.
614 *
615 * This is not needed for correctness, it's just a fast path.
616 */
617 for (i = 0; i < nmembers; i++)
618 {
619 if (TransactionIdIsCurrentTransactionId(members[i].xid))
620 {
621 debug_elog3(DEBUG2, "IsRunning: I (%d) am running!", i);
622 pfree(members);
623 return true;
624 }
625 }
626
627 /*
628 * This could be made faster by having another entry point in procarray.c,
629 * walking the PGPROC array only once for all the members. But in most
630 * cases nmembers should be small enough that it doesn't much matter.
631 */
632 for (i = 0; i < nmembers; i++)
633 {
634 if (TransactionIdIsInProgress(members[i].xid))
635 {
636 debug_elog4(DEBUG2, "IsRunning: member %d (%u) is running",
637 i, members[i].xid);
638 pfree(members);
639 return true;
640 }
641 }
642
643 pfree(members);
644
645 debug_elog3(DEBUG2, "IsRunning: %u is not running", multi);
646
647 return false;
648}
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:941

References DEBUG2, debug_elog2, debug_elog3, debug_elog4, GetMultiXactIdMembers(), i, pfree(), TransactionIdIsCurrentTransactionId(), and TransactionIdIsInProgress().

Referenced by compute_new_xmax_infomask(), FreezeMultiXactId(), HeapTupleSatisfiesUpdate(), and HeapTupleSatisfiesVacuumHorizon().

MultiXactIdPrecedes()

bool MultiXactIdPrecedes ( MultiXactId  multi1,
MultiXactId  multi2 
)

Definition at line 3265 of file multixact.c.

3266{
3267 int32 diff = (int32) (multi1 - multi2);
3268
3269 return (diff < 0);
3270}
int32_t int32
Definition: c.h:534

Referenced by check_mxid_in_range(), copy_table_data(), do_start_worker(), FreezeMultiXactId(), GetMultiXactIdMembers(), GetNewMultiXactId(), GetOldestMultiXactId(), heap_prepare_freeze_tuple(), heap_tuple_should_freeze(), heap_vacuum_eager_scan_setup(), MultiXactAdvanceNextMXact(), MultiXactAdvanceOldest(), MultiXactIdSetOldestVisible(), MultiXactOffsetPagePrecedes(), relation_needs_vacanalyze(), SetMultiXactIdLimit(), TruncateMultiXact(), vac_truncate_clog(), vac_update_datfrozenxid(), vac_update_relstats(), vacuum_get_cutoffs(), and vacuum_xid_failsafe_check().

MultiXactIdPrecedesOrEquals()

bool MultiXactIdPrecedesOrEquals ( MultiXactId  multi1,
MultiXactId  multi2 
)

Definition at line 3279 of file multixact.c.

3280{
3281 int32 diff = (int32) (multi1 - multi2);
3282
3283 return (diff <= 0);
3284}

Referenced by check_mxid_in_range(), heap_tuple_should_freeze(), heap_vacuum_rel(), TruncateMultiXact(), and vacuum_get_cutoffs().

MultiXactIdSetOldestMember()

void MultiXactIdSetOldestMember ( void  )

Definition at line 664 of file multixact.c.

665{
667 {
668 MultiXactId nextMXact;
669
670 /*
671 * You might think we don't need to acquire a lock here, since
672 * fetching and storing of TransactionIds is probably atomic, but in
673 * fact we do: suppose we pick up nextMXact and then lose the CPU for
674 * a long time. Someone else could advance nextMXact, and then
675 * another someone else could compute an OldestVisibleMXactId that
676 * would be after the value we are going to store when we get control
677 * back. Which would be wrong.
678 *
679 * Note that a shared lock is sufficient, because it's enough to stop
680 * someone from advancing nextMXact; and nobody else could be trying
681 * to write to our OldestMember entry, only reading (and we assume
682 * storing it is atomic.)
683 */
684 LWLockAcquire(MultiXactGenLock, LW_SHARED);
685
686 /*
687 * We have to beware of the possibility that nextMXact is in the
688 * wrapped-around state. We don't fix the counter itself here, but we
689 * must be sure to store a valid value in our array entry.
690 */
691 nextMXact = MultiXactState->nextMXact;
692 if (nextMXact < FirstMultiXactId)
693 nextMXact = FirstMultiXactId;
694
696
697 LWLockRelease(MultiXactGenLock);
698
699 debug_elog4(DEBUG2, "MultiXact: setting OldestMember[%d] = %u",
700 MyProcNumber, nextMXact);
701 }
702}

References DEBUG2, debug_elog4, FirstMultiXactId, LW_SHARED, LWLockAcquire(), LWLockRelease(), MultiXactIdIsValid, MultiXactState, MyProcNumber, MultiXactStateData::nextMXact, and OldestMemberMXactId.

Referenced by heap_delete(), heap_lock_tuple(), heap_lock_updated_tuple(), heap_update(), and test_create_multixact().

MultiXactMemberFreezeThreshold()

int MultiXactMemberFreezeThreshold ( void  )

Definition at line 2924 of file multixact.c.

2925{
2926 MultiXactOffset members;
2927 uint32 multixacts;
2928 uint32 victim_multixacts;
2929 double fraction;
2930 int result;
2931 MultiXactId oldestMultiXactId;
2932 MultiXactOffset oldestOffset;
2933
2934 /* If we can't determine member space utilization, assume the worst. */
2935 if (!GetMultiXactInfo(&multixacts, &members, &oldestMultiXactId, &oldestOffset))
2936 return 0;
2937
2938 /* If member space utilization is low, no special action is required. */
2939 if (members <= MULTIXACT_MEMBER_SAFE_THRESHOLD)
2941
2942 /*
2943 * Compute a target for relminmxid advancement. The number of multixacts
2944 * we try to eliminate from the system is based on how far we are past
2945 * MULTIXACT_MEMBER_SAFE_THRESHOLD.
2946 */
2947 fraction = (double) (members - MULTIXACT_MEMBER_SAFE_THRESHOLD) /
2949 victim_multixacts = multixacts * fraction;
2950
2951 /* fraction could be > 1.0, but lowest possible freeze age is zero */
2952 if (victim_multixacts > multixacts)
2953 return 0;
2954 result = multixacts - victim_multixacts;
2955
2956 /*
2957 * Clamp to autovacuum_multixact_freeze_max_age, so that we never make
2958 * autovacuum less aggressive than it would otherwise be.
2959 */
2961}
int autovacuum_multixact_freeze_max_age
Definition: autovacuum.c:130
#define Min(x, y)
Definition: c.h:1003
#define MULTIXACT_MEMBER_SAFE_THRESHOLD
Definition: multixact.c:212
#define MULTIXACT_MEMBER_DANGER_THRESHOLD
Definition: multixact.c:213
bool GetMultiXactInfo(uint32 *multixacts, MultiXactOffset *members, MultiXactId *oldestMultiXactId, MultiXactOffset *oldestOffset)
Definition: multixact.c:2867

References autovacuum_multixact_freeze_max_age, GetMultiXactInfo(), Min, MULTIXACT_MEMBER_DANGER_THRESHOLD, and MULTIXACT_MEMBER_SAFE_THRESHOLD.

Referenced by do_autovacuum(), do_start_worker(), and vacuum_get_cutoffs().

multixactmemberssyncfiletag()

int multixactmemberssyncfiletag ( const FileTagftag,
char *  path 
)

Definition at line 3438 of file multixact.c.

3439{
3440 return SlruSyncFileTag(MultiXactMemberCtl, ftag, path);
3441}
int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
Definition: slru.c:1856

References MultiXactMemberCtl, and SlruSyncFileTag().

multixactoffsetssyncfiletag()

int multixactoffsetssyncfiletag ( const FileTagftag,
char *  path 
)

Definition at line 3429 of file multixact.c.

3430{
3431 return SlruSyncFileTag(MultiXactOffsetCtl, ftag, path);
3432}

References MultiXactOffsetCtl, and SlruSyncFileTag().

MultiXactSetNextMXact()

void MultiXactSetNextMXact ( MultiXactId  nextMulti,
MultiXactOffset  nextMultiOffset 
)

Definition at line 2258 of file multixact.c.

2260{
2261 debug_elog4(DEBUG2, "MultiXact: setting next multi to %u offset %u",
2262 nextMulti, nextMultiOffset);
2263 LWLockAcquire(MultiXactGenLock, LW_EXCLUSIVE);
2264 MultiXactState->nextMXact = nextMulti;
2265 MultiXactState->nextOffset = nextMultiOffset;
2266 LWLockRelease(MultiXactGenLock);
2267
2268 /*
2269 * During a binary upgrade, make sure that the offsets SLRU is large
2270 * enough to contain the next value that would be created.
2271 *
2272 * We need to do this pretty early during the first startup in binary
2273 * upgrade mode: before StartupMultiXact() in fact, because this routine
2274 * is called even before that by StartupXLOG(). And we can't do it
2275 * earlier than at this point, because during that first call of this
2276 * routine we determine the MultiXactState->nextMXact value that
2277 * MaybeExtendOffsetSlru needs.
2278 */
2279 if (IsBinaryUpgrade)
2281}
bool IsBinaryUpgrade
Definition: globals.c:121
static void MaybeExtendOffsetSlru(void)
Definition: multixact.c:2048

References DEBUG2, debug_elog4, IsBinaryUpgrade, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaybeExtendOffsetSlru(), MultiXactState, MultiXactStateData::nextMXact, and MultiXactStateData::nextOffset.

Referenced by BootStrapXLOG(), StartupXLOG(), and xlog_redo().

MultiXactShmemInit()

void MultiXactShmemInit ( void  )

Definition at line 1955 of file multixact.c.

1956{
1957 bool found;
1958
1959 debug_elog2(DEBUG2, "Shared Memory Init for MultiXact");
1960
1963
1965 "multixact_offset", multixact_offset_buffers, 0,
1966 "pg_multixact/offsets", LWTRANCHE_MULTIXACTOFFSET_BUFFER,
1967 LWTRANCHE_MULTIXACTOFFSET_SLRU,
1969 false);
1972 "multixact_member", multixact_member_buffers, 0,
1973 "pg_multixact/members", LWTRANCHE_MULTIXACTMEMBER_BUFFER,
1974 LWTRANCHE_MULTIXACTMEMBER_SLRU,
1976 false);
1977 /* doesn't call SimpleLruTruncate() or meet criteria for unit tests */
1978
1979 /* Initialize our shared state struct */
1980 MultiXactState = ShmemInitStruct("Shared MultiXact State",
1982 &found);
1983 if (!IsUnderPostmaster)
1984 {
1985 Assert(!found);
1986
1987 /* Make sure we zero out the per-backend state */
1990 }
1991 else
1992 Assert(found);
1993
1994 /*
1995 * Set up array pointers.
1996 */
1999}
#define MemSet(start, val, len)
Definition: c.h:1019
void ConditionVariableInit(ConditionVariable *cv)
int multixact_offset_buffers
Definition: globals.c:163
bool IsUnderPostmaster
Definition: globals.c:120
int multixact_member_buffers
Definition: globals.c:162
static bool MultiXactMemberPagePrecedes(int64 page1, int64 page2)
Definition: multixact.c:3245
#define MULTIXACT_OFFSETS_PER_PAGE
Definition: multixact.c:106
#define SHARED_MULTIXACT_STATE_SIZE
static bool MultiXactOffsetPagePrecedes(int64 page1, int64 page2)
Definition: multixact.c:3225
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, const char *subdir, int buffer_tranche_id, int bank_tranche_id, SyncRequestHandler sync_handler, bool long_segment_names)
Definition: slru.c:252
#define SlruPagePrecedesUnitTests(ctl, per_page)
Definition: slru.h:200
MultiXactId perBackendXactIds[FLEXIBLE_ARRAY_MEMBER]
Definition: multixact.c:327
@ SYNC_HANDLER_MULTIXACT_MEMBER
Definition: sync.h:41
@ SYNC_HANDLER_MULTIXACT_OFFSET
Definition: sync.h:40

References Assert(), ConditionVariableInit(), DEBUG2, debug_elog2, IsUnderPostmaster, MaxOldestSlot, MemSet, multixact_member_buffers, multixact_offset_buffers, MULTIXACT_OFFSETS_PER_PAGE, MultiXactMemberCtl, MultiXactMemberPagePrecedes(), MultiXactOffsetCtl, MultiXactOffsetPagePrecedes(), MultiXactState, MultiXactStateData::nextoff_cv, OldestMemberMXactId, OldestVisibleMXactId, MultiXactStateData::perBackendXactIds, SHARED_MULTIXACT_STATE_SIZE, ShmemInitStruct(), SimpleLruInit(), SlruPagePrecedesUnitTests, SYNC_HANDLER_MULTIXACT_MEMBER, and SYNC_HANDLER_MULTIXACT_OFFSET.

Referenced by CreateOrAttachShmemStructs().

MultiXactShmemSize()

Size MultiXactShmemSize ( void  )

Definition at line 1938 of file multixact.c.

1939{
1940 Size size;
1941
1942 /* We need 2*MaxOldestSlot perBackendXactIds[] entries */
1943#define SHARED_MULTIXACT_STATE_SIZE \
1944 add_size(offsetof(MultiXactStateData, perBackendXactIds), \
1945 mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot))
1946
1950
1951 return size;
1952}
size_t Size
Definition: c.h:610
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:198

References add_size(), multixact_member_buffers, multixact_offset_buffers, SHARED_MULTIXACT_STATE_SIZE, and SimpleLruShmemSize().

Referenced by CalculateShmemSize().

mxid_to_string()

char * mxid_to_string ( MultiXactId  multi,
int  nmembers,
MultiXactMembermembers 
)

Definition at line 1768 of file multixact.c.

1769{
1770 static char *str = NULL;
1772 int i;
1773
1774 if (str != NULL)
1775 pfree(str);
1776
1778
1779 appendStringInfo(&buf, "%u %d[%u (%s)", multi, nmembers, members[0].xid,
1780 mxstatus_to_string(members[0].status));
1781
1782 for (i = 1; i < nmembers; i++)
1783 appendStringInfo(&buf, ", %u (%s)", members[i].xid,
1784 mxstatus_to_string(members[i].status));
1785
1788 pfree(buf.data);
1789 return str;
1790}
const char * str
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1746
MemoryContext TopMemoryContext
Definition: mcxt.c:166
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97

References appendStringInfo(), appendStringInfoChar(), buf, i, initStringInfo(), MemoryContextStrdup(), mxstatus_to_string(), pfree(), str, and TopMemoryContext.

Referenced by GetMultiXactIdMembers(), MultiXactIdCreate(), MultiXactIdCreateFromMembers(), mXactCacheGetById(), mXactCacheGetBySet(), and mXactCachePut().

mxstatus_to_string()

char * mxstatus_to_string ( MultiXactStatus  status )

Definition at line 1745 of file multixact.c.

1746{
1747 switch (status)
1748 {
1750 return "keysh";
1752 return "sh";
1754 return "fornokeyupd";
1756 return "forupd";
1758 return "nokeyupd";
1760 return "upd";
1761 default:
1762 elog(ERROR, "unrecognized multixact status %d", status);
1763 return "";
1764 }
1765}

References elog, ERROR, MultiXactStatusForKeyShare, MultiXactStatusForNoKeyUpdate, MultiXactStatusForShare, MultiXactStatusForUpdate, MultiXactStatusNoKeyUpdate, and MultiXactStatusUpdate.

Referenced by MultiXactIdExpand(), mxid_to_string(), and pg_get_multixact_members().

PostPrepare_MultiXact()

void PostPrepare_MultiXact ( FullTransactionId  fxid )

Definition at line 1841 of file multixact.c.

1842{
1843 MultiXactId myOldestMember;
1844
1845 /*
1846 * Transfer our OldestMemberMXactId value to the slot reserved for the
1847 * prepared transaction.
1848 */
1849 myOldestMember = OldestMemberMXactId[MyProcNumber];
1850 if (MultiXactIdIsValid(myOldestMember))
1851 {
1852 ProcNumber dummyProcNumber = TwoPhaseGetDummyProcNumber(fxid, false);
1853
1854 /*
1855 * Even though storing MultiXactId is atomic, acquire lock to make
1856 * sure others see both changes, not just the reset of the slot of the
1857 * current backend. Using a volatile pointer might suffice, but this
1858 * isn't a hot spot.
1859 */
1860 LWLockAcquire(MultiXactGenLock, LW_EXCLUSIVE);
1861
1862 OldestMemberMXactId[dummyProcNumber] = myOldestMember;
1864
1865 LWLockRelease(MultiXactGenLock);
1866 }
1867
1868 /*
1869 * We don't need to transfer OldestVisibleMXactId value, because the
1870 * transaction is not going to be looking at any more multixacts once it's
1871 * prepared.
1872 *
1873 * We assume that storing a MultiXactId is atomic and so we need not take
1874 * MultiXactGenLock to do this.
1875 */
1877
1878 /*
1879 * Discard the local MultiXactId cache like in AtEOXact_MultiXact.
1880 */
1881 MXactContext = NULL;
1883}

References dclist_init(), InvalidMultiXactId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MultiXactIdIsValid, MXactCache, MXactContext, MyProcNumber, OldestMemberMXactId, OldestVisibleMXactId, and TwoPhaseGetDummyProcNumber().

Referenced by PrepareTransaction().

ReadMultiXactIdRange()

void ReadMultiXactIdRange ( MultiXactIdoldest,
MultiXactIdnext 
)

Definition at line 782 of file multixact.c.

783{
784 LWLockAcquire(MultiXactGenLock, LW_SHARED);
787 LWLockRelease(MultiXactGenLock);
788
789 if (*oldest < FirstMultiXactId)
790 *oldest = FirstMultiXactId;
791 if (*next < FirstMultiXactId)
793}
static int32 next
Definition: blutils.c:224

References FirstMultiXactId, LW_SHARED, LWLockAcquire(), LWLockRelease(), MultiXactState, next, MultiXactStateData::nextMXact, and MultiXactStateData::oldestMultiXactId.

Referenced by update_cached_mxid_range().

ReadNextMultiXactId()

MultiXactId ReadNextMultiXactId ( void  )

Definition at line 762 of file multixact.c.

763{
764 MultiXactId mxid;
765
766 /* XXX we could presumably do this without a lock. */
767 LWLockAcquire(MultiXactGenLock, LW_SHARED);
769 LWLockRelease(MultiXactGenLock);
770
771 if (mxid < FirstMultiXactId)
772 mxid = FirstMultiXactId;
773
774 return mxid;
775}

References FirstMultiXactId, LW_SHARED, LWLockAcquire(), LWLockRelease(), MultiXactState, and MultiXactStateData::nextMXact.

Referenced by ATRewriteTables(), AutoVacWorkerMain(), do_start_worker(), mxid_age(), refresh_by_heap_swap(), vac_update_datfrozenxid(), vac_update_relstats(), vacuum_get_cutoffs(), and vacuum_xid_failsafe_check().

SetMultiXactIdLimit()

void SetMultiXactIdLimit ( MultiXactId  oldest_datminmxid,
Oid  oldest_datoid,
bool  is_startup 
)

Definition at line 2292 of file multixact.c.

2294{
2295 MultiXactId multiVacLimit;
2296 MultiXactId multiWarnLimit;
2297 MultiXactId multiStopLimit;
2298 MultiXactId multiWrapLimit;
2299 MultiXactId curMulti;
2300 bool needs_offset_vacuum;
2301
2302 Assert(MultiXactIdIsValid(oldest_datminmxid));
2303
2304 /*
2305 * We pretend that a wrap will happen halfway through the multixact ID
2306 * space, but that's not really true, because multixacts wrap differently
2307 * from transaction IDs. Note that, separately from any concern about
2308 * multixact IDs wrapping, we must ensure that multixact members do not
2309 * wrap. Limits for that are set in SetOffsetVacuumLimit, not here.
2310 */
2311 multiWrapLimit = oldest_datminmxid + (MaxMultiXactId >> 1);
2312 if (multiWrapLimit < FirstMultiXactId)
2313 multiWrapLimit += FirstMultiXactId;
2314
2315 /*
2316 * We'll refuse to continue assigning MultiXactIds once we get within 3M
2317 * multi of data loss. See SetTransactionIdLimit.
2318 */
2319 multiStopLimit = multiWrapLimit - 3000000;
2320 if (multiStopLimit < FirstMultiXactId)
2321 multiStopLimit -= FirstMultiXactId;
2322
2323 /*
2324 * We'll start complaining loudly when we get within 40M multis of data
2325 * loss. This is kind of arbitrary, but if you let your gas gauge get
2326 * down to 2% of full, would you be looking for the next gas station? We
2327 * need to be fairly liberal about this number because there are lots of
2328 * scenarios where most transactions are done by automatic clients that
2329 * won't pay attention to warnings. (No, we're not gonna make this
2330 * configurable. If you know enough to configure it, you know enough to
2331 * not get in this kind of trouble in the first place.)
2332 */
2333 multiWarnLimit = multiWrapLimit - 40000000;
2334 if (multiWarnLimit < FirstMultiXactId)
2335 multiWarnLimit -= FirstMultiXactId;
2336
2337 /*
2338 * We'll start trying to force autovacuums when oldest_datminmxid gets to
2339 * be more than autovacuum_multixact_freeze_max_age mxids old.
2340 *
2341 * Note: autovacuum_multixact_freeze_max_age is a PGC_POSTMASTER parameter
2342 * so that we don't have to worry about dealing with on-the-fly changes in
2343 * its value. See SetTransactionIdLimit.
2344 */
2345 multiVacLimit = oldest_datminmxid + autovacuum_multixact_freeze_max_age;
2346 if (multiVacLimit < FirstMultiXactId)
2347 multiVacLimit += FirstMultiXactId;
2348
2349 /* Grab lock for just long enough to set the new limit values */
2350 LWLockAcquire(MultiXactGenLock, LW_EXCLUSIVE);
2351 MultiXactState->oldestMultiXactId = oldest_datminmxid;
2352 MultiXactState->oldestMultiXactDB = oldest_datoid;
2353 MultiXactState->multiVacLimit = multiVacLimit;
2354 MultiXactState->multiWarnLimit = multiWarnLimit;
2355 MultiXactState->multiStopLimit = multiStopLimit;
2356 MultiXactState->multiWrapLimit = multiWrapLimit;
2357 curMulti = MultiXactState->nextMXact;
2358 LWLockRelease(MultiXactGenLock);
2359
2360 /* Log the info */
2362 (errmsg_internal("MultiXactId wrap limit is %u, limited by database with OID %u",
2363 multiWrapLimit, oldest_datoid)));
2364
2365 /*
2366 * Computing the actual limits is only possible once the data directory is
2367 * in a consistent state. There's no need to compute the limits while
2368 * still replaying WAL - no decisions about new multis are made even
2369 * though multixact creations might be replayed. So we'll only do further
2370 * checks after TrimMultiXact() has been called.
2371 */
2373 return;
2374
2376
2377 /* Set limits for offset vacuum. */
2378 needs_offset_vacuum = SetOffsetVacuumLimit(is_startup);
2379
2380 /*
2381 * If past the autovacuum force point, immediately signal an autovac
2382 * request. The reason for this is that autovac only processes one
2383 * database per invocation. Once it's finished cleaning up the oldest
2384 * database, it'll call here, and we'll signal the postmaster to start
2385 * another iteration immediately if there are still any old databases.
2386 */
2387 if ((MultiXactIdPrecedes(multiVacLimit, curMulti) ||
2388 needs_offset_vacuum) && IsUnderPostmaster)
2390
2391 /* Give an immediate warning if past the wrap warn point */
2392 if (MultiXactIdPrecedes(multiWarnLimit, curMulti))
2393 {
2394 char *oldest_datname;
2395
2396 /*
2397 * We can be called when not inside a transaction, for example during
2398 * StartupXLOG(). In such a case we cannot do database access, so we
2399 * must just report the oldest DB's OID.
2400 *
2401 * Note: it's also possible that get_database_name fails and returns
2402 * NULL, for example because the database just got dropped. We'll
2403 * still warn, even though the warning might now be unnecessary.
2404 */
2405 if (IsTransactionState())
2406 oldest_datname = get_database_name(oldest_datoid);
2407 else
2408 oldest_datname = NULL;
2409
2410 if (oldest_datname)
2412 (errmsg_plural("database \"%s\" must be vacuumed before %u more MultiXactId is used",
2413 "database \"%s\" must be vacuumed before %u more MultiXactIds are used",
2414 multiWrapLimit - curMulti,
2415 oldest_datname,
2416 multiWrapLimit - curMulti),
2417 errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
2418 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
2419 else
2421 (errmsg_plural("database with OID %u must be vacuumed before %u more MultiXactId is used",
2422 "database with OID %u must be vacuumed before %u more MultiXactIds are used",
2423 multiWrapLimit - curMulti,
2424 oldest_datoid,
2425 multiWrapLimit - curMulti),
2426 errhint("To avoid MultiXactId assignment failures, execute a database-wide VACUUM in that database.\n"
2427 "You might also need to commit or roll back old prepared transactions, or drop stale replication slots.")));
2428 }
2429}
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1184
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1161
int errhint(const char *fmt,...)
Definition: elog.c:1321
#define WARNING
Definition: elog.h:36
char * get_database_name(Oid dbid)
Definition: lsyscache.c:1259
static bool SetOffsetVacuumLimit(bool is_startup)
Definition: multixact.c:2647
#define MaxMultiXactId
Definition: multixact.h:27
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:165
@ PMSIGNAL_START_AUTOVAC_LAUNCHER
Definition: pmsignal.h:39
MultiXactId multiWrapLimit
Definition: multixact.c:269
MultiXactId multiStopLimit
Definition: multixact.c:268
MultiXactId multiWarnLimit
Definition: multixact.c:267
MultiXactId multiVacLimit
Definition: multixact.c:266
bool finishedStartup
Definition: multixact.c:247
bool IsTransactionState(void)
Definition: xact.c:387

References Assert(), autovacuum_multixact_freeze_max_age, DEBUG1, ereport, errhint(), errmsg_internal(), errmsg_plural(), MultiXactStateData::finishedStartup, FirstMultiXactId, get_database_name(), InRecovery, IsTransactionState(), IsUnderPostmaster, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaxMultiXactId, MultiXactStateData::multiStopLimit, MultiXactStateData::multiVacLimit, MultiXactStateData::multiWarnLimit, MultiXactStateData::multiWrapLimit, MultiXactIdIsValid, MultiXactIdPrecedes(), MultiXactState, MultiXactStateData::nextMXact, MultiXactStateData::oldestMultiXactDB, MultiXactStateData::oldestMultiXactId, PMSIGNAL_START_AUTOVAC_LAUNCHER, SendPostmasterSignal(), SetOffsetVacuumLimit(), and WARNING.

Referenced by BootStrapXLOG(), multixact_redo(), MultiXactAdvanceOldest(), StartupXLOG(), TrimMultiXact(), and vac_truncate_clog().

StartupMultiXact()

void StartupMultiXact ( void  )

Definition at line 2083 of file multixact.c.

2084{
2087 int64 pageno;
2088
2089 /*
2090 * Initialize offset's idea of the latest page number.
2091 */
2092 pageno = MultiXactIdToOffsetPage(multi);
2093 pg_atomic_write_u64(&MultiXactOffsetCtl->shared->latest_page_number,
2094 pageno);
2095
2096 /*
2097 * Initialize member's idea of the latest page number.
2098 */
2099 pageno = MXOffsetToMemberPage(offset);
2100 pg_atomic_write_u64(&MultiXactMemberCtl->shared->latest_page_number,
2101 pageno);
2102}

References MultiXactIdToOffsetPage(), MultiXactMemberCtl, MultiXactOffsetCtl, MultiXactState, MXOffsetToMemberPage(), MultiXactStateData::nextMXact, MultiXactStateData::nextOffset, and pg_atomic_write_u64().

Referenced by StartupXLOG().

TrimMultiXact()

void TrimMultiXact ( void  )

Definition at line 2108 of file multixact.c.

2109{
2110 MultiXactId nextMXact;
2111 MultiXactOffset offset;
2112 MultiXactId oldestMXact;
2113 Oid oldestMXactDB;
2114 int64 pageno;
2115 int entryno;
2116 int flagsoff;
2117
2118 LWLockAcquire(MultiXactGenLock, LW_SHARED);
2119 nextMXact = MultiXactState->nextMXact;
2120 offset = MultiXactState->nextOffset;
2121 oldestMXact = MultiXactState->oldestMultiXactId;
2122 oldestMXactDB = MultiXactState->oldestMultiXactDB;
2123 LWLockRelease(MultiXactGenLock);
2124
2125 /* Clean up offsets state */
2126
2127 /*
2128 * (Re-)Initialize our idea of the latest page number for offsets.
2129 */
2130 pageno = MultiXactIdToOffsetPage(nextMXact);
2131 pg_atomic_write_u64(&MultiXactOffsetCtl->shared->latest_page_number,
2132 pageno);
2133
2134 /*
2135 * Zero out the remainder of the current offsets page. See notes in
2136 * TrimCLOG() for background. Unlike CLOG, some WAL record covers every
2137 * pg_multixact SLRU mutation. Since, also unlike CLOG, we ignore the WAL
2138 * rule "write xlog before data," nextMXact successors may carry obsolete,
2139 * nonzero offset values. Zero those so case 2 of GetMultiXactIdMembers()
2140 * operates normally.
2141 */
2142 entryno = MultiXactIdToOffsetEntry(nextMXact);
2143 if (entryno != 0)
2144 {
2145 int slotno;
2146 MultiXactOffset *offptr;
2148
2150 slotno = SimpleLruReadPage(MultiXactOffsetCtl, pageno, true, nextMXact);
2151 offptr = (MultiXactOffset *) MultiXactOffsetCtl->shared->page_buffer[slotno];
2152 offptr += entryno;
2153
2154 MemSet(offptr, 0, BLCKSZ - (entryno * sizeof(MultiXactOffset)));
2155
2156 MultiXactOffsetCtl->shared->page_dirty[slotno] = true;
2157 LWLockRelease(lock);
2158 }
2159
2160 /*
2161 * And the same for members.
2162 *
2163 * (Re-)Initialize our idea of the latest page number for members.
2164 */
2165 pageno = MXOffsetToMemberPage(offset);
2166 pg_atomic_write_u64(&MultiXactMemberCtl->shared->latest_page_number,
2167 pageno);
2168
2169 /*
2170 * Zero out the remainder of the current members page. See notes in
2171 * TrimCLOG() for motivation.
2172 */
2173 flagsoff = MXOffsetToFlagsOffset(offset);
2174 if (flagsoff != 0)
2175 {
2176 int slotno;
2177 TransactionId *xidptr;
2178 int memberoff;
2180
2182 memberoff = MXOffsetToMemberOffset(offset);
2183 slotno = SimpleLruReadPage(MultiXactMemberCtl, pageno, true, offset);
2184 xidptr = (TransactionId *)
2185 (MultiXactMemberCtl->shared->page_buffer[slotno] + memberoff);
2186
2187 MemSet(xidptr, 0, BLCKSZ - memberoff);
2188
2189 /*
2190 * Note: we don't need to zero out the flag bits in the remaining
2191 * members of the current group, because they are always reset before
2192 * writing.
2193 */
2194
2195 MultiXactMemberCtl->shared->page_dirty[slotno] = true;
2196 LWLockRelease(lock);
2197 }
2198
2199 /* signal that we're officially up */
2200 LWLockAcquire(MultiXactGenLock, LW_EXCLUSIVE);
2202 LWLockRelease(MultiXactGenLock);
2203
2204 /* Now compute how far away the next members wraparound is. */
2205 SetMultiXactIdLimit(oldestMXact, oldestMXactDB, true);
2206}
unsigned int Oid
Definition: postgres_ext.h:32

References MultiXactStateData::finishedStartup, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemSet, MultiXactIdToOffsetEntry(), MultiXactIdToOffsetPage(), MultiXactMemberCtl, MultiXactOffsetCtl, MultiXactState, MXOffsetToFlagsOffset(), MXOffsetToMemberOffset(), MXOffsetToMemberPage(), MultiXactStateData::nextMXact, MultiXactStateData::nextOffset, MultiXactStateData::oldestMultiXactDB, MultiXactStateData::oldestMultiXactId, pg_atomic_write_u64(), SetMultiXactIdLimit(), SimpleLruGetBankLock(), and SimpleLruReadPage().

Referenced by StartupXLOG().

TruncateMultiXact()

void TruncateMultiXact ( MultiXactId  newOldestMulti,
Oid  newOldestMultiDB 
)

Definition at line 3050 of file multixact.c.

3051{
3052 MultiXactId oldestMulti;
3053 MultiXactId nextMulti;
3054 MultiXactOffset newOldestOffset;
3055 MultiXactOffset oldestOffset;
3056 MultiXactOffset nextOffset;
3057 mxtruncinfo trunc;
3058 MultiXactId earliest;
3059
3062
3063 /*
3064 * We can only allow one truncation to happen at once. Otherwise parts of
3065 * members might vanish while we're doing lookups or similar. There's no
3066 * need to have an interlock with creating new multis or such, since those
3067 * are constrained by the limits (which only grow, never shrink).
3068 */
3069 LWLockAcquire(MultiXactTruncationLock, LW_EXCLUSIVE);
3070
3071 LWLockAcquire(MultiXactGenLock, LW_SHARED);
3072 nextMulti = MultiXactState->nextMXact;
3073 nextOffset = MultiXactState->nextOffset;
3074 oldestMulti = MultiXactState->oldestMultiXactId;
3075 LWLockRelease(MultiXactGenLock);
3076 Assert(MultiXactIdIsValid(oldestMulti));
3077
3078 /*
3079 * Make sure to only attempt truncation if there's values to truncate
3080 * away. In normal processing values shouldn't go backwards, but there's
3081 * some corner cases (due to bugs) where that's possible.
3082 */
3083 if (MultiXactIdPrecedesOrEquals(newOldestMulti, oldestMulti))
3084 {
3085 LWLockRelease(MultiXactTruncationLock);
3086 return;
3087 }
3088
3089 /*
3090 * Note we can't just plow ahead with the truncation; it's possible that
3091 * there are no segments to truncate, which is a problem because we are
3092 * going to attempt to read the offsets page to determine where to
3093 * truncate the members SLRU. So we first scan the directory to determine
3094 * the earliest offsets page number that we can read without error.
3095 *
3096 * When nextMXact is less than one segment away from multiWrapLimit,
3097 * SlruScanDirCbFindEarliest can find some early segment other than the
3098 * actual earliest. (MultiXactOffsetPagePrecedes(EARLIEST, LATEST)
3099 * returns false, because not all pairs of entries have the same answer.)
3100 * That can also arise when an earlier truncation attempt failed unlink()
3101 * or returned early from this function. The only consequence is
3102 * returning early, which wastes space that we could have liberated.
3103 *
3104 * NB: It's also possible that the page that oldestMulti is on has already
3105 * been truncated away, and we crashed before updating oldestMulti.
3106 */
3107 trunc.earliestExistingPage = -1;
3110 if (earliest < FirstMultiXactId)
3111 earliest = FirstMultiXactId;
3112
3113 /* If there's nothing to remove, we can bail out early. */
3114 if (MultiXactIdPrecedes(oldestMulti, earliest))
3115 {
3116 LWLockRelease(MultiXactTruncationLock);
3117 return;
3118 }
3119
3120 /*
3121 * First, compute the safe truncation point for MultiXactMember. This is
3122 * the starting offset of the oldest multixact.
3123 *
3124 * Hopefully, find_multixact_start will always work here, because we've
3125 * already checked that it doesn't precede the earliest MultiXact on disk.
3126 * But if it fails, don't truncate anything, and log a message.
3127 */
3128 if (oldestMulti == nextMulti)
3129 {
3130 /* there are NO MultiXacts */
3131 oldestOffset = nextOffset;
3132 }
3133 else if (!find_multixact_start(oldestMulti, &oldestOffset))
3134 {
3135 ereport(LOG,
3136 (errmsg("oldest MultiXact %u not found, earliest MultiXact %u, skipping truncation",
3137 oldestMulti, earliest)));
3138 LWLockRelease(MultiXactTruncationLock);
3139 return;
3140 }
3141
3142 /*
3143 * Secondly compute up to where to truncate. Lookup the corresponding
3144 * member offset for newOldestMulti for that.
3145 */
3146 if (newOldestMulti == nextMulti)
3147 {
3148 /* there are NO MultiXacts */
3149 newOldestOffset = nextOffset;
3150 }
3151 else if (!find_multixact_start(newOldestMulti, &newOldestOffset))
3152 {
3153 ereport(LOG,
3154 (errmsg("cannot truncate up to MultiXact %u because it does not exist on disk, skipping truncation",
3155 newOldestMulti)));
3156 LWLockRelease(MultiXactTruncationLock);
3157 return;
3158 }
3159
3160 elog(DEBUG1, "performing multixact truncation: "
3161 "offsets [%u, %u), offsets segments [%" PRIx64 ", %" PRIx64 "), "
3162 "members [%u, %u), members segments [%" PRIx64 ", %" PRIx64 ")",
3163 oldestMulti, newOldestMulti,
3164 MultiXactIdToOffsetSegment(oldestMulti),
3165 MultiXactIdToOffsetSegment(newOldestMulti),
3166 oldestOffset, newOldestOffset,
3167 MXOffsetToMemberSegment(oldestOffset),
3168 MXOffsetToMemberSegment(newOldestOffset));
3169
3170 /*
3171 * Do truncation, and the WAL logging of the truncation, in a critical
3172 * section. That way offsets/members cannot get out of sync anymore, i.e.
3173 * once consistent the newOldestMulti will always exist in members, even
3174 * if we crashed in the wrong moment.
3175 */
3177
3178 /*
3179 * Prevent checkpoints from being scheduled concurrently. This is critical
3180 * because otherwise a truncation record might not be replayed after a
3181 * crash/basebackup, even though the state of the data directory would
3182 * require it.
3183 */
3186
3187 /* WAL log truncation */
3188 WriteMTruncateXlogRec(newOldestMultiDB,
3189 oldestMulti, newOldestMulti,
3190 oldestOffset, newOldestOffset);
3191
3192 /*
3193 * Update in-memory limits before performing the truncation, while inside
3194 * the critical section: Have to do it before truncation, to prevent
3195 * concurrent lookups of those values. Has to be inside the critical
3196 * section as otherwise a future call to this function would error out,
3197 * while looking up the oldest member in offsets, if our caller crashes
3198 * before updating the limits.
3199 */
3200 LWLockAcquire(MultiXactGenLock, LW_EXCLUSIVE);
3201 MultiXactState->oldestMultiXactId = newOldestMulti;
3202 MultiXactState->oldestMultiXactDB = newOldestMultiDB;
3203 LWLockRelease(MultiXactGenLock);
3204
3205 /* First truncate members */
3206 PerformMembersTruncation(oldestOffset, newOldestOffset);
3207
3208 /* Then offsets */
3209 PerformOffsetsTruncation(oldestMulti, newOldestMulti);
3210
3211 MyProc->delayChkptFlags &= ~DELAY_CHKPT_START;
3212
3214 LWLockRelease(MultiXactTruncationLock);
3215}
#define LOG
Definition: elog.h:31
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
static void WriteMTruncateXlogRec(Oid oldestMultiDB, MultiXactId startTruncOff, MultiXactId endTruncOff, MultiXactOffset startTruncMemb, MultiXactOffset endTruncMemb)
Definition: multixact.c:3305
static bool find_multixact_start(MultiXactId multi, MultiXactOffset *result)
Definition: multixact.c:2822
static bool SlruScanDirCbFindEarliest(SlruCtl ctl, char *filename, int64 segpage, void *data)
Definition: multixact.c:2973
bool MultiXactIdPrecedesOrEquals(MultiXactId multi1, MultiXactId multi2)
Definition: multixact.c:3279
#define DELAY_CHKPT_START
Definition: proc.h:135
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
Definition: slru.c:1816
PGPROC * MyProc
Definition: proc.c:66
int delayChkptFlags
Definition: proc.h:257
int64 earliestExistingPage
Definition: multixact.c:2965
bool RecoveryInProgress(void)
Definition: xlog.c:6386

References Assert(), DEBUG1, DELAY_CHKPT_START, PGPROC::delayChkptFlags, mxtruncinfo::earliestExistingPage, elog, END_CRIT_SECTION, ereport, errmsg(), find_multixact_start(), MultiXactStateData::finishedStartup, FirstMultiXactId, LOG, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), MULTIXACT_OFFSETS_PER_PAGE, MultiXactIdIsValid, MultiXactIdPrecedes(), MultiXactIdPrecedesOrEquals(), MultiXactIdToOffsetSegment(), MultiXactOffsetCtl, MultiXactState, MXOffsetToMemberSegment(), MyProc, MultiXactStateData::nextMXact, MultiXactStateData::nextOffset, MultiXactStateData::oldestMultiXactDB, MultiXactStateData::oldestMultiXactId, PerformMembersTruncation(), PerformOffsetsTruncation(), RecoveryInProgress(), SlruScanDirCbFindEarliest(), SlruScanDirectory(), START_CRIT_SECTION, and WriteMTruncateXlogRec().

Referenced by vac_truncate_clog().

AltStyle によって変換されたページ (->オリジナル) /