* Remove stale transactions, if any.
*/
ExpireOldKnownAssignedTransactionIds(running->oldestRunningXid);
+
+ /*
+ * Remove stale locks, if any.
+ *
+ * Locks are always assigned to the toplevel xid so we don't need to care
+ * about subxcnt/subxids (and by extension not about ->suboverflowed).
+ */
StandbyReleaseOldLocks(running->xcnt, running->xids);
/*
* Allocate a temporary array to avoid modifying the array passed as
* argument.
*/
- xids = palloc(sizeof(TransactionId) * running->xcnt);
+ xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
/*
* Add to the temp array any xids which have not already completed.
*/
nxids = 0;
- for (i = 0; i < running->xcnt; i++)
+ for (i = 0; i < running->xcnt + running->subxcnt; i++)
{
TransactionId xid = running->xids[i];
oldestRunningXid = ShmemVariableCache->nextXid;
/*
- * Spin over procArray collecting all xids and subxids.
+ * Spin over procArray collecting all xids
*/
for (index = 0; index < arrayP->numProcs; index++)
{
int pgprocno = arrayP->pgprocnos[index];
- volatile PGPROC *proc = &allProcs[pgprocno];
volatile PGXACT *pgxact = &allPgXact[pgprocno];
TransactionId xid;
- int nxids;
/* Fetch xid just once - see GetNewTransactionId */
xid = pgxact->xid;
if (TransactionIdPrecedes(xid, oldestRunningXid))
oldestRunningXid = xid;
- /*
- * Save subtransaction XIDs. Other backends can't add or remove
- * entries while we're holding XidGenLock.
- */
- nxids = pgxact->nxids;
- if (nxids > 0)
- {
- memcpy(&xids[count], (void *) proc->subxids.xids,
- nxids * sizeof(TransactionId));
- count += nxids;
- subcount += nxids;
+ if (pgxact->overflowed)
+ suboverflowed = true;
+ }
- if (pgxact->overflowed)
- suboverflowed = true;
+ /*
+ * Spin over procArray collecting all subxids, but only if there hasn't
+ * been a suboverflow.
+ */
+ if (!suboverflowed)
+ {
+ for (index = 0; index < arrayP->numProcs; index++)
+ {
+ int pgprocno = arrayP->pgprocnos[index];
+ volatile PGPROC *proc = &allProcs[pgprocno];
+ volatile PGXACT *pgxact = &allPgXact[pgprocno];
+ int nxids;
/*
- * Top-level XID of a transaction is always less than any of its
- * subxids, so we don't need to check if any of the subxids are
- * smaller than oldestRunningXid
+ * Save subtransaction XIDs. Other backends can't add or remove
+ * entries while we're holding XidGenLock.
*/
+ nxids = pgxact->nxids;
+ if (nxids > 0)
+ {
+ memcpy(&xids[count], (void *) proc->subxids.xids,
+ nxids * sizeof(TransactionId));
+ count += nxids;
+ subcount += nxids;
+
+ /*
+ * Top-level XID of a transaction is always less than any of
+ * its subxids, so we don't need to check if any of the subxids
+ * are smaller than oldestRunningXid
+ */
+ }
}
}
- CurrentRunningXacts->xcnt = count;
+ CurrentRunningXacts->xcnt = count - subcount;
+ CurrentRunningXacts->subxcnt = subcount;
CurrentRunningXacts->subxid_overflow = suboverflowed;
CurrentRunningXacts->nextXid = ShmemVariableCache->nextXid;
CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
RunningTransactionsData running;
running.xcnt = xlrec->xcnt;
+ running.subxcnt = xlrec->subxcnt;
running.subxid_overflow = xlrec->subxid_overflow;
running.nextXid = xlrec->nextXid;
running.latestCompletedXid = xlrec->latestCompletedXid;
XLogRecPtr recptr;
xlrec.xcnt = CurrRunningXacts->xcnt;
+ xlrec.subxcnt = CurrRunningXacts->subxcnt;
xlrec.subxid_overflow = CurrRunningXacts->subxid_overflow;
xlrec.nextXid = CurrRunningXacts->nextXid;
xlrec.oldestRunningXid = CurrRunningXacts->oldestRunningXid;
{
rdata[0].next = &(rdata[1]);
rdata[1].data = (char *) CurrRunningXacts->xids;
- rdata[1].len = xlrec.xcnt * sizeof(TransactionId);
+ rdata[1].len = (xlrec.xcnt + xlrec.subxcnt) * sizeof(TransactionId);
rdata[1].buffer = InvalidBuffer;
lastrdata = 1;
}
CurrRunningXacts->nextXid);
else
elog(trace_recovery(DEBUG2),
- "snapshot of %u running transaction ids (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
- CurrRunningXacts->xcnt,
+ "snapshot of %u+%u running transaction ids (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
+ CurrRunningXacts->xcnt, CurrRunningXacts->subxcnt,
(uint32) (recptr >> 32), (uint32) recptr,
CurrRunningXacts->oldestRunningXid,
CurrRunningXacts->latestCompletedXid,
typedef struct xl_running_xacts
{
int xcnt; /* # of xact ids in xids[] */
+ int subxcnt; /* # of subxact ids in xids[] */
bool subxid_overflow; /* snapshot overflowed, subxids missing */
TransactionId nextXid; /* copy of ShmemVariableCache->nextXid */
TransactionId oldestRunningXid; /* *not* oldestXmin */
typedef struct RunningTransactionsData
{
int xcnt; /* # of xact ids in xids[] */
+ int subxcnt; /* # of subxact ids in xids[] */
bool subxid_overflow; /* snapshot overflowed, subxids missing */
TransactionId nextXid; /* copy of ShmemVariableCache->nextXid */
TransactionId oldestRunningXid; /* *not* oldestXmin */