*** 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" *************** *** 79,84 **** bool XLogArchiveMode = false; --- 80,86 ---- char *XLogArchiveCommand = NULL; bool EnableHotStandby = false; bool fullPageWrites = true; + bool compress_backup_block = false; bool log_checkpoints = false; int sync_method = DEFAULT_SYNC_METHOD; int wal_level = WAL_LEVEL_MINIMAL; *************** *** 787,792 **** static bool ReserveXLogSwitch(XLogRecPtr *StartPos, XLogRecPtr *EndPos, --- 789,795 ---- 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); *************** *** 994,999 **** begin:; --- 997,1014 ---- rdt->next = &(dtbuf_rdt2[i]); rdt = rdt->next; + if (compress_backup_block) + { + rdt->data = CompressBackupBlock(page, BLCKSZ - bkpb->hole_length, &(rdt->len)); + if (rdt->data != NULL) + { + write_len += rdt->len; + bkpb->hole_length = BLCKSZ - rdt->len; + rdt->next = NULL; + continue; + } + } + if (bkpb->hole_length == 0) { rdt->data = page; *************** *** 2082,2087 **** WaitXLogInsertionsToFinish(XLogRecPtr upto) --- 2097,2144 ---- } /* + * 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. * *************** *** 4319,4324 **** RestoreBackupBlockContents(XLogRecPtr lsn, BkpBlock bkpb, char *blk, --- 4376,4386 ---- { memcpy((char *) page, blk, BLCKSZ); } + else if (VARATT_IS_COMPRESSED((struct varlena *) blk)) + { + /* If it's compressed, decompress it */ + pglz_decompress((PGLZ_Header *) blk, (char *) page); + } else { memcpy((char *) page, blk, bkpb.hole_offset); *** a/src/backend/utils/misc/guc.c --- b/src/backend/utils/misc/guc.c *************** *** 853,858 **** static struct config_bool ConfigureNamesBool[] = --- 853,867 ---- NULL, NULL, NULL }, { + {"compress_backup_block", PGC_SIGHUP, WAL_SETTINGS, + gettext_noop("Compress backup block in WAL."), + NULL + }, + &compress_backup_block, + false, + NULL, NULL, NULL + }, + { {"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT, gettext_noop("Logs each checkpoint."), NULL *** a/src/include/access/xlog.h --- b/src/include/access/xlog.h *************** *** 189,194 **** extern bool XLogArchiveMode; --- 189,195 ---- extern char *XLogArchiveCommand; extern bool EnableHotStandby; extern bool fullPageWrites; + extern bool compress_backup_block; extern bool log_checkpoints; extern int num_xloginsert_slots;