PostgreSQL Source Code git master
Loading...
Searching...
No Matches
hash_xlog.c File Reference
#include "postgres.h"
#include "access/bufmask.h"
#include "access/hash.h"
#include "access/hash_xlog.h"
#include "access/xlogutils.h"
#include "storage/standby.h"
Include dependency graph for hash_xlog.c:

Go to the source code of this file.

Functions

static void hash_xlog_init_meta_page (XLogReaderState *record)
 
static void hash_xlog_init_bitmap_page (XLogReaderState *record)
 
static void hash_xlog_insert (XLogReaderState *record)
 
static void hash_xlog_add_ovfl_page (XLogReaderState *record)
 
static void hash_xlog_split_allocate_page (XLogReaderState *record)
 
static void hash_xlog_split_page (XLogReaderState *record)
 
static void hash_xlog_split_complete (XLogReaderState *record)
 
static void hash_xlog_move_page_contents (XLogReaderState *record)
 
static void hash_xlog_squeeze_page (XLogReaderState *record)
 
static void hash_xlog_delete (XLogReaderState *record)
 
static void hash_xlog_split_cleanup (XLogReaderState *record)
 
static void hash_xlog_update_meta_page (XLogReaderState *record)
 
static void hash_xlog_vacuum_one_page (XLogReaderState *record)
 
void hash_redo (XLogReaderState *record)
 
void hash_mask (char *pagedata, BlockNumber blkno)
 

Function Documentation

◆ hash_mask()

void hash_mask ( char pagedata,
BlockNumber  blkno 
)

Definition at line 1094 of file hash_xlog.c.

