On Wed, Feb 15, 2012 at 2:54 AM, Tom Lane <[email protected]> wrote:
> Alexander Korotkov <[email protected]> writes:
> > ITSM, I found the problem. This piece of code is triggering an error. It
> > assumes each page of corresponding to have initialized buffer. That
> should
> > be true because we're inserting index tuples from up to down while
> > splits propagate from down to up.
> > But this assumptions becomes false we turn buffer off in the root page.
> So,
> > root page can produce pages without initialized buffers when splits.
>
> Hmm ... can we tighten the error check rather than just remove it? It
> feels less than safe to assume that a hash-entry-not-found condition
> *must* reflect a corner-case situation like that. At the very least
> I'd like to see it verify that we'd turned off buffering before deciding
> this is OK. Better, would it be practical to make dummy entries in the
> hash table even after turning buffers off, so that the logic here
> becomes
>
> if (!found) error;
> else if (entry is dummy) return without doing anything;
> else proceed;
>
> regards, tom lane
>
Ok, there is another patch fixes this problem. Instead of error triggering
remove it adds empty buffers on root page split if needed.
------
With best regards,
Alexander Korotkov.
*** a/src/backend/access/gist/gistbuild.c
--- b/src/backend/access/gist/gistbuild.c
***************
*** 668,677 **** gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer,
if (is_split && BufferGetBlockNumber(buffer) == GIST_ROOT_BLKNO)
{
GISTBufferingInsertStack *oldroot = gfbb->rootitem;
! Page page = BufferGetPage(buffer);
! ItemId iid;
! IndexTuple idxtuple;
! BlockNumber leftmostchild;
gfbb->rootitem = (GISTBufferingInsertStack *) MemoryContextAlloc(
gfbb->context, sizeof(GISTBufferingInsertStack));
--- 668,678 ----
if (is_split && BufferGetBlockNumber(buffer) == GIST_ROOT_BLKNO)
{
GISTBufferingInsertStack *oldroot = gfbb->rootitem;
! Page page = BufferGetPage(buffer);
! ItemId iid;
! IndexTuple idxtuple;
! BlockNumber leftmostchild;
! OffsetNumber maxoff, i;
gfbb->rootitem = (GISTBufferingInsertStack *) MemoryContextAlloc(
gfbb->context, sizeof(GISTBufferingInsertStack));
***************
*** 694,699 **** gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer,
--- 695,719 ----
oldroot->parent = gfbb->rootitem;
oldroot->blkno = leftmostchild;
oldroot->downlinkoffnum = InvalidOffsetNumber;
+
+ /*
+ * If root page split produce new pages on leven which have buffers
+ * then initialize empty buffers there.
+ */
+ if (LEVEL_HAS_BUFFERS(oldroot->level, gfbb))
+ {
+ maxoff = PageGetMaxOffsetNumber(page);
+ for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
+ {
+ iid = PageGetItemId(page, i);
+ idxtuple = (IndexTuple) PageGetItem(page, iid);
+ gistGetNodeBuffer(gfbb,
+ buildstate->giststate,
+ ItemPointerGetBlockNumber(&(idxtuple->t_tid)),
+ i,
+ gfbb->rootitem);
+ }
+ }
}
if (splitinfo)
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers