8
8
* Portions Copyright (c) 1994, Regents of the University of California
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.129 2006/03/05 15:58:20 momjian Exp $
11
+ * $PostgreSQL: pgsql/src/backend/access/gist/gist.c,v 1.130 2006/03/30 23:03:09 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -90,6 +90,7 @@ gistbuild(PG_FUNCTION_ARGS)
90
90
double reltuples ;
91
91
GISTBuildState buildstate ;
92
92
Buffer buffer ;
93
+ Page page ;
93
94
94
95
/*
95
96
* We expect to be called exactly once for any index relation. If that's
@@ -104,33 +105,33 @@ gistbuild(PG_FUNCTION_ARGS)
104
105
105
106
/* initialize the root page */
106
107
buffer = gistNewBuffer (index );
108
+ Assert (BufferGetBlockNumber (buffer ) == GIST_ROOT_BLKNO );
109
+ page = BufferGetPage (buffer );
110
+
111
+ START_CRIT_SECTION ();
112
+
107
113
GISTInitBuffer (buffer , F_LEAF );
108
114
if (!index -> rd_istemp )
109
115
{
110
116
XLogRecPtr recptr ;
111
117
XLogRecData rdata ;
112
- Page page ;
113
118
114
- rdata .buffer = InvalidBuffer ;
115
119
rdata .data = (char * ) & (index -> rd_node );
116
120
rdata .len = sizeof (RelFileNode );
121
+ rdata .buffer = InvalidBuffer ;
117
122
rdata .next = NULL ;
118
123
119
- page = BufferGetPage (buffer );
120
-
121
- START_CRIT_SECTION ();
122
-
123
124
recptr = XLogInsert (RM_GIST_ID , XLOG_GIST_CREATE_INDEX , & rdata );
124
125
PageSetLSN (page , recptr );
125
126
PageSetTLI (page , ThisTimeLineID );
126
-
127
- END_CRIT_SECTION ();
128
127
}
129
128
else
130
- PageSetLSN (BufferGetPage ( buffer ) , XLogRecPtrForTemp );
129
+ PageSetLSN (page , XLogRecPtrForTemp );
131
130
LockBuffer (buffer , GIST_UNLOCK );
132
131
WriteBuffer (buffer );
133
132
133
+ END_CRIT_SECTION ();
134
+
134
135
/* build the index */
135
136
buildstate .numindexattrs = indexInfo -> ii_NumIndexAttrs ;
136
137
buildstate .indtuples = 0 ;
@@ -305,13 +306,27 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
305
306
bool is_splitted = false;
306
307
bool is_leaf = (GistPageIsLeaf (state -> stack -> page )) ? true : false;
307
308
309
+ /*
310
+ * XXX this code really ought to work by locking, but not modifying,
311
+ * all the buffers it needs; then starting a critical section; then
312
+ * modifying the buffers in an already-determined way and writing an
313
+ * XLOG record to reflect that. Since it doesn't, we've got to put
314
+ * a critical section around the entire process, which is horrible
315
+ * from a robustness point of view.
316
+ */
317
+ START_CRIT_SECTION ();
308
318
309
319
if (!is_leaf )
310
320
311
321
/*
312
322
* This node's key has been modified, either because a child split
313
323
* occurred or because we needed to adjust our key for an insert in a
314
324
* child node. Therefore, remove the old version of this node's key.
325
+ *
326
+ * Note: for WAL replay, in the non-split case we handle this by
327
+ * setting up a one-element todelete array; in the split case, it's
328
+ * handled implicitly because the tuple vector passed to gistSplit
329
+ * won't include this tuple.
315
330
*/
316
331
317
332
PageIndexTupleDelete (state -> stack -> page , state -> stack -> childoffnum );
@@ -336,9 +351,7 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
336
351
XLogRecData * rdata ;
337
352
338
353
rdata = formSplitRdata (state -> r -> rd_node , state -> stack -> blkno ,
339
- & (state -> key ), dist );
340
-
341
- START_CRIT_SECTION ();
354
+ is_leaf , & (state -> key ), dist );
342
355
343
356
recptr = XLogInsert (RM_GIST_ID , XLOG_GIST_PAGE_SPLIT , rdata );
344
357
ptr = dist ;
@@ -348,8 +361,6 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
348
361
PageSetTLI (BufferGetPage (ptr -> buffer ), ThisTimeLineID );
349
362
ptr = ptr -> next ;
350
363
}
351
-
352
- END_CRIT_SECTION ();
353
364
}
354
365
else
355
366
{
@@ -410,7 +421,6 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
410
421
else
411
422
ourpage = dist ;
412
423
413
-
414
424
/* now gets all needed data, and sets nsn's */
415
425
page = (Page ) BufferGetPage (ourpage -> buffer );
416
426
opaque = GistPageGetOpaque (page );
@@ -437,8 +447,11 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
437
447
WriteBuffer (ptr -> buffer );
438
448
ptr = ptr -> next ;
439
449
}
450
+
451
+ WriteNoReleaseBuffer (state -> stack -> buffer );
440
452
}
441
- WriteNoReleaseBuffer (state -> stack -> buffer );
453
+
454
+ END_CRIT_SECTION ();
442
455
}
443
456
else
444
457
{
@@ -451,7 +464,7 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
451
464
if (!state -> r -> rd_istemp )
452
465
{
453
466
OffsetNumber noffs = 0 ,
454
- offs [MAXALIGN ( sizeof ( OffsetNumber )) / sizeof ( OffsetNumber ) ];
467
+ offs [1 ];
455
468
XLogRecPtr recptr ;
456
469
XLogRecData * rdata ;
457
470
@@ -462,17 +475,14 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
462
475
noffs = 1 ;
463
476
}
464
477
465
- rdata = formUpdateRdata (state -> r -> rd_node , state -> stack -> blkno ,
466
- offs , noffs , false, state -> itup , state -> ituplen ,
478
+ rdata = formUpdateRdata (state -> r -> rd_node , state -> stack -> buffer ,
479
+ offs , noffs , false,
480
+ state -> itup , state -> ituplen ,
467
481
& (state -> key ));
468
482
469
- START_CRIT_SECTION ();
470
-
471
- recptr = XLogInsert (RM_GIST_ID , XLOG_GIST_ENTRY_UPDATE , rdata );
483
+ recptr = XLogInsert (RM_GIST_ID , XLOG_GIST_PAGE_UPDATE , rdata );
472
484
PageSetLSN (state -> stack -> page , recptr );
473
485
PageSetTLI (state -> stack -> page , ThisTimeLineID );
474
-
475
- END_CRIT_SECTION ();
476
486
}
477
487
else
478
488
PageSetLSN (state -> stack -> page , XLogRecPtrForTemp );
@@ -481,6 +491,8 @@ gistplacetopage(GISTInsertState *state, GISTSTATE *giststate)
481
491
state -> needInsertComplete = false;
482
492
WriteNoReleaseBuffer (state -> stack -> buffer );
483
493
494
+ END_CRIT_SECTION ();
495
+
484
496
if (!is_leaf ) /* small optimization: inform scan ablout
485
497
* deleting... */
486
498
gistadjscans (state -> r , GISTOP_DEL , state -> stack -> blkno ,
@@ -636,30 +648,14 @@ gistfindleaf(GISTInsertState *state, GISTSTATE *giststate)
636
648
}
637
649
638
650
/*
639
- * Should have the same interface as XLogReadBuffer
640
- */
641
- static Buffer
642
- gistReadAndLockBuffer (Relation r , BlockNumber blkno )
643
- {
644
- Buffer buffer = ReadBuffer (r , blkno );
645
-
646
- LockBuffer (buffer , GIST_SHARE );
647
- return buffer ;
648
- }
649
-
650
- /*
651
- * Traverse the tree to find path from root page.
651
+ * Traverse the tree to find path from root page to specified "child" block.
652
652
*
653
653
* returns from the begining of closest parent;
654
654
*
655
- * Function is used in both regular and recovery mode, so must work with
656
- * different read functions (gistReadAndLockBuffer and XLogReadBuffer)
657
- *
658
655
* To prevent deadlocks, this should lock only one page simultaneously.
659
656
*/
660
657
GISTInsertStack *
661
- gistFindPath (Relation r , BlockNumber child ,
662
- Buffer (* myReadBuffer ) (Relation , BlockNumber ))
658
+ gistFindPath (Relation r , BlockNumber child )
663
659
{
664
660
Page page ;
665
661
Buffer buffer ;
@@ -677,7 +673,8 @@ gistFindPath(Relation r, BlockNumber child,
677
673
678
674
while (top && top -> blkno != child )
679
675
{
680
- buffer = myReadBuffer (r , top -> blkno ); /* locks buffer */
676
+ buffer = ReadBuffer (r , top -> blkno );
677
+ LockBuffer (buffer , GIST_SHARE );
681
678
gistcheckpage (r , buffer );
682
679
page = (Page ) BufferGetPage (buffer );
683
680
@@ -833,7 +830,7 @@ gistFindCorrectParent(Relation r, GISTInsertStack *child)
833
830
}
834
831
835
832
/* ok, find new path */
836
- ptr = parent = gistFindPath (r , child -> blkno , gistReadAndLockBuffer );
833
+ ptr = parent = gistFindPath (r , child -> blkno );
837
834
Assert (ptr != NULL );
838
835
839
836
/* read all buffers as expected by caller */
@@ -1192,27 +1189,31 @@ gistnewroot(Relation r, Buffer buffer, IndexTuple *itup, int len, ItemPointer ke
1192
1189
1193
1190
Assert (BufferGetBlockNumber (buffer ) == GIST_ROOT_BLKNO );
1194
1191
page = BufferGetPage (buffer );
1195
- GISTInitBuffer (buffer , 0 );
1196
1192
1193
+ START_CRIT_SECTION ();
1194
+
1195
+ GISTInitBuffer (buffer , 0 ); /* XXX not F_LEAF? */
1197
1196
gistfillbuffer (r , page , itup , len , FirstOffsetNumber );
1197
+
1198
1198
if (!r -> rd_istemp )
1199
1199
{
1200
1200
XLogRecPtr recptr ;
1201
1201
XLogRecData * rdata ;
1202
1202
1203
- rdata = formUpdateRdata (r -> rd_node , GIST_ROOT_BLKNO ,
1204
- NULL , 0 , false, itup , len , key );
1205
-
1206
- START_CRIT_SECTION ();
1203
+ rdata = formUpdateRdata (r -> rd_node , buffer ,
1204
+ NULL , 0 , false,
1205
+ itup , len , key );
1207
1206
1208
1207
recptr = XLogInsert (RM_GIST_ID , XLOG_GIST_NEW_ROOT , rdata );
1209
1208
PageSetLSN (page , recptr );
1210
1209
PageSetTLI (page , ThisTimeLineID );
1211
-
1212
- END_CRIT_SECTION ();
1213
1210
}
1214
1211
else
1215
1212
PageSetLSN (page , XLogRecPtrForTemp );
1213
+
1214
+ WriteNoReleaseBuffer (buffer );
1215
+
1216
+ END_CRIT_SECTION ();
1216
1217
}
1217
1218
1218
1219
void
0 commit comments