*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
***************
*** 1805,1817 **** include 'filename'
! full_page_writes (boolean)
full_page_writes> configuration parameter
! When this parameter is on, the PostgreSQL> server
writes the entire content of each disk page to WAL during the
first modification of that page after a checkpoint.
This is needed because
--- 1805,1818 ----
! full_page_writes (enum)
full_page_writes> configuration parameter
! When this parameter is on> or compress>,
! the PostgreSQL> server
writes the entire content of each disk page to WAL during the
first modification of that page after a checkpoint.
This is needed because
***************
*** 1829,1834 **** include 'filename'
--- 1830,1840 ----
+ Valid values are on>, compress>, and off>.
+ The default is on>.
+
+
+
Turning this parameter off speeds normal operation, but
might lead to either unrecoverable data corruption, or silent
data corruption, after a system failure. The risks are similar to turning off
***************
*** 1843,1851 **** include 'filename'
This parameter can only be set in the postgresql.conf>
file or on the server command line.
- The default is on>.
--- 1849,1861 ----
+ Setting this parameter to compress> compresses
+ the full page image to reduce the amount of WAL data.
+
+
+
This parameter can only be set in the postgresql.conf>
file or on the server command line.
*** a/src/backend/access/rmgrdesc/xlogdesc.c
--- b/src/backend/access/rmgrdesc/xlogdesc.c
***************
*** 31,36 **** const struct config_enum_entry wal_level_options[] = {
--- 31,51 ----
{NULL, 0, false}
};
+ static const char *
+ full_page_writes_str(FullPageWritesLevel level)
+ {
+ switch (level)
+ {
+ case FULL_PAGE_WRITES_ON:
+ return "true";
+ case FULL_PAGE_WRITES_COMPRESS:
+ return "compress";
+ case FULL_PAGE_WRITES_OFF:
+ return "false";
+ }
+ return "unrecognized";
+ }
+
void
xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
{
***************
*** 48,54 **** xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
(uint32) (checkpoint->redo >> 32), (uint32) checkpoint->redo,
checkpoint->ThisTimeLineID,
checkpoint->PrevTimeLineID,
! checkpoint->fullPageWrites ? "true" : "false",
checkpoint->nextXidEpoch, checkpoint->nextXid,
checkpoint->nextOid,
checkpoint->nextMulti,
--- 63,69 ----
(uint32) (checkpoint->redo >> 32), (uint32) checkpoint->redo,
checkpoint->ThisTimeLineID,
checkpoint->PrevTimeLineID,
! full_page_writes_str(checkpoint->fullPageWrites),
checkpoint->nextXidEpoch, checkpoint->nextXid,
checkpoint->nextOid,
checkpoint->nextMulti,
***************
*** 126,135 **** xlog_desc(StringInfo buf, uint8 xl_info, char *rec)
}
else if (info == XLOG_FPW_CHANGE)
{
! bool fpw;
! memcpy(&fpw, rec, sizeof(bool));
! appendStringInfo(buf, "full_page_writes: %s", fpw ? "true" : "false");
}
else if (info == XLOG_END_OF_RECOVERY)
{
--- 141,150 ----
}
else if (info == XLOG_FPW_CHANGE)
{
! int fpw;
! memcpy(&fpw, rec, sizeof(int));
! appendStringInfo(buf, "full_page_writes: %s", full_page_writes_str(fpw));
}
else if (info == XLOG_END_OF_RECOVERY)
{
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 55,60 ****
--- 55,61 ----
#include "storage/spin.h"
#include "utils/builtins.h"
#include "utils/guc.h"
+ #include "utils/pg_lzcompress.h"
#include "utils/ps_status.h"
#include "utils/relmapper.h"
#include "utils/snapmgr.h"
***************
*** 78,84 **** int XLogArchiveTimeout = 0;
bool XLogArchiveMode = false;
char *XLogArchiveCommand = NULL;
bool EnableHotStandby = false;
! bool fullPageWrites = true;
bool log_checkpoints = false;
int sync_method = DEFAULT_SYNC_METHOD;
int wal_level = WAL_LEVEL_MINIMAL;
--- 79,85 ----
bool XLogArchiveMode = false;
char *XLogArchiveCommand = NULL;
bool EnableHotStandby = false;
! int fullPageWrites = FULL_PAGE_WRITES_ON;
bool log_checkpoints = false;
int sync_method = DEFAULT_SYNC_METHOD;
int wal_level = WAL_LEVEL_MINIMAL;
***************
*** 165,171 **** static TimeLineID receiveTLI = 0;
* that the recovery starting checkpoint record indicates, and then updated
* each time XLOG_FPW_CHANGE record is replayed.
*/
! static bool lastFullPageWrites;
/*
* Local copy of SharedRecoveryInProgress variable. True actually means "not
--- 166,172 ----
* that the recovery starting checkpoint record indicates, and then updated
* each time XLOG_FPW_CHANGE record is replayed.
*/
! static int lastFullPageWrites;
/*
* Local copy of SharedRecoveryInProgress variable. True actually means "not
***************
*** 796,801 **** static bool ReserveXLogSwitch(XLogRecPtr *StartPos, XLogRecPtr *EndPos,
--- 797,803 ----
XLogRecPtr *PrevPtr);
static XLogRecPtr WaitXLogInsertionsToFinish(XLogRecPtr upto);
static void WakeupWaiters(XLogRecPtr EndPos);
+ static char *CompressBackupBlock(char *page, uint32 orig_len, uint32 *len);
static char *GetXLogBuffer(XLogRecPtr ptr);
static XLogRecPtr XLogBytePosToRecPtr(uint64 bytepos);
static XLogRecPtr XLogBytePosToEndRecPtr(uint64 bytepos);
***************
*** 846,851 **** XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata)
--- 848,854 ----
static XLogRecord *rechdr;
XLogRecPtr StartPos;
XLogRecPtr EndPos;
+ int fpw;
if (rechdr == NULL)
{
***************
*** 898,908 **** begin:;
/*
* Decide if we need to do full-page writes in this XLOG record: true if
! * full_page_writes is on or we have a PITR request for it. Since we
! * don't yet have an insertion slot, fullPageWrites and forcePageWrites
! * could change under us, but we'll recheck them once we have a slot.
*/
! doPageWrites = Insert->fullPageWrites || Insert->forcePageWrites;
len = 0;
for (rdt = rdata;;)
--- 901,913 ----
/*
* Decide if we need to do full-page writes in this XLOG record: true if
! * full_page_writes is needed (i.e., on or compress) or we have a PITR
! * request for it. Since we don't yet have an insertion slot,
! * fullPageWrites and forcePageWrites could change under us, but we'll
! * recheck them once we have a slot.
*/
! fpw = Insert->fullPageWrites;
! doPageWrites = FullPageWritesIsNeeded(fpw) || Insert->forcePageWrites;
len = 0;
for (rdt = rdata;;)
***************
*** 1003,1008 **** begin:;
--- 1008,1026 ----
rdt->next = &(dtbuf_rdt2[i]);
rdt = rdt->next;
+ if (fpw <= FULL_PAGE_WRITES_COMPRESS)
+ {
+ rdt->data = CompressBackupBlock(page, BLCKSZ - bkpb->hole_length, &(rdt->len));
+ if (rdt->data != NULL)
+ {
+ write_len += rdt->len;
+ bkpb->hole_length = BLCKSZ - rdt->len;
+ bkpb->flags = BKPBLOCK_COMPRESSED;
+ rdt->next = NULL;
+ continue;
+ }
+ }
+
if (bkpb->hole_length == 0)
{
rdt->data = page;
***************
*** 1133,1144 **** begin:;
}
/*
! * Also check to see if fullPageWrites or forcePageWrites was just turned
! * on; if we weren't already doing full-page writes then go back and
! * recompute. (If it was just turned off, we could recompute the record
! * without full pages, but we choose not to bother.)
*/
! if ((Insert->fullPageWrites || Insert->forcePageWrites) && !doPageWrites)
{
/* Oops, must redo it with full-page data. */
WALInsertSlotRelease();
--- 1151,1164 ----
}
/*
! * Also check to see if fullPageWrites was just changed on or compress,
! * or if forcePageWrites was just turned on; if we weren't already doing
! * full-page writes then go back and recompute. (If it was just turned off,
! * we could recompute the record without full pages, but we choose not
! * to bother.)
*/
! if ((FullPageWritesIsNeeded(Insert->fullPageWrites) || Insert->forcePageWrites) &&
! !doPageWrites)
{
/* Oops, must redo it with full-page data. */
WALInsertSlotRelease();
***************
*** 2091,2096 **** WaitXLogInsertionsToFinish(XLogRecPtr upto)
--- 2111,2158 ----
}
/*
+ * Create a compressed version of a backup block
+ *
+ * If successful, return a compressed result and set 'len' to its length.
+ * Otherwise (ie, compressed result is actually bigger than original),
+ * return NULL.
+ */
+ static char *
+ CompressBackupBlock(char *page, uint32 orig_len, uint32 *len)
+ {
+ struct varlena *buf;
+
+ #define PGLZ_BLCKSZ PGLZ_MAX_OUTPUT(BLCKSZ)
+
+ buf = (struct varlena *) palloc(PGLZ_BLCKSZ);
+
+ /*
+ * We recheck the actual size even if pglz_compress() reports success,
+ * because it might be satisfied with having saved as little as one byte
+ * in the compressed data --- which could turn into a net loss once you
+ * consider header and alignment padding. Worst case, the compressed
+ * format might require three padding bytes (plus header, which is
+ * included in VARSIZE(buf)), whereas the uncompressed format would take
+ * only one header byte and no padding if the value is short enough. So
+ * we insist on a savings of more than 2 bytes to ensure we have a gain.
+ */
+ if (pglz_compress(page, BLCKSZ,
+ (PGLZ_Header *) buf, PGLZ_strategy_default) &&
+ VARSIZE(buf) < orig_len - 2)
+ {
+ /* successful compression */
+ *len = VARHDRSZ + VARSIZE(buf);
+ return (char *) buf;
+ }
+ else
+ {
+ /* incompressible data */
+ pfree(buf);
+ return NULL;
+ }
+ }
+
+ /*
* Get a pointer to the right location in the WAL buffer containing the
* given XLogRecPtr.
*
***************
*** 2346,2351 **** XLogCheckBuffer(XLogRecData *rdata, bool holdsExclusiveLock,
--- 2408,2414 ----
* The page needs to be backed up, so set up *bkpb
*/
BufferGetTag(rdata->buffer, &bkpb->node, &bkpb->fork, &bkpb->block);
+ bkpb->flags = BKPBLOCK_UNCOMPRESSED;
if (rdata->buffer_std)
{
***************
*** 4307,4313 **** RestoreBackupBlockContents(XLogRecPtr lsn, BkpBlock bkpb, char *blk,
page = (Page) BufferGetPage(buffer);
! if (bkpb.hole_length == 0)
{
memcpy((char *) page, blk, BLCKSZ);
}
--- 4370,4381 ----
page = (Page) BufferGetPage(buffer);
! if (bkpb.flags == BKPBLOCK_COMPRESSED)
! {
! /* If it's compressed, decompress it */
! pglz_decompress((PGLZ_Header *) blk, (char *) page);
! }
! else if (bkpb.hole_length == 0)
{
memcpy((char *) page, blk, BLCKSZ);
}
***************
*** 8975,8984 **** UpdateFullPageWrites(void)
* setting it to false, first write the WAL record and then set the global
* flag.
*/
! if (fullPageWrites)
{
WALInsertSlotAcquire(true);
! Insert->fullPageWrites = true;
WALInsertSlotRelease();
}
--- 9043,9052 ----
* setting it to false, first write the WAL record and then set the global
* flag.
*/
! if (FullPageWritesIsNeeded(fullPageWrites))
{
WALInsertSlotAcquire(true);
! Insert->fullPageWrites = fullPageWrites;
WALInsertSlotRelease();
}
***************
*** 8991,9007 **** UpdateFullPageWrites(void)
XLogRecData rdata;
rdata.data = (char *) (&fullPageWrites);
! rdata.len = sizeof(bool);
rdata.buffer = InvalidBuffer;
rdata.next = NULL;
XLogInsert(RM_XLOG_ID, XLOG_FPW_CHANGE, &rdata);
}
! if (!fullPageWrites)
{
WALInsertSlotAcquire(true);
! Insert->fullPageWrites = false;
WALInsertSlotRelease();
}
END_CRIT_SECTION();
--- 9059,9075 ----
XLogRecData rdata;
rdata.data = (char *) (&fullPageWrites);
! rdata.len = sizeof(int);
rdata.buffer = InvalidBuffer;
rdata.next = NULL;
XLogInsert(RM_XLOG_ID, XLOG_FPW_CHANGE, &rdata);
}
! if (!FullPageWritesIsNeeded(fullPageWrites))
{
WALInsertSlotAcquire(true);
! Insert->fullPageWrites = fullPageWrites;
WALInsertSlotRelease();
}
END_CRIT_SECTION();
***************
*** 9353,9368 **** xlog_redo(XLogRecPtr lsn, XLogRecord *record)
{
/* use volatile pointer to prevent code rearrangement */
volatile XLogCtlData *xlogctl = XLogCtl;
! bool fpw;
! memcpy(&fpw, XLogRecGetData(record), sizeof(bool));
/*
* Update the LSN of the last replayed XLOG_FPW_CHANGE record so that
* do_pg_start_backup() and do_pg_stop_backup() can check whether
* full_page_writes has been disabled during online backup.
*/
! if (!fpw)
{
SpinLockAcquire(&xlogctl->info_lck);
if (xlogctl->lastFpwDisableRecPtr < ReadRecPtr)
--- 9421,9436 ----
{
/* use volatile pointer to prevent code rearrangement */
volatile XLogCtlData *xlogctl = XLogCtl;
! int fpw;
! memcpy(&fpw, XLogRecGetData(record), sizeof(int));
/*
* Update the LSN of the last replayed XLOG_FPW_CHANGE record so that
* do_pg_start_backup() and do_pg_stop_backup() can check whether
* full_page_writes has been disabled during online backup.
*/
! if (!FullPageWritesIsNeeded(fpw))
{
SpinLockAcquire(&xlogctl->info_lck);
if (xlogctl->lastFpwDisableRecPtr < ReadRecPtr)
***************
*** 9686,9692 **** do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
do
{
! bool checkpointfpw;
/*
* Force a CHECKPOINT. Aside from being necessary to prevent torn
--- 9754,9760 ----
do
{
! int checkpointfpw;
/*
* Force a CHECKPOINT. Aside from being necessary to prevent torn
***************
*** 9737,9743 **** do_pg_start_backup(const char *backupidstr, bool fast, TimeLineID *starttli_p,
recptr = xlogctl->lastFpwDisableRecPtr;
SpinLockRelease(&xlogctl->info_lck);
! if (!checkpointfpw || startpoint <= recptr)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("WAL generated with full_page_writes=off was replayed "
--- 9805,9811 ----
recptr = xlogctl->lastFpwDisableRecPtr;
SpinLockRelease(&xlogctl->info_lck);
! if (!FullPageWritesIsNeeded(checkpointfpw) || startpoint <= recptr)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("WAL generated with full_page_writes=off was replayed "
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
***************
*** 381,386 **** static const struct config_enum_entry synchronous_commit_options[] = {
--- 381,403 ----
};
/*
+ * Although only "on", "off", and "compress" are documented, we
+ * accept all the likely variants of "on" and "off".
+ */
+ static const struct config_enum_entry full_page_writes_options[] = {
+ {"compress", FULL_PAGE_WRITES_COMPRESS, false},
+ {"on", FULL_PAGE_WRITES_ON, false},
+ {"off", FULL_PAGE_WRITES_OFF, false},
+ {"true", FULL_PAGE_WRITES_ON, true},
+ {"false", FULL_PAGE_WRITES_OFF, true},
+ {"yes", FULL_PAGE_WRITES_ON, true},
+ {"no", FULL_PAGE_WRITES_OFF, true},
+ {"1", FULL_PAGE_WRITES_ON, true},
+ {"0", FULL_PAGE_WRITES_OFF, true},
+ {NULL, 0, false}
+ };
+
+ /*
* Options for enum values stored in other modules
*/
extern const struct config_enum_entry wal_level_options[];
***************
*** 840,858 **** static struct config_bool ConfigureNamesBool[] =
NULL, NULL, NULL
},
{
- {"full_page_writes", PGC_SIGHUP, WAL_SETTINGS,
- gettext_noop("Writes full pages to WAL when first modified after a checkpoint."),
- gettext_noop("A page write in process during an operating system crash might be "
- "only partially written to disk. During recovery, the row changes "
- "stored in WAL are not enough to recover. This option writes "
- "pages when first modified after a checkpoint to WAL so full recovery "
- "is possible.")
- },
- &fullPageWrites,
- true,
- NULL, NULL, NULL
- },
- {
{"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
gettext_noop("Logs each checkpoint."),
NULL
--- 857,862 ----
***************
*** 3288,3293 **** static struct config_enum ConfigureNamesEnum[] =
--- 3292,3311 ----
},
{
+ {"full_page_writes", PGC_SIGHUP, WAL_SETTINGS,
+ gettext_noop("Writes full pages to WAL when first modified after a checkpoint."),
+ gettext_noop("A page write in process during an operating system crash might be "
+ "only partially written to disk. During recovery, the row changes "
+ "stored in WAL are not enough to recover. This option writes "
+ "pages when first modified after a checkpoint to WAL so full recovery "
+ "is possible.")
+ },
+ &fullPageWrites,
+ FULL_PAGE_WRITES_ON, full_page_writes_options,
+ NULL, NULL, NULL
+ },
+
+ {
{"trace_recovery_messages", PGC_SIGHUP, DEVELOPER_OPTIONS,
gettext_noop("Enables logging of recovery-related debugging information."),
gettext_noop("Each level includes all the levels that follow it. The later"
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 173,179 ****
# fsync
# fsync_writethrough
# open_sync
! #full_page_writes = on # recover from partial page writes
#wal_buffers = -1 # min 32kB, -1 sets based on shared_buffers
# (change requires restart)
#wal_writer_delay = 200ms # 1-10000 milliseconds
--- 173,180 ----
# fsync
# fsync_writethrough
# open_sync
! #full_page_writes = on # recover from partial page writes;
! # off, compress, or on
#wal_buffers = -1 # min 32kB, -1 sets based on shared_buffers
# (change requires restart)
#wal_writer_delay = 200ms # 1-10000 milliseconds
*** a/src/bin/pg_controldata/pg_controldata.c
--- b/src/bin/pg_controldata/pg_controldata.c
***************
*** 218,224 **** main(int argc, char *argv[])
printf(_("Latest checkpoint's PrevTimeLineID: %u\n"),
ControlFile.checkPointCopy.PrevTimeLineID);
printf(_("Latest checkpoint's full_page_writes: %s\n"),
! ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
printf(_("Latest checkpoint's NextXID: %u/%u\n"),
ControlFile.checkPointCopy.nextXidEpoch,
ControlFile.checkPointCopy.nextXid);
--- 218,224 ----
printf(_("Latest checkpoint's PrevTimeLineID: %u\n"),
ControlFile.checkPointCopy.PrevTimeLineID);
printf(_("Latest checkpoint's full_page_writes: %s\n"),
! FullPageWritesStr(ControlFile.checkPointCopy.fullPageWrites));
printf(_("Latest checkpoint's NextXID: %u/%u\n"),
ControlFile.checkPointCopy.nextXidEpoch,
ControlFile.checkPointCopy.nextXid);
*** a/src/bin/pg_resetxlog/pg_resetxlog.c
--- b/src/bin/pg_resetxlog/pg_resetxlog.c
***************
*** 496,502 **** GuessControlValues(void)
ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
ControlFile.checkPointCopy.ThisTimeLineID = 1;
ControlFile.checkPointCopy.PrevTimeLineID = 1;
! ControlFile.checkPointCopy.fullPageWrites = false;
ControlFile.checkPointCopy.nextXidEpoch = 0;
ControlFile.checkPointCopy.nextXid = FirstNormalTransactionId;
ControlFile.checkPointCopy.nextOid = FirstBootstrapObjectId;
--- 496,502 ----
ControlFile.checkPointCopy.redo = SizeOfXLogLongPHD;
ControlFile.checkPointCopy.ThisTimeLineID = 1;
ControlFile.checkPointCopy.PrevTimeLineID = 1;
! ControlFile.checkPointCopy.fullPageWrites = FULL_PAGE_WRITES_OFF;
ControlFile.checkPointCopy.nextXidEpoch = 0;
ControlFile.checkPointCopy.nextXid = FirstNormalTransactionId;
ControlFile.checkPointCopy.nextOid = FirstBootstrapObjectId;
***************
*** 583,589 **** PrintControlValues(bool guessed)
printf(_("Latest checkpoint's TimeLineID: %u\n"),
ControlFile.checkPointCopy.ThisTimeLineID);
printf(_("Latest checkpoint's full_page_writes: %s\n"),
! ControlFile.checkPointCopy.fullPageWrites ? _("on") : _("off"));
printf(_("Latest checkpoint's NextXID: %u/%u\n"),
ControlFile.checkPointCopy.nextXidEpoch,
ControlFile.checkPointCopy.nextXid);
--- 583,589 ----
printf(_("Latest checkpoint's TimeLineID: %u\n"),
ControlFile.checkPointCopy.ThisTimeLineID);
printf(_("Latest checkpoint's full_page_writes: %s\n"),
! FullPageWritesStr(ControlFile.checkPointCopy.fullPageWrites));
printf(_("Latest checkpoint's NextXID: %u/%u\n"),
ControlFile.checkPointCopy.nextXidEpoch,
ControlFile.checkPointCopy.nextXid);
*** a/src/include/access/xlog.h
--- b/src/include/access/xlog.h
***************
*** 188,194 **** extern int XLogArchiveTimeout;
extern bool XLogArchiveMode;
extern char *XLogArchiveCommand;
extern bool EnableHotStandby;
- extern bool fullPageWrites;
extern bool log_checkpoints;
extern int num_xloginsert_slots;
--- 188,193 ----
***************
*** 201,206 **** typedef enum WalLevel
--- 200,217 ----
} WalLevel;
extern int wal_level;
+ typedef enum FullPageWritesLevel
+ {
+ FULL_PAGE_WRITES_OFF = 0,
+ FULL_PAGE_WRITES_COMPRESS,
+ FULL_PAGE_WRITES_ON
+ } FullPageWritesLevel;
+ extern int fullPageWrites;
+ #define FullPageWritesIsNeeded(fpw) (fpw >= FULL_PAGE_WRITES_COMPRESS)
+ #define FullPageWritesStr(fpw) \
+ (fpw == FULL_PAGE_WRITES_ON ? _("on") : \
+ (fpw == FULL_PAGE_WRITES_OFF ? _("off") : _("compress")))
+
#define XLogArchivingActive() (XLogArchiveMode && wal_level >= WAL_LEVEL_ARCHIVE)
#define XLogArchiveCommandSet() (XLogArchiveCommand[0] != '\0')
*** a/src/include/access/xlog_internal.h
--- b/src/include/access/xlog_internal.h
***************
*** 46,57 **** typedef struct BkpBlock
RelFileNode node; /* relation containing block */
ForkNumber fork; /* fork within the relation */
BlockNumber block; /* block number */
! uint16 hole_offset; /* number of bytes before "hole" */
! uint16 hole_length; /* number of bytes in "hole" */
/* ACTUAL BLOCK DATA FOLLOWS AT END OF STRUCT */
} BkpBlock;
/*
* Each page of XLOG file has a header like this:
*/
--- 46,61 ----
RelFileNode node; /* relation containing block */
ForkNumber fork; /* fork within the relation */
BlockNumber block; /* block number */
! unsigned hole_offset:15, /* number of bytes before "hole" */
! flags:2, /* state of a backup block, see below */
! hole_length:15; /* number of bytes in "hole" */
/* ACTUAL BLOCK DATA FOLLOWS AT END OF STRUCT */
} BkpBlock;
+ #define BKPBLOCK_UNCOMPRESSED 0 /* uncompressed */
+ #define BKPBLOCK_COMPRESSED 1 /* comperssed */
+
/*
* Each page of XLOG file has a header like this:
*/
*** a/src/include/catalog/pg_control.h
--- b/src/include/catalog/pg_control.h
***************
*** 35,41 **** typedef struct CheckPoint
TimeLineID ThisTimeLineID; /* current TLI */
TimeLineID PrevTimeLineID; /* previous TLI, if this record begins a new
* timeline (equals ThisTimeLineID otherwise) */
! bool fullPageWrites; /* current full_page_writes */
uint32 nextXidEpoch; /* higher-order bits of nextXid */
TransactionId nextXid; /* next free XID */
Oid nextOid; /* next free OID */
--- 35,41 ----
TimeLineID ThisTimeLineID; /* current TLI */
TimeLineID PrevTimeLineID; /* previous TLI, if this record begins a new
* timeline (equals ThisTimeLineID otherwise) */
! int fullPageWrites; /* current full_page_writes */
uint32 nextXidEpoch; /* higher-order bits of nextXid */
TransactionId nextXid; /* next free XID */
Oid nextOid; /* next free OID */