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

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

Definition at line 1835 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().

1836 {
1837  XLogRecPtr cutoff;
1838  XLogRecPtr redo;
1839  DIR *snap_dir;
1840  struct dirent *snap_de;
1841  char path[MAXPGPATH];
1842 
1843  /*
1844  * We start of with a minimum of the last redo pointer. No new replication
1845  * slot will start before that, so that's a safe upper bound for removal.
1846  */
1847  redo = GetRedoRecPtr();
1848 
1849  /* now check for the restart ptrs from existing slots */
1851 
1852  /* don't start earlier than the restart lsn */
1853  if (redo < cutoff)
1854  cutoff = redo;
1855 
1856  snap_dir = AllocateDir("pg_logical/snapshots");
1857  while ((snap_de = ReadDir(snap_dir, "pg_logical/snapshots")) != NULL)
1858  {
1859  uint32 hi;
1860  uint32 lo;
1861  XLogRecPtr lsn;
1862  struct stat statbuf;
1863 
1864  if (strcmp(snap_de->d_name, ".") == 0 ||
1865  strcmp(snap_de->d_name, "..") == 0)
1866  continue;
1867 
1868  snprintf(path, MAXPGPATH, "pg_logical/snapshots/%s", snap_de->d_name);
1869 
1870  if (lstat(path, &statbuf) == 0 && !S_ISREG(statbuf.st_mode))
1871  {
1872  elog(DEBUG1, "only regular files expected: %s", path);
1873  continue;
1874  }
1875 
1876  /*
1877  * temporary filenames from SnapBuildSerialize() include the LSN and
1878  * everything but are postfixed by .$pid.tmp. We can just remove them
1879  * the same as other files because there can be none that are
1880  * currently being written that are older than cutoff.
1881  *
1882  * We just log a message if a file doesn't fit the pattern, it's
1883  * probably some editors lock/state file or similar...
1884  */
1885  if (sscanf(snap_de->d_name, "%X-%X.snap", &hi, &lo) != 2)
1886  {
1887  ereport(LOG,
1888  (errmsg("could not parse file name \"%s\"", path)));
1889  continue;
1890  }
1891 
1892  lsn = ((uint64) hi) << 32 | lo;
1893 
1894  /* check whether we still need it */
1895  if (lsn < cutoff || cutoff == InvalidXLogRecPtr)
1896  {
1897  elog(DEBUG1, "removing snapbuild snapshot %s", path);
1898 
1899  /*
1900  * It's not particularly harmful, though strange, if we can't
1901  * remove the file here. Don't prevent the checkpoint from
1902  * completing, that'd be cure worse than the disease.
1903  */
1904  if (unlink(path) < 0)
1905  {
1906  ereport(LOG,
1908  errmsg("could not remove file \"%s\": %m",
1909  path)));
1910  continue;
1911  }
1912  }
1913  }
1914  FreeDir(snap_dir);
1915 }
#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:707
unsigned int uint32
Definition: c.h:265
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2207
int unlink(const char *filename)
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:226
uint64 XLogRecPtr
Definition: xlogdefs.h:21
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2273
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:8115
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:2316
void FreeSnapshotBuilder ( SnapBuild cache)

Definition at line 320 of file snapbuild.c.

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

Referenced by FreeDecodingContext().

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

Definition at line 930 of file snapbuild.c.

References i, and SnapBuildEndTxn().

Referenced by DecodeAbort().

933 {
934  int i;
935 
936  for (i = 0; i < nsubxacts; i++)
937  {
938  TransactionId subxid = subxacts[i];
939 
940  SnapBuildEndTxn(builder, lsn, subxid);
941  }
942 
943  SnapBuildEndTxn(builder, lsn, xid);
944 }
uint32 TransactionId
Definition: c.h:393
static void SnapBuildEndTxn(SnapBuild *builder, XLogRecPtr lsn, TransactionId xid)
Definition: snapbuild.c:894
int i
void SnapBuildClearExportedSnapshot ( void  )

Definition at line 630 of file snapbuild.c.

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

