Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 24992c6

Browse files
committed
Rewrite PageIndexDeleteNoCompact into a form that only deletes 1 tuple.
The full generality of deleting an arbitrary number of tuples is no longer needed, so let's save some code and cycles by replacing the original coding with an implementation based on PageIndexTupleDelete. We can always get back the old code from git if we need it again for new callers (though I don't care for its willingness to mess with line pointers it wasn't told to mess with). Discussion: <552.1473445163@sss.pgh.pa.us>
1 parent 1a4be10 commit 24992c6

File tree

4 files changed

+74
-129
lines changed

4 files changed

+74
-129
lines changed

src/backend/access/brin/brin_pageops.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ brin_doupdate(Relation idxrel, BlockNumber pagesPerRange,
245245
if (extended)
246246
brin_page_init(BufferGetPage(newbuf), BRIN_PAGETYPE_REGULAR);
247247

248-
PageIndexDeleteNoCompact(oldpage, &oldoff, 1);
248+
PageIndexTupleDeleteNoCompact(oldpage, oldoff);
249249
newoff = PageAddItem(newpage, (Item) newtup, newsz,
250250
InvalidOffsetNumber, false, false);
251251
if (newoff == InvalidOffsetNumber)

src/backend/access/brin/brin_xlog.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,8 @@ brin_xlog_update(XLogReaderState *record)
148148
page = (Page) BufferGetPage(buffer);
149149

150150
offnum = xlrec->oldOffnum;
151-
if (PageGetMaxOffsetNumber(page) + 1 < offnum)
152-
elog(PANIC, "brin_xlog_update: invalid max offset number");
153151

154-
PageIndexDeleteNoCompact(page, &offnum, 1);
152+
PageIndexTupleDeleteNoCompact(page, offnum);
155153

156154
PageSetLSN(page, lsn);
157155
MarkBufferDirty(buffer);

src/backend/storage/page/bufpage.c

+71-123
Original file line numberDiff line numberDiff line change
@@ -415,8 +415,7 @@ PageRestoreTempPage(Page tempPage, Page oldPage)
415415
}
416416

417417
/*
418-
* sorting support for PageRepairFragmentation, PageIndexMultiDelete,
419-
* PageIndexDeleteNoCompact
418+
* sorting support for PageRepairFragmentation and PageIndexMultiDelete
420419
*/
421420
typedef struct itemIdSortData
422421
{
@@ -762,15 +761,14 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum)
762761
* Now move everything between the old upper bound (beginning of tuple
763762
* space) and the beginning of the deleted tuple forward, so that space in
764763
* the middle of the page is left free. If we've just deleted the tuple
765-
* at the beginning of tuple space, then there's no need to do the copy
766-
* (and bcopy on some architectures SEGV's if asked to move zero bytes).
764+
* at the beginning of tuple space, then there's no need to do the copy.
767765
*/
768766

769767
/* beginning of tuple space */
770768
addr = (char *) page + phdr->pd_upper;
771769

772770
if (offset > phdr->pd_upper)
773-
memmove(addr + size, addr, (int) (offset - phdr->pd_upper));
771+
memmove(addr + size, addr, offset - phdr->pd_upper);
774772

775773
/* adjust free space boundary pointers */
776774
phdr->pd_upper += size;
@@ -918,155 +916,105 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
918916
compactify_tuples(itemidbase, nused, page);
919917
}
920918

