PostgreSQL Source Code git master
Loading...
Searching...
No Matches
hash_xlog.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * hash_xlog.c
4 * WAL replay logic for hash index.
5 *
6 *
7 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 * IDENTIFICATION
11 * src/backend/access/hash/hash_xlog.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include "access/bufmask.h"
18#include "access/hash.h"
19#include "access/hash_xlog.h"
20#include "access/xlogutils.h"
21#include "storage/standby.h"
22
23/*
24 * replay a hash index meta page
25 */
26static void
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}
48
49/*
50 * replay a hash index bitmap page
51 */
52static void
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}
97
98/*
99 * replay a hash index insert without split
100 */
101static void
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}
144
145/*
146 * replay addition of overflow page for hash index
147 */
148static void
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}
282
283/*
284 * replay allocation of page for split operation
285 */
286static void
288{
289 XLogRecPtr lsn = record->EndRecPtr;
294 XLogRedoAction action;
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 */
303 action = XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &oldbuf);
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}
398
399/*
400 * replay of split operation
401 */
402static void
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}
412
413/*
414 * replay completion of split operation
415 */
416static void
418{
419 XLogRecPtr lsn = record->EndRecPtr;
423 XLogRedoAction action;
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}
471
472/*
473 * replay move of page contents for squeeze operation of hash index
474 */
475static void
477{
478 XLogRecPtr lsn = record->EndRecPtr;
483 XLogRedoAction action;
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)
493 action = XLogReadBufferForRedoExtended(record, 1, RBM_NORMAL, true, &writebuf);
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
502 action = XLogReadBufferForRedo(record, 1, &writebuf);
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}
596
597/*
598 * replay squeeze page operation of hash index
599 */
600static void
602{
603 XLogRecPtr lsn = record->EndRecPtr;
610 XLogRedoAction action;
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)
620 action = XLogReadBufferForRedoExtended(record, 1, RBM_NORMAL, true, &writebuf);
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)
630 action = XLogReadBufferForRedo(record, 1, &writebuf);
631 else
632 action = BLK_NOTFOUND;
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}
829
830/*
831 * replay delete operation of hash index
832 */
833static void
835{
836 XLogRecPtr lsn = record->EndRecPtr;
840 Page page;
841 XLogRedoAction action;
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)
851 action = XLogReadBufferForRedoExtended(record, 1, RBM_NORMAL, true, &deletebuf);
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
860 action = XLogReadBufferForRedo(record, 1, &deletebuf);
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}
907
908/*
909 * replay split cleanup flag operation for primary bucket page.
910 */
911static void
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}
932
933/*
934 * replay for update meta page
935 */
936static void
938{
939 HashMetaPage metap;
940 XLogRecPtr lsn = record->EndRecPtr;
943 Page page;
944
945 if (XLogReadBufferForRedo(record, 0, &metabuf) == BLK_NEEDS_REDO)
946 {
947 page = BufferGetPage(metabuf);
948 metap = HashPageGetMeta(page);
949
950 metap->hashm_ntuples = xldata->ntuples;
951
952 PageSetLSN(page, lsn);
954 }
957}
958
959/*
960 * replay delete operation in hash index to remove
961 * tuples marked as DEAD during index tuple insertion.
962 */
963static void
965{
966 XLogRecPtr lsn = record->EndRecPtr;
968 Buffer buffer;
970 Page page;
971 XLogRedoAction action;
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}
1038
1039void
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}
1089
1090/*
1091 * Mask a hash page before performing consistency checks on it.
1092 */
1093void
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}
uint32 BlockNumber
Definition block.h:31
#define InvalidBlockNumber
Definition block.h:33
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition block.h:71
#define CLRBIT(x, i)
Definition blutils.c:28
#define SETBIT(x, i)
Definition blutils.c:29
int Buffer
Definition buf.h:23
#define InvalidBuffer
Definition buf.h:25
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
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition bufmgr.c:4469
void UnlockReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5626
void MarkBufferDirty(Buffer buffer)
Definition bufmgr.c:3170
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:468
static Size BufferGetPageSize(Buffer buffer)
Definition bufmgr.h:457
@ RBM_ZERO_AND_CLEANUP_LOCK
Definition bufmgr.h:49
@ RBM_NORMAL
Definition bufmgr.h:46
static bool BufferIsValid(Buffer bufnum)
Definition bufmgr.h:419
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition bufpage.c:1170
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition bufpage.h:416
PageData * Page
Definition bufpage.h:81
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition bufpage.h:504
#define MAXALIGN(LEN)
Definition c.h:955
uint8_t uint8
Definition c.h:681
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:308
#define Assert(condition)
Definition c.h:1002
uint16_t uint16
Definition c.h:682
uint32_t uint32
Definition c.h:683
size_t Size
Definition c.h:748
#define PANIC
Definition elog.h:44
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define HashPageGetOpaque(page)
Definition hash.h:88
#define LH_BUCKET_PAGE
Definition hash.h:55
#define LH_UNUSED_PAGE
Definition hash.h:53
#define HashPageGetBitmap(page)
Definition hash.h:316
#define HASHO_PAGE_ID
Definition hash.h:101
#define HashPageGetMeta(page)
Definition hash.h:323
#define LH_PAGE_TYPE
Definition hash.h:63
#define LH_OVERFLOW_PAGE
Definition hash.h:54
#define InvalidBucket
Definition hash.h:37
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
void hash_mask(char *pagedata, BlockNumber blkno)
Definition hash_xlog.c:1094
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
void hash_redo(XLogReaderState *record)
Definition hash_xlog.c:1040
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 XLH_SPLIT_META_UPDATE_SPLITPOINT
Definition hash_xlog.h:46
#define XLOG_HASH_MOVE_PAGE_CONTENTS
Definition hash_xlog.h:34
#define XLOG_HASH_VACUUM_ONE_PAGE
Definition hash_xlog.h:40
#define XLH_SPLIT_META_UPDATE_MASKS
Definition hash_xlog.h:45
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
void _hash_pageinit(Page page, Size size)
Definition hashpage.c:596
void _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid, uint16 ffactor, bool initpage)
Definition hashpage.c:498
IndexTupleData * IndexTuple
Definition itup.h:53
static Size IndexTupleSize(const IndexTupleData *itup)
Definition itup.h:71
#define InvalidOffsetNumber
Definition off.h:26
uint16 OffsetNumber
Definition off.h:24
const void size_t len
const void * data
static char buf[DEFAULT_XLOG_SEG_SIZE]
static int fb(int x)
void ResolveRecoveryConflictWithSnapshot(TransactionId snapshotConflictHorizon, bool isCatalogRel, RelFileLocator locator)
Definition standby.c:470
BlockNumber hashm_mapp[HASH_MAX_BITMAPS]
Definition hash.h:264
uint32 hashm_lowmask
Definition hash.h:256
uint32 hashm_maxbucket
Definition hash.h:254
uint32 hashm_spares[HASH_MAX_SPLITPOINTS]
Definition hash.h:262
double hashm_ntuples
Definition hash.h:248
uint32 hashm_firstfree
Definition hash.h:259
uint32 hashm_ovflpoint
Definition hash.h:257
uint32 hashm_highmask
Definition hash.h:255
uint32 hashm_nmaps
Definition hash.h:260
uint16 hasho_flag
Definition hash.h:82
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 XLogRecGetInfo(decoder)
Definition xlogreader.h:410
#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
void XLogFlushBufferForRedoIfInit(XLogReaderState *record, uint8 block_id, Buffer buffer)
Definition xlogutils.c:334
XLogRedoAction XLogReadBufferForRedoExtended(XLogReaderState *record, uint8 block_id, ReadBufferMode mode, bool get_cleanup_lock, Buffer *buf)
Definition xlogutils.c:362
#define InHotStandby
Definition xlogutils.h:60
XLogRedoAction
Definition xlogutils.h:73
@ BLK_RESTORED
Definition xlogutils.h:76
@ BLK_NEEDS_REDO
Definition xlogutils.h:74
@ BLK_NOTFOUND
Definition xlogutils.h:77