Commit bb4a3963 authored by Robert Haas's avatar Robert Haas

hash: Support WAL consistency checking.

Kuntal Ghosh, reviewed by Amit Kapila and Ashutosh Sharma, with
a few tweaks by me.

Discussion: http://postgr.es/m/CAGz5QCJLERUn_zoO0eDv6_Y_d0o4tNTMPeR7ivTLBg4rUrJdwg@mail.gmail.com
parent 2609e91f
...@@ -8267,9 +8267,9 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1) ...@@ -8267,9 +8267,9 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
records, or to a comma-separated list of resource managers to check records, or to a comma-separated list of resource managers to check
only records originating from those resource managers. Currently, only records originating from those resource managers. Currently,
the supported resource managers are <literal>heap</>, the supported resource managers are <literal>heap</>,
<literal>heap2</>, <literal>btree</>, <literal>gin</>, <literal>heap2</>, <literal>btree</>, <literal>hash</>,
<literal>gist</>, <literal>sequence</>, <literal>spgist</>, <literal>gin</>, <literal>gist</>, <literal>sequence</>,
<literal>brin</>, and <literal>generic</>. Only <literal>spgist</>, <literal>brin</>, and <literal>generic</>. Only
superusers can change this setting. superusers can change this setting.
</para> </para>
</listitem> </listitem>
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
*/ */
#include "postgres.h" #include "postgres.h"
#include "access/bufmask.h"
#include "access/hash.h" #include "access/hash.h"
#include "access/hash_xlog.h" #include "access/hash_xlog.h"
#include "access/xlogutils.h" #include "access/xlogutils.h"
...@@ -961,3 +962,38 @@ hash_redo(XLogReaderState *record) ...@@ -961,3 +962,38 @@ hash_redo(XLogReaderState *record)
elog(PANIC, "hash_redo: unknown op code %u", info); elog(PANIC, "hash_redo: unknown op code %u", info);
} }
} }
/*
* Mask a hash page before performing consistency checks on it.
*/
void
hash_mask(char *pagedata, BlockNumber blkno)
{
Page page = (Page) pagedata;
HashPageOpaque opaque;
mask_page_lsn(page);
mask_page_hint_bits(page);
mask_unused_space(page);
opaque = (HashPageOpaque) PageGetSpecialPointer(page);
if (opaque->hasho_flag & LH_UNUSED_PAGE)
{
/*
* Mask everything on a UNUSED page.
*/
mask_page_content(page);
}
else if ((opaque->hasho_flag & LH_BUCKET_PAGE) ||
(opaque->hasho_flag & LH_OVERFLOW_PAGE))
{
/*
* In hash bucket and overflow pages, it is possible to modify the
* LP_FLAGS without emitting any WAL record. Hence, mask the line
* pointer flags. See hashgettuple() for details.
*/
mask_lp_flags(page);
}
}
...@@ -253,5 +253,6 @@ typedef struct xl_hash_init_bitmap_page ...@@ -253,5 +253,6 @@ typedef struct xl_hash_init_bitmap_page
extern void hash_redo(XLogReaderState *record); extern void hash_redo(XLogReaderState *record);
extern void hash_desc(StringInfo buf, XLogReaderState *record); extern void hash_desc(StringInfo buf, XLogReaderState *record);
extern const char *hash_identify(uint8 info); extern const char *hash_identify(uint8 info);
extern void hash_mask(char *pagedata, BlockNumber blkno);
#endif /* HASH_XLOG_H */ #endif /* HASH_XLOG_H */
...@@ -37,7 +37,7 @@ PG_RMGR(RM_STANDBY_ID, "Standby", standby_redo, standby_desc, standby_identify, ...@@ -37,7 +37,7 @@ PG_RMGR(RM_STANDBY_ID, "Standby", standby_redo, standby_desc, standby_identify,
PG_RMGR(RM_HEAP2_ID, "Heap2", heap2_redo, heap2_desc, heap2_identify, NULL, NULL, heap_mask) PG_RMGR(RM_HEAP2_ID, "Heap2", heap2_redo, heap2_desc, heap2_identify, NULL, NULL, heap_mask)
PG_RMGR(RM_HEAP_ID, "Heap", heap_redo, heap_desc, heap_identify, NULL, NULL, heap_mask) PG_RMGR(RM_HEAP_ID, "Heap", heap_redo, heap_desc, heap_identify, NULL, NULL, heap_mask)
PG_RMGR(RM_BTREE_ID, "Btree", btree_redo, btree_desc, btree_identify, NULL, NULL, btree_mask) PG_RMGR(RM_BTREE_ID, "Btree", btree_redo, btree_desc, btree_identify, NULL, NULL, btree_mask)
PG_RMGR(RM_HASH_ID, "Hash", hash_redo, hash_desc, hash_identify, NULL, NULL, NULL) PG_RMGR(RM_HASH_ID, "Hash", hash_redo, hash_desc, hash_identify, NULL, NULL, hash_mask)
PG_RMGR(RM_GIN_ID, "Gin", gin_redo, gin_desc, gin_identify, gin_xlog_startup, gin_xlog_cleanup, gin_mask) PG_RMGR(RM_GIN_ID, "Gin", gin_redo, gin_desc, gin_identify, gin_xlog_startup, gin_xlog_cleanup, gin_mask)
PG_RMGR(RM_GIST_ID, "Gist", gist_redo, gist_desc, gist_identify, gist_xlog_startup, gist_xlog_cleanup, gist_mask) PG_RMGR(RM_GIST_ID, "Gist", gist_redo, gist_desc, gist_identify, gist_xlog_startup, gist_xlog_cleanup, gist_mask)
PG_RMGR(RM_SEQ_ID, "Sequence", seq_redo, seq_desc, seq_identify, NULL, NULL, seq_mask) PG_RMGR(RM_SEQ_ID, "Sequence", seq_redo, seq_desc, seq_identify, NULL, NULL, seq_mask)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment