Zdenek Kotala wrote:
> Alvaro Herrera napsal(a):
>> Simon Riggs wrote:
>>
>>> But perhaps writing a single WAL record if you scan whole page and set
>>> all bits at once. Then it makes sense in some cases.
>>
>> So this is what I ended up doing; attached.
>
> Please, DO NOT MOVE position of page version in PageHeader structure!
Hmm. The only way I see we could do that is to modify the checksum
struct member to a predefined value before calculating the page's
checksum.
Ah, actually there's another alternative -- leave the checksum on its
current position (start of struct) and move other members below
pg_pagesize_version (leaning towards pd_tli and pd_flags). That'd leave
the page version in the same position.
(Hmm, maybe it's better to move pd_lower and pd_upper?)
> And PG_PAGE_LAYOUT_VERSION should be bump to 5.
Easily done; thanks for the reminder.
--
Alvaro Herrera http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.
*** src/include/storage/bufpage.h 14 Jul 2008 03:22:32 -0000 1.83
--- src/include/storage/bufpage.h 30 Oct 2008 15:05:24 -0000
***************
*** 17,22 ****
--- 17,23 ----
#include "access/xlogdefs.h"
#include "storage/item.h"
#include "storage/off.h"
+ #include "utils/pg_crc.h"
/*
* A postgres disk page is an abstraction layered on top of a postgres
***************
*** 87,92 ****
--- 88,94 ----
*
* space management information generic to any page
*
+ * pd_checksum - the checksum of the page
* pd_lsn - identifies xlog record for last change to this page.
* pd_tli - ditto.
* pd_flags - flag bits.
***************
*** 118,136 ****
* the constraint on pagesize mod 256 is not an important restriction.
* On the high end, we can only support pages up to 32KB because lp_off/lp_len
* are 15 bits.
*/
typedef struct PageHeaderData
{
! /* XXX LSN is member of *any* block, not only page-organized ones */
XLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog
* record for last change to this page */
- uint16 pd_tli; /* least significant bits of the TimeLineID
- * containing the LSN */
- uint16 pd_flags; /* flag bits, see below */
LocationIndex pd_lower; /* offset to start of free space */
LocationIndex pd_upper; /* offset to end of free space */
LocationIndex pd_special; /* offset to start of special space */
uint16 pd_pagesize_version;
TransactionId pd_prune_xid; /* oldest prunable XID, or zero if none */
ItemIdData pd_linp[1]; /* beginning of line pointer array */
} PageHeaderData;
--- 120,143 ----
* the constraint on pagesize mod 256 is not an important restriction.
* On the high end, we can only support pages up to 32KB because lp_off/lp_len
* are 15 bits.
+ *
+ * Note that pd_tli appears in a rather awkward position in the struct;
+ * this is because we moved it to accomodate pd_checksum without changing
+ * pg_pagesize_version's offset.
*/
typedef struct PageHeaderData
{
! /* XXX CRC & LSN are members of *any* block, not only page-organized ones */
! pg_crc32 pd_checksum; /* The block-level checksum */
XLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog
* record for last change to this page */
LocationIndex pd_lower; /* offset to start of free space */
LocationIndex pd_upper; /* offset to end of free space */
LocationIndex pd_special; /* offset to start of special space */
uint16 pd_pagesize_version;
+ uint16 pd_tli; /* least significant bits of the TimeLineID
+ * containing the LSN */
+ uint16 pd_flags; /* flag bits, see below */
TransactionId pd_prune_xid; /* oldest prunable XID, or zero if none */
ItemIdData pd_linp[1]; /* beginning of line pointer array */
} PageHeaderData;
***************
*** 148,159 ****
* PD_PAGE_FULL is set if an UPDATE doesn't find enough free space in the
* page for its new tuple version; this suggests that a prune is needed.
* Again, this is just a hint.
*/
#define PD_HAS_FREE_LINES 0x0001 /* are there any unused line pointers? */
#define PD_PAGE_FULL 0x0002 /* not enough free space for new
* tuple? */
! #define PD_VALID_FLAG_BITS 0x0003 /* OR of all valid pd_flags bits */
/*
* Page layout version number 0 is for pre-7.3 Postgres releases.
--- 155,172 ----
* PD_PAGE_FULL is set if an UPDATE doesn't find enough free space in the
* page for its new tuple version; this suggests that a prune is needed.
* Again, this is just a hint.
+ *
+ * PG_UNLOGGED_CHANGE indicates whether a process has set hint bits on the
+ * page. This is used to determine whether a WAL message needs to be emitted
+ * before writing the page to disk when page checksums are enabled.
*/
#define PD_HAS_FREE_LINES 0x0001 /* are there any unused line pointers? */
#define PD_PAGE_FULL 0x0002 /* not enough free space for new
* tuple? */
+ #define PD_UNLOGGED_CHANGE 0x0004 /* does the page have unlogged hint
+ bits? */
! #define PD_VALID_FLAG_BITS 0x0007 /* OR of all valid pd_flags bits */
/*
* Page layout version number 0 is for pre-7.3 Postgres releases.
***************
*** 163,170 ****
* Release 8.3 uses 4; it changed the HeapTupleHeader layout again, and
* added the pd_flags field (by stealing some bits from pd_tli),
* as well as adding the pd_prune_xid field (which enlarges the header).
*/
! #define PG_PAGE_LAYOUT_VERSION 4
/* ----------------------------------------------------------------
--- 176,186 ----
* Release 8.3 uses 4; it changed the HeapTupleHeader layout again, and
* added the pd_flags field (by stealing some bits from pd_tli),
* as well as adding the pd_prune_xid field (which enlarges the header).
+ * Release 8.4 uses 5; it added a checksum to the page header, and moved
+ * pd_tli and pd_flags so that the page version would keep the same
+ * offset.
*/
! #define PG_PAGE_LAYOUT_VERSION 5
/* ----------------------------------------------------------------
***************
*** 352,357 ****
--- 368,407 ----
#define PageClearPrunable(page) \
(((PageHeader) (page))->pd_prune_xid = InvalidTransactionId)
+ /* ----------------------------------------------------------------
+ * CRC support
+ * ----------------------------------------------------------------
+ */
+ #define PAGE_CHECKSUM_TYPE pg_crc32
+ #define SIZEOF_PAGE_CHECKSUM sizeof(PAGE_CHECKSUM_TYPE)
+ #define PAGE_INVALID_CHECKSUM 0xb79a6e9c
+
+ #define CalcPageChecksum(buffer, sum) \
+ do { \
+ INIT_CRC32(sum); \
+ COMP_CRC32(sum, &buffer[sizeof(pg_crc32)], BLCKSZ - sizeof(pg_crc32)); \
+ FIN_CRC32(sum); \
+ } while (0)
+
+ /* beware multiple evaluation of argument */
+ #define WritePageChecksum(buffer) \
+ do { \
+ PAGE_CHECKSUM_TYPE chksum; \
+ CalcPageChecksum(buffer, chksum); \
+ PageSetChecksum(buffer, chksum); \
+ } while (0)
+
+ #define PageGetChecksum(page) \
+ (((PageHeader) (page))->pd_checksum)
+ #define PageSetChecksum(page, checksum) \
+ (((PageHeader) (page))->pd_checksum = (checksum))
+
+ #define PageHasUnloggedChange(page) \
+ (((PageHeader) (page))->pd_flags & PD_UNLOGGED_CHANGE)
+ #define PageSetUnloggedChange(page) \
+ (((PageHeader) (page))->pd_flags |= PD_UNLOGGED_CHANGE)
+ #define PageClearUnloggedChange(page) \
+ (((PageHeader) (page))->pd_flags &= ~PD_UNLOGGED_CHANGE)
/* ----------------------------------------------------------------
* extern declarations
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers