aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xact.c8
-rw-r--r--src/backend/storage/large_object/inv_api.c15
-rw-r--r--src/backend/utils/time/snapmgr.c68
-rw-r--r--src/include/utils/snapmgr.h6
-rw-r--r--src/test/regress/input/largeobject.source5
-rw-r--r--src/test/regress/output/largeobject.source9
-rw-r--r--src/test/regress/output/largeobject_1.source9
7 files changed, 101 insertions, 19 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index b61fe41083f..c5a1b33a9e9 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.269 2008/11/19 10:34:50 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.270 2008/12/04 14:51:02 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1667,6 +1667,9 @@ CommitTransaction(void)
/* Clean up the relation cache */
AtEOXact_RelationCache(true);
+ /* Clean up the snapshot manager */
+ AtEarlyCommit_Snapshot();
+
/*
* Make catalog changes visible to all backends. This has to happen after
* relcache references are dropped (see comments for
@@ -1906,6 +1909,9 @@ PrepareTransaction(void)
/* Clean up the relation cache */
AtEOXact_RelationCache(true);
+ /* Clean up the snapshot manager */
+ AtEarlyCommit_Snapshot();
+
/* notify and flatfiles don't need a postprepare call */
PostPrepare_PgStat();
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index 3936260e6cf..14f101adb34 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -24,7 +24,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.135 2008/11/02 01:45:28 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.136 2008/12/04 14:51:02 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@@ -247,7 +247,13 @@ inv_open(Oid lobjId, int flags, MemoryContext mcxt)
}
else if (flags & INV_READ)
{
- retval->snapshot = RegisterSnapshot(GetActiveSnapshot());
+ /*
+ * We must register the snapshot in TopTransaction's resowner,
+ * because it must stay alive until the LO is closed rather than until
+ * the current portal shuts down.
+ */
+ retval->snapshot = RegisterSnapshotOnOwner(GetActiveSnapshot(),
+ TopTransactionResourceOwner);
retval->flags = IFS_RDLOCK;
}
else
@@ -270,8 +276,11 @@ void
inv_close(LargeObjectDesc *obj_desc)
{
Assert(PointerIsValid(obj_desc));
+
if (obj_desc->snapshot != SnapshotNow)
- UnregisterSnapshot(obj_desc->snapshot);
+ UnregisterSnapshotFromOwner(obj_desc->snapshot,
+ TopTransactionResourceOwner);
+
pfree(obj_desc);
}
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);
diff --git a/src/include/utils/snapmgr.h b/src/include/utils/snapmgr.h
index 8f3cc44c57b..f4e55c9930f 100644
--- a/src/include/utils/snapmgr.h
+++ b/src/include/utils/snapmgr.h
@@ -6,13 +6,14 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/snapmgr.h,v 1.2 2008/05/12 20:02:02 alvherre Exp $
+ * $PostgreSQL: pgsql/src/include/utils/snapmgr.h,v 1.3 2008/12/04 14:51:02 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef SNAPMGR_H
#define SNAPMGR_H
+#include "utils/resowner.h"
#include "utils/snapshot.h"
@@ -34,9 +35,12 @@ extern bool ActiveSnapshotSet(void);
extern Snapshot RegisterSnapshot(Snapshot snapshot);
extern void UnregisterSnapshot(Snapshot snapshot);
+extern Snapshot RegisterSnapshotOnOwner(Snapshot snapshot, ResourceOwner owner);
+extern void UnregisterSnapshotFromOwner(Snapshot snapshot, ResourceOwner owner);
extern void AtSubCommit_Snapshot(int level);
extern void AtSubAbort_Snapshot(int level);
+extern void AtEarlyCommit_Snapshot(void);
extern void AtEOXact_Snapshot(bool isCommit);
#endif /* SNAPMGR_H */
diff --git a/src/test/regress/input/largeobject.source b/src/test/regress/input/largeobject.source
index 1d62caa3eaf..46ba9261ac5 100644
--- a/src/test/regress/input/largeobject.source
+++ b/src/test/regress/input/largeobject.source
@@ -83,6 +83,11 @@ SELECT lo_close(fd) FROM lotest_stash_values;
END;
+-- Test resource management
+BEGIN;
+SELECT lo_open(loid, x'40000'::int) from lotest_stash_values;
+ABORT;
+
-- Test truncation.
BEGIN;
UPDATE lotest_stash_values SET fd=lo_open(loid, CAST(x'20000' | x'40000' AS integer));
diff --git a/src/test/regress/output/largeobject.source b/src/test/regress/output/largeobject.source
index 36b51fdccdd..9d69f6c913e 100644
--- a/src/test/regress/output/largeobject.source
+++ b/src/test/regress/output/largeobject.source
@@ -116,6 +116,15 @@ SELECT lo_close(fd) FROM lotest_stash_values;
(1 row)
END;
+-- Test resource management
+BEGIN;
+SELECT lo_open(loid, x'40000'::int) from lotest_stash_values;
+ lo_open
+---------
+ 0
+(1 row)
+
+ABORT;
-- Test truncation.
BEGIN;
UPDATE lotest_stash_values SET fd=lo_open(loid, CAST(x'20000' | x'40000' AS integer));
diff --git a/src/test/regress/output/largeobject_1.source b/src/test/regress/output/largeobject_1.source
index f1157e45718..1fbc29c2517 100644
--- a/src/test/regress/output/largeobject_1.source
+++ b/src/test/regress/output/largeobject_1.source
@@ -116,6 +116,15 @@ SELECT lo_close(fd) FROM lotest_stash_values;
(1 row)
END;
+-- Test resource management
+BEGIN;
+SELECT lo_open(loid, x'40000'::int) from lotest_stash_values;
+ lo_open
+---------
+ 0
+(1 row)
+
+ABORT;
-- Test truncation.
BEGIN;
UPDATE lotest_stash_values SET fd=lo_open(loid, CAST(x'20000' | x'40000' AS integer));