PostgreSQL Source Code git master
Functions | Variables
ginxlog.c File Reference
#include "postgres.h"
#include "access/bufmask.h"
#include "access/gin_private.h"
#include "access/ginxlog.h"
#include "access/xlogutils.h"
#include "utils/memutils.h"
Include dependency graph for ginxlog.c:

Go to the source code of this file.

Functions

static void  ginRedoClearIncompleteSplit (XLogReaderState *record, uint8 block_id)
 
static void  ginRedoCreatePTree (XLogReaderState *record)
 
static void  ginRedoInsertEntry (Buffer buffer, bool isLeaf, BlockNumber rightblkno, void *rdata)
 
 
static void  ginRedoInsertData (Buffer buffer, bool isLeaf, BlockNumber rightblkno, void *rdata)
 
static void  ginRedoInsert (XLogReaderState *record)
 
static void  ginRedoSplit (XLogReaderState *record)
 
static void  ginRedoVacuumPage (XLogReaderState *record)
 
 
static void  ginRedoDeletePage (XLogReaderState *record)
 
static void  ginRedoUpdateMetapage (XLogReaderState *record)
 
static void  ginRedoInsertListPage (XLogReaderState *record)
 
static void  ginRedoDeleteListPages (XLogReaderState *record)
 
void  gin_redo (XLogReaderState *record)
 
void  gin_xlog_startup (void)
 
void  gin_xlog_cleanup (void)
 
void  gin_mask (char *pagedata, BlockNumber blkno)
 

Variables

static MemoryContext  opCtx
 

Function Documentation

gin_mask()

void gin_mask ( char *  pagedata,
BlockNumber  blkno 
)

Definition at line 792 of file ginxlog.c.

793{
794 Page page = (Page) pagedata;
795 PageHeader pagehdr = (PageHeader) page;
796 GinPageOpaque opaque;
797
799 opaque = GinPageGetOpaque(page);
800
802
803 /*
804 * For a GIN_DELETED page, the page is initialized to empty. Hence, mask
805 * the whole page content. For other pages, mask the hole if pd_lower
806 * appears to have been set correctly.
807 */
808 if (opaque->flags & GIN_DELETED)
809 mask_page_content(page);
810 else if (pagehdr->pd_lower > SizeOfPageHeaderData)
811 mask_unused_space(page);
812}
void mask_page_content(Page page)
Definition: bufmask.c:119
void mask_page_lsn_and_checksum(Page page)
Definition: bufmask.c:31
void mask_unused_space(Page page)
Definition: bufmask.c:71
void mask_page_hint_bits(Page page)
Definition: bufmask.c:46
PageHeaderData * PageHeader
Definition: bufpage.h:174
#define SizeOfPageHeaderData
Definition: bufpage.h:217
PageData * Page
Definition: bufpage.h:82
#define GinPageGetOpaque(page)
Definition: ginblock.h:110
#define GIN_DELETED
Definition: ginblock.h:43
uint16 flags
Definition: ginblock.h:36
LocationIndex pd_lower
Definition: bufpage.h:166

References GinPageOpaqueData::flags, GIN_DELETED, GinPageGetOpaque, mask_page_content(), mask_page_hint_bits(), mask_page_lsn_and_checksum(), mask_unused_space(), PageHeaderData::pd_lower, and SizeOfPageHeaderData.

gin_redo()

void gin_redo ( XLogReaderStaterecord )

Definition at line 725 of file ginxlog.c.

726{
727 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
728 MemoryContext oldCtx;
729
730 /*
731 * GIN indexes do not require any conflict processing. NB: If we ever
732 * implement a similar optimization as we have in b-tree, and remove
733 * killed tuples outside VACUUM, we'll need to handle that here.
734 */
735
737 switch (info)
738 {
740 ginRedoCreatePTree(record);
741 break;
742 case XLOG_GIN_INSERT:
743 ginRedoInsert(record);
744 break;
745 case XLOG_GIN_SPLIT:
746 ginRedoSplit(record);
747 break;
749 ginRedoVacuumPage(record);
750 break;
753 break;
755 ginRedoDeletePage(record);
756 break;
758 ginRedoUpdateMetapage(record);
759 break;
761 ginRedoInsertListPage(record);
762 break;
765 break;
766 default:
767 elog(PANIC, "gin_redo: unknown op code %u", info);
768 }
769 MemoryContextSwitchTo(oldCtx);
771}
uint8_t uint8
Definition: c.h:536
#define PANIC
Definition: elog.h:42
#define elog(elevel,...)
Definition: elog.h:226
static void ginRedoInsert(XLogReaderState *record)
Definition: ginxlog.c:347
static void ginRedoSplit(XLogReaderState *record)
Definition: ginxlog.c:401
static void ginRedoDeletePage(XLogReaderState *record)
Definition: ginxlog.c:476
static void ginRedoVacuumDataLeafPage(XLogReaderState *record)
Definition: ginxlog.c:451
static void ginRedoDeleteListPages(XLogReaderState *record)
Definition: ginxlog.c:674
static void ginRedoUpdateMetapage(XLogReaderState *record)
Definition: ginxlog.c:527
static void ginRedoInsertListPage(XLogReaderState *record)
Definition: ginxlog.c:619
static MemoryContext opCtx
Definition: ginxlog.c:22
static void ginRedoCreatePTree(XLogReaderState *record)
Definition: ginxlog.c:44
static void ginRedoVacuumPage(XLogReaderState *record)
Definition: ginxlog.c:439
#define XLOG_GIN_UPDATE_META_PAGE
Definition: ginxlog.h:162
#define XLOG_GIN_INSERT
Definition: ginxlog.h:35
#define XLOG_GIN_CREATE_PTREE
Definition: ginxlog.h:19
#define XLOG_GIN_VACUUM_PAGE
Definition: ginxlog.h:135
#define XLOG_GIN_DELETE_PAGE
Definition: ginxlog.h:153
#define XLOG_GIN_INSERT_LISTPAGE
Definition: ginxlog.h:180
#define XLOG_GIN_VACUUM_DATA_LEAF_PAGE
Definition: ginxlog.h:141
#define XLOG_GIN_SPLIT
Definition: ginxlog.h:109
#define XLOG_GIN_DELETE_LISTPAGE
Definition: ginxlog.h:194
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:400
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410