1095{
1096 Page page = (Page) pagedata;
1097 HashPageOpaque opaque;
1098 int pagetype;
1099
1101
1102 mask_page_hint_bits(page);
1103 mask_unused_space(page);
1104
1105 opaque = HashPageGetOpaque(page);
1106
1107 pagetype = opaque->hasho_flag & LH_PAGE_TYPE;
1108 if (pagetype == LH_UNUSED_PAGE)
1109 {
1110 /*
1111 * Mask everything on a UNUSED page.
1112 */
1113 mask_page_content(page);
1114 }
1115 else if (pagetype == LH_BUCKET_PAGE ||
1117 {
1118 /*
1119 * In hash bucket and overflow pages, it is possible to modify the
1120 * LP_FLAGS without emitting any WAL record. Hence, mask the line
1121 * pointer flags. See hashgettuple(), _hash_kill_items() for details.
1122 */
1123 mask_lp_flags(page);
1124 }
1125
1126 /*
1127 * It is possible that the hint bit LH_PAGE_HAS_DEAD_TUPLES may remain
1128 * unlogged. So, mask it. See _hash_kill_items() for details.
1129 */
1131}
void mask_lp_flags(Page page)
Definition bufmask.c:94
void mask_page_content(Page page)
Definition bufmask.c:118
void mask_page_lsn_and_checksum(Page page)
Definition bufmask.c:31
void mask_unused_space(Page page)
Definition bufmask.c:70
void mask_page_hint_bits(Page page)
Definition bufmask.c:46
PageData * Page
Definition bufpage.h:81
#define HashPageGetOpaque(page)
Definition hash.h:88
#define LH_BUCKET_PAGE
Definition hash.h:55
#define LH_UNUSED_PAGE
Definition hash.h:53
#define LH_PAGE_TYPE
Definition hash.h:63
#define LH_OVERFLOW_PAGE
Definition hash.h:54
static int fb(int x)
uint16 hasho_flag
Definition hash.h:82

References fb(), HashPageOpaqueData::hasho_flag, HashPageGetOpaque, LH_BUCKET_PAGE, LH_OVERFLOW_PAGE, LH_PAGE_TYPE, LH_UNUSED_PAGE, mask_lp_flags(), mask_page_content(), mask_page_hint_bits(), mask_page_lsn_and_checksum(), and mask_unused_space().

◆ hash_redo()

void hash_redo ( XLogReaderState record)

Definition at line 1040 of file hash_xlog.c.

1041{
1042 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1043
1044 switch (info)
1045 {
1048 break;
1051 break;
1052 case XLOG_HASH_INSERT:
1053 hash_xlog_insert(record);
1054 break;
1057 break;
1060 break;
1062 hash_xlog_split_page(record);
1063 break;
1066 break;
1069 break;
1071 hash_xlog_squeeze_page(record);
1072 break;
1073 case XLOG_HASH_DELETE:
1074 hash_xlog_delete(record);
1075 break;
1078 break;
1081 break;
1084 break;
1085 default:
1086 elog(PANIC, "hash_redo: unknown op code %u", info);
1087 }
1088}
uint8_t uint8
Definition c.h:678
#define PANIC
Definition elog.h:44
#define elog(elevel,...)
Definition elog.h:228
static void hash_xlog_split_cleanup(XLogReaderState *record)
Definition hash_xlog.c:912
static void hash_xlog_add_ovfl_page(XLogReaderState *record)
Definition hash_xlog.c:149
static void hash_xlog_split_page(XLogReaderState *record)
Definition hash_xlog.c:403
static void hash_xlog_init_meta_page(XLogReaderState *record)
Definition hash_xlog.c:27
static void hash_xlog_split_complete(XLogReaderState *record)
Definition hash_xlog.c:417
static void hash_xlog_update_meta_page(XLogReaderState *record)
Definition hash_xlog.c:937
static void hash_xlog_vacuum_one_page(XLogReaderState *record)
Definition hash_xlog.c:964
static void hash_xlog_squeeze_page(XLogReaderState *record)
Definition hash_xlog.c:601
static void hash_xlog_insert(XLogReaderState *record)
Definition hash_xlog.c:102
static void hash_xlog_move_page_contents(XLogReaderState *record)
Definition hash_xlog.c:476
static void hash_xlog_split_allocate_page(XLogReaderState *record)
Definition hash_xlog.c:287
static void hash_xlog_delete(XLogReaderState *record)
Definition hash_xlog.c:834
static void hash_xlog_init_bitmap_page(XLogReaderState *record)
Definition hash_xlog.c:53
#define XLOG_HASH_INIT_BITMAP_PAGE
Definition hash_xlog.h:28
#define XLOG_HASH_SQUEEZE_PAGE
Definition hash_xlog.h:35
#define XLOG_HASH_SPLIT_CLEANUP
Definition hash_xlog.h:37
#define XLOG_HASH_ADD_OVFL_PAGE
Definition hash_xlog.h:30
#define XLOG_HASH_UPDATE_META_PAGE
Definition hash_xlog.h:38
#define XLOG_HASH_INSERT
Definition hash_xlog.h:29
#define XLOG_HASH_SPLIT_ALLOCATE_PAGE
Definition hash_xlog.h:31
#define XLOG_HASH_SPLIT_PAGE
Definition hash_xlog.h:32
#define XLOG_HASH_INIT_META_PAGE
Definition hash_xlog.h:27
#define XLOG_HASH_DELETE
Definition hash_xlog.h:36
#define XLOG_HASH_SPLIT_COMPLETE
Definition hash_xlog.h:33
#define XLOG_HASH_MOVE_PAGE_CONTENTS
Definition hash_xlog.h:34
#define XLOG_HASH_VACUUM_ONE_PAGE
Definition hash_xlog.h:40
#define XLogRecGetInfo(decoder)
Definition xlogreader.h:410

References elog, fb(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_cleanup(), hash_xlog_split_complete(), hash_xlog_split_page(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), PANIC, XLOG_HASH_ADD_OVFL_PAGE, XLOG_HASH_DELETE, XLOG_HASH_INIT_BITMAP_PAGE, XLOG_HASH_INIT_META_PAGE, XLOG_HASH_INSERT, XLOG_HASH_MOVE_PAGE_CONTENTS, XLOG_HASH_SPLIT_ALLOCATE_PAGE, XLOG_HASH_SPLIT_CLEANUP, XLOG_HASH_SPLIT_COMPLETE, XLOG_HASH_SPLIT_PAGE, XLOG_HASH_SQUEEZE_PAGE, XLOG_HASH_UPDATE_META_PAGE, XLOG_HASH_VACUUM_ONE_PAGE, and XLogRecGetInfo.

◆ hash_xlog_add_ovfl_page()

static void hash_xlog_add_ovfl_page ( XLogReaderState record)
static

Definition at line 149 of file hash_xlog.c.

150{
151 XLogRecPtr lsn = record->EndRecPtr;
156 BlockNumber leftblk;
157 BlockNumber rightblk;
162 char *data;
164 bool new_bmpage = false;
165
166 XLogRecGetBlockTag(record, 0, NULL, NULL, &rightblk);
167 XLogRecGetBlockTag(record, 1, NULL, NULL, &leftblk);
168
169 ovflbuf = XLogInitBufferForRedo(record, 0);
171
172 data = XLogRecGetBlockData(record, 0, &datalen);
173 num_bucket = (uint32 *) data;
174 Assert(datalen == sizeof(uint32));
176 true);
177 /* update backlink */
180 ovflopaque->hasho_prevblkno = leftblk;
181
182 PageSetLSN(ovflpage, lsn);
184
185 if (XLogReadBufferForRedo(record, 1, &leftbuf) == BLK_NEEDS_REDO)
186 {
189
192 leftopaque->hasho_nextblkno = rightblk;
193
194 PageSetLSN(leftpage, lsn);
196 }
197
201
202 /*
203 * Note: in normal operation, we'd update the bitmap and meta page while
204 * still holding lock on the overflow pages. But during replay it's not
205 * necessary to hold those locks, since no other index updates can be
206 * happening concurrently.
207 */
208 if (XLogRecHasBlockRef(record, 2))
209 {
211
213 {
215 uint32 *freep = NULL;
217
219
220 data = XLogRecGetBlockData(record, 2, &datalen);
222
224
225 PageSetLSN(mappage, lsn);
227 }
230 }
231
232 if (XLogRecHasBlockRef(record, 3))
233 {
235
236 newmapbuf = XLogInitBufferForRedo(record, 3);
237
238 _hash_initbitmapbuffer(newmapbuf, xlrec->bmsize, true);
239
240 new_bmpage = true;
242
245
247 }
248
249 if (XLogReadBufferForRedo(record, 4, &metabuf) == BLK_NEEDS_REDO)
250 {
251 HashMetaPage metap;
252 Page page;
254
255 data = XLogRecGetBlockData(record, 4, &datalen);
257
258 page = BufferGetPage(metabuf);
259 metap = HashPageGetMeta(page);
261
262 if (!xlrec->bmpage_found)
263 {
264 metap->hashm_spares[metap->hashm_ovflpoint]++;
265
266 if (new_bmpage)
267 {
269
270 metap->hashm_mapp[metap->hashm_nmaps] = newmapblk;
271 metap->hashm_nmaps++;
272 metap->hashm_spares[metap->hashm_ovflpoint]++;
273 }
274 }
275
276 PageSetLSN(page, lsn);
278 }
281}
uint32 BlockNumber
Definition block.h:31
#define InvalidBlockNumber
Definition block.h:33
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition block.h:71
#define SETBIT(x, i)
Definition blutils.c:29
int Buffer
Definition buf.h:23
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition bufmgr.c:4455
void UnlockReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5612
void MarkBufferDirty(Buffer buffer)
Definition bufmgr.c:3156
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:468
static bool BufferIsValid(Buffer bufnum)
Definition bufmgr.h:419
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition bufpage.h:416
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:305
#define Assert(condition)
Definition c.h:999
uint32_t uint32
Definition c.h:680
size_t Size
Definition c.h:745
#define HashPageGetBitmap(page)
Definition hash.h:316
#define HashPageGetMeta(page)
Definition hash.h:323
void _hash_initbitmapbuffer(Buffer buf, uint16 bmsize, bool initpage)
Definition hashovfl.c:778
void _hash_initbuf(Buffer buf, uint32 max_bucket, uint32 num_bucket, uint32 flag, bool initpage)
Definition hashpage.c:157
const void * data
BlockNumber hashm_mapp[HASH_MAX_BITMAPS]
Definition hash.h:264
uint32 hashm_spares[HASH_MAX_SPLITPOINTS]
Definition hash.h:262
uint32 hashm_firstfree
Definition hash.h:259
uint32 hashm_ovflpoint
Definition hash.h:257
uint32 hashm_nmaps
Definition hash.h:260
XLogRecPtr EndRecPtr
Definition xlogreader.h:206
uint64 XLogRecPtr
Definition xlogdefs.h:21
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
void XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum)
#define XLogRecGetData(decoder)
Definition xlogreader.h:415
#define XLogRecHasBlockRef(decoder, block_id)
Definition xlogreader.h:420
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition xlogutils.c:303
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition xlogutils.c:315
@ BLK_NEEDS_REDO
Definition xlogutils.h:74

