aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/file/fd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/file/fd.c')
-rw-r--r--src/backend/storage/file/fd.c67
1 files changed, 35 insertions, 32 deletions
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index b608b2c311b..32979229d8f 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.150 2009/08/05 18:01:54 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.151 2009/12/03 11:03:28 heikki Exp $
*
* NOTES:
*
@@ -55,6 +55,7 @@
#include "storage/fd.h"
#include "storage/ipc.h"
#include "utils/guc.h"
+#include "utils/resowner.h"
/*
@@ -134,7 +135,7 @@ typedef struct vfd
{
int fd; /* current FD, or VFD_CLOSED if none */
unsigned short fdstate; /* bitflags for VFD's state */
- SubTransactionId create_subid; /* for TEMPORARY fds, creating subxact */
+ ResourceOwner resowner; /* owner, for automatic cleanup */
File nextFree; /* link to next free VFD, if in freelist */
File lruMoreRecently; /* doubly linked recency-of-use list */
File lruLessRecently;
@@ -865,6 +866,7 @@ PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
vfdP->fileMode = fileMode;
vfdP->seekPos = 0;
vfdP->fdstate = 0x0;
+ vfdP->resowner = NULL;
return file;
}
@@ -876,11 +878,12 @@ PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
* There's no need to pass in fileFlags or fileMode either, since only
* one setting makes any sense for a temp file.
*
- * interXact: if true, don't close the file at end-of-transaction. In
- * most cases, you don't want temporary files to outlive the transaction
- * that created them, so this should be false -- but if you need
- * "somewhat" temporary storage, this might be useful. In either case,
- * the file is removed when the File is explicitly closed.
+ * Unless interXact is true, the file is remembered by CurrentResourceOwner
+ * to ensure it's closed and deleted when it's no longer needed, typically at
+ * the end-of-transaction. In most cases, you don't want temporary files to
+ * outlive the transaction that created them, so this should be false -- but
+ * if you need "somewhat" temporary storage, this might be useful. In either
+ * case, the file is removed when the File is explicitly closed.
*/
File
OpenTemporaryFile(bool interXact)
@@ -918,11 +921,14 @@ OpenTemporaryFile(bool interXact)
/* Mark it for deletion at close */
VfdCache[file].fdstate |= FD_TEMPORARY;
- /* Mark it for deletion at EOXact */
+ /* Register it with the current resource owner */
if (!interXact)
{
VfdCache[file].fdstate |= FD_XACT_TEMPORARY;
- VfdCache[file].create_subid = GetCurrentSubTransactionId();
+
+ ResourceOwnerEnlargeFiles(CurrentResourceOwner);
+ ResourceOwnerRememberFile(CurrentResourceOwner, file);
+ VfdCache[file].resowner = CurrentResourceOwner;
/* ensure cleanup happens at eoxact */
have_xact_temporary_files = true;
@@ -1051,6 +1057,10 @@ FileClose(File file)
elog(LOG, "could not unlink file \"%s\": %m", vfdP->fileName);
}
+ /* Unregister it from the resource owner */
+ if (vfdP->resowner)
+ ResourceOwnerForgetFile(vfdP->resowner, file);
+
/*
* Return the Vfd slot to the free list
*/
@@ -1695,24 +1705,6 @@ AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
{
Index i;
- if (have_xact_temporary_files)
- {
- Assert(FileIsNotOpen(0)); /* Make sure ring not corrupted */
- for (i = 1; i < SizeVfdCache; i++)
- {
- unsigned short fdstate = VfdCache[i].fdstate;
-
- if ((fdstate & FD_XACT_TEMPORARY) &&
- VfdCache[i].create_subid == mySubid)
- {
- if (isCommit)
- VfdCache[i].create_subid = parentSubid;
- else if (VfdCache[i].fileName != NULL)
- FileClose(i);
- }
- }
- }
-
for (i = 0; i < numAllocatedDescs; i++)
{
if (allocatedDescs[i].create_subid == mySubid)
@@ -1733,9 +1725,10 @@ AtEOSubXact_Files(bool isCommit, SubTransactionId mySubid,
*
* This routine is called during transaction commit or abort (it doesn't
* particularly care which). All still-open per-transaction temporary file
- * VFDs are closed, which also causes the underlying files to be
- * deleted. Furthermore, all "allocated" stdio files are closed.
- * We also forget any transaction-local temp tablespace list.
+ * VFDs are closed, which also causes the underlying files to be deleted
+ * (although they should've been closed already by the ResourceOwner
+ * cleanup). Furthermore, all "allocated" stdio files are closed. We also
+ * forget any transaction-local temp tablespace list.
*/
void
AtEOXact_Files(void)
@@ -1787,16 +1780,26 @@ CleanupTempFiles(bool isProcExit)
/*
* If we're in the process of exiting a backend process, close
* all temporary files. Otherwise, only close temporary files
- * local to the current transaction.
+ * local to the current transaction. They should be closed
+ * by the ResourceOwner mechanism already, so this is just
+ * a debugging cross-check.
*/
- if (isProcExit || (fdstate & FD_XACT_TEMPORARY))
+ if (isProcExit)
+ FileClose(i);
+ else if (fdstate & FD_XACT_TEMPORARY)
+ {
+ elog(WARNING,
+ "temporary file %s not closed at end-of-transaction",
+ VfdCache[i].fileName);
FileClose(i);
+ }
}
}
have_xact_temporary_files = false;
}
+ /* Clean up "allocated" stdio files and dirs. */
while (numAllocatedDescs > 0)
FreeDesc(&allocatedDescs[0]);
}