Commit b9f3a929 authored by Tom Lane's avatar Tom Lane

Create a new HeapTupleSatisfiesVacuum() routine in tqual.c that embodies the

validity checking rules for VACUUM.  Make some other rearrangements of the
VACUUM code to allow more code to be shared between full and lazy VACUUM.
Minor code cleanups and added comments for TransactionId manipulations.
parent eaafc9d6
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.122 2001/07/06 09:41:36 inoue Exp $
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.123 2001/07/12 04:11:12 tgl Exp $
*
*
* INTERFACE ROUTINES
......@@ -48,11 +48,6 @@
#include "pgstat.h"
XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from,
Buffer newbuf, HeapTuple newtup);
XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
char *unused, int unlen);
/* comments are in heap_update */
static xl_heaptid _locked_tuple_;
static void _heap_unlock_tuple(void *data);
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.44 2001/05/14 20:30:19 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.45 2001/07/12 04:11:13 tgl Exp $
*
* NOTES
* This file contains the high level access-method interface to the
......@@ -24,6 +24,7 @@
#include "catalog/catname.h"
#include "miscadmin.h"
static int RecoveryCheckingEnabled(void);
static void TransRecover(Relation logRelation);
static bool TransactionLogTest(TransactionId transactionId, XidStatus status);
......@@ -40,29 +41,11 @@ static void TransactionLogUpdate(TransactionId transactionId,
Relation LogRelation = (Relation) NULL;
/* ----------------
* global variables holding cached transaction id's and statuses.
* ----------------
*/
TransactionId cachedTestXid;
XidStatus cachedTestXidStatus;
/* ----------------
* transaction system constants
* Single-item cache for results of TransactionLogTest.
* ----------------
*/
/* ----------------------------------------------------------------
* 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;
static TransactionId cachedTestXid = NullTransactionId;
static XidStatus cachedTestXidStatus;
/* ----------------
* transaction recovery state variables
......@@ -76,7 +59,7 @@ TransactionId FirstTransactionId = (TransactionId) 514;
* goes from zero to one. -cim 3/21/90
* ----------------
*/
int RecoveryCheckingEnableState = 0;
static int RecoveryCheckingEnableState = 0;
/* ----------------
* recovery checking accessors
......@@ -203,14 +186,9 @@ TransactionLogUpdate(TransactionId transactionId, /* trans id to update */
/*
* update (invalidate) our single item TransactionLogTest cache.
*
* if (status != XID_COMMIT)
*
* What's the hell ?! Why != XID_COMMIT ?!
*/
TransactionIdStore(transactionId, &cachedTestXid);
cachedTestXidStatus = status;
}
/* ----------------------------------------------------------------
......@@ -355,17 +333,15 @@ InitializeTransactionLog(void)
/*
* if we have a virgin database, we initialize the log relation by
* committing the AmiTransactionId (id 512) and we initialize the
* committing the AmiTransactionId and we initialize the
* variable relation by setting the next available transaction id to
* FirstTransactionId (id 514). OID initialization happens as a side
* FirstTransactionId. OID initialization happens as a side
* effect of bootstrapping in varsup.c.
*/
SpinAcquire(OidGenLockId);
if (!TransactionIdDidCommit(AmiTransactionId))
{
TransactionLogUpdate(AmiTransactionId, XID_COMMIT);
TransactionIdStore(AmiTransactionId, &cachedTestXid);
cachedTestXidStatus = XID_COMMIT;
Assert(!IsUnderPostmaster &&
ShmemVariableCache->nextXid <= FirstTransactionId);
ShmemVariableCache->nextXid = FirstTransactionId;
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/Attic/transsup.c,v 1.30 2001/03/22 06:16:10 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/access/transam/Attic/transsup.c,v 1.31 2001/07/12 04:11:13 tgl Exp $
*
* NOTES
* This file contains support functions for the high
......@@ -16,12 +16,67 @@
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/xact.h"
#include "utils/bit.h"
/* ----------------
* transaction system version id
*
* this is stored on the first page of the log, time and variable
* relations on the first 4 bytes. This is so that if we improve
* the format of the transaction log after postgres version 2, then
* people won't have to rebuild their databases.
*
* TRANS_SYSTEM_VERSION 100 means major version 1 minor version 0.
* Two databases with the same major version should be compatible,
* even if their minor versions differ.
*
* XXX This isn't actually being used!
* ----------------
*/
#define TRANS_SYSTEM_VERSION 200
/* ----------------
* LogRelationContents structure
*
* This structure describes the storage of the data in the
* first 128 bytes of the log relation. This storage is never
* used for transaction status because transaction id's begin
* their numbering at 512.
*
* The first 4 bytes of this relation store the version
* number of the transaction system.
*
* XXX This isn't actually being used!
* ----------------
*/
typedef struct LogRelationContentsData
{
XLogRecPtr LSN; /* temp hack: LSN is member of any block */
/* so should be described in bufmgr */
int TransSystemVersion;
} LogRelationContentsData;
typedef LogRelationContentsData *LogRelationContents;
/* ----------------
* BitIndexOf computes the index of the Nth xid on a given block
* ----------------
*/
#define BitIndexOf(N) ((N) * 2)
/* ----------------
* transaction page definitions
* ----------------
*/
#define TP_DataSize (BLCKSZ - sizeof(XLogRecPtr))
#define TP_NumXidStatusPerBlock (TP_DataSize * 4)
static XidStatus TransBlockGetXidStatus(Block tblock,
TransactionId transactionId);
static void TransBlockSetXidStatus(Block tblock,
......@@ -54,7 +109,7 @@ TransComputeBlockNumber(Relation relation, /* relation to test */
* test */
BlockNumber *blockNumberOutP)
{
long itemsPerBlock = 0;
uint32 itemsPerBlock = 0;
/*
* we calculate the block number of our transaction by dividing the
......@@ -135,10 +190,7 @@ TransBlockGetLastTransactionIdStatus(Block tblock,
if (xstatus != XID_INPROGRESS)
{
if (returnXidP != NULL)
{
TransactionIdStore(baseXid, returnXidP);
TransactionIdAdd(returnXidP, index - 1);
}
TransactionIdStore(baseXid + (index - 1), returnXidP);
break;
}
}
......
......@@ -6,7 +6,7 @@
* Copyright (c) 2000, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.40 2001/05/25 15:45:32 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.41 2001/07/12 04:11:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -18,8 +18,7 @@
#include "storage/proc.h"
/* Number of XIDs and OIDs to prefetch (preallocate) per XLOG write */
#define VAR_XID_PREFETCH 1024
/* Number of OIDs to prefetch (preallocate) per XLOG write */
#define VAR_OID_PREFETCH 8192
/* Spinlocks for serializing generation of XIDs and OIDs, respectively */
......@@ -29,10 +28,13 @@ SPINLOCK OidGenLockId;
/* pointer to "variable cache" in shared memory (set up by shmem.c) */
VariableCache ShmemVariableCache = NULL;
/*
* Allocate the next XID for my new transaction.
*/
void
GetNewTransactionId(TransactionId *xid)
{
/*
* During bootstrap initialization, we return the special bootstrap
* transaction id.
......@@ -49,10 +51,22 @@ GetNewTransactionId(TransactionId *xid)
(ShmemVariableCache->nextXid)++;
SpinRelease(XidGenLockId);
/*
* Must set MyProc->xid before releasing XidGenLock. This ensures that
* when GetSnapshotData calls ReadNewTransactionId, all active XIDs
* before the returned value of nextXid are already present in the shared
* PROC array. Else we have a race condition.
*
* XXX by storing xid into MyProc without acquiring SInvalLock, we are
* relying on fetch/store of an xid to be atomic, else other backends
* might see a partially-set xid here. But holding both locks at once
* would be a nasty concurrency hit (and at this writing, could cause a
* deadlock against GetSnapshotData). So for now, assume atomicity.
*/
if (MyProc != (PROC *) NULL)
MyProc->xid = *xid;
SpinRelease(XidGenLockId);
}
/*
......@@ -61,7 +75,6 @@ GetNewTransactionId(TransactionId *xid)
void
ReadNewTransactionId(TransactionId *xid)
{
/*
* During bootstrap initialization, we return the special bootstrap
* transaction id.
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.105 2001/07/06 21:04:25 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.106 2001/07/12 04:11:13 tgl Exp $
*
* NOTES
* Transaction aborts can now occur two ways:
......@@ -199,14 +199,9 @@ static void StartTransaction(void);
/* ----------------
* global variables holding the current transaction state.
*
* Note: when we are running several slave processes, the
* current transaction state data is copied into shared memory
* and the CurrentTransactionState pointer changed to
* point to the shared copy. All this occurrs in slaves.c
* ----------------
*/
TransactionStateData CurrentTransactionStateData = {
static TransactionStateData CurrentTransactionStateData = {
0, /* transaction id */
FirstCommandId, /* command id */
0, /* scan command id */
......@@ -234,29 +229,17 @@ static void *_RollbackData = NULL;
* info returned when the system is disabled
*
* Apparently a lot of this code is inherited from other prototype systems.
*
* For DisabledStartTime, use a symbolic value to make the relationships clearer.
* The old value of 1073741823 corresponds to a date in y2004, which is coming closer
* every day. It appears that if we return a value guaranteed larger than
* any real time associated with a transaction then comparisons in other
* modules will still be correct. Let's use BIG_ABSTIME for this. tgl 2/14/97
*
* Note: I have no idea what the significance of the
* 1073741823 in DisabledStartTime.. I just carried
* this over when converting things from the old
* V1 transaction system. -cim 3/18/90
* ----------------
*/
TransactionId DisabledTransactionId = (TransactionId) -1;
static CommandId DisabledCommandId = (CommandId) -1;
CommandId DisabledCommandId = (CommandId) -1;
AbsoluteTime DisabledStartTime = (AbsoluteTime) BIG_ABSTIME; /* 1073741823; */
/* ----------------
* overflow flag
* ----------------
*/
bool CommandIdCounterOverflowFlag;
static AbsoluteTime DisabledStartTime = (AbsoluteTime) BIG_ABSTIME;
/* ----------------
* catalog creation transaction bootstrapping flag.
......@@ -362,7 +345,7 @@ IsAbortedTransactionBlockState(void)
* themselves.
* --------------------------------
*/
int SavedTransactionState;
static int SavedTransactionState;
void
OverrideTransactionSystem(bool flag)
......@@ -403,12 +386,12 @@ GetCurrentTransactionId(void)
* "disabled" transaction id.
*/
if (s->state == TRANS_DISABLED)
return (TransactionId) DisabledTransactionId;
return DisabledTransactionId;
/*
* otherwise return the current transaction id.
*/
return (TransactionId) s->transactionIdData;
return s->transactionIdData;
}
......@@ -426,7 +409,7 @@ GetCurrentCommandId(void)
* "disabled" command id.
*/
if (s->state == TRANS_DISABLED)
return (CommandId) DisabledCommandId;
return DisabledCommandId;
return s->commandId;
}
......@@ -441,7 +424,7 @@ GetScanCommandId(void)
* "disabled" command id.
*/
if (s->state == TRANS_DISABLED)
return (CommandId) DisabledCommandId;
return DisabledCommandId;
return s->scanCommandId;
}
......@@ -461,7 +444,7 @@ GetCurrentTransactionStartTime(void)
* "disabled" starting time.
*/
if (s->state == TRANS_DISABLED)
return (AbsoluteTime) DisabledStartTime;
return DisabledStartTime;
return s->startTime;
}
......@@ -479,8 +462,7 @@ TransactionIdIsCurrentTransactionId(TransactionId xid)
if (AMI_OVERRIDE)
return false;
return (bool)
TransactionIdEquals(xid, s->transactionIdData);
return TransactionIdEquals(xid, s->transactionIdData);
}
......@@ -511,19 +493,6 @@ CommandIdGEScanCommandId(CommandId cid)
}
/* --------------------------------
* ClearCommandIdCounterOverflowFlag
* --------------------------------
*/
#ifdef NOT_USED
void
ClearCommandIdCounterOverflowFlag(void)
{
CommandIdCounterOverflowFlag = false;
}
#endif
/* --------------------------------
* CommandCounterIncrement
* --------------------------------
......@@ -533,10 +502,7 @@ CommandCounterIncrement(void)
{
CurrentTransactionStateData.commandId += 1;
if (CurrentTransactionStateData.commandId == FirstCommandId)
{
CommandIdCounterOverflowFlag = true;
elog(ERROR, "You may only have 2^32-1 commands per transaction");
}
CurrentTransactionStateData.scanCommandId = CurrentTransactionStateData.commandId;
......@@ -551,9 +517,7 @@ CommandCounterIncrement(void)
void
SetScanCommandId(CommandId savedId)
{
CurrentTransactionStateData.scanCommandId = savedId;
}
/* ----------------------------------------------------------------
......@@ -1113,6 +1077,13 @@ AbortTransaction(void)
/*
* Let others to know about no transaction in progress - vadim
* 11/26/96
*
* XXX it'd be nice to acquire SInvalLock for this, but too much risk of
* lockup: what if we were holding SInvalLock when we elog'd? Net effect
* is that we are relying on fetch/store of an xid to be atomic, else
* other backends might see a partially-zeroed xid here. Would it be
* safe to release spins before we reset xid/xmin? But see also
* GetNewTransactionId, which does the same thing.
*/
if (MyProc != (PROC *) NULL)
{
......
/*-------------------------------------------------------------------------
*
* xid.c
* POSTGRES transaction identifier type.
* POSTGRES transaction identifier datatype.
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: xid.c,v 1.30 2001/03/22 03:59:18 momjian Exp $
* $Id: xid.c,v 1.31 2001/07/12 04:11:13 tgl Exp $
*
* OLD COMMENTS
* XXX WARNING
......@@ -30,12 +30,6 @@
#define PG_RETURN_TRANSACTIONID(x) PG_RETURN_UINT32(x)
extern TransactionId NullTransactionId;
extern TransactionId DisabledTransactionId;
extern TransactionId AmiTransactionId;
extern TransactionId FirstTransactionId;
/* XXX name for catalogs */
Datum
xidin(PG_FUNCTION_ARGS)
{
......@@ -44,7 +38,6 @@ xidin(PG_FUNCTION_ARGS)
PG_RETURN_TRANSACTIONID((TransactionId) atol(representation));
}
/* XXX name for catalogs */
Datum
xidout(PG_FUNCTION_ARGS)
{
......@@ -73,15 +66,5 @@ xideq(PG_FUNCTION_ARGS)
TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
PG_RETURN_BOOL(xid1 == xid2);
}
/* ----------------------------------------------------------------
* TransactionIdAdd
* ----------------------------------------------------------------
*/
void
TransactionIdAdd(TransactionId *xid, int value)
{
*xid += value;
PG_RETURN_BOOL(TransactionIdEquals(xid1, xid2));
}
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.35 2001/07/06 21:04:26 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v 1.36 2001/07/12 04:11:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -194,7 +194,7 @@ TransactionIdIsInProgress(TransactionId xid)
{
PROC *proc = (PROC *) MAKE_PTR(pOffset);
if (proc->xid == xid)
if (TransactionIdEquals(proc->xid, xid))
{
result = true;
break;
......@@ -212,15 +212,20 @@ TransactionIdIsInProgress(TransactionId xid)
* when all current transaction were started.
* It's used by vacuum to decide what deleted
* tuples must be preserved in a table.
*
* Note: we include all currently running xids in the set of considered xids.
* This ensures that if a just-started xact has not yet set its snapshot,
* when it does set the snapshot it cannot set xmin less than what we compute.
*/
void
GetXmaxRecent(TransactionId *XmaxRecent)
{
SISeg *segP = shmInvalBuffer;
ProcState *stateP = segP->procState;
TransactionId result;
int index;
*XmaxRecent = GetCurrentTransactionId();
result = GetCurrentTransactionId();
SpinAcquire(SInvalLock);
......@@ -231,18 +236,24 @@ GetXmaxRecent(TransactionId *XmaxRecent)
if (pOffset != INVALID_OFFSET)
{
PROC *proc = (PROC *) MAKE_PTR(pOffset);
TransactionId xmin;
TransactionId xid;
xmin = proc->xmin; /* we don't use spin-locking in
* AbortTransaction() ! */
if (proc == MyProc || xmin < FirstTransactionId)
continue;
if (xmin < *XmaxRecent)
*XmaxRecent = xmin;
xid = proc->xid;
if (! TransactionIdIsSpecial(xid))
{
if (TransactionIdPrecedes(xid, result))
result = xid;
xid = proc->xmin;
if (! TransactionIdIsSpecial(xid))
if (TransactionIdPrecedes(xid, result))
result = xid;
}
}
}
SpinRelease(SInvalLock);
*XmaxRecent = result;
}
/*
......@@ -291,28 +302,21 @@ GetSnapshotData(bool serializable)
if (pOffset != INVALID_OFFSET)
{
PROC *proc = (PROC *) MAKE_PTR(pOffset);
TransactionId xid;
TransactionId xid = proc->xid;
/*
* We don't use spin-locking when changing proc->xid in
* GetNewTransactionId() and in AbortTransaction() !..
* Ignore my own proc (dealt with my xid above), procs not
* running a transaction, and xacts started since we read
* the next transaction ID. There's no need to store XIDs
* above what we got from ReadNewTransactionId, since we'll
* treat them as running anyway.
*/
xid = proc->xid;
if (proc == MyProc ||
xid < FirstTransactionId || xid >= snapshot->xmax)
{
/*--------
* Seems that there is no sense to store
* xid >= snapshot->xmax
* (what we got from ReadNewTransactionId above)
* in snapshot->xip. We just assume that all xacts
* with such xid-s are running and may be ignored.
*--------
*/
TransactionIdIsSpecial(xid) ||
! TransactionIdPrecedes(xid, snapshot->xmax))
continue;
}
if (xid < snapshot->xmin)
if (TransactionIdPrecedes(xid, snapshot->xmin))
snapshot->xmin = xid;
snapshot->xip[count] = xid;
count++;
......
......@@ -8,18 +8,18 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.37 2001/01/24 19:43:18 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.38 2001/07/12 04:11:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* #define TQUALDEBUG 1 */
#include "postgres.h"
#include "storage/sinval.h"
#include "utils/tqual.h"
SnapshotData SnapshotDirtyData;
static SnapshotData SnapshotDirtyData;
Snapshot SnapshotDirty = &SnapshotDirtyData;
Snapshot QuerySnapshot = NULL;
......@@ -587,10 +587,138 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
return false;
}
/*
* HeapTupleSatisfiesVacuum - determine tuple status for VACUUM and related
* operations
*
* XmaxRecent is a cutoff XID (obtained from GetXmaxRecent()). Tuples
* deleted by XIDs >= XmaxRecent are deemed "recently dead"; they might
* still be visible to some open transaction, so we can't remove them,
* even if we see that the deleting transaction has committed.
*
* As with the other HeapTupleSatisfies routines, we may update the tuple's
* "hint" status bits if we see that the inserting or deleting transaction
* has now committed or aborted. The caller is responsible for noticing any
* change in t_infomask and scheduling a disk write if so.
*/
HTSV_Result
HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId XmaxRecent)
{
/*
* Has inserting transaction committed?
*
* If the inserting transaction aborted, then the tuple was never visible
* to any other transaction, so we can delete it immediately.
*/
if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
{
if (tuple->t_infomask & HEAP_XMIN_INVALID)
return HEAPTUPLE_DEAD;
else if (tuple->t_infomask & HEAP_MOVED_OFF)
{
if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
{
tuple->t_infomask |= HEAP_XMIN_INVALID;
return HEAPTUPLE_DEAD;
}
/* Assume we can only get here if previous VACUUM aborted, */
/* ie, it couldn't still be in progress */
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
}
else if (tuple->t_infomask & HEAP_MOVED_IN)
{
if (!TransactionIdDidCommit((TransactionId) tuple->t_cmin))
{
/* Assume we can only get here if previous VACUUM aborted */
tuple->t_infomask |= HEAP_XMIN_INVALID;
return HEAPTUPLE_DEAD;
}
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
}
else if (TransactionIdDidAbort(tuple->t_xmin))
{
tuple->t_infomask |= HEAP_XMIN_INVALID;
return HEAPTUPLE_DEAD;
}
else if (TransactionIdDidCommit(tuple->t_xmin))
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
else if (TransactionIdIsInProgress(tuple->t_xmin))
return HEAPTUPLE_INSERT_IN_PROGRESS;
else
{
/*
* Not Aborted, Not Committed, Not in Progress -
* so it's from crashed process. - vadim 11/26/96
*/
tuple->t_infomask |= HEAP_XMIN_INVALID;
return HEAPTUPLE_DEAD;
}
/* Should only get here if we set XMIN_COMMITTED */
Assert(tuple->t_infomask & HEAP_XMIN_COMMITTED);
}
/*
* Okay, the inserter committed, so it was good at some point. Now
* what about the deleting transaction?
*/
if (tuple->t_infomask & HEAP_XMAX_INVALID)
return HEAPTUPLE_LIVE;
if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
{
if (TransactionIdDidAbort(tuple->t_xmax))
{
tuple->t_infomask |= HEAP_XMAX_INVALID;
return HEAPTUPLE_LIVE;
}
else if (TransactionIdDidCommit(tuple->t_xmax))
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
else if (TransactionIdIsInProgress(tuple->t_xmax))
return HEAPTUPLE_DELETE_IN_PROGRESS;
else
{
/*
* Not Aborted, Not Committed, Not in Progress -
* so it's from crashed process. - vadim 06/02/97
*/
tuple->t_infomask |= HEAP_XMAX_INVALID;
return HEAPTUPLE_LIVE;
}
/* Should only get here if we set XMAX_COMMITTED */
Assert(tuple->t_infomask & HEAP_XMAX_COMMITTED);
}
/*
* Deleter committed, but check special cases.
*/
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
{
/* "deleting" xact really only marked it for update */
return HEAPTUPLE_LIVE;
}
if (TransactionIdEquals(tuple->t_xmin, tuple->t_xmax))
{
/* inserter also deleted it, so it was never visible to anyone else */
return HEAPTUPLE_DEAD;
}
if (!TransactionIdPrecedes(tuple->t_xmax, XmaxRecent))
{
/* deleting xact is too recent, tuple could still be visible */
return HEAPTUPLE_RECENTLY_DEAD;
}
/* Otherwise, it's dead and removable */
return HEAPTUPLE_DEAD;
}
void
SetQuerySnapshot(void)
{
/* Initialize snapshot overriding to false */
ReferentialIntegritySnapshotOverride = false;
......@@ -615,13 +743,11 @@ SetQuerySnapshot(void)
QuerySnapshot = GetSnapshotData(false);
Assert(QuerySnapshot != NULL);
}
void
FreeXactSnapshot(void)
{
if (QuerySnapshot != NULL && QuerySnapshot != SerializableSnapshot)
{
free(QuerySnapshot->xip);
......@@ -637,5 +763,4 @@ FreeXactSnapshot(void)
}
SerializableSnapshot = NULL;
}
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: heapam.h,v 1.65 2001/06/22 19:16:23 wieck Exp $
* $Id: heapam.h,v 1.66 2001/07/12 04:11:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -15,6 +15,7 @@
#define HEAPAM_H
#include <time.h>
#include "access/htup.h"
#include "access/relscan.h"
#include "access/tupmacs.h"
......@@ -218,6 +219,11 @@ extern void heap_restrpos(HeapScanDesc scan);
extern void heap_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void heap_undo(XLogRecPtr lsn, XLogRecord *rptr);
extern void heap_desc(char *buf, uint8 xl_info, char *rec);
extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
char *unused, int unlen);
extern XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf,
ItemPointerData from,
Buffer newbuf, HeapTuple newtup);
/* in common/heaptuple.c */
extern Size ComputeDataSize(TupleDesc tupleDesc, Datum *value, char *nulls);
......
/*-------------------------------------------------------------------------
*
* transam.h
* postgres transaction access method support code header
* postgres transaction access method support code
*
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: transam.h,v 1.35 2001/05/25 15:45:33 momjian Exp $
*
* NOTES
* Transaction System Version 101 now support proper oid
* generation and recording in the variable relation.
* $Id: transam.h,v 1.36 2001/07/12 04:11:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -20,77 +16,60 @@
#include "storage/bufmgr.h"
/* ----------------
* transaction system version id
* Special transaction ID values
*
* this is stored on the first page of the log, time and variable
* relations on the first 4 bytes. This is so that if we improve
* the format of the transaction log after postgres version 2, then
* people won't have to rebuild their databases.
* We do not use any transaction IDs less than 512 --- this leaves the first
* 128 bytes of pg_log available for special purposes such as version number
* storage. (Currently, we do not actually use them for anything.)
*
* TRANS_SYSTEM_VERSION 100 means major version 1 minor version 0.
* Two databases with the same major version should be compatible,
* even if their minor versions differ.
* AmiTransactionId is the XID for "bootstrap" operations. It should always
* be considered valid.
*
* FirstTransactionId is the first "normal" transaction id.
* ----------------
*/
#define NullTransactionId ((TransactionId) 0)
#define DisabledTransactionId ((TransactionId) 1)
#define AmiTransactionId ((TransactionId) 512)
#define FirstTransactionId ((TransactionId) 514)
/* ----------------
* transaction ID manipulation macros
* ----------------
*/
#define TRANS_SYSTEM_VERSION 200
#define TransactionIdIsValid(xid) ((bool) ((xid) != NullTransactionId))
#define TransactionIdIsSpecial(xid) ((bool) ((xid) < FirstTransactionId))
#define TransactionIdEquals(id1, id2) ((bool) ((id1) == (id2)))
#define TransactionIdPrecedes(id1, id2) ((bool) ((id1) < (id2)))
#define TransactionIdStore(xid, dest) \
(*((TransactionId*) (dest)) = (TransactionId) (xid))
#define StoreInvalidTransactionId(dest) \
(*((TransactionId*) (dest)) = NullTransactionId)
/* ----------------
* transaction id status values
* transaction status values
*
* someday we will use "11" = 3 = XID_COMMIT_CHILD to mean the
* commiting of child xactions.
* ----------------
*/
#define XID_COMMIT 2 /* transaction commited */
#define XID_ABORT 1 /* transaction aborted */
#define XID_INPROGRESS 0 /* transaction in progress */
#define XID_ABORT 1 /* transaction aborted */
#define XID_COMMIT 2 /* transaction commited */
#define XID_COMMIT_CHILD 3 /* child xact commited */
typedef unsigned char XidStatus;/* (2 bits) */
typedef unsigned char XidStatus; /* (2 bits) */
/* ----------
* note: we reserve the first 16384 object ids for internal use.
* We reserve the first 16384 object ids for manual assignment.
* oid's less than this appear in the .bki files. the choice of
* 16384 is completely arbitrary.
* ----------
*/
#define BootstrapObjectIdData 16384
/* ----------------
* BitIndexOf computes the index of the Nth xid on a given block
* ----------------
*/
#define BitIndexOf(N) ((N) * 2)
/* ----------------
* transaction page definitions
* ----------------
*/
#define TP_DataSize (BLCKSZ - sizeof(XLogRecPtr))
#define TP_NumXidStatusPerBlock (TP_DataSize * 4)
/* ----------------
* LogRelationContents structure
*
* This structure describes the storage of the data in the
* first 128 bytes of the log relation. This storage is never
* used for transaction status because transaction id's begin
* their numbering at 512.
*
* The first 4 bytes of this relation store the version
* number of the transaction system.
* ----------------
*/
typedef struct LogRelationContentsData
{
XLogRecPtr LSN; /* temp hack: LSN is member of any block */
/* so should be described in bufmgr */
int TransSystemVersion;
} LogRelationContentsData;
typedef LogRelationContentsData *LogRelationContents;
/*
* VariableCache is placed in shmem and used by
* backends to get next available XID & OID.
......@@ -104,6 +83,7 @@ typedef struct VariableCacheData
typedef VariableCacheData *VariableCache;
/* ----------------
* extern declarations
* ----------------
......@@ -142,16 +122,7 @@ extern void CheckMaxObjectId(Oid assigned_oid);
/* in transam.c */
extern Relation LogRelation;
extern TransactionId cachedTestXid;
extern XidStatus cachedTestXidStatus;
extern TransactionId NullTransactionId;
extern TransactionId AmiTransactionId;
extern TransactionId FirstTransactionId;
extern int RecoveryCheckingEnableState;
/* in transsup.c */
/* in xact.c */
extern bool AMI_OVERRIDE;
/* in varsup.c */
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: xact.h,v 1.33 2001/03/22 04:00:32 momjian Exp $
* $Id: xact.h,v 1.34 2001/07/12 04:11:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -67,17 +67,6 @@ typedef TransactionStateData *TransactionState;
#define TBLOCK_ABORT 4
#define TBLOCK_ENDABORT 5
/* ----------------
* transaction ID manipulation macros
* ----------------
*/
#define TransactionIdIsValid(xid) ((bool) ((xid) != NullTransactionId))
#define TransactionIdEquals(id1, id2) ((bool) ((id1) == (id2)))
#define TransactionIdStore(xid, dest) \
(*((TransactionId*) (dest)) = (TransactionId) (xid))
#define StoreInvalidTransactionId(dest) \
(*((TransactionId*) (dest)) = NullTransactionId)
/*
* XLOG allows to store some information in high 4 bits of log
* record xl_info field
......@@ -133,8 +122,6 @@ extern void AbortOutOfAnyTransaction(void);
extern void RecordTransactionCommit(void);
extern TransactionId DisabledTransactionId;
extern void XactPushRollback(void (*func) (void *), void *data);
extern void XactPopRollback(void);
......@@ -146,6 +133,5 @@ extern void xact_desc(char *buf, uint8 xl_info, char *rec);
extern Datum xidin(PG_FUNCTION_ARGS);
extern Datum xidout(PG_FUNCTION_ARGS);
extern Datum xideq(PG_FUNCTION_ARGS);
extern void TransactionIdAdd(TransactionId *xid, int value);
#endif /* XACT_H */
......@@ -7,23 +7,43 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: vacuum.h,v 1.36 2001/06/27 23:31:39 tgl Exp $
* $Id: vacuum.h,v 1.37 2001/07/12 04:11:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef VACUUM_H
#define VACUUM_H
#include <time.h>
#include <sys/time.h>
#ifdef HAVE_GETRUSAGE
#include <sys/resource.h>
#else
#include "rusagestub.h"
#endif
#include "nodes/parsenodes.h"
#include "storage/block.h"
/* State structure for vac_init_rusage/vac_show_rusage */
typedef struct VacRUsage
{
struct timeval tv;
struct rusage ru;
} VacRUsage;
/* in commands/vacuum.c */
extern void vacuum(VacuumStmt *vacstmt);
extern void vac_update_relstats(Oid relid,
BlockNumber num_pages,
double num_tuples,
bool hasindex);
extern void vac_init_rusage(VacRUsage *ru0);
extern const char *vac_show_rusage(VacRUsage *ru0);
/* in commands/analyze.c */
extern void analyze_rel(Oid relid, VacuumStmt *vacstmt);
......
......@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: tqual.h,v 1.31 2001/06/18 21:38:02 momjian Exp $
* $Id: tqual.h,v 1.32 2001/07/12 04:11:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -23,8 +23,9 @@ typedef struct SnapshotData
{
TransactionId xmin; /* XID < xmin are visible to me */
TransactionId xmax; /* XID >= xmax are invisible to me */
uint32 xcnt; /* # of xact below */
TransactionId *xip; /* array of xacts in progress */
uint32 xcnt; /* # of xact ids in xip[] */
TransactionId *xip; /* array of xact IDs in progress */
/* note: all ids in xip[] satisfy xmin <= xip[i] < xmax */
ItemPointerData tid; /* required for Dirty snapshot -:( */
} SnapshotData;
......@@ -34,8 +35,8 @@ typedef SnapshotData *Snapshot;
#define SnapshotSelf ((Snapshot) 0x1)
#define SnapshotAny ((Snapshot) 0x2)
extern Snapshot SnapshotDirty;
extern Snapshot QuerySnapshot;
extern DLLIMPORT Snapshot SnapshotDirty;
extern DLLIMPORT Snapshot QuerySnapshot;
extern DLLIMPORT Snapshot SerializableSnapshot;
extern bool ReferentialIntegritySnapshotOverride;
......@@ -66,11 +67,11 @@ extern bool ReferentialIntegritySnapshotOverride;
(IsSnapshotSelf(snapshot) ? \
HeapTupleSatisfiesItself((tuple)->t_data) \
: \
(IsSnapshotDirty(snapshot) ? \
HeapTupleSatisfiesDirty((tuple)->t_data) \
(IsSnapshotNow(snapshot) ? \
HeapTupleSatisfiesNow((tuple)->t_data) \
: \
(IsSnapshotNow(snapshot) ? \
HeapTupleSatisfiesNow((tuple)->t_data) \
(IsSnapshotDirty(snapshot) ? \
HeapTupleSatisfiesDirty((tuple)->t_data) \
: \
HeapTupleSatisfiesSnapshot((tuple)->t_data, snapshot) \
) \
......@@ -79,18 +80,31 @@ extern bool ReferentialIntegritySnapshotOverride;
) \
)
/* Result codes for HeapTupleSatisfiesUpdate */
#define HeapTupleMayBeUpdated 0
#define HeapTupleInvisible 1
#define HeapTupleSelfUpdated 2
#define HeapTupleUpdated 3
#define HeapTupleBeingUpdated 4
/* Result codes for HeapTupleSatisfiesVacuum */
typedef enum
{
HEAPTUPLE_DEAD, /* tuple is dead and deletable */
HEAPTUPLE_LIVE, /* tuple is live (committed, no deleter) */
HEAPTUPLE_RECENTLY_DEAD, /* tuple is dead, but not deletable yet */
HEAPTUPLE_INSERT_IN_PROGRESS, /* inserting xact is still in progress */
HEAPTUPLE_DELETE_IN_PROGRESS /* deleting xact is still in progress */
} HTSV_Result;
extern bool HeapTupleSatisfiesItself(HeapTupleHeader tuple);
extern bool HeapTupleSatisfiesNow(HeapTupleHeader tuple);
extern bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple);
extern bool HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple,
Snapshot snapshot);
extern int HeapTupleSatisfiesUpdate(HeapTuple tuple);
extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
TransactionId XmaxRecent);
extern Snapshot GetSnapshotData(bool serializable);
extern void SetQuerySnapshot(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment