1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-30 06:01:21 +03:00

Postgres95 1.01 Distribution - Virgin Sources

This commit is contained in:
Marc G. Fournier
1996-07-09 06:22:35 +00:00
commit d31084e9d1
868 changed files with 242656 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
#-------------------------------------------------------------------------
#
# Makefile.inc--
# Makefile for access/transam
#
# Copyright (c) 1994, Regents of the University of California
#
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/access/transam/Attic/Makefile.inc,v 1.1.1.1 1996/07/09 06:21:13 scrappy Exp $
#
#-------------------------------------------------------------------------
SUBSRCS+= transam.c transsup.c varsup.c xact.c xid.c

View File

@@ -0,0 +1,675 @@
/*-------------------------------------------------------------------------
*
* transam.c--
* postgres transaction log/time interface routines
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.1.1.1 1996/07/09 06:21:13 scrappy Exp $
*
* NOTES
* This file contains the high level access-method interface to the
* transaction system.
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "machine.h" /* in port/ directory (needed for BLCKSZ) */
#include "access/heapam.h"
#include "storage/buf.h"
#include "storage/bufmgr.h"
#include "utils/memutils.h"
#include "utils/mcxt.h"
#include "utils/rel.h"
#include "utils/elog.h"
#include "utils/nabstime.h"
#include "catalog/catname.h"
#include "access/transam.h"
#include "access/xact.h"
#include "commands/vacuum.h" /* for VacuumRunning */
/* ----------------
* global variables holding pointers to relations used
* by the transaction system. These are initialized by
* InitializeTransactionLog().
* ----------------
*/
Relation LogRelation = (Relation) NULL;
Relation TimeRelation = (Relation) NULL;
Relation VariableRelation = (Relation) NULL;
/* ----------------
* global variables holding cached transaction id's and statuses.
* ----------------
*/
TransactionId cachedGetCommitTimeXid;
AbsoluteTime cachedGetCommitTime;
TransactionId cachedTestXid;
XidStatus cachedTestXidStatus;
/* ----------------
* transaction system constants
* ----------------
*/
/* ----------------------------------------------------------------
* transaction system constants
*
* read the comments for GetNewTransactionId in order to
* understand the initial values for AmiTransactionId and
* FirstTransactionId. -cim 3/23/90
* ----------------------------------------------------------------
*/
TransactionId NullTransactionId = (TransactionId) 0;
TransactionId AmiTransactionId = (TransactionId) 512;
TransactionId FirstTransactionId = (TransactionId) 514;
/* ----------------
* transaction recovery state variables
*
* When the transaction system is initialized, we may
* need to do recovery checking. This decision is decided
* by the postmaster or the user by supplying the backend
* with a special flag. In general, we want to do recovery
* checking whenever we are running without a postmaster
* or when the number of backends running under the postmaster
* goes from zero to one. -cim 3/21/90
* ----------------
*/
int RecoveryCheckingEnableState = 0;
/* ------------------
* spinlock for oid generation
* -----------------
*/
extern int OidGenLockId;
/* ----------------
* globals that must be reset at abort
* ----------------
*/
extern bool BuildingBtree;
/* ----------------
* recovery checking accessors
* ----------------
*/
int
RecoveryCheckingEnabled()
{
return RecoveryCheckingEnableState;
}
void
SetRecoveryCheckingEnabled(bool state)
{
RecoveryCheckingEnableState = (state == true);
}
/* ----------------------------------------------------------------
* postgres log/time access method interface
*
* TransactionLogTest
* TransactionLogUpdate
* ========
* these functions do work for the interface
* functions - they search/retrieve and append/update
* information in the log and time relations.
* ----------------------------------------------------------------
*/
/* --------------------------------
* TransactionLogTest
* --------------------------------
*/
bool /* true/false: does transaction id have specified status? */
TransactionLogTest(TransactionId transactionId, /* transaction id to test */
XidStatus status) /* transaction status */
{
BlockNumber blockNumber;
XidStatus xidstatus; /* recorded status of xid */
bool fail = false; /* success/failure */
/* ----------------
* during initialization consider all transactions
* as having been committed
* ----------------
*/
if (! RelationIsValid(LogRelation))
return (bool) (status == XID_COMMIT);
/* ----------------
* before going to the buffer manager, check our single
* item cache to see if we didn't just check the transaction
* status a moment ago.
* ----------------
*/
if (TransactionIdEquals(transactionId, cachedTestXid))
return (bool)
(status == cachedTestXidStatus);
/* ----------------
* compute the item pointer corresponding to the
* page containing our transaction id. We save the item in
* our cache to speed up things if we happen to ask for the
* same xid's status more than once.
* ----------------
*/
TransComputeBlockNumber(LogRelation, transactionId, &blockNumber);
xidstatus = TransBlockNumberGetXidStatus(LogRelation,
blockNumber,
transactionId,
&fail);
if (! fail) {
TransactionIdStore(transactionId, &cachedTestXid);
cachedTestXidStatus = xidstatus;
return (bool)
(status == xidstatus);
}
/* ----------------
* here the block didn't contain the information we wanted
* ----------------
*/
elog(WARN, "TransactionLogTest: failed to get xidstatus");
/*
* so lint is happy...
*/
return(false);
}
/* --------------------------------
* TransactionLogUpdate
* --------------------------------
*/
void
TransactionLogUpdate(TransactionId transactionId, /* trans id to update */
XidStatus status) /* new trans status */
{
BlockNumber blockNumber;
bool fail = false; /* success/failure */
AbsoluteTime currentTime; /* time of this transaction */
/* ----------------
* during initialization we don't record any updates.
* ----------------
*/
if (! RelationIsValid(LogRelation))
return;
/* ----------------
* get the transaction commit time
* ----------------
*/
currentTime = getSystemTime();
/* ----------------
* update the log relation
* ----------------
*/
TransComputeBlockNumber(LogRelation, transactionId, &blockNumber);
TransBlockNumberSetXidStatus(LogRelation,
blockNumber,
transactionId,
status,
&fail);
/* ----------------
* update (invalidate) our single item TransactionLogTest cache.
* ----------------
*/
TransactionIdStore(transactionId, &cachedTestXid);
cachedTestXidStatus = status;
/* ----------------
* now we update the time relation, if necessary
* (we only record commit times)
* ----------------
*/
if (RelationIsValid(TimeRelation) && status == XID_COMMIT) {
TransComputeBlockNumber(TimeRelation, transactionId, &blockNumber);
TransBlockNumberSetCommitTime(TimeRelation,
blockNumber,
transactionId,
currentTime,
&fail);
/* ----------------
* update (invalidate) our single item GetCommitTime cache.
* ----------------
*/
TransactionIdStore(transactionId, &cachedGetCommitTimeXid);
cachedGetCommitTime = currentTime;
}
/* ----------------
* now we update the "last committed transaction" field
* in the variable relation if we are recording a commit.
* ----------------
*/
if (RelationIsValid(VariableRelation) && status == XID_COMMIT)
UpdateLastCommittedXid(transactionId);
}
/* --------------------------------
* TransactionIdGetCommitTime
* --------------------------------
*/
AbsoluteTime /* commit time of transaction id */
TransactionIdGetCommitTime(TransactionId transactionId) /* transaction id to test */
{
BlockNumber blockNumber;
AbsoluteTime commitTime; /* commit time */
bool fail = false; /* success/failure */
/* ----------------
* return invalid if we aren't running yet...
* ----------------
*/
if (! RelationIsValid(TimeRelation))
return INVALID_ABSTIME;
/* ----------------
* before going to the buffer manager, check our single
* item cache to see if we didn't just get the commit time
* a moment ago.
* ----------------
*/
if (TransactionIdEquals(transactionId, cachedGetCommitTimeXid))
return cachedGetCommitTime;
/* ----------------
* compute the item pointer corresponding to the
* page containing our transaction commit time
* ----------------
*/
TransComputeBlockNumber(TimeRelation, transactionId, &blockNumber);
commitTime = TransBlockNumberGetCommitTime(TimeRelation,
blockNumber,
transactionId,
&fail);
/* ----------------
* update our cache and return the transaction commit time
* ----------------
*/
if (! fail) {
TransactionIdStore(transactionId, &cachedGetCommitTimeXid);
cachedGetCommitTime = commitTime;
return commitTime;
} else
return INVALID_ABSTIME;
}
/* ----------------------------------------------------------------
* transaction recovery code
* ----------------------------------------------------------------
*/
/* --------------------------------
* TransRecover
*
* preform transaction recovery checking.
*
* Note: this should only be preformed if no other backends
* are running. This is known by the postmaster and
* conveyed by the postmaster passing a "do recovery checking"
* flag to the backend.
*
* here we get the last recorded transaction from the log,
* get the "last" and "next" transactions from the variable relation
* and then preform some integrity tests:
*
* 1) No transaction may exist higher then the "next" available
* transaction recorded in the variable relation. If this is the
* case then it means either the log or the variable relation
* has become corrupted.
*
* 2) The last committed transaction may not be higher then the
* next available transaction for the same reason.
*
* 3) The last recorded transaction may not be lower then the
* last committed transaction. (the reverse is ok - it means
* that some transactions have aborted since the last commit)
*
* Here is what the proper situation looks like. The line
* represents the data stored in the log. 'c' indicates the
* transaction was recorded as committed, 'a' indicates an
* abortted transaction and '.' represents information not
* recorded. These may correspond to in progress transactions.
*
* c c a c . . a . . . . . . . . . .
* | |
* last next
*
* Since "next" is only incremented by GetNewTransactionId() which
* is called when transactions are started. Hence if there
* are commits or aborts after "next", then it means we committed
* or aborted BEFORE we started the transaction. This is the
* rational behind constraint (1).
*
* Likewise, "last" should never greater then "next" for essentially
* the same reason - it would imply we committed before we started.
* This is the reasoning for (2).
*
* (3) implies we may never have a situation such as:
*
* c c a c . . a c . . . . . . . . .
* | |
* last next
*
* where there is a 'c' greater then "last".
*
* Recovery checking is more difficult in the case where
* several backends are executing concurrently because the
* transactions may be executing in the other backends.
* So, we only do recovery stuff when the backend is explicitly
* passed a flag on the command line.
* --------------------------------
*/
void
TransRecover(Relation logRelation)
{
#if 0
/* ----------------
* first get the last recorded transaction in the log.
* ----------------
*/
TransGetLastRecordedTransaction(logRelation, logLastXid, &fail);
if (fail == true)
elog(WARN, "TransRecover: failed TransGetLastRecordedTransaction");
/* ----------------
* next get the "last" and "next" variables
* ----------------
*/
VariableRelationGetLastXid(&varLastXid);
VariableRelationGetNextXid(&varNextXid);
/* ----------------
* intregity test (1)
* ----------------
*/
if (TransactionIdIsLessThan(varNextXid, logLastXid))
elog(WARN, "TransRecover: varNextXid < logLastXid");
/* ----------------
* intregity test (2)
* ----------------
*/
/* ----------------
* intregity test (3)
* ----------------
*/
/* ----------------
* here we have a valid "
*
* **** RESUME HERE ****
* ----------------
*/
varNextXid = TransactionIdDup(varLastXid);
TransactionIdIncrement(&varNextXid);
VarPut(var, VAR_PUT_LASTXID, varLastXid);
VarPut(var, VAR_PUT_NEXTXID, varNextXid);
#endif
}
/* ----------------------------------------------------------------
* Interface functions
*
* InitializeTransactionLog
* ========
* this function (called near cinit) initializes
* the transaction log, time and variable relations.
*
* TransactionId DidCommit
* TransactionId DidAbort
* TransactionId IsInProgress
* ========
* these functions test the transaction status of
* a specified transaction id.
*
* TransactionId Commit
* TransactionId Abort
* TransactionId SetInProgress
* ========
* these functions set the transaction status
* of the specified xid. TransactionIdCommit() also
* records the current time in the time relation
* and updates the variable relation counter.
*
* ----------------------------------------------------------------
*/
/*
* InitializeTransactionLog --
* Initializes transaction logging.
*/
void
InitializeTransactionLog()
{
Relation logRelation;
Relation timeRelation;
MemoryContext oldContext;
/* ----------------
* don't do anything during bootstrapping
* ----------------
*/
if (AMI_OVERRIDE)
return;
/* ----------------
* disable the transaction system so the access methods
* don't interfere during initialization.
* ----------------
*/
OverrideTransactionSystem(true);
/* ----------------
* make sure allocations occur within the top memory context
* so that our log management structures are protected from
* garbage collection at the end of every transaction.
* ----------------
*/
oldContext = MemoryContextSwitchTo(TopMemoryContext);
/* ----------------
* first open the log and time relations
* (these are created by amiint so they are guaranteed to exist)
* ----------------
*/
logRelation = heap_openr(LogRelationName);
timeRelation = heap_openr(TimeRelationName);
VariableRelation = heap_openr(VariableRelationName);
/* ----------------
* XXX TransactionLogUpdate requires that LogRelation
* and TimeRelation are valid so we temporarily set
* them so we can initialize things properly.
* This could be done cleaner.
* ----------------
*/
LogRelation = logRelation;
TimeRelation = timeRelation;
/* ----------------
* if we have a virgin database, we initialize the log and time
* relation by committing the AmiTransactionId (id 512) and we
* initialize the variable relation by setting the next available
* transaction id to FirstTransactionId (id 514). OID initialization
* happens as a side effect of bootstrapping in varsup.c.
* ----------------
*/
SpinAcquire(OidGenLockId);
if (!TransactionIdDidCommit(AmiTransactionId)) {
/* ----------------
* SOMEDAY initialize the information stored in
* the headers of the log/time/variable relations.
* ----------------
*/
TransactionLogUpdate(AmiTransactionId, XID_COMMIT);
VariableRelationPutNextXid(FirstTransactionId);
} else if (RecoveryCheckingEnabled()) {
/* ----------------
* if we have a pre-initialized database and if the
* perform recovery checking flag was passed then we
* do our database integrity checking.
* ----------------
*/
TransRecover(logRelation);
}
LogRelation = (Relation) NULL;
TimeRelation = (Relation) NULL;
SpinRelease(OidGenLockId);
/* ----------------
* now re-enable the transaction system
* ----------------
*/
OverrideTransactionSystem(false);
/* ----------------
* instantiate the global variables
* ----------------
*/
LogRelation = logRelation;
TimeRelation = timeRelation;
/* ----------------
* restore the memory context to the previous context
* before we return from initialization.
* ----------------
*/
MemoryContextSwitchTo(oldContext);
}
/* --------------------------------
* TransactionId DidCommit
* TransactionId DidAbort
* TransactionId IsInProgress
* --------------------------------
*/
/*
* TransactionIdDidCommit --
* True iff transaction associated with the identifier did commit.
*
* Note:
* Assumes transaction identifier is valid.
*/
bool /* true if given transaction committed */
TransactionIdDidCommit(TransactionId transactionId)
{
if (AMI_OVERRIDE)
return true;
return
TransactionLogTest(transactionId, XID_COMMIT);
}
/*
* TransactionIdDidAborted --
* True iff transaction associated with the identifier did abort.
*
* Note:
* Assumes transaction identifier is valid.
* XXX Is this unneeded?
*/
bool /* true if given transaction aborted */
TransactionIdDidAbort(TransactionId transactionId)
{
if (AMI_OVERRIDE)
return false;
return
TransactionLogTest(transactionId, XID_ABORT);
}
bool /* true if given transaction neither committed nor aborted */
TransactionIdIsInProgress(TransactionId transactionId)
{
if (AMI_OVERRIDE)
return false;
return
TransactionLogTest(transactionId, XID_INPROGRESS);
}
/* --------------------------------
* TransactionId Commit
* TransactionId Abort
* TransactionId SetInProgress
* --------------------------------
*/
/*
* TransactionIdCommit --
* Commits the transaction associated with the identifier.
*
* Note:
* Assumes transaction identifier is valid.
*/
void
TransactionIdCommit(TransactionId transactionId)
{
if (AMI_OVERRIDE)
return;
/*
* Within TransactionLogUpdate we call UpdateLastCommited()
* which assumes we have exclusive access to pg_variable.
* Therefore we need to get exclusive access before calling
* TransactionLogUpdate. -mer 18 Aug 1992
*/
SpinAcquire(OidGenLockId);
TransactionLogUpdate(transactionId, XID_COMMIT);
SpinRelease(OidGenLockId);
}
/*
* TransactionIdAbort --
* Aborts the transaction associated with the identifier.
*
* Note:
* Assumes transaction identifier is valid.
*/
void
TransactionIdAbort(TransactionId transactionId)
{
BuildingBtree = false;
if (VacuumRunning)
vc_abort();
if (AMI_OVERRIDE)
return;
TransactionLogUpdate(transactionId, XID_ABORT);
}
void
TransactionIdSetInProgress(TransactionId transactionId)
{
if (AMI_OVERRIDE)
return;
TransactionLogUpdate(transactionId, XID_INPROGRESS);
}

