summaryrefslogtreecommitdiff
path: root/src/backend/utils/time/snapmgr.c
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2008-12-04 14:51:02 +0000
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2008-12-04 14:51:02 +0000
commit7b640b0345dc4fbd39ff568700985b432f6afa07 (patch)
treebf19fbefd12623fd923cc9fcfc51e41767ad50b2 /src/backend/utils/time/snapmgr.c
parent30c52532d2fe9dfc915ae1292f03adf7d033816b (diff)
Fix a couple of snapshot management bugs in the new ResourceOwner world:
non-writable large objects need to have their snapshots registered on the transaction resowner, not the current portal's, because it must persist until the large object is closed (which the portal does not). Also, ensure that the serializable snapshot is recorded by the transaction resource owner too, even when a subtransaction has changed the current resource owner before serializable is taken. Per bug reports from Pavan Deolasee.
Diffstat (limited to 'src/backend/utils/time/snapmgr.c')
-rw-r--r--src/backend/utils/time/snapmgr.c68
1 files changed, 54 insertions, 14 deletions
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 1107abdf27a..d37dc5df84c 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -19,7 +19,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/time/snapmgr.c,v 1.7 2008/11/25 20:28:29 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/time/snapmgr.c,v 1.8 2008/12/04 14:51:02 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@@ -136,7 +136,8 @@ GetTransactionSnapshot(void)
*/
if (IsXactIsoLevelSerializable)
{
- CurrentSnapshot = RegisterSnapshot(CurrentSnapshot);
+ CurrentSnapshot = RegisterSnapshotOnOwner(CurrentSnapshot,
+ TopTransactionResourceOwner);
registered_serializable = true;
}
@@ -345,14 +346,27 @@ ActiveSnapshotSet(void)
/*
* RegisterSnapshot
- * Register a snapshot as being in use
+ * Register a snapshot as being in use by the current resource owner
*
* If InvalidSnapshot is passed, it is not registered.
*/
Snapshot
RegisterSnapshot(Snapshot snapshot)
{
- Snapshot snap;
+ if (snapshot == InvalidSnapshot)
+ return InvalidSnapshot;
+
+ return RegisterSnapshotOnOwner(snapshot, CurrentResourceOwner);
+}
+
+/*
+ * RegisterSnapshotOnOwner
+ * As above, but use the specified resource owner
+ */
+Snapshot
+RegisterSnapshotOnOwner(Snapshot snapshot, ResourceOwner owner)
+{
+ Snapshot snap;
if (snapshot == InvalidSnapshot)
return InvalidSnapshot;
@@ -361,9 +375,9 @@ RegisterSnapshot(Snapshot snapshot)
snap = snapshot->copied ? snapshot : CopySnapshot(snapshot);
/* and tell resowner.c about it */
- ResourceOwnerEnlargeSnapshots(CurrentResourceOwner);
+ ResourceOwnerEnlargeSnapshots(owner);
snap->regd_count++;
- ResourceOwnerRememberSnapshot(CurrentResourceOwner, snap);
+ ResourceOwnerRememberSnapshot(owner, snap);
RegisteredSnapshots++;
@@ -383,10 +397,23 @@ UnregisterSnapshot(Snapshot snapshot)
if (snapshot == NULL)
return;
+ UnregisterSnapshotFromOwner(snapshot, CurrentResourceOwner);
+}
+
+/*
+ * UnregisterSnapshotFromOwner
+ * As above, but use the specified resource owner
+ */
+void
+UnregisterSnapshotFromOwner(Snapshot snapshot, ResourceOwner owner)
+{
+ if (snapshot == NULL)
+ return;
+
Assert(snapshot->regd_count > 0);
Assert(RegisteredSnapshots > 0);
- ResourceOwnerForgetSnapshot(CurrentResourceOwner, snapshot);
+ ResourceOwnerForgetSnapshot(owner, snapshot);
RegisteredSnapshots--;
if (--snapshot->regd_count == 0 && snapshot->active_count == 0)
{
@@ -464,6 +491,26 @@ AtSubAbort_Snapshot(int level)
}
/*
+ * AtEarlyCommit_Snapshot
+ *
+ * Snapshot manager's cleanup function, to be called on commit, before
+ * doing resowner.c resource release.
+ */
+void
+AtEarlyCommit_Snapshot(void)
+{
+ /*
+ * On a serializable transaction we must unregister our private refcount to
+ * the serializable snapshot.
+ */
+ if (registered_serializable)
+ UnregisterSnapshotFromOwner(CurrentSnapshot,
+ TopTransactionResourceOwner);
+ registered_serializable = false;
+
+}
+
+/*
* AtEOXact_Snapshot
* Snapshot manager's cleanup function for end of transaction
*/
@@ -475,13 +522,6 @@ AtEOXact_Snapshot(bool isCommit)
{
ActiveSnapshotElt *active;
- /*
- * On a serializable snapshot we must first unregister our private
- * refcount to the serializable snapshot.
- */
- if (registered_serializable)
- UnregisterSnapshot(CurrentSnapshot);
-
if (RegisteredSnapshots != 0)
elog(WARNING, "%d registered snapshots seem to remain after cleanup",
RegisteredSnapshots);