References _hash_initbitmapbuffer(), _hash_initbuf(), Assert, BLK_NEEDS_REDO, BlockNumberIsValid(), BufferGetBlockNumber(), BufferGetPage(), BufferIsValid(), data, XLogReaderState::EndRecPtr, fb(), HashMetaPageData::hashm_firstfree, HashMetaPageData::hashm_mapp, HashMetaPageData::hashm_nmaps, HashMetaPageData::hashm_ovflpoint, HashMetaPageData::hashm_spares, HashPageGetBitmap, HashPageGetMeta, HashPageGetOpaque, InvalidBlockNumber, LH_OVERFLOW_PAGE, MarkBufferDirty(), PageSetLSN(), PG_USED_FOR_ASSERTS_ONLY, SETBIT, UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogReadBufferForRedo(), XLogRecGetBlockData(), XLogRecGetBlockTag(), XLogRecGetData, and XLogRecHasBlockRef.

Referenced by hash_redo().

◆ hash_xlog_delete()

static void hash_xlog_delete ( XLogReaderState record)
static

Definition at line 834 of file hash_xlog.c.

835{
836 XLogRecPtr lsn = record->EndRecPtr;
840 Page page;
842
843 /*
844 * Ensure we have a cleanup lock on primary bucket page before we start
845 * with the actual replay operation. This is to ensure that neither a
846 * scan can start nor a scan can be already-in-progress during the replay
847 * of this operation. If we allow scans during this operation, then they
848 * can miss some records or show the same record multiple times.
849 */
850 if (xldata->is_primary_bucket_page)
852 else
853 {
854 /*
855 * we don't care for return value as the purpose of reading bucketbuf
856 * is to ensure a cleanup lock on primary bucket page.
857 */
859
861 }
862
863 /* replay the record for deleting entries in bucket page */
864 if (action == BLK_NEEDS_REDO)
865 {
866 char *ptr;
867 Size len;
868
869 ptr = XLogRecGetBlockData(record, 1, &len);
870
871 page = BufferGetPage(deletebuf);
872
873 if (len > 0)
874 {
875 OffsetNumber *unused;
877
878 unused = (OffsetNumber *) ptr;
879 unend = (OffsetNumber *) (ptr + len);
880
881 if ((unend - unused) > 0)
882 PageIndexMultiDelete(page, unused, unend - unused);
883 }
884
885 /*
886 * Mark the page as not containing any LP_DEAD items only if
887 * clear_dead_marking flag is set to true. See comments in
888 * hashbucketcleanup() for details.
889 */
890 if (xldata->clear_dead_marking)
891 {
893
896 }
897
898 PageSetLSN(page, lsn);
900 }
903
906}
#define InvalidBuffer
Definition buf.h:25
@ RBM_NORMAL
Definition bufmgr.h:46
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition bufpage.c:1170
uint16 OffsetNumber
Definition off.h:24
const void size_t len
XLogRedoAction XLogReadBufferForRedoExtended(XLogReaderState *record, uint8 block_id, ReadBufferMode mode, bool get_cleanup_lock, Buffer *buf)
Definition xlogutils.c:362
XLogRedoAction
Definition xlogutils.h:73