View File

@@ -0,0 +1,663 @@
/*-------------------------------------------------------------------------
*
* transsup.c--
* postgres transaction access method support code
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/Attic/transsup.c,v 1.1.1.1 1996/07/09 06:21:13 scrappy Exp $
*
* NOTES
* This file contains support functions for the high
* level access method interface routines found in transam.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "machine.h" /* in port/ directory (needed for BLCKSZ) */
#include "storage/buf.h"
#include "storage/bufmgr.h"
#include "utils/rel.h"
#include "utils/elog.h"
#include "utils/memutils.h"
#include "utils/nabstime.h"
#include "catalog/heap.h"
#include "access/transam.h" /* where the declarations go */
#include "access/xact.h" /* where the declarations go */
#include "storage/smgr.h"
/* ----------------------------------------------------------------
* general support routines
* ----------------------------------------------------------------
*/
/* --------------------------------
* AmiTransactionOverride
*
* This function is used to manipulate the bootstrap flag.
* --------------------------------
*/
void
AmiTransactionOverride(bool flag)
{
AMI_OVERRIDE = flag;
}
/* --------------------------------
* TransComputeBlockNumber
* --------------------------------
*/
void
TransComputeBlockNumber(Relation relation, /* relation to test */
TransactionId transactionId, /* transaction id to test */
BlockNumber *blockNumberOutP)
{
long itemsPerBlock;
/* ----------------
* we calculate the block number of our transaction
* by dividing the transaction id by the number of
* transaction things per block.
* ----------------
*/
if (relation == LogRelation)
itemsPerBlock = TP_NumXidStatusPerBlock;
else if (relation == TimeRelation)
itemsPerBlock = TP_NumTimePerBlock;
else
elog(WARN, "TransComputeBlockNumber: unknown relation");
/* ----------------
* warning! if the transaction id's get too large
* then a BlockNumber may not be large enough to hold the results
* of our division.
*
* XXX this will all vanish soon when we implement an improved
* transaction id schema -cim 3/23/90
*
* This has vanished now that xid's are 4 bytes (no longer 5).
* -mer 5/24/92
* ----------------
*/
(*blockNumberOutP) = transactionId / itemsPerBlock;
}
/* ----------------------------------------------------------------
* trans block support routines
* ----------------------------------------------------------------
*/
/* --------------------------------
* TransBlockGetLastTransactionIdStatus
*
* This returns the status and transaction id of the last
* transaction information recorded on the given TransBlock.
* --------------------------------
*/
XidStatus
TransBlockGetLastTransactionIdStatus(Block tblock,
TransactionId baseXid,
TransactionId *returnXidP)
{
Index index;
Index maxIndex;
bits8 bit1;
bits8 bit2;
BitIndex offset;
XidStatus xstatus;
/* ----------------
* sanity check
* ----------------
*/
Assert((tblock != NULL));
/* ----------------
* search downward from the top of the block data, looking
* for the first Non-in progress transaction status. Since we
* are scanning backward, this will be last recorded transaction
* status on the block.
* ----------------
*/
maxIndex = TP_NumXidStatusPerBlock;
for (index = maxIndex-1; index>=0; index--) {
offset = BitIndexOf(index);
bit1 = ((bits8) BitArrayBitIsSet((BitArray) tblock, offset++)) << 1;
bit2 = (bits8) BitArrayBitIsSet((BitArray) tblock, offset);
xstatus = (bit1 | bit2) ;
/* ----------------
* here we have the status of some transaction, so test
* if the status is recorded as "in progress". If so, then
* we save the transaction id in the place specified by the caller.
* ----------------
*/
if (xstatus != XID_INPROGRESS) {
if (returnXidP != NULL) {
TransactionIdStore(baseXid, returnXidP);
TransactionIdAdd(returnXidP, index);
}
break;
}
}
/* ----------------
* if we get here and index is 0 it means we couldn't find
* a non-inprogress transaction on the block. For now we just
* return this info to the user. They can check if the return
* status is "in progress" to know this condition has arisen.
* ----------------
*/
if (index == 0) {
if (returnXidP != NULL)
TransactionIdStore(baseXid, returnXidP);
}
/* ----------------
* return the status to the user
* ----------------
*/
return xstatus;
}
/* --------------------------------
* TransBlockGetXidStatus
*
* This returns the status of the desired transaction
* --------------------------------
*/
XidStatus
TransBlockGetXidStatus(Block tblock,
TransactionId transactionId)
{
Index index;
bits8 bit1;
bits8 bit2;
BitIndex offset;
/* ----------------
* sanity check
* ----------------
*/
if (tblock == NULL) {
return XID_INVALID;
}
/* ----------------
* calculate the index into the transaction data where
* our transaction status is located
*
* XXX this will be replaced soon when we move to the
* new transaction id scheme -cim 3/23/90
*
* The old system has now been replaced. -mer 5/24/92
* ----------------
*/
index = transactionId % TP_NumXidStatusPerBlock;
/* ----------------
* get the data at the specified index
* ----------------
*/
offset = BitIndexOf(index);
bit1 = ((bits8) BitArrayBitIsSet((BitArray) tblock, offset++)) << 1;
bit2 = (bits8) BitArrayBitIsSet((BitArray) tblock, offset);
/* ----------------
* return the transaction status to the caller
* ----------------
*/
return (XidStatus)
(bit1 | bit2);
}
/* --------------------------------
* TransBlockSetXidStatus
*
* This sets the status of the desired transaction
* --------------------------------
*/
void
TransBlockSetXidStatus(Block tblock,
TransactionId transactionId,
XidStatus xstatus)
{
Index index;
BitIndex offset;
/* ----------------
* sanity check
* ----------------
*/
if (tblock == NULL)
return;
/* ----------------
* calculate the index into the transaction data where
* we sould store our transaction status.
*
* XXX this will be replaced soon when we move to the
* new transaction id scheme -cim 3/23/90
*
* The new scheme is here -mer 5/24/92
* ----------------
*/
index = transactionId % TP_NumXidStatusPerBlock;
offset = BitIndexOf(index);
/* ----------------
* store the transaction value at the specified offset
* ----------------
*/
switch(xstatus) {
case XID_COMMIT: /* set 10 */
BitArraySetBit((BitArray) tblock, offset);
BitArrayClearBit((BitArray) tblock, offset + 1);
break;
case XID_ABORT: /* set 01 */
BitArrayClearBit((BitArray) tblock, offset);
BitArraySetBit((BitArray) tblock, offset + 1);
break;
case XID_INPROGRESS: /* set 00 */
BitArrayClearBit((BitArray) tblock, offset);
BitArrayClearBit((BitArray) tblock, offset + 1);
break;
default:
elog(NOTICE,
"TransBlockSetXidStatus: invalid status: %d (ignored)",
xstatus);
break;
}
}
/* --------------------------------
* TransBlockGetCommitTime
*
* This returns the transaction commit time for the
* specified transaction id in the trans block.
* --------------------------------
*/
AbsoluteTime
TransBlockGetCommitTime(Block tblock,
TransactionId transactionId)
{
Index index;
AbsoluteTime *timeArray;
/* ----------------
* sanity check
* ----------------
*/
if (tblock == NULL)
return INVALID_ABSTIME;
/* ----------------
* calculate the index into the transaction data where
* our transaction commit time is located
*
* XXX this will be replaced soon when we move to the
* new transaction id scheme -cim 3/23/90
*
* The new scheme is here. -mer 5/24/92
* ----------------
*/
index = transactionId % TP_NumTimePerBlock;
/* ----------------
* return the commit time to the caller
* ----------------
*/
timeArray = (AbsoluteTime *) tblock;
return (AbsoluteTime)
timeArray[ index ];
}
/* --------------------------------
* TransBlockSetCommitTime
*
* This sets the commit time of the specified transaction
* --------------------------------
*/
void
TransBlockSetCommitTime(Block tblock,
TransactionId transactionId,
AbsoluteTime commitTime)
{
Index index;
AbsoluteTime *timeArray;
/* ----------------
* sanity check
* ----------------
*/
if (tblock == NULL)
return;
/* ----------------
* calculate the index into the transaction data where
* we sould store our transaction status.
*
* XXX this will be replaced soon when we move to the
* new transaction id scheme -cim 3/23/90
*
* The new scheme is here. -mer 5/24/92
* ----------------
*/
index = transactionId % TP_NumTimePerBlock;
/* ----------------
* store the transaction commit time at the specified index
* ----------------
*/
timeArray = (AbsoluteTime *) tblock;
timeArray[ index ] = commitTime;
}
/* ----------------------------------------------------------------
* transam i/o support routines
* ----------------------------------------------------------------
*/
/* --------------------------------
* TransBlockNumberGetXidStatus
* --------------------------------
*/
XidStatus
TransBlockNumberGetXidStatus(Relation relation,
BlockNumber blockNumber,
TransactionId xid,
bool *failP)
{
Buffer buffer; /* buffer associated with block */
Block block; /* block containing xstatus */
XidStatus xstatus; /* recorded status of xid */
bool localfail; /* bool used if failP = NULL */
/* ----------------
* SOMEDAY place a read lock on the log relation
* That someday is today 5 Aug 1991 -mer
* ----------------
*/
RelationSetLockForRead(relation);
/* ----------------
* get the page containing the transaction information
* ----------------
*/
buffer = ReadBuffer(relation, blockNumber);
block = BufferGetBlock(buffer);
/* ----------------
* get the status from the block. note, for now we always
* return false in failP.
* ----------------
*/
if (failP == NULL)
failP = &localfail;
(*failP) = false;
xstatus = TransBlockGetXidStatus(block, xid);
/* ----------------
* release the buffer and return the status
* ----------------
*/
ReleaseBuffer(buffer);
/* ----------------
* SOMEDAY release our lock on the log relation
* ----------------
*/
RelationUnsetLockForRead(relation);
return
xstatus;
}
/* --------------------------------
* TransBlockNumberSetXidStatus
* --------------------------------
*/
void
TransBlockNumberSetXidStatus(Relation relation,
BlockNumber blockNumber,
TransactionId xid,
XidStatus xstatus,
bool *failP)
{
Buffer buffer; /* buffer associated with block */
Block block; /* block containing xstatus */
bool localfail; /* bool used if failP = NULL */
/* ----------------
* SOMEDAY gain exclusive access to the log relation
*
* That someday is today 5 Aug 1991 -mer
* ----------------
*/
RelationSetLockForWrite(relation);
/* ----------------
* get the block containing the transaction status
* ----------------
*/
buffer = ReadBuffer(relation, blockNumber);
block = BufferGetBlock(buffer);
/* ----------------
* attempt to update the status of the transaction on the block.
* if we are successful, write the block. otherwise release the buffer.
* note, for now we always return false in failP.
* ----------------
*/
if (failP == NULL)
failP = &localfail;
(*failP) = false;
TransBlockSetXidStatus(block, xid, xstatus);
if ((*failP) == false)
WriteBuffer(buffer);
else
ReleaseBuffer(buffer);
/* ----------------
* SOMEDAY release our lock on the log relation
* ----------------
*/
RelationUnsetLockForWrite(relation);
}
/* --------------------------------
* TransBlockNumberGetCommitTime
* --------------------------------
*/
AbsoluteTime
TransBlockNumberGetCommitTime(Relation relation,
BlockNumber blockNumber,
TransactionId xid,
bool *failP)
{
Buffer buffer; /* buffer associated with block */
Block block; /* block containing commit time */
bool localfail; /* bool used if failP = NULL */
AbsoluteTime xtime; /* commit time */
/* ----------------
* SOMEDAY place a read lock on the time relation
*
* That someday is today 5 Aug. 1991 -mer
* ----------------
*/
RelationSetLockForRead(relation);
/* ----------------
* get the block containing the transaction information
* ----------------
*/
buffer = ReadBuffer(relation, blockNumber);
block = BufferGetBlock(buffer);
/* ----------------
* get the commit time from the block
* note, for now we always return false in failP.
* ----------------
*/
if (failP == NULL)
failP = &localfail;
(*failP) = false;
xtime = TransBlockGetCommitTime(block, xid);
/* ----------------
* release the buffer and return the commit time
* ----------------
*/
ReleaseBuffer(buffer);
/* ----------------
* SOMEDAY release our lock on the time relation
* ----------------
*/
RelationUnsetLockForRead(relation);
if ((*failP) == false)
return xtime;
else
return INVALID_ABSTIME;
}
/* --------------------------------
* TransBlockNumberSetCommitTime
* --------------------------------
*/
void
TransBlockNumberSetCommitTime(Relation relation,
BlockNumber blockNumber,
TransactionId xid,
AbsoluteTime xtime,
bool *failP)
{
Buffer buffer; /* buffer associated with block */
Block block; /* block containing commit time */
bool localfail; /* bool used if failP = NULL */
/* ----------------
* SOMEDAY gain exclusive access to the time relation
*
* That someday is today 5 Aug. 1991 -mer
* ----------------
*/
RelationSetLockForWrite(relation);
/* ----------------
* get the block containing our commit time
* ----------------
*/
buffer = ReadBuffer(relation, blockNumber);
block = BufferGetBlock(buffer);
/* ----------------
* attempt to update the commit time of the transaction on the block.
* if we are successful, write the block. otherwise release the buffer.
* note, for now we always return false in failP.
* ----------------
*/
if (failP == NULL)
failP = &localfail;
(*failP) = false;
TransBlockSetCommitTime(block, xid, xtime);
if ((*failP) == false)
WriteBuffer(buffer);
else
ReleaseBuffer(buffer);
/* ----------------
* SOMEDAY release our lock on the time relation
* ----------------
*/
RelationUnsetLockForWrite(relation);
}
/* --------------------------------
* TransGetLastRecordedTransaction
* --------------------------------
*/
void
TransGetLastRecordedTransaction(Relation relation,
TransactionId xid, /* return: transaction id */
bool *failP)
{
BlockNumber blockNumber; /* block number */
Buffer buffer; /* buffer associated with block */
Block block; /* block containing xid status */
BlockNumber n; /* number of blocks in the relation */
TransactionId baseXid;
(*failP) = false;
/* ----------------
* SOMEDAY gain exclusive access to the log relation
*
* That someday is today 5 Aug. 1991 -mer
* It looks to me like we only need to set a read lock here, despite
* the above comment about exclusive access. The block is never
* actually written into, we only check status bits.
* ----------------
*/
RelationSetLockForRead(relation);
/* ----------------
* we assume the last block of the log contains the last
* recorded transaction. If the relation is empty we return
* failure to the user.
* ----------------
*/
n = RelationGetNumberOfBlocks(relation);
if (n == 0) {
(*failP) = true;
return;
}
/* ----------------
* get the block containing the transaction information
* ----------------
*/
blockNumber = n-1;
buffer = ReadBuffer(relation, blockNumber);
block = BufferGetBlock(buffer);
/* ----------------
* get the last xid on the block
* ----------------
*/
baseXid = blockNumber * TP_NumXidStatusPerBlock;
/* XXX ???? xid won't get returned! - AY '94 */
(void) TransBlockGetLastTransactionIdStatus(block, baseXid, &xid);
ReleaseBuffer(buffer);
/* ----------------
* SOMEDAY release our lock on the log relation
* ----------------
*/
RelationUnsetLockForRead(relation);
}