References elog, ginRedoCreatePTree(), ginRedoDeleteListPages(), ginRedoDeletePage(), ginRedoInsert(), ginRedoInsertListPage(), ginRedoSplit(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), ginRedoVacuumPage(), MemoryContextReset(), MemoryContextSwitchTo(), opCtx, PANIC, XLOG_GIN_CREATE_PTREE, XLOG_GIN_DELETE_LISTPAGE, XLOG_GIN_DELETE_PAGE, XLOG_GIN_INSERT, XLOG_GIN_INSERT_LISTPAGE, XLOG_GIN_SPLIT, XLOG_GIN_UPDATE_META_PAGE, XLOG_GIN_VACUUM_DATA_LEAF_PAGE, XLOG_GIN_VACUUM_PAGE, and XLogRecGetInfo.

gin_xlog_cleanup()

void gin_xlog_cleanup ( void  )

Definition at line 782 of file ginxlog.c.

783{
785 opCtx = NULL;
786}
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:469

References MemoryContextDelete(), and opCtx.

gin_xlog_startup()

void gin_xlog_startup ( void  )

Definition at line 774 of file ginxlog.c.

775{
777 "GIN recovery temporary context",
779}
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CurrentMemoryContext, and opCtx.

ginRedoClearIncompleteSplit()

static void ginRedoClearIncompleteSplit ( XLogReaderStaterecord,
uint8  block_id 
)
static

Definition at line 25 of file ginxlog.c.

26{
27 XLogRecPtr lsn = record->EndRecPtr;
28 Buffer buffer;
29 Page page;
30
31 if (XLogReadBufferForRedo(record, block_id, &buffer) == BLK_NEEDS_REDO)
32 {
33 page = BufferGetPage(buffer);
34 GinPageGetOpaque(page)->flags &= ~GIN_INCOMPLETE_SPLIT;
35
36 PageSetLSN(page, lsn);
37 MarkBufferDirty(buffer);
38 }
39 if (BufferIsValid(buffer))
40 UnlockReleaseBuffer(buffer);
41}
int Buffer
Definition: buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5355
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2921
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:417
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:368
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:391
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:303
@ BLK_NEEDS_REDO
Definition: xlogutils.h:74

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

Referenced by ginRedoInsert(), and ginRedoSplit().

ginRedoCreatePTree()

static void ginRedoCreatePTree ( XLogReaderStaterecord )
static

Definition at line 44 of file ginxlog.c.

45{
46 XLogRecPtr lsn = record->EndRecPtr;
48 char *ptr;
49 Buffer buffer;
50 Page page;
51
52 buffer = XLogInitBufferForRedo(record, 0);
53 page = BufferGetPage(buffer);
54
56
57 ptr = XLogRecGetData(record) + sizeof(ginxlogCreatePostingTree);
58
59 /* Place page data */
60 memcpy(GinDataLeafPageGetPostingList(page), ptr, data->size);
61
62 GinDataPageSetDataSize(page, data->size);
63
64 PageSetLSN(page, lsn);
65
66 MarkBufferDirty(buffer);
67 UnlockReleaseBuffer(buffer);
68}
#define GIN_DATA
Definition: ginblock.h:41
#define GIN_COMPRESSED
Definition: ginblock.h:48
#define GIN_LEAF
Definition: ginblock.h:42
#define GinDataPageSetDataSize(page, size)
Definition: ginblock.h:309
#define GinDataLeafPageGetPostingList(page)
Definition: ginblock.h:278
void GinInitBuffer(Buffer b, uint32 f)
Definition: ginutil.c:355
struct ginxlogCreatePostingTree ginxlogCreatePostingTree
const void * data
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:315

References BufferGetPage(), data, XLogReaderState::EndRecPtr, GIN_COMPRESSED, GIN_DATA, GIN_LEAF, GinDataLeafPageGetPostingList, GinDataPageSetDataSize, GinInitBuffer(), MarkBufferDirty(), PageSetLSN(), UnlockReleaseBuffer(), XLogInitBufferForRedo(), and XLogRecGetData.

Referenced by gin_redo().

ginRedoDeleteListPages()

static void ginRedoDeleteListPages ( XLogReaderStaterecord )
static

Definition at line 674 of file ginxlog.c.

