aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/resowner/resowner.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/resowner/resowner.c')
-rw-r--r--src/backend/utils/resowner/resowner.c103
1 files changed, 102 insertions, 1 deletions
diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index 4ef47ca5601..1f8658d0104 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/resowner/resowner.c,v 1.32 2009/06/11 14:49:06 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/resowner/resowner.c,v 1.33 2009/12/03 11:03:29 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -72,6 +72,11 @@ typedef struct ResourceOwnerData
int nsnapshots; /* number of owned snapshot references */
Snapshot *snapshots; /* dynamically allocated array */
int maxsnapshots; /* currently allocated array size */
+
+ /* We have built-in support for remembering open temporary files */
+ int nfiles; /* number of owned temporary files */
+ File *files; /* dynamically allocated array */
+ int maxfiles; /* currently allocated array size */
} ResourceOwnerData;
@@ -105,6 +110,7 @@ static void PrintRelCacheLeakWarning(Relation rel);
static void PrintPlanCacheLeakWarning(CachedPlan *plan);
static void PrintTupleDescLeakWarning(TupleDesc tupdesc);
static void PrintSnapshotLeakWarning(Snapshot snapshot);
+static void PrintFileLeakWarning(File file);
/*****************************************************************************
@@ -316,6 +322,14 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
UnregisterSnapshot(owner->snapshots[owner->nsnapshots - 1]);
}
+ /* Ditto for temporary files */
+ while (owner->nfiles > 0)
+ {
+ if (isCommit)
+ PrintFileLeakWarning(owner->files[owner->nfiles - 1]);
+ FileClose(owner->files[owner->nfiles - 1]);
+ }
+
/* Clean up index scans too */
ReleaseResources_hash();
}
@@ -347,6 +361,7 @@ ResourceOwnerDelete(ResourceOwner owner)
Assert(owner->nplanrefs == 0);
Assert(owner->ntupdescs == 0);
Assert(owner->nsnapshots == 0);
+ Assert(owner->nfiles == 0);
/*
* Delete children. The recursive call will delink the child from me, so
@@ -377,6 +392,8 @@ ResourceOwnerDelete(ResourceOwner owner)
pfree(owner->tupdescs);
if (owner->snapshots)
pfree(owner->snapshots);
+ if (owner->files)
+ pfree(owner->files);
pfree(owner);
}
@@ -1035,3 +1052,87 @@ PrintSnapshotLeakWarning(Snapshot snapshot)
"Snapshot reference leak: Snapshot %p still referenced",
snapshot);
}
+
+
+/*
+ * Make sure there is room for at least one more entry in a ResourceOwner's
+ * files reference array.
+ *
+ * This is separate from actually inserting an entry because if we run out
+ * of memory, it's critical to do so *before* acquiring the resource.
+ */
+void
+ResourceOwnerEnlargeFiles(ResourceOwner owner)
+{
+ int newmax;
+
+ if (owner->nfiles < owner->maxfiles)
+ return; /* nothing to do */
+
+ if (owner->files == NULL)
+ {
+ newmax = 16;
+ owner->files = (File *)
+ MemoryContextAlloc(TopMemoryContext, newmax * sizeof(File));
+ owner->maxfiles = newmax;
+ }
+ else
+ {
+ newmax = owner->maxfiles * 2;
+ owner->files = (File *)
+ repalloc(owner->files, newmax * sizeof(File));
+ owner->maxfiles = newmax;
+ }
+}
+
+/*
+ * Remember that a temporary file is owned by a ResourceOwner
+ *
+ * Caller must have previously done ResourceOwnerEnlargeFiles()
+ */
+void
+ResourceOwnerRememberFile(ResourceOwner owner, File file)
+{
+ Assert(owner->nfiles < owner->maxfiles);
+ owner->files[owner->nfiles] = file;
+ owner->nfiles++;
+}
+
+/*
+ * Forget that a temporary file is owned by a ResourceOwner
+ */
+void
+ResourceOwnerForgetFile(ResourceOwner owner, File file)
+{
+ File *files = owner->files;
+ int ns1 = owner->nfiles - 1;
+ int i;
+
+ for (i = ns1; i >= 0; i--)
+ {
+ if (files[i] == file)
+ {
+ while (i < ns1)
+ {
+ files[i] = files[i + 1];
+ i++;
+ }
+ owner->nfiles = ns1;
+ return;
+ }
+ }
+ elog(ERROR, "temporery file %d is not owned by resource owner %s",
+ file, owner->name);
+}
+
+
+/*
+ * Debugging subroutine
+ */
+static void
+PrintFileLeakWarning(File file)
+{
+ elog(WARNING,
+ "temporary file leak: File %d still referenced",
+ file);
+}