@@ -325,9 +325,10 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
325
325
{
326
326
Page page = BufferGetPage (stack -> buffer );
327
327
XLogRecData * payloadrdata ;
328
- bool fit ;
328
+ GinPlaceToPageRC rc ;
329
329
uint16 xlflags = 0 ;
330
330
Page childpage = NULL ;
331
+ Page newlpage = NULL , newrpage = NULL ;
331
332
332
333
if (GinPageIsData (page ))
333
334
xlflags |= GIN_INSERT_ISDATA ;
@@ -345,16 +346,17 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
345
346
}
346
347
347
348
/*
348
- * Try to put the incoming tuple on the page. If it doesn't fit,
349
- * placeToPage method will return false and leave the page unmodified, and
350
- * we'll have to split the page.
349
+ * Try to put the incoming tuple on the page. placeToPage will decide
350
+ * if the page needs to be split.
351
351
*/
352
- START_CRIT_SECTION ();
353
- fit = btree -> placeToPage (btree , stack -> buffer , stack -> off ,
354
- insertdata , updateblkno ,
355
- & payloadrdata );
356
- if (fit )
352
+ rc = btree -> placeToPage (btree , stack -> buffer , stack ,
353
+ insertdata , updateblkno ,
354
+ & payloadrdata , & newlpage , & newrpage );
355
+ if (rc == UNMODIFIED )
356
+ return true;
357
+ else if (rc == INSERTED )
357
358
{
359
+ /* placeToPage did START_CRIT_SECTION() */
358
360
MarkBufferDirty (stack -> buffer );
359
361
360
362
/* An insert to an internal page finishes the split of the child. */
@@ -373,7 +375,6 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
373
375
374
376
xlrec .node = btree -> index -> rd_node ;
375
377
xlrec .blkno = BufferGetBlockNumber (stack -> buffer );
376
- xlrec .offset = stack -> off ;
377
378
xlrec .flags = xlflags ;
378
379
379
380
rdata [0 ].buffer = InvalidBuffer ;
@@ -415,20 +416,16 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
415
416
416
417
return true;
417
418
}
418
- else
419
+ else if ( rc == SPLIT )
419
420
{
420
421
/* Didn't fit, have to split */
421
422
Buffer rbuffer ;
422
- Page newlpage ;
423
423
BlockNumber savedRightLink ;
424
- Page rpage ;
425
424
XLogRecData rdata [2 ];
426
425
ginxlogSplit data ;
427
426
Buffer lbuffer = InvalidBuffer ;
428
427
Page newrootpg = NULL ;
429
428
430
- END_CRIT_SECTION ();
431
-
432
429
rbuffer = GinNewBuffer (btree -> index );
433
430
434
431
/* During index build, count the new page */
@@ -443,12 +440,9 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
443
440
savedRightLink = GinPageGetOpaque (page )-> rightlink ;
444
441
445
442
/*
446
- * newlpage is a pointer to memory page, it is not associated with a
447
- * buffer . stack->buffer is not touched yet.
443
+ * newlpage and newrpage are pointers to memory pages, not associated
444
+ * with buffers . stack->buffer is not touched yet.
448
445
*/
449
- newlpage = btree -> splitPage (btree , stack -> buffer , rbuffer , stack -> off ,
450
- insertdata , updateblkno ,
451
- & payloadrdata );
452
446
453
447
data .node = btree -> index -> rd_node ;
454
448
data .rblkno = BufferGetBlockNumber (rbuffer );
@@ -481,8 +475,6 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
481
475
else
482
476
rdata [0 ].next = payloadrdata ;
483
477
484
- rpage = BufferGetPage (rbuffer );
485
-
486
478
if (stack -> parent == NULL )
487
479
{
488
480
/*
@@ -508,7 +500,7 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
508
500
data .lblkno = BufferGetBlockNumber (lbuffer );
509
501
data .flags |= GIN_SPLIT_ROOT ;
510
502
511
- GinPageGetOpaque (rpage )-> rightlink = InvalidBlockNumber ;
503
+ GinPageGetOpaque (newrpage )-> rightlink = InvalidBlockNumber ;
512
504
GinPageGetOpaque (newlpage )-> rightlink = BufferGetBlockNumber (rbuffer );
513
505
514
506
/*
@@ -517,20 +509,20 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
517
509
* than overwriting the original page directly, so that we can still
518
510
* abort gracefully if this fails.)
519
511
*/
520
- newrootpg = PageGetTempPage (rpage );
521
- GinInitPage (newrootpg , GinPageGetOpaque (newlpage )-> flags & ~GIN_LEAF , BLCKSZ );
512
+ newrootpg = PageGetTempPage (newrpage );
513
+ GinInitPage (newrootpg , GinPageGetOpaque (newlpage )-> flags & ~( GIN_LEAF | GIN_COMPRESSED ) , BLCKSZ );
522
514
523
515
btree -> fillRoot (btree , newrootpg ,
524
516
BufferGetBlockNumber (lbuffer ), newlpage ,
525
- BufferGetBlockNumber (rbuffer ), rpage );
517
+ BufferGetBlockNumber (rbuffer ), newrpage );
526
518
}
527
519
else
528
520
{
529
521
/* split non-root page */
530
522
data .rrlink = savedRightLink ;
531
523
data .lblkno = BufferGetBlockNumber (stack -> buffer );
532
524
533
- GinPageGetOpaque (rpage )-> rightlink = savedRightLink ;
525
+ GinPageGetOpaque (newrpage )-> rightlink = savedRightLink ;
534
526
GinPageGetOpaque (newlpage )-> flags |= GIN_INCOMPLETE_SPLIT ;
535
527
GinPageGetOpaque (newlpage )-> rightlink = BufferGetBlockNumber (rbuffer );
536
528
}
@@ -550,16 +542,24 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
550
542
START_CRIT_SECTION ();
551
543
552
544
MarkBufferDirty (rbuffer );
545
+ MarkBufferDirty (stack -> buffer );
553
546
547
+ /*
548
+ * Restore the temporary copies over the real buffers. But don't free
549
+ * the temporary copies yet, WAL record data points to them.
550
+ */
554
551
if (stack -> parent == NULL )
555
552
{
556
- PageRestoreTempPage (newlpage , BufferGetPage (lbuffer ));
557
553
MarkBufferDirty (lbuffer );
558
- newlpage = newrootpg ;
554
+ memcpy (BufferGetPage (stack -> buffer ), newrootpg , BLCKSZ );
555
+ memcpy (BufferGetPage (lbuffer ), newlpage , BLCKSZ );
556
+ memcpy (BufferGetPage (rbuffer ), newrpage , BLCKSZ );
557
+ }
558
+ else
559
+ {
560
+ memcpy (BufferGetPage (stack -> buffer ), newlpage , BLCKSZ );
561
+ memcpy (BufferGetPage (rbuffer ), newrpage , BLCKSZ );
559
562
}
560
-
561
- PageRestoreTempPage (newlpage , BufferGetPage (stack -> buffer ));
562
- MarkBufferDirty (stack -> buffer );
563
563
564
564
/* write WAL record */
565
565
if (RelationNeedsWAL (btree -> index ))
@@ -568,7 +568,7 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
568
568
569
569
recptr = XLogInsert (RM_GIN_ID , XLOG_GIN_SPLIT , rdata );
570
570
PageSetLSN (BufferGetPage (stack -> buffer ), recptr );
571
- PageSetLSN (rpage , recptr );
571
+ PageSetLSN (BufferGetPage ( rbuffer ) , recptr );
572
572
if (stack -> parent == NULL )
573
573
PageSetLSN (BufferGetPage (lbuffer ), recptr );
574
574
}
@@ -582,6 +582,11 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
582
582
if (stack -> parent == NULL )
583
583
UnlockReleaseBuffer (lbuffer );
584
584
585
+ pfree (newlpage );
586
+ pfree (newrpage );
587
+ if (newrootpg )
588
+ pfree (newrootpg );
589
+
585
590
/*
586
591
* If we split the root, we're done. Otherwise the split is not
587
592
* complete until the downlink for the new page has been inserted to
@@ -592,6 +597,8 @@ ginPlaceToPage(GinBtree btree, GinBtreeStack *stack,
592
597
else
593
598
return false;
594
599
}
600
+ else
601
+ elog (ERROR , "unknown return code from GIN placeToPage method: %d" , rc );
595
602
}
596
603
597
604
/*
0 commit comments