675{
676 XLogRecPtr lsn = record->EndRecPtr;
678 Buffer metabuffer;
679 Page metapage;
680 int i;
681
682 metabuffer = XLogInitBufferForRedo(record, 0);
684 metapage = BufferGetPage(metabuffer);
685
686 GinInitMetabuffer(metabuffer);
687
688 memcpy(GinPageGetMeta(metapage), &data->metadata, sizeof(GinMetaPageData));
689 PageSetLSN(metapage, lsn);
690 MarkBufferDirty(metabuffer);
691
692 /*
693 * In normal operation, shiftList() takes exclusive lock on all the
694 * pages-to-be-deleted simultaneously. During replay, however, it should
695 * be all right to lock them one at a time. This is dependent on the fact
696 * that we are deleting pages from the head of the list, and that readers
697 * share-lock the next page before releasing the one they are on. So we
698 * cannot get past a reader that is on, or due to visit, any page we are
699 * going to delete. New incoming readers will block behind our metapage
700 * lock and then see a fully updated page list.
701 *
702 * No full-page images are taken of the deleted pages. Instead, they are
703 * re-initialized as empty, deleted pages. Their right-links don't need to
704 * be preserved, because no new readers can see the pages, as explained
705 * above.
706 */
707 for (i = 0; i < data->ndeleted; i++)
708 {
709 Buffer buffer;
710 Page page;
711
712 buffer = XLogInitBufferForRedo(record, i + 1);
713 page = BufferGetPage(buffer);
714 GinInitBuffer(buffer, GIN_DELETED);
715
716 PageSetLSN(page, lsn);
717 MarkBufferDirty(buffer);
718
719 UnlockReleaseBuffer(buffer);
720 }
721 UnlockReleaseBuffer(metabuffer);
722}
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:4198
#define GIN_METAPAGE_BLKNO
Definition: ginblock.h:51
#define GinPageGetMeta(p)
Definition: ginblock.h:104
void GinInitMetabuffer(Buffer b)
Definition: ginutil.c:361
Assert(PointerIsAligned(start, uint64))
i
int i
Definition: isn.c:77

References Assert(), BufferGetBlockNumber(), BufferGetPage(), data, XLogReaderState::EndRecPtr, GIN_DELETED, GIN_METAPAGE_BLKNO, GinInitBuffer(), GinInitMetabuffer(), GinPageGetMeta, i, MarkBufferDirty(), PageSetLSN(), UnlockReleaseBuffer(), XLogInitBufferForRedo(), and XLogRecGetData.

Referenced by gin_redo().

ginRedoDeletePage()

static void ginRedoDeletePage ( XLogReaderStaterecord )
static

Definition at line 476 of file ginxlog.c.

477{
478 XLogRecPtr lsn = record->EndRecPtr;
480 Buffer dbuffer;
481 Buffer pbuffer;
482 Buffer lbuffer;
483 Page page;
484
485 /*
486 * Lock left page first in order to prevent possible deadlock with
487 * ginStepRight().
488 */
489 if (XLogReadBufferForRedo(record, 2, &lbuffer) == BLK_NEEDS_REDO)
490 {
491 page = BufferGetPage(lbuffer);
492 Assert(GinPageIsData(page));
493 GinPageGetOpaque(page)->rightlink = data->rightLink;
494 PageSetLSN(page, lsn);
495 MarkBufferDirty(lbuffer);
496 }
497
498 if (XLogReadBufferForRedo(record, 0, &dbuffer) == BLK_NEEDS_REDO)
499 {
500 page = BufferGetPage(dbuffer);
501 Assert(GinPageIsData(page));
502 GinPageSetDeleted(page);
503 GinPageSetDeleteXid(page, data->deleteXid);
504 PageSetLSN(page, lsn);
505 MarkBufferDirty(dbuffer);
506 }
507
508 if (XLogReadBufferForRedo(record, 1, &pbuffer) == BLK_NEEDS_REDO)
509 {
510 page = BufferGetPage(pbuffer);
511 Assert(GinPageIsData(page));
512 Assert(!GinPageIsLeaf(page));
513 GinPageDeletePostingItem(page, data->parentOffset);
514 PageSetLSN(page, lsn);
515 MarkBufferDirty(pbuffer);
516 }
517
518 if (BufferIsValid(lbuffer))
519 UnlockReleaseBuffer(lbuffer);
520 if (BufferIsValid(pbuffer))
521 UnlockReleaseBuffer(pbuffer);
522 if (BufferIsValid(dbuffer))
523 UnlockReleaseBuffer(dbuffer);
524}
#define GinPageSetDeleteXid(page, xid)
Definition: ginblock.h:136
#define GinPageIsData(page)
Definition: ginblock.h:115
#define GinPageSetDeleted(page)
Definition: ginblock.h:125
#define GinPageIsLeaf(page)
Definition: ginblock.h:112
void GinPageDeletePostingItem(Page page, OffsetNumber offset)
Definition: gindatapage.c:417

References Assert(), BLK_NEEDS_REDO, BufferGetPage(), BufferIsValid(), data, XLogReaderState::EndRecPtr, GinPageDeletePostingItem(), GinPageGetOpaque, GinPageIsData, GinPageIsLeaf, GinPageSetDeleted, GinPageSetDeleteXid, MarkBufferDirty(), PageSetLSN(), UnlockReleaseBuffer(), XLogReadBufferForRedo(), and XLogRecGetData.

