Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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