PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
snapbuild.h File Reference
#include "access/xlogdefs.h"
#include "utils/snapmgr.h"
Include dependency graph for snapbuild.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef struct SnapBuild SnapBuild
 

Enumerations

enum  SnapBuildState { SNAPBUILD_START, SNAPBUILD_FULL_SNAPSHOT, SNAPBUILD_CONSISTENT }
 

Functions

void CheckPointSnapBuild (void)
 
SnapBuildAllocateSnapshotBuilder (struct ReorderBuffer *cache, TransactionId xmin_horizon, XLogRecPtr start_lsn)
 
void FreeSnapshotBuilder (SnapBuild *cache)
 
void SnapBuildSnapDecRefcount (Snapshot snap)
 
Snapshot SnapBuildInitalSnapshot (SnapBuild *builder)
 
const char * SnapBuildExportSnapshot (SnapBuild *snapstate)
 
void SnapBuildClearExportedSnapshot (void)
 
SnapBuildState SnapBuildCurrentState (SnapBuild *snapstate)
 
Snapshot SnapBuildGetOrBuildSnapshot (SnapBuild *builder, TransactionId xid)
 
bool SnapBuildXactNeedsSkip (SnapBuild *snapstate, XLogRecPtr ptr)
 
void SnapBuildCommitTxn (SnapBuild *builder, XLogRecPtr lsn, TransactionId xid, int nsubxacts, TransactionId *subxacts)
 
void SnapBuildAbortTxn (SnapBuild *builder, XLogRecPtr lsn, TransactionId xid, int nsubxacts, TransactionId *subxacts)
 
bool SnapBuildProcessChange (SnapBuild *builder, TransactionId xid, XLogRecPtr lsn)
 
void SnapBuildProcessNewCid (SnapBuild *builder, TransactionId xid, XLogRecPtr lsn, struct xl_heap_new_cid *cid)
 
void SnapBuildProcessRunningXacts (SnapBuild *builder, XLogRecPtr lsn, struct xl_running_xacts *running)
 
void SnapBuildSerializationPoint (SnapBuild *builder, XLogRecPtr lsn)
 

Typedef Documentation

Definition at line 45 of file snapbuild.h.

Enumeration Type Documentation

Enumerator
SNAPBUILD_START 
SNAPBUILD_FULL_SNAPSHOT 
SNAPBUILD_CONSISTENT 

Definition at line 18 of file snapbuild.h.

19 {
20  /*
21  * Initial state, we can't do much yet.
22  */
24 
25  /*
26  * We have collected enough information to decode tuples in transactions
27  * that started after this.
28  *
29  * Once we reached this we start to collect changes. We cannot apply them
30  * yet because the might be based on transactions that were still running
31  * when we reached them yet.
32  */
34 
35  /*
36  * Found a point after hitting built_full_snapshot where all transactions
37  * that were running at that point finished. Till we reach that we hold
38  * off calling any commit callbacks.
39  */
SnapBuildState
Definition: snapbuild.h:18

Function Documentation

SnapBuild* AllocateSnapshotBuilder ( struct ReorderBuffer cache,
TransactionId  xmin_horizon,
XLogRecPtr  start_lsn 
)

Definition at line 282 of file snapbuild.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), SnapBuild::committed, SnapBuild::context, CurrentMemoryContext, SnapBuild::includes_all_transactions, SnapBuild::initial_xmin_horizon, MemoryContextSwitchTo(), palloc0(), SnapBuild::reorder, SNAPBUILD_START, SnapBuild::start_decoding_at, SnapBuild::state, SnapBuild::xcnt, SnapBuild::xcnt_space, and SnapBuild::xip.

Referenced by StartupDecodingContext().

285 {
286  MemoryContext context;
287  MemoryContext oldcontext;
288  SnapBuild *builder;
289 
290  /* allocate memory in own context, to have better accountability */
292  "snapshot builder context",
294  oldcontext = MemoryContextSwitchTo(context);
295 
296  builder = palloc0(sizeof(SnapBuild));
297 
298  builder->state = SNAPBUILD_START;
299  builder->context = context;
300  builder->reorder = reorder;
301  /* Other struct members initialized by zeroing via palloc0 above */
302 
303  builder->committed.xcnt = 0;
304  builder->committed.xcnt_space = 128; /* arbitrary number */
305  builder->committed.xip =
306  palloc0(builder->committed.xcnt_space * sizeof(TransactionId));
307  builder->committed.includes_all_transactions = true;
308 
309  builder->initial_xmin_horizon = xmin_horizon;
310  builder->start_decoding_at = start_lsn;
311 
312  MemoryContextSwitchTo(oldcontext);
313 
314  return builder;
315 }
uint32 TransactionId
Definition: c.h:397
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
size_t xcnt_space
Definition: snapbuild.c:201
size_t xcnt
Definition: snapbuild.c:200
SnapBuildState state
Definition: snapbuild.c:145
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
ReorderBuffer * reorder
Definition: snapbuild.c:181
TransactionId initial_xmin_horizon
Definition: snapbuild.c:166
TransactionId * xip
Definition: snapbuild.c:202
bool includes_all_transactions
Definition: snapbuild.c:222
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:878
MemoryContext context
Definition: snapbuild.c:148
struct SnapBuild::@23 committed
XLogRecPtr start_decoding_at
Definition: snapbuild.c:160
void CheckPointSnapBuild ( void  )