Referenced by exec_replication_command().

631 {
632  /* nothing exported, that is the usual case */
633  if (!ExportInProgress)
634  return;
635 
636  if (!IsTransactionState())
637  elog(ERROR, "clearing exported snapshot in wrong transaction state");
638 
639  /* make sure nothing could have ever happened */
641 
644  ExportInProgress = false;
645 }
void AbortCurrentTransaction(void)
Definition: xact.c:2984
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static ResourceOwner SavedResourceOwnerDuringExport
Definition: snapbuild.c:245
#define ERROR
Definition: elog.h:43
static bool ExportInProgress
Definition: snapbuild.c:246
#define NULL
Definition: c.h:226
bool IsTransactionState(void)
Definition: xact.c:349
#define elog
Definition: elog.h:219
void SnapBuildCommitTxn ( SnapBuild builder,
XLogRecPtr  lsn,
TransactionId  xid,
int  nsubxacts,
TransactionId subxacts 
)

Definition at line 950 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().

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

Definition at line 364 of file snapbuild.c.

References SnapBuild::state.

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

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

Definition at line 512 of file snapbuild.c.

References Assert, SnapBuild::committed, CurrentResourceOwner, elog, ereport, errmsg_plural(), ERROR, ExportInProgress, ExportSnapshot(), FirstSnapshotSet, GetMaxSnapshotXidCount(), GetTopTransactionId(), SnapBuild::includes_all_transactions, IsTransactionOrTransactionBlock(), LOG, MyPgXact, NormalTransactionIdPrecedes, NULL, palloc(), SNAPBUILD_CONSISTENT, SnapBuildBuildSnapshot(), StartTransactionCommand(), SnapBuild::state, test(), TransactionIdAdvance, TransactionIdIsValid, XACT_REPEATABLE_READ, XactIsoLevel, XactReadOnly, SnapshotData::xcnt, xidComparator(), SnapshotData::xip, SnapshotData::xmax, SnapshotData::xmin, and PGXACT::xmin.

Referenced by CreateReplicationSlot().