Referenced by gin_redo().

ginRedoInsert()

static void ginRedoInsert ( XLogReaderStaterecord )
static

Definition at line 347 of file ginxlog.c.

348{
349 XLogRecPtr lsn = record->EndRecPtr;
351 Buffer buffer;
352#ifdef NOT_USED
353 BlockNumber leftChildBlkno = InvalidBlockNumber;
354#endif
355 BlockNumber rightChildBlkno = InvalidBlockNumber;
356 bool isLeaf = (data->flags & GIN_INSERT_ISLEAF) != 0;
357
358 /*
359 * First clear incomplete-split flag on child page if this finishes a
360 * split.
361 */
362 if (!isLeaf)
363 {
364 char *payload = XLogRecGetData(record) + sizeof(ginxlogInsert);
365
366#ifdef NOT_USED
367 leftChildBlkno = BlockIdGetBlockNumber((BlockId) payload);
368#endif
369 payload += sizeof(BlockIdData);
370 rightChildBlkno = BlockIdGetBlockNumber((BlockId) payload);
371
373 }
374
375 if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
376 {
377 Page page = BufferGetPage(buffer);
378 Size len;
379 char *payload = XLogRecGetBlockData(record, 0, &len);
380
381 /* How to insert the payload is tree-type specific */
382 if (data->flags & GIN_INSERT_ISDATA)
383 {
384 Assert(GinPageIsData(page));
385 ginRedoInsertData(buffer, isLeaf, rightChildBlkno, payload);
386 }
387 else
388 {
389 Assert(!GinPageIsData(page));
390 ginRedoInsertEntry(buffer, isLeaf, rightChildBlkno, payload);
391 }
392
393 PageSetLSN(page, lsn);
394 MarkBufferDirty(buffer);
395 }
396 if (BufferIsValid(buffer))
397 UnlockReleaseBuffer(buffer);
398}
uint32 BlockNumber
Definition: block.h:31
struct BlockIdData BlockIdData
#define InvalidBlockNumber
Definition: block.h:33
static BlockNumber BlockIdGetBlockNumber(const BlockIdData *blockId)
Definition: block.h:103
size_t Size
Definition: c.h:610
static void ginRedoInsertEntry(Buffer buffer, bool isLeaf, BlockNumber rightblkno, void *rdata)
Definition: ginxlog.c:71
static void ginRedoClearIncompleteSplit(XLogReaderState *record, uint8 block_id)
Definition: ginxlog.c:25
static void ginRedoInsertData(Buffer buffer, bool isLeaf, BlockNumber rightblkno, void *rdata)
Definition: ginxlog.c:319
#define GIN_INSERT_ISDATA
Definition: ginxlog.h:124
#define GIN_INSERT_ISLEAF
Definition: ginxlog.h:125
const void size_t len
Definition: block.h:54
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:2045

References Assert(), BLK_NEEDS_REDO, BlockIdGetBlockNumber(), BufferGetPage(), BufferIsValid(), data, XLogReaderState::EndRecPtr, GIN_INSERT_ISDATA, GIN_INSERT_ISLEAF, GinPageIsData, ginRedoClearIncompleteSplit(), ginRedoInsertData(), ginRedoInsertEntry(), InvalidBlockNumber, len, MarkBufferDirty(), PageSetLSN(), UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by gin_redo().

ginRedoInsertData()

static void ginRedoInsertData ( Buffer  buffer,
bool  isLeaf,
BlockNumber  rightblkno,
void *  rdata 
)
static

Definition at line 319 of file ginxlog.c.

320{
321 Page page = BufferGetPage(buffer);
322
323 if (isLeaf)
324 {
326
327 Assert(GinPageIsLeaf(page));
328
329 ginRedoRecompress(page, data);
330 }
331 else
332 {
334 PostingItem *oldpitem;
335
336 Assert(!GinPageIsLeaf(page));
337
338 /* update link to right page after split */
339 oldpitem = GinDataPageGetPostingItem(page, data->offset);
340 PostingItemSetBlockNumber(oldpitem, rightblkno);
341
342 GinDataPageAddPostingItem(page, &data->newitem, data->offset);
343 }
344}
#define GinDataPageGetPostingItem(page, i)
Definition: ginblock.h:298
#define PostingItemSetBlockNumber(pointer, blockNumber)
Definition: ginblock.h:192
void GinDataPageAddPostingItem(Page page, PostingItem *data, OffsetNumber offset)
Definition: gindatapage.c:380
static void ginRedoRecompress(Page page, ginxlogRecompressDataLeaf *data)
Definition: ginxlog.c:117

References Assert(), BufferGetPage(), data, GinDataPageAddPostingItem(), GinDataPageGetPostingItem, GinPageIsLeaf, ginRedoRecompress(), and PostingItemSetBlockNumber.

Referenced by ginRedoInsert().

ginRedoInsertEntry()

static void ginRedoInsertEntry ( Buffer  buffer,
bool  isLeaf,
BlockNumber  rightblkno,
void *  rdata 
)
static

Definition at line 71 of file ginxlog.c.

