predicate.h-before
application/octet-stream
Filename: predicate.h-before
Type: application/octet-stream
Part: 0
Message:
Re: git diff --patience
/*-------------------------------------------------------------------------
*
* predicate.h
* POSTGRES predicate locking definitions.
*
*
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL$
*
*-------------------------------------------------------------------------
*/
#ifndef PREDICATE_H
#define PREDICATE_H
#include "access/htup.h"
#include "storage/lock.h"
#include "utils/relcache.h"
#include "utils/snapshot.h"
/* GUC variables */
extern int max_predicate_locks_per_xact;
/*
* The SERIALIZABLEXACTTAG struct identifies a serializable transaction.
*/
typedef struct SERIALIZABLEXACTTAG
{
VirtualTransactionId vxid; /* We always have one of these. */
} SERIALIZABLEXACTTAG;
/*
* Information needed for each serializable database transaction to support SSI techniques.
* TODO SSI: Should inConflict and outConflict be lists? That would allow us to reduce
* false positives, *and* would allow us to guarantee that an immediate retry
* of a transaction would never fail on the exact same conflicts.
* The RAM doesn't look like it would be the limiting factor, but CPU time might
* be -- we should have baseline benchmarks before attempting this.
*/
typedef struct SERIALIZABLEXACT
{
/* hash key */
SERIALIZABLEXACTTAG tag;
/* data */
struct SERIALIZABLEXACT *outConflict; /* ptr to write transaction
* whose data we couldn't
* read. invalid means no
* conflict; self-reference
* means multiple or
* committed. */
struct SERIALIZABLEXACT *inConflict; /* ptr to read transaction
* which couldn't see our
* write. invalid means no
* conflict; self-reference
* means multiple or
* committed. */
TransactionId topXid; /* top level xid for the transaction, if one
* exists */
TransactionId finishedBefore; /* invalid means still running; else
* the struct expires when no tags <
* this. */
TransactionId xmin; /* the transaction's snapshot xmin */
SHM_QUEUE predicateLocks; /* list of associated PREDICATELOCK objects */
SHM_QUEUE xids; /* list of associated SERIALIZABLEXID objects */
SHM_QUEUE finishedLink; /* list link in
* FinishedSerializableTransactions */
bool rolledBack; /* ignore conflicts when true; allows deferred
* cleanup */
} SERIALIZABLEXACT;
typedef enum PredicateLockTargetType
{
PREDLOCKTAG_RELATION,
PREDLOCKTAG_PAGE,
PREDLOCKTAG_TUPLE
/* TODO Other types may be needed for index locking */
} PredicateLockTargetType;
/*
* The PREDICATELOCKTARGETTAG struct is defined to fit into 16
* bytes with no padding. Note that this would need adjustment if we were
* to widen Oid or BlockNumber to more than 32 bits.
*/
typedef struct PREDICATELOCKTARGETTAG
{
uint32 locktag_field1; /* a 32-bit ID field */
uint32 locktag_field2; /* a 32-bit ID field */
uint32 locktag_field3; /* a 32-bit ID field */
uint16 locktag_field4; /* a 16-bit ID field */
uint16 locktag_field5; /* a 16-bit ID field */
} PREDICATELOCKTARGETTAG;
/*
* These macros define how we map logical IDs of lockable objects into
* the physical fields of PREDICATELOCKTARGETTAG. Use these to set up values,
* rather than accessing the fields directly. Note multiple eval of target!
*
* TODO SSI: If we always use the same fields for the same type of value,
* we should rename these. Holding off until it's clear there are no exceptions.
* Since indexes are relations with blocks and tuples, it's looking likely that
* the rename will be possible. If not, we may need to divide the last field
* and use part of it for a target type, so that we know how to interpret the
* data..
*/
#define SET_PREDICATELOCKTARGETTAG_RELATION(locktag,dboid,reloid) \
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = InvalidBlockNumber, \
(locktag).locktag_field4 = InvalidOffsetNumber, \
(locktag).locktag_field5 = 0)
#define SET_PREDICATELOCKTARGETTAG_PAGE(locktag,dboid,reloid,blocknum) \
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = (blocknum), \
(locktag).locktag_field4 = InvalidOffsetNumber, \
(locktag).locktag_field5 = 0)
#define SET_PREDICATELOCKTARGETTAG_TUPLE(locktag,dboid,reloid,blocknum,offnum) \
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = (blocknum), \
(locktag).locktag_field4 = (offnum), \
(locktag).locktag_field5 = 0)
#define GET_PREDICATELOCKTARGETTAG_DB(locktag) \
((locktag).locktag_field1)
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag) \
((locktag).locktag_field2)
#define GET_PREDICATELOCKTARGETTAG_PAGE(locktag) \
((locktag).locktag_field3)
#define GET_PREDICATELOCKTARGETTAG_OFFSET(locktag) \
((locktag).locktag_field4)
#define GET_PREDICATELOCKTARGETTAG_TYPE(locktag) \
(((locktag).locktag_field4 != InvalidOffsetNumber) ? PREDLOCKTAG_TUPLE : \
(((locktag).locktag_field3 != InvalidBlockNumber) ? PREDLOCKTAG_PAGE : \
PREDLOCKTAG_RELATION))
typedef struct PredicateLockData
{
int nelements;
PREDICATELOCKTARGETTAG *locktags;
SERIALIZABLEXACT *xacts;
} PredicateLockData;
/*
* function prototypes
*/
/* housekeeping for shared memory predicate lock structures */
extern void InitPredicateLocks(void);
extern Size PredicateLockShmemSize(void);
/* predicate lock reporting */
extern PredicateLockData *GetPredicateLockStatusData(void);
extern bool PageIsPredicateLocked(const Relation relation, const BlockNumber blkno);
/* predicate lock maintenance */
extern void RegisterSerializableTransaction(const Snapshot snapshot);
extern void PredicateLockRelation(const Relation relation);
extern void PredicateLockPage(const Relation relation, const BlockNumber blkno);
extern void PredicateLockTuple(const Relation relation, const HeapTuple tuple);
extern void PredicateLockPageSplit(const Relation relation, const BlockNumber oldblkno, const BlockNumber newblkno);
extern void PredicateLockPageCombine(const Relation relation, const BlockNumber oldblkno, const BlockNumber newblkno);
extern void ReleasePredicateLocks(const bool isCommit);
/* conflict detection (may also trigger rollback) */
extern void CheckForSerializableConflictOut(const bool valid, const Relation relation, const HeapTuple tuple, const Buffer buffer);
extern void CheckForSerializableConflictIn(const Relation relation, const HeapTuple tuple, const Buffer buffer);
/* final rollback checking */
extern void PreCommit_CheckForSerializationFailure(void);
#endif /* PREDICATE_H */