References BLK_NEEDS_REDO, BufferGetPage(), BufferIsValid(), XLogReaderState::EndRecPtr, fb(), HashPageGetOpaque, InvalidBuffer, len, MarkBufferDirty(), PageIndexMultiDelete(), PageSetLSN(), RBM_NORMAL, UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogReadBufferForRedoExtended(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by hash_redo().

◆ hash_xlog_init_bitmap_page()

static void hash_xlog_init_bitmap_page ( XLogReaderState record)
static

Definition at line 53 of file hash_xlog.c.

54{
55 XLogRecPtr lsn = record->EndRecPtr;
58 Page page;
59 HashMetaPage metap;
61
63
64 /*
65 * Initialize bitmap page
66 */
73
74 /* add the new bitmap page to the metapage's list of bitmaps */
76 {
77 /*
78 * Note: in normal operation, we'd update the metapage while still
79 * holding lock on the bitmap page. But during replay it's not
80 * necessary to hold that lock, since nobody can see it yet; the
81 * creating transaction hasn't yet committed.
82 */
83 page = BufferGetPage(metabuf);
84 metap = HashPageGetMeta(page);
85
86 num_buckets = metap->hashm_maxbucket + 1;
87 metap->hashm_mapp[metap->hashm_nmaps] = num_buckets + 1;
88 metap->hashm_nmaps++;
89
90 PageSetLSN(page, lsn);
93 }
96}
uint32 hashm_maxbucket
Definition hash.h:254
void XLogFlushBufferForRedoIfInit(XLogReaderState *record, uint8 block_id, Buffer buffer)
Definition xlogutils.c:334

References _hash_initbitmapbuffer(), BLK_NEEDS_REDO, BufferGetPage(), BufferIsValid(), XLogReaderState::EndRecPtr, fb(), HashMetaPageData::hashm_mapp, HashMetaPageData::hashm_maxbucket, HashMetaPageData::hashm_nmaps, HashPageGetMeta, MarkBufferDirty(), PageSetLSN(), UnlockReleaseBuffer(), XLogFlushBufferForRedoIfInit(), XLogInitBufferForRedo(), XLogReadBufferForRedo(), and XLogRecGetData.

Referenced by hash_redo().

◆ hash_xlog_init_meta_page()

static void hash_xlog_init_meta_page ( XLogReaderState record)
static

Definition at line 27 of file hash_xlog.c.

28{
29 XLogRecPtr lsn = record->EndRecPtr;
30 Page page;
32
34
35 /* create the index' metapage */
36 metabuf = XLogInitBufferForRedo(record, 0);
38 _hash_init_metabuffer(metabuf, xlrec->num_tuples, xlrec->procid,
39 xlrec->ffactor, true);
40 page = BufferGetPage(metabuf);
41 PageSetLSN(page, lsn);
44
45 /* all done */
47}
void _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid, uint16 ffactor, bool initpage)
Definition hashpage.c:498

References _hash_init_metabuffer(), Assert, BufferGetPage(), BufferIsValid(), XLogReaderState::EndRecPtr, fb(), MarkBufferDirty(), PageSetLSN(), UnlockReleaseBuffer(), XLogFlushBufferForRedoIfInit(), XLogInitBufferForRedo(), and XLogRecGetData.

Referenced by hash_redo().

◆ hash_xlog_insert()

static void hash_xlog_insert ( XLogReaderState record)
static

Definition at line 102 of file hash_xlog.c.

103{
104 HashMetaPage metap;
105 XLogRecPtr lsn = record->EndRecPtr;
107 Buffer buffer;
108 Page page;
109
110 if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
111 {
112 Size datalen;
113 char *datapos = XLogRecGetBlockData(record, 0, &datalen);
114
115 page = BufferGetPage(buffer);
116
117 if (PageAddItem(page, datapos, datalen, xlrec->offnum, false, false) == InvalidOffsetNumber)
118 elog(PANIC, "hash_xlog_insert: failed to add item");
119
120 PageSetLSN(page, lsn);
121 MarkBufferDirty(buffer);
122 }
123 if (BufferIsValid(buffer))
124 UnlockReleaseBuffer(buffer);
125
126 if (XLogReadBufferForRedo(record, 1, &buffer) == BLK_NEEDS_REDO)
127 {
128 /*
129 * Note: in normal operation, we'd update the metapage while still
130 * holding lock on the page we inserted into. But during replay it's
131 * not necessary to hold that lock, since no other index updates can
132 * be happening concurrently.
133 */
134 page = BufferGetPage(buffer);
135 metap = HashPageGetMeta(page);
136 metap->hashm_ntuples += 1;
137
138 PageSetLSN(page, lsn);
139 MarkBufferDirty(buffer);
140 }
141 if (BufferIsValid(buffer))
142 UnlockReleaseBuffer(buffer);
143}
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition bufpage.h:504
#define InvalidOffsetNumber
Definition off.h:26
double hashm_ntuples
Definition hash.h:248

