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 * The following functions return an MVCC snapshot that can be used in tuple
7 * visibility checks:
8 *
9 * - GetTransactionSnapshot
10 * - GetLatestSnapshot
11 * - GetCatalogSnapshot
12 * - GetNonHistoricCatalogSnapshot
13 *
14 * Each of these functions returns a reference to a statically allocated
15 * snapshot. The statically allocated snapshot is subject to change on any
16 * snapshot-related function call, and should not be used directly. Instead,
17 * call PushActiveSnapshot() or RegisterSnapshot() to create a longer-lived
18 * copy and use that.
19 *
20 * We keep track of snapshots in two ways: those "registered" by resowner.c,
21 * and the "active snapshot" stack. All snapshots in either of them live in
22 * persistent memory. When a snapshot is no longer in any of these lists
23 * (tracked by separate refcounts on each snapshot), its memory can be freed.
24 *
25 * In addition to the above-mentioned MVCC snapshots, there are some special
26 * snapshots like SnapshotSelf, SnapshotAny, and "dirty" snapshots. They can
27 * only be used in limited contexts and cannot be registered or pushed to the
28 * active stack.
29 *
30 * ActiveSnapshot stack
31 * --------------------
32 *
33 * Most visibility checks use the current "active snapshot" returned by
34 * GetActiveSnapshot(). When running normal queries, the active snapshot is
35 * set when query execution begins based on the transaction isolation level.
36 *
37 * The active snapshot is tracked in a stack so that the currently active one
38 * is at the top of the stack. It mirrors the process call stack: whenever we
39 * recurse or switch context to fetch rows from a different portal for
40 * example, the appropriate snapshot is pushed to become the active snapshot,
41 * and popped on return. Once upon a time, ActiveSnapshot was just a global
42 * variable that was saved and restored similar to CurrentMemoryContext, but
43 * nowadays it's managed as a separate data structure so that we can keep
44 * track of which snapshots are in use and reset MyProc->xmin when there is no
45 * active snapshot.
46 *
47 * However, there are a couple of exceptions where the active snapshot stack
48 * does not strictly mirror the call stack:
49 *
50 * - VACUUM and a few other utility commands manage their own transactions,
51 * which take their own snapshots. They are called with an active snapshot
52 * set, like most utility commands, but they pop the active snapshot that
53 * was pushed by the caller. PortalRunUtility knows about the possibility
54 * that the snapshot it pushed is no longer active on return.
55 *
56 * - When COMMIT or ROLLBACK is executed within a procedure or DO-block, the
57 * active snapshot stack is destroyed, and re-established later when
58 * subsequent statements in the procedure are executed. There are many
59 * limitations on when in-procedure COMMIT/ROLLBACK is allowed; one such
60 * limitation is that all the snapshots on the active snapshot stack are
61 * known to portals that are being executed, which makes it safe to reset
62 * the stack. See EnsurePortalSnapshotExists().
63 *
64 * Registered snapshots
65 * --------------------
66 *
67 * In addition to snapshots pushed to the active snapshot stack, a snapshot
68 * can be registered with a resource owner.
69 *
70 * The FirstXactSnapshot, if any, is treated a bit specially: we increment its
71 * regd_count and list it in RegisteredSnapshots, but this reference is not
72 * tracked by a resource owner. We used to use the TopTransactionResourceOwner
73 * to track this snapshot reference, but that introduces logical circularity
74 * and thus makes it impossible to clean up in a sane fashion. It's better to
75 * handle this reference as an internally-tracked registration, so that this
76 * module is entirely lower-level than ResourceOwners.
77 *
78 * Likewise, any snapshots that have been exported by pg_export_snapshot
79 * have regd_count = 1 and are listed in RegisteredSnapshots, but are not
80 * tracked by any resource owner.
81 *
82 * Likewise, the CatalogSnapshot is listed in RegisteredSnapshots when it
83 * is valid, but is not tracked by any resource owner.
84 *
85 * The same is true for historic snapshots used during logical decoding,
86 * their lifetime is managed separately (as they live longer than one xact.c
87 * transaction).
88 *
89 * These arrangements let us reset MyProc->xmin when there are no snapshots
90 * referenced by this transaction, and advance it when the one with oldest
91 * Xmin is no longer referenced. For simplicity however, only registered
92 * snapshots not active snapshots participate in tracking which one is oldest;
93 * we don't try to change MyProc->xmin except when the active-snapshot
94 * stack is empty.
95 *
96 *
97 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
98 * Portions Copyright (c) 1994, Regents of the University of California
99 *
100 * IDENTIFICATION
101 * src/backend/utils/time/snapmgr.c
102 *
103 *-------------------------------------------------------------------------
104 */
105#include "postgres.h"
106
107#include <sys/stat.h>
108#include <unistd.h>
109
110#include "access/subtrans.h"
111#include "access/transam.h"
112#include "access/xact.h"
113#include "datatype/timestamp.h"
114#include "lib/pairingheap.h"
115#include "miscadmin.h"
116#include "port/pg_lfind.h"
117#include "storage/fd.h"
118#include "storage/predicate.h"
119#include "storage/proc.h"
120#include "storage/procarray.h"
121#include "utils/builtins.h"
123#include "utils/memutils.h"
124#include "utils/resowner.h"
125#include "utils/snapmgr.h"
126#include "utils/syscache.h"
127
128
129/*
130 * CurrentSnapshot points to the only snapshot taken in transaction-snapshot
131 * mode, and to the latest one taken in a read-committed transaction.
132 * SecondarySnapshot is a snapshot that's always up-to-date as of the current
133 * instant, even in transaction-snapshot mode. It should only be used for
134 * special-purpose code (say, RI checking.) CatalogSnapshot points to an
135 * MVCC snapshot intended to be used for catalog scans; we must invalidate it
136 * whenever a system catalog change occurs.
137 *
138 * These SnapshotData structs are static to simplify memory allocation
139 * (see the hack in GetSnapshotData to avoid repeated malloc/free).
140 */
147
148/* Pointers to valid snapshots */
153
154/*
155 * These are updated by GetSnapshotData. We initialize them this way
156 * for the convenience of TransactionIdIsInProgress: even in bootstrap
157 * mode, we don't want it to say that BootstrapTransactionId is in progress.
158 */
161
162/* (table, ctid) => (cmin, cmax) mapping during timetravel */
163static HTAB *tuplecid_data = NULL;
164
165/*
166 * Elements of the active snapshot stack.
167 *
168 * Each element here accounts for exactly one active_count on SnapshotData.
169 *
170 * NB: the code assumes that elements in this list are in non-increasing
171 * order of as_level; also, the list must be NULL-terminated.
172 */
173typedef struct ActiveSnapshotElt
174{
179
180/* Top of the stack of active snapshots */
182
183/*
184 * Currently registered Snapshots. Ordered in a heap by xmin, so that we can
185 * quickly find the one with lowest xmin, to advance our MyProc->xmin.
186 */
187static int xmin_cmp(const pairingheap_node *a, const pairingheap_node *b,
188 void *arg);
189
191
192/* first GetTransactionSnapshot call in a transaction? */
193bool FirstSnapshotSet = false;
194
195/*
196 * Remember the serializable transaction snapshot, if any. We cannot trust
197 * FirstSnapshotSet in combination with IsolationUsesXactSnapshot(), because
198 * GUC may be reset before us, changing the value of IsolationUsesXactSnapshot.
199 */
201
202/* Define pathname of exported-snapshot files */
203#define SNAPSHOT_EXPORT_DIR "pg_snapshots"
204
205/* Structure holding info about exported snapshot. */
206typedef struct ExportedSnapshot
207{
208 char *snapfile;
211
212/* Current xact's exported snapshots (a list of ExportedSnapshot structs) */
214
215/* Prototypes for local functions */
216static Snapshot CopySnapshot(Snapshot snapshot);
217static void UnregisterSnapshotNoOwner(Snapshot snapshot);
218static void FreeSnapshot(Snapshot snapshot);
219static void SnapshotResetXmin(void);
220
221/* ResourceOwner callbacks to track snapshot references */
222static void ResOwnerReleaseSnapshot(Datum res);
223
225{
226 .name = "snapshot reference",
227 .release_phase = RESOURCE_RELEASE_AFTER_LOCKS,
228 .release_priority = RELEASE_PRIO_SNAPSHOT_REFS,
229 .ReleaseResource = ResOwnerReleaseSnapshot,
230 .DebugPrint = NULL /* the default message is fine */
231};
232
233/* Convenience wrappers over ResourceOwnerRemember/Forget */
234static inline void
236{
238}
239static inline void
241{
243}
244
245/*
246 * Snapshot fields to be serialized.
247 *
248 * Only these fields need to be sent to the cooperating backend; the
249 * remaining ones can (and must) be set by the receiver upon restore.
250 */
252{
261
262/*
263 * GetTransactionSnapshot
264 * Get the appropriate snapshot for a new query in a transaction.
265 *
266 * Note that the return value points at static storage that will be modified
267 * by future calls and by CommandCounterIncrement(). Callers must call
268 * RegisterSnapshot or PushActiveSnapshot on the returned snap before doing
269 * any other non-trivial work that could invalidate it.
270 */
273{
274 /*
275 * Return historic snapshot if doing logical decoding.
276 *
277 * Historic snapshots are only usable for catalog access, not for
278 * general-purpose queries. The caller is responsible for ensuring that
279 * the snapshot is used correctly! (PostgreSQL code never calls this
280 * during logical decoding, but extensions can do it.)
281 */
283 {
284 /*
285 * We'll never need a non-historic transaction snapshot in this
286 * (sub-)transaction, so there's no need to be careful to set one up
287 * for later calls to GetTransactionSnapshot().
288 */
290 return HistoricSnapshot;
291 }
292
293 /* First call in transaction? */
294 if (!FirstSnapshotSet)
295 {
296 /*
297 * Don't allow catalog snapshot to be older than xact snapshot. Must
298 * do this first to allow the empty-heap Assert to succeed.
299 */
301
303 Assert(FirstXactSnapshot == NULL);
304
305 if (IsInParallelMode())
306 elog(ERROR,
307 "cannot take query snapshot during a parallel operation");
308
309 /*
310 * In transaction-snapshot mode, the first snapshot must live until
311 * end of xact regardless of what the caller does with it, so we must
312 * make a copy of it rather than returning CurrentSnapshotData
313 * directly. Furthermore, if we're running in serializable mode,
314 * predicate.c needs to wrap the snapshot fetch in its own processing.
315 */
317 {
318 /* First, create the snapshot in CurrentSnapshotData */
321 else
323 /* Make a saved copy */
326 /* Mark it as "registered" in FirstXactSnapshot */
329 }
330 else
332
333 FirstSnapshotSet = true;
334 return CurrentSnapshot;
335 }
336
338 return CurrentSnapshot;
339
340 /* Don't allow catalog snapshot to be older than xact snapshot. */
342
344
345 return CurrentSnapshot;
346}
347
348/*
349 * GetLatestSnapshot
350 * Get a snapshot that is up-to-date as of the current instant,
351 * even if we are executing in transaction-snapshot mode.
352 */
355{
356 /*
357 * We might be able to relax this, but nothing that could otherwise work
358 * needs it.
359 */
360 if (IsInParallelMode())
361 elog(ERROR,
362 "cannot update SecondarySnapshot during a parallel operation");
363
364 /*
365 * So far there are no cases requiring support for GetLatestSnapshot()
366 * during logical decoding, but it wouldn't be hard to add if required.
367 */
369
370 /* If first call in transaction, go ahead and set the xact snapshot */
371 if (!FirstSnapshotSet)
372 return GetTransactionSnapshot();
373
375
376 return SecondarySnapshot;
377}
378
379/*
380 * GetCatalogSnapshot
381 * Get a snapshot that is sufficiently up-to-date for scan of the
382 * system catalog with the specified OID.
383 */
386{
387 /*
388 * Return historic snapshot while we're doing logical decoding, so we can
389 * see the appropriate state of the catalog.
390 *
391 * This is the primary reason for needing to reset the system caches after
392 * finishing decoding.
393 */
395 return HistoricSnapshot;
396
397 return GetNonHistoricCatalogSnapshot(relid);
398}
399
400/*
401 * GetNonHistoricCatalogSnapshot
402 * Get a snapshot that is sufficiently up-to-date for scan of the system
403 * catalog with the specified OID, even while historic snapshots are set
404 * up.
405 */
408{
409 /*
410 * If the caller is trying to scan a relation that has no syscache, no
411 * catcache invalidations will be sent when it is updated. For a few key
412 * relations, snapshot invalidations are sent instead. If we're trying to
413 * scan a relation for which neither catcache nor snapshot invalidations
414 * are sent, we must refresh the snapshot every time.
415 */
416 if (CatalogSnapshot &&
418 !RelationHasSysCache(relid))
420
421 if (CatalogSnapshot == NULL)
422 {
423 /* Get new snapshot. */
425
426 /*
427 * Make sure the catalog snapshot will be accounted for in decisions
428 * about advancing PGPROC->xmin. We could apply RegisterSnapshot, but
429 * that would result in making a physical copy, which is overkill; and
430 * it would also create a dependency on some resource owner, which we
431 * do not want for reasons explained at the head of this file. Instead
432 * just shove the CatalogSnapshot into the pairing heap manually. This
433 * has to be reversed in InvalidateCatalogSnapshot, of course.
434 *
435 * NB: it had better be impossible for this to throw error, since the
436 * CatalogSnapshot pointer is already valid.
437 */
439 }
440
441 return CatalogSnapshot;
442}
443
444/*
445 * InvalidateCatalogSnapshot
446 * Mark the current catalog snapshot, if any, as invalid
447 *
448 * We could change this API to allow the caller to provide more fine-grained
449 * invalidation details, so that a change to relation A wouldn't prevent us
450 * from using our cached snapshot to scan relation B, but so far there's no
451 * evidence that the CPU cycles we spent tracking such fine details would be
452 * well-spent.
453 */
454void
456{
457 if (CatalogSnapshot)
458 {
460 CatalogSnapshot = NULL;
462 INJECTION_POINT("pre-invalidate-catalog-snapshot-end", NULL);
463 INJECTION_POINT("invalidate-catalog-snapshot-end", NULL);
464 }
465}
466
467/*
468 * InvalidateCatalogSnapshotConditionally
469 * Drop catalog snapshot if it's the only one we have
470 *
471 * This is called when we are about to wait for client input, so we don't
472 * want to continue holding the catalog snapshot if it might mean that the
473 * global xmin horizon can't advance. However, if there are other snapshots
474 * still active or registered, the catalog snapshot isn't likely to be the
475 * oldest one, so we might as well keep it.
476 */
477void
479{
480 if (CatalogSnapshot &&
481 ActiveSnapshot == NULL &&
484}
485
486/*
487 * SnapshotSetCommandId
488 * Propagate CommandCounterIncrement into the static snapshots, if set
489 */
490void
492{
493 if (!FirstSnapshotSet)
494 return;
495
496 if (CurrentSnapshot)
497 CurrentSnapshot->curcid = curcid;
499 SecondarySnapshot->curcid = curcid;
500 /* Should we do the same with CatalogSnapshot? */
501}
502
503/*
504 * SetTransactionSnapshot
505 * Set the transaction's snapshot from an imported MVCC snapshot.
506 *
507 * Note that this is very closely tied to GetTransactionSnapshot --- it
508 * must take care of all the same considerations as the first-snapshot case
509 * in GetTransactionSnapshot.
510 */
511static void
513 int sourcepid, PGPROC *sourceproc)
514{
515 /* Caller should have checked this already */
517
518 /* Better do this to ensure following Assert succeeds. */
520
522 Assert(FirstXactSnapshot == NULL);
524
525 /*
526 * Even though we are not going to use the snapshot it computes, we must
527 * call GetSnapshotData, for two reasons: (1) to be sure that
528 * CurrentSnapshotData's XID arrays have been allocated, and (2) to update
529 * the state for GlobalVis*.
530 */
532
533 /*
534 * Now copy appropriate fields from the source snapshot.
535 */
536 CurrentSnapshot->xmin = sourcesnap->xmin;
537 CurrentSnapshot->xmax = sourcesnap->xmax;
538 CurrentSnapshot->xcnt = sourcesnap->xcnt;
539 Assert(sourcesnap->xcnt <= GetMaxSnapshotXidCount());
540 if (sourcesnap->xcnt > 0)
541 memcpy(CurrentSnapshot->xip, sourcesnap->xip,
542 sourcesnap->xcnt * sizeof(TransactionId));
543 CurrentSnapshot->subxcnt = sourcesnap->subxcnt;
544 Assert(sourcesnap->subxcnt <= GetMaxSnapshotSubxidCount());
545 if (sourcesnap->subxcnt > 0)
546 memcpy(CurrentSnapshot->subxip, sourcesnap->subxip,
547 sourcesnap->subxcnt * sizeof(TransactionId));
550 /* NB: curcid should NOT be copied, it's a local matter */
551
553
554 /*
555 * Now we have to fix what GetSnapshotData did with MyProc->xmin and
556 * TransactionXmin. There is a race condition: to make sure we are not
557 * causing the global xmin to go backwards, we have to test that the
558 * source transaction is still running, and that has to be done
559 * atomically. So let procarray.c do it.
560 *
561 * Note: in serializable mode, predicate.c will do this a second time. It
562 * doesn't seem worth contorting the logic here to avoid two calls,
563 * especially since it's not clear that predicate.c *must* do this.
564 */
565 if (sourceproc != NULL)
566 {
569 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
570 errmsg("could not import the requested snapshot"),
571 errdetail("The source transaction is not running anymore.")));
572 }
573 else if (!ProcArrayInstallImportedXmin(CurrentSnapshot->xmin, sourcevxid))
575 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
576 errmsg("could not import the requested snapshot"),
577 errdetail("The source process with PID %d is not running anymore.",
578 sourcepid)));
579
580 /*
581 * In transaction-snapshot mode, the first snapshot must live until end of
582 * xact, so we must make a copy of it. Furthermore, if we're running in
583 * serializable mode, predicate.c needs to do its own processing.
584 */
586 {
589 sourcepid);
590 /* Make a saved copy */
593 /* Mark it as "registered" in FirstXactSnapshot */
596 }
597
598 FirstSnapshotSet = true;
599}
600
601/*
602 * CopySnapshot
603 * Copy the given snapshot.
604 *
605 * The copy is palloc'd in TopTransactionContext and has initial refcounts set
606 * to 0. The returned snapshot has the copied flag set.
607 */
608static Snapshot
610{
611 Snapshot newsnap;
612 Size subxipoff;
613 Size size;
614
615 Assert(snapshot != InvalidSnapshot);
616
617 /* We allocate any XID arrays needed in the same palloc block. */
618 size = subxipoff = sizeof(SnapshotData) +
619 snapshot->xcnt * sizeof(TransactionId);
620 if (snapshot->subxcnt > 0)
621 size += snapshot->subxcnt * sizeof(TransactionId);
622
624 memcpy(newsnap, snapshot, sizeof(SnapshotData));
625
626 newsnap->regd_count = 0;
627 newsnap->active_count = 0;
628 newsnap->copied = true;
629 newsnap->snapXactCompletionCount = 0;
630
631 /* setup XID array */
632 if (snapshot->xcnt > 0)
633 {
634 newsnap->xip = (TransactionId *) (newsnap + 1);
635 memcpy(newsnap->xip, snapshot->xip,
636 snapshot->xcnt * sizeof(TransactionId));
637 }
638 else
639 newsnap->xip = NULL;
640
641 /*
642 * Setup subXID array. Don't bother to copy it if it had overflowed,
643 * though, because it's not used anywhere in that case. Except if it's a
644 * snapshot taken during recovery; all the top-level XIDs are in subxip as
645 * well in that case, so we mustn't lose them.
646 */
647 if (snapshot->subxcnt > 0 &&
648 (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
649 {
650 newsnap->subxip = (TransactionId *) ((char *) newsnap + subxipoff);
651 memcpy(newsnap->subxip, snapshot->subxip,
652 snapshot->subxcnt * sizeof(TransactionId));
653 }
654 else
655 newsnap->subxip = NULL;
656
657 return newsnap;
658}
659
660/*
661 * FreeSnapshot
662 * Free the memory associated with a snapshot.
663 */
664static void
666{
667 Assert(snapshot->regd_count == 0);
668 Assert(snapshot->active_count == 0);
669 Assert(snapshot->copied);
670
671 pfree(snapshot);
672}
673
674/*
675 * PushActiveSnapshot
676 * Set the given snapshot as the current active snapshot
677 *
678 * If the passed snapshot is a statically-allocated one, or it is possibly
679 * subject to a future command counter update, create a new long-lived copy
680 * with active refcount=1. Otherwise, only increment the refcount.
681 */
682void
684{
686}
687
688/*
689 * PushActiveSnapshotWithLevel
690 * Set the given snapshot as the current active snapshot
691 *
692 * Same as PushActiveSnapshot except that caller can specify the
693 * transaction nesting level that "owns" the snapshot. This level
694 * must not be deeper than the current top of the snapshot stack.
695 */
696void
697PushActiveSnapshotWithLevel(Snapshot snapshot, int snap_level)
698{
699 ActiveSnapshotElt *newactive;
700
701 Assert(snapshot != InvalidSnapshot);
702 Assert(ActiveSnapshot == NULL || snap_level >= ActiveSnapshot->as_level);
703
705
706 /*
707 * Checking SecondarySnapshot is probably useless here, but it seems
708 * better to be sure.
709 */
710 if (snapshot == CurrentSnapshot || snapshot == SecondarySnapshot ||
711 !snapshot->copied)
712 newactive->as_snap = CopySnapshot(snapshot);
713 else
714 newactive->as_snap = snapshot;
715
716 newactive->as_next = ActiveSnapshot;
717 newactive->as_level = snap_level;
718
719 newactive->as_snap->active_count++;
720
721 ActiveSnapshot = newactive;
722}
723
724/*
725 * PushCopiedSnapshot
726 * As above, except forcibly copy the presented snapshot.
727 *
728 * This should be used when the ActiveSnapshot has to be modifiable, for
729 * example if the caller intends to call UpdateActiveSnapshotCommandId.
730 * The new snapshot will be released when popped from the stack.
731 */
732void
734{
736}
737
738/*
739 * UpdateActiveSnapshotCommandId
740 *
741 * Update the current CID of the active snapshot. This can only be applied
742 * to a snapshot that is not referenced elsewhere.
743 */
744void
746{
747 CommandId save_curcid,
748 curcid;
749
750 Assert(ActiveSnapshot != NULL);
753
754 /*
755 * Don't allow modification of the active snapshot during parallel
756 * operation. We share the snapshot to worker backends at the beginning
757 * of parallel operation, so any change to the snapshot can lead to
758 * inconsistencies. We have other defenses against
759 * CommandCounterIncrement, but there are a few places that call this
760 * directly, so we put an additional guard here.
761 */
762 save_curcid = ActiveSnapshot->as_snap->curcid;
763 curcid = GetCurrentCommandId(false);
764 if (IsInParallelMode() && save_curcid != curcid)
765 elog(ERROR, "cannot modify commandid in active snapshot during a parallel operation");
766 ActiveSnapshot->as_snap->curcid = curcid;
767}
768
769/*
770 * PopActiveSnapshot
771 *
772 * Remove the topmost snapshot from the active snapshot stack, decrementing the
773 * reference count, and free it if this was the last reference.
774 */
775void
777{
778 ActiveSnapshotElt *newstack;
779
780 newstack = ActiveSnapshot->as_next;
781
783
785
789
791 ActiveSnapshot = newstack;
792
794}
795
796/*
797 * GetActiveSnapshot
798 * Return the topmost snapshot in the Active stack.
799 */
802{
803 Assert(ActiveSnapshot != NULL);
804
805 return ActiveSnapshot->as_snap;
806}
807
808/*
809 * ActiveSnapshotSet
810 * Return whether there is at least one snapshot in the Active stack
811 */
812bool
814{
815 return ActiveSnapshot != NULL;
816}
817
818/*
819 * RegisterSnapshot
820 * Register a snapshot as being in use by the current resource owner
821 *
822 * If InvalidSnapshot is passed, it is not registered.
823 */
826{
827 if (snapshot == InvalidSnapshot)
828 return InvalidSnapshot;
829
831}
832
833/*
834 * RegisterSnapshotOnOwner
835 * As above, but use the specified resource owner
836 */
839{
840 Snapshot snap;
841
842 if (snapshot == InvalidSnapshot)
843 return InvalidSnapshot;
844
845 /* Static snapshot? Create a persistent copy */
846 snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
847
848 /* and tell resowner.c about it */
850 snap->regd_count++;
852
853 if (snap->regd_count == 1)
855
856 return snap;
857}
858
859/*
860 * UnregisterSnapshot
861 *
862 * Decrement the reference count of a snapshot, remove the corresponding
863 * reference from CurrentResourceOwner, and free the snapshot if no more
864 * references remain.
865 */
866void
868{
869 if (snapshot == NULL)
870 return;
871
873}
874
875/*
876 * UnregisterSnapshotFromOwner
877 * As above, but use the specified resource owner
878 */
879void
881{
882 if (snapshot == NULL)
883 return;
884
885 ResourceOwnerForgetSnapshot(owner, snapshot);
887}
888
889static void
891{
892 Assert(snapshot->regd_count > 0);
894
895 snapshot->regd_count--;
896 if (snapshot->regd_count == 0)
898
899 if (snapshot->regd_count == 0 && snapshot->active_count == 0)
900 {
901 FreeSnapshot(snapshot);
903 }
904}
905
906/*
907 * Comparison function for RegisteredSnapshots heap. Snapshots are ordered
908 * by xmin, so that the snapshot with smallest xmin is at the top.
909 */
910static int
912{
913 const SnapshotData *asnap = pairingheap_const_container(SnapshotData, ph_node, a);
914 const SnapshotData *bsnap = pairingheap_const_container(SnapshotData, ph_node, b);
915
916 if (TransactionIdPrecedes(asnap->xmin, bsnap->xmin))
917 return 1;
918 else if (TransactionIdFollows(asnap->xmin, bsnap->xmin))
919 return -1;
920 else
921 return 0;
922}
923
924/*
925 * SnapshotResetXmin
926 *
927 * If there are no more snapshots, we can reset our PGPROC->xmin to
928 * InvalidTransactionId. Note we can do this without locking because we assume
929 * that storing an Xid is atomic.
930 *
931 * Even if there are some remaining snapshots, we may be able to advance our
932 * PGPROC->xmin to some degree. This typically happens when a portal is
933 * dropped. For efficiency, we only consider recomputing PGPROC->xmin when
934 * the active snapshot stack is empty; this allows us not to need to track
935 * which active snapshot is oldest.
936 */
937static void
939{
940 Snapshot minSnapshot;
941
942 if (ActiveSnapshot != NULL)
943 return;
944
946 {
948 return;
949 }
950
951 minSnapshot = pairingheap_container(SnapshotData, ph_node,
953
954 if (TransactionIdPrecedes(MyProc->xmin, minSnapshot->xmin))
955 MyProc->xmin = TransactionXmin = minSnapshot->xmin;
956}
957
958/*
959 * AtSubCommit_Snapshot
960 */
961void
963{
964 ActiveSnapshotElt *active;
965
966 /*
967 * Relabel the active snapshots set in this subtransaction as though they
968 * are owned by the parent subxact.
969 */
970 for (active = ActiveSnapshot; active != NULL; active = active->as_next)
971 {
972 if (active->as_level < level)
973 break;
974 active->as_level = level - 1;
975 }
976}
977
978/*
979 * AtSubAbort_Snapshot
980 * Clean up snapshots after a subtransaction abort
981 */
982void
984{
985 /* Forget the active snapshots set by this subtransaction */
986 while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
987 {
989
991
992 /*
993 * Decrement the snapshot's active count. If it's still registered or
994 * marked as active by an outer subtransaction, we can't free it yet.
995 */
998
1002
1003 /* and free the stack element */
1005
1007 }
1008
1010}
1011
1012/*
1013 * AtEOXact_Snapshot
1014 * Snapshot manager's cleanup function for end of transaction
1015 */
1016void
1017AtEOXact_Snapshot(bool isCommit, bool resetXmin)
1018{
1019 /*
1020 * In transaction-snapshot mode we must release our privately-managed
1021 * reference to the transaction snapshot. We must remove it from
1022 * RegisteredSnapshots to keep the check below happy. But we don't bother
1023 * to do FreeSnapshot, for two reasons: the memory will go away with
1024 * TopTransactionContext anyway, and if someone has left the snapshot
1025 * stacked as active, we don't want the code below to be chasing through a
1026 * dangling pointer.
1027 */
1028 if (FirstXactSnapshot != NULL)
1029 {
1033 }
1034 FirstXactSnapshot = NULL;
1035
1036 /*
1037 * If we exported any snapshots, clean them up.
1038 */
1039 if (exportedSnapshots != NIL)
1040 {
1041 ListCell *lc;
1042
1043 /*
1044 * Get rid of the files. Unlink failure is only a WARNING because (1)
1045 * it's too late to abort the transaction, and (2) leaving a leaked
1046 * file around has little real consequence anyway.
1047 *
1048 * We also need to remove the snapshots from RegisteredSnapshots to
1049 * prevent a warning below.
1050 *
1051 * As with the FirstXactSnapshot, we don't need to free resources of
1052 * the snapshot itself as it will go away with the memory context.
1053 */
1054 foreach(lc, exportedSnapshots)
1055 {
1056 ExportedSnapshot *esnap = (ExportedSnapshot *) lfirst(lc);
1057
1058 if (unlink(esnap->snapfile))
1059 elog(WARNING, "could not unlink file \"%s\": %m",
1060 esnap->snapfile);
1061
1063 &esnap->snapshot->ph_node);
1064 }
1065
1067 }
1068
1069 /* Drop catalog snapshot if any */
1071
1072 /* On commit, complain about leftover snapshots */
1073 if (isCommit)
1074 {
1075 ActiveSnapshotElt *active;
1076
1078 elog(WARNING, "registered snapshots seem to remain after cleanup");
1079
1080 /* complain about unpopped active snapshots */
1081 for (active = ActiveSnapshot; active != NULL; active = active->as_next)
1082 elog(WARNING, "snapshot %p still active", active);
1083 }
1084
1085 /*
1086 * And reset our state. We don't need to free the memory explicitly --
1087 * it'll go away with TopTransactionContext.
1088 */
1089 ActiveSnapshot = NULL;
1091
1092 CurrentSnapshot = NULL;
1093 SecondarySnapshot = NULL;
1094
1095 FirstSnapshotSet = false;
1096
1097 /*
1098 * During normal commit processing, we call ProcArrayEndTransaction() to
1099 * reset the MyProc->xmin. That call happens prior to the call to
1100 * AtEOXact_Snapshot(), so we need not touch xmin here at all.
1101 */
1102 if (resetXmin)
1104
1105 Assert(resetXmin || MyProc->xmin == 0);
1106}
1107
1108
1109/*
1110 * ExportSnapshot
1111 * Export the snapshot to a file so that other backends can import it.
1112 * Returns the token (the file name) that can be used to import this
1113 * snapshot.
1114 */
1115char *
1117{
1118 TransactionId topXid;
1119 TransactionId *children;
1120 ExportedSnapshot *esnap;
1121 int nchildren;
1122 int addTopXid;
1124 FILE *f;
1125 int i;
1126 MemoryContext oldcxt;
1127 char path[MAXPGPATH];
1128 char pathtmp[MAXPGPATH];
1129
1130 /*
1131 * It's tempting to call RequireTransactionBlock here, since it's not very
1132 * useful to export a snapshot that will disappear immediately afterwards.
1133 * However, we haven't got enough information to do that, since we don't
1134 * know if we're at top level or not. For example, we could be inside a
1135 * plpgsql function that is going to fire off other transactions via
1136 * dblink. Rather than disallow perfectly legitimate usages, don't make a
1137 * check.
1138 *
1139 * Also note that we don't make any restriction on the transaction's
1140 * isolation level; however, importers must check the level if they are
1141 * serializable.
1142 */
1143
1144 /*
1145 * Get our transaction ID if there is one, to include in the snapshot.
1146 */
1147 topXid = GetTopTransactionIdIfAny();
1148
1149 /*
1150 * We cannot export a snapshot from a subtransaction because there's no
1151 * easy way for importers to verify that the same subtransaction is still
1152 * running.
1153 */
1154 if (IsSubTransaction())
1155 ereport(ERROR,
1156 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1157 errmsg("cannot export a snapshot from a subtransaction")));
1158
1159 /*
1160 * We do however allow previous committed subtransactions to exist.
1161 * Importers of the snapshot must see them as still running, so get their
1162 * XIDs to add them to the snapshot.
1163 */
1164 nchildren = xactGetCommittedChildren(&children);
1165
1166 /*
1167 * Generate file path for the snapshot. We start numbering of snapshots
1168 * inside the transaction from 1.
1169 */
1170 snprintf(path, sizeof(path), SNAPSHOT_EXPORT_DIR "/%08X-%08X-%d",
1173
1174 /*
1175 * Copy the snapshot into TopTransactionContext, add it to the
1176 * exportedSnapshots list, and mark it pseudo-registered. We do this to
1177 * ensure that the snapshot's xmin is honored for the rest of the
1178 * transaction.
1179 */
1180 snapshot = CopySnapshot(snapshot);
1181
1183 esnap = (ExportedSnapshot *) palloc(sizeof(ExportedSnapshot));
1184 esnap->snapfile = pstrdup(path);
1185 esnap->snapshot = snapshot;
1187 MemoryContextSwitchTo(oldcxt);
1188
1189 snapshot->regd_count++;
1191
1192 /*
1193 * Fill buf with a text serialization of the snapshot, plus identification
1194 * data about this transaction. The format expected by ImportSnapshot is
1195 * pretty rigid: each line must be fieldname:value.
1196 */
1198
1199 appendStringInfo(&buf, "vxid:%d/%u\n", MyProc->vxid.procNumber, MyProc->vxid.lxid);
1200 appendStringInfo(&buf, "pid:%d\n", MyProcPid);
1201 appendStringInfo(&buf, "dbid:%u\n", MyDatabaseId);
1202 appendStringInfo(&buf, "iso:%d\n", XactIsoLevel);
1203 appendStringInfo(&buf, "ro:%d\n", XactReadOnly);
1204
1205 appendStringInfo(&buf, "xmin:%u\n", snapshot->xmin);
1206 appendStringInfo(&buf, "xmax:%u\n", snapshot->xmax);
1207
1208 /*
1209 * We must include our own top transaction ID in the top-xid data, since
1210 * by definition we will still be running when the importing transaction
1211 * adopts the snapshot, but GetSnapshotData never includes our own XID in
1212 * the snapshot. (There must, therefore, be enough room to add it.)
1213 *
1214 * However, it could be that our topXid is after the xmax, in which case
1215 * we shouldn't include it because xip[] members are expected to be before
1216 * xmax. (We need not make the same check for subxip[] members, see
1217 * snapshot.h.)
1218 */
1219 addTopXid = (TransactionIdIsValid(topXid) &&
1220 TransactionIdPrecedes(topXid, snapshot->xmax)) ? 1 : 0;
1221 appendStringInfo(&buf, "xcnt:%d\n", snapshot->xcnt + addTopXid);
1222 for (i = 0; i < snapshot->xcnt; i++)
1223 appendStringInfo(&buf, "xip:%u\n", snapshot->xip[i]);
1224 if (addTopXid)
1225 appendStringInfo(&buf, "xip:%u\n", topXid);
1226
1227 /*
1228 * Similarly, we add our subcommitted child XIDs to the subxid data. Here,
1229 * we have to cope with possible overflow.
1230 */
1231 if (snapshot->suboverflowed ||
1232 snapshot->subxcnt + nchildren > GetMaxSnapshotSubxidCount())
1233 appendStringInfoString(&buf, "sof:1\n");
1234 else
1235 {
1236 appendStringInfoString(&buf, "sof:0\n");
1237 appendStringInfo(&buf, "sxcnt:%d\n", snapshot->subxcnt + nchildren);
1238 for (i = 0; i < snapshot->subxcnt; i++)
1239 appendStringInfo(&buf, "sxp:%u\n", snapshot->subxip[i]);
1240 for (i = 0; i < nchildren; i++)
1241 appendStringInfo(&buf, "sxp:%u\n", children[i]);
1242 }
1243 appendStringInfo(&buf, "rec:%u\n", snapshot->takenDuringRecovery);
1244
1245 /*
1246 * Now write the text representation into a file. We first write to a
1247 * ".tmp" filename, and rename to final filename if no error. This
1248 * ensures that no other backend can read an incomplete file
1249 * (ImportSnapshot won't allow it because of its valid-characters check).
1250 */
1251 snprintf(pathtmp, sizeof(pathtmp), "%s.tmp", path);
1252 if (!(f = AllocateFile(pathtmp, PG_BINARY_W)))
1253 ereport(ERROR,
1255 errmsg("could not create file \"%s\": %m", pathtmp)));
1256
1257 if (fwrite(buf.data, buf.len, 1, f) != 1)
1258 ereport(ERROR,
1260 errmsg("could not write to file \"%s\": %m", pathtmp)));
1261
1262 /* no fsync() since file need not survive a system crash */
1263
1264 if (FreeFile(f))
1265 ereport(ERROR,
1267 errmsg("could not write to file \"%s\": %m", pathtmp)));
1268
1269 /*
1270 * Now that we have written everything into a .tmp file, rename the file
1271 * to remove the .tmp suffix.
1272 */
1273 if (rename(pathtmp, path) < 0)
1274 ereport(ERROR,
1276 errmsg("could not rename file \"%s\" to \"%s\": %m",
1277 pathtmp, path)));
1278
1279 /*
1280 * The basename of the file is what we return from pg_export_snapshot().
1281 * It's already in path in a textual format and we know that the path
1282 * starts with SNAPSHOT_EXPORT_DIR. Skip over the prefix and the slash
1283 * and pstrdup it so as not to return the address of a local variable.
1284 */
1285 return pstrdup(path + strlen(SNAPSHOT_EXPORT_DIR) + 1);
1286}
1287
1288/*
1289 * pg_export_snapshot
1290 * SQL-callable wrapper for ExportSnapshot.
1291 */
1292Datum
1294{
1295 char *snapshotName;
1296
1297 snapshotName = ExportSnapshot(GetActiveSnapshot());
1298 PG_RETURN_TEXT_P(cstring_to_text(snapshotName));
1299}
1300
1301
1302/*
1303 * Parsing subroutines for ImportSnapshot: parse a line with the given
1304 * prefix followed by a value, and advance *s to the next line. The
1305 * filename is provided for use in error messages.
1306 */
1307static int
1308parseIntFromText(const char *prefix, char **s, const char *filename)
1309{
1310 char *ptr = *s;
1311 int prefixlen = strlen(prefix);
1312 int val;
1313
1314 if (strncmp(ptr, prefix, prefixlen) != 0)
1315 ereport(ERROR,
1316 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1317 errmsg("invalid snapshot data in file \"%s\"", filename)));
1318 ptr += prefixlen;
1319 if (sscanf(ptr, "%d", &val) != 1)
1320 ereport(ERROR,
1321 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1322 errmsg("invalid snapshot data in file \"%s\"", filename)));
1323 ptr = strchr(ptr, '\n');
1324 if (!ptr)
1325 ereport(ERROR,
1326 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1327 errmsg("invalid snapshot data in file \"%s\"", filename)));
1328 *s = ptr + 1;
1329 return val;
1330}
1331
1332static TransactionId
1333parseXidFromText(const char *prefix, char **s, const char *filename)
1334{
1335 char *ptr = *s;
1336 int prefixlen = strlen(prefix);
1338
1339 if (strncmp(ptr, prefix, prefixlen) != 0)
1340 ereport(ERROR,
1341 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1342 errmsg("invalid snapshot data in file \"%s\"", filename)));
1343 ptr += prefixlen;
1344 if (sscanf(ptr, "%u", &val) != 1)
1345 ereport(ERROR,
1346 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1347 errmsg("invalid snapshot data in file \"%s\"", filename)));
1348 ptr = strchr(ptr, '\n');
1349 if (!ptr)
1350 ereport(ERROR,
1351 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1352 errmsg("invalid snapshot data in file \"%s\"", filename)));
1353 *s = ptr + 1;
1354 return val;
1355}
1356
1357static void
1358parseVxidFromText(const char *prefix, char **s, const char *filename,
1360{
1361 char *ptr = *s;
1362 int prefixlen = strlen(prefix);
1363
1364 if (strncmp(ptr, prefix, prefixlen) != 0)
1365 ereport(ERROR,
1366 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1367 errmsg("invalid snapshot data in file \"%s\"", filename)));
1368 ptr += prefixlen;
1369 if (sscanf(ptr, "%d/%u", &vxid->procNumber, &vxid->localTransactionId) != 2)
1370 ereport(ERROR,
1371 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1372 errmsg("invalid snapshot data in file \"%s\"", filename)));
1373 ptr = strchr(ptr, '\n');
1374 if (!ptr)
1375 ereport(ERROR,
1376 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1377 errmsg("invalid snapshot data in file \"%s\"", filename)));
1378 *s = ptr + 1;
1379}
1380
1381/*
1382 * ImportSnapshot
1383 * Import a previously exported snapshot. The argument should be a
1384 * filename in SNAPSHOT_EXPORT_DIR. Load the snapshot from that file.
1385 * This is called by "SET TRANSACTION SNAPSHOT 'foo'".
1386 */
1387void
1388ImportSnapshot(const char *idstr)
1389{
1390 char path[MAXPGPATH];
1391 FILE *f;
1392 struct stat stat_buf;
1393 char *filebuf;
1394 int xcnt;
1395 int i;
1396 VirtualTransactionId src_vxid;
1397 int src_pid;
1398 Oid src_dbid;
1399 int src_isolevel;
1400 bool src_readonly;
1401 SnapshotData snapshot;
1402
1403 /*
1404 * Must be at top level of a fresh transaction. Note in particular that
1405 * we check we haven't acquired an XID --- if we have, it's conceivable
1406 * that the snapshot would show it as not running, making for very screwy
1407 * behavior.
1408 */
1409 if (FirstSnapshotSet ||
1412 ereport(ERROR,
1413 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1414 errmsg("SET TRANSACTION SNAPSHOT must be called before any query")));
1415
1416 /*
1417 * If we are in read committed mode then the next query would execute with
1418 * a new snapshot thus making this function call quite useless.
1419 */
1421 ereport(ERROR,
1422 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1423 errmsg("a snapshot-importing transaction must have isolation level SERIALIZABLE or REPEATABLE READ")));
1424
1425 /*
1426 * Verify the identifier: only 0-9, A-F and hyphens are allowed. We do
1427 * this mainly to prevent reading arbitrary files.
1428 */
1429 if (strspn(idstr, "0123456789ABCDEF-") != strlen(idstr))
1430 ereport(ERROR,
1431 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1432 errmsg("invalid snapshot identifier: \"%s\"", idstr)));
1433
1434 /* OK, read the file */
1435 snprintf(path, MAXPGPATH, SNAPSHOT_EXPORT_DIR "/%s", idstr);
1436
1437 f = AllocateFile(path, PG_BINARY_R);
1438 if (!f)
1439 {
1440 /*
1441 * If file is missing while identifier has a correct format, avoid
1442 * system errors.
1443 */
1444 if (errno == ENOENT)
1445 ereport(ERROR,
1446 (errcode(ERRCODE_UNDEFINED_OBJECT),
1447 errmsg("snapshot \"%s\" does not exist", idstr)));
1448 else
1449 ereport(ERROR,
1451 errmsg("could not open file \"%s\" for reading: %m",
1452 path)));
1453 }
1454
1455 /* get the size of the file so that we know how much memory we need */
1456 if (fstat(fileno(f), &stat_buf))
1457 elog(ERROR, "could not stat file \"%s\": %m", path);
1458
1459 /* and read the file into a palloc'd string */
1460 filebuf = (char *) palloc(stat_buf.st_size + 1);
1461 if (fread(filebuf, stat_buf.st_size, 1, f) != 1)
1462 elog(ERROR, "could not read file \"%s\": %m", path);
1463
1464 filebuf[stat_buf.st_size] = '\0';
1465
1466 FreeFile(f);
1467
1468 /*
1469 * Construct a snapshot struct by parsing the file content.
1470 */
1471 memset(&snapshot, 0, sizeof(snapshot));
1472
1473 parseVxidFromText("vxid:", &filebuf, path, &src_vxid);
1474 src_pid = parseIntFromText("pid:", &filebuf, path);
1475 /* we abuse parseXidFromText a bit here ... */
1476 src_dbid = parseXidFromText("dbid:", &filebuf, path);
1477 src_isolevel = parseIntFromText("iso:", &filebuf, path);
1478 src_readonly = parseIntFromText("ro:", &filebuf, path);
1479
1480 snapshot.snapshot_type = SNAPSHOT_MVCC;
1481
1482 snapshot.xmin = parseXidFromText("xmin:", &filebuf, path);
1483 snapshot.xmax = parseXidFromText("xmax:", &filebuf, path);
1484
1485 snapshot.xcnt = xcnt = parseIntFromText("xcnt:", &filebuf, path);
1486
1487 /* sanity-check the xid count before palloc */
1488 if (xcnt < 0 || xcnt > GetMaxSnapshotXidCount())
1489 ereport(ERROR,
1490 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1491 errmsg("invalid snapshot data in file \"%s\"", path)));
1492
1493 snapshot.xip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
1494 for (i = 0; i < xcnt; i++)
1495 snapshot.xip[i] = parseXidFromText("xip:", &filebuf, path);
1496
1497 snapshot.suboverflowed = parseIntFromText("sof:", &filebuf, path);
1498
1499 if (!snapshot.suboverflowed)
1500 {
1501 snapshot.subxcnt = xcnt = parseIntFromText("sxcnt:", &filebuf, path);
1502
1503 /* sanity-check the xid count before palloc */
1504 if (xcnt < 0 || xcnt > GetMaxSnapshotSubxidCount())
1505 ereport(ERROR,
1506 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1507 errmsg("invalid snapshot data in file \"%s\"", path)));
1508
1509 snapshot.subxip = (TransactionId *) palloc(xcnt * sizeof(TransactionId));
1510 for (i = 0; i < xcnt; i++)
1511 snapshot.subxip[i] = parseXidFromText("sxp:", &filebuf, path);
1512 }
1513 else
1514 {
1515 snapshot.subxcnt = 0;
1516 snapshot.subxip = NULL;
1517 }
1518
1519 snapshot.takenDuringRecovery = parseIntFromText("rec:", &filebuf, path);
1520
1521 /*
1522 * Do some additional sanity checking, just to protect ourselves. We
1523 * don't trouble to check the array elements, just the most critical
1524 * fields.
1525 */
1526 if (!VirtualTransactionIdIsValid(src_vxid) ||
1527 !OidIsValid(src_dbid) ||
1528 !TransactionIdIsNormal(snapshot.xmin) ||
1529 !TransactionIdIsNormal(snapshot.xmax))
1530 ereport(ERROR,
1531 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1532 errmsg("invalid snapshot data in file \"%s\"", path)));
1533
1534 /*
1535 * If we're serializable, the source transaction must be too, otherwise
1536 * predicate.c has problems (SxactGlobalXmin could go backwards). Also, a
1537 * non-read-only transaction can't adopt a snapshot from a read-only
1538 * transaction, as predicate.c handles the cases very differently.
1539 */
1541 {
1542 if (src_isolevel != XACT_SERIALIZABLE)
1543 ereport(ERROR,
1544 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1545 errmsg("a serializable transaction cannot import a snapshot from a non-serializable transaction")));
1546 if (src_readonly && !XactReadOnly)
1547 ereport(ERROR,
1548 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1549 errmsg("a non-read-only serializable transaction cannot import a snapshot from a read-only transaction")));
1550 }
1551
1552 /*
1553 * We cannot import a snapshot that was taken in a different database,
1554 * because vacuum calculates OldestXmin on a per-database basis; so the
1555 * source transaction's xmin doesn't protect us from data loss. This
1556 * restriction could be removed if the source transaction were to mark its
1557 * xmin as being globally applicable. But that would require some
1558 * additional syntax, since that has to be known when the snapshot is
1559 * initially taken. (See pgsql-hackers discussion of 2011-10-21.)
1560 */
1561 if (src_dbid != MyDatabaseId)
1562 ereport(ERROR,
1563 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1564 errmsg("cannot import a snapshot from a different database")));
1565
1566 /* OK, install the snapshot */
1567 SetTransactionSnapshot(&snapshot, &src_vxid, src_pid, NULL);
1568}
1569
1570/*
1571 * XactHasExportedSnapshots
1572 * Test whether current transaction has exported any snapshots.
1573 */
1574bool
1576{
1577 return (exportedSnapshots != NIL);
1578}
1579
1580/*
1581 * DeleteAllExportedSnapshotFiles
1582 * Clean up any files that have been left behind by a crashed backend
1583 * that had exported snapshots before it died.
1584 *
1585 * This should be called during database startup or crash recovery.
1586 */
1587void
1589{
1590 char buf[MAXPGPATH + sizeof(SNAPSHOT_EXPORT_DIR)];
1591 DIR *s_dir;
1592 struct dirent *s_de;
1593
1594 /*
1595 * Problems in reading the directory, or unlinking files, are reported at
1596 * LOG level. Since we're running in the startup process, ERROR level
1597 * would prevent database start, and it's not important enough for that.
1598 */
1600
1601 while ((s_de = ReadDirExtended(s_dir, SNAPSHOT_EXPORT_DIR, LOG)) != NULL)
1602 {
1603 if (strcmp(s_de->d_name, ".") == 0 ||
1604 strcmp(s_de->d_name, "..") == 0)
1605 continue;
1606
1607 snprintf(buf, sizeof(buf), SNAPSHOT_EXPORT_DIR "/%s", s_de->d_name);
1608
1609 if (unlink(buf) != 0)
1610 ereport(LOG,
1612 errmsg("could not remove file \"%s\": %m", buf)));
1613 }
1614
1615 FreeDir(s_dir);
1616}
1617
1618/*
1619 * ThereAreNoPriorRegisteredSnapshots
1620 * Is the registered snapshot count less than or equal to one?
1621 *
1622 * Don't use this to settle important decisions. While zero registrations and
1623 * no ActiveSnapshot would confirm a certain idleness, the system makes no
1624 * guarantees about the significance of one registered snapshot.
1625 */
1626bool
1628{
1631 return true;
1632
1633 return false;
1634}
1635
1636/*
1637 * HaveRegisteredOrActiveSnapshot
1638 * Is there any registered or active snapshot?
1639 *
1640 * NB: Unless pushed or active, the cached catalog snapshot will not cause
1641 * this function to return true. That allows this function to be used in
1642 * checks enforcing a longer-lived snapshot.
1643 */
1644bool
1646{
1647 if (ActiveSnapshot != NULL)
1648 return true;
1649
1650 /*
1651 * The catalog snapshot is in RegisteredSnapshots when valid, but can be
1652 * removed at any time due to invalidation processing. If explicitly
1653 * registered more than one snapshot has to be in RegisteredSnapshots.
1654 */
1655 if (CatalogSnapshot != NULL &&
1657 return false;
1658
1660}
1661
1662
1663/*
1664 * Setup a snapshot that replaces normal catalog snapshots that allows catalog
1665 * access to behave just like it did at a certain point in the past.
1666 *
1667 * Needed for logical decoding.
1668 */
1669void
1670SetupHistoricSnapshot(Snapshot historic_snapshot, HTAB *tuplecids)
1671{
1672 Assert(historic_snapshot != NULL);
1673
1674 /* setup the timetravel snapshot */
1675 HistoricSnapshot = historic_snapshot;
1676
1677 /* setup (cmin, cmax) lookup hash */
1678 tuplecid_data = tuplecids;
1679}
1680
1681
1682/*
1683 * Make catalog snapshots behave normally again.
1684 */
1685void
1687{
1688 HistoricSnapshot = NULL;
1689 tuplecid_data = NULL;
1690}
1691
1692bool
1694{
1695 return HistoricSnapshot != NULL;
1696}
1697
1698HTAB *
1700{
1702 return tuplecid_data;
1703}
1704
1705/*
1706 * EstimateSnapshotSpace
1707 * Returns the size needed to store the given snapshot.
1708 *
1709 * We are exporting only required fields from the Snapshot, stored in
1710 * SerializedSnapshotData.
1711 */
1712Size
1714{
1715 Size size;
1716
1717 Assert(snapshot != InvalidSnapshot);
1718 Assert(snapshot->snapshot_type == SNAPSHOT_MVCC);
1719
1720 /* We allocate any XID arrays needed in the same palloc block. */
1721 size = add_size(sizeof(SerializedSnapshotData),
1722 mul_size(snapshot->xcnt, sizeof(TransactionId)));
1723 if (snapshot->subxcnt > 0 &&
1724 (!snapshot->suboverflowed || snapshot->takenDuringRecovery))
1725 size = add_size(size,
1726 mul_size(snapshot->subxcnt, sizeof(TransactionId)));
1727
1728 return size;
1729}
1730
1731/*
1732 * SerializeSnapshot
1733 * Dumps the serialized snapshot (extracted from given snapshot) onto the
1734 * memory location at start_address.
1735 */
1736void
1737SerializeSnapshot(Snapshot snapshot, char *start_address)
1738{
1739 SerializedSnapshotData serialized_snapshot;
1740
1741 Assert(snapshot->subxcnt >= 0);
1742
1743 /* Copy all required fields */
1744 serialized_snapshot.xmin = snapshot->xmin;
1745 serialized_snapshot.xmax = snapshot->xmax;
1746 serialized_snapshot.xcnt = snapshot->xcnt;
1747 serialized_snapshot.subxcnt = snapshot->subxcnt;
1748 serialized_snapshot.suboverflowed = snapshot->suboverflowed;
1749 serialized_snapshot.takenDuringRecovery = snapshot->takenDuringRecovery;
1750 serialized_snapshot.curcid = snapshot->curcid;
1751
1752 /*
1753 * Ignore the SubXID array if it has overflowed, unless the snapshot was
1754 * taken during recovery - in that case, top-level XIDs are in subxip as
1755 * well, and we mustn't lose them.
1756 */
1757 if (serialized_snapshot.suboverflowed && !snapshot->takenDuringRecovery)
1758 serialized_snapshot.subxcnt = 0;
1759
1760 /* Copy struct to possibly-unaligned buffer */
1761 memcpy(start_address,
1762 &serialized_snapshot, sizeof(SerializedSnapshotData));
1763
1764 /* Copy XID array */
1765 if (snapshot->xcnt > 0)
1766 memcpy((TransactionId *) (start_address +
1767 sizeof(SerializedSnapshotData)),
1768 snapshot->xip, snapshot->xcnt * sizeof(TransactionId));
1769
1770 /*
1771 * Copy SubXID array. Don't bother to copy it if it had overflowed,
1772 * though, because it's not used anywhere in that case. Except if it's a
1773 * snapshot taken during recovery; all the top-level XIDs are in subxip as
1774 * well in that case, so we mustn't lose them.
1775 */
1776 if (serialized_snapshot.subxcnt > 0)
1777 {
1778 Size subxipoff = sizeof(SerializedSnapshotData) +
1779 snapshot->xcnt * sizeof(TransactionId);
1780
1781 memcpy((TransactionId *) (start_address + subxipoff),
1782 snapshot->subxip, snapshot->subxcnt * sizeof(TransactionId));
1783 }
1784}
1785
1786/*
1787 * RestoreSnapshot
1788 * Restore a serialized snapshot from the specified address.
1789 *
1790 * The copy is palloc'd in TopTransactionContext and has initial refcounts set
1791 * to 0. The returned snapshot has the copied flag set.
1792 */
1794RestoreSnapshot(char *start_address)
1795{
1796 SerializedSnapshotData serialized_snapshot;
1797 Size size;
1798 Snapshot snapshot;
1799 TransactionId *serialized_xids;
1800
1801 memcpy(&serialized_snapshot, start_address,
1802 sizeof(SerializedSnapshotData));
1803 serialized_xids = (TransactionId *)
1804 (start_address + sizeof(SerializedSnapshotData));
1805
1806 /* We allocate any XID arrays needed in the same palloc block. */
1807 size = sizeof(SnapshotData)
1808 + serialized_snapshot.xcnt * sizeof(TransactionId)
1809 + serialized_snapshot.subxcnt * sizeof(TransactionId);
1810
1811 /* Copy all required fields */
1813 snapshot->snapshot_type = SNAPSHOT_MVCC;
1814 snapshot->xmin = serialized_snapshot.xmin;
1815 snapshot->xmax = serialized_snapshot.xmax;
1816 snapshot->xip = NULL;
1817 snapshot->xcnt = serialized_snapshot.xcnt;
1818 snapshot->subxip = NULL;
1819 snapshot->subxcnt = serialized_snapshot.subxcnt;
1820 snapshot->suboverflowed = serialized_snapshot.suboverflowed;
1821 snapshot->takenDuringRecovery = serialized_snapshot.takenDuringRecovery;
1822 snapshot->curcid = serialized_snapshot.curcid;
1823 snapshot->snapXactCompletionCount = 0;
1824
1825 /* Copy XIDs, if present. */
1826 if (serialized_snapshot.xcnt > 0)
1827 {
1828 snapshot->xip = (TransactionId *) (snapshot + 1);
1829 memcpy(snapshot->xip, serialized_xids,
1830 serialized_snapshot.xcnt * sizeof(TransactionId));
1831 }
1832
1833 /* Copy SubXIDs, if present. */
1834 if (serialized_snapshot.subxcnt > 0)
1835 {
1836 snapshot->subxip = ((TransactionId *) (snapshot + 1)) +
1837 serialized_snapshot.xcnt;
1838 memcpy(snapshot->subxip, serialized_xids + serialized_snapshot.xcnt,
1839 serialized_snapshot.subxcnt * sizeof(TransactionId));
1840 }
1841
1842 /* Set the copied flag so that the caller will set refcounts correctly. */
1843 snapshot->regd_count = 0;
1844 snapshot->active_count = 0;
1845 snapshot->copied = true;
1846
1847 return snapshot;
1848}
1849
1850/*
1851 * Install a restored snapshot as the transaction snapshot.
1852 *
1853 * The second argument is of type void * so that snapmgr.h need not include
1854 * the declaration for PGPROC.
1855 */
1856void
1857RestoreTransactionSnapshot(Snapshot snapshot, void *source_pgproc)
1858{
1859 SetTransactionSnapshot(snapshot, NULL, InvalidPid, source_pgproc);
1860}
1861
1862/*
1863 * XidInMVCCSnapshot
1864 * Is the given XID still-in-progress according to the snapshot?
1865 *
1866 * Note: GetSnapshotData never stores either top xid or subxids of our own
1867 * backend into a snapshot, so these xids will not be reported as "running"
1868 * by this function. This is OK for current uses, because we always check
1869 * TransactionIdIsCurrentTransactionId first, except when it's known the
1870 * XID could not be ours anyway.
1871 */
1872bool
1874{
1875 /*
1876 * Make a quick range check to eliminate most XIDs without looking at the
1877 * xip arrays. Note that this is OK even if we convert a subxact XID to
1878 * its parent below, because a subxact with XID < xmin has surely also got
1879 * a parent with XID < xmin, while one with XID >= xmax must belong to a
1880 * parent that was not yet committed at the time of this snapshot.
1881 */
1882
1883 /* Any xid < xmin is not in-progress */
1884 if (TransactionIdPrecedes(xid, snapshot->xmin))
1885 return false;
1886 /* Any xid >= xmax is in-progress */
1887 if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
1888 return true;
1889
1890 /*
1891 * Snapshot information is stored slightly differently in snapshots taken
1892 * during recovery.
1893 */
1894 if (!snapshot->takenDuringRecovery)
1895 {
1896 /*
1897 * If the snapshot contains full subxact data, the fastest way to
1898 * check things is just to compare the given XID against both subxact
1899 * XIDs and top-level XIDs. If the snapshot overflowed, we have to
1900 * use pg_subtrans to convert a subxact XID to its parent XID, but
1901 * then we need only look at top-level XIDs not subxacts.
1902 */
1903 if (!snapshot->suboverflowed)
1904 {
1905 /* we have full data, so search subxip */
1906 if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
1907 return true;
1908
1909 /* not there, fall through to search xip[] */
1910 }
1911 else
1912 {
1913 /*
1914 * Snapshot overflowed, so convert xid to top-level. This is safe
1915 * because we eliminated too-old XIDs above.
1916 */
1918
1919 /*
1920 * If xid was indeed a subxact, we might now have an xid < xmin,
1921 * so recheck to avoid an array scan. No point in rechecking
1922 * xmax.
1923 */
1924 if (TransactionIdPrecedes(xid, snapshot->xmin))
1925 return false;
1926 }
1927
1928 if (pg_lfind32(xid, snapshot->xip, snapshot->xcnt))
1929 return true;
1930 }
1931 else
1932 {
1933 /*
1934 * In recovery we store all xids in the subxip array because it is by
1935 * far the bigger array, and we mostly don't know which xids are
1936 * top-level and which are subxacts. The xip array is empty.
1937 *
1938 * We start by searching subtrans, if we overflowed.
1939 */
1940 if (snapshot->suboverflowed)
1941 {
1942 /*
1943 * Snapshot overflowed, so convert xid to top-level. This is safe
1944 * because we eliminated too-old XIDs above.
1945 */
1947
1948 /*
1949 * If xid was indeed a subxact, we might now have an xid < xmin,
1950 * so recheck to avoid an array scan. No point in rechecking
1951 * xmax.
1952 */
1953 if (TransactionIdPrecedes(xid, snapshot->xmin))
1954 return false;
1955 }
1956
1957 /*
1958 * We now have either a top-level xid higher than xmin or an
1959 * indeterminate xid. We don't know whether it's top level or subxact
1960 * but it doesn't matter. If it's present, the xid is visible.
1961 */
1962 if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
1963 return true;
1964 }
1965
1966 return false;
1967}
1968
1969/* ResourceOwner callbacks */
1970
1971static void
1973{
1975}
static int32 next
Definition: blutils.c:224
#define PG_BINARY_R
Definition: c.h:1265
int32_t int32
Definition: c.h:539
uint32_t uint32
Definition: c.h:543
#define PG_BINARY_W
Definition: c.h:1266
uint32 CommandId
Definition: c.h:676
uint32 TransactionId
Definition: c.h:662
#define OidIsValid(objectId)
Definition: c.h:779
size_t Size
Definition: c.h:615
int errcode_for_file_access(void)
Definition: elog.c:886
int errdetail(const char *fmt,...)
Definition: elog.c:1216
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define LOG
Definition: elog.h:31
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
int FreeDir(DIR *dir)
Definition: fd.c:3022
int FreeFile(FILE *file)
Definition: fd.c:2840
struct dirent * ReadDirExtended(DIR *dir, const char *dirname, int elevel)
Definition: fd.c:2985
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2904
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2641
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
int MyProcPid
Definition: globals.c:47
Oid MyDatabaseId
Definition: globals.c:94
Assert(PointerIsAligned(start, uint64))
long val
Definition: informix.c:689
#define INJECTION_POINT(name, arg)
int b
Definition: isn.c:74
int a
Definition: isn.c:73
int i
Definition: isn.c:77
List * lappend(List *list, void *datum)
Definition: list.c:339
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:69
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
MemoryContext TopTransactionContext
Definition: mcxt.c:171
char * pstrdup(const char *in)
Definition: mcxt.c:1759
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc(Size size)
Definition: mcxt.c:1365
#define InvalidPid
Definition: miscadmin.h:32
void pairingheap_remove(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:184
void pairingheap_add(pairingheap *heap, pairingheap_node *node)
Definition: pairingheap.c:126
pairingheap_node * pairingheap_first(pairingheap *heap)
Definition: pairingheap.c:144
#define pairingheap_is_empty(h)
Definition: pairingheap.h:99
#define pairingheap_is_singular(h)
Definition: pairingheap.h:102
#define pairingheap_container(type, membername, ptr)
Definition: pairingheap.h:43
#define pairingheap_const_container(type, membername, ptr)
Definition: pairingheap.h:51
#define pairingheap_reset(h)
Definition: pairingheap.h:96
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
void * arg
#define MAXPGPATH
static char * filename
Definition: pg_dumpall.c:120
static bool pg_lfind32(uint32 key, const uint32 *base, uint32 nelem)
Definition: pg_lfind.h:153
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:260
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
uint64_t Datum
Definition: postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
unsigned int Oid
Definition: postgres_ext.h:32
void SetSerializableTransactionSnapshot(Snapshot snapshot, VirtualTransactionId *sourcevxid, int sourcepid)
Definition: predicate.c:1722
Snapshot GetSerializableTransactionSnapshot(Snapshot snapshot)
Definition: predicate.c:1682
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:2028
Snapshot GetSnapshotData(Snapshot snapshot)
Definition: procarray.c:2123
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:2017
bool ProcArrayInstallRestoredXmin(TransactionId xmin, PGPROC *proc)
Definition: procarray.c:2564
bool ProcArrayInstallImportedXmin(TransactionId xmin, VirtualTransactionId *sourcevxid)
Definition: procarray.c:2480
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:561
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:521
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:449
#define RELEASE_PRIO_SNAPSHOT_REFS
Definition: resowner.h:75
@ RESOURCE_RELEASE_AFTER_LOCKS
Definition: resowner.h:56
Size add_size(Size s1, Size s2)
Definition: shmem.c:495
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510
static Snapshot HistoricSnapshot
Definition: snapmgr.c:152
static Snapshot FirstXactSnapshot
Definition: snapmgr.c:200
TransactionId RecentXmin
Definition: snapmgr.c:160
static SnapshotData CatalogSnapshotData
Definition: snapmgr.c:143
void UnregisterSnapshotFromOwner(Snapshot snapshot, ResourceOwner owner)
Definition: snapmgr.c:880
static void SetTransactionSnapshot(Snapshot sourcesnap, VirtualTransactionId *sourcevxid, int sourcepid, PGPROC *sourceproc)
Definition: snapmgr.c:512
void AtSubAbort_Snapshot(int level)
Definition: snapmgr.c:983
void SerializeSnapshot(Snapshot snapshot, char *start_address)
Definition: snapmgr.c:1737
SnapshotData SnapshotSelfData
Definition: snapmgr.c:144
void AtEOXact_Snapshot(bool isCommit, bool resetXmin)
Definition: snapmgr.c:1017
struct ActiveSnapshotElt ActiveSnapshotElt
static Snapshot CurrentSnapshot
Definition: snapmgr.c:149
static Snapshot SecondarySnapshot
Definition: snapmgr.c:150
bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
Definition: snapmgr.c:1873
static List * exportedSnapshots
Definition: snapmgr.c:213
static pairingheap RegisteredSnapshots
Definition: snapmgr.c:190
bool FirstSnapshotSet
Definition: snapmgr.c:193
static void UnregisterSnapshotNoOwner(Snapshot snapshot)
Definition: snapmgr.c:890
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:272
Snapshot GetLatestSnapshot(void)
Definition: snapmgr.c:354
void TeardownHistoricSnapshot(bool is_error)
Definition: snapmgr.c:1686
Snapshot GetCatalogSnapshot(Oid relid)
Definition: snapmgr.c:385
void UnregisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:867
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:683
static Snapshot CopySnapshot(Snapshot snapshot)
Definition: snapmgr.c:609
Snapshot RestoreSnapshot(char *start_address)
Definition: snapmgr.c:1794
void AtSubCommit_Snapshot(int level)
Definition: snapmgr.c:962
static void ResourceOwnerRememberSnapshot(ResourceOwner owner, Snapshot snap)
Definition: snapmgr.c:235
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:745
static void SnapshotResetXmin(void)
Definition: snapmgr.c:938
static int parseIntFromText(const char *prefix, char **s, const char *filename)
Definition: snapmgr.c:1308
static SnapshotData SecondarySnapshotData
Definition: snapmgr.c:142
static int xmin_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
Definition: snapmgr.c:911
TransactionId TransactionXmin
Definition: snapmgr.c:159
SnapshotData SnapshotAnyData
Definition: snapmgr.c:145
bool HistoricSnapshotActive(void)
Definition: snapmgr.c:1693
void ImportSnapshot(const char *idstr)
Definition: snapmgr.c:1388
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:813
Snapshot RegisterSnapshot(Snapshot snapshot)
Definition: snapmgr.c:825
bool XactHasExportedSnapshots(void)
Definition: snapmgr.c:1575
static const ResourceOwnerDesc snapshot_resowner_desc
Definition: snapmgr.c:224
void DeleteAllExportedSnapshotFiles(void)
Definition: snapmgr.c:1588
static void parseVxidFromText(const char *prefix, char **s, const char *filename, VirtualTransactionId *vxid)
Definition: snapmgr.c:1358
static void FreeSnapshot(Snapshot snapshot)
Definition: snapmgr.c:665
#define SNAPSHOT_EXPORT_DIR
Definition: snapmgr.c:203
bool HaveRegisteredOrActiveSnapshot(void)
Definition: snapmgr.c:1645
void InvalidateCatalogSnapshotConditionally(void)
Definition: snapmgr.c:478
static SnapshotData CurrentSnapshotData
Definition: snapmgr.c:141
SnapshotData SnapshotToastData
Definition: snapmgr.c:146
static void ResourceOwnerForgetSnapshot(ResourceOwner owner, Snapshot snap)
Definition: snapmgr.c:240
bool ThereAreNoPriorRegisteredSnapshots(void)
Definition: snapmgr.c:1627
void RestoreTransactionSnapshot(Snapshot snapshot, void *source_pgproc)
Definition: snapmgr.c:1857
void SnapshotSetCommandId(CommandId curcid)
Definition: snapmgr.c:491
struct SerializedSnapshotData SerializedSnapshotData
void PopActiveSnapshot(void)
Definition: snapmgr.c:776
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:733
char * ExportSnapshot(Snapshot snapshot)
Definition: snapmgr.c:1116
Size EstimateSnapshotSpace(Snapshot snapshot)
Definition: snapmgr.c:1713
static ActiveSnapshotElt * ActiveSnapshot
Definition: snapmgr.c:181
void SetupHistoricSnapshot(Snapshot historic_snapshot, HTAB *tuplecids)
Definition: snapmgr.c:1670
static HTAB * tuplecid_data
Definition: snapmgr.c:163
Snapshot RegisterSnapshotOnOwner(Snapshot snapshot, ResourceOwner owner)
Definition: snapmgr.c:838
static TransactionId parseXidFromText(const char *prefix, char **s, const char *filename)
Definition: snapmgr.c:1333
HTAB * HistoricSnapshotGetTupleCids(void)
Definition: snapmgr.c:1699
void InvalidateCatalogSnapshot(void)
Definition: snapmgr.c:455
void PushActiveSnapshotWithLevel(Snapshot snapshot, int snap_level)
Definition: snapmgr.c:697
Snapshot GetNonHistoricCatalogSnapshot(Oid relid)
Definition: snapmgr.c:407
struct ExportedSnapshot ExportedSnapshot
static Snapshot CatalogSnapshot
Definition: snapmgr.c:151
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:801
Datum pg_export_snapshot(PG_FUNCTION_ARGS)
Definition: snapmgr.c:1293
static void ResOwnerReleaseSnapshot(Datum res)
Definition: snapmgr.c:1972
struct SnapshotData * Snapshot
Definition: snapshot.h:117
struct SnapshotData SnapshotData
@ SNAPSHOT_TOAST
Definition: snapshot.h:70
@ SNAPSHOT_SELF
Definition: snapshot.h:60
@ SNAPSHOT_MVCC
Definition: snapshot.h:46
@ SNAPSHOT_ANY
Definition: snapshot.h:65
#define InvalidSnapshot
Definition: snapshot.h:119
PGPROC * MyProc
Definition: proc.c:67
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
struct ActiveSnapshotElt * as_next
Definition: snapmgr.c:177
Snapshot as_snap
Definition: snapmgr.c:175
Definition: dirent.c:26
char * snapfile
Definition: snapmgr.c:208
Snapshot snapshot
Definition: snapmgr.c:209
Definition: dynahash.c:222
Definition: pg_list.h:54
Definition: proc.h:179
TransactionId xmin
Definition: proc.h:194
LocalTransactionId lxid
Definition: proc.h:217
struct PGPROC::@130 vxid
ProcNumber procNumber
Definition: proc.h:212
const char * name
Definition: resowner.h:93
TransactionId xmax
Definition: snapmgr.c:254
TransactionId xmin
Definition: snapmgr.c:253
TransactionId xmin
Definition: snapshot.h:153
int32 subxcnt
Definition: snapshot.h:177
bool copied
Definition: snapshot.h:181
uint32 regd_count
Definition: snapshot.h:201
uint32 active_count
Definition: snapshot.h:200
CommandId curcid
Definition: snapshot.h:183
pairingheap_node ph_node
Definition: snapshot.h:202
uint32 xcnt
Definition: snapshot.h:165
TransactionId * subxip
Definition: snapshot.h:176
uint64 snapXactCompletionCount
Definition: snapshot.h:209
TransactionId xmax
Definition: snapshot.h:154
SnapshotType snapshot_type
Definition: snapshot.h:140
TransactionId * xip
Definition: snapshot.h:164
bool suboverflowed
Definition: snapshot.h:178
bool takenDuringRecovery
Definition: snapshot.h:180
LocalTransactionId localTransactionId
Definition: lock.h:64
ProcNumber procNumber
Definition: lock.h:63
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15
__int64 st_size
Definition: win32_port.h:263
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:162
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:737
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:714
static bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.h:297
#define InvalidTransactionId
Definition: transam.h:31
static bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.h:312
#define FirstNormalTransactionId
Definition: transam.h:34
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.h:263
text * cstring_to_text(const char *s)
Definition: varlena.c:181
#define fstat
Definition: win32_port.h:273
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:930
bool XactReadOnly
Definition: xact.c:83
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:442
int XactIsoLevel
Definition: xact.c:80
bool IsSubTransaction(void)
Definition: xact.c:5062
bool IsInParallelMode(void)
Definition: xact.c:1090
int xactGetCommittedChildren(TransactionId **ptr)
Definition: xact.c:5808
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:830
#define XACT_SERIALIZABLE
Definition: xact.h:39
#define IsolationUsesXactSnapshot()
Definition: xact.h:52
#define IsolationIsSerializable()
Definition: xact.h:53