Index: doc/src/sgml/config.sgml
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/doc/src/sgml/config.sgml,v
retrieving revision 1.124
diff -c -r1.124 config.sgml
*** doc/src/sgml/config.sgml 17 May 2007 23:36:04 -0000 1.124
--- doc/src/sgml/config.sgml 29 May 2007 01:15:44 -0000
***************
*** 3485,3490 ****
--- 3485,3524 ----
+
+ temp_tablespaces (string)
+
+ temp_tablespaces> configuration parameter
+
+ tablespace>temp>>
+
+
+ This variable specifies tablespaces in which to create temp
+ objects (temp tables and indexes on temp tables) when a
+ CREATE> command does not explicitly specify a tablespace
+ and temp files when necessary (eg. for sorting operations).
+
+
+
+ The value is either a list of names of tablespaces, or an empty
+ string to specify using the default tablespace of the current database.
+ If the value does not match the name of any existing tablespace,
+ PostgreSQL> will automatically use the default
+ tablespace of the current database.
+
+
+
+ The first tablespace that will be used is choosen randomly from the
+ list, starting from that we cycle through the list in order.
+
+
+
+ For more information on tablespaces,
+ see .
+
+
+
+
check_function_bodies (boolean)
Index: src/backend/commands/indexcmds.c
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/backend/commands/indexcmds.c,v
retrieving revision 1.158
diff -c -r1.158 indexcmds.c
*** src/backend/commands/indexcmds.c 2 May 2007 21:08:45 -0000 1.158
--- src/backend/commands/indexcmds.c 29 May 2007 01:15:44 -0000
***************
*** 208,214 ****
}
else
{
! tablespaceId = GetDefaultTablespace();
/* note InvalidOid is OK in this case */
}
--- 208,220 ----
}
else
{
! /*
! * if the target table is temporary then use a temp_tablespace
! */
! if (!rel->rd_istemp)
! tablespaceId = GetDefaultTablespace();
! else
! tablespaceId = GetTempTablespace();
/* note InvalidOid is OK in this case */
}
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.225
diff -c -r1.225 tablecmds.c
*** src/backend/commands/tablecmds.c 18 May 2007 23:19:41 -0000 1.225
--- src/backend/commands/tablecmds.c 29 May 2007 01:15:44 -0000
***************
*** 331,336 ****
--- 331,340 ----
errmsg("tablespace \"%s\" does not exist",
stmt->tablespacename)));
}
+ else if (stmt->relation->istemp)
+ {
+ tablespaceId = GetTempTablespace();
+ }
else
{
tablespaceId = GetDefaultTablespace();
Index: src/backend/commands/tablespace.c
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/backend/commands/tablespace.c,v
retrieving revision 1.45
diff -c -r1.45 tablespace.c
*** src/backend/commands/tablespace.c 22 Mar 2007 19:51:44 -0000 1.45
--- src/backend/commands/tablespace.c 30 May 2007 23:31:14 -0000
***************
*** 65,75 ****
#include "utils/lsyscache.h"
! /* GUC variable */
char *default_tablespace = NULL;
static bool remove_tablespace_directories(Oid tablespaceoid, bool redo);
static void set_short_version(const char *path);
--- 65,79 ----
#include "utils/lsyscache.h"
! /* GUC variables */
char *default_tablespace = NULL;
+ char *temp_tablespaces = NULL;
+ int next_temp_tablespace;
+ int num_temp_tablespaces;
static bool remove_tablespace_directories(Oid tablespaceoid, bool redo);
+ static bool tempfiles_older_than_postmaster(Oid tablespaceoid);
static void set_short_version(const char *path);
***************
*** 453,462 ****
* Try to remove the physical infrastructure
*/
if (!remove_tablespace_directories(tablespaceoid, false))
! ereport(ERROR,
! (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
! errmsg("tablespace \"%s\" is not empty",
! tablespacename)));
/* Record the filesystem change in XLOG */
{
--- 457,483 ----
* Try to remove the physical infrastructure
*/
if (!remove_tablespace_directories(tablespaceoid, false))
! {
! /*
! * Investigate if there are temp files older than postmaster startup.
! * The only reason for this is if there was a server crash, on that
! * case we do not delete temp files at startup for the DBA to
! * investigate the crash. So, at least we want to warn him that
! * in this tablespace there are temp files older than postmaster so he
! * can decide if he care of it or not.
! */
! if (tempfiles_older_than_postmaster(tablespaceoid))
! ereport(ERROR,
! (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
! errmsg("tablespace \"%s\" is not empty",
! tablespacename),
! errhint("there are temp files older than postmaster startup, it's probably safe to delete them")));
! else
! ereport(ERROR,
! (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
! errmsg("tablespace \"%s\" is not empty",
! tablespacename)));
! }
/* Record the filesystem change in XLOG */
{
***************
*** 624,629 ****
--- 645,714 ----
return true;
}
+
+ /*
+ * tempfiles_older_than_postmaster
+ *
+ * Returns TRUE if there are files older than postmaster in
+ * pg_tblspc/#tablespaceoid#/PG_TEMP_FILES_DIR, FALSE otherwise
+ *
+ */
+ static bool
+ tempfiles_older_than_postmaster(Oid tablespaceoid)
+ {
+ char *location;
+ DIR *dirdesc;
+ struct dirent *de;
+ char *subfile;
+ struct stat st;
+
+ location = (char *) palloc(20 + OIDCHARS + 1);
+ sprintf(location, "pg_tblspc/%u/%s", tablespaceoid, PG_TEMP_FILES_DIR);
+
+ dirdesc = AllocateDir(location);
+ if (dirdesc == NULL)
+ {
+ if (errno == ENOENT)
+ {
+ /*
+ * If there isn't a PG_TEMP_FILES_DIR then exit
+ */
+ pfree(location);
+ return false;
+ }
+ }
+
+ while ((de = ReadDir(dirdesc, location)) != NULL)
+ {
+ if (strcmp(de->d_name, ".") == 0 ||
+ strcmp(de->d_name, "..") == 0)
+ continue;
+
+ subfile = palloc(strlen(location) + 1 + strlen(de->d_name) + 1);
+ sprintf(subfile, "%s/%s", location, de->d_name);
+
+ if (stat(subfile, &st) == 0)
+ {
+ if (time_t_to_timestamptz(st.st_atime) < PgStartTime)
+ {
+ pfree(subfile);
+ pfree(location);
+ FreeDir(dirdesc);
+ return true;
+ }
+ }
+
+ pfree(subfile);
+ }
+
+ FreeDir(dirdesc);
+
+ pfree(location);
+
+ return false;
+ }
+
+
/*
* write out the PG_VERSION file in the specified directory
*/
***************
*** 935,940 ****
--- 1020,1165 ----
return result;
}
+ /*
+ * Routines for handling the GUC variable 'temp_tablespaces'.
+ */
+
+ /* assign_hook: validate new temp_tablespaces, do extra actions as needed */
+ const char *
+ assign_temp_tablespaces(const char *newval, bool doit, GucSource source)
+ {
+ char *rawname;
+ List *namelist;
+ ListCell *l;
+
+ /* Need a modifiable copy of string */
+ rawname = pstrdup(newval);
+
+ /* Parse string into list of identifiers */
+ if (!SplitIdentifierString(rawname, ',', &namelist))
+ {
+ /* syntax error in name list */
+ pfree(rawname);
+ list_free(namelist);
+ return NULL;
+ }
+
+ num_temp_tablespaces = 0;
+ foreach(l, namelist)
+ {
+ char *curname = (char *) lfirst(l);
+ if (curname[0] == '\0')
+ continue;
+
+ /*
+ * If we aren't inside a transaction, we cannot do database access so
+ * cannot verify the individual names. Must accept the list on faith.
+ */
+ if (source >= PGC_S_INTERACTIVE && IsTransactionState())
+ {
+ /*
+ * Verify that all the names are valid tablspace names
+ * We do not check for USAGE rights should we?
+ */
+ if (get_tablespace_oid(curname) == InvalidOid)
+ ereport((source == PGC_S_TEST) ? NOTICE : ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("tablespace \"%s\" does not exist", curname)));
+ }
+ num_temp_tablespaces++;
+ }
+
+ /*
+ * Select the first tablespace to use
+ */
+ Assert(num_temp_tablespaces >= 0);
+ if (num_temp_tablespaces != 0)
+ next_temp_tablespace = MyProcPid % num_temp_tablespaces;
+
+ pfree(rawname);
+ list_free(namelist);
+ return newval;
+ }
+
+ /*
+ * GetTempTablespace -- get the OID of the tablespace for temporary objects
+ *
+ * May return InvalidOid to indicate "use the database's default tablespace"
+ *
+ * This exists to hide the temp_tablespace GUC variable.
+ */
+ Oid
+ GetTempTablespace(void)
+ {
+ Oid result;
+ char *curname = NULL;
+ char *rawname;
+ List *namelist;
+ ListCell *l;
+ int i = 0;
+
+ if ( temp_tablespaces == NULL )
+ return InvalidOid;
+
+ /* Need a modifiable version of temp_tablespaces */
+ rawname = pstrdup(temp_tablespaces);
+
+ /* Parse string into list of identifiers */
+ if (!SplitIdentifierString(rawname, ',', &namelist))
+ {
+ /* syntax error in name list */
+ pfree(rawname);
+ list_free(namelist);
+ return InvalidOid;
+ }
+
+ /*
+ * Iterate through the list of namespaces until the one we need
+ * (next_temp_tablespace)
+ */
+ foreach(l, namelist)
+ {
+ curname = (char *) lfirst(l);
+ if ( i == next_temp_tablespace )
+ break;
+ i++;
+ }
+
+
+ /* Prepare for the next time the function is called */
+ next_temp_tablespace++;
+ if (next_temp_tablespace == num_temp_tablespaces)
+ next_temp_tablespace = 0;
+
+ /* Fast path for temp_tablespaces == "" */
+ if ( curname == NULL || curname[0] == '\0') {
+ list_free(namelist);
+ pfree(rawname);
+ return InvalidOid;
+ }
+
+ /*
+ * It is tempting to cache this lookup for more speed, but then we would
+ * fail to detect the case where the tablespace was dropped since the GUC
+ * variable was set. Note also that we don't complain if the value fails
+ * to refer to an existing tablespace; we just silently return InvalidOid,
+ * causing the new object to be created in the database's tablespace.
+ */
+ result = get_tablespace_oid(curname);
+
+ /* We don't free rawname before because curname points to a part of it */
+ pfree(rawname);
+
+ /*
+ * Allow explicit specification of database's default tablespace in
+ * default_tablespace without triggering permissions checks.
+ */
+ if (result == MyDatabaseTableSpace)
+ result = InvalidOid;
+
+ list_free(namelist);
+ return result;
+ }
/*
* get_tablespace_oid - given a tablespace name, look up the OID
Index: src/backend/executor/execMain.c
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/backend/executor/execMain.c,v
retrieving revision 1.293
diff -c -r1.293 execMain.c
*** src/backend/executor/execMain.c 27 Apr 2007 22:05:47 -0000 1.293
--- src/backend/executor/execMain.c 29 May 2007 01:15:44 -0000
***************
*** 2442,2447 ****
--- 2442,2451 ----
errmsg("tablespace \"%s\" does not exist",
into->tableSpaceName)));
}
+ else if (into->rel->istemp)
+ {
+ tablespaceId = GetTempTablespace();
+ }
else
{
tablespaceId = GetDefaultTablespace();
Index: src/backend/executor/nodeHashjoin.c
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/backend/executor/nodeHashjoin.c,v
retrieving revision 1.89
diff -c -r1.89 nodeHashjoin.c
*** src/backend/executor/nodeHashjoin.c 2 Feb 2007 00:07:03 -0000 1.89
--- src/backend/executor/nodeHashjoin.c 29 May 2007 01:15:44 -0000
***************
*** 15,27 ****
#include "postgres.h"
#include "executor/executor.h"
#include "executor/hashjoin.h"
#include "executor/nodeHash.h"
#include "executor/nodeHashjoin.h"
#include "utils/memutils.h"
-
static TupleTableSlot *ExecHashJoinOuterGetTuple(PlanState *outerNode,
HashJoinState *hjstate,
uint32 *hashvalue);
--- 15,27 ----
#include "postgres.h"
+ #include "commands/tablespace.h"
#include "executor/executor.h"
#include "executor/hashjoin.h"
#include "executor/nodeHash.h"
#include "executor/nodeHashjoin.h"
#include "utils/memutils.h"
static TupleTableSlot *ExecHashJoinOuterGetTuple(PlanState *outerNode,
HashJoinState *hjstate,
uint32 *hashvalue);
***************
*** 763,769 ****
if (file == NULL)
{
/* First write to this batch file, so open it. */
! file = BufFileCreateTemp(false);
*fileptr = file;
}
--- 763,769 ----
if (file == NULL)
{
/* First write to this batch file, so open it. */
! file = BufFileCreateTemp(false, GetTempTablespace());
*fileptr = file;
}
Index: src/backend/storage/file/buffile.c
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/backend/storage/file/buffile.c,v
retrieving revision 1.25
diff -c -r1.25 buffile.c
*** src/backend/storage/file/buffile.c 5 Jan 2007 22:19:37 -0000 1.25
--- src/backend/storage/file/buffile.c 29 May 2007 01:15:44 -0000
***************
*** 63,68 ****
--- 63,69 ----
bool isTemp; /* can only add files if this is TRUE */
bool isInterXact; /* keep open over transactions? */
+ Oid tblspcOid; /* Tablespace Oid or InvalidOid */
bool dirty; /* does buffer need to be written? */
/*
***************
*** 98,103 ****
--- 99,105 ----
file->offsets = (long *) palloc(sizeof(long));
file->offsets[0] = 0L;
file->isTemp = false;
+ file->tblspcOid = InvalidOid;
file->dirty = false;
file->curFile = 0;
file->curOffset = 0L;
***************
*** 116,122 ****
File pfile;
Assert(file->isTemp);
! pfile = OpenTemporaryFile(file->isInterXact);
Assert(pfile >= 0);
file->files = (File *) repalloc(file->files,
--- 118,124 ----
File pfile;
Assert(file->isTemp);
! pfile = OpenTemporaryFile(file->isInterXact, file->tblspcOid);
Assert(pfile >= 0);
file->files = (File *) repalloc(file->files,
***************
*** 137,153 ****
* memory context that will survive across transaction boundaries.
*/
BufFile *
! BufFileCreateTemp(bool interXact)
{
BufFile *file;
File pfile;
! pfile = OpenTemporaryFile(interXact);
Assert(pfile >= 0);
file = makeBufFile(pfile);
file->isTemp = true;
file->isInterXact = interXact;
return file;
}
--- 139,156 ----
* memory context that will survive across transaction boundaries.
*/
BufFile *
! BufFileCreateTemp(bool interXact, Oid tblspcOid)
{
BufFile *file;
File pfile;
! pfile = OpenTemporaryFile(interXact, tblspcOid);
Assert(pfile >= 0);
file = makeBufFile(pfile);
file->isTemp = true;
file->isInterXact = interXact;
+ file->tblspcOid = tblspcOid;
return file;
}
Index: src/backend/storage/file/fd.c
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/backend/storage/file/fd.c,v
retrieving revision 1.137
diff -c -r1.137 fd.c
*** src/backend/storage/file/fd.c 6 Mar 2007 02:06:14 -0000 1.137
--- src/backend/storage/file/fd.c 29 May 2007 19:14:42 -0000
***************
*** 76,82 ****
*/
#define FD_MINFREE 10
-
/*
* A number of platforms allow individual processes to open many more files
* than they can really support when *many* processes do the same thing.
--- 76,81 ----
***************
*** 225,231 ****
--- 224,232 ----
static void FreeVfd(File file);
static int FileAccess(File file);
+ #ifdef NOT_USED
static char *make_database_relative(const char *filename);
+ #endif
static void AtProcExit_Files(int code, Datum arg);
static void CleanupTempFiles(bool isProcExit);
static void RemovePgTempFilesInDir(const char *tmpdirname);
***************
*** 721,726 ****
--- 722,728 ----
VfdCache[0].nextFree = file;
}
+ #ifdef NOT_USED
/*
* make_database_relative()
* Prepend DatabasePath to the given file name.
***************
*** 737,742 ****
--- 739,745 ----
sprintf(buf, "%s/%s", DatabasePath, filename);
return buf;
}
+ #endif
/* returns 0 on success, -1 on re-open failure (with errno set) */
static int
***************
*** 844,849 ****
--- 847,853 ----
return file;
}
+ #ifdef NOT_USED
/*
* open a file in the database directory ($PGDATA/base/DIROID/)
*
***************
*** 861,925 ****
pfree(fname);
return fd;
}
/*
* Open a temporary file that will disappear when we close it.
*
- * This routine takes care of generating an appropriate tempfile name.
- * 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.
*/
File
! OpenTemporaryFile(bool interXact)
{
- char tempfilepath[MAXPGPATH];
File file;
! /*
! * Generate a tempfile name that should be unique within the current
! * database instance.
! */
! snprintf(tempfilepath, sizeof(tempfilepath),
! "%s/%s%d.%ld", PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
! MyProcPid, tempFileCounter++);
!
! /*
! * 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)
{
- 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 = make_database_relative(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, "could not create temporary file \"%s\": %m",
! tempfilepath);
}
/* Mark it for deletion at close */
VfdCache[file].fdstate |= FD_TEMPORARY;
--- 865,907 ----
pfree(fname);
return fd;
}
+ #endif
/*
* Open a temporary file that will disappear when we close it.
*
* 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.
+ *
+ * tblspcOid: the oid of the tablespace where the temp file will be created.
+ * if InvalidOid we fall into $PGDATA/base
*/
File
! OpenTemporaryFile(bool interXact, Oid tblspcOid)
{
File file;
! if (tblspcOid != InvalidOid)
{
/*
! * As we got a valid tablespace, try to create the
! * file there
*/
! file = OpenTempFileInTblspc(tblspcOid);
}
+ /*
+ * Create a normal temporary file if no tablespace was passed or
+ * couldn't create the file in the tablespace "tblspcOid"
+ */
+ if (tblspcOid == InvalidOid || file <= 0)
+ {
+ file = OpenTempFileInTblspc(InvalidOid);
+ }
+
/* Mark it for deletion at close */
VfdCache[file].fdstate |= FD_TEMPORARY;
***************
*** 933,938 ****
--- 915,1006 ----
return file;
}
+
+ /*
+ * Actually call PathNameOpenFile() to create the file.
+ *
+ * This routine takes care of generating an appropriate tempfile name.
+ * There's no need to pass in fileFlags or fileMode either, since only
+ * one setting makes any sense for a temp file.
+ *
+ * tblspcOid: the oid of the tabespace where the file will be created or
+ * InvalidOid if $PGDATA/base should be used.
+ */
+ File
+ OpenTempFileInTblspc(Oid tblspcOid)
+ {
+ char tempfilepath[MAXPGPATH];
+ int pathlen;
+ File file;
+ char *path;
+
+ pathlen = 20 + OIDCHARS + 1;
+ path = (char *) palloc(pathlen);
+
+ if (tblspcOid == InvalidOid)
+ snprintf(path, pathlen, "base/%s", PG_TEMP_FILES_DIR);
+ else
+ snprintf(path, pathlen, "pg_tblspc/%u/%s", tblspcOid,
+ PG_TEMP_FILES_DIR);
+ /*
+ * Generate a tempfile name that should be unique within the current
+ * database instance.
+ */
+ snprintf(tempfilepath, sizeof(tempfilepath),
+ "%s/%s%d.%ld", path, PG_TEMP_FILE_PREFIX,
+ MyProcPid, tempFileCounter++);
+
+ /*
+ * Open the file. Note: we don't use O_EXCL, in case there is an
+ * orphaned temp file that can be reused.
+ */
+ file = PathNameOpenFile(tempfilepath,
+ O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
+ 0600);
+ /*
+ * 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.
+ */
+ if (file <= 0)
+ {
+ mkdir(path, S_IRWXU);
+ file = PathNameOpenFile(tempfilepath,
+ O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
+ 0600);
+
+ if (file <= 0)
+ {
+ if (tblspcOid == InvalidOid)
+ {
+ /*
+ * If can't open the file in base/pgsql_tmp directory then we
+ * throw an error
+ */
+ pfree(path);
+ elog(ERROR, "could not create temporary file \"%s\": %m",
+ tempfilepath);
+ }
+ else
+ {
+ /*
+ * If can't open the file in pg_tblspc/(tblspc_oid)/pgsql_tmp
+ * directory then we throw a notice
+ */
+ elog(NOTICE, "could not create temporary file \"%s\": %m",
+ tempfilepath);
+ }
+ }
+ }
+ pfree(path);
+
+ return file;
+ }
+
+
/*
* close a file when done with it
*/
***************
*** 1292,1297 ****
--- 1360,1379 ----
errno = save_errno;
}
+ /*
+ * TEMPORARY hack to log the Windows error code on fopen failures, in
+ * hopes of diagnosing some hard-to-reproduce problems.
+ */
+ #ifdef WIN32
+ {
+ int save_errno = errno;
+
+ elog(LOG, "Windows fopen(\"%s\",\"%s\") failed: code %lu, errno %d",
+ name, mode, GetLastError(), save_errno);
+ errno = save_errno;
+ }
+ #endif
+
return NULL;
}
***************
*** 1647,1664 ****
struct dirent *db_de;
/*
! * Cycle through pgsql_tmp directories for all databases and remove old
* temp files.
*/
! db_dir = AllocateDir("base");
! while ((db_de = ReadDir(db_dir, "base")) != NULL)
{
if (strcmp(db_de->d_name, ".") == 0 ||
strcmp(db_de->d_name, "..") == 0)
continue;
! snprintf(temp_path, sizeof(temp_path), "base/%s/%s",
db_de->d_name, PG_TEMP_FILES_DIR);
RemovePgTempFilesInDir(temp_path);
}
--- 1729,1752 ----
struct dirent *db_de;
/*
! * First process pgsql_tmp in base directory
! */
! snprintf(temp_path, sizeof(temp_path), "base/%s", PG_TEMP_FILES_DIR);
! RemovePgTempFilesInDir(temp_path);
!
! /*
! * Cycle through pgsql_tmp directories for all tablespaces and remove old
* temp files.
*/
! db_dir = AllocateDir("pg_tblspc");
! while ((db_de = ReadDir(db_dir, "pg_tblspc")) != NULL)
{
if (strcmp(db_de->d_name, ".") == 0 ||
strcmp(db_de->d_name, "..") == 0)
continue;
! snprintf(temp_path, sizeof(temp_path), "pg_tblspc/%s/%s",
db_de->d_name, PG_TEMP_FILES_DIR);
RemovePgTempFilesInDir(temp_path);
}
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.391
diff -c -r1.391 guc.c
*** src/backend/utils/misc/guc.c 8 May 2007 16:33:51 -0000 1.391
--- src/backend/utils/misc/guc.c 29 May 2007 01:15:44 -0000
***************
*** 103,108 ****
--- 103,109 ----
extern int CommitDelay;
extern int CommitSiblings;
extern char *default_tablespace;
+ extern char *temp_tablespaces;
extern bool fullPageWrites;
#ifdef TRACE_SORT
***************
*** 2387,2392 ****
--- 2388,2403 ----
},
#endif /* USE_SSL */
+ {
+ {"temp_tablespaces", PGC_USERSET, PGC_S_FILE,
+ gettext_noop("Sets the tablespaces suitable for creating new objects and sort files."),
+ NULL,
+ GUC_LIST_INPUT | GUC_LIST_QUOTE
+ },
+ &temp_tablespaces,
+ NULL, assign_temp_tablespaces, NULL
+ },
+
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.215
diff -c -r1.215 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample 18 Apr 2007 16:44:18 -0000 1.215
--- src/backend/utils/misc/postgresql.conf.sample 29 May 2007 01:15:44 -0000
***************
*** 408,413 ****
--- 408,415 ----
#search_path = '"$user",public' # schema names
#default_tablespace = '' # a tablespace name, '' uses
# the default
+ #temp_tablespaces = '' # a list of tablespace names,
+ # '' uses default_tablespace
#check_function_bodies = on
#default_transaction_isolation = 'read committed'
#default_transaction_read_only = off
Index: src/backend/utils/sort/logtape.c
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/backend/utils/sort/logtape.c,v
retrieving revision 1.23
diff -c -r1.23 logtape.c
*** src/backend/utils/sort/logtape.c 5 Jan 2007 22:19:47 -0000 1.23
--- src/backend/utils/sort/logtape.c 29 May 2007 01:15:44 -0000
***************
*** 77,82 ****
--- 77,83 ----
#include "postgres.h"
+ #include "commands/tablespace.h"
#include "storage/buffile.h"
#include "utils/logtape.h"
***************
*** 528,534 ****
Assert(ntapes > 0);
lts = (LogicalTapeSet *) palloc(sizeof(LogicalTapeSet) +
(ntapes - 1) *sizeof(LogicalTape));
! lts->pfile = BufFileCreateTemp(false);
lts->nFileBlocks = 0L;
lts->forgetFreeSpace = false;
lts->blocksSorted = true; /* a zero-length array is sorted ... */
--- 529,535 ----
Assert(ntapes > 0);
lts = (LogicalTapeSet *) palloc(sizeof(LogicalTapeSet) +
(ntapes - 1) *sizeof(LogicalTape));
! lts->pfile = BufFileCreateTemp(false, GetTempTablespace());
lts->nFileBlocks = 0L;
lts->forgetFreeSpace = false;
lts->blocksSorted = true; /* a zero-length array is sorted ... */
Index: src/backend/utils/sort/tuplestore.c
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/backend/utils/sort/tuplestore.c,v
retrieving revision 1.31
diff -c -r1.31 tuplestore.c
*** src/backend/utils/sort/tuplestore.c 21 May 2007 17:57:34 -0000 1.31
--- src/backend/utils/sort/tuplestore.c 29 May 2007 01:17:19 -0000
***************
*** 46,51 ****
--- 46,52 ----
#include "postgres.h"
#include "access/heapam.h"
+ #include "commands/tablespace.h"
#include "executor/executor.h"
#include "storage/buffile.h"
#include "utils/memutils.h"
***************
*** 425,431 ****
/*
* Nope; time to switch to tape-based operation.
*/
! state->myfile = BufFileCreateTemp(state->interXact);
state->status = TSS_WRITEFILE;
dumptuples(state);
break;
--- 426,433 ----
/*
* Nope; time to switch to tape-based operation.
*/
! state->myfile = BufFileCreateTemp(state->interXact,
! GetTempTablespace());
state->status = TSS_WRITEFILE;
dumptuples(state);
break;
Index: src/include/commands/tablespace.h
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/include/commands/tablespace.h,v
retrieving revision 1.16
diff -c -r1.16 tablespace.h
*** src/include/commands/tablespace.h 6 Mar 2007 02:06:15 -0000 1.16
--- src/include/commands/tablespace.h 29 May 2007 01:15:44 -0000
***************
*** 41,46 ****
--- 41,47 ----
extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
extern Oid GetDefaultTablespace(void);
+ extern Oid GetTempTablespace(void);
extern Oid get_tablespace_oid(const char *tablespacename);
extern char *get_tablespace_name(Oid spc_oid);
Index: src/include/storage/buffile.h
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/include/storage/buffile.h,v
retrieving revision 1.20
diff -c -r1.20 buffile.h
*** src/include/storage/buffile.h 5 Jan 2007 22:19:57 -0000 1.20
--- src/include/storage/buffile.h 29 May 2007 01:15:44 -0000
***************
*** 34,40 ****
* prototypes for functions in buffile.c
*/
! extern BufFile *BufFileCreateTemp(bool interXact);
extern void BufFileClose(BufFile *file);
extern size_t BufFileRead(BufFile *file, void *ptr, size_t size);
extern size_t BufFileWrite(BufFile *file, void *ptr, size_t size);
--- 34,40 ----
* prototypes for functions in buffile.c
*/
! extern BufFile *BufFileCreateTemp(bool interXact, Oid tblspcOid);
extern void BufFileClose(BufFile *file);
extern size_t BufFileRead(BufFile *file, void *ptr, size_t size);
extern size_t BufFileWrite(BufFile *file, void *ptr, size_t size);
Index: src/include/storage/fd.h
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/include/storage/fd.h,v
retrieving revision 1.57
diff -c -r1.57 fd.h
*** src/include/storage/fd.h 5 Jan 2007 22:19:57 -0000 1.57
--- src/include/storage/fd.h 29 May 2007 19:14:45 -0000
***************
*** 59,67 ****
*/
/* Operations on virtual Files --- equivalent to Unix kernel file ops */
extern File FileNameOpenFile(FileName fileName, int fileFlags, int fileMode);
extern File PathNameOpenFile(FileName fileName, int fileFlags, int fileMode);
! extern File OpenTemporaryFile(bool interXact);
extern void FileClose(File file);
extern void FileUnlink(File file);
extern int FileRead(File file, char *buffer, int amount);
--- 59,70 ----
*/
/* Operations on virtual Files --- equivalent to Unix kernel file ops */
+ #ifdef NOT_USED
extern File FileNameOpenFile(FileName fileName, int fileFlags, int fileMode);
+ #endif
extern File PathNameOpenFile(FileName fileName, int fileFlags, int fileMode);
! extern File OpenTemporaryFile(bool interXact, Oid tblspcOid);
! extern File OpenTempFileInTblspc(Oid tblspcOid);
extern void FileClose(File file);
extern void FileUnlink(File file);
extern int FileRead(File file, char *buffer, int amount);
***************
*** 99,102 ****
--- 102,107 ----
#define PG_TEMP_FILES_DIR "pgsql_tmp"
#define PG_TEMP_FILE_PREFIX "pgsql_tmp"
+ #define OIDCHARS 10 /* max chars printed by %u */
+
#endif /* FD_H */
Index: src/include/utils/guc.h
===================================================================
RCS file: /home/postgres/PG_RELEASES/pg_repository/pgsql/src/include/utils/guc.h,v
retrieving revision 1.81
diff -c -r1.81 guc.h
*** src/include/utils/guc.h 12 Apr 2007 06:53:48 -0000 1.81
--- src/include/utils/guc.h 29 May 2007 01:15:44 -0000
***************
*** 238,241 ****
--- 238,245 ----
extern const char *assign_xlog_sync_method(const char *method,
bool doit, GucSource source);
+ /* in commands/tablespace.c */
+ extern const char *assign_temp_tablespaces(const char *newval,
+ bool doit, GucSource source);
+
#endif /* GUC_H */