References BLK_NEEDS_REDO, BufferGetPage(), BufferIsValid(), elog, XLogReaderState::EndRecPtr, fb(), HashMetaPageData::hashm_ntuples, HashPageGetMeta, InvalidOffsetNumber, MarkBufferDirty(), PageAddItem, PageSetLSN(), PANIC, UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by hash_redo().

◆ hash_xlog_move_page_contents()

static void hash_xlog_move_page_contents ( XLogReaderState record)
static

Definition at line 476 of file hash_xlog.c.

477{
478 XLogRecPtr lsn = record->EndRecPtr;
484
485 /*
486 * Ensure we have a cleanup lock on primary bucket page before we start
487 * with the actual replay operation. This is to ensure that neither a
488 * scan can start nor a scan can be already-in-progress during the replay
489 * of this operation. If we allow scans during this operation, then they
490 * can miss some records or show the same record multiple times.
491 */
492 if (xldata->is_prim_bucket_same_wrt)
494 else
495 {
496 /*
497 * we don't care for return value as the purpose of reading bucketbuf
498 * is to ensure a cleanup lock on primary bucket page.
499 */
501
503 }
504
505 /* replay the record for adding entries in overflow buffer */
506 if (action == BLK_NEEDS_REDO)
507 {
509 char *begin;
510 char *data;
511 Size datalen;
512 uint16 ninserted = 0;
513
514 data = begin = XLogRecGetBlockData(record, 1, &datalen);
515
517
518 if (xldata->ntups > 0)
519 {
521
522 data += sizeof(OffsetNumber) * xldata->ntups;
523
524 while (data - begin < datalen)
525 {
526 IndexTuple itup = (IndexTuple) data;
527 Size itemsz;
528 OffsetNumber l;
529
530 itemsz = IndexTupleSize(itup);
531 itemsz = MAXALIGN(itemsz);
532
533 data += itemsz;
534
535 l = PageAddItem(writepage, itup, itemsz, towrite[ninserted], false, false);
536 if (l == InvalidOffsetNumber)
537 elog(ERROR, "hash_xlog_move_page_contents: failed to add item to hash index page, size %zu bytes", itemsz);
538
539 ninserted++;
540 }
541 }
542
543 /*
544 * number of tuples inserted must be same as requested in REDO record.
545 */
546 Assert(ninserted == xldata->ntups);
547
548 PageSetLSN(writepage, lsn);
550 }
551
552 /* replay the record for deleting entries from overflow buffer */
554 {
555 Page page;
556 char *ptr;
557 Size len;
558
559 ptr = XLogRecGetBlockData(record, 2, &len);
560
561 page = BufferGetPage(deletebuf);
562
563 if (len > 0)
564 {
565 OffsetNumber *unused;
567
568 unused = (OffsetNumber *) ptr;
569 unend = (OffsetNumber *) (ptr + len);
570
571 if ((unend - unused) > 0)
572 PageIndexMultiDelete(page, unused, unend - unused);
573 }
574
575 PageSetLSN(page, lsn);
577 }
578
579 /*
580 * Replay is complete, now we can release the buffers. We release locks at
581 * end of replay operation to ensure that we hold lock on primary bucket
582 * page till end of operation. We can optimize by releasing the lock on
583 * write buffer as soon as the operation for same is complete, if it is
584 * not same as primary bucket page, but that doesn't seem to be worth
585 * complicating the code.
586 */
589
592
595}
#define MAXALIGN(LEN)
Definition c.h:952
uint16_t uint16
Definition c.h:679
#define ERROR
Definition elog.h:40
IndexTupleData * IndexTuple
Definition itup.h:53
static Size IndexTupleSize(const IndexTupleData *itup)
Definition itup.h:71