72{
73 Page page = BufferGetPage(buffer);
75 OffsetNumber offset = data->offset;
76 IndexTuple itup;
77
78 if (rightblkno != InvalidBlockNumber)
79 {
80 /* update link to right page after split */
81 Assert(!GinPageIsLeaf(page));
82 Assert(offset >= FirstOffsetNumber && offset <= PageGetMaxOffsetNumber(page));
83 itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offset));
84 GinSetDownlink(itup, rightblkno);
85 }
86
87 if (data->isDelete)
88 {
89 Assert(GinPageIsLeaf(page));
90 Assert(offset >= FirstOffsetNumber && offset <= PageGetMaxOffsetNumber(page));
91 PageIndexTupleDelete(page, offset);
92 }
93
94 itup = &data->tuple;
95
96 if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), offset, false, false) == InvalidOffsetNumber)
97 {
98 RelFileLocator locator;
99 ForkNumber forknum;
100 BlockNumber blknum;
101
102 BufferGetTag(buffer, &locator, &forknum, &blknum);
103 elog(ERROR, "failed to add item to index page in %u/%u/%u",
104 locator.spcOid, locator.dbOid, locator.relNumber);
105 }
106}
void BufferGetTag(Buffer buffer, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum)
Definition: bufmgr.c:4219
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Definition: bufpage.c:1051
static Item PageGetItem(const PageData *page, const ItemIdData *itemId)
Definition: bufpage.h:354
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:244
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:472
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition: bufpage.h:372
#define ERROR
Definition: elog.h:39
#define GinSetDownlink(itup, blkno)
Definition: ginblock.h:258
Pointer Item
Definition: item.h:17
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
#define FirstOffsetNumber
Definition: off.h:27
ForkNumber
Definition: relpath.h:56
RelFileNumber relNumber
Definition: relfilelocator.h:62

References Assert(), BufferGetPage(), BufferGetTag(), data, RelFileLocator::dbOid, elog, ERROR, FirstOffsetNumber, GinPageIsLeaf, GinSetDownlink, IndexTupleSize(), InvalidBlockNumber, InvalidOffsetNumber, PageAddItem, PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), PageIndexTupleDelete(), RelFileLocator::relNumber, and RelFileLocator::spcOid.

Referenced by ginRedoInsert().

ginRedoInsertListPage()

static void ginRedoInsertListPage ( XLogReaderStaterecord )
static

Definition at line 619 of file ginxlog.c.

620{
621 XLogRecPtr lsn = record->EndRecPtr;
623 Buffer buffer;
624 Page page;
625 OffsetNumber l,
626 off = FirstOffsetNumber;
627 int i,
628 tupsize;
629 char *payload;
630 IndexTuple tuples;
631 Size totaltupsize;
632
633 /* We always re-initialize the page. */
634 buffer = XLogInitBufferForRedo(record, 0);
635 page = BufferGetPage(buffer);
636
637 GinInitBuffer(buffer, GIN_LIST);
638 GinPageGetOpaque(page)->rightlink = data->rightlink;
639 if (data->rightlink == InvalidBlockNumber)
640 {
641 /* tail of sublist */
642 GinPageSetFullRow(page);
643 GinPageGetOpaque(page)->maxoff = 1;
644 }
645 else
646 {
647 GinPageGetOpaque(page)->maxoff = 0;
648 }
649
650 payload = XLogRecGetBlockData(record, 0, &totaltupsize);
651
652 tuples = (IndexTuple) payload;
653 for (i = 0; i < data->ntuples; i++)
654 {
655 tupsize = IndexTupleSize(tuples);
656
657 l = PageAddItem(page, (Item) tuples, tupsize, off, false, false);
658
659 if (l == InvalidOffsetNumber)
660 elog(ERROR, "failed to add item to index page");
661
662 tuples = (IndexTuple) (((char *) tuples) + tupsize);
663 off++;
664 }
665 Assert((char *) tuples == payload + totaltupsize);
666
667 PageSetLSN(page, lsn);
668 MarkBufferDirty(buffer);
669
670 UnlockReleaseBuffer(buffer);
671}
#define GIN_LIST
Definition: ginblock.h:45
#define GinPageSetFullRow(page)
Definition: ginblock.h:120

References Assert(), BufferGetPage(), data, elog, XLogReaderState::EndRecPtr, ERROR, FirstOffsetNumber, GIN_LIST, GinInitBuffer(), GinPageGetOpaque, GinPageSetFullRow, i, IndexTupleSize(), InvalidBlockNumber, InvalidOffsetNumber, MarkBufferDirty(), PageAddItem, PageSetLSN(), UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by gin_redo().

ginRedoRecompress()

static void ginRedoRecompress ( Page  page,
)
static

Definition at line 117 of file ginxlog.c.

