8
8
* Portions Copyright (c) 1994, Regents of the University of California
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.31 2006/04/01 03:03:37 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.32 2006/04/13 03:53:05 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -51,32 +51,16 @@ log_incomplete_split(RelFileNode node, BlockNumber leftblk,
51
51
}
52
52
53
53
static void
54
- forget_matching_split (Relation reln , RelFileNode node ,
55
- BlockNumber insertblk , OffsetNumber offnum ,
56
- bool is_root )
54
+ forget_matching_split (RelFileNode node , BlockNumber downlink , bool is_root )
57
55
{
58
- Buffer buffer ;
59
- Page page ;
60
- IndexTuple itup ;
61
- BlockNumber rightblk ;
62
56
ListCell * l ;
63
57
64
- /* Get downlink TID from page */
65
- buffer = XLogReadBuffer (reln , insertblk , false);
66
- if (!BufferIsValid (buffer ))
67
- return ;
68
- page = (Page ) BufferGetPage (buffer );
69
- itup = (IndexTuple ) PageGetItem (page , PageGetItemId (page , offnum ));
70
- rightblk = ItemPointerGetBlockNumber (& (itup -> t_tid ));
71
- Assert (ItemPointerGetOffsetNumber (& (itup -> t_tid )) == P_HIKEY );
72
- UnlockReleaseBuffer (buffer );
73
-
74
58
foreach (l , incomplete_splits )
75
59
{
76
60
bt_incomplete_split * split = (bt_incomplete_split * ) lfirst (l );
77
61
78
62
if (RelFileNodeEquals (node , split -> node ) &&
79
- rightblk == split -> rightblk )
63
+ downlink == split -> rightblk )
80
64
{
81
65
if (is_root != split -> is_root )
82
66
elog (LOG , "forget_matching_split: fishy is_root data (expected %d, got %d)" ,
@@ -87,6 +71,20 @@ forget_matching_split(Relation reln, RelFileNode node,
87
71
}
88
72
}
89
73
74
+ /*
75
+ * _bt_restore_page -- re-enter all the index tuples on a page
76
+ *
77
+ * The page is freshly init'd, and *from (length len) is a copy of what
78
+ * had been its upper part (pd_upper to pd_special). We assume that the
79
+ * tuples had been added to the page in item-number order, and therefore
80
+ * the one with highest item number appears first (lowest on the page).
81
+ *
82
+ * NOTE: the way this routine is coded, the rebuilt page will have the items
83
+ * in correct itemno sequence, but physically the opposite order from the
84
+ * original, because we insert them in the opposite of itemno order. This
85
+ * does not matter in any current btree code, but it's something to keep an
86
+ * eye on. Is it worth changing just on general principles?
87
+ */
90
88
static void
91
89
_bt_restore_page (Page page , char * from , int len )
92
90
{
@@ -158,18 +156,24 @@ btree_xlog_insert(bool isleaf, bool ismeta,
158
156
char * datapos ;
159
157
int datalen ;
160
158
xl_btree_metadata md ;
159
+ BlockNumber downlink = 0 ;
161
160
162
161
datapos = (char * ) xlrec + SizeOfBtreeInsert ;
163
162
datalen = record -> xl_len - SizeOfBtreeInsert ;
163
+ if (!isleaf )
164
+ {
165
+ memcpy (& downlink , datapos , sizeof (BlockNumber ));
166
+ datapos += sizeof (BlockNumber );
167
+ datalen -= sizeof (BlockNumber );
168
+ }
164
169
if (ismeta )
165
170
{
166
171
memcpy (& md , datapos , sizeof (xl_btree_metadata ));
167
172
datapos += sizeof (xl_btree_metadata );
168
173
datalen -= sizeof (xl_btree_metadata );
169
174
}
170
175
171
- if ((record -> xl_info & XLR_BKP_BLOCK_1 ) && !ismeta &&
172
- incomplete_splits == NIL )
176
+ if ((record -> xl_info & XLR_BKP_BLOCK_1 ) && !ismeta && isleaf )
173
177
return ; /* nothing to do */
174
178
175
179
reln = XLogOpenRelation (xlrec -> target .node );
@@ -208,13 +212,8 @@ btree_xlog_insert(bool isleaf, bool ismeta,
208
212
md .fastroot , md .fastlevel );
209
213
210
214
/* Forget any split this insertion completes */
211
- if (!isleaf && incomplete_splits != NIL )
212
- {
213
- forget_matching_split (reln , xlrec -> target .node ,
214
- ItemPointerGetBlockNumber (& (xlrec -> target .tid )),
215
- ItemPointerGetOffsetNumber (& (xlrec -> target .tid )),
216
- false);
217
- }
215
+ if (!isleaf )
216
+ forget_matching_split (xlrec -> target .node , downlink , false);
218
217
}
219
218
220
219
static void
@@ -224,14 +223,17 @@ btree_xlog_split(bool onleft, bool isroot,
224
223
xl_btree_split * xlrec = (xl_btree_split * ) XLogRecGetData (record );
225
224
Relation reln ;
226
225
BlockNumber targetblk ;
226
+ OffsetNumber targetoff ;
227
227
BlockNumber leftsib ;
228
228
BlockNumber rightsib ;
229
+ BlockNumber downlink = 0 ;
229
230
Buffer buffer ;
230
231
Page page ;
231
232
BTPageOpaque pageop ;
232
233
233
234
reln = XLogOpenRelation (xlrec -> target .node );
234
235
targetblk = ItemPointerGetBlockNumber (& (xlrec -> target .tid ));
236
+ targetoff = ItemPointerGetOffsetNumber (& (xlrec -> target .tid ));
235
237
leftsib = (onleft ) ? targetblk : xlrec -> otherblk ;
236
238
rightsib = (onleft ) ? xlrec -> otherblk : targetblk ;
237
239
@@ -252,6 +254,16 @@ btree_xlog_split(bool onleft, bool isroot,
252
254
(char * ) xlrec + SizeOfBtreeSplit ,
253
255
xlrec -> leftlen );
254
256
257
+ if (onleft && xlrec -> level > 0 )
258
+ {
259
+ IndexTuple itup ;
260
+
261
+ /* extract downlink in the target tuple */
262
+ itup = (IndexTuple ) PageGetItem (page , PageGetItemId (page , targetoff ));
263
+ downlink = ItemPointerGetBlockNumber (& (itup -> t_tid ));
264
+ Assert (ItemPointerGetOffsetNumber (& (itup -> t_tid )) == P_HIKEY );
265
+ }
266
+
255
267
PageSetLSN (page , lsn );
256
268
PageSetTLI (page , ThisTimeLineID );
257
269
MarkBufferDirty (buffer );
@@ -274,6 +286,16 @@ btree_xlog_split(bool onleft, bool isroot,
274
286
(char * ) xlrec + SizeOfBtreeSplit + xlrec -> leftlen ,
275
287
record -> xl_len - SizeOfBtreeSplit - xlrec -> leftlen );
276
288
289
+ if (!onleft && xlrec -> level > 0 )
290
+ {
291
+ IndexTuple itup ;
292
+
293
+ /* extract downlink in the target tuple */
294
+ itup = (IndexTuple ) PageGetItem (page , PageGetItemId (page , targetoff ));
295
+ downlink = ItemPointerGetBlockNumber (& (itup -> t_tid ));
296
+ Assert (ItemPointerGetOffsetNumber (& (itup -> t_tid )) == P_HIKEY );
297
+ }
298
+
277
299
PageSetLSN (page , lsn );
278
300
PageSetTLI (page , ThisTimeLineID );
279
301
MarkBufferDirty (buffer );
@@ -308,13 +330,8 @@ btree_xlog_split(bool onleft, bool isroot,
308
330
}
309
331
310
332
/* Forget any split this insertion completes */
311
- if (xlrec -> level > 0 && incomplete_splits != NIL )
312
- {
313
- forget_matching_split (reln , xlrec -> target .node ,
314
- ItemPointerGetBlockNumber (& (xlrec -> target .tid )),
315
- ItemPointerGetOffsetNumber (& (xlrec -> target .tid )),
316
- false);
317
- }
333
+ if (xlrec -> level > 0 )
334
+ forget_matching_split (xlrec -> target .node , downlink , false);
318
335
319
336
/* The job ain't done till the parent link is inserted... */
320
337
log_incomplete_split (xlrec -> target .node ,
@@ -516,6 +533,7 @@ btree_xlog_newroot(XLogRecPtr lsn, XLogRecord *record)
516
533
Buffer buffer ;
517
534
Page page ;
518
535
BTPageOpaque pageop ;
536
+ BlockNumber downlink = 0 ;
519
537
520
538
reln = XLogOpenRelation (xlrec -> node );
521
539
buffer = XLogReadBuffer (reln , xlrec -> rootblk , true);
@@ -532,9 +550,17 @@ btree_xlog_newroot(XLogRecPtr lsn, XLogRecord *record)
532
550
pageop -> btpo_flags |= BTP_LEAF ;
533
551
534
552
if (record -> xl_len > SizeOfBtreeNewroot )
553
+ {
554
+ IndexTuple itup ;
555
+
535
556
_bt_restore_page (page ,
536
557
(char * ) xlrec + SizeOfBtreeNewroot ,
537
558
record -> xl_len - SizeOfBtreeNewroot );
559
+ /* extract downlink to the right-hand split page */
560
+ itup = (IndexTuple ) PageGetItem (page , PageGetItemId (page , P_FIRSTKEY ));
561
+ downlink = ItemPointerGetBlockNumber (& (itup -> t_tid ));
562
+ Assert (ItemPointerGetOffsetNumber (& (itup -> t_tid )) == P_HIKEY );
563
+ }
538
564
539
565
PageSetLSN (page , lsn );
540
566
PageSetTLI (page , ThisTimeLineID );
@@ -546,14 +572,8 @@ btree_xlog_newroot(XLogRecPtr lsn, XLogRecord *record)
546
572
xlrec -> rootblk , xlrec -> level );
547
573
548
574
/* Check to see if this satisfies any incomplete insertions */
549
- if (record -> xl_len > SizeOfBtreeNewroot &&
550
- incomplete_splits != NIL )
551
- {
552
- forget_matching_split (reln , xlrec -> node ,
553
- xlrec -> rootblk ,
554
- P_FIRSTKEY ,
555
- true);
556
- }
575
+ if (record -> xl_len > SizeOfBtreeNewroot )
576
+ forget_matching_split (xlrec -> node , downlink , true);
557
577
}
558
578
559
579
0 commit comments