1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-14 08:21:07 +03:00

Change CRCs in WAL records from 64bit to 32bit for performance reasons.

Instead of a separate CRC on each backup block, include backup blocks
in their parent WAL record's CRC; this is important to ensure that the
backup block really goes with the WAL record, ie there was not a page
tear right at the start of the backup block.  Implement a simple form
of compression of backup blocks: drop any run of zeroes starting at
pd_lower, so as not to store the unused 'hole' that commonly exists in
PG heap and index pages.  Tweak PageRepairFragmentation and related
routines to ensure they keep the unused space zeroed, so that the above
compression method remains effective.  All per recent discussions.
This commit is contained in:
Tom Lane
2005-06-02 05:55:29 +00:00
parent c196c7ae8b
commit 21fda22ec4
11 changed files with 516 additions and 212 deletions

View File

@ -1,32 +1,65 @@
/*
* pg_crc.h
*
* PostgreSQL 64-bit CRC support
* PostgreSQL CRC support
*
* See Ross Williams' excellent introduction
* A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
* ftp://ftp.rocksoft.com/papers/crc_v3.txt or several other net sites.
*
* We use a normal (not "reflected", in Williams' terms) CRC, using initial
* all-ones register contents and a final bit inversion.
*
* The 64-bit variant is not used as of PostgreSQL 8.1, but we retain the
* code for possible future use.
*
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/pg_crc.h,v 1.12 2004/12/31 22:03:46 pgsql Exp $
* $PostgreSQL: pgsql/src/include/utils/pg_crc.h,v 1.13 2005/06/02 05:55:29 tgl Exp $
*/
#ifndef PG_CRC_H
#define PG_CRC_H
typedef uint32 pg_crc32;
/* Initialize a CRC accumulator */
#define INIT_CRC32(crc) ((crc) = 0xFFFFFFFF)
/* Finish a CRC calculation */
#define FIN_CRC32(crc) ((crc) ^= 0xFFFFFFFF)
/* Accumulate some (more) bytes into a CRC */
#define COMP_CRC32(crc, data, len) \
do { \
unsigned char *__data = (unsigned char *) (data); \
uint32 __len = (len); \
\
while (__len-- > 0) \
{ \
int __tab_index = ((int) ((crc) >> 24) ^ *__data++) & 0xFF; \
(crc) = pg_crc32_table[__tab_index] ^ ((crc) << 8); \
} \
} while (0)
/* Check for equality of two CRCs */
#define EQ_CRC32(c1,c2) ((c1) == (c2))
/* Constant table for CRC calculation */
extern const uint32 pg_crc32_table[];
#ifdef PROVIDE_64BIT_CRC
/*
* If we have a 64-bit integer type, then a 64-bit CRC looks just like the
* usual sort of implementation. (See Ross Williams' excellent introduction
* A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
* ftp://ftp.rocksoft.com/papers/crc_v3.txt or several other net sites.)
* If we have no working 64-bit type, then fake it with two 32-bit registers.
*
* The present implementation is a normal (not "reflected", in Williams'
* terms) 64-bit CRC, using initial all-ones register contents and a final
* bit inversion. The chosen polynomial is borrowed from the DLT1 spec
* (ECMA-182, available from http://www.ecma.ch/ecma1/STAND/ECMA-182.HTM):
*
* x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
* x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
* x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
* x^7 + x^4 + x + 1
* usual sort of implementation. If we have no working 64-bit type, then
* fake it with two 32-bit registers. (Note: experience has shown that the
* two-32-bit-registers code is as fast as, or even much faster than, the
* 64-bit code on all but true 64-bit machines. INT64_IS_BUSTED is therefore
* probably the wrong control symbol to use to select the implementation.)
*/
#ifdef INT64_IS_BUSTED
@ -39,11 +72,11 @@
* all machines, we could do a configure test to decide how to order the
* two fields, but it seems not worth the trouble.
*/
typedef struct crc64
typedef struct pg_crc64
{
uint32 crc0;
uint32 crc1;
} crc64;
} pg_crc64;
/* Initialize a CRC accumulator */
#define INIT_CRC64(crc) ((crc).crc0 = 0xffffffff, (crc).crc1 = 0xffffffff)
@ -62,8 +95,8 @@ do { \
while (__len-- > 0) \
{ \
int __tab_index = ((int) (__crc1 >> 24) ^ *__data++) & 0xFF; \
__crc1 = crc_table1[__tab_index] ^ ((__crc1 << 8) | (__crc0 >> 24)); \
__crc0 = crc_table0[__tab_index] ^ (__crc0 << 8); \
__crc1 = pg_crc64_table1[__tab_index] ^ ((__crc1 << 8) | (__crc0 >> 24)); \
__crc0 = pg_crc64_table0[__tab_index] ^ (__crc0 << 8); \
} \
(crc).crc0 = __crc0; \
(crc).crc1 = __crc1; \
@ -73,15 +106,15 @@ do { \
#define EQ_CRC64(c1,c2) ((c1).crc0 == (c2).crc0 && (c1).crc1 == (c2).crc1)
/* Constant table for CRC calculation */
extern const uint32 crc_table0[];
extern const uint32 crc_table1[];
extern const uint32 pg_crc64_table0[];
extern const uint32 pg_crc64_table1[];
#else /* int64 works */
typedef struct crc64
typedef struct pg_crc64
{
uint64 crc0;
} crc64;
} pg_crc64;
/* Initialize a CRC accumulator */
#define INIT_CRC64(crc) ((crc).crc0 = UINT64CONST(0xffffffffffffffff))
@ -99,7 +132,7 @@ do { \
while (__len-- > 0) \
{ \
int __tab_index = ((int) (__crc0 >> 56) ^ *__data++) & 0xFF; \
__crc0 = crc_table[__tab_index] ^ (__crc0 << 8); \
__crc0 = pg_crc64_table[__tab_index] ^ (__crc0 << 8); \
} \
(crc).crc0 = __crc0; \
} while (0)
@ -108,7 +141,9 @@ do { \
#define EQ_CRC64(c1,c2) ((c1).crc0 == (c2).crc0)
/* Constant table for CRC calculation */
extern const uint64 crc_table[];
extern const uint64 pg_crc64_table[];
#endif /* INT64_IS_BUSTED */
#endif /* PROVIDE_64BIT_CRC */
#endif /* PG_CRC_H */