Add WAL logging for CREATE/DROP DATABASE and CREATE/DROP TABLESPACE.

Fix TablespaceCreateDbspace() to be able to create a dummy directory
in place of a dropped tablespace's symlink.  This eliminates the open
problem of a PANIC during WAL replay when a replayed action attempts
to touch a file in a since-deleted tablespace.  It also makes for a
significant improvement in the usability of PITR replay.
This commit is contained in:
Tom Lane 2004-08-29 21:08:48 +00:00
parent ee66401f31
commit 50742aed68
9 changed files with 483 additions and 106 deletions

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.46 2004/08/08 04:34:43 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.47 2004/08/29 21:08:47 tgl Exp $
-->
<chapter id="backup">
<title>Backup and Restore</title>
@ -902,17 +902,9 @@ restore_command = 'cp /mnt/server/archivedir/%f %p'
<para>
At this writing, there are several limitations of the on-line backup
technique. These will probably be fixed in future releases.
technique. These will probably be fixed in future releases:
<itemizedlist>
<listitem>
<para>
The effects of <command>CREATE DATABASE</>, <command>DROP DATABASE</>,
<command>CREATE TABLESPACE</>, and <command>DROP TABLESPACE</> are
not fully reflected in the WAL log. It is recommended that you take
a new base backup after performing one of these operations.
</para>
</listitem>
<listitem>
<para>
Operations on non-btree indexes (hash, R-tree, and GiST indexes) are
@ -932,7 +924,7 @@ restore_command = 'cp /mnt/server/archivedir/%f %p'
since we may need to fix partially-written disk pages. It is not
necessary to store so many page copies for PITR operations, however.
An area for future development is to compress archived WAL data by
removing unnecesssary page copies.
removing unnecessary page copies.
</para>
</sect2>
</sect1>

View File

