On Wed, Feb 15, 2012 at 2:54 AM, Tom Lane <t...@sss.pgh.pa.us> wrote:

> Alexander Korotkov <aekorot...@gmail.com> 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 (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to