919+
921920
/*
922-
* PageIndexDeleteNoCompact
923-
* Delete the given items for an index page, and defragment the resulting
924-
* free space, but do not compact the item pointers array.
925-
*
926-
* itemnos is the array of tuples to delete; nitems is its size. maxIdxTuples
927-
* is the maximum number of tuples that can exist in a page.
921+
* PageIndexTupleDeleteNoCompact
928922
*
929-
* Unused items at the end of the array are removed.
923+
* Remove the specified tuple from an index page, but set its line pointer
924+
* to "unused" instead of compacting it out, except that it can be removed
925+
* if it's the last line pointer on the page.
930926
*
931927
* This is used for index AMs that require that existing TIDs of live tuples
932-
* remain unchanged.
928+
* remain unchanged, and are willing to allow unused line pointers instead.
933929
*/
934930
void
935-
PageIndexDeleteNoCompact(Page page, OffsetNumber *itemnos, int nitems)
931+
PageIndexTupleDeleteNoCompact(Page page, OffsetNumber offnum)
936932
{
937933
PageHeader phdr = (PageHeader) page;
938-
LocationIndex pd_lower = phdr->pd_lower;
939-
LocationIndex pd_upper = phdr->pd_upper;
940-
LocationIndex pd_special = phdr->pd_special;
934+
char *addr;
935+
ItemId tup;
936+
Size size;
937+
unsigned offset;
941938
int nline;
942-
bool empty;
943-
OffsetNumber offnum;
944-
int nextitm;
945939

946940
/*
947941
* As with PageRepairFragmentation, paranoia seems justified.
948942
*/
949-
if (pd_lower < SizeOfPageHeaderData ||
950-
pd_lower > pd_upper ||
951-
pd_upper > pd_special ||
952-
pd_special > BLCKSZ ||
953-
pd_special != MAXALIGN(pd_special))
943+
if (phdr->pd_lower < SizeOfPageHeaderData ||
944+
phdr->pd_lower > phdr->pd_upper ||
945+
phdr->pd_upper > phdr->pd_special ||
946+
phdr->pd_special > BLCKSZ ||
947+
phdr->pd_special != MAXALIGN(phdr->pd_special))
954948
ereport(ERROR,
955949
(errcode(ERRCODE_DATA_CORRUPTED),
956950
errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u",
957-
pd_lower, pd_upper, pd_special)));
951+
phdr->pd_lower, phdr->pd_upper, phdr->pd_special)));
952+
953+
nline = PageGetMaxOffsetNumber(page);
954+
if ((int) offnum <= 0 || (int) offnum > nline)
955+
elog(ERROR, "invalid index offnum: %u", offnum);
956+
957+
tup = PageGetItemId(page, offnum);
958+
Assert(ItemIdHasStorage(tup));
959+
size = ItemIdGetLength(tup);
960+
offset = ItemIdGetOffset(tup);
961+
962+
if (offset < phdr->pd_upper || (offset + size) > phdr->pd_special ||
963+
offset != MAXALIGN(offset))
964+
ereport(ERROR,
965+
(errcode(ERRCODE_DATA_CORRUPTED),
966+
errmsg("corrupted item pointer: offset = %u, size = %u",
967+
offset, (unsigned int) size)));
968+
969+
/* Amount of space to actually be deleted */
970+
size = MAXALIGN(size);
958971

959972
/*
960-
* Scan the existing item pointer array and mark as unused those that are
961-
* in our kill-list; make sure any non-interesting ones are marked unused
962-
* as well.
973+
* Either set the item pointer to "unused", or zap it if it's the last
974+
* one. (Note: it's possible that the next-to-last one(s) are already
975+
* unused, but we do not trouble to try to compact them out if so.)
963976
*/
964-
nline = PageGetMaxOffsetNumber(page);
965-
empty = true;
966-
nextitm = 0;
967-
for (offnum = FirstOffsetNumber; offnum <= nline; offnum = OffsetNumberNext(offnum))
977+
if ((int) offnum < nline)
978+
ItemIdSetUnused(tup);
979+
else
968980
{
969-
ItemId lp;
970-
ItemLength itemlen;
971-
ItemOffset offset;
981+
phdr->pd_lower -= sizeof(ItemIdData);
982+
nline--; /* there's one less than when we started */
983+
}
972984

973-
lp = PageGetItemId(page, offnum);
985+
/*
986+
* Now move everything between the old upper bound (beginning of tuple
987+
* space) and the beginning of the deleted tuple forward, so that space in
988+
* the middle of the page is left free. If we've just deleted the tuple
989+
* at the beginning of tuple space, then there's no need to do the copy.
990+
*/
974991

975-
itemlen = ItemIdGetLength(lp);
976-
offset = ItemIdGetOffset(lp);
992+
/* beginning of tuple space */
993+
addr = (char *) page + phdr->pd_upper;
977994

978-
if (ItemIdIsUsed(lp))
979-
{
980-
if (offset < pd_upper ||
981-
(offset + itemlen) > pd_special ||
982-
offset != MAXALIGN(offset))
983-
ereport(ERROR,
984-
(errcode(ERRCODE_DATA_CORRUPTED),
985-
errmsg("corrupted item pointer: offset = %u, length = %u",
986-
offset, (unsigned int) itemlen)));
987-
988-
if (nextitm < nitems && offnum == itemnos[nextitm])
989-
{
990-
/* this one is on our list to delete, so mark it unused */
991-
ItemIdSetUnused(lp);
992-
nextitm++;
993-
}
994-
else if (ItemIdHasStorage(lp))
995-
{
996-
/* This one's live -- must do the compaction dance */
997-
empty = false;
998-
}
999-
else
1000-
{
1001-
/* get rid of this one too */
1002-
ItemIdSetUnused(lp);
1003-
}
1004-
}
1005-
}
995+
if (offset > phdr->pd_upper)
996+
memmove(addr + size, addr, offset - phdr->pd_upper);
1006997