513 {
514  Snapshot snap;
515  char *snapname;
516  TransactionId xid;
517  TransactionId *newxip;
518  int newxcnt = 0;
519 
520  if (builder->state != SNAPBUILD_CONSISTENT)
521  elog(ERROR, "cannot export a snapshot before reaching a consistent state");
522 
523  if (!builder->committed.includes_all_transactions)
524  elog(ERROR, "cannot export a snapshot, not all transactions are monitored anymore");
525 
526  /* so we don't overwrite the existing value */
528  elog(ERROR, "cannot export a snapshot when MyPgXact->xmin already is valid");
529 
531  elog(ERROR, "cannot export a snapshot from within a transaction");
532 
534  elog(ERROR, "can only export one snapshot at a time");
535 
537  ExportInProgress = true;
538 
540 
542 
543  /* There doesn't seem to a nice API to set these */
545  XactReadOnly = true;
546 
547  snap = SnapBuildBuildSnapshot(builder, GetTopTransactionId());
548 
549  /*
550  * We know that snap->xmin is alive, enforced by the logical xmin
551  * mechanism. Due to that we can do this without locks, we're only
552  * changing our own value.
553  */
554  MyPgXact->xmin = snap->xmin;
555 
556  /* allocate in transaction context */
557  newxip = (TransactionId *)
559 
560  /*
561  * snapbuild.c builds transactions in an "inverted" manner, which means it
562  * stores committed transactions in ->xip, not ones in progress. Build a
563  * classical snapshot by marking all non-committed transactions as
564  * in-progress. This can be expensive.
565  */
566  for (xid = snap->xmin; NormalTransactionIdPrecedes(xid, snap->xmax);)
567  {
568  void *test;
569 
570  /*
571  * Check whether transaction committed using the decoding snapshot
572  * meaning of ->xip.
573  */
574  test = bsearch(&xid, snap->xip, snap->xcnt,
575  sizeof(TransactionId), xidComparator);
576 
577  if (test == NULL)
578  {
579  if (newxcnt >= GetMaxSnapshotXidCount())
580  elog(ERROR, "snapshot too large");
581 
582  newxip[newxcnt++] = xid;
583  }
584 
586  }
587 
588  snap->xcnt = newxcnt;
589  snap->xip = newxip;
590 
591  /*
592  * now that we've built a plain snapshot, use the normal mechanisms for
593  * exporting it
594  */
595  snapname = ExportSnapshot(snap);
596 
597  ereport(LOG,
598  (errmsg_plural("exported logical decoding snapshot: \"%s\" with %u transaction ID",
599  "exported logical decoding snapshot: \"%s\" with %u transaction IDs",
600  snap->xcnt,
601  snapname, snap->xcnt)));
602  return snapname;
603 }
#define TransactionIdAdvance(dest)
Definition: transam.h:48
static void test(void)
uint32 TransactionId
Definition: c.h:393
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:850
TransactionId xmin
Definition: proc.h:203
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
#define XACT_REPEATABLE_READ
Definition: xact.h:30
bool IsTransactionOrTransactionBlock(void)
Definition: xact.c:4320
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1150
TransactionId GetTopTransactionId(void)
Definition: xact.c:388
#define LOG
Definition: elog.h:26
static ResourceOwner SavedResourceOwnerDuringExport
Definition: snapbuild.c:245
PGXACT * MyPgXact
Definition: proc.c:68
#define ERROR
Definition: elog.h:43
bool FirstSnapshotSet
Definition: snapmgr.c:203
static bool ExportInProgress
Definition: snapbuild.c:246
TransactionId xmax
Definition: snapshot.h:66
TransactionId xmin
Definition: snapshot.h:65
#define ereport(elevel, rest)
Definition: elog.h:122
static Snapshot SnapBuildBuildSnapshot(SnapBuild *builder, TransactionId xid)
Definition: snapbuild.c:429
TransactionId * xip
Definition: snapshot.h:76
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1451
bool XactReadOnly
Definition: xact.c:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
void StartTransactionCommand(void)
Definition: xact.c:2675
int XactIsoLevel
Definition: xact.c:74
#define NormalTransactionIdPrecedes(id1, id2)
Definition: transam.h:62
uint32 xcnt
Definition: snapshot.h:77
void * palloc(Size size)
Definition: mcxt.c:891
#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
Snapshot SnapBuildGetOrBuildSnapshot ( SnapBuild builder,
TransactionId  xid 
)

Definition at line 609 of file snapbuild.c.

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

Referenced by DecodeLogicalMsgOp().

610 {
611  Assert(builder->state == SNAPBUILD_CONSISTENT);
612 
613  /* only build a new snapshot if we don't have a prebuilt one */
614  if (builder->snapshot == NULL)
615  {
616  builder->snapshot = SnapBuildBuildSnapshot(builder, xid);
617  /* increase refcount for the snapshot builder */
619  }
620 
621  return builder->snapshot;
622 }
Snapshot snapshot
Definition: snapbuild.c:170
SnapBuildState state
Definition: snapbuild.c:144
static Snapshot SnapBuildBuildSnapshot(SnapBuild *builder, TransactionId xid)
Definition: snapbuild.c:429
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
static void SnapBuildSnapIncRefcount(Snapshot snap)
Definition: snapbuild.c:385
bool SnapBuildProcessChange ( SnapBuild builder,
TransactionId  xid,
XLogRecPtr  lsn 
)

Definition at line 653 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().

