Fix oversight in previous error-reporting patch; mustn't pfree path string
[PostgreSQL.git] / src / backend / utils / time / snapmgr.c
blob1ab405a285ec0501561a60e74337f81f9ed8e84b
1 /*-------------------------------------------------------------------------
2 * snapmgr.c
3 * PostgreSQL snapshot manager
5 * We keep track of snapshots in two ways: the "registered snapshots" list,
6 * and the "active snapshot" stack. All snapshots in either of them live in
7 * persistent memory. When a snapshot is no longer in any of these lists
8 * (tracked by separate refcounts on each snapshot), its memory can be freed.
10 * These arrangements let us reset MyProc->xmin when there are no snapshots
11 * referenced by this transaction. (One possible improvement would be to be
12 * able to advance Xmin when the snapshot with the earliest Xmin is no longer
13 * referenced. That's a bit harder though, it requires more locking, and
14 * anyway it should be rather uncommon to keep snapshots referenced for too
15 * long.)
17 * Note: parts of this code could probably be replaced by appropriate use
18 * of resowner.c.
21 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
22 * Portions Copyright (c) 1994, Regents of the University of California
24 * IDENTIFICATION
25 * $PostgreSQL$
27 *-------------------------------------------------------------------------
29 #include "postgres.h"
31 #include "access/transam.h"
32 #include "access/xact.h"
33 #include "storage/proc.h"
34 #include "storage/procarray.h"
35 #include "utils/memutils.h"
36 #include "utils/memutils.h"
37 #include "utils/snapmgr.h"
38 #include "utils/tqual.h"
42 * CurrentSnapshot points to the only snapshot taken in a serializable
43 * transaction, and to the latest one taken in a read-committed transaction.
44 * SecondarySnapshot is a snapshot that's always up-to-date as of the current
45 * instant, even on a serializable transaction. It should only be used for
46 * special-purpose code (say, RI checking.)
48 * These SnapshotData structs are static to simplify memory allocation
49 * (see the hack in GetSnapshotData to avoid repeated malloc/free).
51 static SnapshotData CurrentSnapshotData = {HeapTupleSatisfiesMVCC};
52 static SnapshotData SecondarySnapshotData = {HeapTupleSatisfiesMVCC};
54 /* Pointers to valid snapshots */
55 static Snapshot CurrentSnapshot = NULL;
56 static Snapshot SecondarySnapshot = NULL;
59 * These are updated by GetSnapshotData. We initialize them this way
60 * for the convenience of TransactionIdIsInProgress: even in bootstrap
61 * mode, we don't want it to say that BootstrapTransactionId is in progress.
63 * RecentGlobalXmin is initialized to InvalidTransactionId, to ensure that no
64 * one tries to use a stale value. Readers should ensure that it has been set
65 * to something else before using it.
67 TransactionId TransactionXmin = FirstNormalTransactionId;
68 TransactionId RecentXmin = FirstNormalTransactionId;
69 TransactionId RecentGlobalXmin = InvalidTransactionId;
72 * Elements of the list of registered snapshots.
74 * Note that we keep refcounts both here and in SnapshotData. This is because
75 * the same snapshot may be registered more than once in a subtransaction, and
76 * if a subxact aborts we want to be able to subtract the correct amount of
77 * counts from SnapshotData. (Another approach would be keeping one
78 * RegdSnapshotElt each time a snapshot is registered, but that seems
79 * unnecessary wastage.)
81 * NB: the code assumes that elements in this list are in non-increasing
82 * order of s_level; also, the list must be NULL-terminated.
84 typedef struct RegdSnapshotElt
86 Snapshot s_snap;
87 uint32 s_count;
88 int s_level;
89 struct RegdSnapshotElt *s_next;
90 } RegdSnapshotElt;
93 * Elements of the active snapshot stack.
95 * It's not necessary to keep a refcount like we do for the registered list;
96 * each element here accounts for exactly one active_count on SnapshotData.
97 * We cannot condense them like we do for RegdSnapshotElt because it would mess
98 * up the order of entries in the stack.
100 * NB: the code assumes that elements in this list are in non-increasing
101 * order of as_level; also, the list must be NULL-terminated.
103 typedef struct ActiveSnapshotElt
105 Snapshot as_snap;
106 int as_level;
107 struct ActiveSnapshotElt *as_next;
108 } ActiveSnapshotElt;
110 /* Head of the list of registered snapshots */
111 static RegdSnapshotElt *RegisteredSnapshotList = NULL;
113 /* Top of the stack of active snapshots */
114 static ActiveSnapshotElt *ActiveSnapshot = NULL;
116 /* first GetTransactionSnapshot call in a transaction? */
117 bool FirstSnapshotSet = false;
120 * Remembers whether this transaction registered a serializable snapshot at
121 * start. We cannot trust FirstSnapshotSet in combination with
122 * IsXactIsoLevelSerializable, because GUC may be reset before us.
124 static bool registered_serializable = false;
127 static Snapshot CopySnapshot(Snapshot snapshot);
128 static void FreeSnapshot(Snapshot snapshot);
129 static void SnapshotResetXmin(void);
133 * GetTransactionSnapshot
134 * Get the appropriate snapshot for a new query in a transaction.
137 * Note that the return value may point at static storage that will be modified
138 * by future calls and by CommandCounterIncrement(). Callers should call
139 * RegisterSnapshot or PushActiveSnapshot on the returned snap if it is to be
140 * used very long.
142 Snapshot
143 GetTransactionSnapshot(void)
145 /* First call in transaction? */
146 if (!FirstSnapshotSet)
148 CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);
149 FirstSnapshotSet = true;
152 * In serializable mode, the first snapshot must live until end of xact
153 * regardless of what the caller does with it, so we must register it
154 * internally here and unregister it at end of xact.
156 if (IsXactIsoLevelSerializable)
158 CurrentSnapshot = RegisterSnapshot(CurrentSnapshot);
159 registered_serializable = true;
162 return CurrentSnapshot;
165 if (IsXactIsoLevelSerializable)
166 return CurrentSnapshot;
168 CurrentSnapshot = GetSnapshotData(&CurrentSnapshotData);
170 return CurrentSnapshot;
174 * GetLatestSnapshot
175 * Get a snapshot that is up-to-date as of the current instant,
176 * even if we are executing in SERIALIZABLE mode.
178 Snapshot
179 GetLatestSnapshot(void)
181 /* Should not be first call in transaction */
182 if (!FirstSnapshotSet)
183 elog(ERROR, "no snapshot has been set");
185 SecondarySnapshot = GetSnapshotData(&SecondarySnapshotData);
187 return SecondarySnapshot;
191 * SnapshotSetCommandId
192 * Propagate CommandCounterIncrement into the static snapshots, if set
194 void
195 SnapshotSetCommandId(CommandId curcid)
197 if (!FirstSnapshotSet)
198 return;
200 if (CurrentSnapshot)
201 CurrentSnapshot->curcid = curcid;
202 if (SecondarySnapshot)
203 SecondarySnapshot->curcid = curcid;
207 * CopySnapshot
208 * Copy the given snapshot.
210 * The copy is palloc'd in TopTransactionContext and has initial refcounts set
211 * to 0. The returned snapshot has the copied flag set.
213 static Snapshot
214 CopySnapshot(Snapshot snapshot)
216 Snapshot newsnap;
217 Size subxipoff;
218 Size size;
220 Assert(snapshot != InvalidSnapshot);
222 /* We allocate any XID arrays needed in the same palloc block. */
223 size = subxipoff = sizeof(SnapshotData) +
224 snapshot->xcnt * sizeof(TransactionId);
225 if (snapshot->subxcnt > 0)
226 size += snapshot->subxcnt * sizeof(TransactionId);
228 newsnap = (Snapshot) MemoryContextAlloc(TopTransactionContext, size);
229 memcpy(newsnap, snapshot, sizeof(SnapshotData));
231 newsnap->regd_count = 0;
232 newsnap->active_count = 0;
233 newsnap->copied = true;
235 /* setup XID array */
236 if (snapshot->xcnt > 0)
238 newsnap->xip = (TransactionId *) (newsnap + 1);
239 memcpy(newsnap->xip, snapshot->xip,
240 snapshot->xcnt * sizeof(TransactionId));
242 else
243 newsnap->xip = NULL;
245 /* setup subXID array */
246 if (snapshot->subxcnt > 0)
248 newsnap->subxip = (TransactionId *) ((char *) newsnap + subxipoff);
249 memcpy(newsnap->subxip, snapshot->subxip,
250 snapshot->subxcnt * sizeof(TransactionId));
252 else
253 newsnap->subxip = NULL;
255 return newsnap;
259 * FreeSnapshot
260 * Free the memory associated with a snapshot.
262 static void
263 FreeSnapshot(Snapshot snapshot)
265 Assert(snapshot->regd_count == 0);
266 Assert(snapshot->active_count == 0);
267 Assert(snapshot->copied);
269 pfree(snapshot);
273 * PushActiveSnapshot
274 * Set the given snapshot as the current active snapshot
276 * If this is the first use of this snapshot, create a new long-lived copy with
277 * active refcount=1. Otherwise, only increment the refcount.
279 void
280 PushActiveSnapshot(Snapshot snap)
282 ActiveSnapshotElt *newactive;
284 Assert(snap != InvalidSnapshot);
286 newactive = MemoryContextAlloc(TopTransactionContext, sizeof(ActiveSnapshotElt));
287 /* Static snapshot? Create a persistent copy */
288 newactive->as_snap = snap->copied ? snap : CopySnapshot(snap);
289 newactive->as_next = ActiveSnapshot;
290 newactive->as_level = GetCurrentTransactionNestLevel();
292 newactive->as_snap->active_count++;
294 ActiveSnapshot = newactive;
298 * PushUpdatedSnapshot
299 * As above, except we set the snapshot's CID to the current CID.
301 void
302 PushUpdatedSnapshot(Snapshot snapshot)
304 Snapshot newsnap;
307 * We cannot risk modifying a snapshot that's possibly already used
308 * elsewhere, so make a new copy to scribble on.
310 newsnap = CopySnapshot(snapshot);
311 newsnap->curcid = GetCurrentCommandId(false);
313 PushActiveSnapshot(newsnap);
317 * PopActiveSnapshot
319 * Remove the topmost snapshot from the active snapshot stack, decrementing the
320 * reference count, and free it if this was the last reference.
322 void
323 PopActiveSnapshot(void)
325 ActiveSnapshotElt *newstack;
327 newstack = ActiveSnapshot->as_next;
329 Assert(ActiveSnapshot->as_snap->active_count > 0);
331 ActiveSnapshot->as_snap->active_count--;
333 if (ActiveSnapshot->as_snap->active_count == 0 &&
334 ActiveSnapshot->as_snap->regd_count == 0)
335 FreeSnapshot(ActiveSnapshot->as_snap);
337 pfree(ActiveSnapshot);
338 ActiveSnapshot = newstack;
340 SnapshotResetXmin();
344 * GetActiveSnapshot
345 * Return the topmost snapshot in the Active stack.
347 Snapshot
348 GetActiveSnapshot(void)
350 Assert(ActiveSnapshot != NULL);
352 return ActiveSnapshot->as_snap;
356 * ActiveSnapshotSet
357 * Return whether there is at least one snapshot in the Active stack
359 bool
360 ActiveSnapshotSet(void)
362 return ActiveSnapshot != NULL;
366 * RegisterSnapshot
367 * Register a snapshot as being in use
369 * If InvalidSnapshot is passed, it is not registered.
371 Snapshot
372 RegisterSnapshot(Snapshot snapshot)
374 RegdSnapshotElt *elt;
375 RegdSnapshotElt *newhead;
376 int level;
378 if (snapshot == InvalidSnapshot)
379 return InvalidSnapshot;
381 level = GetCurrentTransactionNestLevel();
384 * If there's already an item in the list for the same snapshot and the
385 * same subxact nest level, increment its refcounts. Otherwise create a
386 * new one.
388 for (elt = RegisteredSnapshotList; elt != NULL; elt = elt->s_next)
390 if (elt->s_level < level)
391 break;
393 if (elt->s_snap == snapshot && elt->s_level == level)
395 elt->s_snap->regd_count++;
396 elt->s_count++;
398 return elt->s_snap;
403 * Create the new list element. If it's not been copied into persistent
404 * memory already, we must do so; otherwise we can just increment the
405 * reference count.
407 newhead = MemoryContextAlloc(TopTransactionContext, sizeof(RegdSnapshotElt));
408 newhead->s_next = RegisteredSnapshotList;
409 /* Static snapshot? Create a persistent copy */
410 newhead->s_snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
411 newhead->s_level = level;
412 newhead->s_count = 1;
414 newhead->s_snap->regd_count++;
416 RegisteredSnapshotList = newhead;
418 return RegisteredSnapshotList->s_snap;
422 * UnregisterSnapshot
423 * Signals that a snapshot is no longer necessary
425 * If both reference counts fall to zero, the snapshot memory is released.
426 * If only the registered list refcount falls to zero, just the list element is
427 * freed.
429 void
430 UnregisterSnapshot(Snapshot snapshot)
432 RegdSnapshotElt *prev = NULL;
433 RegdSnapshotElt *elt;
434 bool found = false;
436 if (snapshot == InvalidSnapshot)
437 return;
439 for (elt = RegisteredSnapshotList; elt != NULL; elt = elt->s_next)
441 if (elt->s_snap == snapshot)
443 Assert(elt->s_snap->regd_count > 0);
444 Assert(elt->s_count > 0);
446 elt->s_snap->regd_count--;
447 elt->s_count--;
448 found = true;
450 if (elt->s_count == 0)
452 /* delink it from the registered snapshot list */
453 if (prev)
454 prev->s_next = elt->s_next;
455 else
456 RegisteredSnapshotList = elt->s_next;
458 /* free the snapshot itself if it's no longer relevant */
459 if (elt->s_snap->regd_count == 0 && elt->s_snap->active_count == 0)
460 FreeSnapshot(elt->s_snap);
462 /* and free the list element */
463 pfree(elt);
466 break;
469 prev = elt;
472 if (!found)
473 elog(WARNING, "unregistering failed for snapshot %p", snapshot);
475 SnapshotResetXmin();
479 * SnapshotResetXmin
481 * If there are no more snapshots, we can reset our PGPROC->xmin to InvalidXid.
482 * Note we can do this without locking because we assume that storing an Xid
483 * is atomic.
485 static void
486 SnapshotResetXmin(void)
488 if (RegisteredSnapshotList == NULL && ActiveSnapshot == NULL)
489 MyProc->xmin = InvalidTransactionId;
493 * AtSubCommit_Snapshot
495 void
496 AtSubCommit_Snapshot(int level)
498 ActiveSnapshotElt *active;
499 RegdSnapshotElt *regd;
502 * Relabel the active snapshots set in this subtransaction as though they
503 * are owned by the parent subxact.
505 for (active = ActiveSnapshot; active != NULL; active = active->as_next)
507 if (active->as_level < level)
508 break;
509 active->as_level = level - 1;
513 * Reassign all registered snapshots to the parent subxact.
515 * Note: this code is somewhat bogus in that we could end up with multiple
516 * entries for the same snapshot and the same subxact level (my parent's
517 * level). Cleaning that up is more trouble than it's currently worth,
518 * however.
520 for (regd = RegisteredSnapshotList; regd != NULL; regd = regd->s_next)
522 if (regd->s_level == level)
523 regd->s_level--;
528 * AtSubAbort_Snapshot
529 * Clean up snapshots after a subtransaction abort
531 void
532 AtSubAbort_Snapshot(int level)
534 RegdSnapshotElt *prev;
535 RegdSnapshotElt *regd;
537 /* Forget the active snapshots set by this subtransaction */
538 while (ActiveSnapshot && ActiveSnapshot->as_level >= level)
540 ActiveSnapshotElt *next;
542 next = ActiveSnapshot->as_next;
545 * Decrement the snapshot's active count. If it's still registered or
546 * marked as active by an outer subtransaction, we can't free it yet.
548 Assert(ActiveSnapshot->as_snap->active_count >= 1);
549 ActiveSnapshot->as_snap->active_count -= 1;
551 if (ActiveSnapshot->as_snap->active_count == 0 &&
552 ActiveSnapshot->as_snap->regd_count == 0)
553 FreeSnapshot(ActiveSnapshot->as_snap);
555 /* and free the stack element */
556 pfree(ActiveSnapshot);
558 ActiveSnapshot = next;
561 /* Unregister all snapshots registered during this subtransaction */
562 prev = NULL;
563 for (regd = RegisteredSnapshotList; regd != NULL; )
565 if (regd->s_level >= level)
567 RegdSnapshotElt *tofree;
569 if (prev)
570 prev->s_next = regd->s_next;
571 else
572 RegisteredSnapshotList = regd->s_next;
574 tofree = regd;
575 regd = regd->s_next;
577 tofree->s_snap->regd_count -= tofree->s_count;
579 /* free the snapshot if possible */
580 if (tofree->s_snap->regd_count == 0 &&
581 tofree->s_snap->active_count == 0)
582 FreeSnapshot(tofree->s_snap);
584 /* and free the list element */
585 pfree(tofree);
587 else
589 prev = regd;
590 regd = regd->s_next;
594 SnapshotResetXmin();
598 * AtEOXact_Snapshot
599 * Snapshot manager's cleanup function for end of transaction
601 void
602 AtEOXact_Snapshot(bool isCommit)
604 /* On commit, complain about leftover snapshots */
605 if (isCommit)
607 ActiveSnapshotElt *active;
608 RegdSnapshotElt *regd;
611 * On a serializable snapshot we must first unregister our private
612 * refcount to the serializable snapshot.
614 if (registered_serializable)
615 UnregisterSnapshot(CurrentSnapshot);
617 /* complain about unpopped active snapshots */
618 for (active = ActiveSnapshot; active != NULL; active = active->as_next)
619 elog(WARNING, "snapshot %p still active", active);
621 /* complain about any unregistered snapshot */
622 for (regd = RegisteredSnapshotList; regd != NULL; regd = regd->s_next)
623 elog(WARNING,
624 "snapshot %p not destroyed at commit (%d regd refs, %d active refs)",
625 regd->s_snap, regd->s_snap->regd_count,
626 regd->s_snap->active_count);
630 * And reset our state. We don't need to free the memory explicitly --
631 * it'll go away with TopTransactionContext.
633 ActiveSnapshot = NULL;
634 RegisteredSnapshotList = NULL;
636 CurrentSnapshot = NULL;
637 SecondarySnapshot = NULL;
639 FirstSnapshotSet = false;
640 registered_serializable = false;