03-modify-tools_v2.patch
application/octet-stream
Filename: 03-modify-tools_v2.patch
Type: application/octet-stream
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| contrib/pg_standby/pg_standby.c | 74 | 11 |
| src/backend/access/transam/xlog.c | 2 | 0 |
| src/bin/pg_basebackup/pg_basebackup.c | 4 | 0 |
| src/bin/pg_basebackup/pg_receivewal.c | 6 | 2 |
| src/bin/pg_basebackup/receivelog.c | 5 | 5 |
| src/bin/pg_basebackup/streamutil.c | 80 | 0 |
| src/bin/pg_basebackup/streamutil.h | 1 | 0 |
| src/bin/pg_controldata/pg_controldata.c | 9 | 0 |
| src/bin/pg_resetwal/pg_resetwal.c | 27 | 9 |
| src/bin/pg_rewind/pg_rewind.c | 7 | 0 |
| src/bin/pg_waldump/pg_waldump.c | 152 | 56 |
| src/include/access/xlog_internal.h | 15 | 3 |
diff --git a/contrib/pg_standby/pg_standby.c b/contrib/pg_standby/pg_standby.c
index d7fa2a8..279728d 100644
--- a/contrib/pg_standby/pg_standby.c
+++ b/contrib/pg_standby/pg_standby.c
@@ -33,9 +33,12 @@
#include "pg_getopt.h"
#include "access/xlog_internal.h"
+#include "access/xlogreader.h"
const char *progname;
+uint32 XLogSegSize;
+
/* Options and defaults */
int sleeptime = 5; /* amount of time to sleep between file checks */
int waittime = -1; /* how long we have been waiting, -1 no wait
@@ -100,6 +103,72 @@ int nextWALFileType;
struct stat stat_buf;
+static bool SetWALFileNameForCleanup(void);
+
+/* Set XLogSegSize from the WAL file specified by WALFilePath */
+static bool
+RetrieveXLogSegSize()
+{
+ bool ret_val = false;
+ int fd;
+ char *buf = (char *) malloc(XLOG_BLCKSZ);
+
+ /* Already set a valid XLogSegSize? */
+ if (IsValidXLogSegSize(XLogSegSize))
+ return true;
+
+ if ((fd = open(WALFilePath, O_RDWR, 0)) < 0)
+ {
+ fprintf(stderr, "%s: couldn't open WAL file \"%s\"\n",
+ progname, WALFilePath);
+ return false;
+ }
+ if (read(fd, buf, XLOG_BLCKSZ) == XLOG_BLCKSZ)
+ {
+ XLogPageHeader hdr = (XLogPageHeader) buf;
+ XLogLongPageHeader longhdr = (XLogLongPageHeader) hdr;
+
+ XLogSegSize = longhdr->xlp_seg_size;
+
+ if (IsValidXLogSegSize(XLogSegSize))
+ {
+ /* successfully retrieved WAL segment size */
+ ret_val = true;
+
+ /* check if clean up is necessary */
+ need_cleanup = SetWALFileNameForCleanup();
+ if (debug)
+ {
+ fprintf(stderr,
+ _("WAL segment size: %d \n"), XLogSegSize);
+ fprintf(stderr, "Keep archive history: ");
+
+ if (need_cleanup)
+ fprintf(stderr, "%s and later\n",
+ exclusiveCleanupFileName);
+ else
+ fprintf(stderr, "no cleanup required\n");
+ }
+ }
+ else
+ fprintf(stderr,
+ "%s: WAL segment size must be a power of two between 1MB and 1GB, but the WAL file header specifies %d bytes\n",
+ progname, XLogSegSize);
+ close(fd);
+ }
+ else
+ {
+ if (errno != 0)
+ fprintf(stderr, "could not read file \"%s\": %s",
+ WALFilePath, strerror(errno));
+ else
+ fprintf(stderr, "not enough data in file \"%s\"", WALFilePath);
+ }
+
+ fflush(stderr);
+ return ret_val;
+}
+
/* =====================================================================
*
* Customizable section
@@ -184,7 +253,9 @@ CustomizableNextWALFileReady(void)
nextWALFileType = XLOG_BACKUP_LABEL;
return true;
}
- else if (stat_buf.st_size == XLOG_SEG_SIZE)
+ else if (!RetrieveXLogSegSize())
+ return false;
+ else if (stat_buf.st_size == XLogSegSize)
{
#ifdef WIN32
@@ -204,7 +275,7 @@ CustomizableNextWALFileReady(void)
/*
* If still too small, wait until it is the correct size
*/
- if (stat_buf.st_size > XLOG_SEG_SIZE)
+ if (stat_buf.st_size > XLogSegSize)
{
if (debug)
{
@@ -218,8 +289,6 @@ CustomizableNextWALFileReady(void)
return false;
}
-#define MaxSegmentsPerLogFile ( 0xFFFFFFFF / XLOG_SEG_SIZE )
-
static void
CustomizableCleanupPriorWALFiles(void)
{
@@ -315,6 +384,7 @@ SetWALFileNameForCleanup(void)
uint32 log_diff = 0,
seg_diff = 0;
bool cleanup = false;
+ int MaxSegmentsPerLogFile = (0xFFFFFFFF / XLogSegSize);
if (restartWALFileName)
{
@@ -708,8 +778,6 @@ main(int argc, char **argv)
CustomizableInitialize();
- need_cleanup = SetWALFileNameForCleanup();
-
if (debug)
{
fprintf(stderr, "Trigger file: %s\n", triggerPath ? triggerPath : "<not set>");
@@ -721,11 +789,6 @@ main(int argc, char **argv)
fprintf(stderr, "Max wait interval: %d %s\n",
maxwaittime, (maxwaittime > 0 ? "seconds" : "forever"));
fprintf(stderr, "Command for restore: %s\n", restoreCommand);
- fprintf(stderr, "Keep archive history: ");
- if (need_cleanup)
- fprintf(stderr, "%s and later\n", exclusiveCleanupFileName);
- else
- fprintf(stderr, "no cleanup required\n");
fflush(stderr);
}
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index ef0ec72..a13e836 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -110,6 +110,8 @@ int wal_retrieve_retry_interval = 5000;
bool XLOG_DEBUG = false;
#endif
+uint32 XLogSegSize = XLOG_SEG_SIZE;
+
/*
* Number of WAL insertion locks to use. A higher value allows more insertions
* to happen concurrently, but adds some CPU overhead to flushing the WAL,
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index be754a5..a7920bc 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -2394,6 +2394,10 @@ main(int argc, char **argv)
exit(1);
}
+ /* determine remote server's xlog segment size */
+ if (!RetrieveXLogSegSize(conn))
+ disconnect_and_exit(1);
+
/* Create pg_wal symlink, if required */
if (strcmp(xlog_dir, "") != 0)
{
diff --git a/src/bin/pg_basebackup/pg_receivewal.c b/src/bin/pg_basebackup/pg_receivewal.c
index 144823d..0e713c8 100644
--- a/src/bin/pg_basebackup/pg_receivewal.c
+++ b/src/bin/pg_basebackup/pg_receivewal.c
@@ -254,7 +254,7 @@ FindStreamingStart(uint32 *tli)
disconnect_and_exit(1);
}
- if (statbuf.st_size != XLOG_SEG_SIZE)
+ if (statbuf.st_size != XLogSegSize)
{
fprintf(stderr,
_("%s: segment file \"%s\" has incorrect size %d, skipping\n"),
@@ -295,7 +295,7 @@ FindStreamingStart(uint32 *tli)
bytes_out = (buf[3] << 24) | (buf[2] << 16) |
(buf[1] << 8) | buf[0];
- if (bytes_out != XLOG_SEG_SIZE)
+ if (bytes_out != XLogSegSize)
{
fprintf(stderr,
_("%s: compressed segment file \"%s\" has incorrect uncompressed size %d, skipping\n"),
@@ -664,6 +664,10 @@ main(int argc, char **argv)
if (!RunIdentifySystem(conn, NULL, NULL, NULL, &db_name))
disconnect_and_exit(1);
+ /* determine remote server's xlog segment size */
+ if (!RetrieveXLogSegSize(conn))
+ disconnect_and_exit(1);
+
/*
* Check that there is a database associated with connection, none should
* be defined in this context.
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index 7b842a5..1bf234f 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -201,7 +201,7 @@ close_walfile(StreamCtl *stream, XLogRecPtr pos)
if (stream->partial_suffix)
{
- if (currpos == XLOG_SEG_SIZE)
+ if (currpos == XLogSegSize)
r = stream->walmethod->close(walfile, CLOSE_NORMAL);
else
{
@@ -229,7 +229,7 @@ close_walfile(StreamCtl *stream, XLogRecPtr pos)
* new node. This is in line with walreceiver.c always doing a
* XLogArchiveForceDone() after a complete segment.
*/
- if (currpos == XLOG_SEG_SIZE && stream->mark_done)
+ if (currpos == XLogSegSize && stream->mark_done)
{
/* writes error message if failed */
if (!mark_file_as_archived(stream, current_walfile_name))
@@ -1147,10 +1147,10 @@ ProcessXLogDataMsg(PGconn *conn, StreamCtl *stream, char *copybuf, int len,
/*
* If crossing a WAL boundary, only write up until we reach
- * XLOG_SEG_SIZE.
+ * XLogSegSize.
*/
- if (xlogoff + bytes_left > XLOG_SEG_SIZE)
- bytes_to_write = XLOG_SEG_SIZE - xlogoff;
+ if (xlogoff + bytes_left > XLogSegSize)
+ bytes_to_write = XLogSegSize - xlogoff;
else
bytes_to_write = bytes_left;
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index d7ba7e2..85213ee 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -24,12 +24,18 @@
#include "receivelog.h"
#include "streamutil.h"
+#include "access/xlog_internal.h"
#include "pqexpbuffer.h"
#include "common/fe_memutils.h"
#include "datatype/timestamp.h"
#define ERRCODE_DUPLICATE_OBJECT "42710"
+uint32 XLogSegSize;
+
+/* SHOW command for replication connection was introduced in version 10 */
+#define MINIMUM_VERSION_FOR_SHOW_CMD 100000
+
const char *progname;
char *connection_string = NULL;
char *dbhost = NULL;
@@ -231,6 +237,80 @@ GetConnection(void)
}
/*
+ * From version 10, explicitly set XLogSegSize using SHOW wal_segment_size
+ * since ControlFile is not accessible here.
+ */
+bool
+RetrieveXLogSegSize(PGconn *conn)
+{
+ PGresult *res;
+ char *tmp_result;
+ char xlog_unit[3];
+ int xlog_val,
+ multiplier = 1;
+
+ /* check connection existence */
+ Assert(conn != NULL);
+
+ /* for previous versions set the default xlog seg size */
+ if (PQserverVersion(conn) < MINIMUM_VERSION_FOR_SHOW_CMD)
+ {
+ XLogSegSize = XLOG_SEG_SIZE;
+ return true;
+ }
+
+ res = PQexec(conn, "SHOW wal_segment_size");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ {
+ fprintf(stderr, _("%s: could not send replication command \"%s\": %s\n"),
+ progname, "SHOW wal_segment_size", PQerrorMessage(conn));
+
+ PQclear(res);
+ return false;
+ }
+ if (PQntuples(res) != 1 || PQnfields(res) < 1)
+ {
+ fprintf(stderr,
+ _("%s: could not fetch WAL segment size: got %d rows and %d fields, expected %d rows and %d or more fields\n"),
+ progname, PQntuples(res), PQnfields(res), 1, 1);
+
+ PQclear(res);
+ return false;
+ }
+
+ /* wal_segment_size ranges from 1MB to 1GB */
+ tmp_result = pg_strdup(PQgetvalue(res, 0, 0));
+
+ /* fetch xlog value and unit from the result */
+ if (sscanf(tmp_result, "%d%s", &xlog_val, xlog_unit) != 2)
+ {
+ fprintf(stderr, _("%s: WAL segment size could not be parsed\n"),
+ progname);
+ return false;
+ }
+
+ /* set the multiplier based on unit to convert XLogSegSize to bytes */
+ if (strcmp(xlog_unit, "MB") == 0)
+ multiplier = 1024 * 1024;
+ else if (strcmp(xlog_unit, "GB") == 0)
+ multiplier = 1024 * 1024 * 1024;
+
+ /* convert and set XLogSegSize */
+ XLogSegSize = xlog_val * multiplier;
+
+ if (!IsValidXLogSegSize(XLogSegSize))
+ {
+ fprintf(stderr,
+ _("%s: WAL segment size must be a power of two between 1MB and 1GB, but the remote server reported a value of %d bytes\n"),
+ progname, XLogSegSize);
+ return false;
+ }
+
+ PQclear(res);
+ return true;
+}
+
+/*
* Run IDENTIFY_SYSTEM through a given connection and give back to caller
* some result information if requested:
* - System identifier
diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h
index 6f68786..6fb85ba 100644
--- a/src/bin/pg_basebackup/streamutil.h
+++ b/src/bin/pg_basebackup/streamutil.h
@@ -39,6 +39,7 @@ extern bool RunIdentifySystem(PGconn *conn, char **sysid,
TimeLineID *starttli,
XLogRecPtr *startpos,
char **db_name);
+extern bool RetrieveXLogSegSize(PGconn *conn);
extern TimestampTz feGetCurrentTimestamp(void);
extern void feTimestampDifference(TimestampTz start_time, TimestampTz stop_time,
long *secs, int *microsecs);
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index 2ea8931..288860a 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -26,6 +26,7 @@
#include "common/controldata_utils.h"
#include "pg_getopt.h"
+uint32 XLogSegSize;
static void
usage(const char *progname)
@@ -164,6 +165,14 @@ main(int argc, char *argv[])
"Either the file is corrupt, or it has a different layout than this program\n"
"is expecting. The results below are untrustworthy.\n\n"));
+ /* set XLogSegSize */
+ XLogSegSize = ControlFile->xlog_seg_size;
+
+ if (!IsValidXLogSegSize(XLogSegSize))
+ fprintf(stderr,
+ _("WARNING: WAL segment size specified, %d bytes, is not a power of two between 1MB and 1GB. The file is corrupt and the results below are untrustworthy."),
+ XLogSegSize);
+
/*
* This slightly-chintzy coding will work as long as the control file
* timestamps are within the range of time_t; that should be the case in
diff --git a/src/bin/pg_resetwal/pg_resetwal.c b/src/bin/pg_resetwal/pg_resetwal.c
index d4dd1d4..28be212 100644
--- a/src/bin/pg_resetwal/pg_resetwal.c
+++ b/src/bin/pg_resetwal/pg_resetwal.c
@@ -56,6 +56,7 @@
#include "storage/large_object.h"
#include "pg_getopt.h"
+uint32 XLogSegSize;
static ControlFileData ControlFile; /* pg_control values */
static XLogSegNo newXlogSegNo; /* new XLOG segment # */
@@ -94,6 +95,7 @@ main(int argc, char *argv[])
char *endptr;
char *endptr2;
char *DataDir = NULL;
+ char *log_fname = NULL;
int fd;
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_resetwal"));
@@ -265,7 +267,12 @@ main(int argc, char *argv[])
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit(1);
}
- XLogFromFileName(optarg, &minXlogTli, &minXlogSegNo);
+
+ /*
+ * XLogFromFileName requires XLogSegSize which is not yet
+ * set. Hence XLog details are set later on.
+ */
+ log_fname = pg_strdup(optarg);
break;
default:
@@ -350,6 +357,9 @@ main(int argc, char *argv[])
if (!ReadControlFile())
GuessControlValues();
+ if (log_fname != NULL)
+ XLogFromFileName(log_fname, &minXlogTli, &minXlogSegNo);
+
/*
* Also look at existing segment files to set up newXlogSegNo
*/
@@ -573,18 +583,26 @@ ReadControlFile(void)
offsetof(ControlFileData, crc));
FIN_CRC32C(crc);
- if (EQ_CRC32C(crc, ((ControlFileData *) buffer)->crc))
+ if (!EQ_CRC32C(crc, ((ControlFileData *) buffer)->crc))
{
- /* Valid data... */
- memcpy(&ControlFile, buffer, sizeof(ControlFile));
- return true;
+ /* We will use the data but treat it as guessed. */
+ fprintf(stderr, _("%s: pg_control exists but has invalid CRC; proceed with caution\n"),
+ progname);
+ guessed = true;
}
- fprintf(stderr, _("%s: pg_control exists but has invalid CRC; proceed with caution\n"),
- progname);
- /* We will use the data anyway, but treat it as guessed. */
memcpy(&ControlFile, buffer, sizeof(ControlFile));
- guessed = true;
+ XLogSegSize = ControlFile.xlog_seg_size;
+
+ /* return false if XLogSegSize is not valid */
+ if (!IsValidXLogSegSize(XLogSegSize))
+ {
+ fprintf(stderr,
+ _("%s: WAL segment size must be a power of two between 1MB and 1GB; ignoring control file specifying %d bytes\n"),
+ progname, XLogSegSize);
+ return false;
+ }
+
return true;
}
diff --git a/src/bin/pg_rewind/pg_rewind.c b/src/bin/pg_rewind/pg_rewind.c
index 6c75b56..a1b2107 100644
--- a/src/bin/pg_rewind/pg_rewind.c
+++ b/src/bin/pg_rewind/pg_rewind.c
@@ -44,6 +44,7 @@ static ControlFileData ControlFile_target;
static ControlFileData ControlFile_source;
const char *progname;
+uint32 XLogSegSize;
/* Configuration options */
char *datadir_target = NULL;
@@ -631,6 +632,12 @@ digestControlFile(ControlFileData *ControlFile, char *src, size_t size)
memcpy(ControlFile, src, sizeof(ControlFileData));
+ /* set and validate XLogSegSize */
+ XLogSegSize = ControlFile->xlog_seg_size;
+
+ if (!IsValidXLogSegSize(XLogSegSize))
+ pg_fatal("WAL segment size must be a power of two between 1MB and 1GB, but the control file specifies %d bytes\n", XLogSegSize);
+
/* Additional checks on control file */
checkControlFile(ControlFile);
}
diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c
index ed73ffe..36db1f6 100644
--- a/src/bin/pg_waldump/pg_waldump.c
+++ b/src/bin/pg_waldump/pg_waldump.c
@@ -22,10 +22,13 @@
#include "common/fe_memutils.h"
#include "getopt_long.h"
#include "rmgrdesc.h"
+#include "sys/stat.h"
static const char *progname;
+uint32 XLogSegSize;
+
typedef struct XLogDumpPrivate
{
TimeLineID timeline;
@@ -144,77 +147,167 @@ split_path(const char *path, char **dir, char **fname)
}
/*
- * Try to find the file in several places:
- * if directory == NULL:
- * fname
- * XLOGDIR / fname
- * $PGDATA / XLOGDIR / fname
- * else
- * directory / fname
- * directory / XLOGDIR / fname
+ * Open the file in the valid target directory.
*
* return a read only fd
*/
static int
-fuzzy_open_file(const char *directory, const char *fname)
+open_file_in_directory(const char *directory, const char *fname)
{
int fd = -1;
char fpath[MAXPGPATH];
- if (directory == NULL)
+ Assert(directory != NULL);
+
+ snprintf(fpath, MAXPGPATH, "%s/%s", directory, fname);
+ fd = open(fpath, O_RDONLY | PG_BINARY, 0);
+
+ if (fd < 0 && errno != ENOENT)
+ fatal_error("could not open file \"%s\": %s",
+ fname, strerror(errno));
+ return fd;
+}
+
+/*
+ * Try to find fname in the given directory. Returns true if it is found,
+ * false otherwise. If fname is NULL, search the complete directory for any
+ * file with a valid WAL file name.
+ */
+static bool
+search_directory(char *directory, char *fname)
+{
+ int fd = -1;
+ DIR *xldir;
+
+ /* open file if valid filename is provided */
+ if (fname != NULL)
+ fd = open_file_in_directory(directory, fname);
+
+ /*
+ * A valid file name is not passed so search the complete directory. If
+ * we find any file whose name is like a valid WAL file name then try to
+ * open it. If we can not open it then bail out.
+ */
+ else if ((xldir = opendir(directory)) != NULL)
+ {
+ struct dirent *xlde;
+
+ while ((xlde = readdir(xldir)) != NULL)
+ {
+ if (IsXLogFileName(xlde->d_name))
+ {
+ fd = open_file_in_directory(directory, xlde->d_name);
+ fname = xlde->d_name;
+ break;
+ }
+ }
+
+ closedir(xldir);
+ }
+
+ /* set XLogSegSize if file is successfully opened */
+ if (fd >= 0)
+ {
+ char *buf = (char *) malloc(XLOG_BLCKSZ);
+
+ if (read(fd, buf, XLOG_BLCKSZ) == XLOG_BLCKSZ)
+ {
+ XLogPageHeader hdr = (XLogPageHeader) buf;
+ XLogLongPageHeader longhdr = (XLogLongPageHeader) hdr;
+
+ XLogSegSize = longhdr->xlp_seg_size;
+
+ if (!IsValidXLogSegSize(XLogSegSize))
+ fatal_error("WAL segment size must be a power of two between 1MB and 1GB, but the WAL file \"%s\" header specifies %d bytes",
+ fname, XLogSegSize);
+ }
+ else
+ {
+ if (errno != 0)
+ fatal_error("could not read file \"%s\": %s",
+ fname, strerror(errno));
+ else
+ fatal_error("not enough data in file \"%s\"", fname);
+ }
+ free(buf);
+ close(fd);
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Identify the target directory and set XLogSegSize.
+ *
+ * Try to find the file in several places:
+ * if directory != NULL:
+ * directory /
+ * directory / XLOGDIR /
+ * else
+ * .
+ * XLOGDIR /
+ * $PGDATA / XLOGDIR /
+ *
+ * Set the valid target directory in private->inpath.
+ */
+static void
+identify_target_directory(XLogDumpPrivate *private, char *directory,
+ char *fname)
+{
+ char fpath[MAXPGPATH];
+
+ if (directory != NULL)
+ {
+ if (search_directory(directory, fname))
+ {
+ private->inpath = strdup(directory);
+ return;
+ }
+
+ /* directory / XLOGDIR */
+ snprintf(fpath, MAXPGPATH, "%s/%s", directory, XLOGDIR);
+ if (search_directory(fpath, fname))
+ {
+ private->inpath = strdup(fpath);
+ return;
+ }
+ }
+ else
{
const char *datadir;
- /* fname */
- fd = open(fname, O_RDONLY | PG_BINARY, 0);
- if (fd < 0 && errno != ENOENT)
- return -1;
- else if (fd >= 0)
- return fd;
-
- /* XLOGDIR / fname */
- snprintf(fpath, MAXPGPATH, "%s/%s",
- XLOGDIR, fname);
- fd = open(fpath, O_RDONLY | PG_BINARY, 0);
- if (fd < 0 && errno != ENOENT)
- return -1;
- else if (fd >= 0)
- return fd;
+ /* current directory */
+ if (search_directory(".", fname))
+ {
+ private->inpath = strdup(".");
+ return;
+ }
+ /* XLOGDIR */
+ if (search_directory(XLOGDIR, fname))
+ {
+ private->inpath = strdup(XLOGDIR);
+ return;
+ }
datadir = getenv("PGDATA");
- /* $PGDATA / XLOGDIR / fname */
+ /* $PGDATA / XLOGDIR */
if (datadir != NULL)
{
- snprintf(fpath, MAXPGPATH, "%s/%s/%s",
- datadir, XLOGDIR, fname);
- fd = open(fpath, O_RDONLY | PG_BINARY, 0);
- if (fd < 0 && errno != ENOENT)
- return -1;
- else if (fd >= 0)
- return fd;
+ snprintf(fpath, MAXPGPATH, "%s/%s", datadir, XLOGDIR);
+ if (search_directory(fpath, fname))
+ {
+ private->inpath = strdup(fpath);
+ return;
+ }
}
}
+
+ /* could not locate WAL file */
+ if (fname)
+ fatal_error("could not locate WAL file \"%s\"", fname);
else
- {
- /* directory / fname */
- snprintf(fpath, MAXPGPATH, "%s/%s",
- directory, fname);
- fd = open(fpath, O_RDONLY | PG_BINARY, 0);
- if (fd < 0 && errno != ENOENT)
- return -1;
- else if (fd >= 0)
- return fd;
-
- /* directory / XLOGDIR / fname */
- snprintf(fpath, MAXPGPATH, "%s/%s/%s",
- directory, XLOGDIR, fname);
- fd = open(fpath, O_RDONLY | PG_BINARY, 0);
- if (fd < 0 && errno != ENOENT)
- return -1;
- else if (fd >= 0)
- return fd;
- }
- return -1;
+ fatal_error("could not find any WAL file");
}
/*
@@ -267,7 +360,7 @@ XLogDumpXLogRead(const char *directory, TimeLineID timeline_id,
*/
for (tries = 0; tries < 10; tries++)
{
- sendFile = fuzzy_open_file(directory, fname);
+ sendFile = open_file_in_directory(directory, fname);
if (sendFile >= 0)
break;
if (errno == ENOENT)
@@ -935,7 +1028,8 @@ main(int argc, char **argv)
private.inpath, strerror(errno));
}
- fd = fuzzy_open_file(private.inpath, fname);
+ identify_target_directory(&private, private.inpath, fname);
+ fd = open_file_in_directory(private.inpath, fname);
if (fd < 0)
fatal_error("could not open file \"%s\"", fname);
close(fd);
@@ -968,7 +1062,7 @@ main(int argc, char **argv)
/* ignore directory, already have that */
split_path(argv[optind + 1], &directory, &fname);
- fd = fuzzy_open_file(private.inpath, fname);
+ fd = open_file_in_directory(private.inpath, fname);
if (fd < 0)
fatal_error("could not open file \"%s\"", fname);
close(fd);
@@ -1000,6 +1094,8 @@ main(int argc, char **argv)
goto bad_argument;
}
}
+ else
+ identify_target_directory(&private, private.inpath, NULL);
/* we don't know what to print */
if (XLogRecPtrIsInvalid(private.startptr))
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 3fee2ee..9c0039c 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -89,11 +89,23 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
* The XLOG is split into WAL segments (physical files) of the size indicated
* by XLOG_SEG_SIZE.
*/
-#define XLogSegSize ((uint32) XLOG_SEG_SIZE)
-#define XLogSegmentsPerXLogId (UINT64CONST(0x100000000) / XLOG_SEG_SIZE)
+
+extern uint32 XLogSegSize;
+
+/* XLogSegSize can range from 1MB to 1GB */
+#define XLogSegMinSize 1024 * 1024
+#define XLogSegMaxSize 1024 * 1024 * 1024
+
+/* check that the given size is a valid XLogSegSize */
+#define IsPowerOf2(x) (((x) & ((x)-1)) == 0)
+#define IsValidXLogSegSize(size) \
+ (IsPowerOf2(size) && \
+ (size >= XLogSegMinSize && size <= XLogSegMaxSize))
+
+#define XLogSegmentsPerXLogId (UINT64CONST(0x100000000) / XLogSegSize)
#define XLogSegNoOffsetToRecPtr(segno, offset, dest) \
- (dest) = (segno) * XLOG_SEG_SIZE + (offset)
+ (dest) = (segno) * XLogSegSize + (offset)
#define XLogSegmentOffset(xlogptr) \
((xlogptr) & (XLogSegSize - 1))