/* * Place tuple on page and fills WAL record * * If the tuple doesn't fit, returns false without modifying the page. * * On insertion to an internal node, in addition to inserting the given item, * the downlink of the existing item at 'off' is updated to point to * 'updateblkno'. */ static GinPlaceToPageRC entryPlaceToPage(GinBtree btree, Buffer buf, GinBtreeStack *stack, void *insertPayload, BlockNumber updateblkno, XLogRecData **prdata, Page *newlpage, Page *newrpage) { GinBtreeEntryInsertData *insertData = insertPayload; Page page = BufferGetPage(buf); OffsetNumber off = stack->off; OffsetNumber placed; int cnt = 0; /* these must be static so they can be returned to caller */ static XLogRecData rdata[3]; static ginxlogInsertEntry data; /* quick exit if it doesn't fit */ if (!entryIsEnoughSpace(btree, buf, off, insertData)) { entrySplitPage(btree, buf, stack, insertPayload, updateblkno, prdata, newlpage, newrpage); return SPLIT; } START_CRIT_SECTION(); *prdata = rdata; entryPreparePage(btree, page, off, insertData, updateblkno); placed = PageAddItem(page, (Item) insertData->entry, IndexTupleSize(insertData->entry), off, false, false); if (placed != off) elog(ERROR, "failed to add item to index page in \"%s\"", RelationGetRelationName(btree->index)); data.isDelete = insertData->isDelete; data.offset = off; rdata[cnt].buffer = buf; rdata[cnt].buffer_std = true; rdata[cnt].data = (char *) &data; rdata[cnt].len = offsetof(ginxlogInsertEntry, tuple); rdata[cnt].next = &rdata[cnt + 1]; cnt++; rdata[cnt].buffer = buf; rdata[cnt].buffer_std = true; rdata[cnt].data = (char *) insertData->entry; rdata[cnt].len = IndexTupleSize(insertData->entry); rdata[cnt].next = NULL; return INSERTED; }
/* * Place tuple on page and fills WAL record * * If the tuple doesn't fit, returns false without modifying the page. * * On insertion to an internal node, in addition to inserting the given item, * the downlink of the existing item at 'off' is updated to point to * 'updateblkno'. * * On INSERTED, registers the buffer as buffer ID 0, with data. * On SPLIT, returns rdata that represents the split pages in *prdata. */ static GinPlaceToPageRC entryPlaceToPage(GinBtree btree, Buffer buf, GinBtreeStack *stack, void *insertPayload, BlockNumber updateblkno, Page *newlpage, Page *newrpage) { GinBtreeEntryInsertData *insertData = insertPayload; Page page = BufferGetPage(buf, NULL, NULL, BGP_NO_SNAPSHOT_TEST); OffsetNumber off = stack->off; OffsetNumber placed; /* this must be static so it can be returned to caller. */ static ginxlogInsertEntry data; /* quick exit if it doesn't fit */ if (!entryIsEnoughSpace(btree, buf, off, insertData)) { entrySplitPage(btree, buf, stack, insertPayload, updateblkno, newlpage, newrpage); return SPLIT; } START_CRIT_SECTION(); entryPreparePage(btree, page, off, insertData, updateblkno); placed = PageAddItem(page, (Item) insertData->entry, IndexTupleSize(insertData->entry), off, false, false); if (placed != off) elog(ERROR, "failed to add item to index page in \"%s\"", RelationGetRelationName(btree->index)); if (RelationNeedsWAL(btree->index)) { data.isDelete = insertData->isDelete; data.offset = off; XLogBeginInsert(); XLogRegisterBuffer(0, buf, REGBUF_STANDARD); XLogRegisterBufData(0, (char *) &data, offsetof(ginxlogInsertEntry, tuple)); XLogRegisterBufData(0, (char *) insertData->entry, IndexTupleSize(insertData->entry)); } return INSERTED; }
/* * Prepare to insert data on an entry page. * * If it will fit, return GPTP_INSERT after doing whatever setup is needed * before we enter the insertion critical section. *ptp_workspace can be * set to pass information along to the execPlaceToPage function. * * If it won't fit, perform a page split and return two temporary page * images into *newlpage and *newrpage, with result GPTP_SPLIT. * * In neither case should the given page buffer be modified here. * * Note: on insertion to an internal node, in addition to inserting the given * item, the downlink of the existing item at stack->off will be updated to * point to updateblkno. */ static GinPlaceToPageRC entryBeginPlaceToPage(GinBtree btree, Buffer buf, GinBtreeStack *stack, void *insertPayload, BlockNumber updateblkno, void **ptp_workspace, Page *newlpage, Page *newrpage) { GinBtreeEntryInsertData *insertData = insertPayload; OffsetNumber off = stack->off; /* If it doesn't fit, deal with split case */ if (!entryIsEnoughSpace(btree, buf, off, insertData)) { entrySplitPage(btree, buf, stack, insertData, updateblkno, newlpage, newrpage); return GPTP_SPLIT; } /* Else, we're ready to proceed with insertion */ return GPTP_INSERT; }