@ -3,20 +3,22 @@
*
* Resource managers definition
*
* $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.15 2004/08/23 23:22:44 tgl Exp $
* $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.16 2004/08/29 21:08:47 tgl Exp $
*/
#include "postgres.h"
#include "access/clog.h"
#include "access/gist.h"
#include "access/hash.h"
#include "access/heapam.h"
#include "access/nbtree.h"
#include "access/rtree.h"
#include "access/clog.h"
#include "access/xact.h"
#include "access/xlog_internal.h"
#include "storage/smgr.h"
#include "commands/dbcommands.h"
#include "commands/sequence.h"
#include "commands/tablespace.h"
#include "storage/smgr.h"
const RmgrData RmgrTable[RM_MAX_ID + 1] = {
@ -24,8 +26,8 @@ const RmgrData RmgrTable[RM_MAX_ID + 1] = {
{"Transaction", xact_redo, xact_undo, xact_desc, NULL, NULL},
{"Storage", smgr_redo, smgr_undo, smgr_desc, NULL, NULL},
{"CLOG", clog_redo, clog_undo, clog_desc, NULL, NULL},
{"Reserved 4", NULL, NULL, NULL, NULL, NULL},
{"Reserved 5", NULL, NULL, NULL, NULL, NULL},
{"Database", dbase_redo, dbase_undo, dbase_desc, NULL, NULL},
{"Tablespace", tblspc_redo, tblspc_undo, tblspc_desc, NULL, NULL},
{"Reserved 6", NULL, NULL, NULL, NULL, NULL},
{"Reserved 7", NULL, NULL, NULL, NULL, NULL},
{"Reserved 8", NULL, NULL, NULL, NULL, NULL},

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.141 2004/08/29 05:06:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.142 2004/08/29 21:08:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -385,6 +385,30 @@ createdb(const CreatedbStmt *stmt)
(errmsg("could not initialize database directory")));
}
#endif /* WIN32 */
/* Record the filesystem change in XLOG */
{
xl_dbase_create_rec xlrec;
XLogRecData rdata[3];
xlrec.db_id = dboid;
rdata[0].buffer = InvalidBuffer;
rdata[0].data = (char *) &xlrec;
rdata[0].len = offsetof(xl_dbase_create_rec, src_path);
rdata[0].next = &(rdata[1]);
rdata[1].buffer = InvalidBuffer;
rdata[1].data = (char *) srcpath;
rdata[1].len = strlen(srcpath) + 1;
rdata[1].next = &(rdata[2]);
rdata[2].buffer = InvalidBuffer;
rdata[2].data = (char *) dstpath;
rdata[2].len = strlen(dstpath) + 1;
rdata[2].next = NULL;
(void) XLogInsert(RM_DBASE_ID, XLOG_DBASE_CREATE, rdata);
}
}
heap_endscan(scan);
heap_close(rel, AccessShareLock);
@ -970,11 +994,27 @@ remove_dbtablespaces(Oid db_id)
}
if (!rmtree(dstpath, true))
{
ereport(WARNING,
(errmsg("could not remove database directory \"%s\"",
dstpath),
errhint("Look in the postmaster's stderr log for more information.")));
dstpath)));
/* Record the filesystem change in XLOG */
{
xl_dbase_drop_rec xlrec;
XLogRecData rdata[2];
xlrec.db_id = db_id;
rdata[0].buffer = InvalidBuffer;
rdata[0].data = (char *) &xlrec;
rdata[0].len = offsetof(xl_dbase_drop_rec, dir_path);
rdata[0].next = &(rdata[1]);
rdata[1].buffer = InvalidBuffer;
rdata[1].data = (char *) dstpath;
rdata[1].len = strlen(dstpath) + 1;
rdata[1].next = NULL;
(void) XLogInsert(RM_DBASE_ID, XLOG_DBASE_DROP, rdata);
}
pfree(dstpath);
@ -1063,3 +1103,105 @@ get_database_name(Oid dbid)
return result;
}
/*
* DATABASE resource manager's routines
*/
void
dbase_redo(XLogRecPtr lsn, XLogRecord *record)
{
uint8 info = record->xl_info & ~XLR_INFO_MASK;
if (info == XLOG_DBASE_CREATE)
{
xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) XLogRecGetData(record);
char *dst_path = xlrec->src_path + strlen(xlrec->src_path) + 1;
struct stat st;
#ifndef WIN32
char buf[2 * MAXPGPATH + 100];
#endif
/*
* Our theory for replaying a CREATE is to forcibly drop the target
* subdirectory if present, then re-copy the source data. This
* may be more work than needed, but it is simple to implement.
*/
if (stat(dst_path, &st) == 0 && S_ISDIR(st.st_mode))
{
if (!rmtree(dst_path, true))
ereport(WARNING,
(errmsg("could not remove database directory \"%s\"",
dst_path)));
}
#ifndef WIN32
/*
* Copy this subdirectory to the new location
*
* XXX use of cp really makes this code pretty grotty, particularly
* with respect to lack of ability to report errors well. Someday
* rewrite to do it for ourselves.
*/
/* We might need to use cp -R one day for portability */
snprintf(buf, sizeof(buf), "cp -r '%s' '%s'",
xlrec->src_path, dst_path);
if (system(buf) != 0)
ereport(ERROR,
(errmsg("could not initialize database directory"),
errdetail("Failing system command was: %s", buf),
errhint("Look in the postmaster's stderr log for more information.")));
#else /* WIN32 */
if (copydir(xlrec->src_path, dst_path) != 0)
{
/* copydir should already have given details of its troubles */
ereport(ERROR,
(errmsg("could not initialize database directory")));
}
#endif /* WIN32 */
}
else if (info == XLOG_DBASE_DROP)
{
xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) XLogRecGetData(record);
/* Drop pages for this database that are in the shared buffer cache */
DropBuffers(xlrec->db_id);
if (!rmtree(xlrec->dir_path, true))
ereport(WARNING,
(errmsg("could not remove database directory \"%s\"",
xlrec->dir_path)));
}
else
elog(PANIC, "dbase_redo: unknown op code %u", info);
}
void
dbase_undo(XLogRecPtr lsn, XLogRecord *record)
{
elog(PANIC, "dbase_undo: unimplemented");
}
void
dbase_desc(char *buf, uint8 xl_info, char *rec)
{
uint8 info = xl_info & ~XLR_INFO_MASK;
if (info == XLOG_DBASE_CREATE)
{
xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) rec;
char *dst_path = xlrec->src_path + strlen(xlrec->src_path) + 1;
sprintf(buf + strlen(buf), "create db: %u copy \"%s\" to \"%s\"",
xlrec->db_id, xlrec->src_path, dst_path);
}
else if (info == XLOG_DBASE_DROP)
{
xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) rec;
sprintf(buf + strlen(buf), "drop db: %u directory: \"%s\"",
xlrec->db_id, xlrec->dir_path);
}
else
strcat(buf, "UNKNOWN");
}