Definition at line 1865 of file snapbuild.c.

References AllocateDir(), dirent::d_name, DEBUG1, elog, ereport, errcode_for_file_access(), errmsg(), FreeDir(), GetRedoRecPtr(), InvalidXLogRecPtr, LOG, lstat, MAXPGPATH, NULL, ReadDir(), ReplicationSlotsComputeLogicalRestartLSN(), snprintf(), and unlink().

Referenced by CheckPointGuts().

1866 {
1867  XLogRecPtr cutoff;
1868  XLogRecPtr redo;
1869  DIR *snap_dir;
1870  struct dirent *snap_de;
1871  char path[MAXPGPATH];
1872 
1873  /*
1874  * We start off with a minimum of the last redo pointer. No new replication
1875  * slot will start before that, so that's a safe upper bound for removal.
1876  */
1877  redo = GetRedoRecPtr();
1878 
1879  /* now check for the restart ptrs from existing slots */
1881 
1882  /* don't start earlier than the restart lsn */
1883  if (redo < cutoff)
1884  cutoff = redo;
1885 
1886  snap_dir = AllocateDir("pg_logical/snapshots");
1887  while ((snap_de = ReadDir(snap_dir, "pg_logical/snapshots")) != NULL)
1888  {
1889  uint32 hi;
1890  uint32 lo;
1891  XLogRecPtr lsn;
1892  struct stat statbuf;
1893 
1894  if (strcmp(snap_de->d_name, ".") == 0 ||
1895  strcmp(snap_de->d_name, "..") == 0)
1896  continue;
1897 
1898  snprintf(path, MAXPGPATH, "pg_logical/snapshots/%s", snap_de->d_name);
1899 
1900  if (lstat(path, &statbuf) == 0 && !S_ISREG(statbuf.st_mode))
1901  {
1902  elog(DEBUG1, "only regular files expected: %s", path);
1903  continue;
1904  }
1905 
1906  /*
1907  * temporary filenames from SnapBuildSerialize() include the LSN and
1908  * everything but are postfixed by .$pid.tmp. We can just remove them
1909  * the same as other files because there can be none that are
1910  * currently being written that are older than cutoff.
1911  *
1912  * We just log a message if a file doesn't fit the pattern, it's
1913  * probably some editors lock/state file or similar...
1914  */
1915  if (sscanf(snap_de->d_name, "%X-%X.snap", &hi, &lo) != 2)
1916  {
1917  ereport(LOG,
1918  (errmsg("could not parse file name \"%s\"", path)));
1919  continue;
1920  }
1921 
1922  lsn = ((uint64) hi) << 32 | lo;
1923 
1924  /* check whether we still need it */
1925  if (lsn < cutoff || cutoff == InvalidXLogRecPtr)
1926  {
1927  elog(DEBUG1, "removing snapbuild snapshot %s", path);
1928 
1929  /*
1930  * It's not particularly harmful, though strange, if we can't
1931  * remove the file here. Don't prevent the checkpoint from
1932  * completing, that'd be a cure worse than the disease.
1933  */
1934  if (unlink(path) < 0)
1935  {
1936  ereport(LOG,
1938  errmsg("could not remove file \"%s\": %m",
1939  path)));
1940  continue;
1941  }
1942  }
1943  }
1944  FreeDir(snap_dir);
1945 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define DEBUG1
Definition: elog.h:25
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
#define LOG
Definition: elog.h:26
Definition: dirent.h:9
Definition: dirent.c:25
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:598
XLogRecPtr ReplicationSlotsComputeLogicalRestartLSN(void)
Definition: slot.c:708
unsigned int uint32
Definition: c.h:268
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2298
int unlink(const char *filename)
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2364
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:8153
int errmsg(const char *fmt,...)
Definition: elog.c:797
char d_name[MAX_PATH]
Definition: dirent.h:14
#define elog
Definition: elog.h:219
#define lstat(path, sb)
Definition: win32.h:272
int FreeDir(DIR *dir)
Definition: fd.c:2407
void FreeSnapshotBuilder ( SnapBuild cache)

Definition at line 321 of file snapbuild.c.

References SnapBuild::context, MemoryContextDelete(), NULL, SnapBuildSnapDecRefcount(), and SnapBuild::snapshot.

Referenced by FreeDecodingContext().