118{
119 int actionno;
120 int segno;
121 GinPostingList *oldseg;
122 Pointer segmentend;
123 char *walbuf;
124 int totalsize;
125 Pointer tailCopy = NULL;
126 Pointer writePtr;
127 Pointer segptr;
128
129 /*
130 * If the page is in pre-9.4 format, convert to new format first.
131 */
132 if (!GinPageIsCompressed(page))
133 {
134 ItemPointer uncompressed = (ItemPointer) GinDataPageGetData(page);
135 int nuncompressed = GinPageGetOpaque(page)->maxoff;
136 int npacked;
137
138 /*
139 * Empty leaf pages are deleted as part of vacuum, but leftmost and
140 * rightmost pages are never deleted. So, pg_upgrade'd from pre-9.4
141 * instances might contain empty leaf pages, and we need to handle
142 * them correctly.
143 */
144 if (nuncompressed > 0)
145 {
146 GinPostingList *plist;
147
148 plist = ginCompressPostingList(uncompressed, nuncompressed,
149 BLCKSZ, &npacked);
150 totalsize = SizeOfGinPostingList(plist);
151
152 Assert(npacked == nuncompressed);
153
154 memcpy(GinDataLeafPageGetPostingList(page), plist, totalsize);
155 }
156 else
157 {
158 totalsize = 0;
159 }
160
161 GinDataPageSetDataSize(page, totalsize);
164 }
165
166 oldseg = GinDataLeafPageGetPostingList(page);
167 writePtr = (Pointer) oldseg;
168 segmentend = (Pointer) oldseg + GinDataLeafPageGetPostingListSize(page);
169 segno = 0;
170
171 walbuf = ((char *) data) + sizeof(ginxlogRecompressDataLeaf);
172 for (actionno = 0; actionno < data->nactions; actionno++)
173 {
174 uint8 a_segno = *((uint8 *) (walbuf++));
175 uint8 a_action = *((uint8 *) (walbuf++));
176 GinPostingList *newseg = NULL;
177 int newsegsize = 0;
178 ItemPointerData *items = NULL;
179 uint16 nitems = 0;
180 ItemPointerData *olditems;
181 int nolditems;
182 ItemPointerData *newitems;
183 int nnewitems;
184 int segsize;
185
186 /* Extract all the information we need from the WAL record */
187 if (a_action == GIN_SEGMENT_INSERT ||
188 a_action == GIN_SEGMENT_REPLACE)
189 {
190 newseg = (GinPostingList *) walbuf;
191 newsegsize = SizeOfGinPostingList(newseg);
192 walbuf += SHORTALIGN(newsegsize);
193 }
194
195 if (a_action == GIN_SEGMENT_ADDITEMS)
196 {
197 memcpy(&nitems, walbuf, sizeof(uint16));
198 walbuf += sizeof(uint16);
199 items = (ItemPointerData *) walbuf;
200 walbuf += nitems * sizeof(ItemPointerData);
201 }
202
203 /* Skip to the segment that this action concerns */
204 Assert(segno <= a_segno);
205 while (segno < a_segno)
206 {
207 /*
208 * Once modification is started and page tail is copied, we've to
209 * copy unmodified segments.
210 */
211 segsize = SizeOfGinPostingList(oldseg);
212 if (tailCopy)
213 {
214 Assert(writePtr + segsize < PageGetSpecialPointer(page));
215 memcpy(writePtr, (Pointer) oldseg, segsize);
216 }
217 writePtr += segsize;
218 oldseg = GinNextPostingListSegment(oldseg);
219 segno++;
220 }
221
222 /*
223 * ADDITEMS action is handled like REPLACE, but the new segment to
224 * replace the old one is reconstructed using the old segment from
225 * disk and the new items from the WAL record.
226 */
227 if (a_action == GIN_SEGMENT_ADDITEMS)
228 {
229 int npacked;
230
231 olditems = ginPostingListDecode(oldseg, &nolditems);
232
234 olditems, nolditems,
235 &nnewitems);
236 Assert(nnewitems == nolditems + nitems);
237
238 newseg = ginCompressPostingList(newitems, nnewitems,
239 BLCKSZ, &npacked);
240 Assert(npacked == nnewitems);
241
242 newsegsize = SizeOfGinPostingList(newseg);
243 a_action = GIN_SEGMENT_REPLACE;
244 }
245
246 segptr = (Pointer) oldseg;
247 if (segptr != segmentend)
248 segsize = SizeOfGinPostingList(oldseg);
249 else
250 {
251 /*
252 * Positioned after the last existing segment. Only INSERTs
253 * expected here.
254 */
255 Assert(a_action == GIN_SEGMENT_INSERT);
256 segsize = 0;
257 }
258
259 /*
260 * We're about to start modification of the page. So, copy tail of
261 * the page if it's not done already.
262 */
263 if (!tailCopy && segptr != segmentend)
264 {
265 int tailSize = segmentend - segptr;
266
267 tailCopy = (Pointer) palloc(tailSize);
268 memcpy(tailCopy, segptr, tailSize);
269 segptr = tailCopy;
270 oldseg = (GinPostingList *) segptr;
271 segmentend = segptr + tailSize;
272 }
273
274 switch (a_action)
275 {
277 segptr += segsize;
278 segno++;
279 break;
280
282 /* copy the new segment in place */
283 Assert(writePtr + newsegsize <= PageGetSpecialPointer(page));
284 memcpy(writePtr, newseg, newsegsize);
285 writePtr += newsegsize;
286 break;
287
289 /* copy the new version of segment in place */
290 Assert(writePtr + newsegsize <= PageGetSpecialPointer(page));
291 memcpy(writePtr, newseg, newsegsize);
292 writePtr += newsegsize;
293 segptr += segsize;
294 segno++;
295 break;
296
297 default:
298 elog(ERROR, "unexpected GIN leaf action: %u", a_action);
299 }
300 oldseg = (GinPostingList *) segptr;
301 }
302
303 /* Copy the rest of unmodified segments if any. */
304 segptr = (Pointer) oldseg;
305 if (segptr != segmentend && tailCopy)
306 {
307 int restSize = segmentend - segptr;
308
309 Assert(writePtr + restSize <= PageGetSpecialPointer(page));
310 memcpy(writePtr, segptr, restSize);
311 writePtr += restSize;
312 }
313
314 totalsize = writePtr - (Pointer) GinDataLeafPageGetPostingList(page);
315 GinDataPageSetDataSize(page, totalsize);
316}
#define PageGetSpecialPointer(page)
Definition: bufpage.h:339
char * Pointer
Definition: c.h:529
#define SHORTALIGN(LEN)
Definition: c.h:806
uint16_t uint16
Definition: c.h:537
#define SizeOfGinPostingList(plist)
Definition: ginblock.h:342
#define GinDataLeafPageGetPostingListSize(page)
Definition: ginblock.h:280
#define GinPageSetCompressed(page)
Definition: ginblock.h:122
#define GinNextPostingListSegment(cur)
Definition: ginblock.h:343
#define GinDataPageGetData(page)
Definition: ginblock.h:295
#define GinPageIsCompressed(page)
Definition: ginblock.h:121
ItemPointer ginPostingListDecode(GinPostingList *plist, int *ndecoded_out)
GinPostingList * ginCompressPostingList(const ItemPointer ipd, int nipd, int maxsize, int *nwritten)
ItemPointer ginMergeItemPointers(ItemPointerData *a, uint32 na, ItemPointerData *b, uint32 nb, int *nmerged)
#define GIN_SEGMENT_ADDITEMS
Definition: ginxlog.h:95
#define GIN_SEGMENT_DELETE
Definition: ginxlog.h:92
#define GIN_SEGMENT_INSERT
Definition: ginxlog.h:93
#define GIN_SEGMENT_REPLACE
Definition: ginxlog.h:94
#define nitems(x)
Definition: indent.h:31
ItemPointerData * ItemPointer
Definition: itemptr.h:49
struct ItemPointerData ItemPointerData
void * palloc(Size size)
Definition: mcxt.c:1365
static ItemArray items
Definition: test_tidstore.c:48

