]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - lib/libc/db/btree/bt_split.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / lib / libc / db / btree / bt_split.c
1 /*-
2  * Copyright (c) 1990, 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Mike Olson.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 4. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #if defined(LIBC_SCCS) && !defined(lint)
34 static char sccsid[] = "@(#)bt_split.c  8.10 (Berkeley) 1/9/95";
35 #endif /* LIBC_SCCS and not lint */
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/types.h>
40
41 #include <limits.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45
46 #include <db.h>
47 #include "btree.h"
48
49 static int       bt_broot(BTREE *, PAGE *, PAGE *, PAGE *);
50 static PAGE     *bt_page(BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
51 static int       bt_preserve(BTREE *, pgno_t);
52 static PAGE     *bt_psplit(BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t);
53 static PAGE     *bt_root(BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
54 static int       bt_rroot(BTREE *, PAGE *, PAGE *, PAGE *);
55 static recno_t   rec_total(PAGE *);
56
57 #ifdef STATISTICS
58 u_long  bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved;
59 #endif
60
61 /*
62  * __BT_SPLIT -- Split the tree.
63  *
64  * Parameters:
65  *      t:      tree
66  *      sp:     page to split
67  *      key:    key to insert
68  *      data:   data to insert
69  *      flags:  BIGKEY/BIGDATA flags
70  *      ilen:   insert length
71  *      skip:   index to leave open
72  *
73  * Returns:
74  *      RET_ERROR, RET_SUCCESS
75  */
76 int
77 __bt_split(BTREE *t, PAGE *sp, const DBT *key, const DBT *data, int flags,
78     size_t ilen, u_int32_t argskip)
79 {
80         BINTERNAL *bi;
81         BLEAF *bl, *tbl;
82         DBT a, b;
83         EPGNO *parent;
84         PAGE *h, *l, *r, *lchild, *rchild;
85         indx_t nxtindex;
86         u_int16_t skip;
87         u_int32_t n, nbytes, nksize;
88         int parentsplit;
89         char *dest;
90
91         /*
92          * Split the page into two pages, l and r.  The split routines return
93          * a pointer to the page into which the key should be inserted and with
94          * skip set to the offset which should be used.  Additionally, l and r
95          * are pinned.
96          */
97         skip = argskip;
98         h = sp->pgno == P_ROOT ?
99             bt_root(t, sp, &l, &r, &skip, ilen) :
100             bt_page(t, sp, &l, &r, &skip, ilen);
101         if (h == NULL)
102                 return (RET_ERROR);
103
104         /*
105          * Insert the new key/data pair into the leaf page.  (Key inserts
106          * always cause a leaf page to split first.)
107          */
108         h->linp[skip] = h->upper -= ilen;
109         dest = (char *)h + h->upper;
110         if (F_ISSET(t, R_RECNO))
111                 WR_RLEAF(dest, data, flags)
112         else
113                 WR_BLEAF(dest, key, data, flags)
114
115         /* If the root page was split, make it look right. */
116         if (sp->pgno == P_ROOT &&
117             (F_ISSET(t, R_RECNO) ?
118             bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
119                 goto err2;
120
121         /*
122          * Now we walk the parent page stack -- a LIFO stack of the pages that
123          * were traversed when we searched for the page that split.  Each stack
124          * entry is a page number and a page index offset.  The offset is for
125          * the page traversed on the search.  We've just split a page, so we
126          * have to insert a new key into the parent page.
127          *
128          * If the insert into the parent page causes it to split, may have to
129          * continue splitting all the way up the tree.  We stop if the root
130          * splits or the page inserted into didn't have to split to hold the
131          * new key.  Some algorithms replace the key for the old page as well
132          * as the new page.  We don't, as there's no reason to believe that the
133          * first key on the old page is any better than the key we have, and,
134          * in the case of a key being placed at index 0 causing the split, the
135          * key is unavailable.
136          *
137          * There are a maximum of 5 pages pinned at any time.  We keep the left
138          * and right pages pinned while working on the parent.   The 5 are the
139          * two children, left parent and right parent (when the parent splits)
140          * and the root page or the overflow key page when calling bt_preserve.
141          * This code must make sure that all pins are released other than the
142          * root page or overflow page which is unlocked elsewhere.
143          */
144         while ((parent = BT_POP(t)) != NULL) {
145                 lchild = l;
146                 rchild = r;
147
148                 /* Get the parent page. */
149                 if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
150                         goto err2;
151
152                 /*
153                  * The new key goes ONE AFTER the index, because the split
154                  * was to the right.
155                  */
156                 skip = parent->index + 1;
157
158                 /*
159                  * Calculate the space needed on the parent page.
160                  *
161                  * Prefix trees: space hack when inserting into BINTERNAL
162                  * pages.  Retain only what's needed to distinguish between
163                  * the new entry and the LAST entry on the page to its left.
164                  * If the keys compare equal, retain the entire key.  Note,
165                  * we don't touch overflow keys, and the entire key must be
166                  * retained for the next-to-left most key on the leftmost
167                  * page of each level, or the search will fail.  Applicable
168                  * ONLY to internal pages that have leaf pages as children.
169                  * Further reduction of the key between pairs of internal
170                  * pages loses too much information.
171                  */
172                 switch (rchild->flags & P_TYPE) {
173                 case P_BINTERNAL:
174                         bi = GETBINTERNAL(rchild, 0);
175                         nbytes = NBINTERNAL(bi->ksize);
176                         break;
177                 case P_BLEAF:
178                         bl = GETBLEAF(rchild, 0);
179                         nbytes = NBINTERNAL(bl->ksize);
180                         if (t->bt_pfx && !(bl->flags & P_BIGKEY) &&
181                             (h->prevpg != P_INVALID || skip > 1)) {
182                                 tbl = GETBLEAF(lchild, NEXTINDEX(lchild) - 1);
183                                 a.size = tbl->ksize;
184                                 a.data = tbl->bytes;
185                                 b.size = bl->ksize;
186                                 b.data = bl->bytes;
187                                 nksize = t->bt_pfx(&a, &b);
188                                 n = NBINTERNAL(nksize);
189                                 if (n < nbytes) {
190 #ifdef STATISTICS
191                                         bt_pfxsaved += nbytes - n;
192 #endif
193                                         nbytes = n;
194                                 } else
195                                         nksize = 0;
196                         } else
197                                 nksize = 0;
198                         break;
199                 case P_RINTERNAL:
200                 case P_RLEAF:
201                         nbytes = NRINTERNAL;
202                         break;
203                 default:
204                         abort();
205                 }
206
207                 /* Split the parent page if necessary or shift the indices. */
208                 if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t)) {
209                         sp = h;
210                         h = h->pgno == P_ROOT ?
211                             bt_root(t, h, &l, &r, &skip, nbytes) :
212                             bt_page(t, h, &l, &r, &skip, nbytes);
213                         if (h == NULL)
214                                 goto err1;
215                         parentsplit = 1;
216                 } else {
217                         if (skip < (nxtindex = NEXTINDEX(h)))
218                                 memmove(h->linp + skip + 1, h->linp + skip,
219                                     (nxtindex - skip) * sizeof(indx_t));
220                         h->lower += sizeof(indx_t);
221                         parentsplit = 0;
222                 }
223
224                 /* Insert the key into the parent page. */
225                 switch (rchild->flags & P_TYPE) {
226                 case P_BINTERNAL:
227                         h->linp[skip] = h->upper -= nbytes;
228                         dest = (char *)h + h->linp[skip];
229                         memmove(dest, bi, nbytes);
230                         ((BINTERNAL *)dest)->pgno = rchild->pgno;
231                         break;
232                 case P_BLEAF:
233                         h->linp[skip] = h->upper -= nbytes;
234                         dest = (char *)h + h->linp[skip];
235                         WR_BINTERNAL(dest, nksize ? nksize : bl->ksize,
236                             rchild->pgno, bl->flags & P_BIGKEY);
237                         memmove(dest, bl->bytes, nksize ? nksize : bl->ksize);
238                         if (bl->flags & P_BIGKEY &&
239                             bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
240                                 goto err1;
241                         break;
242                 case P_RINTERNAL:
243                         /*
244                          * Update the left page count.  If split
245                          * added at index 0, fix the correct page.
246                          */
247                         if (skip > 0)
248                                 dest = (char *)h + h->linp[skip - 1];
249                         else
250                                 dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
251                         ((RINTERNAL *)dest)->nrecs = rec_total(lchild);
252                         ((RINTERNAL *)dest)->pgno = lchild->pgno;
253
254                         /* Update the right page count. */
255                         h->linp[skip] = h->upper -= nbytes;
256                         dest = (char *)h + h->linp[skip];
257                         ((RINTERNAL *)dest)->nrecs = rec_total(rchild);
258                         ((RINTERNAL *)dest)->pgno = rchild->pgno;
259                         break;
260                 case P_RLEAF:
261                         /*
262                          * Update the left page count.  If split
263                          * added at index 0, fix the correct page.
264                          */
265                         if (skip > 0)
266                                 dest = (char *)h + h->linp[skip - 1];
267                         else
268                                 dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
269                         ((RINTERNAL *)dest)->nrecs = NEXTINDEX(lchild);
270                         ((RINTERNAL *)dest)->pgno = lchild->pgno;
271
272                         /* Update the right page count. */
273                         h->linp[skip] = h->upper -= nbytes;
274                         dest = (char *)h + h->linp[skip];
275                         ((RINTERNAL *)dest)->nrecs = NEXTINDEX(rchild);
276                         ((RINTERNAL *)dest)->pgno = rchild->pgno;
277                         break;
278                 default:
279                         abort();
280                 }
281
282                 /* Unpin the held pages. */
283                 if (!parentsplit) {
284                         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
285                         break;
286                 }
287
288                 /* If the root page was split, make it look right. */
289                 if (sp->pgno == P_ROOT &&
290                     (F_ISSET(t, R_RECNO) ?
291                     bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
292                         goto err1;
293
294                 mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
295                 mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
296         }
297
298         /* Unpin the held pages. */
299         mpool_put(t->bt_mp, l, MPOOL_DIRTY);
300         mpool_put(t->bt_mp, r, MPOOL_DIRTY);
301
302         /* Clear any pages left on the stack. */
303         return (RET_SUCCESS);
304
305         /*
306          * If something fails in the above loop we were already walking back
307          * up the tree and the tree is now inconsistent.  Nothing much we can
308          * do about it but release any memory we're holding.
309          */
310 err1:   mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
311         mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
312
313 err2:   mpool_put(t->bt_mp, l, 0);
314         mpool_put(t->bt_mp, r, 0);
315         __dbpanic(t->bt_dbp);
316         return (RET_ERROR);
317 }
318
319 /*
320  * BT_PAGE -- Split a non-root page of a btree.
321  *
322  * Parameters:
323  *      t:      tree
324  *      h:      root page
325  *      lp:     pointer to left page pointer
326  *      rp:     pointer to right page pointer
327  *      skip:   pointer to index to leave open
328  *      ilen:   insert length
329  *
330  * Returns:
331  *      Pointer to page in which to insert or NULL on error.
332  */
333 static PAGE *
334 bt_page(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen)
335 {
336         PAGE *l, *r, *tp;
337         pgno_t npg;
338
339 #ifdef STATISTICS
340         ++bt_split;
341 #endif
342         /* Put the new right page for the split into place. */
343         if ((r = __bt_new(t, &npg)) == NULL)
344                 return (NULL);
345         r->pgno = npg;
346         r->lower = BTDATAOFF;
347         r->upper = t->bt_psize;
348         r->nextpg = h->nextpg;
349         r->prevpg = h->pgno;
350         r->flags = h->flags & P_TYPE;
351
352         /*
353          * If we're splitting the last page on a level because we're appending
354          * a key to it (skip is NEXTINDEX()), it's likely that the data is
355          * sorted.  Adding an empty page on the side of the level is less work
356          * and can push the fill factor much higher than normal.  If we're
357          * wrong it's no big deal, we'll just do the split the right way next
358          * time.  It may look like it's equally easy to do a similar hack for
359          * reverse sorted data, that is, split the tree left, but it's not.
360          * Don't even try.
361          */
362         if (h->nextpg == P_INVALID && *skip == NEXTINDEX(h)) {
363 #ifdef STATISTICS
364                 ++bt_sortsplit;
365 #endif
366                 h->nextpg = r->pgno;
367                 r->lower = BTDATAOFF + sizeof(indx_t);
368                 *skip = 0;
369                 *lp = h;
370                 *rp = r;
371                 return (r);
372         }
373
374         /* Put the new left page for the split into place. */
375         if ((l = (PAGE *)calloc(1, t->bt_psize)) == NULL) {
376                 mpool_put(t->bt_mp, r, 0);
377                 return (NULL);
378         }
379         l->pgno = h->pgno;
380         l->nextpg = r->pgno;
381         l->prevpg = h->prevpg;
382         l->lower = BTDATAOFF;
383         l->upper = t->bt_psize;
384         l->flags = h->flags & P_TYPE;
385
386         /* Fix up the previous pointer of the page after the split page. */
387         if (h->nextpg != P_INVALID) {
388                 if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) {
389                         free(l);
390                         /* XXX mpool_free(t->bt_mp, r->pgno); */
391                         return (NULL);
392                 }
393                 tp->prevpg = r->pgno;
394                 mpool_put(t->bt_mp, tp, MPOOL_DIRTY);
395         }
396
397         /*
398          * Split right.  The key/data pairs aren't sorted in the btree page so
399          * it's simpler to copy the data from the split page onto two new pages
400          * instead of copying half the data to the right page and compacting
401          * the left page in place.  Since the left page can't change, we have
402          * to swap the original and the allocated left page after the split.
403          */
404         tp = bt_psplit(t, h, l, r, skip, ilen);
405
406         /* Move the new left page onto the old left page. */
407         memmove(h, l, t->bt_psize);
408         if (tp == l)
409                 tp = h;
410         free(l);
411
412         *lp = h;
413         *rp = r;
414         return (tp);
415 }
416
417 /*
418  * BT_ROOT -- Split the root page of a btree.
419  *
420  * Parameters:
421  *      t:      tree
422  *      h:      root page
423  *      lp:     pointer to left page pointer
424  *      rp:     pointer to right page pointer
425  *      skip:   pointer to index to leave open
426  *      ilen:   insert length
427  *
428  * Returns:
429  *      Pointer to page in which to insert or NULL on error.
430  */
431 static PAGE *
432 bt_root(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen)
433 {
434         PAGE *l, *r, *tp;
435         pgno_t lnpg, rnpg;
436
437 #ifdef STATISTICS
438         ++bt_split;
439         ++bt_rootsplit;
440 #endif
441         /* Put the new left and right pages for the split into place. */
442         if ((l = __bt_new(t, &lnpg)) == NULL ||
443             (r = __bt_new(t, &rnpg)) == NULL)
444                 return (NULL);
445         l->pgno = lnpg;
446         r->pgno = rnpg;
447         l->nextpg = r->pgno;
448         r->prevpg = l->pgno;
449         l->prevpg = r->nextpg = P_INVALID;
450         l->lower = r->lower = BTDATAOFF;
451         l->upper = r->upper = t->bt_psize;
452         l->flags = r->flags = h->flags & P_TYPE;
453
454         /* Split the root page. */
455         tp = bt_psplit(t, h, l, r, skip, ilen);
456
457         *lp = l;
458         *rp = r;
459         return (tp);
460 }
461
462 /*
463  * BT_RROOT -- Fix up the recno root page after it has been split.
464  *
465  * Parameters:
466  *      t:      tree
467  *      h:      root page
468  *      l:      left page
469  *      r:      right page
470  *
471  * Returns:
472  *      RET_ERROR, RET_SUCCESS
473  */
474 static int
475 bt_rroot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
476 {
477         char *dest;
478
479         /* Insert the left and right keys, set the header information. */
480         h->linp[0] = h->upper = t->bt_psize - NRINTERNAL;
481         dest = (char *)h + h->upper;
482         WR_RINTERNAL(dest,
483             l->flags & P_RLEAF ? NEXTINDEX(l) : rec_total(l), l->pgno);
484
485         h->linp[1] = h->upper -= NRINTERNAL;
486         dest = (char *)h + h->upper;
487         WR_RINTERNAL(dest,
488             r->flags & P_RLEAF ? NEXTINDEX(r) : rec_total(r), r->pgno);
489
490         h->lower = BTDATAOFF + 2 * sizeof(indx_t);
491
492         /* Unpin the root page, set to recno internal page. */
493         h->flags &= ~P_TYPE;
494         h->flags |= P_RINTERNAL;
495         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
496
497         return (RET_SUCCESS);
498 }
499
500 /*
501  * BT_BROOT -- Fix up the btree root page after it has been split.
502  *
503  * Parameters:
504  *      t:      tree
505  *      h:      root page
506  *      l:      left page
507  *      r:      right page
508  *
509  * Returns:
510  *      RET_ERROR, RET_SUCCESS
511  */
512 static int
513 bt_broot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
514 {
515         BINTERNAL *bi;
516         BLEAF *bl;
517         u_int32_t nbytes;
518         char *dest;
519
520         /*
521          * If the root page was a leaf page, change it into an internal page.
522          * We copy the key we split on (but not the key's data, in the case of
523          * a leaf page) to the new root page.
524          *
525          * The btree comparison code guarantees that the left-most key on any
526          * level of the tree is never used, so it doesn't need to be filled in.
527          */
528         nbytes = NBINTERNAL(0);
529         h->linp[0] = h->upper = t->bt_psize - nbytes;
530         dest = (char *)h + h->upper;
531         WR_BINTERNAL(dest, 0, l->pgno, 0);
532
533         switch (h->flags & P_TYPE) {
534         case P_BLEAF:
535                 bl = GETBLEAF(r, 0);
536                 nbytes = NBINTERNAL(bl->ksize);
537                 h->linp[1] = h->upper -= nbytes;
538                 dest = (char *)h + h->upper;
539                 WR_BINTERNAL(dest, bl->ksize, r->pgno, 0);
540                 memmove(dest, bl->bytes, bl->ksize);
541
542                 /*
543                  * If the key is on an overflow page, mark the overflow chain
544                  * so it isn't deleted when the leaf copy of the key is deleted.
545                  */
546                 if (bl->flags & P_BIGKEY &&
547                     bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
548                         return (RET_ERROR);
549                 break;
550         case P_BINTERNAL:
551                 bi = GETBINTERNAL(r, 0);
552                 nbytes = NBINTERNAL(bi->ksize);
553                 h->linp[1] = h->upper -= nbytes;
554                 dest = (char *)h + h->upper;
555                 memmove(dest, bi, nbytes);
556                 ((BINTERNAL *)dest)->pgno = r->pgno;
557                 break;
558         default:
559                 abort();
560         }
561
562         /* There are two keys on the page. */
563         h->lower = BTDATAOFF + 2 * sizeof(indx_t);
564
565         /* Unpin the root page, set to btree internal page. */
566         h->flags &= ~P_TYPE;
567         h->flags |= P_BINTERNAL;
568         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
569
570         return (RET_SUCCESS);
571 }
572
573 /*
574  * BT_PSPLIT -- Do the real work of splitting the page.
575  *
576  * Parameters:
577  *      t:      tree
578  *      h:      page to be split
579  *      l:      page to put lower half of data
580  *      r:      page to put upper half of data
581  *      pskip:  pointer to index to leave open
582  *      ilen:   insert length
583  *
584  * Returns:
585  *      Pointer to page in which to insert.
586  */
587 static PAGE *
588 bt_psplit(BTREE *t, PAGE *h, PAGE *l, PAGE *r, indx_t *pskip, size_t ilen)
589 {
590         BINTERNAL *bi;
591         BLEAF *bl;
592         CURSOR *c;
593         RLEAF *rl;
594         PAGE *rval;
595         void *src;
596         indx_t full, half, nxt, off, skip, top, used;
597         u_int32_t nbytes;
598         int bigkeycnt, isbigkey;
599
600         /*
601          * Split the data to the left and right pages.  Leave the skip index
602          * open.  Additionally, make some effort not to split on an overflow
603          * key.  This makes internal page processing faster and can save
604          * space as overflow keys used by internal pages are never deleted.
605          */
606         bigkeycnt = 0;
607         skip = *pskip;
608         full = t->bt_psize - BTDATAOFF;
609         half = full / 2;
610         used = 0;
611         for (nxt = off = 0, top = NEXTINDEX(h); nxt < top; ++off) {
612                 if (skip == off) {
613                         nbytes = ilen;
614                         isbigkey = 0;           /* XXX: not really known. */
615                 } else
616                         switch (h->flags & P_TYPE) {
617                         case P_BINTERNAL:
618                                 src = bi = GETBINTERNAL(h, nxt);
619                                 nbytes = NBINTERNAL(bi->ksize);
620                                 isbigkey = bi->flags & P_BIGKEY;
621                                 break;
622                         case P_BLEAF:
623                                 src = bl = GETBLEAF(h, nxt);
624                                 nbytes = NBLEAF(bl);
625                                 isbigkey = bl->flags & P_BIGKEY;
626                                 break;
627                         case P_RINTERNAL:
628                                 src = GETRINTERNAL(h, nxt);
629                                 nbytes = NRINTERNAL;
630                                 isbigkey = 0;
631                                 break;
632                         case P_RLEAF:
633                                 src = rl = GETRLEAF(h, nxt);
634                                 nbytes = NRLEAF(rl);
635                                 isbigkey = 0;
636                                 break;
637                         default:
638                                 abort();
639                         }
640
641                 /*
642                  * If the key/data pairs are substantial fractions of the max
643                  * possible size for the page, it's possible to get situations
644                  * where we decide to try and copy too much onto the left page.
645                  * Make sure that doesn't happen.
646                  */
647                 if ((skip <= off && used + nbytes + sizeof(indx_t) >= full) ||
648                     nxt == top - 1) {
649                         --off;
650                         break;
651                 }
652
653                 /* Copy the key/data pair, if not the skipped index. */
654                 if (skip != off) {
655                         ++nxt;
656
657                         l->linp[off] = l->upper -= nbytes;
658                         memmove((char *)l + l->upper, src, nbytes);
659                 }
660
661                 used += nbytes + sizeof(indx_t);
662                 if (used >= half) {
663                         if (!isbigkey || bigkeycnt == 3)
664                                 break;
665                         else
666                                 ++bigkeycnt;
667                 }
668         }
669
670         /*
671          * Off is the last offset that's valid for the left page.
672          * Nxt is the first offset to be placed on the right page.
673          */
674         l->lower += (off + 1) * sizeof(indx_t);
675
676         /*
677          * If splitting the page that the cursor was on, the cursor has to be
678          * adjusted to point to the same record as before the split.  If the
679          * cursor is at or past the skipped slot, the cursor is incremented by
680          * one.  If the cursor is on the right page, it is decremented by the
681          * number of records split to the left page.
682          */
683         c = &t->bt_cursor;
684         if (F_ISSET(c, CURS_INIT) && c->pg.pgno == h->pgno) {
685                 if (c->pg.index >= skip)
686                         ++c->pg.index;
687                 if (c->pg.index < nxt)                  /* Left page. */
688                         c->pg.pgno = l->pgno;
689                 else {                                  /* Right page. */
690                         c->pg.pgno = r->pgno;
691                         c->pg.index -= nxt;
692                 }
693         }
694
695         /*
696          * If the skipped index was on the left page, just return that page.
697          * Otherwise, adjust the skip index to reflect the new position on
698          * the right page.
699          */
700         if (skip <= off) {
701                 skip = MAX_PAGE_OFFSET;
702                 rval = l;
703         } else {
704                 rval = r;
705                 *pskip -= nxt;
706         }
707
708         for (off = 0; nxt < top; ++off) {
709                 if (skip == nxt) {
710                         ++off;
711                         skip = MAX_PAGE_OFFSET;
712                 }
713                 switch (h->flags & P_TYPE) {
714                 case P_BINTERNAL:
715                         src = bi = GETBINTERNAL(h, nxt);
716                         nbytes = NBINTERNAL(bi->ksize);
717                         break;
718                 case P_BLEAF:
719                         src = bl = GETBLEAF(h, nxt);
720                         nbytes = NBLEAF(bl);
721                         break;
722                 case P_RINTERNAL:
723                         src = GETRINTERNAL(h, nxt);
724                         nbytes = NRINTERNAL;
725                         break;
726                 case P_RLEAF:
727                         src = rl = GETRLEAF(h, nxt);
728                         nbytes = NRLEAF(rl);
729                         break;
730                 default:
731                         abort();
732                 }
733                 ++nxt;
734                 r->linp[off] = r->upper -= nbytes;
735                 memmove((char *)r + r->upper, src, nbytes);
736         }
737         r->lower += off * sizeof(indx_t);
738
739         /* If the key is being appended to the page, adjust the index. */
740         if (skip == top)
741                 r->lower += sizeof(indx_t);
742
743         return (rval);
744 }
745
746 /*
747  * BT_PRESERVE -- Mark a chain of pages as used by an internal node.
748  *
749  * Chains of indirect blocks pointed to by leaf nodes get reclaimed when the
750  * record that references them gets deleted.  Chains pointed to by internal
751  * pages never get deleted.  This routine marks a chain as pointed to by an
752  * internal page.
753  *
754  * Parameters:
755  *      t:      tree
756  *      pg:     page number of first page in the chain.
757  *
758  * Returns:
759  *      RET_SUCCESS, RET_ERROR.
760  */
761 static int
762 bt_preserve(BTREE *t, pgno_t pg)
763 {
764         PAGE *h;
765
766         if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
767                 return (RET_ERROR);
768         h->flags |= P_PRESERVE;
769         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
770         return (RET_SUCCESS);
771 }
772
773 /*
774  * REC_TOTAL -- Return the number of recno entries below a page.
775  *
776  * Parameters:
777  *      h:      page
778  *
779  * Returns:
780  *      The number of recno entries below a page.
781  *
782  * XXX
783  * These values could be set by the bt_psplit routine.  The problem is that the
784  * entry has to be popped off of the stack etc. or the values have to be passed
785  * all the way back to bt_split/bt_rroot and it's not very clean.
786  */
787 static recno_t
788 rec_total(PAGE *h)
789 {
790         recno_t recs;
791         indx_t nxt, top;
792
793         for (recs = 0, nxt = 0, top = NEXTINDEX(h); nxt < top; ++nxt)
794                 recs += GETRINTERNAL(h, nxt)->nrecs;
795         return (recs);
796 }