initdb-walsegsize-v2_WIP.patch
application/octet-stream
Filename: initdb-walsegsize-v2_WIP.patch
Type: application/octet-stream
Part: 0
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 | + | − |
|---|---|---|
| configure | 0 | 51 |
| configure.in | 0 | 27 |
| contrib/pg_standby/pg_standby.c | 17 | 17 |
| doc/src/sgml/installation.sgml | 0 | 14 |
| doc/src/sgml/wal.sgml | 1 | 1 |
| src/backend/access/transam/xlog.c | 130 | 38 |
| src/backend/access/transam/xlogfuncs.c | 1 | 1 |
| src/backend/access/transam/xlogutils.c | 1 | 1 |
| src/backend/postmaster/checkpointer.c | 1 | 1 |
| src/backend/replication/walreceiver.c | 1 | 1 |
| src/backend/replication/walreceiverfuncs.c | 2 | 2 |
| src/backend/replication/walsender.c | 1 | 1 |
| src/backend/utils/misc/guc.c | 10 | 23 |
| src/bin/initdb/initdb.c | 29 | 0 |
| src/bin/pg_basebackup/pg_basebackup.c | 3 | 0 |
| src/bin/pg_basebackup/receivelog.h | 2 | 0 |
| src/bin/pg_basebackup/streamutil.c | 53 | 0 |
| src/bin/pg_basebackup/streamutil.h | 1 | 0 |
| src/bin/pg_controldata/pg_controldata.c | 7 | 0 |
| src/bin/pg_resetxlog/pg_resetxlog.c | 13 | 1 |
| src/bin/pg_rewind/pg_rewind.c | 6 | 0 |
| src/bin/pg_test_fsync/pg_test_fsync.c | 3 | 3 |
| src/bin/pg_xlogdump/pg_xlogdump.c | 23 | 0 |
| src/include/access/xlog.h | 3 | 0 |
| src/include/access/xlog_internal.h | 16 | 1 |
| src/include/pg_config.h.in | 0 | 7 |
| src/include/pg_config_manual.h | 6 | 0 |
| src/include/utils/guc.h | 0 | 1 |
| src/tools/msvc/Solution.pm | 1 | 1 |
diff --git a/configure b/configure
index 9a83f19..1b43e8c 100755
--- a/configure
+++ b/configure
@@ -816,7 +816,6 @@ enable_tap_tests
with_blocksize
with_segsize
with_wal_blocksize
-with_wal_segsize
with_CC
enable_depend
enable_cassert
@@ -1508,8 +1507,6 @@ Optional Packages:
--with-segsize=SEGSIZE set table segment size in GB [1]
--with-wal-blocksize=BLOCKSIZE
set WAL block size in kB [8]
- --with-wal-segsize=SEGSIZE
- set WAL segment size in MB [16]
--with-CC=CMD set compiler (deprecated)
--with-tcl build Tcl modules (PL/Tcl)
--with-tclconfig=DIR tclConfig.sh is in DIR
@@ -3674,54 +3671,6 @@ cat >>confdefs.h <<_ACEOF
#define XLOG_BLCKSZ ${XLOG_BLCKSZ}
_ACEOF
-
-#
-# WAL segment size
-#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for WAL segment size" >&5
-$as_echo_n "checking for WAL segment size... " >&6; }
-
-
-
-# Check whether --with-wal-segsize was given.
-if test "${with_wal_segsize+set}" = set; then :
- withval=$with_wal_segsize;
- case $withval in
- yes)
- as_fn_error $? "argument required for --with-wal-segsize option" "$LINENO" 5
- ;;
- no)
- as_fn_error $? "argument required for --with-wal-segsize option" "$LINENO" 5
- ;;
- *)
- wal_segsize=$withval
- ;;
- esac
-
-else
- wal_segsize=16
-fi
-
-
-case ${wal_segsize} in
- 1) ;;
- 2) ;;
- 4) ;;
- 8) ;;
- 16) ;;
- 32) ;;
- 64) ;;
- *) as_fn_error $? "Invalid WAL segment size. Allowed values are 1,2,4,8,16,32,64." "$LINENO" 5
-esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${wal_segsize}MB" >&5
-$as_echo "${wal_segsize}MB" >&6; }
-
-
-cat >>confdefs.h <<_ACEOF
-#define XLOG_SEG_SIZE (${wal_segsize} * 1024 * 1024)
-_ACEOF
-
-
#
# C compiler
#
diff --git a/configure.in b/configure.in
index 52e4e78..4d6437c 100644
--- a/configure.in
+++ b/configure.in
@@ -344,33 +344,6 @@ AC_DEFINE_UNQUOTED([XLOG_BLCKSZ], ${XLOG_BLCKSZ}, [
])
#
-# WAL segment size
-#
-AC_MSG_CHECKING([for WAL segment size])
-PGAC_ARG_REQ(with, wal-segsize, [SEGSIZE], [set WAL segment size in MB [16]],
- [wal_segsize=$withval],
- [wal_segsize=16])
-case ${wal_segsize} in
- 1) ;;
- 2) ;;
- 4) ;;
- 8) ;;
- 16) ;;
- 32) ;;
- 64) ;;
- *) AC_MSG_ERROR([Invalid WAL segment size. Allowed values are 1,2,4,8,16,32,64.])
-esac
-AC_MSG_RESULT([${wal_segsize}MB])
-
-AC_DEFINE_UNQUOTED([XLOG_SEG_SIZE], [(${wal_segsize} * 1024 * 1024)], [
- XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2
- and larger than XLOG_BLCKSZ (preferably, a great deal larger than
- XLOG_BLCKSZ).
-
- Changing XLOG_SEG_SIZE requires an initdb.
-])
-
-#
# C compiler
#
diff --git a/contrib/pg_standby/pg_standby.c b/contrib/pg_standby/pg_standby.c
index e4136f9..269e6ec 100644
--- a/contrib/pg_standby/pg_standby.c
+++ b/contrib/pg_standby/pg_standby.c
@@ -36,6 +36,8 @@
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
@@ -177,15 +179,27 @@ CustomizableNextWALFileReady(void)
{
/*
* If it's a backup file, return immediately. If it's a regular file
- * return only if it's the right size already.
+ * check and verify the size
*/
if (IsBackupHistoryFileName(nextWALFileName))
{
nextWALFileType = XLOG_BACKUP_LABEL;
return true;
}
- else if (stat_buf.st_size == XLOG_SEG_SIZE)
+ else
{
+
+ if (!IsValidXLogSegSize(stat_buf.st_size))
+ {
+ fprintf(stderr,
+ _("%s: file size is invalid %d \n"),
+ progname, (int) stat_buf.st_size);
+
+ exit(0);
+ }
+
+ XLogSegSize = (int) stat_buf.st_size;
+
#ifdef WIN32
/*
@@ -200,26 +214,11 @@ CustomizableNextWALFileReady(void)
nextWALFileType = XLOG_DATA;
return true;
}
-
- /*
- * If still too small, wait until it is the correct size
- */
- if (stat_buf.st_size > XLOG_SEG_SIZE)
- {
- if (debug)
- {
- fprintf(stderr, "file size greater than expected\n");
- fflush(stderr);
- }
- exit(3);
- }
}
return false;
}
-#define MaxSegmentsPerLogFile ( 0xFFFFFFFF / XLOG_SEG_SIZE )
-
static void
CustomizableCleanupPriorWALFiles(void)
{
@@ -315,6 +314,7 @@ SetWALFileNameForCleanup(void)
uint32 log_diff = 0,
seg_diff = 0;
bool cleanup = false;
+ int MaxSegmentsPerLogFile = (0xFFFFFFFF / XLOG_SEG_SIZE);
if (restartWALFileName)
{
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 4431ed7..09ab77f 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -1053,20 +1053,6 @@ su - postgres
</varlistentry>
<varlistentry>
- <term><option>--with-wal-segsize=<replaceable>SEGSIZE</replaceable></option></term>
- <listitem>
- <para>
- Set the <firstterm>WAL segment size</>, in megabytes. This is
- the size of each individual file in the WAL log. It may be useful
- to adjust this size to control the granularity of WAL log shipping.
- The default size is 16 megabytes.
- The value must be a power of 2 between 1 and 64 (megabytes).
- Note that changing this value requires an initdb.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
<term><option>--with-wal-blocksize=<replaceable>BLOCKSIZE</replaceable></option></term>
<listitem>
<para>
diff --git a/doc/src/sgml/wal.sgml b/doc/src/sgml/wal.sgml
index 346aa76..7f95863 100644
--- a/doc/src/sgml/wal.sgml
+++ b/doc/src/sgml/wal.sgml
@@ -752,7 +752,7 @@
<acronym>WAL</acronym> logs are stored in the directory
<filename>pg_wal</filename> under the data directory, as a set of
segment files, normally each 16 MB in size (but the size can be changed
- by altering the <option>--with-wal-segsize</> configure option when
+ by altering the <option>--with-wal-segsize</> initdb option when
building the server). Each segment is divided into pages, normally
8 kB each (this size can be changed via the <option>--with-wal-blocksize</>
configure option). The log record headers are described in
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 2f5d603..6bd5964 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -84,6 +84,7 @@ extern uint32 bootstrap_data_checksum_version;
/* User-settable parameters */
+int wal_segment_size = 2048; /* 16 MB */
int max_wal_size = 64; /* 1 GB */
int min_wal_size = 5; /* 80 MB */
int wal_keep_segments = 0;
@@ -106,6 +107,24 @@ int wal_retrieve_retry_interval = 5000;
bool XLOG_DEBUG = false;
#endif
+uint32 XLogSegSize;
+
+/*
+ * These variables are set in assign_wal_segment_size
+ *
+ * WalModMask: It is an AND mask for XLogSegSize to allow for faster modulo
+ * operations using it.
+ *
+ * WalShiftBit: It is an shift bit for XLogSegSize to allow for faster
+ * division operations using it.
+ *
+ * UsableBytesInSegment: It is the number of bytes in a WAL segment usable for
+ * WAL data.
+ */
+uint32 WalModMask;
+static int UsableBytesInSegment;
+static int WalShiftBit;
+
/*
* 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,
@@ -719,10 +738,9 @@ static ControlFileData *ControlFile = NULL;
(((recptr) / XLOG_BLCKSZ) % (XLogCtl->XLogCacheBlck + 1))
/*
- * These are the number of bytes in a WAL page and segment usable for WAL data.
+ * These are the number of bytes in a WAL page usable for WAL data.
*/
#define UsableBytesInPage (XLOG_BLCKSZ - SizeOfXLogShortPHD)
-#define UsableBytesInSegment ((XLOG_SEG_SIZE / XLOG_BLCKSZ) * UsableBytesInPage - (SizeOfXLogLongPHD - SizeOfXLogShortPHD))
/*
* Private, possibly out-of-date copy of shared LogwrtResult.
@@ -957,6 +975,7 @@ XLogInsertRecord(XLogRecData *rdata,
if (!XLogInsertAllowed())
elog(ERROR, "cannot make new WAL entries during recovery");
+
/*----------
*
* We have now done all the preparatory work we can without holding a
@@ -1120,7 +1139,7 @@ XLogInsertRecord(XLogRecData *rdata,
EndPos = StartPos + SizeOfXLogRecord;
if (StartPos / XLOG_BLCKSZ != EndPos / XLOG_BLCKSZ)
{
- if (EndPos % XLOG_SEG_SIZE == EndPos % XLOG_BLCKSZ)
+ if ((EndPos & WalModMask) == EndPos % XLOG_BLCKSZ)
EndPos += SizeOfXLogLongPHD;
else
EndPos += SizeOfXLogShortPHD;
@@ -1279,7 +1298,7 @@ ReserveXLogSwitch(XLogRecPtr *StartPos, XLogRecPtr *EndPos, XLogRecPtr *PrevPtr)
startbytepos = Insert->CurrBytePos;
ptr = XLogBytePosToEndRecPtr(startbytepos);
- if (ptr % XLOG_SEG_SIZE == 0)
+ if ((ptr & WalModMask) == 0)
{
SpinLockRelease(&Insert->insertpos_lck);
*EndPos = *StartPos = ptr;
@@ -1292,7 +1311,7 @@ ReserveXLogSwitch(XLogRecPtr *StartPos, XLogRecPtr *EndPos, XLogRecPtr *PrevPtr)
*StartPos = XLogBytePosToRecPtr(startbytepos);
*EndPos = XLogBytePosToEndRecPtr(endbytepos);
- segleft = XLOG_SEG_SIZE - ((*EndPos) % XLOG_SEG_SIZE);
+ segleft = XLOG_SEG_SIZE - ((*EndPos) & WalModMask);
if (segleft != XLOG_SEG_SIZE)
{
/* consume the rest of the segment */
@@ -1306,7 +1325,7 @@ ReserveXLogSwitch(XLogRecPtr *StartPos, XLogRecPtr *EndPos, XLogRecPtr *PrevPtr)
*PrevPtr = XLogBytePosToRecPtr(prevbytepos);
- Assert((*EndPos) % XLOG_SEG_SIZE == 0);
+ Assert(((*EndPos) & WalModMask) == 0);
Assert(XLogRecPtrToBytePos(*EndPos) == endbytepos);
Assert(XLogRecPtrToBytePos(*StartPos) == startbytepos);
Assert(XLogRecPtrToBytePos(*PrevPtr) == prevbytepos);
@@ -1376,7 +1395,7 @@ CopyXLogRecordToWAL(int write_len, bool isLogSwitch, XLogRecData *rdata,
pagehdr->xlp_info |= XLP_FIRST_IS_CONTRECORD;
/* skip over the page header */
- if (CurrPos % XLogSegSize == 0)
+ if ((CurrPos & WalModMask) == 0)
{
CurrPos += SizeOfXLogLongPHD;
currpos += SizeOfXLogLongPHD;
@@ -1407,7 +1426,7 @@ CopyXLogRecordToWAL(int write_len, bool isLogSwitch, XLogRecData *rdata,
* allocated and zeroed in the WAL buffers so that when the caller (or
* someone else) does XLogWrite(), it can really write out all the zeros.
*/
- if (isLogSwitch && CurrPos % XLOG_SEG_SIZE != 0)
+ if (isLogSwitch && (CurrPos & WalModMask) != 0)
{
/* An xlog-switch record doesn't contain any data besides the header */
Assert(write_len == SizeOfXLogRecord);
@@ -1416,7 +1435,7 @@ CopyXLogRecordToWAL(int write_len, bool isLogSwitch, XLogRecData *rdata,
* We do this one page at a time, to make sure we don't deadlock
* against ourselves if wal_buffers < XLOG_SEG_SIZE.
*/
- Assert(EndPos % XLogSegSize == 0);
+ Assert((EndPos & WalModMask) == 0);
/* Use up all the remaining space on the first page */
CurrPos += freespace;
@@ -1741,10 +1760,10 @@ GetXLogBuffer(XLogRecPtr ptr)
* the page header.
*/
if (ptr % XLOG_BLCKSZ == SizeOfXLogShortPHD &&
- ptr % XLOG_SEG_SIZE > XLOG_BLCKSZ)
+ (ptr & WalModMask) > XLOG_BLCKSZ)
initializedUpto = ptr - SizeOfXLogShortPHD;
else if (ptr % XLOG_BLCKSZ == SizeOfXLogLongPHD &&
- ptr % XLOG_SEG_SIZE < XLOG_BLCKSZ)
+ (ptr & WalModMask) < XLOG_BLCKSZ)
initializedUpto = ptr - SizeOfXLogLongPHD;
else
initializedUpto = ptr;
@@ -1794,6 +1813,7 @@ XLogBytePosToRecPtr(uint64 bytepos)
uint32 seg_offset;
XLogRecPtr result;
+
fullsegs = bytepos / UsableBytesInSegment;
bytesleft = bytepos % UsableBytesInSegment;
@@ -1878,7 +1898,7 @@ XLogRecPtrToBytePos(XLogRecPtr ptr)
XLByteToSeg(ptr, fullsegs);
- fullpages = (ptr % XLOG_SEG_SIZE) / XLOG_BLCKSZ;
+ fullpages = (ptr & WalModMask) / XLOG_BLCKSZ;
offset = ptr % XLOG_BLCKSZ;
if (fullpages == 0)
@@ -2043,7 +2063,7 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, bool opportunistic)
/*
* If first page of an XLOG segment file, make it a long header.
*/
- if ((NewPage->xlp_pageaddr % XLogSegSize) == 0)
+ if ((NewPage->xlp_pageaddr & WalModMask) == 0)
{
XLogLongPageHeader NewLongPage = (XLogLongPageHeader) NewPage;
@@ -2095,6 +2115,7 @@ CalculateCheckpointSegments(void)
* number of segments consumed between checkpoints.
*-------
*/
+
target = (double) max_wal_size / (2.0 + CheckPointCompletionTarget);
/* round down */
@@ -2105,9 +2126,58 @@ CalculateCheckpointSegments(void)
}
void
+assign_wal_segment_size(int newval, void *extra)
+{
+ /*
+ * During system initialization, XLogSegSize is not set so we use
+ * DEFAULT_XLOG_SEG_SIZE instead.
+ */
+ int WalSegSize = (XLogSegSize == 0) ? DEFAULT_XLOG_SEG_SIZE : XLOG_SEG_SIZE;
+
+ wal_segment_size = newval;
+ UsableBytesInSegment = (wal_segment_size * UsableBytesInPage) -
+ (SizeOfXLogLongPHD - SizeOfXLogShortPHD);
+ WalModMask = WalSegSize - 1;
+
+ /* Set the WalShiftBit */
+ WalShiftBit = 0;
+ while (WalSegSize > 1)
+ {
+ WalSegSize = WalSegSize >> 1;
+ WalShiftBit++;
+ }
+}
+
+void
+assign_min_wal_size(int newval, void *extra)
+{
+ /*
+ * During system initialization, XLogSegSize is not set so we use
+ * DEFAULT_XLOG_SEG_SIZE instead.
+ *
+ * min_wal_size is in kB and XLogSegSize is in bytes and so it is
+ * converted to kB for the calculation.
+ */
+ int WalSegSize = (XLogSegSize == 0) ? (DEFAULT_XLOG_SEG_SIZE / 1024) :
+ (XLOG_SEG_SIZE / 1024);
+
+ min_wal_size = newval / WalSegSize;
+}
+
+void
assign_max_wal_size(int newval, void *extra)
{
- max_wal_size = newval;
+ /*
+ * During system initialization, XLogSegSize is not set so we use
+ * DEFAULT_XLOG_SEG_SIZE instead.
+ *
+ * max_wal_size is in kB and XLogSegSize is in bytes and so it is
+ * converted to bytes for the calculation.
+ */
+ int WalSegSize = (XLogSegSize == 0) ? (DEFAULT_XLOG_SEG_SIZE / 1024) :
+ (XLOG_SEG_SIZE / 1024);
+
+ max_wal_size = newval / WalSegSize;
CalculateCheckpointSegments();
}
@@ -2135,8 +2205,8 @@ XLOGfileslop(XLogRecPtr PriorRedoPtr)
* correspond to. Always recycle enough segments to meet the minimum, and
* remove enough segments to stay below the maximum.
*/
- minSegNo = PriorRedoPtr / XLOG_SEG_SIZE + min_wal_size - 1;
- maxSegNo = PriorRedoPtr / XLOG_SEG_SIZE + max_wal_size - 1;
+ minSegNo = (PriorRedoPtr >> WalShiftBit) + min_wal_size - 1;
+ maxSegNo = (PriorRedoPtr >> WalShiftBit) + max_wal_size - 1;
/*
* Between those limits, recycle enough segments to get us through to the
@@ -2297,7 +2367,7 @@ XLogWrite(XLogwrtRqst WriteRqst, bool flexible)
{
/* first of group */
startidx = curridx;
- startoffset = (LogwrtResult.Write - XLOG_BLCKSZ) % XLogSegSize;
+ startoffset = (LogwrtResult.Write - XLOG_BLCKSZ) & WalModMask;
}
npages++;
@@ -3606,7 +3676,7 @@ PreallocXlogFiles(XLogRecPtr endptr)
bool use_existent;
XLByteToPrevSeg(endptr, _logSegNo);
- if ((endptr - 1) % XLogSegSize >= (uint32) (0.75 * XLogSegSize))
+ if (((endptr - 1) & WalModMask) >= (uint32) (0.75 * XLogSegSize))
{
_logSegNo++;
use_existent = true;
@@ -4060,7 +4130,7 @@ ReadRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr, int emode,
int32 offset;
XLByteToSeg(xlogreader->latestPagePtr, segno);
- offset = xlogreader->latestPagePtr % XLogSegSize;
+ offset = xlogreader->latestPagePtr & WalModMask;
XLogFileName(fname, xlogreader->readPageTLI, segno);
ereport(emode_for_corrupt_record(emode,
RecPtr ? RecPtr : EndRecPtr),
@@ -4329,6 +4399,8 @@ ReadControlFile(void)
{
pg_crc32c crc;
int fd;
+ uint32 wal_segsz;
+ static char wal_segsz_str[20];
/*
* Read data...
@@ -4429,13 +4501,6 @@ ReadControlFile(void)
" but the server was compiled with XLOG_BLCKSZ %d.",
ControlFile->xlog_blcksz, XLOG_BLCKSZ),
errhint("It looks like you need to recompile or initdb.")));
- if (ControlFile->xlog_seg_size != XLOG_SEG_SIZE)
- ereport(FATAL,
- (errmsg("database files are incompatible with server"),
- errdetail("The database cluster was initialized with XLOG_SEG_SIZE %d,"
- " but the server was compiled with XLOG_SEG_SIZE %d.",
- ControlFile->xlog_seg_size, XLOG_SEG_SIZE),
- errhint("It looks like you need to recompile or initdb.")));
if (ControlFile->nameDataLen != NAMEDATALEN)
ereport(FATAL,
(errmsg("database files are incompatible with server"),
@@ -4512,10 +4577,15 @@ ReadControlFile(void)
" but the server was compiled without USE_FLOAT8_BYVAL."),
errhint("It looks like you need to recompile or initdb.")));
#endif
+ XLogSegSize = ControlFile->xlog_seg_size;
/* Make the initdb settings visible as GUC variables, too */
SetConfigOption("data_checksums", DataChecksumsEnabled() ? "yes" : "no",
PGC_INTERNAL, PGC_S_OVERRIDE);
+ wal_segsz = XLOG_SEG_SIZE / XLOG_BLCKSZ;
+ snprintf(wal_segsz_str, sizeof(wal_segsz_str), "%d", wal_segsz);
+ SetConfigOption("wal_segment_size", wal_segsz_str, PGC_INTERNAL,
+ PGC_S_OVERRIDE);
}
void
@@ -4619,10 +4689,11 @@ XLOGChooseNumBuffers(void)
int xbuffers;
xbuffers = NBuffers / 32;
- if (xbuffers > XLOG_SEG_SIZE / XLOG_BLCKSZ)
- xbuffers = XLOG_SEG_SIZE / XLOG_BLCKSZ;
+ if (xbuffers > wal_segment_size)
+ xbuffers = wal_segment_size;
if (xbuffers < 8)
xbuffers = 8;
+
return xbuffers;
}
@@ -4669,6 +4740,7 @@ XLOGShmemSize(void)
{
Size size;
+ char buf[32];
/*
* If the value of wal_buffers is -1, use the preferred auto-tune value.
* This isn't an amazingly clean place to do this, but we must wait till
@@ -4677,8 +4749,18 @@ XLOGShmemSize(void)
*/
if (XLOGbuffers == -1)
{
- char buf[32];
-
+ /*
+ * The calculation of XLOGbuffers, requires the now run-time parameter
+ * XLogSegSize from the ControlFile. The value determined here is
+ * required to create the shared memory segment. Hence, temporarily
+ * allocating space and reading ControlFile here.
+ */
+ if (!IsBootstrapProcessingMode())
+ {
+ ControlFile = palloc(sizeof(ControlFileData));
+ ReadControlFile();
+ pfree(ControlFile);
+ }
snprintf(buf, sizeof(buf), "%d", XLOGChooseNumBuffers());
SetConfigOption("wal_buffers", buf, PGC_POSTMASTER, PGC_S_OVERRIDE);
}
@@ -4824,6 +4906,13 @@ BootStrapXLOG(void)
pg_crc32c crc;
/*
+ * initdb passes the WAL segment size in an environment variable. We don't
+ * bother doing any sanity checking, we already check in initdb that the
+ * user gives a sane value.
+ */
+ XLogSegSize = pg_atoi(getenv("XLOG_SEG_SIZE"), sizeof(uint32), 0);
+
+ /*
* Select a hopefully-unique system identifier code for this installation.
* We use the result of gettimeofday(), including the fractional seconds
* field, as being about as unique as we can easily get. (Think not to
@@ -5366,7 +5455,7 @@ exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog)
* avoid emplacing a bogus file.
*/
XLogFileCopy(endLogSegNo, endTLI, endLogSegNo,
- endOfLog % XLOG_SEG_SIZE);
+ (endOfLog & WalModMask));
}
else
{
@@ -7298,7 +7387,7 @@ StartupXLOG(void)
XLogRecPtr pageBeginPtr;
pageBeginPtr = EndOfLog - (EndOfLog % XLOG_BLCKSZ);
- Assert(readOff == pageBeginPtr % XLogSegSize);
+ Assert(readOff == (pageBeginPtr & WalModMask));
firstIdx = XLogRecPtrToBufIdx(EndOfLog);
@@ -7447,7 +7536,7 @@ StartupXLOG(void)
* restored from the archive to begin with, it's expected to have a
* .done file).
*/
- if (EndOfLog % XLOG_SEG_SIZE != 0 && XLogArchivingActive())
+ if ((EndOfLog & WalModMask) != 0 && XLogArchivingActive())
{
char origfname[MAXFNAMELEN];
XLogSegNo endLogSegNo;
@@ -7967,6 +8056,9 @@ InitXLOGAccess(void)
ThisTimeLineID = XLogCtl->ThisTimeLineID;
Assert(ThisTimeLineID != 0 || IsBootstrapProcessingMode());
+ /* Same for XLOG_SEG_SIZE */
+ XLogSegSize = ControlFile->xlog_seg_size;
+
/* Use GetRedoRecPtr to copy the RedoRecPtr safely */
(void) GetRedoRecPtr();
/* Also update our copy of doPageWrites. */
@@ -8485,7 +8577,7 @@ CreateCheckPoint(int flags)
freespace = INSERT_FREESPACE(curInsert);
if (freespace == 0)
{
- if (curInsert % XLogSegSize == 0)
+ if ((curInsert & WalModMask) == 0)
curInsert += SizeOfXLogLongPHD;
else
curInsert += SizeOfXLogShortPHD;
@@ -10739,7 +10831,7 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
*/
XLByteToSeg(startpoint, _logSegNo);
BackupHistoryFilePath(histfilepath, ThisTimeLineID, _logSegNo,
- (uint32) (startpoint % XLogSegSize));
+ (uint32) (startpoint & WalModMask));
fp = AllocateFile(histfilepath, "w");
if (!fp)
ereport(ERROR,
@@ -10792,7 +10884,7 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
XLByteToSeg(startpoint, _logSegNo);
BackupHistoryFileName(histfilename, ThisTimeLineID, _logSegNo,
- (uint32) (startpoint % XLogSegSize));
+ (uint32) (startpoint & WalModMask));
seconds_before_warning = 60;
waits = 0;
@@ -11236,7 +11328,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen,
XLogSegNo targetSegNo PG_USED_FOR_ASSERTS_ONLY;
XLByteToSeg(targetPagePtr, targetSegNo);
- targetPageOff = targetPagePtr % XLogSegSize;
+ targetPageOff = targetPagePtr & WalModMask;
/*
* See if we need to switch to a new segment because the requested record
@@ -11303,7 +11395,7 @@ retry:
if (((targetPagePtr) / XLOG_BLCKSZ) != (receivedUpto / XLOG_BLCKSZ))
readLen = XLOG_BLCKSZ;
else
- readLen = receivedUpto % XLogSegSize - targetPageOff;
+ readLen = (receivedUpto & WalModMask) - targetPageOff;
}
else
readLen = XLOG_BLCKSZ;
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 63e6552..ca47b7e 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -494,7 +494,7 @@ pg_xlogfile_name_offset(PG_FUNCTION_ARGS)
/*
* offset
*/
- xrecoff = locationpoint % XLogSegSize;
+ xrecoff = locationpoint & WalModMask;
values[1] = UInt32GetDatum(xrecoff);
isnull[1] = false;
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 0de2419..bf06185 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -672,7 +672,7 @@ XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count)
int segbytes;
int readbytes;
- startoff = recptr % XLogSegSize;
+ startoff = recptr & WalModMask;
/* Do we need to switch to a different xlog segment? */
if (sendFile < 0 || !XLByteInSeg(recptr, sendSegNo))
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index fe9041f..c004e8b 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -624,7 +624,7 @@ CheckArchiveTimeout(void)
* If the returned pointer points exactly to a segment boundary,
* assume nothing happened.
*/
- if ((switchpoint % XLogSegSize) != 0)
+ if ((switchpoint & WalModMask) != 0)
ereport(DEBUG1,
(errmsg("transaction log switch forced (archive_timeout=%d)",
XLogArchiveTimeout)));
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 0e4a4b9..9ff2395 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -991,7 +991,7 @@ XLogWalRcvWrite(char *buf, Size nbytes, XLogRecPtr recptr)
}
/* Calculate the start offset of the received logs */
- startoff = recptr % XLogSegSize;
+ startoff = (recptr & WalModMask);
if (startoff + nbytes > XLogSegSize)
segbytes = XLogSegSize - startoff;
diff --git a/src/backend/replication/walreceiverfuncs.c b/src/backend/replication/walreceiverfuncs.c
index df113b8..42d2da2 100644
--- a/src/backend/replication/walreceiverfuncs.c
+++ b/src/backend/replication/walreceiverfuncs.c
@@ -234,8 +234,8 @@ RequestXLogStreaming(TimeLineID tli, XLogRecPtr recptr, const char *conninfo,
* being created by XLOG streaming, which might cause trouble later on if
* the segment is e.g archived.
*/
- if (recptr % XLogSegSize != 0)
- recptr -= recptr % XLogSegSize;
+ if ((recptr & WalModMask) != 0)
+ recptr -= (recptr & WalModMask);
SpinLockAcquire(&walrcv->mutex);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index f3082c3..8535b4e 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -2047,7 +2047,7 @@ retry:
int segbytes;
int readbytes;
- startoff = recptr % XLogSegSize;
+ startoff = (recptr & WalModMask);
if (sendFile < 0 || !XLByteInSeg(recptr, sendSegNo))
{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 5f43b1e..1dd15de 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -31,6 +31,7 @@
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xact.h"
+#include "access/xlog_internal.h"
#include "catalog/namespace.h"
#include "commands/async.h"
#include "commands/prepare.h"
@@ -510,7 +511,6 @@ static int block_size;
static int segment_size;
static int wal_block_size;
static bool data_checksums;
-static int wal_segment_size;
static bool integer_datetimes;
static bool assert_enabled;
@@ -708,9 +708,6 @@ typedef struct
#if XLOG_BLCKSZ < 1024 || XLOG_BLCKSZ > (1024*1024)
#error XLOG_BLCKSZ must be between 1KB and 1MB
#endif
-#if XLOG_SEG_SIZE < (1024*1024) || XLOG_SEG_SIZE > (1024*1024*1024)
-#error XLOG_SEG_SIZE must be between 1MB and 1GB
-#endif
static const char *memory_units_hint = gettext_noop("Valid units for this parameter are \"kB\", \"MB\", \"GB\", and \"TB\".");
@@ -731,11 +728,6 @@ static const unit_conversion memory_unit_conversion_table[] =
{"MB", GUC_UNIT_XBLOCKS, 1024 / (XLOG_BLCKSZ / 1024)},
{"kB", GUC_UNIT_XBLOCKS, -(XLOG_BLCKSZ / 1024)},
- {"TB", GUC_UNIT_XSEGS, (1024 * 1024 * 1024) / (XLOG_SEG_SIZE / 1024)},
- {"GB", GUC_UNIT_XSEGS, (1024 * 1024) / (XLOG_SEG_SIZE / 1024)},
- {"MB", GUC_UNIT_XSEGS, -(XLOG_SEG_SIZE / (1024 * 1024))},
- {"kB", GUC_UNIT_XSEGS, -(XLOG_SEG_SIZE / 1024)},
-
{""} /* end of table marker */
};
@@ -2223,21 +2215,21 @@ static struct config_int ConfigureNamesInt[] =
{"min_wal_size", PGC_SIGHUP, WAL_CHECKPOINTS,
gettext_noop("Sets the minimum size to shrink the WAL to."),
NULL,
- GUC_UNIT_XSEGS
+ GUC_UNIT_KB
},
&min_wal_size,
- 5, 2, INT_MAX,
- NULL, NULL, NULL
+ 5 * 16 * 1024, 2, INT_MAX,
+ NULL, assign_min_wal_size, NULL
},
{
{"max_wal_size", PGC_SIGHUP, WAL_CHECKPOINTS,
gettext_noop("Sets the WAL size that triggers a checkpoint."),
NULL,
- GUC_UNIT_XSEGS
+ GUC_UNIT_KB
},
&max_wal_size,
- 64, 2, INT_MAX,
+ 64 * 16 * 1024, 2, INT_MAX,
NULL, assign_max_wal_size, NULL
},
@@ -2592,10 +2584,10 @@ static struct config_int ConfigureNamesInt[] =
GUC_UNIT_XBLOCKS | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&wal_segment_size,
- (XLOG_SEG_SIZE / XLOG_BLCKSZ),
- (XLOG_SEG_SIZE / XLOG_BLCKSZ),
- (XLOG_SEG_SIZE / XLOG_BLCKSZ),
- NULL, NULL, NULL
+ DEFAULT_XLOG_SEG_SIZE / XLOG_BLCKSZ,
+ 16,
+ INT_MAX,
+ NULL, assign_wal_segment_size, NULL
},
{
@@ -8041,11 +8033,6 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
snprintf(buffer, sizeof(buffer), "%dkB", XLOG_BLCKSZ / 1024);
values[2] = pstrdup(buffer);
break;
- case GUC_UNIT_XSEGS:
- snprintf(buffer, sizeof(buffer), "%dMB",
- XLOG_SEG_SIZE / (1024 * 1024));
- values[2] = pstrdup(buffer);
- break;
case GUC_UNIT_MS:
values[2] = "ms";
break;
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 443c2ee..b8c8ec0 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -53,6 +53,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <locale.h>
+#include <math.h>
#include <signal.h>
#include <time.h>
@@ -60,6 +61,7 @@
#include "sys/mman.h"
#endif
+#include "access/xlog_internal.h"
#include "catalog/catalog.h"
#include "catalog/pg_authid.h"
#include "common/file_utils.h"
@@ -140,6 +142,8 @@ static bool sync_only = false;
static bool show_setting = false;
static bool data_checksums = false;
static char *xlog_dir = "";
+static char *str_wal_segment_size = "";
+static int wal_segment_size;
/* internal vars */
@@ -1338,6 +1342,9 @@ bootstrap_template1(void)
snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype);
putenv(pg_strdup(cmd));
+ snprintf(cmd, sizeof(cmd), "XLOG_SEG_SIZE=%d", wal_segment_size);
+ putenv(pg_strdup(cmd));
+
unsetenv("LC_ALL");
/* Also ensure backend isn't confused by this environment var: */
@@ -2256,6 +2263,7 @@ usage(const char *progname)
printf(_(" -U, --username=NAME database superuser name\n"));
printf(_(" -W, --pwprompt prompt for a password for the new superuser\n"));
printf(_(" -X, --xlogdir=XLOGDIR location for the transaction log directory\n"));
+ printf(_(" --wal-segsize=SIZE size of wal segment size\n"));
printf(_("\nLess commonly used options:\n"));
printf(_(" -d, --debug generate lots of debugging output\n"));
printf(_(" -k, --data-checksums use data page checksums\n"));
@@ -2942,6 +2950,7 @@ main(int argc, char *argv[])
{"no-sync", no_argument, NULL, 'N'},
{"sync-only", no_argument, NULL, 'S'},
{"xlogdir", required_argument, NULL, 'X'},
+ {"wal-segsize", required_argument, NULL, 'Z'},
{"data-checksums", no_argument, NULL, 'k'},
{NULL, 0, NULL, 0}
};
@@ -3075,6 +3084,9 @@ main(int argc, char *argv[])
case 'X':
xlog_dir = pg_strdup(optarg);
break;
+ case 'Z':
+ str_wal_segment_size = pg_strdup(optarg);
+ break;
default:
/* getopt_long already emitted a complaint */
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
@@ -3137,6 +3149,23 @@ main(int argc, char *argv[])
check_need_password(authmethodlocal, authmethodhost);
+ if (str_wal_segment_size == NULL || !strlen(str_wal_segment_size))
+ wal_segment_size = DEFAULT_XLOG_SEG_SIZE;
+ else
+ {
+ wal_segment_size = atoi(str_wal_segment_size);
+
+ /* Check if wal_segment_size is valid */
+ if (!IsValidXLogSegSize(wal_segment_size * 1024 * 1024))
+ {
+ fprintf(stderr, _("%s: Invalid WAL segment size %d\n"), progname, wal_segment_size);
+ exit(1);
+ }
+
+ /* Convert wal_segment_size to bytes */
+ wal_segment_size = wal_segment_size * 1024 * 1024;
+
+ }
get_restricted_token(progname);
setup_pgdata();
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index ce1fe3b..6674dee 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -2380,6 +2380,9 @@ main(int argc, char **argv)
exit(1);
}
+ if (!SetXLogSegSize(conn))
+ disconnect_and_exit(1);
+
/* Create transaction log symlink, if required */
if (strcmp(xlog_dir, "") != 0)
{
diff --git a/src/bin/pg_basebackup/receivelog.h b/src/bin/pg_basebackup/receivelog.h
index 42e93ac..9265dc0 100644
--- a/src/bin/pg_basebackup/receivelog.h
+++ b/src/bin/pg_basebackup/receivelog.h
@@ -16,6 +16,7 @@
#include "walmethods.h"
#include "access/xlogdefs.h"
+#include "access/xlog_internal.h"
/*
* Called before trying to read more data or when a segment is
@@ -54,4 +55,5 @@ extern bool CheckServerVersionForStreaming(PGconn *conn);
extern bool ReceiveXlogStream(PGconn *conn,
StreamCtl *stream);
+uint32 XLogSegSize;
#endif /* RECEIVELOG_H */
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 31290d3..87efc3c 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -238,6 +238,59 @@ GetConnection(void)
}
/*
+ * Run the SHOW_WAL_SEGMENT_SIZE command to set the XLogSegSize
+ */
+bool
+SetXLogSegSize(PGconn *conn)
+{
+ PGresult *res;
+ char *tmp_result;
+ char xlog_unit[2];
+ int xlog_val,
+ multiplier = 1;
+
+ /* Check connection existence */
+ Assert(conn != NULL);
+
+ res = PQexec(conn, "SHOW wal_segment_size");
+ if (PQresultStatus(res) != PGRES_TUPLES_OK)
+ {
+ fprintf(stderr, _("%s: could not send replication command \"%s\": %s"),
+ progname, "SHOW wal_segment_size", PQerrorMessage(conn));
+
+ PQclear(res);
+ return false;
+ }
+ if (PQntuples(res) != 1 || PQnfields(res) < 1)
+ {
+ fprintf(stderr,
+ _("%s: could not identify system: 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 the xlog value and unit from the result */
+ sscanf(tmp_result, "%d%s", &xlog_val, xlog_unit);
+
+ /* XLogSegSize should be in bytes, set the multiplier based on unit */
+ if (strcmp(xlog_unit, "MB") == 0)
+ multiplier = 1024 * 1024;
+ else if (strcmp(xlog_unit, "GB") == 0)
+ multiplier = 1024 * 1024 * 1024;
+
+ /* Set the XLogSegSize */
+ XLogSegSize = xlog_val * multiplier;
+
+ 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 663bfac..bef750b 100644
--- a/src/bin/pg_basebackup/streamutil.h
+++ b/src/bin/pg_basebackup/streamutil.h
@@ -38,6 +38,7 @@ extern bool RunIdentifySystem(PGconn *conn, char **sysid,
TimeLineID *starttli,
XLogRecPtr *startpos,
char **db_name);
+extern bool SetXLogSegSize(PGconn *conn);
extern int64 feGetCurrentTimestamp(void);
extern void feTimestampDifference(int64 start_time, int64 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 20077a6..45bd5bb 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -27,6 +27,8 @@
#include "pg_getopt.h"
+uint32 XLogSegSize;
+
static void
usage(const char *progname)
{
@@ -163,6 +165,11 @@ main(int argc, char *argv[])
"is expecting. The results below are untrustworthy.\n\n"));
/*
+ * Read the XLOG_SEG_SIZE
+ */
+ XLogSegSize = ControlFile->xlog_seg_size;
+
+ /*
* 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
* all foreseeable circumstances, so we don't bother importing the
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 963802e..4ceebdc 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -57,6 +57,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_resetxlog"));
@@ -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
+ * defined. Hence XLog details are set later on.
+ */
+ log_fname = pg_strdup(optarg);
break;
default:
@@ -347,6 +354,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
*/
@@ -510,6 +520,7 @@ ReadControlFile(void)
{
/* Valid data... */
memcpy(&ControlFile, buffer, sizeof(ControlFile));
+ XLogSegSize = ControlFile.xlog_seg_size;
return true;
}
@@ -517,6 +528,7 @@ ReadControlFile(void)
progname);
/* We will use the data anyway, but treat it as guessed. */
memcpy(&ControlFile, buffer, sizeof(ControlFile));
+ XLogSegSize = ControlFile.xlog_seg_size;
guessed = true;
return true;
}
diff --git a/src/bin/pg_rewind/pg_rewind.c b/src/bin/pg_rewind/pg_rewind.c
index 2014fee..8d0d4a5 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,11 @@ digestControlFile(ControlFileData *ControlFile, char *src, size_t size)
memcpy(ControlFile, src, sizeof(ControlFileData));
+ /*
+ * Read the XLOG_SEG_SIZE
+ */
+ XLogSegSize = ControlFile->xlog_seg_size;
+
/* Additional checks on control file */
checkControlFile(ControlFile);
}
diff --git a/src/bin/pg_test_fsync/pg_test_fsync.c b/src/bin/pg_test_fsync/pg_test_fsync.c
index d65c0ab..b262ae8 100644
--- a/src/bin/pg_test_fsync/pg_test_fsync.c
+++ b/src/bin/pg_test_fsync/pg_test_fsync.c
@@ -62,7 +62,7 @@ static const char *progname;
static int secs_per_test = 5;
static int needs_unlink = 0;
-static char full_buf[XLOG_SEG_SIZE],
+static char full_buf[DEFAULT_XLOG_SEG_SIZE],
*buf,
*filename = FSYNC_FILENAME;
static struct timeval start_t,
@@ -204,7 +204,7 @@ prepare_buf(void)
int ops;
/* write random data into buffer */
- for (ops = 0; ops < XLOG_SEG_SIZE; ops++)
+ for (ops = 0; ops < DEFAULT_XLOG_SEG_SIZE; ops++)
full_buf[ops] = random();
buf = (char *) TYPEALIGN(XLOG_BLCKSZ, full_buf);
@@ -221,7 +221,7 @@ test_open(void)
if ((tmpfile = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) == -1)
die("could not open output file");
needs_unlink = 1;
- if (write(tmpfile, full_buf, XLOG_SEG_SIZE) != XLOG_SEG_SIZE)
+ if (write(tmpfile, full_buf, DEFAULT_XLOG_SEG_SIZE) != DEFAULT_XLOG_SEG_SIZE)
die("write failed");
/* fsync now so that dirty buffers don't skew later tests */
diff --git a/src/bin/pg_xlogdump/pg_xlogdump.c b/src/bin/pg_xlogdump/pg_xlogdump.c
index 590d2ad..61e8276 100644
--- a/src/bin/pg_xlogdump/pg_xlogdump.c
+++ b/src/bin/pg_xlogdump/pg_xlogdump.c
@@ -22,9 +22,11 @@
#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
{
@@ -892,8 +894,10 @@ main(int argc, char **argv)
{
char *directory = NULL;
char *fname = NULL;
+ char full_path[PATH_MAX];
int fd;
XLogSegNo segno;
+ struct stat fst;
split_path(argv[optind], &directory, &fname);
@@ -911,6 +915,25 @@ main(int argc, char **argv)
fatal_error("could not open file \"%s\"", fname);
close(fd);
+ if (private.inpath != NULL)
+ sprintf(full_path, "%s/%s", private.inpath, fname);
+ else
+ strcpy(full_path, fname);
+
+ stat(full_path, &fst);
+
+ if (!IsValidXLogSegSize(fst.st_size))
+ {
+ fprintf(stderr,
+ _("%s: file size %d is invalid \n"),
+ progname, (int) fst.st_size);
+
+ return EXIT_FAILURE;
+
+ }
+
+ XLogSegSize = (int) fst.st_size;
+
/* parse position from file */
XLogFromFileName(fname, &private.timeline, &segno);
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index a425572..8ee107b 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -94,6 +94,7 @@ extern PGDLLIMPORT XLogRecPtr XactLastCommitEnd;
extern bool reachedConsistency;
/* these variables are GUC parameters related to XLOG */
+extern int wal_segment_size;
extern int min_wal_size;
extern int max_wal_size;
extern int wal_keep_segments;
@@ -281,7 +282,9 @@ extern void SetWalWriterSleeping(bool sleeping);
extern void XLogRequestWalReceiverReply(void);
+extern void assign_wal_segment_size(int newval, void *extra);
extern void assign_max_wal_size(int newval, void *extra);
+extern void assign_min_wal_size(int newval, void *extra);
extern void assign_checkpoint_completion_target(double newval, void *extra);
/*
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 8ad4d47..a2d3e89 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -89,7 +89,22 @@ 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)
+
+extern uint32 WalModMask;
+extern uint32 XLogSegSize;
+#define XLOG_SEG_SIZE XLogSegSize
+
+/* XLogSegSize can range from 1MB to 1GB */
+#define XLogSegMinSize 1024 * 1024
+#define XLogSegMaxSize 1024 * 1024 * 1024
+
+/* Check if the given size is a valid XLogSegSize */
+#define IsPower2(x) ((x & (x-1)) == 0)
+#define IsValidXLogSegSize(size) \
+ ((size % (1024 * 1024) == 0) && \
+ IsPower2(size / (1024 * 1024)) && \
+ (size >= XLogSegMinSize && size <= XLogSegMaxSize))
+
#define XLogSegmentsPerXLogId (UINT64CONST(0x100000000) / XLOG_SEG_SIZE)
#define XLogSegNoOffsetToRecPtr(segno, offset, dest) \
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index b9dfdd4..7a143cc 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -912,13 +912,6 @@
*/
#undef XLOG_BLCKSZ
-/* XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2
- and larger than XLOG_BLCKSZ (preferably, a great deal larger than
- XLOG_BLCKSZ). Changing XLOG_SEG_SIZE requires an initdb. */
-#undef XLOG_SEG_SIZE
-
-
-
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h
index c079071..d7d939c 100644
--- a/src/include/pg_config_manual.h
+++ b/src/include/pg_config_manual.h
@@ -14,6 +14,12 @@
*/
/*
+ * This default value is used for wal_segment_size during initdb when no other
+ * value is specified with --walsegsize option.
+ */
+#define DEFAULT_XLOG_SEG_SIZE (16*1024*1024)
+
+/*
* Maximum length for identifiers (e.g. table names, column names,
* function names). Names actually are limited to one less byte than this,
* because the length must include a trailing zero byte.
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 7dd3780..9ff1119 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -218,7 +218,6 @@ typedef enum
#define GUC_UNIT_KB 0x1000 /* value is in kilobytes */
#define GUC_UNIT_BLOCKS 0x2000 /* value is in blocks */
#define GUC_UNIT_XBLOCKS 0x3000 /* value is in xlog blocks */
-#define GUC_UNIT_XSEGS 0x4000 /* value is in xlog segments */
#define GUC_UNIT_MEMORY 0xF000 /* mask for size-related units */
#define GUC_UNIT_MS 0x10000 /* value is in milliseconds */
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index fbf4da3..920e4c0 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -183,7 +183,7 @@ s{PG_VERSION_STR "[^"]+"}{__STRINGIFY(x) #x\n#define __STRINGIFY2(z) __STRINGIFY
1024, "\n";
print O "#define XLOG_BLCKSZ ",
1024 * $self->{options}->{wal_blocksize}, "\n";
- print O "#define XLOG_SEG_SIZE (", $self->{options}->{wal_segsize},
+ print O "#define DEFAULT_XLOG_SEG_SIZE (", $self->{options}->{wal_segsize},
" * 1024 * 1024)\n";
if ($self->{options}->{float4byval})