References Assert(), data, elog, ERROR, GIN_SEGMENT_ADDITEMS, GIN_SEGMENT_DELETE, GIN_SEGMENT_INSERT, GIN_SEGMENT_REPLACE, ginCompressPostingList(), GinDataLeafPageGetPostingList, GinDataLeafPageGetPostingListSize, GinDataPageGetData, GinDataPageSetDataSize, ginMergeItemPointers(), GinNextPostingListSegment, GinPageGetOpaque, GinPageIsCompressed, GinPageSetCompressed, ginPostingListDecode(), InvalidOffsetNumber, items, nitems, PageGetSpecialPointer, palloc(), SHORTALIGN, and SizeOfGinPostingList.

Referenced by ginRedoInsertData(), and ginRedoVacuumDataLeafPage().

ginRedoSplit()

static void ginRedoSplit ( XLogReaderStaterecord )
static

Definition at line 401 of file ginxlog.c.

402{
404 Buffer lbuffer,
405 rbuffer,
406 rootbuf;
407 bool isLeaf = (data->flags & GIN_INSERT_ISLEAF) != 0;
408 bool isRoot = (data->flags & GIN_SPLIT_ROOT) != 0;
409
410 /*
411 * First clear incomplete-split flag on child page if this finishes a
412 * split
413 */
414 if (!isLeaf)
416
417 if (XLogReadBufferForRedo(record, 0, &lbuffer) != BLK_RESTORED)
418 elog(ERROR, "GIN split record did not contain a full-page image of left page");
419
420 if (XLogReadBufferForRedo(record, 1, &rbuffer) != BLK_RESTORED)
421 elog(ERROR, "GIN split record did not contain a full-page image of right page");
422
423 if (isRoot)
424 {
425 if (XLogReadBufferForRedo(record, 2, &rootbuf) != BLK_RESTORED)
426 elog(ERROR, "GIN split record did not contain a full-page image of root page");
427 UnlockReleaseBuffer(rootbuf);
428 }
429
430 UnlockReleaseBuffer(rbuffer);
431 UnlockReleaseBuffer(lbuffer);
432}
#define GIN_SPLIT_ROOT
Definition: ginxlog.h:126
@ BLK_RESTORED
Definition: xlogutils.h:76

References BLK_RESTORED, data, elog, ERROR, GIN_INSERT_ISLEAF, GIN_SPLIT_ROOT, ginRedoClearIncompleteSplit(), UnlockReleaseBuffer(), XLogReadBufferForRedo(), and XLogRecGetData.

Referenced by gin_redo().

ginRedoUpdateMetapage()

static void ginRedoUpdateMetapage ( XLogReaderStaterecord )
static

Definition at line 527 of file ginxlog.c.

