mirror of
https://github.com/postgres/postgres.git
synced 2025-05-06 19:59:18 +03:00
Move temporary files into 'pg_tempfiles' subdirectory of each database
directory (which can be made a symlink to put temp files on another disk). Add code to delete leftover temp files during postmaster startup. Bruce, with some kibitzing from Tom.
This commit is contained in:
parent
6f2182fe18
commit
2a6f7ac456
@ -28,7 +28,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.217 2001/06/07 04:50:57 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.218 2001/06/11 04:12:29 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
*
|
*
|
||||||
@ -243,9 +243,14 @@ static void RandomSalt(char *salt);
|
|||||||
static void SignalChildren(int signal);
|
static void SignalChildren(int signal);
|
||||||
static int CountChildren(void);
|
static int CountChildren(void);
|
||||||
static bool CreateOptsFile(int argc, char *argv[]);
|
static bool CreateOptsFile(int argc, char *argv[]);
|
||||||
static void postmaster_error(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
|
|
||||||
|
|
||||||
static pid_t SSDataBase(int xlop);
|
static pid_t SSDataBase(int xlop);
|
||||||
|
#ifdef __GNUC__
|
||||||
|
/* This checks the format string for consistency. */
|
||||||
|
static void postmaster_error(const char *fmt, ...)
|
||||||
|
__attribute__((format(printf, 1, 2)));
|
||||||
|
#else
|
||||||
|
static void postmaster_error(const char *fmt, ...);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define StartupDataBase() SSDataBase(BS_XLOG_STARTUP)
|
#define StartupDataBase() SSDataBase(BS_XLOG_STARTUP)
|
||||||
#define CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT)
|
#define CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT)
|
||||||
@ -253,7 +258,6 @@ static pid_t SSDataBase(int xlop);
|
|||||||
|
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
static void InitSSL(void);
|
static void InitSSL(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -596,6 +600,12 @@ PostmasterMain(int argc, char *argv[])
|
|||||||
if (!CreateDataDirLockFile(DataDir, true))
|
if (!CreateDataDirLockFile(DataDir, true))
|
||||||
ExitPostmaster(1);
|
ExitPostmaster(1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove old temporary files. At this point there can be no other
|
||||||
|
* Postgres processes running in this directory, so this should be safe.
|
||||||
|
*/
|
||||||
|
RemovePgTempFiles();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Establish input sockets.
|
* Establish input sockets.
|
||||||
*/
|
*/
|
||||||
@ -613,7 +623,8 @@ PostmasterMain(int argc, char *argv[])
|
|||||||
if (NetServer)
|
if (NetServer)
|
||||||
{
|
{
|
||||||
status = StreamServerPort(AF_INET, VirtualHost,
|
status = StreamServerPort(AF_INET, VirtualHost,
|
||||||
(unsigned short) PostPortNumber, UnixSocketDir,
|
(unsigned short) PostPortNumber,
|
||||||
|
UnixSocketDir,
|
||||||
&ServerSock_INET);
|
&ServerSock_INET);
|
||||||
if (status != STATUS_OK)
|
if (status != STATUS_OK)
|
||||||
{
|
{
|
||||||
@ -624,7 +635,8 @@ PostmasterMain(int argc, char *argv[])
|
|||||||
|
|
||||||
#ifdef HAVE_UNIX_SOCKETS
|
#ifdef HAVE_UNIX_SOCKETS
|
||||||
status = StreamServerPort(AF_UNIX, VirtualHost,
|
status = StreamServerPort(AF_UNIX, VirtualHost,
|
||||||
(unsigned short) PostPortNumber, UnixSocketDir,
|
(unsigned short) PostPortNumber,
|
||||||
|
UnixSocketDir,
|
||||||
&ServerSock_UNIX);
|
&ServerSock_UNIX);
|
||||||
if (status != STATUS_OK)
|
if (status != STATUS_OK)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.80 2001/06/06 17:07:46 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.81 2001/06/11 04:12:29 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES:
|
* NOTES:
|
||||||
*
|
*
|
||||||
@ -44,6 +44,7 @@
|
|||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -51,6 +52,12 @@
|
|||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "storage/fd.h"
|
#include "storage/fd.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Filename components for OpenTemporaryFile */
|
||||||
|
#define PG_TEMP_FILES_DIR "pg_tempfiles"
|
||||||
|
#define PG_TEMP_FILE_PREFIX "pg_temp"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Problem: Postgres does a system(ld...) to do dynamic loading.
|
* Problem: Postgres does a system(ld...) to do dynamic loading.
|
||||||
* This will open several extra files in addition to those used by
|
* This will open several extra files in addition to those used by
|
||||||
@ -189,7 +196,7 @@ static void FreeVfd(File file);
|
|||||||
|
|
||||||
static int FileAccess(File file);
|
static int FileAccess(File file);
|
||||||
static File fileNameOpenFile(FileName fileName, int fileFlags, int fileMode);
|
static File fileNameOpenFile(FileName fileName, int fileFlags, int fileMode);
|
||||||
static char *filepath(char *filename);
|
static char *filepath(const char *filename);
|
||||||
static long pg_nofile(void);
|
static long pg_nofile(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -568,28 +575,27 @@ FreeVfd(File file)
|
|||||||
/* filepath()
|
/* filepath()
|
||||||
* Convert given pathname to absolute.
|
* Convert given pathname to absolute.
|
||||||
*
|
*
|
||||||
|
* Result is a palloc'd string.
|
||||||
|
*
|
||||||
* (Generally, this isn't actually necessary, considering that we
|
* (Generally, this isn't actually necessary, considering that we
|
||||||
* should be cd'd into the database directory. Presently it is only
|
* should be cd'd into the database directory. Presently it is only
|
||||||
* necessary to do it in "bootstrap" mode. Maybe we should change
|
* necessary to do it in "bootstrap" mode. Maybe we should change
|
||||||
* bootstrap mode to do the cd, and save a few cycles/bytes here.)
|
* bootstrap mode to do the cd, and save a few cycles/bytes here.)
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
filepath(char *filename)
|
filepath(const char *filename)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
int len;
|
|
||||||
|
|
||||||
/* Not an absolute path name? Then fill in with database path... */
|
/* Not an absolute path name? Then fill in with database path... */
|
||||||
if (*filename != '/')
|
if (*filename != '/')
|
||||||
{
|
{
|
||||||
len = strlen(DatabasePath) + strlen(filename) + 2;
|
buf = (char *) palloc(strlen(DatabasePath) + strlen(filename) + 2);
|
||||||
buf = (char *) palloc(len);
|
|
||||||
sprintf(buf, "%s/%s", DatabasePath, filename);
|
sprintf(buf, "%s/%s", DatabasePath, filename);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buf = (char *) palloc(strlen(filename) + 1);
|
buf = pstrdup(filename);
|
||||||
strcpy(buf, filename);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FILEDEBUG
|
#ifdef FILEDEBUG
|
||||||
@ -742,21 +748,46 @@ PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
|
|||||||
File
|
File
|
||||||
OpenTemporaryFile(void)
|
OpenTemporaryFile(void)
|
||||||
{
|
{
|
||||||
char tempfilename[64];
|
char tempfilepath[128];
|
||||||
File file;
|
File file;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate a tempfile name that's unique within the current
|
* Generate a tempfile name that's unique within the current
|
||||||
* transaction
|
* transaction and database instance.
|
||||||
*/
|
*/
|
||||||
snprintf(tempfilename, sizeof(tempfilename),
|
snprintf(tempfilepath, sizeof(tempfilepath),
|
||||||
"pg_sorttemp%d.%ld", MyProcPid, tempFileCounter++);
|
"%s/%s%d.%ld", PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
|
||||||
|
MyProcPid, tempFileCounter++);
|
||||||
|
|
||||||
/* Open the file */
|
/*
|
||||||
file = FileNameOpenFile(tempfilename,
|
* Open the file. Note: we don't use O_EXCL, in case there is an
|
||||||
O_RDWR | O_CREAT | O_TRUNC | PG_BINARY, 0600);
|
* orphaned temp file that can be reused.
|
||||||
|
*/
|
||||||
|
file = FileNameOpenFile(tempfilepath,
|
||||||
|
O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
|
||||||
|
0600);
|
||||||
if (file <= 0)
|
if (file <= 0)
|
||||||
elog(ERROR, "Failed to create temporary file %s", tempfilename);
|
{
|
||||||
|
char *dirpath;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We might need to create the pg_tempfiles subdirectory, if
|
||||||
|
* no one has yet done so.
|
||||||
|
*
|
||||||
|
* Don't check for error from mkdir; it could fail if someone else
|
||||||
|
* just did the same thing. If it doesn't work then we'll bomb out
|
||||||
|
* on the second create attempt, instead.
|
||||||
|
*/
|
||||||
|
dirpath = filepath(PG_TEMP_FILES_DIR);
|
||||||
|
mkdir(dirpath, S_IRWXU);
|
||||||
|
pfree(dirpath);
|
||||||
|
|
||||||
|
file = FileNameOpenFile(tempfilepath,
|
||||||
|
O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
|
||||||
|
0600);
|
||||||
|
if (file <= 0)
|
||||||
|
elog(ERROR, "Failed to create temporary file %s", tempfilepath);
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark it for deletion at close or EOXact */
|
/* Mark it for deletion at close or EOXact */
|
||||||
VfdCache[file].fdstate |= FD_TEMPORARY;
|
VfdCache[file].fdstate |= FD_TEMPORARY;
|
||||||
@ -1203,3 +1234,76 @@ AtEOXact_Files(void)
|
|||||||
*/
|
*/
|
||||||
tempFileCounter = 0;
|
tempFileCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove old temporary files
|
||||||
|
*
|
||||||
|
* This should be called during postmaster startup. It will forcibly
|
||||||
|
* remove any leftover files created by OpenTemporaryFile.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
RemovePgTempFiles(void)
|
||||||
|
{
|
||||||
|
char db_path[MAXPGPATH];
|
||||||
|
char temp_path[MAXPGPATH];
|
||||||
|
char rm_path[MAXPGPATH];
|
||||||
|
DIR *db_dir;
|
||||||
|
DIR *temp_dir;
|
||||||
|
struct dirent *db_de;
|
||||||
|
struct dirent *temp_de;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cycle through pg_tempfiles for all databases
|
||||||
|
* and remove old temp files.
|
||||||
|
*/
|
||||||
|
snprintf(db_path, sizeof(db_path), "%s/base", DataDir);
|
||||||
|
if ((db_dir = opendir(db_path)) != NULL)
|
||||||
|
{
|
||||||
|
while ((db_de = readdir(db_dir)) != NULL)
|
||||||
|
{
|
||||||
|
if (strcmp(db_de->d_name, ".") == 0 ||
|
||||||
|
strcmp(db_de->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(temp_path, sizeof(temp_path),
|
||||||
|
"%s/%s/%s",
|
||||||
|
db_path, db_de->d_name,
|
||||||
|
PG_TEMP_FILES_DIR);
|
||||||
|
if ((temp_dir = opendir(temp_path)) != NULL)
|
||||||
|
{
|
||||||
|
while ((temp_de = readdir(temp_dir)) != NULL)
|
||||||
|
{
|
||||||
|
if (strcmp(temp_de->d_name, ".") == 0 ||
|
||||||
|
strcmp(temp_de->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(rm_path, sizeof(temp_path),
|
||||||
|
"%s/%s/%s/%s",
|
||||||
|
db_path, db_de->d_name,
|
||||||
|
PG_TEMP_FILES_DIR,
|
||||||
|
temp_de->d_name);
|
||||||
|
|
||||||
|
if (strncmp(temp_de->d_name,
|
||||||
|
PG_TEMP_FILE_PREFIX,
|
||||||
|
strlen(PG_TEMP_FILE_PREFIX)) == 0)
|
||||||
|
{
|
||||||
|
unlink(rm_path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* would prefer to use elog here, but it's not
|
||||||
|
* up and running during postmaster startup...
|
||||||
|
*/
|
||||||
|
fprintf(stderr,
|
||||||
|
"Unexpected file found in temporary-files directory: %s\n",
|
||||||
|
rm_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(temp_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(db_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: fd.h,v 1.29 2001/05/25 15:45:34 momjian Exp $
|
* $Id: fd.h,v 1.30 2001/06/11 04:12:29 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -70,6 +70,7 @@ extern int BasicOpenFile(FileName fileName, int fileFlags, int fileMode);
|
|||||||
/* Miscellaneous support routines */
|
/* Miscellaneous support routines */
|
||||||
extern void closeAllVfds(void);
|
extern void closeAllVfds(void);
|
||||||
extern void AtEOXact_Files(void);
|
extern void AtEOXact_Files(void);
|
||||||
|
extern void RemovePgTempFiles(void);
|
||||||
extern int pg_fsync(int fd);
|
extern int pg_fsync(int fd);
|
||||||
extern int pg_fdatasync(int fd);
|
extern int pg_fdatasync(int fd);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user