View File

@@ -0,0 +1,606 @@
/*-------------------------------------------------------------------------
*
* varsup.c--
* postgres variable relation support routines
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.1.1.1 1996/07/09 06:21:13 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include <math.h>
#include "postgres.h"
#include "machine.h" /* in port/ directory (needed for BLCKSZ) */
#include "storage/buf.h"
#include "storage/bufmgr.h"
#include "storage/ipc.h" /* for OIDGENLOCKID */
#include "utils/rel.h"
#include "utils/elog.h"
#include "access/heapam.h"
#include "access/transam.h" /* where the declarations go */
#include "access/xact.h" /* where the declarations go */
#include "catalog/catname.h"
/* ----------
* note: we reserve the first 16384 object ids for internal use.
* oid's less than this appear in the .bki files. the choice of
* 16384 is completely arbitrary.
* ----------
*/
#define BootstrapObjectIdData 16384
/* ---------------------
* spin lock for oid generation
* ---------------------
*/
int OidGenLockId;
/* ----------------------------------------------------------------
* variable relation query/update routines
* ----------------------------------------------------------------
*/
/* --------------------------------
* VariableRelationGetNextXid
* --------------------------------
*/
void
VariableRelationGetNextXid(TransactionId *xidP)
{
Buffer buf;
VariableRelationContents var;
/* ----------------
* We assume that a spinlock has been acquire to guarantee
* exclusive access to the variable relation.
* ----------------
*/
/* ----------------
* do nothing before things are initialized
* ----------------
*/
if (! RelationIsValid(VariableRelation))
return;
/* ----------------
* read the variable page, get the the nextXid field and
* release the buffer
* ----------------
*/
buf = ReadBuffer(VariableRelation, 0);
if (! BufferIsValid(buf))
{
SpinRelease(OidGenLockId);
elog(WARN, "VariableRelationGetNextXid: ReadBuffer failed");
}
var = (VariableRelationContents) BufferGetBlock(buf);
TransactionIdStore(var->nextXidData, xidP);
ReleaseBuffer(buf);
}
/* --------------------------------
* VariableRelationGetLastXid
* --------------------------------
*/
void
VariableRelationGetLastXid(TransactionId *xidP)
{
Buffer buf;
VariableRelationContents var;
/* ----------------
* We assume that a spinlock has been acquire to guarantee
* exclusive access to the variable relation.
* ----------------
*/
/* ----------------
* do nothing before things are initialized
* ----------------
*/
if (! RelationIsValid(VariableRelation))
return;
/* ----------------
* read the variable page, get the the lastXid field and
* release the buffer
* ----------------
*/
buf = ReadBuffer(VariableRelation, 0);
if (! BufferIsValid(buf))
{
SpinRelease(OidGenLockId);
elog(WARN, "VariableRelationGetNextXid: ReadBuffer failed");
}
var = (VariableRelationContents) BufferGetBlock(buf);
TransactionIdStore(var->lastXidData, xidP);
ReleaseBuffer(buf);
}
/* --------------------------------
* VariableRelationPutNextXid
* --------------------------------
*/
void
VariableRelationPutNextXid(TransactionId xid)
{
Buffer buf;
VariableRelationContents var;
/* ----------------
* We assume that a spinlock has been acquire to guarantee
* exclusive access to the variable relation.
* ----------------
*/
/* ----------------
* do nothing before things are initialized
* ----------------
*/
if (! RelationIsValid(VariableRelation))
return;
/* ----------------
* read the variable page, update the nextXid field and
* write the page back out to disk.
* ----------------
*/
buf = ReadBuffer(VariableRelation, 0);
if (! BufferIsValid(buf))
{
SpinRelease(OidGenLockId);
elog(WARN, "VariableRelationPutNextXid: ReadBuffer failed");
}
var = (VariableRelationContents) BufferGetBlock(buf);
TransactionIdStore(xid, &(var->nextXidData));
WriteBuffer(buf);
}
/* --------------------------------
* VariableRelationPutLastXid
* --------------------------------
*/
void
VariableRelationPutLastXid(TransactionId xid)
{
Buffer buf;
VariableRelationContents var;
/* ----------------
* We assume that a spinlock has been acquire to guarantee
* exclusive access to the variable relation.
* ----------------
*/
/* ----------------
* do nothing before things are initialized
* ----------------
*/
if (! RelationIsValid(VariableRelation))
return;
/* ----------------
* read the variable page, update the lastXid field and
* force the page back out to disk.
* ----------------
*/
buf = ReadBuffer(VariableRelation, 0);
if (! BufferIsValid(buf))
{
SpinRelease(OidGenLockId);
elog(WARN, "VariableRelationPutLastXid: ReadBuffer failed");
}
var = (VariableRelationContents) BufferGetBlock(buf);
TransactionIdStore(xid, &(var->lastXidData));
WriteBuffer(buf);
}
/* --------------------------------
* VariableRelationGetNextOid
* --------------------------------
*/
void
VariableRelationGetNextOid(Oid *oid_return)
{
Buffer buf;
VariableRelationContents var;
/* ----------------
* We assume that a spinlock has been acquire to guarantee
* exclusive access to the variable relation.
* ----------------
*/
/* ----------------
* if the variable relation is not initialized, then we
* assume we are running at bootstrap time and so we return
* an invalid object id -- during this time GetNextBootstrapObjectId
* should be called instead..
* ----------------
*/
if (! RelationIsValid(VariableRelation)) {
if (PointerIsValid(oid_return))
(*oid_return) = InvalidOid;
return;
}
/* ----------------
* read the variable page, get the the nextOid field and
* release the buffer
* ----------------
*/
buf = ReadBuffer(VariableRelation, 0);
if (! BufferIsValid(buf))
{
SpinRelease(OidGenLockId);
elog(WARN, "VariableRelationGetNextXid: ReadBuffer failed");
}
var = (VariableRelationContents) BufferGetBlock(buf);
if (PointerIsValid(oid_return)) {
/* ----------------
* nothing up my sleeve... what's going on here is that this code
* is guaranteed never to be called until all files in data/base/
* are created, and the template database exists. at that point,
* we want to append a pg_database tuple. the first time we do
* this, the oid stored in pg_variable will be bogus, so we use
* a bootstrap value defined at the top of this file.
*
* this comment no longer holds true. This code is called before
* all of the files in data/base are created and you can't rely
* on system oid's to be less than BootstrapObjectIdData. mer 9/18/91
* ----------------
*/
if (OidIsValid(var->nextOid))
(*oid_return) = var->nextOid;
else
(*oid_return) = BootstrapObjectIdData;
}
ReleaseBuffer(buf);
}
/* --------------------------------
* VariableRelationPutNextOid
* --------------------------------
*/
void
VariableRelationPutNextOid(Oid *oidP)
{
Buffer buf;
VariableRelationContents var;
/* ----------------
* We assume that a spinlock has been acquire to guarantee
* exclusive access to the variable relation.
* ----------------
*/
/* ----------------
* do nothing before things are initialized
* ----------------
*/
if (! RelationIsValid(VariableRelation))
return;
/* ----------------
* sanity check
* ----------------
*/
if (! PointerIsValid(oidP))
{
SpinRelease(OidGenLockId);
elog(WARN, "VariableRelationPutNextOid: invalid oid pointer");
}
/* ----------------
* read the variable page, update the nextXid field and
* write the page back out to disk.
* ----------------
*/
buf = ReadBuffer(VariableRelation, 0);
if (! BufferIsValid(buf))
{
SpinRelease(OidGenLockId);
elog(WARN, "VariableRelationPutNextXid: ReadBuffer failed");
}
var = (VariableRelationContents) BufferGetBlock(buf);
var->nextOid = (*oidP);
WriteBuffer(buf);
}
/* ----------------------------------------------------------------
* transaction id generation support
* ----------------------------------------------------------------
*/
/* ----------------
* GetNewTransactionId
*
* In the version 2 transaction system, transaction id's are
* restricted in several ways.
*
* First, all transaction id's are even numbers (4, 88, 121342, etc).
* This means the binary representation of the number will never
* have the least significent bit set. This bit is reserved to
* indicate that the transaction id does not in fact hold an XID,
* but rather a commit time. This makes it possible for the
* vaccuum daemon to disgard information from the log and time
* relations for committed tuples. This is important when archiving
* tuples to an optical disk because tuples with commit times
* stored in their xid fields will not need to consult the log
* and time relations.
*
* Second, since we may someday preform compression of the data
* in the log and time relations, we cause the numbering of the
* transaction ids to begin at 512. This means that some space
* on the page of the log and time relations corresponding to
* transaction id's 0 - 510 will never be used. This space is
* in fact used to store the version number of the postgres
* transaction log and will someday store compression information
* about the log.
*
* Lastly, rather then access the variable relation each time
* a backend requests a new transction id, we "prefetch" 32
* transaction id's by incrementing the nextXid stored in the
* var relation by 64 (remember only even xid's are legal) and then
* returning these id's one at a time until they are exhausted.
* This means we reduce the number of accesses to the variable
* relation by 32 for each backend.
*
* Note: 32 has no special significance. We don't want the
* number to be too large because if when the backend
* terminates, we lose the xid's we cached.
*
* ----------------
*/
#define VAR_XID_PREFETCH 32
static int prefetched_xid_count = 0;
static TransactionId next_prefetched_xid;
void
GetNewTransactionId(TransactionId *xid)
{
TransactionId nextid;
/* ----------------
* during bootstrap initialization, we return the special
* bootstrap transaction id.
* ----------------
*/
if (AMI_OVERRIDE) {
TransactionIdStore(AmiTransactionId, xid);
return;
}
/* ----------------
* if we run out of prefetched xids, then we get some
* more before handing them out to the caller.
* ----------------
*/
if (prefetched_xid_count == 0) {
/* ----------------
* obtain exclusive access to the variable relation page
*
* get the "next" xid from the variable relation
* and save it in the prefetched id.
* ----------------
*/
SpinAcquire(OidGenLockId);
VariableRelationGetNextXid(&nextid);
TransactionIdStore(nextid, &next_prefetched_xid);
/* ----------------
* now increment the variable relation's next xid
* and reset the prefetched_xid_count. We multiply
* the id by two because our xid's are always even.
* ----------------
*/
prefetched_xid_count = VAR_XID_PREFETCH;
TransactionIdAdd(&nextid, prefetched_xid_count);
VariableRelationPutNextXid(nextid);
SpinRelease(OidGenLockId);
}
/* ----------------
* return the next prefetched xid in the pointer passed by
* the user and decrement the prefetch count. We add two
* to id we return the next time this is called because our
* transaction ids are always even.
*
* XXX Transaction Ids used to be even as the low order bit was
* used to determine commit status. This is no long true so
* we now use even and odd transaction ids. -mer 5/26/92
* ----------------
*/
TransactionIdStore(next_prefetched_xid, xid);
TransactionIdAdd(&next_prefetched_xid, 1);
prefetched_xid_count--;
}
/* ----------------
* UpdateLastCommittedXid
* ----------------
*/
void
UpdateLastCommittedXid(TransactionId xid)
{
TransactionId lastid;
/* we assume that spinlock OidGenLockId has been acquired
* prior to entering this function
*/
/* ----------------
* get the "last committed" transaction id from
* the variable relation page.
* ----------------
*/
VariableRelationGetLastXid(&lastid);
/* ----------------
* if the transaction id is greater than the last committed
* transaction then we update the last committed transaction
* in the variable relation.
* ----------------
*/
if (TransactionIdIsLessThan(lastid, xid))
VariableRelationPutLastXid(xid);
}
/* ----------------------------------------------------------------
* object id generation support
* ----------------------------------------------------------------
*/
/* ----------------
* GetNewObjectIdBlock
*
* This support function is used to allocate a block of object ids
* of the given size. applications wishing to do their own object
* id assignments should use this
* ----------------
*/
void
GetNewObjectIdBlock(Oid *oid_return, /* place to return the new object id */
int oid_block_size) /* number of oids desired */
{
Oid nextoid;
/* ----------------
* SOMEDAY obtain exclusive access to the variable relation page
* That someday is today -mer 6 Aug 1992
* ----------------
*/
SpinAcquire(OidGenLockId);
/* ----------------
* get the "next" oid from the variable relation
* and give it to the caller.
* ----------------
*/
VariableRelationGetNextOid(&nextoid);
if (PointerIsValid(oid_return))
(*oid_return) = nextoid;
/* ----------------
* now increment the variable relation's next oid
* field by the size of the oid block requested.
* ----------------
*/
nextoid += oid_block_size;
VariableRelationPutNextOid(&nextoid);
/* ----------------
* SOMEDAY relinquish our lock on the variable relation page
* That someday is today -mer 6 Apr 1992
* ----------------
*/
SpinRelease(OidGenLockId);
}
/* ----------------
* GetNewObjectId
*
* This function allocates and parses out object ids. Like
* GetNewTransactionId(), it "prefetches" 32 object ids by
* incrementing the nextOid stored in the var relation by 32 and then
* returning these id's one at a time until they are exhausted.
* This means we reduce the number of accesses to the variable
* relation by 32 for each backend.
*
* Note: 32 has no special significance. We don't want the
* number to be too large because if when the backend
* terminates, we lose the oids we cached.
*
* ----------------
*/
#define VAR_OID_PREFETCH 32
static int prefetched_oid_count = 0;
static Oid next_prefetched_oid;
void
GetNewObjectId(Oid *oid_return) /* place to return the new object id */
{
/* ----------------
* if we run out of prefetched oids, then we get some
* more before handing them out to the caller.
* ----------------
*/
if (prefetched_oid_count == 0) {
int oid_block_size = VAR_OID_PREFETCH;
/* ----------------
* during bootstrap time, we want to allocate oids
* one at a time. Otherwise there might be some
* bootstrap oid's left in the block we prefetch which
* would be passed out after the variable relation was
* initialized. This would be bad.
* ----------------
*/
if (! RelationIsValid(VariableRelation))
VariableRelation = heap_openr(VariableRelationName);
/* ----------------
* get a new block of prefetched object ids.
* ----------------
*/
GetNewObjectIdBlock(&next_prefetched_oid, oid_block_size);
/* ----------------
* now reset the prefetched_oid_count.
* ----------------
*/
prefetched_oid_count = oid_block_size;
}
/* ----------------
* return the next prefetched oid in the pointer passed by
* the user and decrement the prefetch count.
* ----------------
*/
if (PointerIsValid(oid_return))
(*oid_return) = next_prefetched_oid;
next_prefetched_oid++;
prefetched_oid_count--;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,156 @@
/*-------------------------------------------------------------------------
*
* xid.c--
* POSTGRES transaction identifier code.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/Attic/xid.c,v 1.1.1.1 1996/07/09 06:21:14 scrappy Exp $
*
* OLD COMMENTS
* XXX WARNING
* Much of this file will change when we change our representation
* of transaction ids -cim 3/23/90
*
* It is time to make the switch from 5 byte to 4 byte transaction ids
* This file was totally reworked. -mer 5/22/92
*
*-------------------------------------------------------------------------
*/
#include <stdio.h>
#include "postgres.h"
#include "utils/palloc.h"
#include "utils/elog.h"
#include "utils/memutils.h"
#include "utils/nabstime.h"
extern TransactionId NullTransactionId;
extern TransactionId DisabledTransactionId;
extern TransactionId AmiTransactionId;
extern TransactionId FirstTransactionId;
/* ----------------------------------------------------------------
* TransactionIdIsValid
*
* Macro-ize me.
* ----------------------------------------------------------------
*/
bool
TransactionIdIsValid(TransactionId transactionId)
{
return ((bool) (transactionId != NullTransactionId) );
}
/* XXX char16 name for catalogs */
TransactionId
xidin(char *representation)
{
return (atol(representation));
}
/* XXX char16 name for catalogs */
char*
xidout(TransactionId transactionId)
{
/* return(TransactionIdFormString(transactionId)); */
char *representation;
/* maximum 32 bit unsigned integer representation takes 10 chars */
representation = palloc(11);
(void)sprintf(representation, "%u", transactionId);
return (representation);
}
/* ----------------------------------------------------------------
* StoreInvalidTransactionId
*
* Maybe do away with Pointer types in these routines.
* Macro-ize this one.
* ----------------------------------------------------------------
*/
void
StoreInvalidTransactionId(TransactionId *destination)
{
*destination = NullTransactionId;
}
/* ----------------------------------------------------------------
* TransactionIdStore
*
* Macro-ize this one.
* ----------------------------------------------------------------
*/
void
TransactionIdStore(TransactionId transactionId,
TransactionId *destination)
{
*destination = transactionId;
}
/* ----------------------------------------------------------------
* TransactionIdEquals
* ----------------------------------------------------------------
*/
bool
TransactionIdEquals(TransactionId id1, TransactionId id2)
{
return ((bool) (id1 == id2));
}
/* ----------------------------------------------------------------
* TransactionIdIsLessThan
* ----------------------------------------------------------------
*/
bool
TransactionIdIsLessThan(TransactionId id1, TransactionId id2)
{
return ((bool)(id1 < id2));
}
/* ----------------------------------------------------------------
* xideq
* ----------------------------------------------------------------
*/
/*
* xideq - returns 1, iff xid1 == xid2
* 0 else;
*/
bool
xideq(TransactionId xid1, TransactionId xid2)
{
return( (bool) (xid1 == xid2) );
}
/* ----------------------------------------------------------------
* TransactionIdIncrement
* ----------------------------------------------------------------
*/
void
TransactionIdIncrement(TransactionId *transactionId)
{
(*transactionId)++;
if (*transactionId == DisabledTransactionId)
elog(FATAL, "TransactionIdIncrement: exhausted XID's");
return;
}
/* ----------------------------------------------------------------
* TransactionIdAdd
* ----------------------------------------------------------------
*/
void
TransactionIdAdd(TransactionId *xid, int value)
{
*xid += value;
return;
}