References Assert, BLK_NEEDS_REDO, BufferGetPage(), BufferIsValid(), data, elog, XLogReaderState::EndRecPtr, ERROR, fb(), IndexTupleSize(), InvalidBuffer, InvalidOffsetNumber, len, MarkBufferDirty(), MAXALIGN, PageAddItem, PageIndexMultiDelete(), PageSetLSN(), RBM_NORMAL, UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogReadBufferForRedoExtended(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by hash_redo().

◆ hash_xlog_split_allocate_page()

static void hash_xlog_split_allocate_page ( XLogReaderState record)
static

Definition at line 287 of file hash_xlog.c.

288{
289 XLogRecPtr lsn = record->EndRecPtr;
295
296 /*
297 * To be consistent with normal operation, here we take cleanup locks on
298 * both the old and new buckets even though there can't be any concurrent
299 * inserts.
300 */
301
302 /* replay the record for old bucket */
304
305 /*
306 * Note that we still update the page even if it was restored from a full
307 * page image, because the special space is not included in the image.
308 */
309 if (action == BLK_NEEDS_REDO || action == BLK_RESTORED)
310 {
313
316
317 oldopaque->hasho_flag = xlrec->old_bucket_flag;
318 oldopaque->hasho_prevblkno = xlrec->new_bucket;
319
320 PageSetLSN(oldpage, lsn);
322 }
323
324 /* replay the record for new bucket */
326 &newbuf);
327 _hash_initbuf(newbuf, xlrec->new_bucket, xlrec->new_bucket,
328 xlrec->new_bucket_flag, true);
331
332 /*
333 * We can release the lock on old bucket early as well but doing here to
334 * consistent with normal operation.
335 */
340
341 /*
342 * Note: in normal operation, we'd update the meta page while still
343 * holding lock on the old and new bucket pages. But during replay it's
344 * not necessary to hold those locks, since no other bucket splits can be
345 * happening concurrently.
346 */
347
348 /* replay the record for metapage changes */
349 if (XLogReadBufferForRedo(record, 2, &metabuf) == BLK_NEEDS_REDO)
350 {
351 Page page;
352 HashMetaPage metap;
353 Size datalen;
354 char *data;
355 uint32 *uidata;
356 int uidatacount;
357
358 page = BufferGetPage(metabuf);
359 metap = HashPageGetMeta(page);
360 metap->hashm_maxbucket = xlrec->new_bucket;
361
362 data = XLogRecGetBlockData(record, 2, &datalen);
363
364 /*
365 * This cast is ok because XLogRecGetBlockData() returns a MAXALIGNed
366 * buffer.
367 */
368 uidata = (uint32 *) data;
369 uidatacount = 0;
370
372 {
375
376 /* update metapage */
377 metap->hashm_lowmask = lowmask;
378 metap->hashm_highmask = highmask;
379 }
380
382 {
385
386 /* update metapage */
387 metap->hashm_ovflpoint = ovflpoint;
389 }
390
393 }
394
397}
@ RBM_ZERO_AND_CLEANUP_LOCK
Definition bufmgr.h:49
#define XLH_SPLIT_META_UPDATE_SPLITPOINT
Definition hash_xlog.h:46
#define XLH_SPLIT_META_UPDATE_MASKS
Definition hash_xlog.h:45
uint32 hashm_lowmask
Definition hash.h:256
uint32 hashm_highmask
Definition hash.h:255
@ BLK_RESTORED
Definition xlogutils.h:76

