#include "postgres.h"#include "access/transam.h"#include "access/xact.h"#include "funcapi.h"#include "miscadmin.h"#include "libpq/pqformat.h"#include "utils/builtins.h"#include "utils/snapmgr.h"
Go to the source code of this file.
Data Structures | |
| struct | TxidSnapshot |
| struct | TxidEpoch |
Defines | |
| #define | MAX_TXID UINT64CONST(0x7FFFFFFFFFFFFFFF) |
| #define | TXID_FMT UINT64_FORMAT |
| #define | USE_BSEARCH_IF_NXIP_GREATER 30 |
| #define | TXID_SNAPSHOT_SIZE(nxip) (offsetof(TxidSnapshot, xip) + sizeof(txid) * (nxip)) |
Typedefs | |
| typedef uint64 | txid |
Functions | |
| static void | load_xid_epoch (TxidEpoch *state) |
| static txid | convert_xid (TransactionId xid, const TxidEpoch *state) |
| static int | cmp_txid (const void *aa, const void *bb) |
| static void | sort_snapshot (TxidSnapshot *snap) |
| static bool | is_visible_txid (txid value, const TxidSnapshot *snap) |
| static StringInfo | buf_init (txid xmin, txid xmax) |
| static void | buf_add_txid (StringInfo buf, txid xid) |
| static TxidSnapshot * | buf_finalize (StringInfo buf) |
| static txid | str2txid (const char *s, const char **endp) |
| static TxidSnapshot * | parse_snapshot (const char *str) |
| Datum | txid_current (PG_FUNCTION_ARGS) |
| Datum | txid_current_snapshot (PG_FUNCTION_ARGS) |
| Datum | txid_snapshot_in (PG_FUNCTION_ARGS) |
| Datum | txid_snapshot_out (PG_FUNCTION_ARGS) |
| Datum | txid_snapshot_recv (PG_FUNCTION_ARGS) |
| Datum | txid_snapshot_send (PG_FUNCTION_ARGS) |
| Datum | txid_visible_in_snapshot (PG_FUNCTION_ARGS) |
| Datum | txid_snapshot_xmin (PG_FUNCTION_ARGS) |
| Datum | txid_snapshot_xmax (PG_FUNCTION_ARGS) |
| Datum | txid_snapshot_xip (PG_FUNCTION_ARGS) |
| #define MAX_TXID UINT64CONST(0x7FFFFFFFFFFFFFFF) |
Definition at line 34 of file txid.c.
Referenced by str2txid(), and txid_snapshot_recv().
| #define TXID_FMT UINT64_FORMAT |
Definition at line 40 of file txid.c.
Referenced by txid_snapshot_out().
| #define TXID_SNAPSHOT_SIZE | ( | nxip | ) | (offsetof(TxidSnapshot, xip) + sizeof(txid) * (nxip)) |
Definition at line 67 of file txid.c.
Referenced by buf_init(), txid_current_snapshot(), and txid_snapshot_recv().
| #define USE_BSEARCH_IF_NXIP_GREATER 30 |
Definition at line 46 of file txid.c.
Referenced by is_visible_txid().
| static void buf_add_txid | ( | StringInfo | buf, | |
| txid | xid | |||
| ) | [static] |
Definition at line 195 of file txid.c.
References appendBinaryStringInfo(), StringInfoData::data, and TxidSnapshot::nxip.
Referenced by parse_snapshot().
{
TxidSnapshot *snap = (TxidSnapshot *) buf->data;
/* do this before possible realloc */
snap->nxip++;
appendBinaryStringInfo(buf, (char *) &xid, sizeof(xid));
}
| static TxidSnapshot* buf_finalize | ( | StringInfo | buf | ) | [static] |
Definition at line 206 of file txid.c.
References StringInfoData::data, StringInfoData::len, pfree(), and SET_VARSIZE.
Referenced by parse_snapshot().
{
TxidSnapshot *snap = (TxidSnapshot *) buf->data;
SET_VARSIZE(snap, buf->len);
/* buf is not needed anymore */
buf->data = NULL;
pfree(buf);
return snap;
}
| static StringInfo buf_init | ( | txid | xmin, | |
| txid | xmax | |||
| ) | [static] |
Definition at line 180 of file txid.c.
References appendBinaryStringInfo(), buf, makeStringInfo(), TxidSnapshot::nxip, TXID_SNAPSHOT_SIZE, TxidSnapshot::xmax, and TxidSnapshot::xmin.
Referenced by parse_snapshot().
{
TxidSnapshot snap;
StringInfo buf;
snap.xmin = xmin;
snap.xmax = xmax;
snap.nxip = 0;
buf = makeStringInfo();
appendBinaryStringInfo(buf, (char *) &snap, TXID_SNAPSHOT_SIZE(0));
return buf;
}
| static int cmp_txid | ( | const void * | aa, | |
| const void * | bb | |||
| ) | [static] |
Definition at line 117 of file txid.c.
Referenced by is_visible_txid(), and sort_snapshot().
| static txid convert_xid | ( | TransactionId | xid, | |
| const TxidEpoch * | state | |||
| ) | [static] |
Definition at line 93 of file txid.c.
References TxidEpoch::epoch, epoch, TxidEpoch::last_xid, TransactionIdFollows(), TransactionIdIsNormal, and TransactionIdPrecedes().
Referenced by txid_current(), and txid_current_snapshot().
{
uint64 epoch;
/* return special xid's as-is */
if (!TransactionIdIsNormal(xid))
return (txid) xid;
/* xid can be on either side when near wrap-around */
epoch = (uint64) state->epoch;
if (xid > state->last_xid &&
TransactionIdPrecedes(xid, state->last_xid))
epoch--;
else if (xid < state->last_xid &&
TransactionIdFollows(xid, state->last_xid))
epoch++;
return (epoch << 32) | xid;
}
| static bool is_visible_txid | ( | txid | value, | |
| const TxidSnapshot * | snap | |||
| ) | [static] |
Definition at line 146 of file txid.c.
References cmp_txid(), i, TxidSnapshot::nxip, USE_BSEARCH_IF_NXIP_GREATER, TxidSnapshot::xip, and TxidSnapshot::xmax.
Referenced by txid_visible_in_snapshot().
{
if (value < snap->xmin)
return true;
else if (value >= snap->xmax)
return false;
#ifdef USE_BSEARCH_IF_NXIP_GREATER
else if (snap->nxip > USE_BSEARCH_IF_NXIP_GREATER)
{
void *res;
res = bsearch(&value, snap->xip, snap->nxip, sizeof(txid), cmp_txid);
/* if found, transaction is still in progress */
return (res) ? false : true;
}
#endif
else
{
uint32 i;
for (i = 0; i < snap->nxip; i++)
{
if (value == snap->xip[i])
return false;
}
return true;
}
}
| static void load_xid_epoch | ( | TxidEpoch * | state | ) | [static] |
Definition at line 84 of file txid.c.
References TxidEpoch::epoch, GetNextXidAndEpoch(), and TxidEpoch::last_xid.
Referenced by txid_current(), and txid_current_snapshot().
{
GetNextXidAndEpoch(&state->last_xid, &state->epoch);
}
| static TxidSnapshot* parse_snapshot | ( | const char * | str | ) | [static] |
Definition at line 259 of file txid.c.
References buf, buf_add_txid(), buf_finalize(), buf_init(), elog, ERROR, str2txid(), and val.
Referenced by txid_snapshot_in().
{
txid xmin;
txid xmax;
txid last_val = 0,
val;
const char *str_start = str;
const char *endp;
StringInfo buf;
xmin = str2txid(str, &endp);
if (*endp != ':')
goto bad_format;
str = endp + 1;
xmax = str2txid(str, &endp);
if (*endp != ':')
goto bad_format;
str = endp + 1;
/* it should look sane */
if (xmin == 0 || xmax == 0 || xmin > xmax)
goto bad_format;
/* allocate buffer */
buf = buf_init(xmin, xmax);
/* loop over values */
while (*str != '\0')
{
/* read next value */
val = str2txid(str, &endp);
str = endp;
/* require the input to be in order */
if (val < xmin || val >= xmax || val <= last_val)
goto bad_format;
buf_add_txid(buf, val);
last_val = val;
if (*str == ',')
str++;
else if (*str != '\0')
goto bad_format;
}
return buf_finalize(buf);
bad_format:
elog(ERROR, "invalid input for txid_snapshot: \"%s\"", str_start);
return NULL;
}
| static void sort_snapshot | ( | TxidSnapshot * | snap | ) | [static] |
Definition at line 136 of file txid.c.
References cmp_txid(), TxidSnapshot::nxip, qsort, and TxidSnapshot::xip.
Referenced by txid_current_snapshot().
| static txid str2txid | ( | const char * | s, | |
| const char ** | endp | |||
| ) | [static] |
Definition at line 225 of file txid.c.
Referenced by parse_snapshot().
{
txid val = 0;
txid cutoff = MAX_TXID / 10;
txid cutlim = MAX_TXID % 10;
for (; *s; s++)
{
unsigned d;
if (*s < '0' || *s > '9')
break;
d = *s - '0';
/*
* check for overflow
*/
if (val > cutoff || (val == cutoff && d > cutlim))
{
val = 0;
break;
}
val = val * 10 + d;
}
if (endp)
*endp = s;
return val;
}
| Datum txid_current | ( | PG_FUNCTION_ARGS | ) |
Definition at line 328 of file txid.c.
References convert_xid(), GetTopTransactionId(), load_xid_epoch(), PG_RETURN_INT64, PreventCommandDuringRecovery(), and val.
{
txid val;
TxidEpoch state;
/*
* Must prevent during recovery because if an xid is not assigned we try
* to assign one, which would fail. Programs already rely on this function
* to always return a valid current xid, so we should not change this to
* return NULL or similar invalid xid.
*/
PreventCommandDuringRecovery("txid_current()");
load_xid_epoch(&state);
val = convert_xid(GetTopTransactionId(), &state);
PG_RETURN_INT64(val);
}
| Datum txid_current_snapshot | ( | PG_FUNCTION_ARGS | ) |
Definition at line 356 of file txid.c.
References convert_xid(), cur, elog, ERROR, GetActiveSnapshot(), i, load_xid_epoch(), NULL, TxidSnapshot::nxip, palloc(), PG_RETURN_POINTER, SET_VARSIZE, sort_snapshot(), TXID_SNAPSHOT_SIZE, SnapshotData::xcnt, SnapshotData::xip, TxidSnapshot::xip, SnapshotData::xmax, TxidSnapshot::xmax, SnapshotData::xmin, and TxidSnapshot::xmin.
{
TxidSnapshot *snap;
uint32 nxip,
i,
size;
TxidEpoch state;
Snapshot cur;
cur = GetActiveSnapshot();
if (cur == NULL)
elog(ERROR, "no active snapshot set");
load_xid_epoch(&state);
/* allocate */
nxip = cur->xcnt;
size = TXID_SNAPSHOT_SIZE(nxip);
snap = palloc(size);
SET_VARSIZE(snap, size);
/* fill */
snap->xmin = convert_xid(cur->xmin, &state);
snap->xmax = convert_xid(cur->xmax, &state);
snap->nxip = nxip;
for (i = 0; i < nxip; i++)
snap->xip[i] = convert_xid(cur->xip[i], &state);
/* we want them guaranteed to be in ascending order */
sort_snapshot(snap);
PG_RETURN_POINTER(snap);
}
| Datum txid_snapshot_in | ( | PG_FUNCTION_ARGS | ) |
Definition at line 396 of file txid.c.
References parse_snapshot(), PG_GETARG_CSTRING, and PG_RETURN_POINTER.
{
char *str = PG_GETARG_CSTRING(0);
TxidSnapshot *snap;
snap = parse_snapshot(str);
PG_RETURN_POINTER(snap);
}
| Datum txid_snapshot_out | ( | PG_FUNCTION_ARGS | ) |
Definition at line 412 of file txid.c.
References appendStringInfo(), appendStringInfoChar(), StringInfoData::data, i, initStringInfo(), TxidSnapshot::nxip, PG_GETARG_VARLENA_P, PG_RETURN_CSTRING, TXID_FMT, TxidSnapshot::xip, TxidSnapshot::xmax, and TxidSnapshot::xmin.
{
TxidSnapshot *snap = (TxidSnapshot *) PG_GETARG_VARLENA_P(0);
StringInfoData str;
uint32 i;
initStringInfo(&str);
appendStringInfo(&str, TXID_FMT ":", snap->xmin);
appendStringInfo(&str, TXID_FMT ":", snap->xmax);
for (i = 0; i < snap->nxip; i++)
{
if (i > 0)
appendStringInfoChar(&str, ',');
appendStringInfo(&str, TXID_FMT, snap->xip[i]);
}
PG_RETURN_CSTRING(str.data);
}
| Datum txid_snapshot_recv | ( | PG_FUNCTION_ARGS | ) |
Definition at line 441 of file txid.c.
References buf, cur, StringInfoData::cursor, elog, ERROR, i, StringInfoData::len, MAX_TXID, TxidSnapshot::nxip, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, pq_getmsgint(), pq_getmsgint64(), SET_VARSIZE, TXID_SNAPSHOT_SIZE, TxidSnapshot::xip, TxidSnapshot::xmax, and TxidSnapshot::xmin.
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
TxidSnapshot *snap;
txid last = 0;
int nxip;
int i;
int avail;
int expect;
txid xmin,
xmax;
/*
* load nxip and check for nonsense.
*
* (nxip > avail) check is against int overflows in 'expect'.
*/
nxip = pq_getmsgint(buf, 4);
avail = buf->len - buf->cursor;
expect = 8 + 8 + nxip * 8;
if (nxip < 0 || nxip > avail || expect > avail)
goto bad_format;
xmin = pq_getmsgint64(buf);
xmax = pq_getmsgint64(buf);
if (xmin == 0 || xmax == 0 || xmin > xmax || xmax > MAX_TXID)
goto bad_format;
snap = palloc(TXID_SNAPSHOT_SIZE(nxip));
snap->xmin = xmin;
snap->xmax = xmax;
snap->nxip = nxip;
SET_VARSIZE(snap, TXID_SNAPSHOT_SIZE(nxip));
for (i = 0; i < nxip; i++)
{
txid cur = pq_getmsgint64(buf);
if (cur <= last || cur < xmin || cur >= xmax)
goto bad_format;
snap->xip[i] = cur;
last = cur;
}
PG_RETURN_POINTER(snap);
bad_format:
elog(ERROR, "invalid snapshot data");
return (Datum) NULL;
}
| Datum txid_snapshot_send | ( | PG_FUNCTION_ARGS | ) |
Definition at line 499 of file txid.c.
References buf, i, TxidSnapshot::nxip, PG_GETARG_VARLENA_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendint(), pq_sendint64(), TxidSnapshot::xip, TxidSnapshot::xmax, and TxidSnapshot::xmin.
{
TxidSnapshot *snap = (TxidSnapshot *) PG_GETARG_VARLENA_P(0);
StringInfoData buf;
uint32 i;
pq_begintypsend(&buf);
pq_sendint(&buf, snap->nxip, 4);
pq_sendint64(&buf, snap->xmin);
pq_sendint64(&buf, snap->xmax);
for (i = 0; i < snap->nxip; i++)
pq_sendint64(&buf, snap->xip[i]);
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
| Datum txid_snapshot_xip | ( | PG_FUNCTION_ARGS | ) |
Definition at line 560 of file txid.c.
References arg, FuncCallContext::call_cntr, Int64GetDatum(), MemoryContextAlloc(), FuncCallContext::multi_call_memory_ctx, TxidSnapshot::nxip, PG_GETARG_VARLENA_P, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, FuncCallContext::user_fctx, value, VARSIZE, and TxidSnapshot::xip.
{
FuncCallContext *fctx;
TxidSnapshot *snap;
txid value;
/* on first call initialize snap_state and get copy of snapshot */
if (SRF_IS_FIRSTCALL())
{
TxidSnapshot *arg = (TxidSnapshot *) PG_GETARG_VARLENA_P(0);
fctx = SRF_FIRSTCALL_INIT();
/* make a copy of user snapshot */
snap = MemoryContextAlloc(fctx->multi_call_memory_ctx, VARSIZE(arg));
memcpy(snap, arg, VARSIZE(arg));
fctx->user_fctx = snap;
}
/* return values one-by-one */
fctx = SRF_PERCALL_SETUP();
snap = fctx->user_fctx;
if (fctx->call_cntr < snap->nxip)
{
value = snap->xip[fctx->call_cntr];
SRF_RETURN_NEXT(fctx, Int64GetDatum(value));
}
else
{
SRF_RETURN_DONE(fctx);
}
}
| Datum txid_snapshot_xmax | ( | PG_FUNCTION_ARGS | ) |
Definition at line 547 of file txid.c.
References PG_GETARG_VARLENA_P, PG_RETURN_INT64, and TxidSnapshot::xmax.
{
TxidSnapshot *snap = (TxidSnapshot *) PG_GETARG_VARLENA_P(0);
PG_RETURN_INT64(snap->xmax);
}
| Datum txid_snapshot_xmin | ( | PG_FUNCTION_ARGS | ) |
Definition at line 534 of file txid.c.
References PG_GETARG_VARLENA_P, PG_RETURN_INT64, and TxidSnapshot::xmin.
{
TxidSnapshot *snap = (TxidSnapshot *) PG_GETARG_VARLENA_P(0);
PG_RETURN_INT64(snap->xmin);
}
| Datum txid_visible_in_snapshot | ( | PG_FUNCTION_ARGS | ) |
Definition at line 520 of file txid.c.
References is_visible_txid(), PG_GETARG_INT64, PG_GETARG_VARLENA_P, PG_RETURN_BOOL, and value.
{
txid value = PG_GETARG_INT64(0);
TxidSnapshot *snap = (TxidSnapshot *) PG_GETARG_VARLENA_P(1);
PG_RETURN_BOOL(is_visible_txid(value, snap));
}
1.7.1