528{
529 XLogRecPtr lsn = record->EndRecPtr;
531 Buffer metabuffer;
532 Page metapage;
533 Buffer buffer;
534
535 /*
536 * Restore the metapage. This is essentially the same as a full-page
537 * image, so restore the metapage unconditionally without looking at the
538 * LSN, to avoid torn page hazards.
539 */
540 metabuffer = XLogInitBufferForRedo(record, 0);
542 metapage = BufferGetPage(metabuffer);
543
544 GinInitMetabuffer(metabuffer);
545 memcpy(GinPageGetMeta(metapage), &data->metadata, sizeof(GinMetaPageData));
546 PageSetLSN(metapage, lsn);
547 MarkBufferDirty(metabuffer);
548
549 if (data->ntuples > 0)
550 {
551 /*
552 * insert into tail page
553 */
554 if (XLogReadBufferForRedo(record, 1, &buffer) == BLK_NEEDS_REDO)
555 {
556 Page page = BufferGetPage(buffer);
557 OffsetNumber off;
558 int i;
559 Size tupsize;
560 char *payload;
561 IndexTuple tuples;
562 Size totaltupsize;
563
564 payload = XLogRecGetBlockData(record, 1, &totaltupsize);
565 tuples = (IndexTuple) payload;
566
567 if (PageIsEmpty(page))
568 off = FirstOffsetNumber;
569 else
571
572 for (i = 0; i < data->ntuples; i++)
573 {
574 tupsize = IndexTupleSize(tuples);
575
576 if (PageAddItem(page, (Item) tuples, tupsize, off,
577 false, false) == InvalidOffsetNumber)
578 elog(ERROR, "failed to add item to index page");
579
580 tuples = (IndexTuple) (((char *) tuples) + tupsize);
581
582 off++;
583 }
584 Assert(payload + totaltupsize == (char *) tuples);
585
586 /*
587 * Increase counter of heap tuples
588 */
589 GinPageGetOpaque(page)->maxoff++;
590
591 PageSetLSN(page, lsn);
592 MarkBufferDirty(buffer);
593 }
594 if (BufferIsValid(buffer))
595 UnlockReleaseBuffer(buffer);
596 }
597 else if (data->prevTail != InvalidBlockNumber)
598 {
599 /*
600 * New tail
601 */
602 if (XLogReadBufferForRedo(record, 1, &buffer) == BLK_NEEDS_REDO)
603 {
604 Page page = BufferGetPage(buffer);
605
606 GinPageGetOpaque(page)->rightlink = data->newRightlink;
607
608 PageSetLSN(page, lsn);
609 MarkBufferDirty(buffer);
610 }
611 if (BufferIsValid(buffer))
612 UnlockReleaseBuffer(buffer);
613 }
614
615 UnlockReleaseBuffer(metabuffer);
616}
static bool PageIsEmpty(const PageData *page)
Definition: bufpage.h:224
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52

References Assert(), BLK_NEEDS_REDO, BufferGetBlockNumber(), BufferGetPage(), BufferIsValid(), data, elog, XLogReaderState::EndRecPtr, ERROR, FirstOffsetNumber, GIN_METAPAGE_BLKNO, GinInitMetabuffer(), GinPageGetMeta, GinPageGetOpaque, i, IndexTupleSize(), InvalidBlockNumber, InvalidOffsetNumber, MarkBufferDirty(), OffsetNumberNext, PageAddItem, PageGetMaxOffsetNumber(), PageIsEmpty(), PageSetLSN(), UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogReadBufferForRedo(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by gin_redo().

ginRedoVacuumDataLeafPage()

static void ginRedoVacuumDataLeafPage ( XLogReaderStaterecord )
static

Definition at line 451 of file ginxlog.c.

452{
453 XLogRecPtr lsn = record->EndRecPtr;
454 Buffer buffer;
455
456 if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
457 {
458 Page page = BufferGetPage(buffer);
459 Size len;
461
462 xlrec = (ginxlogVacuumDataLeafPage *) XLogRecGetBlockData(record, 0, &len);
463
464 Assert(GinPageIsLeaf(page));
465 Assert(GinPageIsData(page));
466
467 ginRedoRecompress(page, &xlrec->data);
468 PageSetLSN(page, lsn);
469 MarkBufferDirty(buffer);
470 }
471 if (BufferIsValid(buffer))
472 UnlockReleaseBuffer(buffer);
473}
ginxlogRecompressDataLeaf data
Definition: ginxlog.h:145

References Assert(), BLK_NEEDS_REDO, BufferGetPage(), BufferIsValid(), ginxlogVacuumDataLeafPage::data, XLogReaderState::EndRecPtr, GinPageIsData, GinPageIsLeaf, ginRedoRecompress(), len, MarkBufferDirty(), PageSetLSN(), UnlockReleaseBuffer(), XLogReadBufferForRedo(), and XLogRecGetBlockData().

Referenced by gin_redo().

ginRedoVacuumPage()

static void ginRedoVacuumPage ( XLogReaderStaterecord )
static

Definition at line 439 of file ginxlog.c.

440{
441 Buffer buffer;
442
443 if (XLogReadBufferForRedo(record, 0, &buffer) != BLK_RESTORED)
444 {
445 elog(ERROR, "replay of gin entry tree page vacuum did not restore the page");
446 }
447 UnlockReleaseBuffer(buffer);
448}

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

Referenced by gin_redo().

Variable Documentation

opCtx

static

Definition at line 22 of file ginxlog.c.

Referenced by gin_redo(), gin_xlog_cleanup(), gin_xlog_startup(), and ginInsertCleanup().

AltStyle によって変換されたページ (->オリジナル) /