References _hash_initbuf(), BLK_NEEDS_REDO, BLK_RESTORED, BufferGetPage(), BufferIsValid(), data, XLogReaderState::EndRecPtr, fb(), HashMetaPageData::hashm_highmask, HashMetaPageData::hashm_lowmask, HashMetaPageData::hashm_maxbucket, HashMetaPageData::hashm_ovflpoint, HashMetaPageData::hashm_spares, HashPageGetMeta, HashPageGetOpaque, MarkBufferDirty(), PageSetLSN(), RBM_NORMAL, RBM_ZERO_AND_CLEANUP_LOCK, UnlockReleaseBuffer(), XLH_SPLIT_META_UPDATE_MASKS, XLH_SPLIT_META_UPDATE_SPLITPOINT, XLogReadBufferForRedo(), XLogReadBufferForRedoExtended(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by hash_redo().

◆ hash_xlog_split_cleanup()

static void hash_xlog_split_cleanup ( XLogReaderState record)
static

Definition at line 912 of file hash_xlog.c.

913{
914 XLogRecPtr lsn = record->EndRecPtr;
915 Buffer buffer;
916 Page page;
917
918 if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
919 {
921
922 page = BufferGetPage(buffer);
923
926 PageSetLSN(page, lsn);
927 MarkBufferDirty(buffer);
928 }
929 if (BufferIsValid(buffer))
930 UnlockReleaseBuffer(buffer);
931}

References BLK_NEEDS_REDO, BufferGetPage(), BufferIsValid(), XLogReaderState::EndRecPtr, fb(), HashPageGetOpaque, MarkBufferDirty(), PageSetLSN(), UnlockReleaseBuffer(), and XLogReadBufferForRedo().

Referenced by hash_redo().

◆ hash_xlog_split_complete()

static void hash_xlog_split_complete ( XLogReaderState record)
static

Definition at line 417 of file hash_xlog.c.

418{
419 XLogRecPtr lsn = record->EndRecPtr;
424
425 /* replay the record for old bucket */
426 action = XLogReadBufferForRedo(record, 0, &oldbuf);
427
428 /*
429 * Note that we still update the page even if it was restored from a full
430 * page image, because the bucket flag is not included in the image.
431 */
432 if (action == BLK_NEEDS_REDO || action == BLK_RESTORED)
433 {
436
439
440 oldopaque->hasho_flag = xlrec->old_bucket_flag;
441
442 PageSetLSN(oldpage, lsn);
444 }
447
448 /* replay the record for new bucket */
449 action = XLogReadBufferForRedo(record, 1, &newbuf);
450
451 /*
452 * Note that we still update the page even if it was restored from a full
453 * page image, because the bucket flag is not included in the image.
454 */
455 if (action == BLK_NEEDS_REDO || action == BLK_RESTORED)
456 {
459
462
463 nopaque->hasho_flag = xlrec->new_bucket_flag;
464
465 PageSetLSN(newpage, lsn);
467 }
470}

References BLK_NEEDS_REDO, BLK_RESTORED, BufferGetPage(), BufferIsValid(), XLogReaderState::EndRecPtr, fb(), HashPageGetOpaque, MarkBufferDirty(), PageSetLSN(), UnlockReleaseBuffer(), XLogReadBufferForRedo(), and XLogRecGetData.

Referenced by hash_redo().

◆ hash_xlog_split_page()

static void hash_xlog_split_page ( XLogReaderState record)
static

Definition at line 403 of file hash_xlog.c.

404{
405 Buffer buf;
406
407 if (XLogReadBufferForRedo(record, 0, &buf) != BLK_RESTORED)
408 elog(ERROR, "Hash split record did not contain a full-page image");
409
411}
static char buf[DEFAULT_XLOG_SEG_SIZE]

References BLK_RESTORED, buf, elog, ERROR, UnlockReleaseBuffer(), and XLogReadBufferForRedo().

Referenced by hash_redo().

◆ hash_xlog_squeeze_page()

static void hash_xlog_squeeze_page ( XLogReaderState record)
static

Definition at line 601 of file hash_xlog.c.

602{
603 XLogRecPtr lsn = record->EndRecPtr;
611
612 /*
613 * Ensure we have a cleanup lock on primary bucket page before we start
614 * with the actual replay operation. This is to ensure that neither a
615 * scan can start nor a scan can be already-in-progress during the replay
616 * of this operation. If we allow scans during this operation, then they
617 * can miss some records or show the same record multiple times.
618 */
619 if (xldata->is_prim_bucket_same_wrt)
621 else
622 {
623 /*
624 * we don't care for return value as the purpose of reading bucketbuf
625 * is to ensure a cleanup lock on primary bucket page.
626 */
628
629 if (xldata->ntups > 0 || xldata->is_prev_bucket_same_wrt)
631 else
633 }
634
635 /* replay the record for adding entries in overflow buffer */
636 if (action == BLK_NEEDS_REDO)
637 {
639 char *begin;
640 char *data;
641 Size datalen;
642 uint16 ninserted = 0;
643 bool mod_wbuf = false;
644
645 data = begin = XLogRecGetBlockData(record, 1, &datalen);
646
648
649 if (xldata->ntups > 0)
650 {
652
653 data += sizeof(OffsetNumber) * xldata->ntups;
654
655 while (data - begin < datalen)
656 {
657 IndexTuple itup = (IndexTuple) data;
658 Size itemsz;
659 OffsetNumber l;
660
661 itemsz = IndexTupleSize(itup);
662 itemsz = MAXALIGN(itemsz);
663
664 data += itemsz;
665
666 l = PageAddItem(writepage, itup, itemsz, towrite[ninserted], false, false);
667 if (l == InvalidOffsetNumber)
668 elog(ERROR, "hash_xlog_squeeze_page: failed to add item to hash index page, size %zu bytes", itemsz);
669
670 ninserted++;
671 }
672
673 mod_wbuf = true;
674 }
675 else
676 {
677 /*
678 * Ensure that the required flags are set when there are no
679 * tuples. See _hash_freeovflpage().
680 */
681 Assert(xldata->is_prim_bucket_same_wrt ||
682 xldata->is_prev_bucket_same_wrt);
683 }
684
685 /*
686 * number of tuples inserted must be same as requested in REDO record.
687 */
688 Assert(ninserted == xldata->ntups);
689
690 /*
691 * if the page on which are adding tuples is a page previous to freed
692 * overflow page, then update its nextblkno.
693 */
694 if (xldata->is_prev_bucket_same_wrt)
695 {
697
698 writeopaque->hasho_nextblkno = xldata->nextblkno;
699 mod_wbuf = true;
700 }
701
702 /* Set LSN and mark writebuf dirty iff it is modified */
703 if (mod_wbuf)
704 {
705 PageSetLSN(writepage, lsn);
707 }
708 }
709
710 /* replay the record for initializing overflow buffer */
711 if (XLogReadBufferForRedo(record, 2, &ovflbuf) == BLK_NEEDS_REDO)
712 {
715
717
719
721
722 ovflopaque->hasho_prevblkno = InvalidBlockNumber;
723 ovflopaque->hasho_nextblkno = InvalidBlockNumber;
724 ovflopaque->hasho_bucket = InvalidBucket;
725 ovflopaque->hasho_flag = LH_UNUSED_PAGE;
726 ovflopaque->hasho_page_id = HASHO_PAGE_ID;
727
728 PageSetLSN(ovflpage, lsn);
730 }
733
734 /* replay the record for page previous to the freed overflow page */
735 if (!xldata->is_prev_bucket_same_wrt &&
737 {
740
741 prevopaque->hasho_nextblkno = xldata->nextblkno;
742
743 PageSetLSN(prevpage, lsn);
745 }
748
749 /* replay the record for page next to the freed overflow page */
750 if (XLogRecHasBlockRef(record, 4))
751 {
753
754 if (XLogReadBufferForRedo(record, 4, &nextbuf) == BLK_NEEDS_REDO)
755 {
758
759 nextopaque->hasho_prevblkno = xldata->prevblkno;
760
761 PageSetLSN(nextpage, lsn);
763 }
766 }
767
770
773
774 /*
775 * Note: in normal operation, we'd update the bitmap and meta page while
776 * still holding lock on the primary bucket page and overflow pages. But
777 * during replay it's not necessary to hold those locks, since no other
778 * index updates can be happening concurrently.
779 */
780 /* replay the record for bitmap page */
781 if (XLogReadBufferForRedo(record, 5, &mapbuf) == BLK_NEEDS_REDO)
782 {
784 uint32 *freep = NULL;
785 char *data;
787 Size datalen;
788
790
791 data = XLogRecGetBlockData(record, 5, &datalen);
793
795
796 PageSetLSN(mappage, lsn);
798 }
801
802 /* replay the record for meta page */
803 if (XLogRecHasBlockRef(record, 6))
804 {
806
807 if (XLogReadBufferForRedo(record, 6, &metabuf) == BLK_NEEDS_REDO)
808 {
809 HashMetaPage metap;
810 Page page;
811 char *data;
813 Size datalen;
814
815 data = XLogRecGetBlockData(record, 6, &datalen);
817
818 page = BufferGetPage(metabuf);
819 metap = HashPageGetMeta(page);
821
822 PageSetLSN(page, lsn);
824 }
827 }
828}
#define CLRBIT(x, i)
Definition blutils.c:28
static Size BufferGetPageSize(Buffer buffer)
Definition bufmgr.h:457
#define HASHO_PAGE_ID
Definition hash.h:101
#define InvalidBucket
Definition hash.h:37
void _hash_pageinit(Page page, Size size)
Definition hashpage.c:596
@ BLK_NOTFOUND
Definition xlogutils.h:77

References _hash_pageinit(), Assert, BLK_NEEDS_REDO, BLK_NOTFOUND, BufferGetPage(), BufferGetPageSize(), BufferIsValid(), CLRBIT, data, elog, XLogReaderState::EndRecPtr, ERROR, fb(), HashMetaPageData::hashm_firstfree, HASHO_PAGE_ID, HashPageGetBitmap, HashPageGetMeta, HashPageGetOpaque, IndexTupleSize(), InvalidBlockNumber, InvalidBucket, InvalidBuffer, InvalidOffsetNumber, LH_UNUSED_PAGE, MarkBufferDirty(), MAXALIGN, PageAddItem, PageSetLSN(), RBM_NORMAL, UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogReadBufferForRedoExtended(), XLogRecGetBlockData(), XLogRecGetData, and XLogRecHasBlockRef.

Referenced by hash_redo().

◆ hash_xlog_update_meta_page()

static void hash_xlog_update_meta_page ( XLogReaderState record)
static

◆ hash_xlog_vacuum_one_page()

static void hash_xlog_vacuum_one_page ( XLogReaderState record)
static

Definition at line 964 of file hash_xlog.c.

965{
966 XLogRecPtr lsn = record->EndRecPtr;
968 Buffer buffer;
970 Page page;
974
976 toDelete = xldata->offsets;
977
978 /*
979 * If we have any conflict processing to do, it must happen before we
980 * update the page.
981 *
982 * Hash index records that are marked as LP_DEAD and being removed during
983 * hash index tuple insertion can conflict with standby queries. You might
984 * think that vacuum records would conflict as well, but we've handled
985 * that already. XLOG_HEAP2_PRUNE_VACUUM_SCAN records provide the highest
986 * xid cleaned by the vacuum of the heap and so we can resolve any
987 * conflicts just once when that arrives. After that we know that no
988 * conflicts exist from individual hash index vacuum records on that
989 * index.
990 */
991 if (InHotStandby)
992 {
993 RelFileLocator rlocator;
994
995 XLogRecGetBlockTag(record, 0, &rlocator, NULL, NULL);
996 ResolveRecoveryConflictWithSnapshot(xldata->snapshotConflictHorizon,
997 xldata->isCatalogRel,
998 rlocator);
999 }
1000
1001 action = XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &buffer);
1002
1003 if (action == BLK_NEEDS_REDO)
1004 {
1005 page = BufferGetPage(buffer);
1006
1007 PageIndexMultiDelete(page, toDelete, xldata->ntuples);
1008
1009 /*
1010 * Mark the page as not containing any LP_DEAD items. See comments in
1011 * _hash_vacuum_one_page() for details.
1012 */
1014 pageopaque->hasho_flag &= ~LH_PAGE_HAS_DEAD_TUPLES;
1015
1016 PageSetLSN(page, lsn);
1017 MarkBufferDirty(buffer);
1018 }
1019 if (BufferIsValid(buffer))
1020 UnlockReleaseBuffer(buffer);
1021
1022 if (XLogReadBufferForRedo(record, 1, &metabuf) == BLK_NEEDS_REDO)
1023 {
1024 Page metapage;
1025 HashMetaPage metap;
1026
1028 metap = HashPageGetMeta(metapage);
1029
1030 metap->hashm_ntuples -= xldata->ntuples;
1031
1032 PageSetLSN(metapage, lsn);
1034 }
1037}
void ResolveRecoveryConflictWithSnapshot(TransactionId snapshotConflictHorizon, bool isCatalogRel, RelFileLocator locator)
Definition standby.c:470
#define InHotStandby
Definition xlogutils.h:60

References BLK_NEEDS_REDO, BufferGetPage(), BufferIsValid(), XLogReaderState::EndRecPtr, fb(), HashMetaPageData::hashm_ntuples, HashPageGetMeta, HashPageGetOpaque, InHotStandby, MarkBufferDirty(), PageIndexMultiDelete(), PageSetLSN(), RBM_NORMAL, ResolveRecoveryConflictWithSnapshot(), UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogReadBufferForRedoExtended(), XLogRecGetBlockTag(), and XLogRecGetData.

Referenced by hash_redo().