diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 96d7d1e3ad9c1bdd64445084b46f65d2a350eed5..6334cdd7e37a9d826c4e008a529aed0f676c0ef5 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -28,7 +28,7 @@ * * * 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 * @@ -243,9 +243,14 @@ static void RandomSalt(char *salt); static void SignalChildren(int signal); static int CountChildren(void); 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); +#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 CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT) @@ -253,7 +258,6 @@ static pid_t SSDataBase(int xlop); #ifdef USE_SSL static void InitSSL(void); - #endif @@ -596,6 +600,12 @@ PostmasterMain(int argc, char *argv[]) if (!CreateDataDirLockFile(DataDir, true)) 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. */ @@ -613,7 +623,8 @@ PostmasterMain(int argc, char *argv[]) if (NetServer) { status = StreamServerPort(AF_INET, VirtualHost, - (unsigned short) PostPortNumber, UnixSocketDir, + (unsigned short) PostPortNumber, + UnixSocketDir, &ServerSock_INET); if (status != STATUS_OK) { @@ -624,7 +635,8 @@ PostmasterMain(int argc, char *argv[]) #ifdef HAVE_UNIX_SOCKETS status = StreamServerPort(AF_UNIX, VirtualHost, - (unsigned short) PostPortNumber, UnixSocketDir, + (unsigned short) PostPortNumber, + UnixSocketDir, &ServerSock_UNIX); if (status != STATUS_OK) { diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 237ae0a442807ba6238e6b12950d5037ab586d1d..f37a9573df935b313d2f996783925803a54d559c 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 - * $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: * @@ -44,6 +44,7 @@ #include <sys/file.h> #include <sys/param.h> #include <sys/stat.h> +#include <dirent.h> #include <errno.h> #include <unistd.h> #include <fcntl.h> @@ -51,6 +52,12 @@ #include "miscadmin.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. * 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 File fileNameOpenFile(FileName fileName, int fileFlags, int fileMode); -static char *filepath(char *filename); +static char *filepath(const char *filename); static long pg_nofile(void); /* @@ -568,28 +575,27 @@ FreeVfd(File file) /* filepath() * Convert given pathname to absolute. * + * Result is a palloc'd string. + * * (Generally, this isn't actually necessary, considering that we * should be cd'd into the database directory. Presently it is only * necessary to do it in "bootstrap" mode. Maybe we should change * bootstrap mode to do the cd, and save a few cycles/bytes here.) */ static char * -filepath(char *filename) +filepath(const char *filename) { char *buf; - int len; /* Not an absolute path name? Then fill in with database path... */ if (*filename != '/') { - len = strlen(DatabasePath) + strlen(filename) + 2; - buf = (char *) palloc(len); + buf = (char *) palloc(strlen(DatabasePath) + strlen(filename) + 2); sprintf(buf, "%s/%s", DatabasePath, filename); } else { - buf = (char *) palloc(strlen(filename) + 1); - strcpy(buf, filename); + buf = pstrdup(filename); } #ifdef FILEDEBUG @@ -742,21 +748,46 @@ PathNameOpenFile(FileName fileName, int fileFlags, int fileMode) File OpenTemporaryFile(void) { - char tempfilename[64]; + char tempfilepath[128]; File file; /* * Generate a tempfile name that's unique within the current - * transaction + * transaction and database instance. */ - snprintf(tempfilename, sizeof(tempfilename), - "pg_sorttemp%d.%ld", MyProcPid, tempFileCounter++); + snprintf(tempfilepath, sizeof(tempfilepath), + "%s/%s%d.%ld", PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX, + MyProcPid, tempFileCounter++); - /* Open the file */ - file = FileNameOpenFile(tempfilename, - O_RDWR | O_CREAT | O_TRUNC | PG_BINARY, 0600); + /* + * Open the file. Note: we don't use O_EXCL, in case there is an + * orphaned temp file that can be reused. + */ + file = FileNameOpenFile(tempfilepath, + O_RDWR | O_CREAT | O_TRUNC | PG_BINARY, + 0600); 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 */ VfdCache[file].fdstate |= FD_TEMPORARY; @@ -1203,3 +1234,76 @@ AtEOXact_Files(void) */ 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); + } +} diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h index 6bb690c3f5713894e358126cd1cfab7f8b39266e..f3e06978a67ed5c4825851bf905d3e3078e3a398 100644 --- a/src/include/storage/fd.h +++ b/src/include/storage/fd.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * 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 */ extern void closeAllVfds(void); extern void AtEOXact_Files(void); +extern void RemovePgTempFiles(void); extern int pg_fsync(int fd); extern int pg_fdatasync(int fd);