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 (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to