322 {
323  MemoryContext context = builder->context;
324 
325  /* free snapshot explicitly, that contains some error checking */
326  if (builder->snapshot != NULL)
327  {
328  SnapBuildSnapDecRefcount(builder->snapshot);
329  builder->snapshot = NULL;
330  }
331 
332  /* other resources are deallocated via memory context reset */
333  MemoryContextDelete(context);
334 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
#define NULL
Definition: c.h:229
void SnapBuildSnapDecRefcount(Snapshot snap)
Definition: snapbuild.c:398
void SnapBuildAbortTxn ( SnapBuild builder,
XLogRecPtr  lsn,
TransactionId  xid,
int  nsubxacts,
TransactionId subxacts 
)

Definition at line 948 of file snapbuild.c.

References i, and SnapBuildEndTxn().

Referenced by DecodeAbort().

951 {
952  int i;
953 
954  for (i = 0; i < nsubxacts; i++)
955  {
956  TransactionId subxid = subxacts[i];
957 
958  SnapBuildEndTxn(builder, lsn, subxid);
959  }
960 
961  SnapBuildEndTxn(builder, lsn, xid);
962 }
uint32 TransactionId
Definition: c.h:397
static void SnapBuildEndTxn(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid)
Definition: snapbuild.c:912
int i
void SnapBuildClearExportedSnapshot ( void  )

Definition at line 648 of file snapbuild.c.

References AbortCurrentTransaction(), CurrentResourceOwner, elog, ERROR, ExportInProgress, IsTransactionState(), NULL, and SavedResourceOwnerDuringExport.

Referenced by exec_replication_command().

649 {
650  /* nothing exported, that is the usual case */
651  if (!ExportInProgress)
652  return;
653 
654  if (!IsTransactionState())
655  elog(ERROR, "clearing exported snapshot in wrong transaction state");
656 
657  /* make sure nothing could have ever happened */
659 
662  ExportInProgress = false;
663 }
void AbortCurrentTransaction(void)
Definition: xact.c:2986
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static ResourceOwner SavedResourceOwnerDuringExport
Definition: snapbuild.c:246
#define ERROR
Definition: elog.h:43
static bool ExportInProgress
Definition: snapbuild.c:247
#define NULL
Definition: c.h:229
bool IsTransactionState(void)
Definition: xact.c:350
#define elog
Definition: elog.h:219
void SnapBuildCommitTxn ( SnapBuild builder,
XLogRecPtr  lsn,
TransactionId  xid,
int  nsubxacts,
TransactionId subxacts 
)

Definition at line 968 of file snapbuild.c.

References SnapBuild::committed, DEBUG1, DEBUG2, elog, SnapBuild::includes_all_transactions, NormalTransactionIdFollows, SnapBuild::reorder, ReorderBufferSetBaseSnapshot(), ReorderBufferXidHasBaseSnapshot(), ReorderBufferXidHasCatalogChanges(), SNAPBUILD_CONSISTENT, SNAPBUILD_FULL_SNAPSHOT, SnapBuildAddCommittedTxn(), SnapBuildBuildSnapshot(), SnapBuildDistributeNewCatalogSnapshot(), SnapBuildEndTxn(), SnapBuildSnapDecRefcount(), SnapBuildSnapIncRefcount(), SnapBuild::snapshot, SnapBuild::start_decoding_at, SnapBuild::state, TransactionIdAdvance, TransactionIdFollowsOrEquals(), TransactionIdIsValid, and SnapBuild::xmax.

Referenced by DecodeCommit().

970 {
971  int nxact;
972 
973  bool forced_timetravel = false;
974  bool sub_needs_timetravel = false;
975  bool top_needs_timetravel = false;
976 
977  TransactionId xmax = xid;
978 
979  /*
980  * If we couldn't observe every change of a transaction because it was
981  * already running at the point we started to observe we have to assume it
982  * made catalog changes.
983  *
984  * This has the positive benefit that we afterwards have enough
985  * information to build an exportable snapshot that's usable by pg_dump et
986  * al.
987  */
988  if (builder->state < SNAPBUILD_CONSISTENT)
989  {
990  /* ensure that only commits after this are getting replayed */
991  if (builder->start_decoding_at <= lsn)
992  builder->start_decoding_at = lsn + 1;
993 
994  /*
995  * We could avoid treating !SnapBuildTxnIsRunning transactions as
996  * timetravel ones, but we want to be able to export a snapshot when
997  * we reached consistency.
998  */
999  forced_timetravel = true;
1000  elog(DEBUG1, "forced to assume catalog changes for xid %u because it was running too early", xid);
1001  }
1002 
1003  for (nxact = 0; nxact < nsubxacts; nxact++)
1004  {
1005  TransactionId subxid = subxacts[nxact];
1006 
1007  /*
1008  * make sure txn is not tracked in running txn's anymore, switch state
1009  */
1010  SnapBuildEndTxn(builder, lsn, subxid);
1011 
1012  /*
1013  * If we're forcing timetravel we also need visibility information
1014  * about subtransaction, so keep track of subtransaction's state.
1015  */
1016  if (forced_timetravel)
1017  {
1018  SnapBuildAddCommittedTxn(builder, subxid);
1019  if (NormalTransactionIdFollows(subxid, xmax))
1020  xmax = subxid;
1021  }
1022 
1023  /*
1024  * Add subtransaction to base snapshot if it DDL, we don't distinguish
1025  * to toplevel transactions there.
1026  */
1027  else if (ReorderBufferXidHasCatalogChanges(builder->reorder, subxid))
1028  {
1029  sub_needs_timetravel = true;
1030 
1031  elog(DEBUG1, "found subtransaction %u:%u with catalog changes.",
1032  xid, subxid);
1033 
1034  SnapBuildAddCommittedTxn(builder, subxid);
1035 
1036  if (NormalTransactionIdFollows(subxid, xmax))
1037  xmax = subxid;
1038  }
1039  }
1040 
1041  /*
1042  * Make sure toplevel txn is not tracked in running txn's anymore, switch
1043  * state to consistent if possible.
1044  */
1045  SnapBuildEndTxn(builder, lsn, xid);
1046 
1047  if (forced_timetravel)
1048  {
1049  elog(DEBUG2, "forced transaction %u to do timetravel.", xid);
1050 
1051  SnapBuildAddCommittedTxn(builder, xid);
1052  }
1053  /* add toplevel transaction to base snapshot */
1054  else if (ReorderBufferXidHasCatalogChanges(builder->reorder, xid))
1055  {
1056  elog(DEBUG2, "found top level transaction %u, with catalog changes!",
1057  xid);
1058 
1059  top_needs_timetravel = true;
1060  SnapBuildAddCommittedTxn(builder, xid);
1061  }
1062  else if (sub_needs_timetravel)
1063  {
1064  /* mark toplevel txn as timetravel as well */
1065  SnapBuildAddCommittedTxn(builder, xid);
1066  }
1067 
1068  /* if there's any reason to build a historic snapshot, do so now */
1069  if (forced_timetravel || top_needs_timetravel || sub_needs_timetravel)
1070  {
1071  /*
1072  * Adjust xmax of the snapshot builder, we only do that for committed,
1073  * catalog modifying, transactions, everything else isn't interesting
1074  * for us since we'll never look at the respective rows.
1075  */
1076  if (!TransactionIdIsValid(builder->xmax) ||
1077  TransactionIdFollowsOrEquals(xmax, builder->xmax))
1078  {
1079  builder->xmax = xmax;
1080  TransactionIdAdvance(builder->xmax);
1081  }
1082 
1083  /*
1084  * If we haven't built a complete snapshot yet there's no need to hand
1085  * it out, it wouldn't (and couldn't) be used anyway.
1086  */
1087  if (builder->state < SNAPBUILD_FULL_SNAPSHOT)
1088  return;
1089 
1090  /*
1091  * Decrease the snapshot builder's refcount of the old snapshot, note
1092  * that it still will be used if it has been handed out to the
1093  * reorderbuffer earlier.
1094  */
1095  if (builder->snapshot)
1097 
1098  builder->snapshot = SnapBuildBuildSnapshot(builder, xid);
1099 
1100  /* we might need to execute invalidations, add snapshot */
1101  if (!ReorderBufferXidHasBaseSnapshot(builder->reorder, xid))
1102  {
1104  ReorderBufferSetBaseSnapshot(builder->reorder, xid, lsn,
1105  builder->snapshot);
1106  }
1107 
1108  /* refcount of the snapshot builder for the new snapshot */
1110 
1111  /* add a new Snapshot to all currently running transactions */
1113  }
1114  else
1115  {
1116  /* record that we cannot export a general snapshot anymore */
1117  builder->committed.includes_all_transactions = false;
1118  }
1119 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
bool ReorderBufferXidHasBaseSnapshot(ReorderBuffer *rb, TransactionId xid)
#define DEBUG1
Definition: elog.h:25
static void SnapBuildAddCommittedTxn(SnapBuild *builder, TransactionId xid)
Definition: snapbuild.c:841
uint32 TransactionId
Definition: c.h:397
Snapshot snapshot
Definition: snapbuild.c:171
void ReorderBufferSetBaseSnapshot(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, Snapshot snap)
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
static void SnapBuildEndTxn(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid)
Definition: snapbuild.c:912
SnapBuildState state
Definition: snapbuild.c:145
static void SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn)
Definition: snapbuild.c:795
#define DEBUG2
Definition: elog.h:24
ReorderBuffer * reorder
Definition: snapbuild.c:181
bool includes_all_transactions
Definition: snapbuild.c:222
bool ReorderBufferXidHasCatalogChanges(ReorderBuffer *rb, TransactionId xid)
static Snapshot SnapBuildBuildSnapshot(SnapBuild *builder, TransactionId xid)
Definition: snapbuild.c:430
TransactionId xmax
Definition: snapbuild.c:154
#define NormalTransactionIdFollows(id1, id2)
Definition: transam.h:67
void SnapBuildSnapDecRefcount(Snapshot snap)
Definition: snapbuild.c:398
struct SnapBuild::@23 committed
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void SnapBuildSnapIncRefcount(Snapshot snap)
Definition: snapbuild.c:386
XLogRecPtr start_decoding_at
Definition: snapbuild.c:160
SnapBuildState SnapBuildCurrentState ( SnapBuild snapstate)

Definition at line 365 of file snapbuild.c.

References SnapBuild::state.

Referenced by DecodeHeap2Op(), DecodeHeapOp(), DecodeLogicalMsgOp(), DecodeXactOp(), and DecodingContextReady().

366 {
367  return builder->state;
368 }
const char* SnapBuildExportSnapshot ( SnapBuild snapstate)

Definition at line 587 of file snapbuild.c.

References CurrentResourceOwner, elog, ereport, errmsg_plural(), ERROR, ExportInProgress, ExportSnapshot(), IsTransactionOrTransactionBlock(), LOG, SnapBuildInitalSnapshot(), StartTransactionCommand(), XACT_REPEATABLE_READ, XactIsoLevel, XactReadOnly, and SnapshotData::xcnt.

Referenced by CreateReplicationSlot().

588 {
589  Snapshot snap;
590  char *snapname;
591 
593  elog(ERROR, "cannot export a snapshot from within a transaction");
594 
596  elog(ERROR, "can only export one snapshot at a time");
597 
599  ExportInProgress = true;
600 
602 
603  /* There doesn't seem to a nice API to set these */
605  XactReadOnly = true;
606 
607  snap = SnapBuildInitalSnapshot(builder);
608 
609  /*
610  * now that we've built a plain snapshot, make it active and use the
611  * normal mechanisms for exporting it
612  */
613  snapname = ExportSnapshot(snap);
614 
615  ereport(LOG,
616  (errmsg_plural("exported logical decoding snapshot: \"%s\" with %u transaction ID",
617  "exported logical decoding snapshot: \"%s\" with %u transaction IDs",
618  snap->xcnt,
619  snapname, snap->xcnt)));
620  return snapname;
621 }
Snapshot SnapBuildInitalSnapshot(SnapBuild *builder)
Definition: snapbuild.c:509
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:850
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
#define XACT_REPEATABLE_READ
Definition: xact.h:30
bool IsTransactionOrTransactionBlock(void)
Definition: xact.c:4322
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1150
#define LOG
Definition: elog.h:26
static ResourceOwner SavedResourceOwnerDuringExport
Definition: snapbuild.c:246
#define ERROR
Definition: elog.h:43
static bool ExportInProgress
Definition: snapbuild.c:247
#define ereport(elevel, rest)
Definition: elog.h:122
bool XactReadOnly
Definition: xact.c:77
void StartTransactionCommand(void)
Definition: xact.c:2677
int XactIsoLevel
Definition: xact.c:74
uint32 xcnt
Definition: snapshot.h:78
#define elog
Definition: elog.h:219
Snapshot SnapBuildGetOrBuildSnapshot ( SnapBuild builder,
TransactionId  xid 
)

Definition at line 627 of file snapbuild.c.

References Assert, NULL, SNAPBUILD_CONSISTENT, SnapBuildBuildSnapshot(), SnapBuildSnapIncRefcount(), SnapBuild::snapshot, and SnapBuild::state.

Referenced by DecodeLogicalMsgOp().

628 {
629  Assert(builder->state == SNAPBUILD_CONSISTENT);
630 
631  /* only build a new snapshot if we don't have a prebuilt one */
632  if (builder->snapshot == NULL)
633  {
634  builder->snapshot = SnapBuildBuildSnapshot(builder, xid);
635  /* increase refcount for the snapshot builder */
637  }
638 
639  return builder->snapshot;
640 }
Snapshot snapshot
Definition: snapbuild.c:171
SnapBuildState state
Definition: snapbuild.c:145
static Snapshot SnapBuildBuildSnapshot(SnapBuild *builder, TransactionId xid)
Definition: snapbuild.c:430
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static void SnapBuildSnapIncRefcount(Snapshot snap)
Definition: snapbuild.c:386
Snapshot SnapBuildInitalSnapshot ( SnapBuild builder)

Definition at line 509 of file snapbuild.c.

References Assert, SnapBuild::committed, elog, ereport, errcode(), errmsg(), ERROR, FirstSnapshotSet, GetMaxSnapshotXidCount(), GetTopTransactionId(), SnapBuild::includes_all_transactions, MyPgXact, NormalTransactionIdPrecedes, NULL, palloc(), SNAPBUILD_CONSISTENT, SnapBuildBuildSnapshot(), SnapBuild::state, test(), TransactionIdAdvance, TransactionIdIsValid, XACT_REPEATABLE_READ, XactIsoLevel, SnapshotData::xcnt, xidComparator(), SnapshotData::xip, SnapshotData::xmax, SnapshotData::xmin, and PGXACT::xmin.

Referenced by CreateReplicationSlot(), and SnapBuildExportSnapshot().

510 {
511  Snapshot snap;
512  TransactionId xid;
513  TransactionId *newxip;
514  int newxcnt = 0;
515 
518 
519  if (builder->state != SNAPBUILD_CONSISTENT)
520  elog(ERROR, "cannot build an initial slot snapshot before reaching a consistent state");
521 
522  if (!builder->committed.includes_all_transactions)
523  elog(ERROR, "cannot build an initial slot snapshot, not all transactions are monitored anymore");
524 
525  /* so we don't overwrite the existing value */
527  elog(ERROR, "cannot build an initial slot snapshot when MyPgXact->xmin already is valid");
528 
529  snap = SnapBuildBuildSnapshot(builder, GetTopTransactionId());
530 
531  /*
532  * We know that snap->xmin is alive, enforced by the logical xmin
533  * mechanism. Due to that we can do this without locks, we're only
534  * changing our own value.
535  */
536  MyPgXact->xmin = snap->xmin;
537 
538  /* allocate in transaction context */
539  newxip = (TransactionId *)
541 
542  /*
543  * snapbuild.c builds transactions in an "inverted" manner, which means it
544  * stores committed transactions in ->xip, not ones in progress. Build a
545  * classical snapshot by marking all non-committed transactions as
546  * in-progress. This can be expensive.
547  */
548  for (xid = snap->xmin; NormalTransactionIdPrecedes(xid, snap->xmax);)
549  {
550  void *test;
551 
552  /*
553  * Check whether transaction committed using the decoding snapshot
554  * meaning of ->xip.
555  */
556  test = bsearch(&xid, snap->xip, snap->xcnt,
557  sizeof(TransactionId), xidComparator);
558 
559  if (test == NULL)
560  {
561  if (newxcnt >= GetMaxSnapshotXidCount())
562  ereport(ERROR,
563  (errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
564  errmsg("initial slot snapshot too large")));
565 
566  newxip[newxcnt++] = xid;
567  }
568 
570  }
571 
572  snap->xcnt = newxcnt;
573  snap->xip = newxip;
574 
575  return snap;
576 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
static void test(void)
uint32 TransactionId
Definition: c.h:397
TransactionId xmin
Definition: proc.h:208
#define XACT_REPEATABLE_READ
Definition: xact.h:30
int errcode(int sqlerrcode)
Definition: elog.c:575
TransactionId GetTopTransactionId(void)
Definition: xact.c:389
PGXACT * MyPgXact
Definition: proc.c:68
SnapBuildState state
Definition: snapbuild.c:145
#define ERROR
Definition: elog.h:43
bool FirstSnapshotSet
Definition: snapmgr.c:203
bool includes_all_transactions
Definition: snapbuild.c:222
TransactionId xmax
Definition: snapshot.h:67
TransactionId xmin
Definition: snapshot.h:66
#define ereport(elevel, rest)
Definition: elog.h:122
static Snapshot SnapBuildBuildSnapshot(SnapBuild *builder, TransactionId xid)
Definition: snapbuild.c:430
TransactionId * xip
Definition: snapshot.h:77
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1446
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
int XactIsoLevel
Definition: xact.c:74
#define NormalTransactionIdPrecedes(id1, id2)
Definition: transam.h:62
uint32 xcnt
Definition: snapshot.h:78
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
struct SnapBuild::@23 committed
#define elog
Definition: elog.h:219
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:138
bool SnapBuildProcessChange ( SnapBuild builder,
TransactionId  xid,
XLogRecPtr  lsn 
)

Definition at line 671 of file snapbuild.c.

References NULL, SnapBuild::reorder, ReorderBufferSetBaseSnapshot(), ReorderBufferXidHasBaseSnapshot(), SNAPBUILD_CONSISTENT, SNAPBUILD_FULL_SNAPSHOT, SnapBuildBuildSnapshot(), SnapBuildSnapIncRefcount(), SnapBuildTxnIsRunning(), SnapBuild::snapshot, and SnapBuild::state.

Referenced by DecodeHeap2Op(), DecodeHeapOp(), and DecodeLogicalMsgOp().

672 {
673  /*
674  * We can't handle data in transactions if we haven't built a snapshot
675  * yet, so don't store them.
676  */
677  if (builder->state < SNAPBUILD_FULL_SNAPSHOT)
678  return false;
679 
680  /*
681  * No point in keeping track of changes in transactions that we don't have
682  * enough information about to decode. This means that they started before
683  * we got into the SNAPBUILD_FULL_SNAPSHOT state.
684  */
685  if (builder->state < SNAPBUILD_CONSISTENT &&
686  SnapBuildTxnIsRunning(builder, xid))
687  return false;
688 
689  /*
690  * If the reorderbuffer doesn't yet have a snapshot, add one now, it will
691  * be needed to decode the change we're currently processing.
692  */
693  if (!ReorderBufferXidHasBaseSnapshot(builder->reorder, xid))
694  {
695  /* only build a new snapshot if we don't have a prebuilt one */
696  if (builder->snapshot == NULL)
697  {
698  builder->snapshot = SnapBuildBuildSnapshot(builder, xid);
699  /* increase refcount for the snapshot builder */
701  }
702 
703  /*
704  * Increase refcount for the transaction we're handing the snapshot
705  * out to.
706  */
708  ReorderBufferSetBaseSnapshot(builder->reorder, xid, lsn,
709  builder->snapshot);
710  }
711 
712  return true;
713 }
bool ReorderBufferXidHasBaseSnapshot(ReorderBuffer *rb, TransactionId xid)
Snapshot snapshot
Definition: snapbuild.c:171
void ReorderBufferSetBaseSnapshot(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, Snapshot snap)
SnapBuildState state
Definition: snapbuild.c:145
ReorderBuffer * reorder
Definition: snapbuild.c:181
static Snapshot SnapBuildBuildSnapshot(SnapBuild *builder, TransactionId xid)
Definition: snapbuild.c:430
static bool SnapBuildTxnIsRunning(SnapBuild *builder, TransactionId xid)
Definition: snapbuild.c:762
#define NULL
Definition: c.h:229
static void SnapBuildSnapIncRefcount(Snapshot snap)
Definition: snapbuild.c:386
void SnapBuildProcessNewCid ( SnapBuild builder,
TransactionId  xid,
XLogRecPtr  lsn,
struct xl_heap_new_cid cid 
)

Definition at line 721 of file snapbuild.c.

References xl_heap_new_cid::cmax, xl_heap_new_cid::cmin, xl_heap_new_cid::combocid, elog, ERROR, InvalidCommandId, Max, SnapBuild::reorder, ReorderBufferAddNewCommandId(), ReorderBufferAddNewTupleCids(), ReorderBufferXidSetCatalogChanges(), xl_heap_new_cid::target_node, xl_heap_new_cid::target_tid, and xl_heap_new_cid::top_xid.

Referenced by DecodeHeap2Op().

723 {
724  CommandId cid;
725 
726  /*
727  * we only log new_cid's if a catalog tuple was modified, so mark the
728  * transaction as containing catalog modifications
729  */
730  ReorderBufferXidSetCatalogChanges(builder->reorder, xid, lsn);
731 
732  ReorderBufferAddNewTupleCids(builder->reorder, xlrec->top_xid, lsn,
733  xlrec->target_node, xlrec->target_tid,
734  xlrec->cmin, xlrec->cmax,
735  xlrec->combocid);
736 
737  /* figure out new command id */
738  if (xlrec->cmin != InvalidCommandId &&
739  xlrec->cmax != InvalidCommandId)
740  cid = Max(xlrec->cmin, xlrec->cmax);
741  else if (xlrec->cmax != InvalidCommandId)
742  cid = xlrec->cmax;
743  else if (xlrec->cmin != InvalidCommandId)
744  cid = xlrec->cmin;
745  else
746  {
747  cid = InvalidCommandId; /* silence compiler */
748  elog(ERROR, "xl_heap_new_cid record without a valid CommandId");
749  }
750 
751  ReorderBufferAddNewCommandId(builder->reorder, xid, lsn, cid + 1);
752 }
uint32 CommandId
Definition: c.h:411
void ReorderBufferAddNewTupleCids(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, RelFileNode node, ItemPointerData tid, CommandId cmin, CommandId cmax, CommandId combocid)
#define ERROR
Definition: elog.h:43
ReorderBuffer * reorder
Definition: snapbuild.c:181
#define InvalidCommandId
Definition: c.h:414
#define Max(x, y)
Definition: c.h:800
void ReorderBufferXidSetCatalogChanges(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn)
#define elog
Definition: elog.h:219
void ReorderBufferAddNewCommandId(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, CommandId cid)
void SnapBuildProcessRunningXacts ( SnapBuild builder,
XLogRecPtr  lsn,
struct xl_running_xacts running 
)

Definition at line 1133 of file snapbuild.c.

References ReorderBuffer::current_restart_decoding_lsn, DEBUG3, elog, InvalidXLogRecPtr, SnapBuild::last_serialized_snapshot, LogicalIncreaseRestartDecodingForSlot(), LogicalIncreaseXminForSlot(), NULL, xl_running_xacts::oldestRunningXid, SnapBuild::reorder, ReorderBufferGetOldestTXN(), ReorderBufferTXN::restart_decoding_lsn, SNAPBUILD_CONSISTENT, SnapBuildFindSnapshot(), SnapBuildPurgeCommittedTxn(), SnapBuildSerialize(), SnapBuild::state, SnapBuild::xmax, and SnapBuild::xmin.

Referenced by DecodeStandbyOp().

1134 {
1135  ReorderBufferTXN *txn;
1136 
1137  /*
1138  * If we're not consistent yet, inspect the record to see whether it
1139  * allows to get closer to being consistent. If we are consistent, dump
1140  * our snapshot so others or we, after a restart, can use it.
1141  */
1142  if (builder->state < SNAPBUILD_CONSISTENT)
1143  {
1144  /* returns false if there's no point in performing cleanup just yet */
1145  if (!SnapBuildFindSnapshot(builder, lsn, running))
1146  return;
1147  }
1148  else
1149  SnapBuildSerialize(builder, lsn);
1150 
1151  /*
1152  * Update range of interesting xids based on the running xacts
1153  * information. We don't increase ->xmax using it, because once we are in
1154  * a consistent state we can do that ourselves and much more efficiently
1155  * so, because we only need to do it for catalog transactions since we
1156  * only ever look at those.
1157  *
1158  * NB: Because of that xmax can be lower than xmin, because we only
1159  * increase xmax when a catalog modifying transaction commits. While odd
1160  * looking, it's correct and actually more efficient this way since we hit
1161  * fast paths in tqual.c.
1162  */
1163  builder->xmin = running->oldestRunningXid;
1164 
1165  /* Remove transactions we don't need to keep track off anymore */
1166  SnapBuildPurgeCommittedTxn(builder);
1167 
1168  elog(DEBUG3, "xmin: %u, xmax: %u, oldestrunning: %u",
1169  builder->xmin, builder->xmax,
1170  running->oldestRunningXid);
1171 
1172  /*
1173  * Increase shared memory limits, so vacuum can work on tuples we prevented
1174  * from being pruned till now.
1175  */
1177 
1178  /*
1179  * Also tell the slot where we can restart decoding from. We don't want to
1180  * do that after every commit because changing that implies an fsync of
1181  * the logical slot's state file, so we only do it every time we see a
1182  * running xacts record.
1183  *
1184  * Do so by looking for the oldest in progress transaction (determined by
1185  * the first LSN of any of its relevant records). Every transaction
1186  * remembers the last location we stored the snapshot to disk before its
1187  * beginning. That point is where we can restart from.
1188  */
1189 
1190  /*
1191  * Can't know about a serialized snapshot's location if we're not
1192  * consistent.
1193  */
1194  if (builder->state < SNAPBUILD_CONSISTENT)
1195  return;
1196 
1197  txn = ReorderBufferGetOldestTXN(builder->reorder);
1198 
1199  /*
1200  * oldest ongoing txn might have started when we didn't yet serialize
1201  * anything because we hadn't reached a consistent state yet.
1202  */
1203  if (txn != NULL && txn->restart_decoding_lsn != InvalidXLogRecPtr)
1205 
1206  /*
1207  * No in-progress transaction, can reuse the last serialized snapshot if
1208  * we have one.
1209  */
1210  else if (txn == NULL &&
1214  builder->last_serialized_snapshot);
1215 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define DEBUG3
Definition: elog.h:23
void LogicalIncreaseRestartDecodingForSlot(XLogRecPtr current_lsn, XLogRecPtr restart_lsn)
Definition: logical.c:815
XLogRecPtr current_restart_decoding_lsn
static bool SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *running)
Definition: snapbuild.c:1228
SnapBuildState state
Definition: snapbuild.c:145
static void SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn)
Definition: snapbuild.c:1468
ReorderBuffer * reorder
Definition: snapbuild.c:181
XLogRecPtr last_serialized_snapshot
Definition: snapbuild.c:176
TransactionId xmax
Definition: snapbuild.c:154
#define NULL
Definition: c.h:229
ReorderBufferTXN * ReorderBufferGetOldestTXN(ReorderBuffer *rb)
void LogicalIncreaseXminForSlot(XLogRecPtr current_lsn, TransactionId xmin)
Definition: logical.c:758
TransactionId xmin
Definition: snapbuild.c:151
XLogRecPtr restart_decoding_lsn
TransactionId oldestRunningXid
Definition: standbydefs.h:53
#define elog
Definition: elog.h:219
static void SnapBuildPurgeCommittedTxn(SnapBuild *builder)
Definition: snapbuild.c:870
void SnapBuildSerializationPoint ( SnapBuild builder,
XLogRecPtr  lsn 
)

Definition at line 1455 of file snapbuild.c.

References SNAPBUILD_CONSISTENT, SnapBuildRestore(), SnapBuildSerialize(), and SnapBuild::state.

Referenced by DecodeXLogOp().

1456 {
1457  if (builder->state < SNAPBUILD_CONSISTENT)
1458  SnapBuildRestore(builder, lsn);
1459  else
1460  SnapBuildSerialize(builder, lsn);
1461 }
static bool SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn)
Definition: snapbuild.c:1665
SnapBuildState state
Definition: snapbuild.c:145
static void SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn)
Definition: snapbuild.c:1468
void SnapBuildSnapDecRefcount ( Snapshot  snap)

Definition at line 398 of file snapbuild.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, SnapshotData::curcid, elog, ERROR, FirstCommandId, HeapTupleSatisfiesHistoricMVCC(), SnapshotData::regd_count, SnapshotData::satisfies, SnapBuildFreeSnapshot(), SnapshotData::suboverflowed, and SnapshotData::takenDuringRecovery.

Referenced by FreeSnapshotBuilder(), ReorderBufferCleanupTXN(), ReorderBufferFreeSnap(), SnapBuildCommitTxn(), and SnapBuildRestore().

399 {
400  /* make sure we don't get passed an external snapshot */
402 
403  /* make sure nobody modified our snapshot */
404  Assert(snap->curcid == FirstCommandId);
405  Assert(!snap->suboverflowed);
406  Assert(!snap->takenDuringRecovery);
407 
408  Assert(snap->regd_count == 0);
409 
410  Assert(snap->active_count > 0);
411 
412  /* slightly more likely, so it's checked even without casserts */
413  if (snap->copied)
414  elog(ERROR, "cannot free a copied snapshot");
415 
416  snap->active_count--;
417  if (snap->active_count == 0)
418  SnapBuildFreeSnapshot(snap);
419 }
SnapshotSatisfiesFunc satisfies
Definition: snapshot.h:54
bool copied
Definition: snapshot.h:94
bool suboverflowed
Definition: snapshot.h:91
uint32 regd_count
Definition: snapshot.h:108
#define FirstCommandId
Definition: c.h:413
#define ERROR
Definition: elog.h:43
static void SnapBuildFreeSnapshot(Snapshot snap)
Definition: snapbuild.c:340
bool HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
Definition: tqual.c:1652
CommandId curcid
Definition: snapshot.h:96
#define Assert(condition)
Definition: c.h:675
bool takenDuringRecovery
Definition: snapshot.h:93
#define elog
Definition: elog.h:219
uint32 active_count
Definition: snapshot.h:107
bool SnapBuildXactNeedsSkip ( SnapBuild snapstate,
XLogRecPtr  ptr 
)

Definition at line 374 of file snapbuild.c.

References SnapBuild::start_decoding_at.

Referenced by DecodeCommit(), and DecodeLogicalMsgOp().

375 {
376  return ptr < builder->start_decoding_at;
377 }