Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2a6f7ac

Browse files
committed
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.
1 parent 6f2182f commit 2a6f7ac

File tree

3 files changed

+140
-23
lines changed

3 files changed

+140
-23
lines changed

src/backend/postmaster/postmaster.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
*
2929
*
3030
* IDENTIFICATION
31-
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.217 2001/06/07 04:50:57 momjian Exp $
31+
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.218 2001/06/11 04:12:29 tgl Exp $
3232
*
3333
* NOTES
3434
*
@@ -243,17 +243,21 @@ static void RandomSalt(char *salt);
243243
static void SignalChildren(int signal);
244244
static int CountChildren(void);
245245
static bool CreateOptsFile(int argc, char *argv[]);
246-
static void postmaster_error(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
247-
248246
static pid_t SSDataBase(int xlop);
247+
#ifdef __GNUC__
248+
/* This checks the format string for consistency. */
249+
static void postmaster_error(const char *fmt, ...)
250+
__attribute__((format(printf, 1, 2)));
251+
#else
252+
static void postmaster_error(const char *fmt, ...);
253+
#endif
249254

250255
#define StartupDataBase() SSDataBase(BS_XLOG_STARTUP)
251256
#define CheckPointDataBase() SSDataBase(BS_XLOG_CHECKPOINT)
252257
#define ShutdownDataBase() SSDataBase(BS_XLOG_SHUTDOWN)
253258

254259
#ifdef USE_SSL
255260
static void InitSSL(void);
256-
257261
#endif
258262

259263

@@ -596,6 +600,12 @@ PostmasterMain(int argc, char *argv[])
596600
if (!CreateDataDirLockFile(DataDir, true))
597601
ExitPostmaster(1);
598602

603+
/*
604+
* Remove old temporary files. At this point there can be no other
605+
* Postgres processes running in this directory, so this should be safe.
606+
*/
607+
RemovePgTempFiles();
608+
599609
/*
600610
* Establish input sockets.
601611
*/
@@ -613,7 +623,8 @@ PostmasterMain(int argc, char *argv[])
613623
if (NetServer)
614624
{
615625
status = StreamServerPort(AF_INET, VirtualHost,
616-
(unsigned short) PostPortNumber, UnixSocketDir,
626+
(unsigned short) PostPortNumber,
627+
UnixSocketDir,
617628
&ServerSock_INET);
618629
if (status != STATUS_OK)
619630
{
@@ -624,7 +635,8 @@ PostmasterMain(int argc, char *argv[])
624635

625636
#ifdef HAVE_UNIX_SOCKETS
626637
status = StreamServerPort(AF_UNIX, VirtualHost,
627-
(unsigned short) PostPortNumber, UnixSocketDir,
638+
(unsigned short) PostPortNumber,
639+
UnixSocketDir,
628640
&ServerSock_UNIX);
629641
if (status != STATUS_OK)
630642
{

src/backend/storage/file/fd.c

Lines changed: 120 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.80 2001/06/06 17:07:46 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.81 2001/06/11 04:12:29 tgl Exp $
1111
*
1212
* NOTES:
1313
*
@@ -44,13 +44,20 @@
4444
#include <sys/file.h>
4545
#include <sys/param.h>
4646
#include <sys/stat.h>
47+
#include <dirent.h>
4748
#include <errno.h>
4849
#include <unistd.h>
4950
#include <fcntl.h>
5051

5152
#include "miscadmin.h"
5253
#include "storage/fd.h"
5354

55+
56+
/* Filename components for OpenTemporaryFile */
57+
#define PG_TEMP_FILES_DIR "pg_tempfiles"
58+
#define PG_TEMP_FILE_PREFIX "pg_temp"
59+
60+
5461
/*
5562
* Problem: Postgres does a system(ld...) to do dynamic loading.
5663
* This will open several extra files in addition to those used by
@@ -189,7 +196,7 @@ static void FreeVfd(File file);
189196

190197
static int FileAccess(File file);
191198
static File fileNameOpenFile(FileName fileName, int fileFlags, int fileMode);
192-
static char *filepath(char *filename);
199+
static char *filepath(const char *filename);
193200
static long pg_nofile(void);
194201

195202
/*
@@ -568,28 +575,27 @@ FreeVfd(File file)
568575
/* filepath()
569576
* Convert given pathname to absolute.
570577
*
578+
* Result is a palloc'd string.
579+
*
571580
* (Generally, this isn't actually necessary, considering that we
572581
* should be cd'd into the database directory. Presently it is only
573582
* necessary to do it in "bootstrap" mode. Maybe we should change
574583
* bootstrap mode to do the cd, and save a few cycles/bytes here.)
575584
*/
576585
static char *
577-
filepath(char *filename)
586+
filepath(const char *filename)
578587
{
579588
char *buf;
580-
int len;
581589

582590
/* Not an absolute path name? Then fill in with database path... */
583591
if (*filename != '/')
584592
{
585-
len = strlen(DatabasePath) + strlen(filename) + 2;
586-
buf = (char *) palloc(len);
593+
buf = (char *) palloc(strlen(DatabasePath) + strlen(filename) + 2);
587594
sprintf(buf, "%s/%s", DatabasePath, filename);
588595
}
589596
else
590597
{
591-
buf = (char *) palloc(strlen(filename) + 1);
592-
strcpy(buf, filename);
598+
buf = pstrdup(filename);
593599
}
594600

595601
#ifdef FILEDEBUG
@@ -742,21 +748,46 @@ PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
742748
File
743749
OpenTemporaryFile(void)
744750
{
745-
char tempfilename[64];
751+
char tempfilepath[128];
746752
File file;
747753

748754
/*
749755
* Generate a tempfile name that's unique within the current
750-
* transaction
756+
* transaction and database instance.
751757
*/
752-
snprintf(tempfilename, sizeof(tempfilename),
753-
"pg_sorttemp%d.%ld", MyProcPid, tempFileCounter++);
758+
snprintf(tempfilepath, sizeof(tempfilepath),
759+
"%s/%s%d.%ld", PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
760+
MyProcPid, tempFileCounter++);
754761

755-
/* Open the file */
756-
file = FileNameOpenFile(tempfilename,
757-
O_RDWR | O_CREAT | O_TRUNC | PG_BINARY, 0600);
762+
/*
763+
* Open the file. Note: we don't use O_EXCL, in case there is an
764+
* orphaned temp file that can be reused.
765+
*/
766+
file = FileNameOpenFile(tempfilepath,
767+
O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
768+
0600);
758769
if (file <= 0)
759-
elog(ERROR, "Failed to create temporary file %s", tempfilename);
770+
{
771+
char *dirpath;
772+
773+
/*
774+
* We might need to create the pg_tempfiles subdirectory, if
775+
* no one has yet done so.
776+
*
777+
* Don't check for error from mkdir; it could fail if someone else
778+
* just did the same thing. If it doesn't work then we'll bomb out
779+
* on the second create attempt, instead.
780+
*/
781+
dirpath = filepath(PG_TEMP_FILES_DIR);
782+
mkdir(dirpath, S_IRWXU);
783+
pfree(dirpath);
784+
785+
file = FileNameOpenFile(tempfilepath,
786+
O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
787+
0600);
788+
if (file <= 0)
789+
elog(ERROR, "Failed to create temporary file %s", tempfilepath);
790+
}
760791

761792
/* Mark it for deletion at close or EOXact */
762793
VfdCache[file].fdstate |= FD_TEMPORARY;
@@ -1203,3 +1234,76 @@ AtEOXact_Files(void)
12031234
*/
12041235
tempFileCounter = 0;
12051236
}
1237+
1238+
1239+
/*
1240+
* Remove old temporary files
1241+
*
1242+
* This should be called during postmaster startup. It will forcibly
1243+
* remove any leftover files created by OpenTemporaryFile.
1244+
*/
1245+
void
1246+
RemovePgTempFiles(void)
1247+
{
1248+
char db_path[MAXPGPATH];
1249+
char temp_path[MAXPGPATH];
1250+
char rm_path[MAXPGPATH];
1251+
DIR *db_dir;
1252+
DIR *temp_dir;
1253+
struct dirent *db_de;
1254+
struct dirent *temp_de;
1255+
1256+
/*
1257+
* Cycle through pg_tempfiles for all databases
1258+
* and remove old temp files.
1259+
*/
1260+
snprintf(db_path, sizeof(db_path), "%s/base", DataDir);
1261+
if ((db_dir = opendir(db_path)) != NULL)
1262+
{
1263+
while ((db_de = readdir(db_dir)) != NULL)
1264+
{
1265+
if (strcmp(db_de->d_name, ".") == 0 ||
1266+
strcmp(db_de->d_name, "..") == 0)
1267+
continue;
1268+
1269+
snprintf(temp_path, sizeof(temp_path),
1270+
"%s/%s/%s",
1271+
db_path, db_de->d_name,
1272+
PG_TEMP_FILES_DIR);
1273+
if ((temp_dir = opendir(temp_path)) != NULL)
1274+
{
1275+
while ((temp_de = readdir(temp_dir)) != NULL)
1276+
{
1277+
if (strcmp(temp_de->d_name, ".") == 0 ||
1278+
strcmp(temp_de->d_name, "..") == 0)
1279+
continue;
1280+
1281+
snprintf(rm_path, sizeof(temp_path),
1282+
"%s/%s/%s/%s",
1283+
db_path, db_de->d_name,
1284+
PG_TEMP_FILES_DIR,
1285+
temp_de->d_name);
1286+
1287+
if (strncmp(temp_de->d_name,
1288+
PG_TEMP_FILE_PREFIX,
1289+
strlen(PG_TEMP_FILE_PREFIX)) == 0)
1290+
{
1291+
unlink(rm_path);
1292+
}
1293+
else
1294+
{
1295+
/*
1296+
* would prefer to use elog here, but it's not
1297+
* up and running during postmaster startup...
1298+
*/
1299+
fprintf(stderr,
1300+
"Unexpected file found in temporary-files directory: %s\n",
1301+
rm_path);
1302+
}
1303+
}
1304+
closedir(temp_dir);
1305+
}
1306+
}
1307+
closedir(db_dir);
1308+
}
1309+
}

src/include/storage/fd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: fd.h,v 1.29 2001/05/25 15:45:34 momjian Exp $
10+
* $Id: fd.h,v 1.30 2001/06/11 04:12:29 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -70,6 +70,7 @@ extern int BasicOpenFile(FileName fileName, int fileFlags, int fileMode);
7070
/* Miscellaneous support routines */
7171
extern void closeAllVfds(void);
7272
extern void AtEOXact_Files(void);
73+
extern void RemovePgTempFiles(void);
7374
extern int pg_fsync(int fd);
7475
extern int pg_fdatasync(int fd);
7576

0 commit comments

Comments
 (0)