@@ -280,80 +280,115 @@ ginFindParents(GinBtree btree, GinBtreeStack *stack,
280
280
}
281
281
282
282
/*
283
- * Insert value (stored in GinBtree) to tree described by stack
284
- *
285
- * During an index build, buildStats is non-null and the counters
286
- * it contains are incremented as needed.
283
+ * Returns true if the insertion is done, false if the page was split and
284
+ * downlink insertion is pending.
287
285
*
288
- * NB: the passed-in stack is freed, as though by freeGinBtreeStack .
286
+ * stack->buffer is locked on entry, and is kept locked .
289
287
*/
290
- void
291
- ginInsertValue (GinBtree btree , GinBtreeStack * stack , GinStatsData * buildStats )
288
+ static bool
289
+ ginPlaceToPage (GinBtree btree , BlockNumber rootBlkno , GinBtreeStack * stack ,
290
+ GinStatsData * buildStats )
292
291
{
293
- GinBtreeStack * parent ;
294
- BlockNumber rootBlkno ;
295
- Page page ,
296
- rpage ,
297
- lpage ;
292
+ Page page = BufferGetPage (stack -> buffer );
293
+ XLogRecData * rdata ;
294
+ bool fit ;
298
295
299
- /* extract root BlockNumber from stack */
300
- Assert (stack != NULL );
301
- parent = stack ;
302
- while (parent -> parent )
303
- parent = parent -> parent ;
304
- rootBlkno = parent -> blkno ;
305
- Assert (BlockNumberIsValid (rootBlkno ));
296
+ START_CRIT_SECTION ();
297
+ fit = btree -> placeToPage (btree , stack -> buffer , stack -> off , & rdata );
298
+ if (fit )
299
+ {
300
+ MarkBufferDirty (stack -> buffer );
306
301
307
- /* this loop crawls up the stack until the insertion is complete */
308
- for (;;)
302
+ if (RelationNeedsWAL (btree -> index ))
303
+ {
304
+ XLogRecPtr recptr ;
305
+
306
+ recptr = XLogInsert (RM_GIN_ID , XLOG_GIN_INSERT , rdata );
307
+ PageSetLSN (page , recptr );
308
+ }
309
+
310
+ END_CRIT_SECTION ();
311
+
312
+ return true;
313
+ }
314
+ else
309
315
{
310
- XLogRecData * rdata ;
316
+ /* Didn't fit, have to split */
317
+ Buffer rbuffer ;
318
+ Page newlpage ;
311
319
BlockNumber savedRightLink ;
312
- bool fit ;
320
+ GinBtreeStack * parent ;
321
+ Page lpage ,
322
+ rpage ;
323
+
324
+ END_CRIT_SECTION ();
325
+
326
+ rbuffer = GinNewBuffer (btree -> index );
313
327
314
- page = BufferGetPage (stack -> buffer );
315
328
savedRightLink = GinPageGetOpaque (page )-> rightlink ;
316
329
317
- START_CRIT_SECTION ();
318
- fit = btree -> placeToPage (btree , stack -> buffer , stack -> off , & rdata );
319
- if (fit )
330
+ /*
331
+ * newlpage is a pointer to memory page, it is not associated with
332
+ * a buffer. stack->buffer is not touched yet.
333
+ */
334
+ newlpage = btree -> splitPage (btree , stack -> buffer , rbuffer , stack -> off , & rdata );
335
+
336
+ ((ginxlogSplit * ) (rdata -> data ))-> rootBlkno = rootBlkno ;
337
+
338
+ /* During index build, count the newly-split page */
339
+ if (buildStats )
320
340
{
341
+ if (btree -> isData )
342
+ buildStats -> nDataPages ++ ;
343
+ else
344
+ buildStats -> nEntryPages ++ ;
345
+ }
346
+
347
+ parent = stack -> parent ;
348
+
349
+ if (parent == NULL )
350
+ {
351
+ /*
352
+ * split root, so we need to allocate new left page and place
353
+ * pointer on root to left and right page
354
+ */
355
+ Buffer lbuffer = GinNewBuffer (btree -> index );
356
+
357
+ ((ginxlogSplit * ) (rdata -> data ))-> isRootSplit = TRUE;
358
+ ((ginxlogSplit * ) (rdata -> data ))-> rrlink = InvalidBlockNumber ;
359
+
360
+ lpage = BufferGetPage (lbuffer );
361
+ rpage = BufferGetPage (rbuffer );
362
+
363
+ GinPageGetOpaque (rpage )-> rightlink = InvalidBlockNumber ;
364
+ GinPageGetOpaque (newlpage )-> rightlink = BufferGetBlockNumber (rbuffer );
365
+ ((ginxlogSplit * ) (rdata -> data ))-> lblkno = BufferGetBlockNumber (lbuffer );
366
+
367
+ START_CRIT_SECTION ();
368
+
369
+ GinInitBuffer (stack -> buffer , GinPageGetOpaque (newlpage )-> flags & ~GIN_LEAF );
370
+ PageRestoreTempPage (newlpage , lpage );
371
+ btree -> fillRoot (btree , stack -> buffer , lbuffer , rbuffer );
372
+
373
+ MarkBufferDirty (rbuffer );
374
+ MarkBufferDirty (lbuffer );
321
375
MarkBufferDirty (stack -> buffer );
322
376
323
377
if (RelationNeedsWAL (btree -> index ))
324
378
{
325
379
XLogRecPtr recptr ;
326
380
327
- recptr = XLogInsert (RM_GIN_ID , XLOG_GIN_INSERT , rdata );
381
+ recptr = XLogInsert (RM_GIN_ID , XLOG_GIN_SPLIT , rdata );
328
382
PageSetLSN (page , recptr );
383
+ PageSetLSN (lpage , recptr );
384
+ PageSetLSN (rpage , recptr );
329
385
}
330
386
331
- LockBuffer (stack -> buffer , GIN_UNLOCK );
332
- END_CRIT_SECTION ();
333
-
334
- freeGinBtreeStack (stack );
335
-
336
- return ;
337
- }
338
- else
339
- {
340
- /* Didn't fit, have to split */
341
- Buffer rbuffer ;
342
- Page newlpage ;
343
-
387
+ UnlockReleaseBuffer (rbuffer );
388
+ UnlockReleaseBuffer (lbuffer );
344
389
END_CRIT_SECTION ();
345
390
346
- rbuffer = GinNewBuffer (btree -> index );
347
-
348
- /*
349
- * newlpage is a pointer to memory page, it is not associated with
350
- * a buffer. stack->buffer is not touched yet.
351
- */
352
- newlpage = btree -> splitPage (btree , stack -> buffer , rbuffer , stack -> off , & rdata );
353
-
354
- ((ginxlogSplit * ) (rdata -> data ))-> rootBlkno = rootBlkno ;
355
-
356
- /* During index build, count the newly-split page */
391
+ /* During index build, count the newly-added root page */
357
392
if (buildStats )
358
393
{
359
394
if (btree -> isData )
@@ -362,98 +397,83 @@ ginInsertValue(GinBtree btree, GinBtreeStack *stack, GinStatsData *buildStats)
362
397
buildStats -> nEntryPages ++ ;
363
398
}
364
399
365
- parent = stack -> parent ;
366
-
367
- if (parent == NULL )
368
- {
369
- /*
370
- * split root, so we need to allocate new left page and place
371
- * pointer on root to left and right page
372
- */
373
- Buffer lbuffer = GinNewBuffer (btree -> index );
374
-
375
- ((ginxlogSplit * ) (rdata -> data ))-> isRootSplit = TRUE;
376
- ((ginxlogSplit * ) (rdata -> data ))-> rrlink = InvalidBlockNumber ;
377
-
378
- page = BufferGetPage (stack -> buffer );
379
- lpage = BufferGetPage (lbuffer );
380
- rpage = BufferGetPage (rbuffer );
381
-
382
- GinPageGetOpaque (rpage )-> rightlink = InvalidBlockNumber ;
383
- GinPageGetOpaque (newlpage )-> rightlink = BufferGetBlockNumber (rbuffer );
384
- ((ginxlogSplit * ) (rdata -> data ))-> lblkno = BufferGetBlockNumber (lbuffer );
385
-
386
- START_CRIT_SECTION ();
387
-
388
- GinInitBuffer (stack -> buffer , GinPageGetOpaque (newlpage )-> flags & ~GIN_LEAF );
389
- PageRestoreTempPage (newlpage , lpage );
390
- btree -> fillRoot (btree , stack -> buffer , lbuffer , rbuffer );
391
-
392
- MarkBufferDirty (rbuffer );
393
- MarkBufferDirty (lbuffer );
394
- MarkBufferDirty (stack -> buffer );
400
+ return true;
401
+ }
402
+ else
403
+ {
404
+ /* split non-root page */
405
+ ((ginxlogSplit * ) (rdata -> data ))-> isRootSplit = FALSE;
406
+ ((ginxlogSplit * ) (rdata -> data ))-> rrlink = savedRightLink ;
395
407
396
- if (RelationNeedsWAL (btree -> index ))
397
- {
398
- XLogRecPtr recptr ;
408
+ lpage = BufferGetPage (stack -> buffer );
409
+ rpage = BufferGetPage (rbuffer );
399
410
400
- recptr = XLogInsert (RM_GIN_ID , XLOG_GIN_SPLIT , rdata );
401
- PageSetLSN (page , recptr );
402
- PageSetLSN (lpage , recptr );
403
- PageSetLSN (rpage , recptr );
404
- }
411
+ GinPageGetOpaque (rpage )-> rightlink = savedRightLink ;
412
+ GinPageGetOpaque (newlpage )-> rightlink = BufferGetBlockNumber (rbuffer );
405
413
406
- UnlockReleaseBuffer (rbuffer );
407
- UnlockReleaseBuffer (lbuffer );
408
- LockBuffer (stack -> buffer , GIN_UNLOCK );
409
- END_CRIT_SECTION ();
414
+ START_CRIT_SECTION ();
415
+ PageRestoreTempPage (newlpage , lpage );
410
416
411
- freeGinBtreeStack (stack );
417
+ MarkBufferDirty (rbuffer );
418
+ MarkBufferDirty (stack -> buffer );
412
419
413
- /* During index build, count the newly-added root page */
414
- if (buildStats )
415
- {
416
- if (btree -> isData )
417
- buildStats -> nDataPages ++ ;
418
- else
419
- buildStats -> nEntryPages ++ ;
420
- }
420
+ if (RelationNeedsWAL (btree -> index ))
421
+ {
422
+ XLogRecPtr recptr ;
421
423
422
- return ;
424
+ recptr = XLogInsert (RM_GIN_ID , XLOG_GIN_SPLIT , rdata );
425
+ PageSetLSN (lpage , recptr );
426
+ PageSetLSN (rpage , recptr );
423
427
}
424
- else
425
- {
426
- /* split non-root page */
427
- ((ginxlogSplit * ) (rdata -> data ))-> isRootSplit = FALSE;
428
- ((ginxlogSplit * ) (rdata -> data ))-> rrlink = savedRightLink ;
428
+ UnlockReleaseBuffer (rbuffer );
429
+ END_CRIT_SECTION ();
429
430
430
- lpage = BufferGetPage (stack -> buffer );
431
- rpage = BufferGetPage (rbuffer );
431
+ return false;
432
+ }
433
+ }
434
+ }
432
435
433
- GinPageGetOpaque (rpage )-> rightlink = savedRightLink ;
434
- GinPageGetOpaque (newlpage )-> rightlink = BufferGetBlockNumber (rbuffer );
436
+ /*
437
+ * Insert value (stored in GinBtree) to tree described by stack
438
+ *
439
+ * During an index build, buildStats is non-null and the counters
440
+ * it contains are incremented as needed.
441
+ *
442
+ * NB: the passed-in stack is freed, as though by freeGinBtreeStack.
443
+ */
444
+ void
445
+ ginInsertValue (GinBtree btree , GinBtreeStack * stack , GinStatsData * buildStats )
446
+ {
447
+ GinBtreeStack * parent ;
448
+ BlockNumber rootBlkno ;
449
+ Page page ;
450
+
451
+ /* extract root BlockNumber from stack */
452
+ Assert (stack != NULL );
453
+ parent = stack ;
454
+ while (parent -> parent )
455
+ parent = parent -> parent ;
456
+ rootBlkno = parent -> blkno ;
457
+ Assert (BlockNumberIsValid (rootBlkno ));
435
458
436
- START_CRIT_SECTION ();
437
- PageRestoreTempPage (newlpage , lpage );
459
+ /* this loop crawls up the stack until the insertion is complete */
460
+ for (;;)
461
+ {
462
+ bool done ;
438
463
439
- MarkBufferDirty (rbuffer );
440
- MarkBufferDirty (stack -> buffer );
464
+ done = ginPlaceToPage (btree , rootBlkno , stack , buildStats );
441
465
442
- if (RelationNeedsWAL (btree -> index ))
443
- {
444
- XLogRecPtr recptr ;
466
+ /* just to be extra sure we don't delete anything by accident... */
467
+ btree -> isDelete = FALSE;
445
468
446
- recptr = XLogInsert (RM_GIN_ID , XLOG_GIN_SPLIT , rdata );
447
- PageSetLSN (lpage , recptr );
448
- PageSetLSN (rpage , recptr );
449
- }
450
- UnlockReleaseBuffer (rbuffer );
451
- END_CRIT_SECTION ();
452
- }
469
+ if (done )
470
+ {
471
+ LockBuffer (stack -> buffer , GIN_UNLOCK );
472
+ freeGinBtreeStack (stack );
473
+ break ;
453
474
}
454
475
455
476
btree -> prepareDownlink (btree , stack -> buffer );
456
- btree -> isDelete = FALSE;
457
477
458
478
/* search parent to lock */
459
479
LockBuffer (parent -> buffer , GIN_EXCLUSIVE );
0 commit comments