1007-
/* this will catch invalid or out-of-order itemnos[] */
1008-
if (nextitm != nitems)
1009-
elog(ERROR, "incorrect index offsets supplied");
998+
/* adjust free space boundary pointer */
999+
phdr->pd_upper += size;
10101000

1011-
if (empty)
1012-
{
1013-
/* Page is completely empty, so just reset it quickly */
1014-
phdr->pd_lower = SizeOfPageHeaderData;
1015-
phdr->pd_upper = pd_special;
1016-
}
1017-
else
1001+
/*
1002+
* Finally, we need to adjust the linp entries that remain.
1003+
*
1004+
* Anything that used to be before the deleted tuple's data was moved
1005+
* forward by the size of the deleted tuple.
1006+
*/
1007+
if (!PageIsEmpty(page))
10181008
{
1019-
/* There are live items: need to compact the page the hard way */
1020-
itemIdSortData itemidbase[MaxOffsetNumber];
1021-
itemIdSort itemidptr;
10221009
int i;
1023-
Size totallen;
10241010

1025-
/*
1026-
* Scan the page taking note of each item that we need to preserve.
1027-
* This includes both live items (those that contain data) and
1028-
* interspersed unused ones. It's critical to preserve these unused
1029-
* items, because otherwise the offset numbers for later live items
1030-
* would change, which is not acceptable. Unused items might get used
1031-
* again later; that is fine.
1032-
*/
1033-
itemidptr = itemidbase;
1034-
totallen = 0;
1035-
PageClearHasFreeLinePointers(page);
1036-
for (i = 0; i < nline; i++)
1011+
for (i = 1; i <= nline; i++)
10371012
{
1038-
ItemId lp;
1039-
1040-
itemidptr->offsetindex = i;
1013+
ItemId ii = PageGetItemId(phdr, i);
10411014

1042-
lp = PageGetItemId(page, i + 1);
1043-
if (ItemIdHasStorage(lp))
1044-
{
1045-
itemidptr->itemoff = ItemIdGetOffset(lp);
1046-
itemidptr->alignedlen = MAXALIGN(ItemIdGetLength(lp));
1047-
totallen += itemidptr->alignedlen;
1048-
itemidptr++;
1049-
}
1050-
else
1051-
{
1052-
PageSetHasFreeLinePointers(page);
1053-
ItemIdSetUnused(lp);
1054-
}
1015+
if (ItemIdHasStorage(ii) && ItemIdGetOffset(ii) <= offset)
1016+
ii->lp_off += size;
10551017
}
1056-
nline = itemidptr - itemidbase;
1057-
/* By here, there are exactly nline elements in itemidbase array */
1058-
1059-
if (totallen > (Size) (pd_special - pd_lower))
1060-
ereport(ERROR,
1061-
(errcode(ERRCODE_DATA_CORRUPTED),
1062-
errmsg("corrupted item lengths: total %u, available space %u",
1063-
(unsigned int) totallen, pd_special - pd_lower)));
1064-
1065-
/*
1066-
* Defragment the data areas of each tuple, being careful to preserve
1067-
* each item's position in the linp array.
1068-
*/
1069-
compactify_tuples(itemidbase, nline, page);
10701018
}
10711019
}
10721020

src/include/storage/bufpage.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,7 @@ extern Size PageGetExactFreeSpace(Page page);
429429
extern Size PageGetHeapFreeSpace(Page page);
430430
extern void PageIndexTupleDelete(Page page, OffsetNumber offset);
431431
extern void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems);
432-
extern void PageIndexDeleteNoCompact(Page page, OffsetNumber *itemnos,
433-
int nitems);
432+
extern void PageIndexTupleDeleteNoCompact(Page page, OffsetNumber offset);
434433
extern bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum,
435434
Item newtup, Size newsize);
436435
extern char *PageSetChecksumCopy(Page page, BlockNumber blkno);

0 commit comments

Comments
 (0)