PostgreSQL Source Code  git master
snapmgr.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * snapmgr.c
4  * PostgreSQL snapshot manager
5  *
6  * We keep track of snapshots in two ways: those "registered" by resowner.c,
7  * and the "active snapshot" stack. All snapshots in either of them live in
8  * persistent memory. When a snapshot is no longer in any of these lists
9  * (tracked by separate refcounts on each snapshot), its memory can be freed.
10  *
11  * The FirstXactSnapshot, if any, is treated a bit specially: we increment its
12  * regd_count and list it in RegisteredSnapshots, but this reference is not
13  * tracked by a resource owner. We used to use the TopTransactionResourceOwner
14  * to track this snapshot reference, but that introduces logical circularity
15  * and thus makes it impossible to clean up in a sane fashion. It's better to
16  * handle this reference as an internally-tracked registration, so that this
17  * module is entirely lower-level than ResourceOwners.
18  *
19  * Likewise, any snapshots that have been exported by pg_export_snapshot
20  * have regd_count = 1 and are listed in RegisteredSnapshots, but are not
21  * tracked by any resource owner.
22  *
23  * Likewise, the CatalogSnapshot is listed in RegisteredSnapshots when it
24  * is valid, but is not tracked by any resource owner.
25  *
26  * The same is true for historic snapshots used during logical decoding,
27  * their lifetime is managed separately (as they live longer than one xact.c
28  * transaction).
29  *
30  * These arrangements let us reset MyProc->xmin when there are no snapshots
31  * referenced by this transaction, and advance it when the one with oldest
32  * Xmin is no longer referenced. For simplicity however, only registered
33  * snapshots not active snapshots participate in tracking which one is oldest;
34  * we don't try to change MyProc->xmin except when the active-snapshot
35  * stack is empty.
36  *
37  *
38  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
39  * Portions Copyright (c) 1994, Regents of the University of California
40  *
41  * IDENTIFICATION
42  * src/backend/utils/time/snapmgr.c
43  *
44  *-------------------------------------------------------------------------
45  */
46 #include "postgres.h"
47 
48 #include <sys/stat.h>
49 #include <unistd.h>
50 
51 #include "access/subtrans.h"
52 #include "access/transam.h"
53 #include "access/xact.h"
54 #include "access/xlog.h"
55 #include "catalog/catalog.h"
56 #include "datatype/timestamp.h"
57 #include "lib/pairingheap.h"
58 #include "miscadmin.h"
59 #include "storage/predicate.h"
60 #include "storage/proc.h"
61 #include "storage/procarray.h"
62 #include "storage/sinval.h"
63 #include "storage/sinvaladt.h"
64 #include "storage/spin.h"
65 #include "utils/builtins.h"
66 #include "utils/memutils.h"
67 #include "utils/old_snapshot.h"
68 #include "utils/rel.h"
69 #include "utils/resowner_private.h"
70 #include "utils/snapmgr.h"
71 #include "utils/syscache.h"
72 #include "utils/timestamp.h"
73 
74 
75 /*
76  * GUC parameters
77  */
78 int old_snapshot_threshold; /* number of minutes, -1 disables */
79 
81 
82 
83 /*
84  * CurrentSnapshot points to the only snapshot taken in transaction-snapshot
85  * mode, and to the latest one taken in a read-committed transaction.
86  * SecondarySnapshot is a snapshot that's always up-to-date as of the current
87  * instant, even in transaction-snapshot mode. It should only be used for
88  * special-purpose code (say, RI checking.) CatalogSnapshot points to an
89  * MVCC snapshot intended to be used for catalog scans; we must invalidate it
90  * whenever a system catalog change occurs.
91  *
92  * These SnapshotData structs are static to simplify memory allocation
93  * (see the hack in GetSnapshotData to avoid repeated malloc/free).
94  */
100 
101 /* Pointers to valid snapshots */
102 static Snapshot CurrentSnapshot = NULL;
104 static Snapshot CatalogSnapshot = NULL;
106 
107 /*
108  * These are updated by GetSnapshotData. We initialize them this way
109  * for the convenience of TransactionIdIsInProgress: even in bootstrap
110  * mode, we don't want it to say that BootstrapTransactionId is in progress.
111  */
114 
115 /* (table, ctid) => (cmin, cmax) mapping during timetravel */
116 static HTAB *tuplecid_data = NULL;
117 
118 /*
119  * Elements of the active snapshot stack.
120  *
121  * Each element here accounts for exactly one active_count on SnapshotData.
122  *
123  * NB: the code assumes that elements in this list are in non-increasing
124  * order of as_level; also, the list must be NULL-terminated.
125  */
126 typedef struct ActiveSnapshotElt
127 {
129  int as_level;
132 
133 /* Top of the stack of active snapshots */
135 
136 /* Bottom of the stack of active snapshots */
138 
139 /*
140  * Currently registered Snapshots. Ordered in a heap by xmin, so that we can
141  * quickly find the one with lowest xmin, to advance our MyProc->xmin.
142  */
143 static int xmin_cmp(const pairingheap_node *a, const pairingheap_node *b,
144  void *arg);
145 
146 static pairingheap RegisteredSnapshots = {&xmin_cmp, NULL, NULL};
147 
148 /* first GetTransactionSnapshot call in a transaction? */
149 bool FirstSnapshotSet = false;
150 
151 /*
152  * Remember the serializable transaction snapshot, if any. We cannot trust
153  * FirstSnapshotSet in combination with IsolationUsesXactSnapshot(), because
154  * GUC may be reset before us, changing the value of IsolationUsesXactSnapshot.
155  */
157 
158 /* Define pathname of exported-snapshot files */
159 #define SNAPSHOT_EXPORT_DIR "pg_snapshots"
160 
161 /* Structure holding info about exported snapshot. */
162 typedef struct ExportedSnapshot
163 {
164  char *snapfile;
167 
168 /* Current xact's exported snapshots (a list of ExportedSnapshot structs) */
170 
171 /* Prototypes for local functions */
173 static Snapshot CopySnapshot(Snapshot snapshot);
174 static void FreeSnapshot(Snapshot snapshot);
175 static void SnapshotResetXmin(void);
176 
177 /*
178  * Snapshot fields to be serialized.
179  *
180  * Only these fields need to be sent to the cooperating backend; the
181  * remaining ones can (and must) be set by the receiver upon restore.
182  */
184 {
195 
196 Size
198 {
199  Size size;
200 
201  size = offsetof(OldSnapshotControlData, xid_by_minute);
202  if (old_snapshot_threshold > 0)
203  size = add_size(size, mul_size(sizeof(TransactionId),
205 
206  return size;
207 }
208 
209 /*
210  * Initialize for managing old snapshot detection.
211  */
212 void
214 {
215  bool found;
216 
217  /*
218  * Create or attach to the OldSnapshotControlData structure.
219  */
220  oldSnapshotControl = (volatile OldSnapshotControlData *)
221  ShmemInitStruct("OldSnapshotControlData",
222  SnapMgrShmemSize(), &found);
223 
224  if (!found)
225  {
226  SpinLockInit(&oldSnapshotControl->mutex_current);
227  oldSnapshotControl->current_timestamp = 0;
228  SpinLockInit(&oldSnapshotControl->mutex_latest_xmin);
229  oldSnapshotControl->latest_xmin = InvalidTransactionId;
230  oldSnapshotControl->next_map_update = 0;
231  SpinLockInit(&oldSnapshotControl->mutex_threshold);
232  oldSnapshotControl->threshold_timestamp = 0;
233  oldSnapshotControl->threshold_xid = InvalidTransactionId;
234  oldSnapshotControl->head_offset = 0;
235  oldSnapshotControl->head_timestamp = 0;
236  oldSnapshotControl->count_used = 0;
237  }
238 }
239 
240 /*
241  * GetTransactionSnapshot
242  * Get the appropriate snapshot for a new query in a transaction.
243  *
244  * Note that the return value may point at static storage that will be modified
245  * by future calls and by CommandCounterIncrement(). Callers should call
246  * RegisterSnapshot or PushActiveSnapshot on the returned snap if it is to be
247  * used very long.
248  */
249 Snapshot
251 {
252  /*
253  * Return historic snapshot if doing logical decoding. We'll never need a
254  * non-historic transaction snapshot in this (sub-)transaction, so there's
255  * no need to be careful to set one up for later calls to
256  * GetTransactionSnapshot().
257  */
259  {
261  return HistoricSnapshot;
262  }
263 
264  /* First call in transaction? */
265  if (!FirstSnapshotSet)
266  {
267  /*
268  * Don't allow catalog snapshot to be older than xact snapshot. Must
269  * do this first to allow the empty-heap Assert to succeed.
270  */
272 
273  Assert(pairingheap_is_empty(&RegisteredSnapshots));
274  Assert(FirstXactSnapshot == NULL);
275 
276  if (IsInParallelMode())
277  elog(ERROR,
278  "cannot take query snapshot during a parallel operation");
279 
280  /*
281  * In transaction-snapshot mode, the first snapshot must live until
282  * end of xact regardless of what the caller does with it, so we must
283  * make a copy of it rather than returning CurrentSnapshotData
284  * directly. Furthermore, if we're running in serializable mode,
285  * predicate.c needs to wrap the snapshot fetch in its own processing.
286  */
288  {
289  /* First, create the snapshot in CurrentSnapshotData */
291  CurrentSnapshot = GetSerializableTransactionSnapshot(&CurrentSnapshotData);
292  else
293  CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);
294  /* Make a saved copy */
295  CurrentSnapshot = CopySnapshot(CurrentSnapshot);
296  FirstXactSnapshot = CurrentSnapshot;
297  /* Mark it as "registered" in FirstXactSnapshot */
298  FirstXactSnapshot->regd_count++;
299  pairingheap_add(&RegisteredSnapshots, &FirstXactSnapshot->ph_node);
300  }
301  else
302  CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);
303 
304  FirstSnapshotSet = true;
305  return CurrentSnapshot;
306  }
307 
309  return CurrentSnapshot;
310 
311  /* Don't allow catalog snapshot to be older than xact snapshot. */
313 
314  CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);
315 
316  return CurrentSnapshot;
317 }
318 
319 /*
320  * GetLatestSnapshot
321  * Get a snapshot that is up-to-date as of the current instant,
322  * even if we are executing in transaction-snapshot mode.
323  */
324 Snapshot
326 {
327  /*
328  * We might be able to relax this, but nothing that could otherwise work
329  * needs it.
330  */
331  if (IsInParallelMode())
332  elog(ERROR,
333  "cannot update SecondarySnapshot during a parallel operation");
334 
335  /*
336  * So far there are no cases requiring support for GetLatestSnapshot()
337  * during logical decoding, but it wouldn't be hard to add if required.
338  */
340 
341  /* If first call in transaction, go ahead and set the xact snapshot */
342  if (!FirstSnapshotSet)
343  return GetTransactionSnapshot();
344 
345  SecondarySnapshot = GetSnapshotData(&SecondarySnapshotData);
346 
347  return SecondarySnapshot;
348 }
349 
350 /*
351  * GetOldestSnapshot
352  *
353  * Get the transaction's oldest known snapshot, as judged by the LSN.
354  * Will return NULL if there are no active or registered snapshots.
355  */
356 Snapshot
358 {
359  Snapshot OldestRegisteredSnapshot = NULL;
360  XLogRecPtr RegisteredLSN = InvalidXLogRecPtr;
361 
362  if (!pairingheap_is_empty(&RegisteredSnapshots))
363  {
364  OldestRegisteredSnapshot = pairingheap_container(SnapshotData, ph_node,
365  pairingheap_first(&RegisteredSnapshots));
366  RegisteredLSN = OldestRegisteredSnapshot->lsn;
367  }
368 
369  if (OldestActiveSnapshot != NULL)
370  {
371  XLogRecPtr ActiveLSN = OldestActiveSnapshot->as_snap->lsn;
372 
373  if (XLogRecPtrIsInvalid(RegisteredLSN) || RegisteredLSN > ActiveLSN)
374  return OldestActiveSnapshot->as_snap;
375  }
376 
377  return OldestRegisteredSnapshot;
378 }
379 
380 /*
381  * GetCatalogSnapshot
382  * Get a snapshot that is sufficiently up-to-date for scan of the
383  * system catalog with the specified OID.
384  */
385 Snapshot
387 {
388  /*
389  * Return historic snapshot while we're doing logical decoding, so we can
390  * see the appropriate state of the catalog.
391  *
392  * This is the primary reason for needing to reset the system caches after
393  * finishing decoding.
394  */
396  return HistoricSnapshot;
397 
398  return GetNonHistoricCatalogSnapshot(relid);
399 }
400 
401 /*
402  * GetNonHistoricCatalogSnapshot
403  * Get a snapshot that is sufficiently up-to-date for scan of the system
404  * catalog with the specified OID, even while historic snapshots are set
405  * up.
406  */
407 Snapshot
409 {
410  /*
411  * If the caller is trying to scan a relation that has no syscache, no
412  * catcache invalidations will be sent when it is updated. For a few key
413  * relations, snapshot invalidations are sent instead. If we're trying to
414  * scan a relation for which neither catcache nor snapshot invalidations
415  * are sent, we must refresh the snapshot every time.
416  */
417  if (CatalogSnapshot &&
419  !RelationHasSysCache(relid))
421 
422  if (CatalogSnapshot == NULL)
423  {
424  /* Get new snapshot. */
425  CatalogSnapshot = GetSnapshotData(&CatalogSnapshotData);
426 
427  /*
428  * Make sure the catalog snapshot will be accounted for in decisions
429  * about advancing PGPROC->xmin. We could apply RegisterSnapshot, but
430  * that would result in making a physical copy, which is overkill; and
431  * it would also create a dependency on some resource owner, which we
432  * do not want for reasons explained at the head of this file. Instead
433  * just shove the CatalogSnapshot into the pairing heap manually. This
434  * has to be reversed in InvalidateCatalogSnapshot, of course.
435  *
436  * NB: it had better be impossible for this to throw error, since the
437  * CatalogSnapshot pointer is already valid.
438  */
439  pairingheap_add(&RegisteredSnapshots, &CatalogSnapshot->ph_node);
440  }
441 
442  return CatalogSnapshot;
443 }
444 
445 /*
446  * InvalidateCatalogSnapshot
447  * Mark the current catalog snapshot, if any, as invalid
448  *
449  * We could change this API to allow the caller to provide more fine-grained
450  * invalidation details, so that a change to relation A wouldn't prevent us
451  * from using our cached snapshot to scan relation B, but so far there's no
452  * evidence that the CPU cycles we spent tracking such fine details would be
453  * well-spent.
454  */
455 void
457 {
458  if (CatalogSnapshot)
459  {
460  pairingheap_remove(&RegisteredSnapshots, &CatalogSnapshot->ph_node);
461  CatalogSnapshot = NULL;
463  }
464 }
465 
466 /*
467  * InvalidateCatalogSnapshotConditionally
468  * Drop catalog snapshot if it's the only one we have
469  *
470  * This is called when we are about to wait for client input, so we don't
471  * want to continue holding the catalog snapshot if it might mean that the
472  * global xmin horizon can't advance. However, if there are other snapshots
473  * still active or registered, the catalog snapshot isn't likely to be the
474  * oldest one, so we might as well keep it.
475  */
476 void
478 {
479  if (CatalogSnapshot &&
480  ActiveSnapshot == NULL &&
481  pairingheap_is_singular(&RegisteredSnapshots))
483 }
484 
485 /*
486  * SnapshotSetCommandId
487  * Propagate CommandCounterIncrement into the static snapshots, if set
488  */
489 void
491 {
492  if (!FirstSnapshotSet)
493  return;
494 
495  if (CurrentSnapshot)
496  CurrentSnapshot->curcid = curcid;
497  if (SecondarySnapshot)
498  SecondarySnapshot->curcid = curcid;
499  /* Should we do the same with CatalogSnapshot? */
500 }
501 
502 /*
503  * SetTransactionSnapshot
504  * Set the transaction's snapshot from an imported MVCC snapshot.
505  *
506  * Note that this is very closely tied to GetTransactionSnapshot --- it
507  * must take care of all the same considerations as the first-snapshot case
508  * in GetTransactionSnapshot.
509  */
510 static void
512  int sourcepid, PGPROC *sourceproc)
513 {
514  /* Caller should have checked this already */
516 
517  /* Better do this to ensure following Assert succeeds. */
519 
520  Assert(pairingheap_is_empty(&RegisteredSnapshots));
521  Assert(FirstXactSnapshot == NULL);
523 
524  /*
525  * Even though we are not going to use the snapshot it computes, we must
526  * call GetSnapshotData, for two reasons: (1) to be sure that
527  * CurrentSnapshotData's XID arrays have been allocated, and (2) to update
528  * the state for GlobalVis*.
529  */
530  CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);
531 
532  /*
533  * Now copy appropriate fields from the source snapshot.
534  */
535  CurrentSnapshot->xmin = sourcesnap->xmin;
536  CurrentSnapshot->xmax = sourcesnap->xmax;
537  CurrentSnapshot->xcnt = sourcesnap->xcnt;
538  Assert(sourcesnap->xcnt <= GetMaxSnapshotXidCount());
539  memcpy(CurrentSnapshot->xip, sourcesnap->xip,
540  sourcesnap->xcnt * sizeof(TransactionId));
541  CurrentSnapshot->subxcnt = sourcesnap->subxcnt;
542  Assert(sourcesnap->subxcnt <= GetMaxSnapshotSubxidCount());
543  memcpy(CurrentSnapshot->subxip, sourcesnap->subxip,
544  sourcesnap->subxcnt * sizeof(TransactionId));
545  CurrentSnapshot->suboverflowed = sourcesnap->suboverflowed;
546  CurrentSnapshot->takenDuringRecovery = sourcesnap->takenDuringRecovery;
547  /* NB: curcid should NOT be copied, it's a local matter */
548 
549  CurrentSnapshot->snapXactCompletionCount = 0;
550 
551  /*
552  * Now we have to fix what GetSnapshotData did with MyProc->xmin and
553  * TransactionXmin. There is a race condition: to make sure we are not
554  * causing the global xmin to go backwards, we have to test that the
555  * source transaction is still running, and that has to be done
556  * atomically. So let procarray.c do it.
557  *
558  * Note: in serializable mode, predicate.c will do this a second time. It
559  * doesn't seem worth contorting the logic here to avoid two calls,
560  * especially since it's not clear that predicate.c *must* do this.
561  */
562  if (sourceproc != NULL)
563  {
564  if (!ProcArrayInstallRestoredXmin(CurrentSnapshot->xmin, sourceproc))
565  ereport(ERROR,
566  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
567  errmsg("could not import the requested snapshot"),
568  errdetail("The source transaction is not running anymore.")));
569  }
570  else if (!ProcArrayInstallImportedXmin(CurrentSnapshot->xmin, sourcevxid))
571  ereport(ERROR,
572  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
573  errmsg("could not import the requested snapshot"),
574  errdetail("The source process with PID %d is not running anymore.",
575  sourcepid)));
576 
577  /*
578  * In transaction-snapshot mode, the first snapshot must live until end of
579  * xact, so we must make a copy of it. Furthermore, if we're running in
580  * serializable mode, predicate.c needs to do its own processing.
581  */
583  {
585  SetSerializableTransactionSnapshot(CurrentSnapshot, sourcevxid,
586  sourcepid);
587  /* Make a saved copy */
588  CurrentSnapshot = CopySnapshot(CurrentSnapshot);
589  FirstXactSnapshot = CurrentSnapshot;
590  /* Mark it as "registered" in FirstXactSnapshot */
591  FirstXactSnapshot->regd_count++;
592  pairingheap_add(&RegisteredSnapshots, &FirstXactSnapshot->ph_node);
593  }
594 
595  FirstSnapshotSet = true;
596 }
597 
598 /*
599  * CopySnapshot
600  * Copy the given snapshot.
601  *
602  * The copy is palloc'd in TopTransactionContext and has initial refcounts set
603  * to 0. The returned snapshot has the copied flag set.
604  */
605 static Snapshot
607 {
608  Snapshot newsnap;
609  Size subxipoff;
610  Size size;
611 
612  Assert(snapshot != InvalidSnapshot);
613 
614  /* We allocate any XID arrays needed in the same palloc block. */
615  size = subxipoff = sizeof(SnapshotData) +
616  snapshot->xcnt * sizeof(TransactionId);
617  if (snapshot->subxcnt > 0)
618  size += snapshot->subxcnt * sizeof(TransactionId);
619 
621  memcpy(newsnap, snapshot, sizeof(SnapshotData));
622 
623  newsnap->regd_count = 0;
624  newsnap->active_count = 0;
625  newsnap->copied = true;
626  newsnap->snapXactCompletionCount = 0;
627 
628  /* setup XID array */
629  if (snapshot->xcnt > 0)
630  {
631  newsnap->xip = (TransactionId *) (newsnap + 1);
632  memcpy(newsnap->xip, snapshot->xip,
633  snapshot->xcnt * sizeof(TransactionId));
634  }
635  else
636  newsnap->xip = NULL;
637 
638  /*
639  * Setup subXID array. Don't bother to copy it if it had overflowed,
640  * though, because it's not used anywhere in that case. Except if it's a
641  * snapshot taken during recovery; all the top-level XIDs are in subxip as
642  * well in that case, so we mustn't lose them.
643  */
644  if (snapshot->subxcnt > 0 &&
645  (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
646  {
647  newsnap->subxip = (TransactionId *) ((char *) newsnap + subxipoff);
648  memcpy(newsnap->subxip, snapshot->subxip,
649  snapshot->subxcnt * sizeof(TransactionId));
650  }
651  else
652  newsnap->subxip = NULL;
653 
654  return newsnap;
655 }
656 
657 /*
658  * FreeSnapshot
659  * Free the memory associated with a snapshot.
660  */
661 static void
663 {
664  Assert(snapshot->regd_count == 0);
665  Assert(snapshot->active_count == 0);
666  Assert(snapshot->copied);
667 
668  pfree(snapshot);
669 }
670 
671 /*
672  * PushActiveSnapshot
673  * Set the given snapshot as the current active snapshot
674  *
675  * If the passed snapshot is a statically-allocated one, or it is possibly
676  * subject to a future command counter update, create a new long-lived copy
677  * with active refcount=1. Otherwise, only increment the refcount.
678  */
679 void
681 {
682  ActiveSnapshotElt *newactive;
683 
684  Assert(snap != InvalidSnapshot);
685 
687 
688  /*
689  * Checking SecondarySnapshot is probably useless here, but it seems
690  * better to be sure.
691  */
692  if (snap == CurrentSnapshot || snap == SecondarySnapshot || !snap->copied)
693  newactive->as_snap = CopySnapshot(snap);
694  else
695  newactive->as_snap = snap;
696 
697  newactive->as_next = ActiveSnapshot;
699 
700  newactive->as_snap->active_count++;
701 
702  ActiveSnapshot = newactive;
703  if (OldestActiveSnapshot == NULL)
704  OldestActiveSnapshot = ActiveSnapshot;
705 }
706 
707 /*
708  * PushCopiedSnapshot
709  * As above, except forcibly copy the presented snapshot.
710  *
711  * This should be used when the ActiveSnapshot has to be modifiable, for
712  * example if the caller intends to call UpdateActiveSnapshotCommandId.
713  * The new snapshot will be released when popped from the stack.
714  */
715 void
717 {
718  PushActiveSnapshot(CopySnapshot(snapshot));
719 }
720 
721 /*
722  * UpdateActiveSnapshotCommandId
723  *
724  * Update the current CID of the active snapshot. This can only be applied
725  * to a snapshot that is not referenced elsewhere.
726  */
727 void
729 {
730  CommandId save_curcid,
731  curcid;
732 
733  Assert(ActiveSnapshot != NULL);
734  Assert(ActiveSnapshot->as_snap->active_count == 1);
735  Assert(ActiveSnapshot->as_snap->regd_count == 0);
736 
737  /*
738  * Don't allow modification of the active snapshot during parallel
739  * operation. We share the snapshot to worker backends at the beginning
740  * of parallel operation, so any change to the snapshot can lead to
741  * inconsistencies. We have other defenses against
742  * CommandCounterIncrement, but there are a few places that call this
743  * directly, so we put an additional guard here.
744  */
745  save_curcid = ActiveSnapshot->as_snap->curcid;
746  curcid = GetCurrentCommandId(false);
747  if (IsInParallelMode() && save_curcid != curcid)
748  elog(ERROR, "cannot modify commandid in active snapshot during a parallel operation");
749  ActiveSnapshot->as_snap->curcid = curcid;
750 }
751 
752 /*
753  * PopActiveSnapshot
754  *
755  * Remove the topmost snapshot from the active snapshot stack, decrementing the
756  * reference count, and free it if this was the last reference.
757  */
758 void
760 {
761  ActiveSnapshotElt *newstack;
762 
763  newstack = ActiveSnapshot->as_next;
764 
765  Assert(ActiveSnapshot->as_snap->active_count > 0);
766 
767  ActiveSnapshot->as_snap->active_count--;
768 
769  if (ActiveSnapshot->as_snap->active_count == 0 &&
770  ActiveSnapshot->as_snap->regd_count == 0)
771  FreeSnapshot(ActiveSnapshot->as_snap);
772 
773  pfree(ActiveSnapshot);
774  ActiveSnapshot = newstack;
775  if (ActiveSnapshot == NULL)
776  OldestActiveSnapshot = NULL;
777 
779 }
780 
781 /*
782  * GetActiveSnapshot
783  * Return the topmost snapshot in the Active stack.
784  */
785 Snapshot
787 {
788  Assert(ActiveSnapshot != NULL);
789 
790  return ActiveSnapshot->as_snap;
791 }
792 
793 /*
794  * ActiveSnapshotSet
795  * Return whether there is at least one snapshot in the Active stack
796  */
797 bool
799 {
800  return ActiveSnapshot != NULL;
801 }
802 
803 /*
804  * RegisterSnapshot
805  * Register a snapshot as being in use by the current resource owner
806  *
807  * If InvalidSnapshot is passed, it is not registered.
808  */
809 Snapshot
811 {
812  if (snapshot == InvalidSnapshot)
813  return InvalidSnapshot;
814 
816 }
817 
818 /*
819  * RegisterSnapshotOnOwner
820  * As above, but use the specified resource owner
821  */
822 Snapshot
824 {
825  Snapshot snap;
826 
827  if (snapshot == InvalidSnapshot)
828  return InvalidSnapshot;
829 
830  /* Static snapshot? Create a persistent copy */
831  snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
832 
833  /* and tell resowner.c about it */
835  snap->regd_count++;
836  ResourceOwnerRememberSnapshot(owner, snap);
837 
838  if (snap->regd_count == 1)
839  pairingheap_add(&RegisteredSnapshots, &snap->ph_node);
840 
841  return snap;
842 }
843 
844 /*
845  * UnregisterSnapshot
846  *
847  * Decrement the reference count of a snapshot, remove the corresponding
848  * reference from CurrentResourceOwner, and free the snapshot if no more
849  * references remain.
850  */
851 void
853 {
854  if (snapshot == NULL)
855  return;
856 
858 }
859 
860 /*
861  * UnregisterSnapshotFromOwner
862  * As above, but use the specified resource owner
863  */
864 void
866 {
867  if (snapshot == NULL)
868  return;
869 
870  Assert(snapshot->regd_count > 0);
871  Assert(!pairingheap_is_empty(&RegisteredSnapshots));
872 
873  ResourceOwnerForgetSnapshot(owner, snapshot);
874 
875  snapshot->regd_count--;
876  if (snapshot->regd_count == 0)
877  pairingheap_remove(&RegisteredSnapshots, &snapshot->ph_node);
878 
879  if (snapshot->regd_count == 0 && snapshot->active_count == 0)
880  {
881  FreeSnapshot(snapshot);
883  }
884 }
885 
886 /*
887  * Comparison function for RegisteredSnapshots heap. Snapshots are ordered
888  * by xmin, so that the snapshot with smallest xmin is at the top.
889  */
890 static int
891 xmin_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
892 {
893  const SnapshotData *asnap = pairingheap_const_container(SnapshotData, ph_node, a);
894  const SnapshotData *bsnap = pairingheap_const_container(SnapshotData, ph_node, b);
895 
896  if (TransactionIdPrecedes(asnap->xmin, bsnap->xmin))
897  return 1;
898  else if (TransactionIdFollows(asnap->xmin, bsnap->xmin))
899  return -1;
900  else
901  return 0;
902 }
903 
904 /*
905  * SnapshotResetXmin
906  *
907  * If there are no more snapshots, we can reset our PGPROC->xmin to InvalidXid.
908  * Note we can do this without locking because we assume that storing an Xid
909  * is atomic.
910  *
911  * Even if there are some remaining snapshots, we may be able to advance our
912  * PGPROC->xmin to some degree. This typically happens when a portal is
913  * dropped. For efficiency, we only consider recomputing PGPROC->xmin when
914  * the active snapshot stack is empty; this allows us not to need to track
915  * which active snapshot is oldest.
916  *
917  * Note: it's tempting to use GetOldestSnapshot() here so that we can include
918  * active snapshots in the calculation. However, that compares by LSN not
919  * xmin so it's not entirely clear that it's the same thing. Also, we'd be
920  * critically dependent on the assumption that the bottommost active snapshot
921  * stack entry has the oldest xmin. (Current uses of GetOldestSnapshot() are
922  * not actually critical, but this would be.)
923  */
924 static void
926 {
927  Snapshot minSnapshot;
928 
929  if (ActiveSnapshot != NULL)
930  return;
931 
932  if (pairingheap_is_empty(&RegisteredSnapshots))
933  {
935  return;
936  }
937 
938  minSnapshot = pairingheap_container(SnapshotData, ph_node,
939  pairingheap_first(&RegisteredSnapshots));
940 
941  if (TransactionIdPrecedes(MyProc->xmin, minSnapshot->xmin))
942  MyProc->xmin = minSnapshot->xmin;
943 }
944 
945 /*
946  * AtSubCommit_Snapshot
947  */
948 void
950 {
951  ActiveSnapshotElt *active;
952 
953  /*
954  * Relabel the active snapshots set in this subtransaction as though they
955  * are owned by the parent subxact.
956  */
957  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
958  {
959  if (active->as_level < level)
960  break;
961  active->as_level = level - 1;
962  }
963 }
964 
965 /*
966  * AtSubAbort_Snapshot
967  * Clean up snapshots after a subtransaction abort
968  */
969 void
971 {
972  /* Forget the active snapshots set by this subtransaction */
973  while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
974  {
976 
977  next = ActiveSnapshot->as_next;
978 
979  /*
980  * Decrement the snapshot's active count. If it's still registered or
981  * marked as active by an outer subtransaction, we can't free it yet.
982  */
983  Assert(ActiveSnapshot->as_snap->active_count >= 1);
984  ActiveSnapshot->as_snap->active_count -= 1;
985 
986  if (ActiveSnapshot->as_snap->active_count == 0 &&
987  ActiveSnapshot->as_snap->regd_count == 0)
988  FreeSnapshot(ActiveSnapshot->as_snap);
989 
990  /* and free the stack element */
991  pfree(ActiveSnapshot);
992 
993  ActiveSnapshot = next;
994  if (ActiveSnapshot == NULL)
995  OldestActiveSnapshot = NULL;
996  }
997 
999 }
1000 
1001 /*
1002  * AtEOXact_Snapshot
1003  * Snapshot manager's cleanup function for end of transaction
1004  */
1005 void
1006 AtEOXact_Snapshot(bool isCommit, bool resetXmin)
1007 {
1008  /*
1009  * In transaction-snapshot mode we must release our privately-managed
1010  * reference to the transaction snapshot. We must remove it from
1011  * RegisteredSnapshots to keep the check below happy. But we don't bother
1012  * to do FreeSnapshot, for two reasons: the memory will go away with
1013  * TopTransactionContext anyway, and if someone has left the snapshot
1014  * stacked as active, we don't want the code below to be chasing through a
1015  * dangling pointer.
1016  */
1017  if (FirstXactSnapshot != NULL)
1018  {
1019  Assert(FirstXactSnapshot->regd_count > 0);
1020  Assert(!pairingheap_is_empty(&RegisteredSnapshots));
1021  pairingheap_remove(&RegisteredSnapshots, &FirstXactSnapshot->ph_node);
1022  }
1023  FirstXactSnapshot = NULL;
1024 
1025  /*
1026  * If we exported any snapshots, clean them up.
1027  */
1028  if (exportedSnapshots != NIL)
1029  {
1030  ListCell *lc;
1031 
1032  /*
1033  * Get rid of the files. Unlink failure is only a WARNING because (1)
1034  * it's too late to abort the transaction, and (2) leaving a leaked
1035  * file around has little real consequence anyway.
1036  *
1037  * We also need to remove the snapshots from RegisteredSnapshots to
1038  * prevent a warning below.
1039  *
1040  * As with the FirstXactSnapshot, we don't need to free resources of
1041  * the snapshot itself as it will go away with the memory context.
1042  */
1043  foreach(lc, exportedSnapshots)
1044  {
1045  ExportedSnapshot *esnap = (ExportedSnapshot *) lfirst(lc);
1046 
1047  if (unlink(esnap->snapfile))
1048  elog(WARNING, "could not unlink file \"%s\": %m",
1049  esnap->snapfile);
1050 
1051  pairingheap_remove(&RegisteredSnapshots,
1052  &esnap->snapshot->ph_node);
1053  }
1054 
1055  exportedSnapshots = NIL;
1056  }
1057 
1058  /* Drop catalog snapshot if any */
1060 
1061  /* On commit, complain about leftover snapshots */
1062  if (isCommit)
1063  {
1064  ActiveSnapshotElt *active;
1065 
1066  if (!pairingheap_is_empty(&RegisteredSnapshots))
1067  elog(WARNING, "registered snapshots seem to remain after cleanup");
1068 
1069  /* complain about unpopped active snapshots */
1070  for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1071  elog(WARNING, "snapshot %p still active", active);
1072  }
1073 
1074  /*
1075  * And reset our state. We don't need to free the memory explicitly --
1076  * it'll go away with TopTransactionContext.
1077  */
1078  ActiveSnapshot = NULL;
1079  OldestActiveSnapshot = NULL;
1080  pairingheap_reset(&RegisteredSnapshots);
1081 
1082  CurrentSnapshot = NULL;
1083  SecondarySnapshot = NULL;
1084 
1085  FirstSnapshotSet = false;
1086 
1087  /*
1088  * During normal commit processing, we call ProcArrayEndTransaction() to
1089  * reset the MyProc->xmin. That call happens prior to the call to
1090  * AtEOXact_Snapshot(), so we need not touch xmin here at all.
1091  */
1092  if (resetXmin)
1094 
1095  Assert(resetXmin || MyProc->xmin == 0);
1096 }
1097 
1098 
1099 /*
1100  * ExportSnapshot
1101  * Export the snapshot to a file so that other backends can import it.
1102  * Returns the token (the file name) that can be used to import this
1103  * snapshot.
1104  */
1105 char *
1107 {
1108  TransactionId topXid;
1109  TransactionId *children;
1110  ExportedSnapshot *esnap;
1111  int nchildren;
1112  int addTopXid;
1114  FILE *f;
1115  int i;
1116  MemoryContext oldcxt;
1117  char path[MAXPGPATH];
1118  char pathtmp[MAXPGPATH];
1119 
1120  /*
1121  * It's tempting to call RequireTransactionBlock here, since it's not very
1122  * useful to export a snapshot that will disappear immediately afterwards.
1123  * However, we haven't got enough information to do that, since we don't
1124  * know if we're at top level or not. For example, we could be inside a
1125  * plpgsql function that is going to fire off other transactions via
1126  * dblink. Rather than disallow perfectly legitimate usages, don't make a
1127  * check.
1128  *
1129  * Also note that we don't make any restriction on the transaction's
1130  * isolation level; however, importers must check the level if they are
1131  * serializable.
1132  */
1133 
1134  /*
1135  * Get our transaction ID if there is one, to include in the snapshot.
1136  */
1137  topXid = GetTopTransactionIdIfAny();
1138 
1139  /*
1140  * We cannot export a snapshot from a subtransaction because there's no
1141  * easy way for importers to verify that the same subtransaction is still
1142  * running.
1143  */
1144  if (IsSubTransaction())
1145  ereport(ERROR,
1146  (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1147  errmsg("cannot export a snapshot from a subtransaction")));
1148 
1149  /*
1150  * We do however allow previous committed subtransactions to exist.
1151  * Importers of the snapshot must see them as still running, so get their
1152  * XIDs to add them to the snapshot.
1153  */
1154  nchildren = xactGetCommittedChildren(&children);
1155 
1156  /*
1157  * Generate file path for the snapshot. We start numbering of snapshots
1158  * inside the transaction from 1.
1159  */
1160  snprintf(path, sizeof(path), SNAPSHOT_EXPORT_DIR "/%08X-%08X-%d",
1161  MyProc->backendId, MyProc->lxid, list_length(exportedSnapshots) + 1);
1162 
1163  /*
1164  * Copy the snapshot into TopTransactionContext, add it to the
1165  * exportedSnapshots list, and mark it pseudo-registered. We do this to
1166  * ensure that the snapshot's xmin is honored for the rest of the
1167  * transaction.
1168  */
1169  snapshot = CopySnapshot(snapshot);
1170 
1172  esnap = (ExportedSnapshot *) palloc(sizeof(ExportedSnapshot));
1173  esnap->snapfile = pstrdup(path);
1174  esnap->snapshot = snapshot;
1175  exportedSnapshots = lappend(exportedSnapshots, esnap);
1176  MemoryContextSwitchTo(oldcxt);
1177 
1178  snapshot->regd_count++;
1179  pairingheap_add(&RegisteredSnapshots, &snapshot->ph_node);
1180 
1181  /*
1182  * Fill buf with a text serialization of the snapshot, plus identification
1183  * data about this transaction. The format expected by ImportSnapshot is
1184  * pretty rigid: each line must be fieldname:value.
1185  */
1186  initStringInfo(&buf);
1187 
1188  appendStringInfo(&buf, "vxid:%d/%u\n", MyProc->backendId, MyProc->lxid);
1189  appendStringInfo(&buf, "pid:%d\n", MyProcPid);
1190  appendStringInfo(&buf, "dbid:%u\n", MyDatabaseId);
1191  appendStringInfo(&buf, "iso:%d\n", XactIsoLevel);
1192  appendStringInfo(&buf, "ro:%d\n", XactReadOnly);
1193 
1194  appendStringInfo(&buf, "xmin:%u\n", snapshot->xmin);
1195  appendStringInfo(&buf, "xmax:%u\n", snapshot->xmax);
1196 
1197  /*
1198  * We must include our own top transaction ID in the top-xid data, since
1199  * by definition we will still be running when the importing transaction
1200  * adopts the snapshot, but GetSnapshotData never includes our own XID in
1201  * the snapshot. (There must, therefore, be enough room to add it.)
1202  *
1203  * However, it could be that our topXid is after the xmax, in which case
1204  * we shouldn't include it because xip[] members are expected to be before
1205  * xmax. (We need not make the same check for subxip[] members, see
1206  * snapshot.h.)
1207  */
1208  addTopXid = (TransactionIdIsValid(topXid) &&
1209  TransactionIdPrecedes(topXid, snapshot->xmax)) ? 1 : 0;
1210  appendStringInfo(&buf, "xcnt:%d\n", snapshot->xcnt + addTopXid);
1211  for (i = 0; i < snapshot->xcnt; i++)
1212  appendStringInfo(&buf, "xip:%u\n", snapshot->xip[i]);
1213  if (addTopXid)
1214  appendStringInfo(&buf, "xip:%u\n", topXid);
1215 
1216  /*
1217  * Similarly, we add our subcommitted child XIDs to the subxid data. Here,
1218  * we have to cope with possible overflow.
1219  */
1220  if (snapshot->suboverflowed ||
1221  snapshot->subxcnt + nchildren > GetMaxSnapshotSubxidCount())
1222  appendStringInfoString(&buf, "sof:1\n");
1223  else
1224  {
1225  appendStringInfoString(&buf, "sof:0\n");
1226  appendStringInfo(&buf, "sxcnt:%d\n", snapshot->subxcnt + nchildren);
1227  for (i = 0; i < snapshot->subxcnt; i++)
1228  appendStringInfo(&buf, "sxp:%u\n", snapshot->subxip[i]);
1229  for (i = 0; i < nchildren; i++)
1230  appendStringInfo(&buf, "sxp:%u\n", children[i]);
1231  }
1232  appendStringInfo(&buf, "rec:%u\n", snapshot->takenDuringRecovery);
1233 
1234  /*
1235  * Now write the text representation into a file. We first write to a
1236  * ".tmp" filename, and rename to final filename if no error. This
1237  * ensures that no other backend can read an incomplete file
1238  * (ImportSnapshot won't allow it because of its valid-characters check).
1239  */
1240  snprintf(pathtmp, sizeof(pathtmp), "%s.tmp", path);
1241  if (!(f = AllocateFile(pathtmp, PG_BINARY_W)))
1242  ereport(ERROR,
1244  errmsg("could not create file \"%s\": %m", pathtmp)));
1245 
1246  if (fwrite(buf.data, buf.len, 1, f) != 1)
1247  ereport(ERROR,
1249  errmsg("could not write to file \"%s\": %m", pathtmp)));
1250 
1251  /* no fsync() since file need not survive a system crash */
1252 
1253  if (FreeFile(f))
1254  ereport(ERROR,
1256  errmsg("could not write to file \"%s\": %m", pathtmp)));
1257 
1258  /*
1259  * Now that we have written everything into a .tmp file, rename the file
1260  * to remove the .tmp suffix.
1261  */
1262  if (rename(pathtmp, path) < 0)
1263  ereport(ERROR,
1265  errmsg("could not rename file \"%s\" to \"%s\": %m",
1266  pathtmp, path)));
1267 
1268  /*
1269  * The basename of the file is what we return from pg_export_snapshot().
1270  * It's already in path in a textual format and we know that the path
1271  * starts with SNAPSHOT_EXPORT_DIR. Skip over the prefix and the slash
1272  * and pstrdup it so as not to return the address of a local variable.
1273  */
1274  return pstrdup(path + strlen(SNAPSHOT_EXPORT_DIR) + 1);
1275 }
1276 
1277 /*
1278  * pg_export_snapshot
1279  * SQL-callable wrapper for ExportSnapshot.
1280  */
1281 Datum
1283 {
1284  char *snapshotName;
1285 
1286  snapshotName = ExportSnapshot(GetActiveSnapshot());
1287  PG_RETURN_TEXT_P(cstring_to_text(snapshotName));
1288 }
1289 
1290 
1291 /*
1292  * Parsing subroutines for ImportSnapshot: parse a line with the given
1293  * prefix followed by a value, and advance *s to the next line. The
1294  * filename is provided for use in error messages.
1295  */
1296 static int
1297 parseIntFromText(const char *prefix, char **s, const char *filename)
1298 {
1299  char *ptr = *s;
1300  int prefixlen = strlen(prefix);
1301  int val;
1302 
1303  if (strncmp(ptr, prefix, prefixlen) != 0)
1304  ereport(ERROR,
1305  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1306  errmsg("invalid snapshot data in file \"%s\"", filename)));
1307  ptr += prefixlen;
1308  if (sscanf(ptr, "%d", &val) != 1)
1309  ereport(ERROR,
1310  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1311  errmsg("invalid snapshot data in file \"%s\"", filename)));
1312  ptr = strchr(ptr, '\n');
1313  if (!ptr)
1314  ereport(ERROR,
1315  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1316  errmsg("invalid snapshot data in file \"%s\"", filename)));
1317  *s = ptr + 1;
1318  return val;
1319 }
1320 
1321 static TransactionId
1322 parseXidFromText(const char *prefix, char **s, const char *filename)
1323 {
1324  char *ptr = *s;
1325  int prefixlen = strlen(prefix);
1327 
1328  if (strncmp(ptr, prefix, prefixlen) != 0)
1329  ereport(ERROR,
1330  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1331  errmsg("invalid snapshot data in file \"%s\"", filename)));
1332  ptr += prefixlen;
1333  if (sscanf(ptr, "%u", &val) != 1)
1334  ereport(ERROR,
1335  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1336  errmsg("invalid snapshot data in file \"%s\"", filename)));
1337  ptr = strchr(ptr, '\n');
1338  if (!ptr)
1339  ereport(ERROR,
1340  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1341  errmsg("invalid snapshot data in file \"%s\"", filename)));
1342  *s = ptr + 1;
1343  return val;
1344 }
1345 
1346 static void
1347 parseVxidFromText(const char *prefix, char **s, const char *filename,
1348  VirtualTransactionId *vxid)
1349 {
1350  char *ptr = *s;
1351  int prefixlen = strlen(prefix);
1352 
1353  if (strncmp(ptr, prefix, prefixlen) != 0)
1354  ereport(ERROR,
1355  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1356  errmsg("invalid snapshot data in file \"%s\"", filename)));
1357  ptr += prefixlen;
1358  if (sscanf(ptr, "%d/%u", &vxid->backendId, &vxid->localTransactionId) != 2)
1359  ereport(ERROR,
1360  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1361  errmsg("invalid snapshot data in file \"%s\"", filename)));
1362  ptr = strchr(ptr, '\n');
1363  if (!ptr)
1364  ereport(ERROR,
1365  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1366  errmsg("invalid snapshot data in file \"%s\"", filename)));
1367  *s = ptr + 1;
1368 }
1369 
1370 /*
1371  * ImportSnapshot
1372  * Import a previously exported snapshot. The argument should be a
1373  * filename in SNAPSHOT_EXPORT_DIR. Load the snapshot from that file.
1374  * This is called by "SET TRANSACTION SNAPSHOT 'foo'".
1375  */
1376 void
1377 ImportSnapshot(const char *idstr)
1378 {
1379  char path[MAXPGPATH];
1380  FILE *f;
1381  struct stat stat_buf;
1382  char *filebuf;
1383  int xcnt;
1384  int i;
1385  VirtualTransactionId src_vxid;
1386  int src_pid;
1387  Oid src_dbid;
1388  int src_isolevel;
1389  bool src_readonly;
1390  SnapshotData snapshot;
1391 
1392  /*
1393  * Must be at top level of a fresh transaction. Note in particular that
1394  * we check we haven't acquired an XID --- if we have, it's conceivable
1395  * that the snapshot would show it as not running, making for very screwy
1396  * behavior.
1397  */
1398  if (FirstSnapshotSet ||
1400  IsSubTransaction())
1401  ereport(ERROR,
1402  (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1403  errmsg("SET TRANSACTION SNAPSHOT must be called before any query")));
1404 
1405  /*
1406  * If we are in read committed mode then the next query would execute with
1407  * a new snapshot thus making this function call quite useless.
1408  */
1410  ereport(ERROR,
1411  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1412  errmsg("a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ")));
1413 
1414  /*
1415  * Verify the identifier: only 0-9, A-F and hyphens are allowed. We do
1416  * this mainly to prevent reading arbitrary files.
1417  */
1418  if (strspn(idstr, "0123456789ABCDEF-") != strlen(idstr))
1419  ereport(ERROR,
1420  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1421  errmsg("invalid snapshot identifier: \"%s\"", idstr)));
1422 
1423  /* OK, read the file */
1424  snprintf(path, MAXPGPATH, SNAPSHOT_EXPORT_DIR "/%s", idstr);
1425 
1426  f = AllocateFile(path, PG_BINARY_R);
1427  if (!f)
1428  ereport(ERROR,
1429  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1430  errmsg("invalid snapshot identifier: \"%s\"", idstr)));
1431 
1432  /* get the size of the file so that we know how much memory we need */
1433  if (fstat(fileno(f), &stat_buf))
1434  elog(ERROR, "could not stat file \"%s\": %m", path);
1435 
1436  /* and read the file into a palloc'd string */
1437  filebuf = (char *) palloc(stat_buf.st_size + 1);
1438  if (fread(filebuf, stat_buf.st_size, 1, f) != 1)
1439  elog(ERROR, "could not read file \"%s\": %m", path);
1440 
1441  filebuf[stat_buf.st_size] = '\0';
1442 
1443  FreeFile(f);
1444 
1445  /*
1446  * Construct a snapshot struct by parsing the file content.
1447  */
1448  memset(&snapshot, 0, sizeof(snapshot));
1449 
1450  parseVxidFromText("vxid:", &filebuf, path, &src_vxid);
1451  src_pid = parseIntFromText("pid:", &filebuf, path);
1452  /* we abuse parseXidFromText a bit here ... */
1453  src_dbid = parseXidFromText("dbid:", &filebuf, path);
1454  src_isolevel = parseIntFromText("iso:", &filebuf, path);
1455  src_readonly = parseIntFromText("ro:", &filebuf, path);
1456 
1457  snapshot.snapshot_type = SNAPSHOT_MVCC;
1458 
1459  snapshot.xmin = parseXidFromText("xmin:", &filebuf, path);
1460  snapshot.xmax = parseXidFromText("xmax:", &filebuf, path);
1461 
1462  snapshot.xcnt = xcnt = parseIntFromText("xcnt:", &filebuf, path);
1463 
1464  /* sanity-check the xid count before palloc */
1465  if (xcnt < 0 || xcnt > GetMaxSnapshotXidCount())
1466  ereport(ERROR,
1467  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1468  errmsg("invalid snapshot data in file \"%s\"", path)));
1469 
1470  snapshot.xip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
1471  for (i = 0; i < xcnt; i++)
1472  snapshot.xip[i] = parseXidFromText("xip:", &filebuf, path);
1473 
1474  snapshot.suboverflowed = parseIntFromText("sof:", &filebuf, path);
1475 
1476  if (!snapshot.suboverflowed)
1477  {
1478  snapshot.subxcnt = xcnt = parseIntFromText("sxcnt:", &filebuf, path);
1479 
1480  /* sanity-check the xid count before palloc */
1481  if (xcnt < 0 || xcnt > GetMaxSnapshotSubxidCount())
1482  ereport(ERROR,
1483  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1484  errmsg("invalid snapshot data in file \"%s\"", path)));
1485 
1486  snapshot.subxip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
1487  for (i = 0; i < xcnt; i++)
1488  snapshot.subxip[i] = parseXidFromText("sxp:", &filebuf, path);
1489  }
1490  else
1491  {
1492  snapshot.subxcnt = 0;
1493  snapshot.subxip = NULL;
1494  }
1495 
1496  snapshot.takenDuringRecovery = parseIntFromText("rec:", &filebuf, path);
1497 
1498  /*
1499  * Do some additional sanity checking, just to protect ourselves. We
1500  * don't trouble to check the array elements, just the most critical
1501  * fields.
1502  */
1503  if (!VirtualTransactionIdIsValid(src_vxid) ||
1504  !OidIsValid(src_dbid) ||
1505  !TransactionIdIsNormal(snapshot.xmin) ||
1506  !TransactionIdIsNormal(snapshot.xmax))
1507  ereport(ERROR,
1508  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1509  errmsg("invalid snapshot data in file \"%s\"", path)));
1510 
1511  /*
1512  * If we're serializable, the source transaction must be too, otherwise
1513  * predicate.c has problems (SxactGlobalXmin could go backwards). Also, a
1514  * non-read-only transaction can't adopt a snapshot from a read-only
1515  * transaction, as predicate.c handles the cases very differently.
1516  */
1518  {
1519  if (src_isolevel != XACT_SERIALIZABLE)
1520  ereport(ERROR,
1521  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1522  errmsg("a serializable transaction cannot import a snapshot from a non-serializable transaction")));
1523  if (src_readonly && !XactReadOnly)
1524  ereport(ERROR,
1525  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1526  errmsg("a non-read-only serializable transaction cannot import a snapshot from a read-only transaction")));
1527  }
1528 
1529  /*
1530  * We cannot import a snapshot that was taken in a different database,
1531  * because vacuum calculates OldestXmin on a per-database basis; so the
1532  * source transaction's xmin doesn't protect us from data loss. This
1533  * restriction could be removed if the source transaction were to mark its
1534  * xmin as being globally applicable. But that would require some
1535  * additional syntax, since that has to be known when the snapshot is
1536  * initially taken. (See pgsql-hackers discussion of 2011-10-21.)
1537  */
1538  if (src_dbid != MyDatabaseId)
1539  ereport(ERROR,
1540  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1541  errmsg("cannot import a snapshot from a different database")));
1542 
1543  /* OK, install the snapshot */
1544  SetTransactionSnapshot(&snapshot, &src_vxid, src_pid, NULL);
1545 }
1546 
1547 /*
1548  * XactHasExportedSnapshots
1549  * Test whether current transaction has exported any snapshots.
1550  */
1551 bool
1553 {
1554  return (exportedSnapshots != NIL);
1555 }
1556 
1557 /*
1558  * DeleteAllExportedSnapshotFiles
1559  * Clean up any files that have been left behind by a crashed backend
1560  * that had exported snapshots before it died.
1561  *
1562  * This should be called during database startup or crash recovery.
1563  */
1564 void
1566 {
1567  char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1568  DIR *s_dir;
1569  struct dirent *s_de;
1570 
1571  /*
1572  * Problems in reading the directory, or unlinking files, are reported at
1573  * LOG level. Since we're running in the startup process, ERROR level
1574  * would prevent database start, and it's not important enough for that.
1575  */
1577 
1578  while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
1579  {
1580  if (strcmp(s_de->d_name, ".") == 0 ||
1581  strcmp(s_de->d_name, "..") == 0)
1582  continue;
1583 
1584  snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1585 
1586  if (unlink(buf) != 0)
1587  ereport(LOG,
1589  errmsg("could not remove file \"%s\": %m", buf)));
1590  }
1591 
1592  FreeDir(s_dir);
1593 }
1594 
1595 /*
1596  * ThereAreNoPriorRegisteredSnapshots
1597  * Is the registered snapshot count less than or equal to one?
1598  *
1599  * Don't use this to settle important decisions. While zero registrations and
1600  * no ActiveSnapshot would confirm a certain idleness, the system makes no
1601  * guarantees about the significance of one registered snapshot.
1602  */
1603 bool
1605 {
1606  if (pairingheap_is_empty(&RegisteredSnapshots) ||
1607  pairingheap_is_singular(&RegisteredSnapshots))
1608  return true;
1609 
1610  return false;
1611 }
1612 
1613 
1614 /*
1615  * Return a timestamp that is exactly on a minute boundary.
1616  *
1617  * If the argument is already aligned, return that value, otherwise move to
1618  * the next minute boundary following the given time.
1619  */
1620 static TimestampTz
1622 {
1623  TimestampTz retval = ts + (USECS_PER_MINUTE - 1);
1624 
1625  return retval - (retval % USECS_PER_MINUTE);
1626 }
1627 
1628 /*
1629  * Get current timestamp for snapshots
1630  *
1631  * This is basically GetCurrentTimestamp(), but with a guarantee that
1632  * the result never moves backward.
1633  */
1636 {
1638 
1639  /*
1640  * Don't let time move backward; if it hasn't advanced, use the old value.
1641  */
1642  SpinLockAcquire(&oldSnapshotControl->mutex_current);
1643  if (now <= oldSnapshotControl->current_timestamp)
1644  now = oldSnapshotControl->current_timestamp;
1645  else
1646  oldSnapshotControl->current_timestamp = now;
1647  SpinLockRelease(&oldSnapshotControl->mutex_current);
1648 
1649  return now;
1650 }
1651 
1652 /*
1653  * Get timestamp through which vacuum may have processed based on last stored
1654  * value for threshold_timestamp.
1655  *
1656  * XXX: So far, we never trust that a 64-bit value can be read atomically; if
1657  * that ever changes, we could get rid of the spinlock here.
1658  */
1661 {
1662  TimestampTz threshold_timestamp;
1663 
1664  SpinLockAcquire(&oldSnapshotControl->mutex_threshold);
1665  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1666  SpinLockRelease(&oldSnapshotControl->mutex_threshold);
1667 
1668  return threshold_timestamp;
1669 }
1670 
1671 void
1673 {
1674  SpinLockAcquire(&oldSnapshotControl->mutex_threshold);
1675  Assert(oldSnapshotControl->threshold_timestamp <= ts);
1676  Assert(TransactionIdPrecedesOrEquals(oldSnapshotControl->threshold_xid, xlimit));
1677  oldSnapshotControl->threshold_timestamp = ts;
1678  oldSnapshotControl->threshold_xid = xlimit;
1679  SpinLockRelease(&oldSnapshotControl->mutex_threshold);
1680 }
1681 
1682 /*
1683  * XXX: Magic to keep old_snapshot_threshold tests appear "working". They
1684  * currently are broken, and discussion of what to do about them is
1685  * ongoing. See
1686  * https://www.postgresql.org/message-id/20200403001235.e6jfdll3gh2ygbuc%40alap3.anarazel.de
1687  */
1688 void
1690 {
1692 
1694 
1695  ts -= 5 * USECS_PER_SEC;
1696 
1697  SpinLockAcquire(&oldSnapshotControl->mutex_threshold);
1698  oldSnapshotControl->threshold_timestamp = ts;
1699  SpinLockRelease(&oldSnapshotControl->mutex_threshold);
1700 }
1701 
1702 /*
1703  * If there is a valid mapping for the timestamp, set *xlimitp to
1704  * that. Returns whether there is such a mapping.
1705  */
1706 static bool
1708 {
1709  bool in_mapping = false;
1710 
1712 
1713  LWLockAcquire(OldSnapshotTimeMapLock, LW_SHARED);
1714 
1715  if (oldSnapshotControl->count_used > 0
1716  && ts >= oldSnapshotControl->head_timestamp)
1717  {
1718  int offset;
1719 
1720  offset = ((ts - oldSnapshotControl->head_timestamp)
1721  / USECS_PER_MINUTE);
1722  if (offset > oldSnapshotControl->count_used - 1)
1723  offset = oldSnapshotControl->count_used - 1;
1724  offset = (oldSnapshotControl->head_offset + offset)
1726 
1727  *xlimitp = oldSnapshotControl->xid_by_minute[offset];
1728 
1729  in_mapping = true;
1730  }
1731 
1732  LWLockRelease(OldSnapshotTimeMapLock);
1733 
1734  return in_mapping;
1735 }
1736 
1737 /*
1738  * TransactionIdLimitedForOldSnapshots
1739  *
1740  * Apply old snapshot limit. This is intended to be called for page pruning
1741  * and table vacuuming, to allow old_snapshot_threshold to override the normal
1742  * global xmin value. Actual testing for snapshot too old will be based on
1743  * whether a snapshot timestamp is prior to the threshold timestamp set in
1744  * this function.
1745  *
1746  * If the limited horizon allows a cleanup action that otherwise would not be
1747  * possible, SetOldSnapshotThresholdTimestamp(*limit_ts, *limit_xid) needs to
1748  * be called before that cleanup action.
1749  */
1750 bool
1752  Relation relation,
1753  TransactionId *limit_xid,
1754  TimestampTz *limit_ts)
1755 {
1756  TimestampTz ts;
1757  TransactionId xlimit = recentXmin;
1758  TransactionId latest_xmin;
1759  TimestampTz next_map_update_ts;
1760  TransactionId threshold_timestamp;
1761  TransactionId threshold_xid;
1762 
1763  Assert(TransactionIdIsNormal(recentXmin));
1765  Assert(limit_ts != NULL && limit_xid != NULL);
1766 
1767  if (!RelationAllowsEarlyPruning(relation))
1768  return false;
1769 
1771 
1772  SpinLockAcquire(&oldSnapshotControl->mutex_latest_xmin);
1773  latest_xmin = oldSnapshotControl->latest_xmin;
1774  next_map_update_ts = oldSnapshotControl->next_map_update;
1775  SpinLockRelease(&oldSnapshotControl->mutex_latest_xmin);
1776 
1777  /*
1778  * Zero threshold always overrides to latest xmin, if valid. Without some
1779  * heuristic it will find its own snapshot too old on, for example, a
1780  * simple UPDATE -- which would make it useless for most testing, but
1781  * there is no principled way to ensure that it doesn't fail in this way.
1782  * Use a five-second delay to try to get useful testing behavior, but this
1783  * may need adjustment.
1784  */
1785  if (old_snapshot_threshold == 0)
1786  {
1787  if (TransactionIdPrecedes(latest_xmin, MyProc->xmin)
1788  && TransactionIdFollows(latest_xmin, xlimit))
1789  xlimit = latest_xmin;
1790 
1791  ts -= 5 * USECS_PER_SEC;
1792  }
1793  else
1794  {
1797 
1798  /* Check for fast exit without LW locking. */
1799  SpinLockAcquire(&oldSnapshotControl->mutex_threshold);
1800  threshold_timestamp = oldSnapshotControl->threshold_timestamp;
1801  threshold_xid = oldSnapshotControl->threshold_xid;
1802  SpinLockRelease(&oldSnapshotControl->mutex_threshold);
1803 
1804  if (ts == threshold_timestamp)
1805  {
1806  /*
1807  * Current timestamp is in same bucket as the last limit that
1808  * was applied. Reuse.
1809  */
1810  xlimit = threshold_xid;
1811  }
1812  else if (ts == next_map_update_ts)
1813  {
1814  /*
1815  * FIXME: This branch is super iffy - but that should probably
1816  * fixed separately.
1817  */
1818  xlimit = latest_xmin;
1819  }
1820  else if (GetOldSnapshotFromTimeMapping(ts, &xlimit))
1821  {
1822  }
1823 
1824  /*
1825  * Failsafe protection against vacuuming work of active transaction.
1826  *
1827  * This is not an assertion because we avoid the spinlock for
1828  * performance, leaving open the possibility that xlimit could advance
1829  * and be more current; but it seems prudent to apply this limit. It
1830  * might make pruning a tiny bit less aggressive than it could be, but
1831  * protects against data loss bugs.
1832  */
1833  if (TransactionIdIsNormal(latest_xmin)
1834  && TransactionIdPrecedes(latest_xmin, xlimit))
1835  xlimit = latest_xmin;
1836  }
1837 
1838  if (TransactionIdIsValid(xlimit) &&
1839  TransactionIdFollowsOrEquals(xlimit, recentXmin))
1840  {
1841  *limit_ts = ts;
1842  *limit_xid = xlimit;
1843 
1844  return true;
1845  }
1846 
1847  return false;
1848 }
1849 
1850 /*
1851  * Take care of the circular buffer that maps time to xid.
1852  */
1853 void
1855 {
1856  TimestampTz ts;
1857  TransactionId latest_xmin;
1858  TimestampTz update_ts;
1859  bool map_update_required = false;
1860 
1861  /* Never call this function when old snapshot checking is disabled. */
1863 
1864  ts = AlignTimestampToMinuteBoundary(whenTaken);
1865 
1866  /*
1867  * Keep track of the latest xmin seen by any process. Update mapping with
1868  * a new value when we have crossed a bucket boundary.
1869  */
1870  SpinLockAcquire(&oldSnapshotControl->mutex_latest_xmin);
1871  latest_xmin = oldSnapshotControl->latest_xmin;
1872  update_ts = oldSnapshotControl->next_map_update;
1873  if (ts > update_ts)
1874  {
1875  oldSnapshotControl->next_map_update = ts;
1876  map_update_required = true;
1877  }
1878  if (TransactionIdFollows(xmin, latest_xmin))
1879  oldSnapshotControl->latest_xmin = xmin;
1880  SpinLockRelease(&oldSnapshotControl->mutex_latest_xmin);
1881 
1882  /* We only needed to update the most recent xmin value. */
1883  if (!map_update_required)
1884  return;
1885 
1886  /* No further tracking needed for 0 (used for testing). */
1887  if (old_snapshot_threshold == 0)
1888  return;
1889 
1890  /*
1891  * We don't want to do something stupid with unusual values, but we don't
1892  * want to litter the log with warnings or break otherwise normal
1893  * processing for this feature; so if something seems unreasonable, just
1894  * log at DEBUG level and return without doing anything.
1895  */
1896  if (whenTaken < 0)
1897  {
1898  elog(DEBUG1,
1899  "MaintainOldSnapshotTimeMapping called with negative whenTaken = %ld",
1900  (long) whenTaken);
1901  return;
1902  }
1903  if (!TransactionIdIsNormal(xmin))
1904  {
1905  elog(DEBUG1,
1906  "MaintainOldSnapshotTimeMapping called with xmin = %lu",
1907  (unsigned long) xmin);
1908  return;
1909  }
1910 
1911  LWLockAcquire(OldSnapshotTimeMapLock, LW_EXCLUSIVE);
1912 
1913  Assert(oldSnapshotControl->head_offset >= 0);
1914  Assert(oldSnapshotControl->head_offset < OLD_SNAPSHOT_TIME_MAP_ENTRIES);
1915  Assert((oldSnapshotControl->head_timestamp % USECS_PER_MINUTE) == 0);
1916  Assert(oldSnapshotControl->count_used >= 0);
1917  Assert(oldSnapshotControl->count_used <= OLD_SNAPSHOT_TIME_MAP_ENTRIES);
1918 
1919  if (oldSnapshotControl->count_used == 0)
1920  {
1921  /* set up first entry for empty mapping */
1922  oldSnapshotControl->head_offset = 0;
1923  oldSnapshotControl->head_timestamp = ts;
1924  oldSnapshotControl->count_used = 1;
1925  oldSnapshotControl->xid_by_minute[0] = xmin;
1926  }
1927  else if (ts < oldSnapshotControl->head_timestamp)
1928  {
1929  /* old ts; log it at DEBUG */
1930  LWLockRelease(OldSnapshotTimeMapLock);
1931  elog(DEBUG1,
1932  "MaintainOldSnapshotTimeMapping called with old whenTaken = %ld",
1933  (long) whenTaken);
1934  return;
1935  }
1936  else if (ts <= (oldSnapshotControl->head_timestamp +
1937  ((oldSnapshotControl->count_used - 1)
1938  * USECS_PER_MINUTE)))
1939  {
1940  /* existing mapping; advance xid if possible */
1941  int bucket = (oldSnapshotControl->head_offset
1942  + ((ts - oldSnapshotControl->head_timestamp)
1943  / USECS_PER_MINUTE))
1945 
1946  if (TransactionIdPrecedes(oldSnapshotControl->xid_by_minute[bucket], xmin))
1947  oldSnapshotControl->xid_by_minute[bucket] = xmin;
1948  }
1949  else
1950  {
1951  /* We need a new bucket, but it might not be the very next one. */
1952  int distance_to_new_tail;
1953  int distance_to_current_tail;
1954  int advance;
1955 
1956  /*
1957  * Our goal is for the new "tail" of the mapping, that is, the entry
1958  * which is newest and thus furthest from the "head" entry, to
1959  * correspond to "ts". Since there's one entry per minute, the
1960  * distance between the current head and the new tail is just the
1961  * number of minutes of difference between ts and the current
1962  * head_timestamp.
1963  *
1964  * The distance from the current head to the current tail is one
1965  * less than the number of entries in the mapping, because the
1966  * entry at the head_offset is for 0 minutes after head_timestamp.
1967  *
1968  * The difference between these two values is the number of minutes
1969  * by which we need to advance the mapping, either adding new entries
1970  * or rotating old ones out.
1971  */
1972  distance_to_new_tail =
1973  (ts - oldSnapshotControl->head_timestamp) / USECS_PER_MINUTE;
1974  distance_to_current_tail =
1975  oldSnapshotControl->count_used - 1;
1976  advance = distance_to_new_tail - distance_to_current_tail;
1977  Assert(advance > 0);
1978 
1979  if (advance >= OLD_SNAPSHOT_TIME_MAP_ENTRIES)
1980  {
1981  /* Advance is so far that all old data is junk; start over. */
1982  oldSnapshotControl->head_offset = 0;
1983  oldSnapshotControl->count_used = 1;
1984  oldSnapshotControl->xid_by_minute[0] = xmin;
1985  oldSnapshotControl->head_timestamp = ts;
1986  }
1987  else
1988  {
1989  /* Store the new value in one or more buckets. */
1990  int i;
1991 
1992  for (i = 0; i < advance; i++)
1993  {
1994  if (oldSnapshotControl->count_used == OLD_SNAPSHOT_TIME_MAP_ENTRIES)
1995  {
1996  /* Map full and new value replaces old head. */
1997  int old_head = oldSnapshotControl->head_offset;
1998 
1999  if (old_head == (OLD_SNAPSHOT_TIME_MAP_ENTRIES - 1))
2000  oldSnapshotControl->head_offset = 0;
2001  else
2002  oldSnapshotControl->head_offset = old_head + 1;
2003  oldSnapshotControl->xid_by_minute[old_head] = xmin;
2004  oldSnapshotControl->head_timestamp += USECS_PER_MINUTE;
2005  }
2006  else
2007  {
2008  /* Extend map to unused entry. */
2009  int new_tail = (oldSnapshotControl->head_offset
2010  + oldSnapshotControl->count_used)
2012 
2013  oldSnapshotControl->count_used++;
2014  oldSnapshotControl->xid_by_minute[new_tail] = xmin;
2015  }
2016  }
2017  }
2018  }
2019 
2020  LWLockRelease(OldSnapshotTimeMapLock);
2021 }
2022 
2023 
2024 /*
2025  * Setup a snapshot that replaces normal catalog snapshots that allows catalog
2026  * access to behave just like it did at a certain point in the past.
2027  *
2028  * Needed for logical decoding.
2029  */
2030 void
2031 SetupHistoricSnapshot(Snapshot historic_snapshot, HTAB *tuplecids)
2032 {
2033  Assert(historic_snapshot != NULL);
2034 
2035  /* setup the timetravel snapshot */
2036  HistoricSnapshot = historic_snapshot;
2037 
2038  /* setup (cmin, cmax) lookup hash */
2039  tuplecid_data = tuplecids;
2040 }
2041 
2042 
2043 /*
2044  * Make catalog snapshots behave normally again.
2045  */
2046 void
2048 {
2049  HistoricSnapshot = NULL;
2050  tuplecid_data = NULL;
2051 }
2052 
2053 bool
2055 {
2056  return HistoricSnapshot != NULL;
2057 }
2058 
2059 HTAB *
2061 {
2063  return tuplecid_data;
2064 }
2065 
2066 /*
2067  * EstimateSnapshotSpace
2068  * Returns the size needed to store the given snapshot.
2069  *
2070  * We are exporting only required fields from the Snapshot, stored in
2071  * SerializedSnapshotData.
2072  */
2073 Size
2075 {
2076  Size size;
2077 
2078  Assert(snap != InvalidSnapshot);
2080 
2081  /* We allocate any XID arrays needed in the same palloc block. */
2082  size = add_size(sizeof(SerializedSnapshotData),
2083  mul_size(snap->xcnt, sizeof(TransactionId)));
2084  if (snap->subxcnt > 0 &&
2085  (!snap->suboverflowed || snap->takenDuringRecovery))
2086  size = add_size(size,
2087  mul_size(snap->subxcnt, sizeof(TransactionId)));
2088 
2089  return size;
2090 }
2091 
2092 /*
2093  * SerializeSnapshot
2094  * Dumps the serialized snapshot (extracted from given snapshot) onto the
2095  * memory location at start_address.
2096  */
2097 void
2098 SerializeSnapshot(Snapshot snapshot, char *start_address)
2099 {
2100  SerializedSnapshotData serialized_snapshot;
2101 
2102  Assert(snapshot->subxcnt >= 0);
2103 
2104  /* Copy all required fields */
2105  serialized_snapshot.xmin = snapshot->xmin;
2106  serialized_snapshot.xmax = snapshot->xmax;
2107  serialized_snapshot.xcnt = snapshot->xcnt;
2108  serialized_snapshot.subxcnt = snapshot->subxcnt;
2109  serialized_snapshot.suboverflowed = snapshot->suboverflowed;
2110  serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
2111  serialized_snapshot.curcid = snapshot->curcid;
2112  serialized_snapshot.whenTaken = snapshot->whenTaken;
2113  serialized_snapshot.lsn = snapshot->lsn;
2114 
2115  /*
2116  * Ignore the SubXID array if it has overflowed, unless the snapshot was
2117  * taken during recovery - in that case, top-level XIDs are in subxip as
2118  * well, and we mustn't lose them.
2119  */
2120  if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
2121  serialized_snapshot.subxcnt = 0;
2122 
2123  /* Copy struct to possibly-unaligned buffer */
2124  memcpy(start_address,
2125  &serialized_snapshot, sizeof(SerializedSnapshotData));
2126 
2127  /* Copy XID array */
2128  if (snapshot->xcnt > 0)
2129  memcpy((TransactionId *) (start_address +
2130  sizeof(SerializedSnapshotData)),
2131  snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
2132 
2133  /*
2134  * Copy SubXID array. Don't bother to copy it if it had overflowed,
2135  * though, because it's not used anywhere in that case. Except if it's a
2136  * snapshot taken during recovery; all the top-level XIDs are in subxip as
2137  * well in that case, so we mustn't lose them.
2138  */
2139  if (serialized_snapshot.subxcnt > 0)
2140  {
2141  Size subxipoff = sizeof(SerializedSnapshotData) +
2142  snapshot->xcnt * sizeof(TransactionId);
2143 
2144  memcpy((TransactionId *) (start_address + subxipoff),
2145  snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
2146  }
2147 }
2148 
2149 /*
2150  * RestoreSnapshot
2151  * Restore a serialized snapshot from the specified address.
2152  *
2153  * The copy is palloc'd in TopTransactionContext and has initial refcounts set
2154  * to 0. The returned snapshot has the copied flag set.
2155  */
2156 Snapshot
2157 RestoreSnapshot(char *start_address)
2158 {
2159  SerializedSnapshotData serialized_snapshot;
2160  Size size;
2161  Snapshot snapshot;
2162  TransactionId *serialized_xids;
2163 
2164  memcpy(&serialized_snapshot, start_address,
2165  sizeof(SerializedSnapshotData));
2166  serialized_xids = (TransactionId *)
2167  (start_address + sizeof(SerializedSnapshotData));
2168 
2169  /* We allocate any XID arrays needed in the same palloc block. */
2170  size = sizeof(SnapshotData)
2171  + serialized_snapshot.xcnt * sizeof(TransactionId)
2172  + serialized_snapshot.subxcnt * sizeof(TransactionId);
2173 
2174  /* Copy all required fields */
2176  snapshot->snapshot_type = SNAPSHOT_MVCC;
2177  snapshot->xmin = serialized_snapshot.xmin;
2178  snapshot->xmax = serialized_snapshot.xmax;
2179  snapshot->xip = NULL;
2180  snapshot->xcnt = serialized_snapshot.xcnt;
2181  snapshot->subxip = NULL;
2182  snapshot->subxcnt = serialized_snapshot.subxcnt;
2183  snapshot->suboverflowed = serialized_snapshot.suboverflowed;
2184  snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
2185  snapshot->curcid = serialized_snapshot.curcid;
2186  snapshot->whenTaken = serialized_snapshot.whenTaken;
2187  snapshot->lsn = serialized_snapshot.lsn;
2188  snapshot->snapXactCompletionCount = 0;
2189 
2190  /* Copy XIDs, if present. */
2191  if (serialized_snapshot.xcnt > 0)
2192  {
2193  snapshot->xip = (TransactionId *) (snapshot + 1);
2194  memcpy(snapshot->xip, serialized_xids,
2195  serialized_snapshot.xcnt * sizeof(TransactionId));
2196  }
2197 
2198  /* Copy SubXIDs, if present. */
2199  if (serialized_snapshot.subxcnt > 0)
2200  {
2201  snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
2202  serialized_snapshot.xcnt;
2203  memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
2204  serialized_snapshot.subxcnt * sizeof(TransactionId));
2205  }
2206 
2207  /* Set the copied flag so that the caller will set refcounts correctly. */
2208  snapshot->regd_count = 0;
2209  snapshot->active_count = 0;
2210  snapshot->copied = true;
2211 
2212  return snapshot;
2213 }
2214 
2215 /*
2216  * Install a restored snapshot as the transaction snapshot.
2217  *
2218  * The second argument is of type void * so that snapmgr.h need not include
2219  * the declaration for PGPROC.
2220  */
2221 void
2222 RestoreTransactionSnapshot(Snapshot snapshot, void *source_pgproc)
2223 {
2224  SetTransactionSnapshot(snapshot, NULL, InvalidPid, source_pgproc);
2225 }
2226 
2227 /*
2228  * XidInMVCCSnapshot
2229  * Is the given XID still-in-progress according to the snapshot?
2230  *
2231  * Note: GetSnapshotData never stores either top xid or subxids of our own
2232  * backend into a snapshot, so these xids will not be reported as "running"
2233  * by this function. This is OK for current uses, because we always check
2234  * TransactionIdIsCurrentTransactionId first, except when it's known the
2235  * XID could not be ours anyway.
2236  */
2237 bool
2239 {
2240  uint32 i;
2241 
2242  /*
2243  * Make a quick range check to eliminate most XIDs without looking at the
2244  * xip arrays. Note that this is OK even if we convert a subxact XID to
2245  * its parent below, because a subxact with XID < xmin has surely also got
2246  * a parent with XID < xmin, while one with XID >= xmax must belong to a
2247  * parent that was not yet committed at the time of this snapshot.
2248  */
2249 
2250  /* Any xid < xmin is not in-progress */
2251  if (TransactionIdPrecedes(xid, snapshot->xmin))
2252  return false;
2253  /* Any xid >= xmax is in-progress */
2254  if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
2255  return true;
2256 
2257  /*
2258  * Snapshot information is stored slightly differently in snapshots taken
2259  * during recovery.
2260  */
2261  if (!snapshot->takenDuringRecovery)
2262  {
2263  /*
2264  * If the snapshot contains full subxact data, the fastest way to
2265  * check things is just to compare the given XID against both subxact
2266  * XIDs and top-level XIDs. If the snapshot overflowed, we have to
2267  * use pg_subtrans to convert a subxact XID to its parent XID, but
2268  * then we need only look at top-level XIDs not subxacts.
2269  */
2270  if (!snapshot->suboverflowed)
2271  {
2272  /* we have full data, so search subxip */
2273  int32 j;
2274 
2275  for (j = 0; j < snapshot->subxcnt; j++)
2276  {
2277  if (TransactionIdEquals(xid, snapshot->subxip[j]))
2278  return true;
2279  }
2280 
2281  /* not there, fall through to search xip[] */
2282  }
2283  else
2284  {
2285  /*
2286  * Snapshot overflowed, so convert xid to top-level. This is safe
2287  * because we eliminated too-old XIDs above.
2288  */
2289  xid = SubTransGetTopmostTransaction(xid);
2290 
2291  /*
2292  * If xid was indeed a subxact, we might now have an xid < xmin,
2293  * so recheck to avoid an array scan. No point in rechecking
2294  * xmax.
2295  */
2296  if (TransactionIdPrecedes(xid, snapshot->xmin))
2297  return false;
2298  }
2299 
2300  for (i = 0; i < snapshot->xcnt; i++)
2301  {
2302  if (TransactionIdEquals(xid, snapshot->xip[i]))
2303  return true;
2304  }
2305  }
2306  else
2307  {
2308  int32 j;
2309 
2310  /*
2311  * In recovery we store all xids in the subxact array because it is by
2312  * far the bigger array, and we mostly don't know which xids are
2313  * top-level and which are subxacts. The xip array is empty.
2314  *
2315  * We start by searching subtrans, if we overflowed.
2316  */
2317  if (snapshot->suboverflowed)
2318  {
2319  /*
2320  * Snapshot overflowed, so convert xid to top-level. This is safe
2321  * because we eliminated too-old XIDs above.
2322  */
2323  xid = SubTransGetTopmostTransaction(xid);
2324 
2325  /*
2326  * If xid was indeed a subxact, we might now have an xid < xmin,
2327  * so recheck to avoid an array scan. No point in rechecking
2328  * xmax.
2329  */
2330  if (TransactionIdPrecedes(xid, snapshot->xmin))
2331  return false;
2332  }
2333 
2334  /*
2335  * We now have either a top-level xid higher than xmin or an
2336  * indeterminate xid. We don't know whether it's top level or subxact
2337  * but it doesn't matter. If it's present, the xid is visible.
2338  */
2339  for (j = 0; j < snapshot->subxcnt; j++)
2340  {
2341  if (TransactionIdEquals(xid, snapshot->subxip[j]))
2342  return true;
2343  }
2344  }
2345 
2346  return false;
2347 }
void ImportSnapshot(const char *idstr)
Definition: snapmgr.c:1377
#define NIL
Definition: pg_list.h:65
uint32 CommandId
Definition: c.h:535
int xactGetCommittedChildren(TransactionId **ptr)
Definition: xact.c:5477
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:130
uint64 snapXactCompletionCount
Definition: snapshot.h:216
Snapshot as_snap
Definition: snapmgr.c:128
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:728
SnapshotData CatalogSnapshotData
Definition: snapmgr.c:97
bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
Definition: snapmgr.c:2238
void SetSerializableTransactionSnapshot(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1648
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:1496
static TransactionId parseXidFromText(const char *prefix, char **s, const char *filename)
Definition: snapmgr.c:1322
#define DEBUG1
Definition: elog.h:25
int MyProcPid
Definition: globals.c:40
TimestampTz GetOldSnapshotThresholdTimestamp(void)
Definition: snapmgr.c:1660
bool XactHasExportedSnapshots(void)
Definition: snapmgr.c:1552
Snapshot RestoreSnapshot(char *start_address)
Definition: snapmgr.c:2157
static int32 next
Definition: blutils.c:219
MemoryContext TopTransactionContext
Definition: mcxt.c:49
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
BackendId backendId
Definition: proc.h:144
uint32 TransactionId
Definition: c.h:521
bool copied
Definition: snapshot.h:185
static int parseIntFromText(const char *prefix, char **s, const char *filename)
Definition: snapmgr.c:1297
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:810
#define pairingheap_reset(h)
Definition: pairingheap.h:93
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:662
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
#define USECS_PER_SEC
Definition: timestamp.h:94
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1578
PGPROC * MyProc
Definition: proc.c:67
int64 TimestampTz
Definition: timestamp.h:39
static void SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
Definition: snapmgr.c:511
static bool OldSnapshotThresholdActive(void)
Definition: snapmgr.h:102
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
char * pstrdup(const char *in)
Definition: mcxt.c:1187
#define SpinLockInit(lock)
Definition: spin.h:60
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2664
static void SnapshotResetXmin(void)
Definition: snapmgr.c:925
#define RelationAllowsEarlyPruning(rel)
Definition: snapmgr.h:38
void ResourceOwnerEnlargeSnapshots(ResourceOwner owner)
Definition: resowner.c:1211
Snapshot GetCatalogSnapshot(Oid relid)
Definition: snapmgr.c:386
XLogRecPtr lsn
Definition: snapshot.h:209
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define IsolationUsesXactSnapshot()
Definition: xact.h:51
static Snapshot HistoricSnapshot
Definition: snapmgr.c:105
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:786
#define pairingheap_is_empty(h)
Definition: pairingheap.h:96
bool ThereAreNoPriorRegisteredSnapshots(void)
Definition: snapmgr.c:1604
#define USECS_PER_MINUTE
Definition: timestamp.h:93
int errcode(int sqlerrcode)
Definition: elog.c:610
TransactionId RecentXmin
Definition: snapmgr.c:113
#define PG_BINARY_W
Definition: c.h:1216
TimestampTz whenTaken
Definition: snapmgr.c:192
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1106
bool suboverflowed
Definition: snapshot.h:182
void PopActiveSnapshot(void)
Definition: snapmgr.c:759
void TeardownHistoricSnapshot(bool is_error)
Definition: snapmgr.c:2047
static SnapshotData CurrentSnapshotData
Definition: snapmgr.c:95
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:156
void AtSubCommit_Snapshot(int level)
Definition: snapmgr.c:949
void RestoreTransactionSnapshot(Snapshot snapshot, void *source_pgproc)
Definition: snapmgr.c:2222
static bool GetOldSnapshotFromTimeMapping(TimestampTz ts, TransactionId *xlimitp)
Definition: snapmgr.c:1707
#define LOG
Definition: elog.h:26
struct SnapshotData * Snapshot
Definition: snapshot.h:121
bool TransactionIdLimitedForOldSnapshots(TransactionId recentXmin, Relation relation, TransactionId *limit_xid, TimestampTz *limit_ts)
Definition: snapmgr.c:1751
unsigned int Oid
Definition: postgres_ext.h:31
LocalTransactionId localTransactionId
Definition: lock.h:65
Definition: dirent.h:9
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:250
uint32 regd_count
Definition: snapshot.h:205
#define OidIsValid(objectId)
Definition: c.h:652
#define PG_BINARY_R
Definition: c.h:1215
SnapshotData SnapshotAnyData
Definition: snapmgr.c:99
static Snapshot CurrentSnapshot
Definition: snapmgr.c:102
Snapshot GetNonHistoricCatalogSnapshot(Oid relid)
Definition: snapmgr.c:408
void SetOldSnapshotThresholdTimestamp(TimestampTz ts, TransactionId xlimit)
Definition: snapmgr.c:1672
signed int int32
Definition: c.h:363
#define XACT_SERIALIZABLE
Definition: xact.h:39
TransactionId TransactionXmin
Definition: snapmgr.c:112
static List * exportedSnapshots
Definition: snapmgr.c:169
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:159
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
struct ActiveSnapshotElt ActiveSnapshotElt
#define pairingheap_container(type, membername, ptr)
Definition: pairingheap.h:43
void AtSubAbort_Snapshot(int level)
Definition: snapmgr.c:970
#define SpinLockAcquire(lock)
Definition: spin.h:62
Definition: dynahash.c:218
#define fstat
Definition: win32_port.h:274
void pfree(void *pointer)
Definition: mcxt.c:1057
bool IsInParallelMode(void)
Definition: xact.c:1012
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TimestampTz threshold_timestamp
Definition: old_snapshot.h:36
Definition: dirent.c:25
#define FirstNormalTransactionId
Definition: transam.h:34
static Snapshot CatalogSnapshot
Definition: snapmgr.c:104
#define ERROR
Definition: elog.h:43
TimestampTz GetSnapshotCurrentTimestamp(void)
Definition: snapmgr.c:1635
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:146
void SerializeSnapshot(Snapshot snapshot, char *start_address)
Definition: snapmgr.c:2098
bool FirstSnapshotSet
Definition: snapmgr.c:149
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:392
TimestampTz next_map_update
Definition: old_snapshot.h:34
static ActiveSnapshotElt * OldestActiveSnapshot
Definition: snapmgr.c:137
#define MAXPGPATH
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:716
TimestampTz current_timestamp
Definition: old_snapshot.h:31
TransactionId threshold_xid
Definition: old_snapshot.h:37
TransactionId xmin
Definition: proc.h:129
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
struct SerializedSnapshotData SerializedSnapshotData
static void parseVxidFromText(const char *prefix, char **s, const char *filename, VirtualTransactionId *vxid)
Definition: snapmgr.c:1347
static char * buf
Definition: pg_test_fsync.c:68
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:680
void ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snapshot)
Definition: resowner.c:1231
int errdetail(const char *fmt,...)
Definition: elog.c:954
int errcode_for_file_access(void)
Definition: elog.c:633
struct SnapshotData SnapshotData
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2322
void SnapshotTooOldMagicForTest(void)
Definition: snapmgr.c:1689
#define InvalidTransactionId
Definition: transam.h:31
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:130
SnapshotType snapshot_type
Definition: snapshot.h:144
Datum pg_export_snapshot(PG_FUNCTION_ARGS)
Definition: snapmgr.c:1282
unsigned int uint32
Definition: c.h:375
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2583
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:798
TransactionId xmax
Definition: snapshot.h:158
__int64 st_size
Definition: win32_port.h:265
TransactionId xmin
Definition: snapshot.h:157
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:425
volatile OldSnapshotControlData * oldSnapshotControl
Definition: snapmgr.c:80
Snapshot snapshot
Definition: snapmgr.c:165
void SnapMgrInit(void)
Definition: snapmgr.c:213
#define pairingheap_const_container(type, membername, ptr)
Definition: pairingheap.h:51
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:456
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:168
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:134
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:852
List * lappend(List *list, void *datum)
Definition: list.c:321
static HTAB * tuplecid_data
Definition: snapmgr.c:116
char * snapfile
Definition: snapmgr.c:164
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define WARNING
Definition: elog.h:40
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
TransactionId xmax
Definition: snapmgr.c:186
#define InvalidSnapshot
Definition: snapshot.h:123
#define SpinLockRelease(lock)
Definition: spin.h:64
Size EstimateSnapshotSpace(Snapshot snap)
Definition: snapmgr.c:2074
Size mul_size(Size s1, Size s2)
Definition: shmem.c:515
uintptr_t Datum
Definition: postgres.h:367
Size add_size(Size s1, Size s2)
Definition: shmem.c:498
Oid MyDatabaseId
Definition: globals.c:85
Snapshot GetOldestSnapshot(void)
Definition: snapmgr.c:357
static SnapshotData SecondarySnapshotData
Definition: snapmgr.c:96
CommandId curcid
Definition: snapshot.h:187
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:606
#define ereport(elevel,...)
Definition: elog.h:144
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1927
Snapshot RegisterSnapshotOnOwner(Snapshot snapshot, ResourceOwner owner)
Definition: snapmgr.c:823
bool XactReadOnly
Definition: xact.c:78
pairingheap_node ph_node
Definition: snapshot.h:206
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:857
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:370
text * cstring_to_text(const char *s)
Definition: varlena.c:188
uint64 XLogRecPtr
Definition: xlogdefs.h:21
TransactionId latest_xmin
Definition: old_snapshot.h:33
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:1473
BackendId backendId
Definition: lock.h:64
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1608
void InvalidateCatalogSnapshotConditionally(void)
Definition: snapmgr.c:477
TransactionId xid_by_minute[FLEXIBLE_ARRAY_MEMBER]
Definition: old_snapshot.h:70
bool takenDuringRecovery
Definition: snapshot.h:184
SnapshotData SnapshotSelfData
Definition: snapmgr.c:98
size_t Size
Definition: c.h:474
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2064
static int list_length(const List *l)
Definition: pg_list.h:149
int XactIsoLevel
Definition: xact.c:75
void UnregisterSnapshotFromOwner(Snapshot snapshot, ResourceOwner owner)
Definition: snapmgr.c:865
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static TimestampTz AlignTimestampToMinuteBoundary(TimestampTz ts)
Definition: snapmgr.c:1621
bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
Definition: procarray.c:2491
Snapshot GetLatestSnapshot(void)
Definition: snapmgr.c:325
void SnapshotSetCommandId(CommandId curcid)
Definition: snapmgr.c:490
int FreeFile(FILE *file)
Definition: fd.c:2521
bool IsSubTransaction(void)
Definition: xact.c:4757
HTAB * HistoricSnapshotGetTupleCids(void)
Definition: snapmgr.c:2060
static char * filename
Definition: pg_dumpall.c:91
uint32 xcnt
Definition: snapshot.h:169
void * palloc(Size size)
Definition: mcxt.c:950
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:2054
int errmsg(const char *fmt,...)
Definition: elog.c:821
void ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snapshot)
Definition: resowner.c:1222
#define IsolationIsSerializable()
Definition: xact.h:52
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
void DeleteAllExportedSnapshotFiles(void)
Definition: snapmgr.c:1565
void SetupHistoricSnapshot(Snapshot historic_snapshot, HTAB *tuplecids)
Definition: snapmgr.c:2031
static int xmin_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
Definition: snapmgr.c:891
#define elog(elevel,...)
Definition: elog.h:214
int old_snapshot_threshold
Definition: snapmgr.c:78
TimestampTz head_timestamp
Definition: old_snapshot.h:68
int i
TransactionId xmin
Definition: snapmgr.c:185
static Snapshot SecondarySnapshot
Definition: snapmgr.c:103
void * arg
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1938
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
TimestampTz whenTaken
Definition: snapshot.h:208
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:170
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:112
char d_name[MAX_PATH]
Definition: dirent.h:15
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:761
#define TransactionIdIsValid(xid)
Definition: transam.h:41
void MaintainOldSnapshotTimeMapping(TimestampTz whenTaken, TransactionId xmin)
Definition: snapmgr.c:1854
#define OLD_SNAPSHOT_TIME_MAP_ENTRIES
Definition: snapmgr.h:32
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
bool ProcArrayInstallImportedXmin(TransactionId xmin, VirtualTransactionId *sourcevxid)
Definition: procarray.c:2416
Size SnapMgrShmemSize(void)
Definition: snapmgr.c:197
Definition: proc.h:112
Definition: pg_list.h:50
#define snprintf
Definition: port.h:215
struct ExportedSnapshot ExportedSnapshot
long val
Definition: informix.c:664
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1542
int FreeDir(DIR *dir)
Definition: fd.c:2701
#define offsetof(type, field)
Definition: c.h:669
void AtEOXact_Snapshot(bool isCommit, bool resetXmin)
Definition: snapmgr.c:1006
TransactionId * subxip
Definition: snapshot.h:180
#define InvalidPid
Definition: miscadmin.h:32
#define pairingheap_is_singular(h)
Definition: pairingheap.h:99
uint32 active_count
Definition: snapshot.h:204
int32 subxcnt
Definition: snapshot.h:181
LocalTransactionId lxid
Definition: proc.h:134