db_meta.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
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 
00043 #include "config.h"
00044 
00045 #ifndef lint
00046 static const char revid[] = "$Id: db__meta_8c-source.html,v 1.1 2008/06/08 10:17:51 sebdiaz Exp $";
00047 #endif /* not lint */
00048 
00049 #ifndef NO_SYSTEM_INCLUDES
00050 #include <sys/types.h>
00051 
00052 #include <errno.h>
00053 #include <string.h>
00054 #endif
00055 
00056 #include "db_int.h"
00057 #include "db_page.h"
00058 #include "db_shash.h"
00059 #include "lock.h"
00060 #include "txn.h"
00061 #include "db_am.h"
00062 #include "btree.h"
00063 
00064 /*
00065  * CDB___db_new --
00066  *      Get a new page, preferably from the freelist.
00067  *
00068  * PUBLIC: int CDB___db_new __P((DBC *, u_int32_t, PAGE **));
00069  */
00070 int
00071 CDB___db_new(dbc, type, pagepp)
00072         DBC *dbc;
00073         u_int32_t type;
00074         PAGE **pagepp;
00075 {
00076         DBMETA *meta;
00077         DB *dbp;
00078         DB_LOCK metalock;
00079         PAGE *h;
00080         db_pgno_t pgno;
00081         int ret;
00082 
00083         dbp = dbc->dbp;
00084         meta = NULL;
00085         h = NULL;
00086 
00087         pgno = PGNO_BASE_MD;
00088         if ((ret = CDB___db_lget(dbc,
00089             LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
00090                 goto err;
00091         if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&meta)) != 0)
00092                 goto err;
00093 
00094         if (meta->free == PGNO_INVALID) {
00095                 if ((ret = CDB_memp_fget(dbp->mpf, &pgno, DB_MPOOL_NEW, &h)) != 0)
00096                         goto err;
00097                 ZERO_LSN(h->lsn);
00098                 h->pgno = pgno;
00099         } else {
00100                 pgno = meta->free;
00101                 if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, &h)) != 0)
00102                         goto err;
00103                 meta->free = h->next_pgno;
00104                 (void)CDB_memp_fset(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
00105         }
00106 
00107         /* Log the change. */
00108         if (DB_LOGGING(dbc)) {
00109                 if ((ret = __db_pg_alloc_log(dbp->dbenv,
00110                     dbc->txn, &LSN(meta), 0, dbp->log_fileid,
00111                     &LSN(meta), &meta->alloc_lsn, &h->lsn, h->pgno,
00112                     (u_int32_t)type, meta->free)) != 0)
00113                         goto err;
00114                 LSN(h) = LSN(meta);
00115                 meta->alloc_lsn = LSN(meta);
00116         }
00117 
00118         (void)CDB_memp_fput(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
00119         (void)__TLPUT(dbc, metalock);
00120 
00121         P_INIT(h, dbp->pgsize, h->pgno, PGNO_INVALID, PGNO_INVALID, 0, type, 0);
00122         *pagepp = h;
00123         return (0);
00124 
00125 err:    if (h != NULL)
00126                 (void)CDB_memp_fput(dbp->mpf, h, 0);
00127         if (meta != NULL)
00128                 (void)CDB_memp_fput(dbp->mpf, meta, 0);
00129         (void)__TLPUT(dbc, metalock);
00130         return (ret);
00131 }
00132 
00133 /*
00134  * CDB___db_free --
00135  *      Add a page to the head of the freelist.
00136  *
00137  * PUBLIC: int CDB___db_free __P((DBC *, PAGE *));
00138  */
00139 int
00140 CDB___db_free(dbc, h)
00141         DBC *dbc;
00142         PAGE *h;
00143 {
00144         DBMETA *meta;
00145         DB *dbp;
00146         DBT ldbt;
00147         DB_LOCK metalock;
00148         db_pgno_t pgno;
00149         u_int32_t dirty_flag;
00150         int ret, t_ret;
00151 
00152         dbp = dbc->dbp;
00153 
00154         /*
00155          * Retrieve the metadata page and insert the page at the head of
00156          * the free list.  If either the lock get or page get routines
00157          * fail, then we need to put the page with which we were called
00158          * back because our caller assumes we take care of it.
00159          */
00160         dirty_flag = 0;
00161         pgno = PGNO_BASE_MD;
00162         if ((ret = CDB___db_lget(dbc,
00163              LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
00164                 goto err;
00165         if ((ret = CDB_memp_fget(dbp->mpf, &pgno, 0, (PAGE **)&meta)) != 0) {
00166                 (void)__TLPUT(dbc, metalock);
00167                 goto err;
00168         }
00169 
00170         /* Log the change. */
00171         if (DB_LOGGING(dbc)) {
00172                 memset(&ldbt, 0, sizeof(ldbt));
00173                 ldbt.data = h;
00174                 ldbt.size = P_OVERHEAD;
00175                 if ((ret = __db_pg_free_log(dbp->dbenv,
00176                     dbc->txn, &LSN(meta), 0, dbp->log_fileid, h->pgno,
00177                     &LSN(meta), &meta->alloc_lsn, &ldbt, meta->free)) != 0) {
00178                         (void)CDB_memp_fput(dbp->mpf, (PAGE *)meta, 0);
00179                         (void)__TLPUT(dbc, metalock);
00180                         return (ret);
00181                 }
00182                 LSN(h) = LSN(meta);
00183                 meta->alloc_lsn = LSN(meta);
00184         }
00185 
00186         P_INIT(h, dbp->pgsize, h->pgno, PGNO_INVALID, meta->free, 0, P_INVALID, 0);
00187 
00188         /* Link the page on the metadata free list. */
00189         meta->free = h->pgno;
00190 
00191         /* Discard the metadata page. */
00192         ret = CDB_memp_fput(dbp->mpf, (PAGE *)meta, DB_MPOOL_DIRTY);
00193         if ((t_ret = __TLPUT(dbc, metalock)) != 0)
00194                 ret = t_ret;
00195 
00196         /* Discard the caller's page reference. */
00197         dirty_flag = DB_MPOOL_DIRTY;
00198 err:    if ((t_ret = CDB_memp_fput(dbp->mpf, h, dirty_flag)) != 0 && ret == 0)
00199                 ret = t_ret;
00200 
00201         /*
00202          * XXX
00203          * We have to unlock the caller's page in the caller!
00204          */
00205         return (ret);
00206 }
00207 
00208 #ifdef DEBUG
00209 /*
00210  * CDB___db_lprint --
00211  *      Print out the list of locks currently held by a cursor.
00212  *
00213  * PUBLIC: int CDB___db_lprint __P((DBC *));
00214  */
00215 int
00216 CDB___db_lprint(dbc)
00217         DBC *dbc;
00218 {
00219         DB *dbp;
00220         DB_LOCKREQ req;
00221 
00222         dbp = dbc->dbp;
00223 
00224         if (LOCKING_ON(dbp->dbenv)) {
00225                 req.op = DB_LOCK_DUMP;
00226                 CDB_lock_vec(dbp->dbenv, dbc->locker, 0, &req, 1, NULL);
00227         }
00228         return (0);
00229 }
00230 #endif
00231 
00232 /*
00233  * CDB___db_lget --
00234  *      The standard lock get call.
00235  *
00236  * PUBLIC: int CDB___db_lget __P((DBC *,
00237  * PUBLIC:     int, db_pgno_t, db_lockmode_t, int, DB_LOCK *));
00238  */
00239 int
00240 CDB___db_lget(dbc, flags, pgno, mode, lkflags, lockp)
00241         DBC *dbc;
00242         int flags, lkflags;
00243         db_pgno_t pgno;
00244         db_lockmode_t mode;
00245         DB_LOCK *lockp;
00246 {
00247         DB *dbp;
00248         DB_ENV *dbenv;
00249         DB_LOCKREQ couple[2];
00250         int ret;
00251 
00252         dbp = dbc->dbp;
00253         dbenv = dbp->dbenv;
00254 
00255         /*
00256          * We do not always check if we're configured for locking before
00257          * calling CDB___db_lget to acquire the lock.
00258          */
00259         if (LOCKING(dbenv) || !LOCKING_ON(dbenv)
00260             || (!LF_ISSET(LCK_ROLLBACK) && F_ISSET(dbc, DBC_RECOVER))
00261             || (!LF_ISSET(LCK_ALWAYS) && F_ISSET(dbc, DBC_OPD))) {
00262                 lockp->off = LOCK_INVALID;
00263                 return (0);
00264         }
00265 
00266         dbc->lock.pgno = pgno;
00267         if (lkflags & DB_LOCK_RECORD)
00268                 dbc->lock.type = DB_RECORD_LOCK;
00269         else
00270                 dbc->lock.type = DB_PAGE_LOCK;
00271         lkflags &= ~DB_LOCK_RECORD;
00272 
00273         /*
00274          * If the transaction enclosing this cursor has DB_LOCK_NOWAIT set,
00275          * pass that along to the lock call.
00276          */
00277         if (DB_NONBLOCK(dbc))
00278                 lkflags |= DB_LOCK_NOWAIT;
00279 
00280         /*
00281          * If the object not currently locked, acquire the lock and return,
00282          * otherwise, lock couple.
00283          */
00284         if (LF_ISSET(LCK_COUPLE)) {
00285                 couple[0].op = DB_LOCK_GET;
00286                 couple[0].obj = &dbc->lock_dbt;
00287                 couple[0].mode = mode;
00288                 couple[1].op = DB_LOCK_PUT;
00289                 couple[1].lock = *lockp;
00290 
00291                 if ((ret = CDB_lock_vec(dbenv,
00292                     dbc->locker, lkflags, couple, 2, NULL)) == 0)
00293                         *lockp = couple[0].lock;
00294         } else
00295                 ret = CDB_lock_get(dbenv,
00296                     dbc->locker, lkflags, &dbc->lock_dbt, mode, lockp);
00297 
00298         if (ret != 0)
00299                 lockp->off = LOCK_INVALID;
00300 
00301         return (ret);
00302 }

Generated on Sun Jun 8 10:56:36 2008 for GNUmifluz by  doxygen 1.5.5