View File

@ -45,7 +45,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.9 2004/08/29 05:06:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.10 2004/08/29 21:08:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -73,6 +73,7 @@
#include "utils/syscache.h"
static bool remove_tablespace_directories(Oid tablespaceoid, bool redo);
static void set_short_version(const char *path);
static bool directory_is_empty(const char *path);
@ -89,6 +90,13 @@ static bool directory_is_empty(const char *path);
* isRedo indicates that we are creating an object during WAL replay;
* we can skip doing locking in that case (and should do so to avoid
* any possible problems with pg_tablespace not being valid).
*
* Also, when isRedo is true, we will cope with the possibility of the
* tablespace not being there either --- this could happen if we are
* replaying an operation on a table in a subsequently-dropped tablespace.
* We handle this by making a directory in the place where the tablespace
* symlink would normally be. This isn't an exact replay of course, but
* it's the best we can do given the available information.
*/
void
TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
@ -137,10 +145,29 @@ TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
{
/* OK, go for it */
if (mkdir(dir, S_IRWXU) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
dir)));
{
char *parentdir;
if (errno != ENOENT || !isRedo)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
dir)));
/* Try to make parent directory too */
parentdir = pstrdup(dir);
get_parent_directory(parentdir);
if (mkdir(parentdir, S_IRWXU) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
parentdir)));
pfree(parentdir);
if (mkdir(dir, S_IRWXU) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
dir)));
}
}
/* OK to drop the exclusive lock */
@ -282,11 +309,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
tuple = heap_formtuple(rel->rd_att, values, nulls);
tablespaceoid = newoid();
HeapTupleSetOid(tuple, tablespaceoid);
simple_heap_insert(rel, tuple);
tablespaceoid = simple_heap_insert(rel, tuple);
CatalogUpdateIndexes(rel, tuple);
@ -332,10 +355,30 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
errmsg("could not create symbolic link \"%s\": %m",
linkloc)));
/* Record the filesystem change in XLOG */
{
xl_tblspc_create_rec xlrec;
XLogRecData rdata[2];
xlrec.ts_id = tablespaceoid;
rdata[0].buffer = InvalidBuffer;
rdata[0].data = (char *) &xlrec;
rdata[0].len = offsetof(xl_tblspc_create_rec, ts_path);
rdata[0].next = &(rdata[1]);
rdata[1].buffer = InvalidBuffer;
rdata[1].data = (char *) location;
rdata[1].len = strlen(location) + 1;
rdata[1].next = NULL;
(void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_CREATE, rdata);
}
pfree(linkloc);
pfree(location);
heap_close(rel, RowExclusiveLock);
/* We keep the lock on pg_tablespace until commit */
heap_close(rel, NoLock);
#else /* !HAVE_SYMLINK */
ereport(ERROR,
@ -358,11 +401,7 @@ DropTableSpace(DropTableSpaceStmt *stmt)
Relation rel;
HeapTuple tuple;
ScanKeyData entry[1];
char *location;
Oid tablespaceoid;
DIR *dirdesc;
struct dirent *de;
char *subfile;
/* don't call this in a transaction block */
PreventTransactionChain((void *) stmt, "DROP TABLESPACE");
@ -404,7 +443,63 @@ DropTableSpace(DropTableSpaceStmt *stmt)
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE,
tablespacename);
location = (char *) palloc(strlen(DataDir) + 16 + 10 + 1);
/*
* Remove the pg_tablespace tuple (this will roll back if we fail below)
*/
simple_heap_delete(rel, &tuple->t_self);
heap_endscan(scandesc);
/*
* 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 */
{
xl_tblspc_drop_rec xlrec;
XLogRecData rdata[1];
xlrec.ts_id = tablespaceoid;
rdata[0].buffer = InvalidBuffer;
rdata[0].data = (char *) &xlrec;
rdata[0].len = sizeof(xl_tblspc_drop_rec);
rdata[0].next = NULL;
(void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_DROP, rdata);
}
/* We keep the lock on pg_tablespace until commit */
heap_close(rel, NoLock);
#else /* !HAVE_SYMLINK */
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("tablespaces are not supported on this platform")));
#endif /* HAVE_SYMLINK */
}
/*
* remove_tablespace_directories: attempt to remove filesystem infrastructure
*
* Returns TRUE if successful, FALSE if some subdirectory is not empty
*
* redo indicates we are redoing a drop from XLOG; okay if nothing there
*/
static bool
remove_tablespace_directories(Oid tablespaceoid, bool redo)
{
char *location;
DIR *dirdesc;
struct dirent *de;
char *subfile;
struct stat st;
location = (char *) palloc(strlen(DataDir) + 11 + 10 + 1);
sprintf(location, "%s/pg_tblspc/%u", DataDir, tablespaceoid);
/*
@ -422,10 +517,17 @@ DropTableSpace(DropTableSpaceStmt *stmt)
*/
dirdesc = AllocateDir(location);
if (dirdesc == NULL)
{
if (redo && errno == ENOENT)
{
pfree(location);
return true;
}
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not open directory \"%s\": %m",
location)));
}
errno = 0;
while ((de = readdir(dirdesc)) != NULL)
@ -444,10 +546,10 @@ DropTableSpace(DropTableSpaceStmt *stmt)
/* This check is just to deliver a friendlier error message */
if (!directory_is_empty(subfile))
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("tablespace \"%s\" is not empty",
tablespacename)));
{
FreeDir(dirdesc);
return false;
}
/* Do the real deed */
if (rmdir(subfile) < 0)
@ -457,6 +559,7 @@ DropTableSpace(DropTableSpaceStmt *stmt)
subfile)));
pfree(subfile);
errno = 0;
}
#ifdef WIN32
@ -475,54 +578,51 @@ DropTableSpace(DropTableSpaceStmt *stmt)
FreeDir(dirdesc);
/*
* Okay, try to unlink PG_VERSION and then remove the symlink.
* Okay, try to unlink PG_VERSION (we allow it to not be there, even
* in non-REDO case, for robustness).
*/
subfile = palloc(strlen(location) + 11 + 1);
sprintf(subfile, "%s/PG_VERSION", location);
if (unlink(subfile) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not unlink file \"%s\": %m",
subfile)));
#ifndef WIN32
if (unlink(location) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not unlink symbolic link \"%s\": %m",
location)));
#else
/* The junction is a directory, not a file */
if (rmdir(location) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not remove junction dir \"%s\": %m",
location)));
#endif
{
if (errno != ENOENT)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not unlink file \"%s\": %m",
subfile)));
}
pfree(subfile);
pfree(location);
/*
* We have successfully destroyed the infrastructure ... there is now
* no way to roll back the DROP ... so proceed to remove the
* pg_tablespace tuple.
* Okay, try to remove the symlink. We must however deal with the
* possibility that it's a directory instead of a symlink --- this
* could happen during WAL replay (see TablespaceCreateDbspace),
* and it is also the normal case on Windows.
*/
simple_heap_delete(rel, &tuple->t_self);
if (lstat(location, &st) == 0 && S_ISDIR(st.st_mode))
{
if (rmdir(location) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not remove directory \"%s\": %m",
location)));
}
else
{
if (unlink(location) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not unlink symbolic link \"%s\": %m",
location)));
}
heap_endscan(scandesc);
pfree(location);
heap_close(rel, ExclusiveLock);
#else /* !HAVE_SYMLINK */
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("tablespaces are not supported on this platform")));
#endif /* HAVE_SYMLINK */
return true;
}
/*
* write out the PG_VERSION file in the specified directory
*/
@ -843,3 +943,88 @@ AlterTableSpaceOwner(const char *name, AclId newOwnerSysId)
heap_endscan(scandesc);
heap_close(rel, NoLock);
}
/*
* TABLESPACE resource manager's routines
*/
void
tblspc_redo(XLogRecPtr lsn, XLogRecord *record)
{
uint8 info = record->xl_info & ~XLR_INFO_MASK;
if (info == XLOG_TBLSPC_CREATE)
{
xl_tblspc_create_rec *xlrec = (xl_tblspc_create_rec *) XLogRecGetData(record);
char *location = xlrec->ts_path;
char *linkloc;
/*
* Attempt to coerce target directory to safe permissions. If this
* fails, it doesn't exist or has the wrong owner.
*/
if (chmod(location, 0700) != 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not set permissions on directory \"%s\": %m",
location)));
/* Create or re-create the PG_VERSION file in the target directory */
set_short_version(location);
/* Create the symlink if not already present */
linkloc = (char *) palloc(strlen(DataDir) + 11 + 10 + 1);
sprintf(linkloc, "%s/pg_tblspc/%u", DataDir, xlrec->ts_id);
if (symlink(location, linkloc) < 0)
{
if (errno != EEXIST)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create symbolic link \"%s\": %m",
linkloc)));
}
pfree(linkloc);
}
else if (info == XLOG_TBLSPC_DROP)
{
xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) XLogRecGetData(record);
if (!remove_tablespace_directories(xlrec->ts_id, true))
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("tablespace %u is not empty",
xlrec->ts_id)));
}
else
elog(PANIC, "tblspc_redo: unknown op code %u", info);
}
void
tblspc_undo(XLogRecPtr lsn, XLogRecord *record)
{
elog(PANIC, "tblspc_undo: unimplemented");
}
void
tblspc_desc(char *buf, uint8 xl_info, char *rec)
{
uint8 info = xl_info & ~XLR_INFO_MASK;
if (info == XLOG_TBLSPC_CREATE)
{
xl_tblspc_create_rec *xlrec = (xl_tblspc_create_rec *) rec;
sprintf(buf + strlen(buf), "create ts: %u \"%s\"",
xlrec->ts_id, xlrec->ts_path);
}
else if (info == XLOG_TBLSPC_DROP)
{
xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) rec;
sprintf(buf + strlen(buf), "drop ts: %u",
xlrec->ts_id);
}
else
strcat(buf, "UNKNOWN");
}

View File

@ -3,7 +3,7 @@
*
* Resource managers definition
*
* $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.12 2004/08/23 23:22:45 tgl Exp $
* $PostgreSQL: pgsql/src/include/access/rmgr.h,v 1.13 2004/08/29 21:08:47 tgl Exp $
*/
#ifndef RMGR_H
#define RMGR_H
@ -17,6 +17,8 @@ typedef uint8 RmgrId;
#define RM_XACT_ID 1
#define RM_SMGR_ID 2
#define RM_CLOG_ID 3
#define RM_DBASE_ID 4
#define RM_TBLSPC_ID 5
#define RM_HEAP_ID 10
#define RM_BTREE_ID 11
#define RM_HASH_ID 12

View File

@ -1,21 +1,41 @@
/*-------------------------------------------------------------------------
*
* dbcommands.h
*
* Database management commands (create/drop database).
*
*
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/commands/dbcommands.h,v 1.33 2004/08/29 04:13:05 momjian Exp $
* $PostgreSQL: pgsql/src/include/commands/dbcommands.h,v 1.34 2004/08/29 21:08:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef DBCOMMANDS_H
#define DBCOMMANDS_H
#include "access/xlog.h"
#include "nodes/parsenodes.h"
/* XLOG stuff */
#define XLOG_DBASE_CREATE 0x00
#define XLOG_DBASE_DROP 0x10
typedef struct xl_dbase_create_rec
{
/* Records copying of a single subdirectory incl. contents */
Oid db_id;
char src_path[1]; /* VARIABLE LENGTH STRING */
/* dst_path follows src_path */
} xl_dbase_create_rec;
typedef struct xl_dbase_drop_rec
{
/* Records dropping of a single subdirectory incl. contents */
Oid db_id;
char dir_path[1]; /* VARIABLE LENGTH STRING */
} xl_dbase_drop_rec;
extern void createdb(const CreatedbStmt *stmt);
extern void dropdb(const char *dbname);
extern void RenameDatabase(const char *oldname, const char *newname);
@ -25,4 +45,8 @@ extern void AlterDatabaseOwner(const char *dbname, AclId newOwnerSysId);
extern Oid get_database_oid(const char *dbname);
extern char *get_database_name(Oid dbid);
extern void dbase_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void dbase_undo(XLogRecPtr lsn, XLogRecord *rptr);
extern void dbase_desc(char *buf, uint8 xl_info, char *rec);
#endif /* DBCOMMANDS_H */

