Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

bt_delete.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  */
00007 /*
00008  * Copyright (c) 1990, 1993, 1994, 1995, 1996
00009  *      Keith Bostic.  All rights reserved.
00010  */
00011 /*
00012  * Copyright (c) 1990, 1993, 1994, 1995
00013  *      The Regents of the University of California.  All rights reserved.
00014  *
00015  * This code is derived from software contributed to Berkeley by
00016  * Mike Olson.
00017  *
00018  * Redistribution and use in source and binary forms, with or without
00019  * modification, are permitted provided that the following conditions
00020  * are met:
00021  * 1. Redistributions of source code must retain the above copyright
00022  *    notice, this list of conditions and the following disclaimer.
00023  * 2. Redistributions in binary form must reproduce the above copyright
00024  *    notice, this list of conditions and the following disclaimer in the
00025  *    documentation and/or other materials provided with the distribution.
00026  * 3. Neither the name of the University nor the names of its contributors
00027  *    may be used to endorse or promote products derived from this software
00028  *    without specific prior written permission.
00029  *
00030  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00031  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00032  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00033  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00034  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00035  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00036  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00037  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00038  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00039  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00040  * SUCH DAMAGE.
00041  *
00042  * $Id: bt_delete.c,v 12.13 2005/10/20 18:14:59 bostic Exp $
00043  */
00044 
00045 #include "db_config.h"
00046 
00047 #ifndef NO_SYSTEM_INCLUDES
00048 #include <sys/types.h>
00049 
00050 #include <string.h>
00051 #endif
00052 
00053 #include "db_int.h"
00054 #include "dbinc/db_page.h"
00055 #include "dbinc/db_shash.h"
00056 #include "dbinc/btree.h"
00057 #include "dbinc/lock.h"
00058 #include "dbinc/mp.h"
00059 
00060 /*
00061  * __bam_ditem --
00062  *      Delete one or more entries from a page.
00063  *
00064  * PUBLIC: int __bam_ditem __P((DBC *, PAGE *, u_int32_t));
00065  */
00066 int
00067 __bam_ditem(dbc, h, indx)
00068         DBC *dbc;
00069         PAGE *h;
00070         u_int32_t indx;
00071 {
00072         BINTERNAL *bi;
00073         BKEYDATA *bk;
00074         DB *dbp;
00075         DB_MPOOLFILE *mpf;
00076         u_int32_t nbytes;
00077         int ret;
00078         db_indx_t *inp;
00079 
00080         dbp = dbc->dbp;
00081         mpf = dbp->mpf;
00082         inp = P_INP(dbp, h);
00083 
00084         switch (TYPE(h)) {
00085         case P_IBTREE:
00086                 bi = GET_BINTERNAL(dbp, h, indx);
00087                 switch (B_TYPE(bi->type)) {
00088                 case B_DUPLICATE:
00089                 case B_KEYDATA:
00090                         nbytes = BINTERNAL_SIZE(bi->len);
00091                         break;
00092                 case B_OVERFLOW:
00093                         nbytes = BINTERNAL_SIZE(bi->len);
00094                         if ((ret =
00095                             __db_doff(dbc, ((BOVERFLOW *)bi->data)->pgno)) != 0)
00096                                 return (ret);
00097                         break;
00098                 default:
00099                         return (__db_pgfmt(dbp->dbenv, PGNO(h)));
00100                 }
00101                 break;
00102         case P_IRECNO:
00103                 nbytes = RINTERNAL_SIZE;
00104                 break;
00105         case P_LBTREE:
00106                 /*
00107                  * If it's a duplicate key, discard the index and don't touch
00108                  * the actual page item.
00109                  *
00110                  * !!!
00111                  * This works because no data item can have an index matching
00112                  * any other index so even if the data item is in a key "slot",
00113                  * it won't match any other index.
00114                  */
00115                 if ((indx % 2) == 0) {
00116                         /*
00117                          * Check for a duplicate after us on the page.  NOTE:
00118                          * we have to delete the key item before deleting the
00119                          * data item, otherwise the "indx + P_INDX" calculation
00120                          * won't work!
00121                          */
00122                         if (indx + P_INDX < (u_int32_t)NUM_ENT(h) &&
00123                             inp[indx] == inp[indx + P_INDX])
00124                                 return (__bam_adjindx(dbc,
00125                                     h, indx, indx + O_INDX, 0));
00126                         /*
00127                          * Check for a duplicate before us on the page.  It
00128                          * doesn't matter if we delete the key item before or
00129                          * after the data item for the purposes of this one.
00130                          */
00131                         if (indx > 0 && inp[indx] == inp[indx - P_INDX])
00132                                 return (__bam_adjindx(dbc,
00133                                     h, indx, indx - P_INDX, 0));
00134                 }
00135                 /* FALLTHROUGH */
00136         case P_LDUP:
00137         case P_LRECNO:
00138                 bk = GET_BKEYDATA(dbp, h, indx);
00139                 switch (B_TYPE(bk->type)) {
00140                 case B_DUPLICATE:
00141                         nbytes = BOVERFLOW_SIZE;
00142                         break;
00143                 case B_OVERFLOW:
00144                         nbytes = BOVERFLOW_SIZE;
00145                         if ((ret = __db_doff(
00146                             dbc, (GET_BOVERFLOW(dbp, h, indx))->pgno)) != 0)
00147                                 return (ret);
00148                         break;
00149                 case B_KEYDATA:
00150                         nbytes = BKEYDATA_SIZE(bk->len);
00151                         break;
00152                 default:
00153                         return (__db_pgfmt(dbp->dbenv, PGNO(h)));
00154                 }
00155                 break;
00156         default:
00157                 return (__db_pgfmt(dbp->dbenv, PGNO(h)));
00158         }
00159 
00160         /* Delete the item and mark the page dirty. */
00161         if ((ret = __db_ditem(dbc, h, indx, nbytes)) != 0)
00162                 return (ret);
00163         if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
00164                 return (ret);
00165 
00166         return (0);
00167 }
00168 
00169 /*
00170  * __bam_adjindx --
00171  *      Adjust an index on the page.
00172  *
00173  * PUBLIC: int __bam_adjindx __P((DBC *, PAGE *, u_int32_t, u_int32_t, int));
00174  */
00175 int
00176 __bam_adjindx(dbc, h, indx, indx_copy, is_insert)
00177         DBC *dbc;
00178         PAGE *h;
00179         u_int32_t indx, indx_copy;
00180         int is_insert;
00181 {
00182         DB *dbp;
00183         DB_MPOOLFILE *mpf;
00184         db_indx_t copy, *inp;
00185         int ret;
00186 
00187         dbp = dbc->dbp;
00188         mpf = dbp->mpf;
00189         inp = P_INP(dbp, h);
00190 
00191         /* Log the change. */
00192         if (DBC_LOGGING(dbc)) {
00193             if ((ret = __bam_adj_log(dbp, dbc->txn, &LSN(h), 0,
00194                 PGNO(h), &LSN(h), indx, indx_copy, (u_int32_t)is_insert)) != 0)
00195                         return (ret);
00196         } else
00197                 LSN_NOT_LOGGED(LSN(h));
00198 
00199         /* Shuffle the indices and mark the page dirty. */
00200         if (is_insert) {
00201                 copy = inp[indx_copy];
00202                 if (indx != NUM_ENT(h))
00203                         memmove(&inp[indx + O_INDX], &inp[indx],
00204                             sizeof(db_indx_t) * (NUM_ENT(h) - indx));
00205                 inp[indx] = copy;
00206                 ++NUM_ENT(h);
00207         } else {
00208                 --NUM_ENT(h);
00209                 if (indx != NUM_ENT(h))
00210                         memmove(&inp[indx], &inp[indx + O_INDX],
00211                             sizeof(db_indx_t) * (NUM_ENT(h) - indx));
00212         }
00213         if ((ret = __memp_fset(mpf, h, DB_MPOOL_DIRTY)) != 0)
00214                 return (ret);
00215 
00216         return (0);
00217 }
00218 
00219 /*
00220  * __bam_dpages --
00221  *      Delete a set of locked pages.
00222  *
00223  * PUBLIC: int __bam_dpages __P((DBC *, int, int));
00224  */
00225 int
00226 __bam_dpages(dbc, use_top, update)
00227         DBC *dbc;
00228         int use_top;
00229         int update;
00230 {
00231         BTREE_CURSOR *cp;
00232         BINTERNAL *bi;
00233         DB *dbp;
00234         DBT a, b;
00235         DB_LOCK c_lock, p_lock;
00236         DB_MPOOLFILE *mpf;
00237         EPG *epg, *save_sp, *stack_epg;
00238         PAGE *child, *parent;
00239         db_indx_t nitems;
00240         db_pgno_t pgno, root_pgno;
00241         db_recno_t rcnt;
00242         int done, ret, t_ret;
00243 
00244         dbp = dbc->dbp;
00245         mpf = dbp->mpf;
00246         cp = (BTREE_CURSOR *)dbc->internal;
00247         nitems = 0;
00248         pgno = PGNO_INVALID;
00249 
00250         /*
00251          * We have the entire stack of deletable pages locked.
00252          *
00253          * Btree calls us with the first page in the stack is to have a
00254          * single item deleted, and the rest of the pages are to be removed.
00255          *
00256          * Recno always has a stack to the root and __bam_merge operations
00257          * may have unneeded items in the sack.  We find the lowest page
00258          * in the stack that has more than one record in it and start there.
00259          */
00260         ret = 0;
00261         if (use_top)
00262                 stack_epg = cp->sp;
00263         else
00264                 for (stack_epg = cp->csp; stack_epg > cp->sp; --stack_epg)
00265                         if (NUM_ENT(stack_epg->page) > 1)
00266                                 break;
00267         epg = stack_epg;
00268         /*
00269          * !!!
00270          * There is an interesting deadlock situation here.  We have to relink
00271          * the leaf page chain around the leaf page being deleted.  Consider
00272          * a cursor walking through the leaf pages, that has the previous page
00273          * read-locked and is waiting on a lock for the page we're deleting.
00274          * It will deadlock here.  Before we unlink the subtree, we relink the
00275          * leaf page chain.
00276          */
00277         if (LEVEL(cp->csp->page) == 1 &&
00278             (ret = __bam_relink(dbc, cp->csp->page, PGNO_INVALID)) != 0)
00279                 goto discard;
00280 
00281         /*
00282          * Delete the last item that references the underlying pages that are
00283          * to be deleted, and adjust cursors that reference that page.  Then,
00284          * save that page's page number and item count and release it.  If
00285          * the application isn't retaining locks because it's running without
00286          * transactions, this lets the rest of the tree get back to business
00287          * immediately.
00288          */
00289         if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
00290                 goto discard;
00291         if ((ret = __bam_ca_di(dbc, PGNO(epg->page), epg->indx, -1)) != 0)
00292                 goto discard;
00293 
00294         if (update && epg->indx == 0) {
00295                 save_sp = cp->csp;
00296                 cp->csp = epg;
00297                 ret = __bam_pupdate(dbc, epg->page);
00298                 cp->csp = save_sp;
00299                 if (ret != 0)
00300                         goto discard;
00301         }
00302 
00303         pgno = PGNO(epg->page);
00304         nitems = NUM_ENT(epg->page);
00305 
00306         ret = __memp_fput(mpf, epg->page, 0);
00307         if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
00308                 ret = t_ret;
00309         if (ret != 0)
00310                 goto err_inc;
00311 
00312         /* Then, discard any pages that we don't care about. */
00313 discard: for (epg = cp->sp; epg < stack_epg; ++epg) {
00314                 if ((t_ret = __memp_fput(mpf, epg->page, 0)) != 0 && ret == 0)
00315                         ret = t_ret;
00316                 epg->page = NULL;
00317                 if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
00318                         ret = t_ret;
00319         }
00320         if (ret != 0)
00321                 goto err;
00322 
00323         /* Free the rest of the pages in the stack. */
00324         while (++epg <= cp->csp) {
00325                 /*
00326                  * Delete page entries so they will be restored as part of
00327                  * recovery.  We don't need to do cursor adjustment here as
00328                  * the pages are being emptied by definition and so cannot
00329                  * be referenced by a cursor.
00330                  */
00331                 if (NUM_ENT(epg->page) != 0) {
00332                         DB_ASSERT(LEVEL(epg->page) != 1);
00333 
00334                         if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
00335                                 goto err;
00336                         /*
00337                          * Sheer paranoia: if we find any pages that aren't
00338                          * emptied by the delete, someone else added an item
00339                          * while we were walking the tree, and we discontinue
00340                          * the delete.  Shouldn't be possible, but we check
00341                          * regardless.
00342                          */
00343                         if (NUM_ENT(epg->page) != 0)
00344                                 goto err;
00345                 }
00346 
00347                 ret = __db_free(dbc, epg->page);
00348                 if (cp->page == epg->page)
00349                         cp->page = NULL;
00350                 epg->page = NULL;
00351                 if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
00352                         ret = t_ret;
00353                 if (ret != 0)
00354                         goto err_inc;
00355         }
00356 
00357         if (0) {
00358 err_inc:        ++epg;
00359 err:            for (; epg <= cp->csp; ++epg) {
00360                         if (epg->page != NULL)
00361                                 (void)__memp_fput(mpf, epg->page, 0);
00362                         (void)__TLPUT(dbc, epg->lock);
00363                 }
00364                 BT_STK_CLR(cp);
00365                 return (ret);
00366         }
00367         BT_STK_CLR(cp);
00368 
00369         /*
00370          * If we just deleted the next-to-last item from the root page, the
00371          * tree can collapse one or more levels.  While there remains only a
00372          * single item on the root page, write lock the last page referenced
00373          * by the root page and copy it over the root page.
00374          */
00375         root_pgno = cp->root;
00376         if (pgno != root_pgno || nitems != 1)
00377                 return (0);
00378 
00379         for (done = 0; !done;) {
00380                 /* Initialize. */
00381                 parent = child = NULL;
00382                 LOCK_INIT(p_lock);
00383                 LOCK_INIT(c_lock);
00384 
00385                 /* Lock the root. */
00386                 pgno = root_pgno;
00387                 if ((ret =
00388                     __db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &p_lock)) != 0)
00389                         goto stop;
00390                 if ((ret = __memp_fget(mpf, &pgno, 0, &parent)) != 0)
00391                         goto stop;
00392 
00393                 if (NUM_ENT(parent) != 1)
00394                         goto stop;
00395 
00396                 switch (TYPE(parent)) {
00397                 case P_IBTREE:
00398                         /*
00399                          * If this is overflow, then try to delete it.
00400                          * The child may or may not still point at it.
00401                          */
00402                         bi = GET_BINTERNAL(dbp, parent, 0);
00403                         if (B_TYPE(bi->type) == B_OVERFLOW)
00404                                 if ((ret = __db_doff(dbc,
00405                                     ((BOVERFLOW *)bi->data)->pgno)) != 0)
00406                                         goto stop;
00407                         pgno = bi->pgno;
00408                         break;
00409                 case P_IRECNO:
00410                         pgno = GET_RINTERNAL(dbp, parent, 0)->pgno;
00411                         break;
00412                 default:
00413                         goto stop;
00414                 }
00415 
00416                 /* Lock the child page. */
00417                 if ((ret =
00418                     __db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &c_lock)) != 0)
00419                         goto stop;
00420                 if ((ret = __memp_fget(mpf, &pgno, 0, &child)) != 0)
00421                         goto stop;
00422 
00423                 /* Log the change. */
00424                 if (DBC_LOGGING(dbc)) {
00425                         memset(&a, 0, sizeof(a));
00426                         a.data = child;
00427                         a.size = dbp->pgsize;
00428                         memset(&b, 0, sizeof(b));
00429                         b.data = P_ENTRY(dbp, parent, 0);
00430                         b.size = TYPE(parent) == P_IRECNO ? RINTERNAL_SIZE :
00431                             BINTERNAL_SIZE(((BINTERNAL *)b.data)->len);
00432                         if ((ret = __bam_rsplit_log(dbp, dbc->txn,
00433                             &child->lsn, 0, PGNO(child), &a, PGNO(parent),
00434                             RE_NREC(parent), &b, &parent->lsn)) != 0)
00435                                 goto stop;
00436                 } else
00437                         LSN_NOT_LOGGED(child->lsn);
00438 
00439                 /*
00440                  * Make the switch.
00441                  *
00442                  * One fixup -- internal pages below the top level do not store
00443                  * a record count, so we have to preserve it if we're not
00444                  * converting to a leaf page.  Note also that we are about to
00445                  * overwrite the parent page, including its LSN.  This is OK
00446                  * because the log message we wrote describing this update
00447                  * stores its LSN on the child page.  When the child is copied
00448                  * onto the parent, the correct LSN is copied into place.
00449                  */
00450                 COMPQUIET(rcnt, 0);
00451                 if (F_ISSET(cp, C_RECNUM) && LEVEL(child) > LEAFLEVEL)
00452                         rcnt = RE_NREC(parent);
00453                 memcpy(parent, child, dbp->pgsize);
00454                 PGNO(parent) = root_pgno;
00455                 if (F_ISSET(cp, C_RECNUM) && LEVEL(child) > LEAFLEVEL)
00456                         RE_NREC_SET(parent, rcnt);
00457 
00458                 /* Mark the pages dirty. */
00459                 if ((ret = __memp_fset(mpf, parent, DB_MPOOL_DIRTY)) != 0)
00460                         goto stop;
00461                 if ((ret = __memp_fset(mpf, child, DB_MPOOL_DIRTY)) != 0)
00462                         goto stop;
00463 
00464                 /* Adjust the cursors. */
00465                 if ((ret = __bam_ca_rsplit(dbc, PGNO(child), root_pgno)) != 0)
00466                         goto stop;
00467 
00468                 /*
00469                  * Free the page copied onto the root page and discard its
00470                  * lock.  (The call to __db_free() discards our reference
00471                  * to the page.)
00472                  */
00473                 if ((ret = __db_free(dbc, child)) != 0) {
00474                         child = NULL;
00475                         goto stop;
00476                 }
00477                 child = NULL;
00478 
00479                 if (0) {
00480 stop:                   done = 1;
00481                 }
00482                 if ((t_ret = __TLPUT(dbc, p_lock)) != 0 && ret == 0)
00483                         ret = t_ret;
00484                 if (parent != NULL &&
00485                     (t_ret = __memp_fput(mpf, parent, 0)) != 0 && ret == 0)
00486                         ret = t_ret;
00487                 if ((t_ret = __TLPUT(dbc, c_lock)) != 0 && ret == 0)
00488                         ret = t_ret;
00489                 if (child != NULL &&
00490                     (t_ret = __memp_fput(mpf, child, 0)) != 0 && ret == 0)
00491                         ret = t_ret;
00492         }
00493 
00494         return (ret);
00495 }
00496 
00497 /*
00498  * __bam_relink --
00499  *      Relink around a deleted page.
00500  *
00501  * PUBLIC: int __bam_relink __P((DBC *, PAGE *, db_pgno_t));
00502  */
00503 int
00504 __bam_relink(dbc, pagep, new_pgno)
00505         DBC *dbc;
00506         PAGE *pagep;
00507         db_pgno_t new_pgno;
00508 {
00509         DB *dbp;
00510         PAGE *np, *pp;
00511         DB_LOCK npl, ppl;
00512         DB_LSN *nlsnp, *plsnp, ret_lsn;
00513         DB_MPOOLFILE *mpf;
00514         int ret, t_ret;
00515 
00516         dbp = dbc->dbp;
00517         np = pp = NULL;
00518         LOCK_INIT(npl);
00519         LOCK_INIT(ppl);
00520         nlsnp = plsnp = NULL;
00521         mpf = dbp->mpf;
00522         ret = 0;
00523 
00524         /*
00525          * Retrieve and lock the one/two pages.  For a remove, we may need
00526          * two pages (the before and after).  For an add, we only need one
00527          * because, the split took care of the prev.
00528          */
00529         if (pagep->next_pgno != PGNO_INVALID) {
00530                 if ((ret = __db_lget(dbc,
00531                     0, pagep->next_pgno, DB_LOCK_WRITE, 0, &npl)) != 0)
00532                         goto err;
00533                 if ((ret = __memp_fget(mpf, &pagep->next_pgno, 0, &np)) != 0) {
00534                         ret = __db_pgerr(dbp, pagep->next_pgno, ret);
00535                         goto err;
00536                 }
00537                 nlsnp = &np->lsn;
00538         }
00539         if (pagep->prev_pgno != PGNO_INVALID) {
00540                 if ((ret = __db_lget(dbc,
00541                     0, pagep->prev_pgno, DB_LOCK_WRITE, 0, &ppl)) != 0)
00542                         goto err;
00543                 if ((ret = __memp_fget(mpf, &pagep->prev_pgno, 0, &pp)) != 0) {
00544                         ret = __db_pgerr(dbp, pagep->prev_pgno, ret);
00545                         goto err;
00546                 }
00547                 plsnp = &pp->lsn;
00548         }
00549 
00550         /* Log the change. */
00551         if (DBC_LOGGING(dbc)) {
00552                 if ((ret = __bam_relink_log(dbp, dbc->txn, &ret_lsn, 0,
00553                     pagep->pgno, new_pgno, pagep->prev_pgno, plsnp,
00554                     pagep->next_pgno, nlsnp)) != 0)
00555                         goto err;
00556         } else
00557                 LSN_NOT_LOGGED(ret_lsn);
00558         if (np != NULL)
00559                 np->lsn = ret_lsn;
00560         if (pp != NULL)
00561                 pp->lsn = ret_lsn;
00562 
00563         /*
00564          * Modify and release the two pages.
00565          */
00566         if (np != NULL) {
00567                 if (new_pgno == PGNO_INVALID)
00568                         np->prev_pgno = pagep->prev_pgno;
00569                 else
00570                         np->prev_pgno = new_pgno;
00571                 ret = __memp_fput(mpf, np, DB_MPOOL_DIRTY);
00572                 if ((t_ret = __TLPUT(dbc, npl)) != 0 && ret == 0)
00573                         ret = t_ret;
00574                 if (ret != 0)
00575                         goto err;
00576         }
00577 
00578         if (pp != NULL) {
00579                 if (new_pgno == PGNO_INVALID)
00580                         pp->next_pgno = pagep->next_pgno;
00581                 else
00582                         pp->next_pgno = new_pgno;
00583                 ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY);
00584                 if ((t_ret = __TLPUT(dbc, ppl)) != 0 && ret == 0)
00585                         ret = t_ret;
00586                 if (ret != 0)
00587                         goto err;
00588         }
00589         return (0);
00590 
00591 err:    if (np != NULL)
00592                 (void)__memp_fput(mpf, np, 0);
00593         (void)__TLPUT(dbc, npl);
00594         if (pp != NULL)
00595                 (void)__memp_fput(mpf, pp, 0);
00596         (void)__TLPUT(dbc, ppl);
00597         return (ret);
00598 }
00599 
00600 /*
00601  * __bam_pupdate --
00602  *      Update parent key pointers up the tree.
00603  *
00604  * PUBLIC: int __bam_pupdate __P((DBC *, PAGE *));
00605  */
00606 int
00607 __bam_pupdate(dbc, lpg)
00608         DBC *dbc;
00609         PAGE *lpg;
00610 {
00611         BTREE_CURSOR *cp;
00612         DB_ENV *dbenv;
00613         EPG *epg;
00614         int ret;
00615 
00616         dbenv = dbc->dbp->dbenv;
00617         cp = (BTREE_CURSOR *)dbc->internal;
00618         ret = 0;
00619 
00620         /*
00621          * Update the parents up the tree.  __bam_pinsert only looks at the
00622          * left child if is a leaf page, so we don't need to change it.  We
00623          * just do a delete and insert; a replace is possible but reusing
00624          * pinsert is better.
00625          */
00626         for (epg = &cp->csp[-1]; epg >= cp->sp; epg--) {
00627                 if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
00628                         return (ret);
00629                 epg->indx--;
00630                 if ((ret = __bam_pinsert(dbc, epg,
00631                     lpg, epg[1].page, BPI_NORECNUM)) != 0) {
00632                         if (ret == DB_NEEDSPLIT) {
00633                                 /* This should not happen. */
00634                                 __db_err(dbenv,
00635                                      "Not enough room in parent: %s: page %lu",
00636                                      dbc->dbp->fname, (u_long)PGNO(epg->page));
00637                                 ret = __db_panic(dbenv, EINVAL);
00638                         }
00639                         return (ret);
00640                 }
00641         }
00642         return (ret);
00643 }

Generated on Sun Dec 25 12:14:12 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2