Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Defines | Typedefs | Functions

txid.c File Reference

#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"
Include dependency graph for txid.c:

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 TxidSnapshotbuf_finalize (StringInfo buf)
static txid str2txid (const char *s, const char **endp)
static TxidSnapshotparse_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 Documentation

#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().


Typedef Documentation

typedef uint64 txid

Definition at line 37 of file txid.c.


Function Documentation

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().

{
    txid        a = *(const txid *) aa;
    txid        b = *(const txid *) bb;

    if (a < b)
        return -1;
    if (a > b)
        return 1;
    return 0;
}

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().

{
    if (snap->nxip > 1)
        qsort(snap->xip, snap->nxip, sizeof(txid), cmp_txid);
}

static txid str2txid ( const char *  s,
const char **  endp 
) [static]

Definition at line 225 of file txid.c.

References MAX_TXID, and val.

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   ) 
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   ) 
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.

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.

Datum txid_visible_in_snapshot ( PG_FUNCTION_ARGS   )