654 {
655  /*
656  * We can't handle data in transactions if we haven't built a snapshot
657  * yet, so don't store them.
658  */
659  if (builder->state < SNAPBUILD_FULL_SNAPSHOT)
660  return false;
661 
662  /*
663  * No point in keeping track of changes in transactions that we don't have
664  * enough information about to decode. This means that they started before
665  * we got into the SNAPBUILD_FULL_SNAPSHOT state.
666  */
667  if (builder->state < SNAPBUILD_CONSISTENT &&
668  SnapBuildTxnIsRunning(builder, xid))
669  return false;
670 
671  /*
672  * If the reorderbuffer doesn't yet have a snapshot, add one now, it will
673  * be needed to decode the change we're currently processing.
674  */
675  if (!ReorderBufferXidHasBaseSnapshot(builder->reorder, xid))
676  {
677  /* only build a new snapshot if we don't have a prebuilt one */
678  if (builder->snapshot == NULL)
679  {
680  builder->snapshot = SnapBuildBuildSnapshot(builder, xid);
681  /* increase refcount for the snapshot builder */
683  }
684 
685  /*
686  * Increase refcount for the transaction we're handing the snapshot
687  * out to.
688  */
690  ReorderBufferSetBaseSnapshot(builder->reorder, xid, lsn,
691  builder->snapshot);
692  }
693 
694  return true;
695 }
bool ReorderBufferXidHasBaseSnapshot(ReorderBuffer *rb, TransactionId xid)
Snapshot snapshot
Definition: snapbuild.c:170
void ReorderBufferSetBaseSnapshot(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn, Snapshot snap)
SnapBuildState state
Definition: snapbuild.c:144
ReorderBuffer * reorder
Definition: snapbuild.c:180
static Snapshot SnapBuildBuildSnapshot(SnapBuild *builder, TransactionId xid)
Definition: snapbuild.c:429
static bool SnapBuildTxnIsRunning(SnapBuild *builder, TransactionId xid)
Definition: snapbuild.c:744
#define NULL
Definition: c.h:226
static void SnapBuildSnapIncRefcount(Snapshot snap)
Definition: snapbuild.c:385
void SnapBuildProcessNewCid ( SnapBuild builder,
TransactionId  xid,
XLogRecPtr  lsn,
struct xl_heap_new_cid cid 
)

Definition at line 703 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().

705 {
706  CommandId cid;
707 
708  /*
709  * we only log new_cid's if a catalog tuple was modified, so mark the
710  * transaction as containing catalog modifications
711  */
712  ReorderBufferXidSetCatalogChanges(builder->reorder, xid, lsn);
713 
714  ReorderBufferAddNewTupleCids(builder->reorder, xlrec->top_xid, lsn,
715  xlrec->target_node, xlrec->target_tid,
716  xlrec->cmin, xlrec->cmax,
717  xlrec->combocid);
718 
719  /* figure out new command id */
720  if (xlrec->cmin != InvalidCommandId &&
721  xlrec->cmax != InvalidCommandId)
722  cid = Max(xlrec->cmin, xlrec->cmax);
723  else if (xlrec->cmax != InvalidCommandId)
724  cid = xlrec->cmax;
725  else if (xlrec->cmin != InvalidCommandId)
726  cid = xlrec->cmin;
727  else
728  {
729  cid = InvalidCommandId; /* silence compiler */
730  elog(ERROR, "xl_heap_new_cid record without a valid CommandId");
731  }
732 
733  ReorderBufferAddNewCommandId(builder->reorder, xid, lsn, cid + 1);
734 }
uint32 CommandId
Definition: c.h:407
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:180
#define InvalidCommandId
Definition: c.h:410
#define Max(x, y)
Definition: c.h:795
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 1115 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().

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

Definition at line 1437 of file snapbuild.c.

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

Referenced by DecodeXLogOp().

1438 {
1439  if (builder->state < SNAPBUILD_CONSISTENT)
1440  SnapBuildRestore(builder, lsn);
1441  else
1442  SnapBuildSerialize(builder, lsn);
1443 }
static bool SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn)
Definition: snapbuild.c:1643
SnapBuildState state
Definition: snapbuild.c:144
static void SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn)
Definition: snapbuild.c:1450
void SnapBuildSnapDecRefcount ( Snapshot  snap)

Definition at line 397 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().

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

Definition at line 373 of file snapbuild.c.

References SnapBuild::start_decoding_at.

Referenced by DecodeCommit(), and DecodeLogicalMsgOp().

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