00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "config.h"
00041
00042 #ifndef lint
00043 static const char revid[] = "$Id: bt__split_8c-source.html,v 1.1 2008/06/08 10:13:45 sebdiaz Exp $";
00044 #endif
00045
00046 #ifndef NO_SYSTEM_INCLUDES
00047 #include <sys/types.h>
00048
00049 #include <errno.h>
00050 #include <limits.h>
00051 #include <string.h>
00052 #endif
00053
00054 #include "db_int.h"
00055 #include "db_page.h"
00056 #include "db_shash.h"
00057 #include "lock.h"
00058 #include "btree.h"
00059
00060 #ifdef DEBUG
00061 #include "WordMonitor.h"
00062 #endif
00063
00064 static int __bam_broot __P((DBC *, PAGE *, PAGE *, PAGE *));
00065 static int __bam_page __P((DBC *, EPG *, EPG *));
00066 static int __bam_pinsert __P((DBC *, EPG *, PAGE *, PAGE *, int));
00067 static int __bam_psplit __P((DBC *, EPG *, PAGE *, PAGE *, db_indx_t *));
00068 static int __bam_root __P((DBC *, EPG *));
00069 static int __ram_root __P((DBC *, PAGE *, PAGE *, PAGE *));
00070
00071
00072
00073
00074
00075
00076
00077 int
00078 CDB___bam_split(dbc, arg)
00079 DBC *dbc;
00080 void *arg;
00081 {
00082 BTREE *t;
00083 BTREE_CURSOR *cp;
00084 DB *dbp;
00085 enum { UP, DOWN } dir;
00086 db_pgno_t root_pgno;
00087 int exact, level, ret;
00088
00089 dbp = dbc->dbp;
00090 cp = (BTREE_CURSOR *)dbc->internal;
00091 root_pgno = cp->root;
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 t = dbp->bt_internal;
00121 for (dir = UP, level = LEAFLEVEL;; dir == UP ? ++level : --level) {
00122
00123
00124
00125 if ((ret = (dbc->dbtype == DB_BTREE ?
00126 CDB___bam_search(dbc, arg, S_WRPAIR, level, NULL, &exact) :
00127 CDB___bam_rsearch(dbc,
00128 (db_recno_t *)arg, S_WRPAIR, level, &exact))) != 0)
00129 return (ret);
00130
00131
00132
00133
00134
00135
00136
00137 if (cp->ovflsize * 2 <=
00138 (db_indx_t)P_FREESPACE(cp->csp[0].page)) {
00139 CDB___bam_stkrel(dbc, STK_NOLOCK);
00140 return (0);
00141 }
00142 ret = cp->csp[0].page->pgno == root_pgno ?
00143 __bam_root(dbc, &cp->csp[0]) :
00144 __bam_page(dbc, &cp->csp[-1], &cp->csp[0]);
00145 BT_STK_CLR(cp);
00146
00147 switch (ret) {
00148 case 0:
00149
00150 if (level == LEAFLEVEL)
00151 return (0);
00152
00153
00154 if (dir == UP)
00155 dir = DOWN;
00156 break;
00157 case DB_NEEDSPLIT:
00158
00159
00160
00161
00162
00163
00164 if (dir == DOWN)
00165 dir = UP;
00166 break;
00167 default:
00168 return (ret);
00169 }
00170 }
00171
00172 }
00173
00174
00175
00176
00177
00178 static int
00179 __bam_root(dbc, cp)
00180 DBC *dbc;
00181 EPG *cp;
00182 {
00183 DB *dbp;
00184 DBT log_dbt;
00185 DB_LSN log_lsn;
00186 PAGE *lp, *rp;
00187 db_indx_t split;
00188 u_int32_t opflags;
00189 int ret;
00190
00191 dbp = dbc->dbp;
00192
00193
00194 if (cp->page->level >= MAXBTREELEVEL) {
00195 CDB___db_err(dbp->dbenv,
00196 "Too many btree levels: %d", cp->page->level);
00197 ret = ENOSPC;
00198 goto err;
00199 }
00200
00201
00202 lp = rp = NULL;
00203 if ((ret = CDB___db_new(dbc, TYPE_TAGS(cp->page), &lp)) != 0 ||
00204 (ret = CDB___db_new(dbc, TYPE_TAGS(cp->page), &rp)) != 0)
00205 goto err;
00206 P_INIT(lp, dbp->pgsize, lp->pgno,
00207 PGNO_INVALID, ISINTERNAL(cp->page) ? PGNO_INVALID : rp->pgno,
00208 cp->page->level, TYPE(cp->page), TAGS(cp->page));
00209 P_INIT(rp, dbp->pgsize, rp->pgno,
00210 ISINTERNAL(cp->page) ? PGNO_INVALID : lp->pgno, PGNO_INVALID,
00211 cp->page->level, TYPE(cp->page), TAGS(cp->page));
00212
00213
00214 if ((ret = __bam_psplit(dbc, cp, lp, rp, &split)) != 0)
00215 goto err;
00216
00217
00218 if (DB_LOGGING(dbc)) {
00219 memset(&log_dbt, 0, sizeof(log_dbt));
00220 log_dbt.data = cp->page;
00221 log_dbt.size = dbp->pgsize;
00222 ZERO_LSN(log_lsn);
00223 opflags = F_ISSET(
00224 (BTREE_CURSOR *)dbc->internal, C_RECNUM) ? SPL_NRECS : 0;
00225 if ((ret = CDB___bam_split_log(dbp->dbenv, dbc->txn,
00226 &LSN(cp->page), 0, dbp->log_fileid, PGNO(lp), &LSN(lp),
00227 PGNO(rp), &LSN(rp), (u_int32_t)NUM_ENT(lp), 0, &log_lsn,
00228 dbc->internal->root, &log_dbt, opflags)) != 0)
00229 goto err;
00230 LSN(lp) = LSN(rp) = LSN(cp->page);
00231 }
00232
00233
00234 if ((ret = (dbc->dbtype == DB_RECNO ?
00235 __ram_root(dbc, cp->page, lp, rp) :
00236 __bam_broot(dbc, cp->page, lp, rp))) != 0)
00237 goto err;
00238
00239
00240 CDB___bam_ca_split(dbp, cp->page->pgno, lp->pgno, rp->pgno, split, 1);
00241
00242
00243 (void)CDB_memp_fput(dbp->mpf, cp->page, DB_MPOOL_DIRTY);
00244 (void)__TLPUT(dbc, cp->lock);
00245 (void)CDB_memp_fput(dbp->mpf, lp, DB_MPOOL_DIRTY);
00246 (void)CDB_memp_fput(dbp->mpf, rp, DB_MPOOL_DIRTY);
00247
00248 return (0);
00249
00250 err: if (lp != NULL)
00251 (void)CDB___db_free(dbc, lp);
00252 if (rp != NULL)
00253 (void)CDB___db_free(dbc, rp);
00254 (void)CDB_memp_fput(dbp->mpf, cp->page, 0);
00255 (void)__TLPUT(dbc, cp->lock);
00256 return (ret);
00257 }
00258
00259
00260
00261
00262
00263 static int
00264 __bam_page(dbc, pp, cp)
00265 DBC *dbc;
00266 EPG *pp, *cp;
00267 {
00268 BTREE_CURSOR *bc;
00269 DBT log_dbt;
00270 DB_LSN log_lsn;
00271 DB *dbp;
00272 DB_LOCK tplock;
00273 DB_LSN save_lsn;
00274 PAGE *lp, *rp, *alloc_rp, *tp;
00275 db_indx_t split;
00276 u_int32_t opflags;
00277 int ret, t_ret;
00278
00279 dbp = dbc->dbp;
00280 alloc_rp = lp = rp = tp = NULL;
00281 tplock.off = LOCK_INVALID;
00282 ret = -1;
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 if ((ret = CDB___os_malloc(dbp->dbenv, dbp->pgsize, NULL, &rp)) != 0)
00302 goto err;
00303 P_INIT(rp, dbp->pgsize, 0,
00304 ISINTERNAL(cp->page) ? PGNO_INVALID : PGNO(cp->page),
00305 ISINTERNAL(cp->page) ? PGNO_INVALID : NEXT_PGNO(cp->page),
00306 cp->page->level, TYPE(cp->page), TAGS(cp->page));
00307
00308
00309
00310
00311
00312 if ((ret = CDB___os_malloc(dbp->dbenv, dbp->pgsize, NULL, &lp)) != 0)
00313 goto err;
00314 P_INIT(lp, dbp->pgsize, PGNO(cp->page),
00315 ISINTERNAL(cp->page) ? PGNO_INVALID : PREV_PGNO(cp->page),
00316 ISINTERNAL(cp->page) ? PGNO_INVALID : 0,
00317 cp->page->level, TYPE(cp->page), TAGS(cp->page));
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 if ((ret = __bam_psplit(dbc, cp, lp, rp, &split)) != 0)
00330 goto err;
00331
00332
00333
00334
00335
00336
00337
00338 if ((ret = __bam_pinsert(dbc, pp, lp, rp, 1)) != 0)
00339 goto err;
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 if (ISLEAF(cp->page) && NEXT_PGNO(cp->page) != PGNO_INVALID) {
00353 if ((ret = CDB___db_lget(dbc,
00354 0, NEXT_PGNO(cp->page), DB_LOCK_WRITE, 0, &tplock)) != 0)
00355 goto err;
00356 if ((ret =
00357 CDB_memp_fget(dbp->mpf, &NEXT_PGNO(cp->page), 0, &tp)) != 0)
00358 goto err;
00359 }
00360
00361
00362
00363
00364
00365 if ((ret = CDB___db_new(dbc, TYPE_TAGS(cp->page), &alloc_rp)) != 0)
00366 goto err;
00367
00368
00369
00370
00371
00372
00373 PGNO(rp) = NEXT_PGNO(lp) = PGNO(alloc_rp);
00374
00375
00376 if ((ret = __bam_pinsert(dbc, pp, lp, rp, 0)) != 0)
00377 goto err;
00378
00379 bc = (BTREE_CURSOR *)dbc->internal;
00380
00381 if (DB_LOGGING(dbc)) {
00382 memset(&log_dbt, 0, sizeof(log_dbt));
00383 log_dbt.data = cp->page;
00384 log_dbt.size = dbp->pgsize;
00385 if (tp == NULL)
00386 ZERO_LSN(log_lsn);
00387 opflags = F_ISSET(bc, C_RECNUM) ? SPL_NRECS : 0;
00388 if ((ret = CDB___bam_split_log(dbp->dbenv, dbc->txn,
00389 &LSN(cp->page), 0, dbp->log_fileid, PGNO(cp->page),
00390 &LSN(cp->page), PGNO(alloc_rp), &LSN(alloc_rp),
00391 (u_int32_t)NUM_ENT(lp),
00392 tp == NULL ? 0 : PGNO(tp),
00393 tp == NULL ? &log_lsn : &LSN(tp),
00394 bc->root, &log_dbt, opflags)) != 0)
00395 goto err;
00396
00397
00398 LSN(alloc_rp) = LSN(lp) = LSN(rp) = LSN(cp->page);
00399 if (tp != NULL)
00400 LSN(tp) = LSN(cp->page);
00401 }
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 save_lsn = alloc_rp->lsn;
00414 memcpy(alloc_rp, rp, LOFFSET(rp));
00415 memcpy((u_int8_t *)alloc_rp + HOFFSET(rp),
00416 (u_int8_t *)rp + HOFFSET(rp), dbp->pgsize - HOFFSET(rp));
00417 alloc_rp->lsn = save_lsn;
00418
00419 save_lsn = cp->page->lsn;
00420 memcpy(cp->page, lp, LOFFSET(lp));
00421 memcpy((u_int8_t *)cp->page + HOFFSET(lp),
00422 (u_int8_t *)lp + HOFFSET(lp), dbp->pgsize - HOFFSET(lp));
00423 cp->page->lsn = save_lsn;
00424
00425
00426 if (tp != NULL)
00427 PREV_PGNO(tp) = PGNO(rp);
00428
00429
00430 CDB___bam_ca_split(dbp, PGNO(cp->page), PGNO(cp->page), PGNO(rp), split, 0);
00431
00432 CDB___os_free(lp, dbp->pgsize);
00433 CDB___os_free(rp, dbp->pgsize);
00434
00435
00436
00437
00438
00439
00440
00441 if ((t_ret =
00442 CDB_memp_fput(dbp->mpf, alloc_rp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
00443 ret = t_ret;
00444 if ((t_ret =
00445 CDB_memp_fput(dbp->mpf, pp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
00446 ret = t_ret;
00447 (void)__TLPUT(dbc, pp->lock);
00448 if ((t_ret =
00449 CDB_memp_fput(dbp->mpf, cp->page, DB_MPOOL_DIRTY)) != 0 && ret == 0)
00450 ret = t_ret;
00451 (void)__TLPUT(dbc, cp->lock);
00452 if (tp != NULL) {
00453 if ((t_ret =
00454 CDB_memp_fput(dbp->mpf, tp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
00455 ret = t_ret;
00456 (void)__TLPUT(dbc, tplock);
00457 }
00458 return (ret);
00459
00460 err: if (lp != NULL)
00461 CDB___os_free(lp, dbp->pgsize);
00462 if (rp != NULL)
00463 CDB___os_free(rp, dbp->pgsize);
00464 if (alloc_rp != NULL)
00465 (void)CDB___db_free(dbc, alloc_rp);
00466
00467 if (tp != NULL)
00468 (void)CDB_memp_fput(dbp->mpf, tp, 0);
00469 if (tplock.off != LOCK_INVALID)
00470
00471 (void)__LPUT(dbc, tplock);
00472
00473 (void)CDB_memp_fput(dbp->mpf, pp->page, 0);
00474 if (ret == DB_NEEDSPLIT)
00475 (void)__LPUT(dbc, pp->lock);
00476 else
00477 (void)__TLPUT(dbc, pp->lock);
00478
00479 (void)CDB_memp_fput(dbp->mpf, cp->page, 0);
00480 if (ret == DB_NEEDSPLIT)
00481 (void)__LPUT(dbc, cp->lock);
00482 else
00483 (void)__TLPUT(dbc, cp->lock);
00484
00485 return (ret);
00486 }
00487
00488
00489
00490
00491
00492 static int
00493 __bam_broot(dbc, rootp, lp, rp)
00494 DBC *dbc;
00495 PAGE *rootp, *lp, *rp;
00496 {
00497 BINTERNAL bi, *child_bi;
00498 BKEYDATA *child_bk;
00499 BTREE_CURSOR *cp;
00500 DB *dbp;
00501 DBT hdr, data;
00502 db_pgno_t root_pgno;
00503 int ret;
00504
00505 dbp = dbc->dbp;
00506 cp = (BTREE_CURSOR *)dbc->internal;
00507
00508
00509
00510
00511
00512
00513 root_pgno = cp->root;
00514 P_INIT(rootp, dbp->pgsize,
00515 root_pgno, PGNO_INVALID, PGNO_INVALID, lp->level + 1, P_IBTREE, TAGS(lp));
00516 #ifdef DEBUG
00517 word_monitor_set(DB_MONITOR(dbp->dbenv), WORD_MONITOR_LEVEL, LEVEL(rootp));
00518 #endif
00519
00520 memset(&data, 0, sizeof(data));
00521 memset(&hdr, 0, sizeof(hdr));
00522
00523
00524
00525
00526
00527
00528 memset(&bi, 0, sizeof(bi));
00529 bi.len = 0;
00530 B_TSET(bi.type, B_KEYDATA, 0);
00531 bi.pgno = lp->pgno;
00532 if (F_ISSET(cp, C_RECNUM)) {
00533 bi.nrecs = CDB___bam_total(lp);
00534 RE_NREC_SET(rootp, bi.nrecs);
00535 }
00536 hdr.data = &bi;
00537 hdr.size = SSZA(BINTERNAL, data);
00538 if ((ret =
00539 CDB___db_pitem(dbc, rootp, 0, BINTERNAL_SIZE(0), &hdr, NULL)) != 0)
00540 return (ret);
00541
00542 switch (TYPE(rp)) {
00543 case P_IBTREE:
00544
00545 child_bi = GET_BINTERNAL(rp, 0);
00546
00547 bi.len = child_bi->len;
00548 B_TSET(bi.type, child_bi->type, 0);
00549 bi.pgno = rp->pgno;
00550 if (F_ISSET(cp, C_RECNUM)) {
00551 bi.nrecs = CDB___bam_total(rp);
00552 RE_NREC_ADJ(rootp, bi.nrecs);
00553 }
00554 hdr.data = &bi;
00555 hdr.size = SSZA(BINTERNAL, data);
00556 data.data = child_bi->data;
00557 data.size = child_bi->len;
00558 if ((ret = CDB___db_pitem(dbc, rootp, 1,
00559 BINTERNAL_SIZE(child_bi->len), &hdr, &data)) != 0)
00560 return (ret);
00561
00562
00563 if (B_TYPE(child_bi->type) == B_OVERFLOW)
00564 if ((ret = CDB___db_ovref(dbc,
00565 ((BOVERFLOW *)(child_bi->data))->pgno, 1)) != 0)
00566 return (ret);
00567 break;
00568 case P_LDUP:
00569 case P_LBTREE:
00570
00571 child_bk = GET_BKEYDATA(rp, 0);
00572 switch (B_TYPE(child_bk->type)) {
00573 case B_KEYDATA:
00574 bi.len = child_bk->len;
00575 B_TSET(bi.type, child_bk->type, 0);
00576 bi.pgno = rp->pgno;
00577 if (F_ISSET(cp, C_RECNUM)) {
00578 bi.nrecs = CDB___bam_total(rp);
00579 RE_NREC_ADJ(rootp, bi.nrecs);
00580 }
00581 hdr.data = &bi;
00582 hdr.size = SSZA(BINTERNAL, data);
00583 data.data = child_bk->data;
00584 data.size = child_bk->len;
00585 if ((ret = CDB___db_pitem(dbc, rootp, 1,
00586 BINTERNAL_SIZE(child_bk->len), &hdr, &data)) != 0)
00587 return (ret);
00588 break;
00589 case B_DUPLICATE:
00590 case B_OVERFLOW:
00591 bi.len = BOVERFLOW_SIZE;
00592 B_TSET(bi.type, child_bk->type, 0);
00593 bi.pgno = rp->pgno;
00594 if (F_ISSET(cp, C_RECNUM)) {
00595 bi.nrecs = CDB___bam_total(rp);
00596 RE_NREC_ADJ(rootp, bi.nrecs);
00597 }
00598 hdr.data = &bi;
00599 hdr.size = SSZA(BINTERNAL, data);
00600 data.data = child_bk;
00601 data.size = BOVERFLOW_SIZE;
00602 if ((ret = CDB___db_pitem(dbc, rootp, 1,
00603 BINTERNAL_SIZE(BOVERFLOW_SIZE), &hdr, &data)) != 0)
00604 return (ret);
00605
00606
00607 if (B_TYPE(child_bk->type) == B_OVERFLOW)
00608 if ((ret = CDB___db_ovref(dbc,
00609 ((BOVERFLOW *)child_bk)->pgno, 1)) != 0)
00610 return (ret);
00611 break;
00612 default:
00613 return (CDB___db_pgfmt(dbp, rp->pgno));
00614 }
00615 break;
00616 default:
00617 return (CDB___db_pgfmt(dbp, rp->pgno));
00618 }
00619 return (0);
00620 }
00621
00622
00623
00624
00625
00626 static int
00627 __ram_root(dbc, rootp, lp, rp)
00628 DBC *dbc;
00629 PAGE *rootp, *lp, *rp;
00630 {
00631 DB *dbp;
00632 DBT hdr;
00633 RINTERNAL ri;
00634 db_pgno_t root_pgno;
00635 int ret;
00636
00637 dbp = dbc->dbp;
00638 root_pgno = dbc->internal->root;
00639
00640
00641 P_INIT(rootp, dbp->pgsize,
00642 root_pgno, PGNO_INVALID, PGNO_INVALID, lp->level + 1, P_IRECNO, TAGS(lp));
00643
00644
00645 memset(&hdr, 0, sizeof(hdr));
00646 hdr.data = &ri;
00647 hdr.size = RINTERNAL_SIZE;
00648
00649
00650 ri.pgno = lp->pgno;
00651 ri.nrecs = CDB___bam_total(lp);
00652 if ((ret = CDB___db_pitem(dbc, rootp, 0, RINTERNAL_SIZE, &hdr, NULL)) != 0)
00653 return (ret);
00654 RE_NREC_SET(rootp, ri.nrecs);
00655 ri.pgno = rp->pgno;
00656 ri.nrecs = CDB___bam_total(rp);
00657 if ((ret = CDB___db_pitem(dbc, rootp, 1, RINTERNAL_SIZE, &hdr, NULL)) != 0)
00658 return (ret);
00659 RE_NREC_ADJ(rootp, ri.nrecs);
00660 return (0);
00661 }
00662
00663
00664
00665
00666
00667 static int
00668 __bam_pinsert(dbc, parent, lchild, rchild, space_check)
00669 DBC *dbc;
00670 EPG *parent;
00671 PAGE *lchild, *rchild;
00672 int space_check;
00673 {
00674 BINTERNAL bi, *child_bi;
00675 BKEYDATA *child_bk, *tmp_bk;
00676 BTREE *t;
00677 BTREE_CURSOR *cp;
00678 DB *dbp;
00679 DBT a, b, hdr, data;
00680 PAGE *ppage;
00681 RINTERNAL ri;
00682 db_indx_t off;
00683 db_recno_t nrecs;
00684 size_t (*func) __P((const DBT *, const DBT *));
00685 u_int32_t n, nbytes, nksize;
00686 int ret;
00687
00688 dbp = dbc->dbp;
00689 cp = (BTREE_CURSOR *)dbc->internal;
00690 t = dbp->bt_internal;
00691 ppage = parent->page;
00692
00693
00694 nrecs = F_ISSET(cp, C_RECNUM) && !space_check ? CDB___bam_total(rchild) : 0;
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 off = parent->indx + O_INDX;
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 switch (TYPE(rchild)) {
00724 case P_IBTREE:
00725 child_bi = GET_BINTERNAL(rchild, 0);
00726 nbytes = BINTERNAL_PSIZE(child_bi->len);
00727
00728 if (P_FREESPACE(ppage) < nbytes)
00729 return (DB_NEEDSPLIT);
00730 if (space_check)
00731 return (0);
00732
00733
00734 memset(&bi, 0, sizeof(bi));
00735 bi.len = child_bi->len;
00736 B_TSET(bi.type, child_bi->type, 0);
00737 bi.pgno = rchild->pgno;
00738 bi.nrecs = nrecs;
00739 memset(&hdr, 0, sizeof(hdr));
00740 hdr.data = &bi;
00741 hdr.size = SSZA(BINTERNAL, data);
00742 memset(&data, 0, sizeof(data));
00743 data.data = child_bi->data;
00744 data.size = child_bi->len;
00745 if ((ret = CDB___db_pitem(dbc, ppage, off,
00746 BINTERNAL_SIZE(child_bi->len), &hdr, &data)) != 0)
00747 return (ret);
00748
00749
00750 if (B_TYPE(child_bi->type) == B_OVERFLOW)
00751 if ((ret = CDB___db_ovref(dbc,
00752 ((BOVERFLOW *)(child_bi->data))->pgno, 1)) != 0)
00753 return (ret);
00754 break;
00755 case P_LDUP:
00756 case P_LBTREE:
00757 child_bk = GET_BKEYDATA(rchild, 0);
00758 switch (B_TYPE(child_bk->type)) {
00759 case B_KEYDATA:
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 if (F_ISSET(dbc, DBC_OPD)) {
00774 if (dbp->dup_compare == CDB___bam_defcmp)
00775 func = CDB___bam_defpfx;
00776 else
00777 func = NULL;
00778 } else
00779 func = t->bt_prefix;
00780
00781 nbytes = BINTERNAL_PSIZE(child_bk->len);
00782 nksize = child_bk->len;
00783 if (func == NULL)
00784 goto noprefix;
00785 if (ppage->prev_pgno == PGNO_INVALID && off <= 1)
00786 goto noprefix;
00787 tmp_bk = GET_BKEYDATA(lchild, NUM_ENT(lchild) -
00788 (TYPE(lchild) == P_LDUP ? O_INDX : P_INDX));
00789 if (B_TYPE(tmp_bk->type) != B_KEYDATA)
00790 goto noprefix;
00791 memset(&a, 0, sizeof(a));
00792 a.size = tmp_bk->len;
00793 a.data = tmp_bk->data;
00794 memset(&b, 0, sizeof(b));
00795 b.size = child_bk->len;
00796 b.data = child_bk->data;
00797 nksize = func(&a, &b);
00798 if ((n = BINTERNAL_PSIZE(nksize)) < nbytes)
00799 nbytes = n;
00800 else
00801 noprefix: nksize = child_bk->len;
00802
00803 if (P_FREESPACE(ppage) < nbytes)
00804 return (DB_NEEDSPLIT);
00805 if (space_check)
00806 return (0);
00807
00808 memset(&bi, 0, sizeof(bi));
00809 bi.len = nksize;
00810 B_TSET(bi.type, child_bk->type, 0);
00811 bi.pgno = rchild->pgno;
00812 bi.nrecs = nrecs;
00813 memset(&hdr, 0, sizeof(hdr));
00814 hdr.data = &bi;
00815 hdr.size = SSZA(BINTERNAL, data);
00816 memset(&data, 0, sizeof(data));
00817 data.data = child_bk->data;
00818 data.size = nksize;
00819 if ((ret = CDB___db_pitem(dbc, ppage, off,
00820 BINTERNAL_SIZE(nksize), &hdr, &data)) != 0)
00821 return (ret);
00822 break;
00823 case B_DUPLICATE:
00824 case B_OVERFLOW:
00825 nbytes = BINTERNAL_PSIZE(BOVERFLOW_SIZE);
00826
00827 if (P_FREESPACE(ppage) < nbytes)
00828 return (DB_NEEDSPLIT);
00829 if (space_check)
00830 return (0);
00831
00832 memset(&bi, 0, sizeof(bi));
00833 bi.len = BOVERFLOW_SIZE;
00834 B_TSET(bi.type, child_bk->type, 0);
00835 bi.pgno = rchild->pgno;
00836 bi.nrecs = nrecs;
00837 memset(&hdr, 0, sizeof(hdr));
00838 hdr.data = &bi;
00839 hdr.size = SSZA(BINTERNAL, data);
00840 memset(&data, 0, sizeof(data));
00841 data.data = child_bk;
00842 data.size = BOVERFLOW_SIZE;
00843 if ((ret = CDB___db_pitem(dbc, ppage, off,
00844 BINTERNAL_SIZE(BOVERFLOW_SIZE), &hdr, &data)) != 0)
00845 return (ret);
00846
00847
00848 if (B_TYPE(child_bk->type) == B_OVERFLOW)
00849 if ((ret = CDB___db_ovref(dbc,
00850 ((BOVERFLOW *)child_bk)->pgno, 1)) != 0)
00851 return (ret);
00852 break;
00853 default:
00854 return (CDB___db_pgfmt(dbp, rchild->pgno));
00855 }
00856 break;
00857 case P_IRECNO:
00858 case P_LRECNO:
00859 nbytes = RINTERNAL_PSIZE;
00860
00861 if (P_FREESPACE(ppage) < nbytes)
00862 return (DB_NEEDSPLIT);
00863 if (space_check)
00864 return (0);
00865
00866
00867 memset(&hdr, 0, sizeof(hdr));
00868 hdr.data = &ri;
00869 hdr.size = RINTERNAL_SIZE;
00870 ri.pgno = rchild->pgno;
00871 ri.nrecs = nrecs;
00872 if ((ret = CDB___db_pitem(dbc,
00873 ppage, off, RINTERNAL_SIZE, &hdr, NULL)) != 0)
00874 return (ret);
00875 break;
00876 default:
00877 return (CDB___db_pgfmt(dbp, rchild->pgno));
00878 }
00879
00880
00881
00882
00883
00884 if (F_ISSET(cp, C_RECNUM)) {
00885
00886 if (DB_LOGGING(dbc) &&
00887 (ret = CDB___bam_cadjust_log(dbp->dbenv, dbc->txn,
00888 &LSN(ppage), 0, dbp->log_fileid, PGNO(ppage),
00889 &LSN(ppage), parent->indx, -(int32_t)nrecs, 0)) != 0)
00890 return (ret);
00891
00892
00893 if (dbc->dbtype == DB_RECNO)
00894 GET_RINTERNAL(ppage, parent->indx)->nrecs -= nrecs;
00895 else
00896 GET_BINTERNAL(ppage, parent->indx)->nrecs -= nrecs;
00897 }
00898
00899 return (0);
00900 }
00901
00902
00903
00904
00905
00906 static int
00907 __bam_psplit(dbc, cp, lp, rp, splitret)
00908 DBC *dbc;
00909 EPG *cp;
00910 PAGE *lp, *rp;
00911 db_indx_t *splitret;
00912 {
00913 DB *dbp;
00914 PAGE *pp;
00915 db_indx_t half, nbytes, off, splitp, top;
00916 int adjust, cnt, iflag, isbigkey, ret;
00917
00918 dbp = dbc->dbp;
00919 pp = cp->page;
00920 adjust = TYPE(pp) == P_LBTREE ? P_INDX : O_INDX;
00921
00922
00923
00924
00925
00926
00927
00928
00929 off = 0;
00930 if (NEXT_PGNO(pp) == PGNO_INVALID &&
00931 ((ISINTERNAL(pp) && cp->indx == NUM_ENT(cp->page) - 1) ||
00932 (!ISINTERNAL(pp) && cp->indx == NUM_ENT(cp->page))))
00933 off = NUM_ENT(cp->page) - adjust;
00934 else if (PREV_PGNO(pp) == PGNO_INVALID && cp->indx == 0)
00935 off = adjust;
00936
00937 if (off != 0)
00938 goto sort;
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961 top = NUM_ENT(pp) - adjust;
00962 half = (dbp->pgsize - HOFFSET(pp)) / 2;
00963 for (nbytes = 0, off = 0; off < top && nbytes < half; ++off)
00964 switch (TYPE(pp)) {
00965 case P_IBTREE:
00966 if (B_TYPE(GET_BINTERNAL(pp, off)->type) == B_KEYDATA)
00967 nbytes +=
00968 BINTERNAL_SIZE(GET_BINTERNAL(pp, off)->len);
00969 else
00970 nbytes += BINTERNAL_SIZE(BOVERFLOW_SIZE);
00971 break;
00972 case P_LBTREE:
00973 if (B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA)
00974 nbytes +=
00975 BKEYDATA_SIZE(GET_BKEYDATA(pp, off)->len);
00976 else
00977 nbytes += BOVERFLOW_SIZE;
00978
00979 ++off;
00980
00981 case P_LDUP:
00982 case P_LRECNO:
00983 if (B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA)
00984 nbytes +=
00985 BKEYDATA_SIZE(GET_BKEYDATA(pp, off)->len);
00986 else
00987 nbytes += BOVERFLOW_SIZE;
00988 break;
00989 case P_IRECNO:
00990 nbytes += RINTERNAL_SIZE;
00991 break;
00992 default:
00993 return (CDB___db_pgfmt(dbp, pp->pgno));
00994 }
00995 sort: splitp = off;
00996
00997
00998
00999
01000
01001
01002
01003 switch (TYPE(pp)) {
01004 case P_IBTREE:
01005 iflag = 1;
01006 isbigkey = B_TYPE(GET_BINTERNAL(pp, off)->type) != B_KEYDATA;
01007 break;
01008 case P_LBTREE:
01009 case P_LDUP:
01010 iflag = 0;
01011 isbigkey = B_TYPE(GET_BKEYDATA(pp, off)->type) != B_KEYDATA;
01012 break;
01013 default:
01014 iflag = isbigkey = 0;
01015 }
01016 if (isbigkey)
01017 for (cnt = 1; cnt <= 3; ++cnt) {
01018 off = splitp + cnt * adjust;
01019 if (off < (db_indx_t)NUM_ENT(pp) &&
01020 ((iflag &&
01021 B_TYPE(GET_BINTERNAL(pp,off)->type) == B_KEYDATA) ||
01022 B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA)) {
01023 splitp = off;
01024 break;
01025 }
01026 if (splitp <= (db_indx_t)(cnt * adjust))
01027 continue;
01028 off = splitp - cnt * adjust;
01029 if (iflag ?
01030 B_TYPE(GET_BINTERNAL(pp, off)->type) == B_KEYDATA :
01031 B_TYPE(GET_BKEYDATA(pp, off)->type) == B_KEYDATA) {
01032 splitp = off;
01033 break;
01034 }
01035 }
01036
01037
01038
01039
01040
01041
01042
01043 if (TYPE(pp) == P_LBTREE &&
01044 pp->inp[splitp] == pp->inp[splitp - adjust])
01045 for (cnt = 1;; ++cnt) {
01046 off = splitp + cnt * adjust;
01047 if (off < NUM_ENT(pp) &&
01048 pp->inp[splitp] != pp->inp[off]) {
01049 splitp = off;
01050 break;
01051 }
01052 if (splitp <= (db_indx_t)(cnt * adjust))
01053 continue;
01054 off = splitp - cnt * adjust;
01055 if (pp->inp[splitp] != pp->inp[off]) {
01056 splitp = off + adjust;
01057 break;
01058 }
01059 }
01060
01061
01062 if ((ret = CDB___bam_copy(dbp, pp, lp, 0, splitp)) != 0)
01063 return (ret);
01064 if ((ret = CDB___bam_copy(dbp, pp, rp, splitp, NUM_ENT(pp))) != 0)
01065 return (ret);
01066
01067 *splitret = splitp;
01068 return (0);
01069 }
01070
01071
01072
01073
01074
01075
01076
01077 int
01078 CDB___bam_copy(dbp, pp, cp, nxt, stop)
01079 DB *dbp;
01080 PAGE *pp, *cp;
01081 u_int32_t nxt, stop;
01082 {
01083 db_indx_t nbytes, off;
01084
01085
01086
01087
01088
01089 for (off = 0; nxt < stop; ++nxt, ++NUM_ENT(cp), ++off) {
01090 switch (TYPE(pp)) {
01091 case P_IBTREE:
01092 if (B_TYPE(GET_BINTERNAL(pp, nxt)->type) == B_KEYDATA)
01093 nbytes =
01094 BINTERNAL_SIZE(GET_BINTERNAL(pp, nxt)->len);
01095 else
01096 nbytes = BINTERNAL_SIZE(BOVERFLOW_SIZE);
01097 break;
01098 case P_LBTREE:
01099
01100
01101
01102
01103 if (off != 0 && (nxt % P_INDX) == 0 &&
01104 pp->inp[nxt] == pp->inp[nxt - P_INDX]) {
01105 cp->inp[off] = cp->inp[off - P_INDX];
01106 continue;
01107 }
01108
01109 case P_LDUP:
01110 case P_LRECNO:
01111 if (B_TYPE(GET_BKEYDATA(pp, nxt)->type) == B_KEYDATA)
01112 nbytes =
01113 BKEYDATA_SIZE(GET_BKEYDATA(pp, nxt)->len);
01114 else
01115 nbytes = BOVERFLOW_SIZE;
01116 break;
01117 case P_IRECNO:
01118 nbytes = RINTERNAL_SIZE;
01119 break;
01120 default:
01121 return (CDB___db_pgfmt(dbp, pp->pgno));
01122 }
01123 cp->inp[off] = HOFFSET(cp) -= nbytes;
01124 memcpy(P_ENTRY(cp, off), P_ENTRY(pp, nxt), nbytes);
01125 }
01126 return (0);
01127 }