View File

@ -1,32 +1,49 @@
/*-------------------------------------------------------------------------
*
* tablespace.h
* prototypes for tablespace.c.
* Tablespace management commands (create/drop tablespace).
*
*
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.3 2004/07/11 19:52:52 tgl Exp $
* $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.4 2004/08/29 21:08:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef TABLESPACE_H
#define TABLESPACE_H
#include "access/xlog.h"
#include "nodes/parsenodes.h"
extern void CreateTableSpace(CreateTableSpaceStmt *stmt);
/* XLOG stuff */
#define XLOG_TBLSPC_CREATE 0x00
#define XLOG_TBLSPC_DROP 0x10
typedef struct xl_tblspc_create_rec
{
Oid ts_id;
char ts_path[1]; /* VARIABLE LENGTH STRING */
} xl_tblspc_create_rec;
typedef struct xl_tblspc_drop_rec
{
Oid ts_id;
} xl_tblspc_drop_rec;
extern void CreateTableSpace(CreateTableSpaceStmt *stmt);
extern void DropTableSpace(DropTableSpaceStmt *stmt);
extern void RenameTableSpace(const char *oldname, const char *newname);
extern void AlterTableSpaceOwner(const char *name, AclId newOwnerSysId);
extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
extern Oid get_tablespace_oid(const char *tablespacename);
extern char *get_tablespace_name(Oid spc_oid);
extern void RenameTableSpace(const char *oldname, const char *newname);
extern void AlterTableSpaceOwner(const char *name, AclId newOwnerSysId);
extern void tblspc_redo(XLogRecPtr lsn, XLogRecord *rptr);
extern void tblspc_undo(XLogRecPtr lsn, XLogRecord *rptr);
extern void tblspc_desc(char *buf, uint8 xl_info, char *rec);
#endif /* TABLESPACE_H */

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/port.h,v 1.56 2004/08/29 05:06:55 momjian Exp $
* $PostgreSQL: pgsql/src/include/port.h,v 1.57 2004/08/29 21:08:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -51,6 +51,7 @@ extern void get_pkglib_path(const char *my_exec_path, char *ret_path);
extern void get_locale_path(const char *my_exec_path, char *ret_path);
extern void set_pglocale_pgservice(const char *argv0, const char *app);
extern bool get_home_path(char *ret_path);
extern void get_parent_directory(char *path);
/*
* is_absolute_path

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/port/path.c,v 1.33 2004/08/29 05:07:02 momjian Exp $
* $PostgreSQL: pgsql/src/port/path.c,v 1.34 2004/08/29 21:08:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -324,6 +324,39 @@ get_locale_path(const char *my_exec_path, char *ret_path)
}
/*
* get_home_path
*/
bool
get_home_path(char *ret_path)
{
if (getenv(HOMEDIR) == NULL)
{
*ret_path = '\0';
return false;
}
else
{
StrNCpy(ret_path, getenv(HOMEDIR), MAXPGPATH);
canonicalize_path(ret_path);
return true;
}
}
/*
* get_parent_directory
*
* Modify the given string in-place to name the parent directory of the
* named file.
*/
void
get_parent_directory(char *path)
{
trim_directory(path);
trim_trailing_separator(path);
}
/*
* set_pglocale_pgservice
@ -373,27 +406,6 @@ set_pglocale_pgservice(const char *argv0, const char *app)
}
/*
* get_include_path
*/
bool
get_home_path(char *ret_path)
{
if (getenv(HOMEDIR) == NULL)
{
*ret_path = '\0';
return false;
}
else
{
StrNCpy(ret_path, getenv(HOMEDIR), MAXPGPATH);
canonicalize_path(ret_path);
return true;
}
}
/*
* make_relative - adjust path to be relative to bin/
*/