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

hash_open.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
00009  *      Margo Seltzer.  All rights reserved.
00010  */
00011 /*
00012  * Copyright (c) 1990, 1993, 1994
00013  *      The Regents of the University of California.  All rights reserved.
00014  *
00015  * This code is derived from software contributed to Berkeley by
00016  * Margo Seltzer.
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: hash_open.c,v 12.7 2005/11/09 14:19:51 margo 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/crypto.h"
00055 #include "dbinc/db_page.h"
00056 #include "dbinc/hash.h"
00057 #include "dbinc/log.h"
00058 #include "dbinc/db_shash.h"
00059 #include "dbinc/lock.h"
00060 #include "dbinc/mp.h"
00061 #include "dbinc/btree.h"
00062 #include "dbinc/fop.h"
00063 
00064 static db_pgno_t __ham_init_meta __P((DB *, HMETA *, db_pgno_t, DB_LSN *));
00065 
00066 /*
00067  * __ham_open --
00068  *
00069  * PUBLIC: int __ham_open __P((DB *,
00070  * PUBLIC:     DB_TXN *, const char * name, db_pgno_t, u_int32_t));
00071  */
00072 int
00073 __ham_open(dbp, txn, name, base_pgno, flags)
00074         DB *dbp;
00075         DB_TXN *txn;
00076         const char *name;
00077         db_pgno_t base_pgno;
00078         u_int32_t flags;
00079 {
00080         DB_ENV *dbenv;
00081         DBC *dbc;
00082         HASH_CURSOR *hcp;
00083         HASH *hashp;
00084         int ret, t_ret;
00085 
00086         dbenv = dbp->dbenv;
00087         dbc = NULL;
00088 
00089         /*
00090          * Get a cursor.  If DB_CREATE is specified, we may be creating
00091          * pages, and to do that safely in CDB we need a write cursor.
00092          * In STD_LOCKING mode, we'll synchronize using the meta page
00093          * lock instead.
00094          */
00095         if ((ret = __db_cursor(dbp,
00096             txn, &dbc, LF_ISSET(DB_CREATE) && CDB_LOCKING(dbenv) ?
00097             DB_WRITECURSOR : 0)) != 0)
00098                 return (ret);
00099 
00100         hcp = (HASH_CURSOR *)dbc->internal;
00101         hashp = dbp->h_internal;
00102         hashp->meta_pgno = base_pgno;
00103         if ((ret = __ham_get_meta(dbc)) != 0)
00104                 goto err1;
00105 
00106         /* Initialize the hdr structure.  */
00107         if (hcp->hdr->dbmeta.magic == DB_HASHMAGIC) {
00108                 /* File exists, verify the data in the header. */
00109                 if (hashp->h_hash == NULL)
00110                         hashp->h_hash = hcp->hdr->dbmeta.version < 5
00111                         ? __ham_func4 : __ham_func5;
00112                 if (!F_ISSET(dbp, DB_AM_RDONLY) && !IS_RECOVERING(dbenv) &&
00113                     hashp->h_hash(dbp,
00114                     CHARKEY, sizeof(CHARKEY)) != hcp->hdr->h_charkey) {
00115                         __db_err(dbp->dbenv,
00116                             "hash: incompatible hash function");
00117                         ret = EINVAL;
00118                         goto err2;
00119                 }
00120                 hashp->h_nelem = hcp->hdr->nelem;
00121                 if (F_ISSET(&hcp->hdr->dbmeta, DB_HASH_DUP))
00122                         F_SET(dbp, DB_AM_DUP);
00123                 if (F_ISSET(&hcp->hdr->dbmeta, DB_HASH_DUPSORT))
00124                         F_SET(dbp, DB_AM_DUPSORT);
00125                 if (F_ISSET(&hcp->hdr->dbmeta, DB_HASH_SUBDB))
00126                         F_SET(dbp, DB_AM_SUBDB);
00127 
00128         } else if (!IS_RECOVERING(dbenv) && !F_ISSET(dbp, DB_AM_RECOVER)) {
00129                 __db_err(dbp->dbenv,
00130                     "%s: Invalid hash meta page %d", name, base_pgno);
00131                 ret = EINVAL;
00132         }
00133 
00134 err2:   /* Release the meta data page */
00135         if ((t_ret = __ham_release_meta(dbc)) != 0 && ret == 0)
00136                 ret = t_ret;
00137 err1:   if ((t_ret  = __db_c_close(dbc)) != 0 && ret == 0)
00138                 ret = t_ret;
00139 
00140         return (ret);
00141 }
00142 
00143 /*
00144  * __ham_metachk --
00145  *
00146  * PUBLIC: int __ham_metachk __P((DB *, const char *, HMETA *));
00147  */
00148 int
00149 __ham_metachk(dbp, name, hashm)
00150         DB *dbp;
00151         const char *name;
00152         HMETA *hashm;
00153 {
00154         DB_ENV *dbenv;
00155         u_int32_t vers;
00156         int ret;
00157 
00158         dbenv = dbp->dbenv;
00159 
00160         /*
00161          * At this point, all we know is that the magic number is for a Hash.
00162          * Check the version, the database may be out of date.
00163          */
00164         vers = hashm->dbmeta.version;
00165         if (F_ISSET(dbp, DB_AM_SWAP))
00166                 M_32_SWAP(vers);
00167         switch (vers) {
00168         case 4:
00169         case 5:
00170         case 6:
00171                 __db_err(dbenv,
00172                     "%s: hash version %lu requires a version upgrade",
00173                     name, (u_long)vers);
00174                 return (DB_OLD_VERSION);
00175         case 7:
00176         case 8:
00177                 break;
00178         default:
00179                 __db_err(dbenv,
00180                     "%s: unsupported hash version: %lu", name, (u_long)vers);
00181                 return (EINVAL);
00182         }
00183 
00184         /* Swap the page if we need to. */
00185         if (F_ISSET(dbp, DB_AM_SWAP) && (ret = __ham_mswap((PAGE *)hashm)) != 0)
00186                 return (ret);
00187 
00188         /* Check the type. */
00189         if (dbp->type != DB_HASH && dbp->type != DB_UNKNOWN)
00190                 return (EINVAL);
00191         dbp->type = DB_HASH;
00192         DB_ILLEGAL_METHOD(dbp, DB_OK_HASH);
00193 
00194         /*
00195          * Check application info against metadata info, and set info, flags,
00196          * and type based on metadata info.
00197          */
00198         if ((ret = __db_fchk(dbenv,
00199             "DB->open", hashm->dbmeta.flags,
00200             DB_HASH_DUP | DB_HASH_SUBDB | DB_HASH_DUPSORT)) != 0)
00201                 return (ret);
00202 
00203         if (F_ISSET(&hashm->dbmeta, DB_HASH_DUP))
00204                 F_SET(dbp, DB_AM_DUP);
00205         else
00206                 if (F_ISSET(dbp, DB_AM_DUP)) {
00207                         __db_err(dbenv,
00208                 "%s: DB_DUP specified to open method but not set in database",
00209                             name);
00210                         return (EINVAL);
00211                 }
00212 
00213         if (F_ISSET(&hashm->dbmeta, DB_HASH_SUBDB))
00214                 F_SET(dbp, DB_AM_SUBDB);
00215         else
00216                 if (F_ISSET(dbp, DB_AM_SUBDB)) {
00217                         __db_err(dbenv,
00218             "%s: multiple databases specified but not supported in file",
00219                         name);
00220                         return (EINVAL);
00221                 }
00222 
00223         if (F_ISSET(&hashm->dbmeta, DB_HASH_DUPSORT)) {
00224                 if (dbp->dup_compare == NULL)
00225                         dbp->dup_compare = __bam_defcmp;
00226         } else
00227                 if (dbp->dup_compare != NULL) {
00228                         __db_err(dbenv,
00229                 "%s: duplicate sort function specified but not set in database",
00230                             name);
00231                         return (EINVAL);
00232                 }
00233 
00234         /* Set the page size. */
00235         dbp->pgsize = hashm->dbmeta.pagesize;
00236 
00237         /* Copy the file's ID. */
00238         memcpy(dbp->fileid, hashm->dbmeta.uid, DB_FILE_ID_LEN);
00239 
00240         return (0);
00241 }
00242 
00243 /*
00244  * __ham_init_meta --
00245  *
00246  * Initialize a hash meta-data page.  We assume that the meta-data page is
00247  * contiguous with the initial buckets that we create.  If that turns out
00248  * to be false, we'll fix it up later.  Return the initial number of buckets
00249  * allocated.
00250  */
00251 static db_pgno_t
00252 __ham_init_meta(dbp, meta, pgno, lsnp)
00253         DB *dbp;
00254         HMETA *meta;
00255         db_pgno_t pgno;
00256         DB_LSN *lsnp;
00257 {
00258         HASH *hashp;
00259         db_pgno_t nbuckets;
00260         u_int i, l2;
00261 
00262         hashp = dbp->h_internal;
00263         if (hashp->h_hash == NULL)
00264                 hashp->h_hash = DB_HASHVERSION < 5 ? __ham_func4 : __ham_func5;
00265 
00266         if (hashp->h_nelem != 0 && hashp->h_ffactor != 0) {
00267                 hashp->h_nelem = (hashp->h_nelem - 1) / hashp->h_ffactor + 1;
00268                 l2 = __db_log2(hashp->h_nelem > 2 ? hashp->h_nelem : 2);
00269         } else
00270                 l2 = 1;
00271         nbuckets = (db_pgno_t)(1 << l2);
00272 
00273         memset(meta, 0, sizeof(HMETA));
00274         meta->dbmeta.lsn = *lsnp;
00275         meta->dbmeta.pgno = pgno;
00276         meta->dbmeta.magic = DB_HASHMAGIC;
00277         meta->dbmeta.version = DB_HASHVERSION;
00278         meta->dbmeta.pagesize = dbp->pgsize;
00279         if (F_ISSET(dbp, DB_AM_CHKSUM))
00280                 FLD_SET(meta->dbmeta.metaflags, DBMETA_CHKSUM);
00281         if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
00282                 meta->dbmeta.encrypt_alg =
00283                    ((DB_CIPHER *)dbp->dbenv->crypto_handle)->alg;
00284                 DB_ASSERT(meta->dbmeta.encrypt_alg != 0);
00285                 meta->crypto_magic = meta->dbmeta.magic;
00286         }
00287         meta->dbmeta.type = P_HASHMETA;
00288         meta->dbmeta.free = PGNO_INVALID;
00289         meta->dbmeta.last_pgno = pgno;
00290         meta->max_bucket = nbuckets - 1;
00291         meta->high_mask = nbuckets - 1;
00292         meta->low_mask = (nbuckets >> 1) - 1;
00293         meta->ffactor = hashp->h_ffactor;
00294         meta->nelem = hashp->h_nelem;
00295         meta->h_charkey = hashp->h_hash(dbp, CHARKEY, sizeof(CHARKEY));
00296         memcpy(meta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN);
00297 
00298         if (F_ISSET(dbp, DB_AM_DUP))
00299                 F_SET(&meta->dbmeta, DB_HASH_DUP);
00300         if (F_ISSET(dbp, DB_AM_SUBDB))
00301                 F_SET(&meta->dbmeta, DB_HASH_SUBDB);
00302         if (dbp->dup_compare != NULL)
00303                 F_SET(&meta->dbmeta, DB_HASH_DUPSORT);
00304 
00305         /*
00306          * Create the first and second buckets pages so that we have the
00307          * page numbers for them and we can store that page number in the
00308          * meta-data header (spares[0]).
00309          */
00310         meta->spares[0] = pgno + 1;
00311 
00312         /* Fill in the last fields of the meta data page. */
00313         for (i = 1; i <= l2; i++)
00314                 meta->spares[i] = meta->spares[0];
00315         for (; i < NCACHED; i++)
00316                 meta->spares[i] = PGNO_INVALID;
00317 
00318         return (nbuckets);
00319 }
00320 
00321 /*
00322  * __ham_new_file --
00323  *      Create the necessary pages to begin a new database file.  If name
00324  * is NULL, then this is an unnamed file, the mpf has been set in the dbp
00325  * and we simply create the pages using mpool.  In this case, we don't log
00326  * because we never have to redo an unnamed create and the undo simply
00327  * frees resources.
00328  *
00329  * This code appears more complex than it is because of the two cases (named
00330  * and unnamed).  The way to read the code is that for each page being created,
00331  * there are three parts: 1) a "get page" chunk (which either uses malloc'd
00332  * memory or calls __memp_fget), 2) the initialization, and 3) the "put page"
00333  * chunk which either does a fop write or an __memp_fput.
00334  *
00335  * PUBLIC: int __ham_new_file __P((DB *, DB_TXN *, DB_FH *, const char *));
00336  */
00337 int
00338 __ham_new_file(dbp, txn, fhp, name)
00339         DB *dbp;
00340         DB_TXN *txn;
00341         DB_FH *fhp;
00342         const char *name;
00343 {
00344         DB_ENV *dbenv;
00345         DB_LSN lsn;
00346         DB_MPOOLFILE *mpf;
00347         DB_PGINFO pginfo;
00348         DBT pdbt;
00349         HMETA *meta;
00350         PAGE *page;
00351         int ret;
00352         db_pgno_t lpgno;
00353         void *buf;
00354 
00355         dbenv = dbp->dbenv;
00356         mpf = dbp->mpf;
00357         meta = NULL;
00358         page = NULL;
00359         buf = NULL;
00360 
00361         if (F_ISSET(dbp, DB_AM_INMEM)) {
00362                 /* Build meta-data page. */
00363                 lpgno = PGNO_BASE_MD;
00364                 if ((ret =
00365                    __memp_fget(mpf, &lpgno, DB_MPOOL_CREATE, &meta)) != 0)
00366                         return (ret);
00367                 LSN_NOT_LOGGED(lsn);
00368                 lpgno = __ham_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
00369                 meta->dbmeta.last_pgno = lpgno;
00370                 if ((ret = __db_log_page(dbp,
00371                     txn, &lsn, meta->dbmeta.pgno, (PAGE *)meta)) != 0)
00372                         goto err;
00373                 ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY);
00374                 meta = NULL;
00375                 if (ret != 0)
00376                         goto err;
00377 
00378                 /* Allocate the final hash bucket. */
00379                 if ((ret =
00380                     __memp_fget(mpf, &lpgno, DB_MPOOL_CREATE, &page)) != 0)
00381                         goto err;
00382                 P_INIT(page,
00383                     dbp->pgsize, lpgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
00384                 LSN_NOT_LOGGED(page->lsn);
00385                 if ((ret =
00386                     __db_log_page(dbp, txn, &page->lsn, lpgno, page)) != 0)
00387                         goto err;
00388                 ret = __memp_fput(mpf, page, DB_MPOOL_DIRTY);
00389                 page = NULL;
00390                 if (ret != 0)
00391                         goto err;
00392         } else {
00393                 memset(&pdbt, 0, sizeof(pdbt));
00394 
00395                 /* Build meta-data page. */
00396                 pginfo.db_pagesize = dbp->pgsize;
00397                 pginfo.type = dbp->type;
00398                 pginfo.flags =
00399                     F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP));
00400                 pdbt.data = &pginfo;
00401                 pdbt.size = sizeof(pginfo);
00402                 if ((ret = __os_calloc(dbp->dbenv, 1, dbp->pgsize, &buf)) != 0)
00403                         return (ret);
00404                 meta = (HMETA *)buf;
00405                 LSN_NOT_LOGGED(lsn);
00406                 lpgno = __ham_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
00407                 meta->dbmeta.last_pgno = lpgno;
00408                 if ((ret = __db_pgout(dbenv, PGNO_BASE_MD, meta, &pdbt)) != 0)
00409                         goto err;
00410                 if ((ret = __fop_write(dbenv, txn, name, DB_APP_DATA, fhp,
00411                     dbp->pgsize, 0, 0, buf, dbp->pgsize, 1, F_ISSET(
00412                     dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0)) != 0)
00413                         goto err;
00414                 meta = NULL;
00415 
00416                 /* Allocate the final hash bucket. */
00417 #ifdef DIAGNOSTIC
00418                 memset(buf, 0, dbp->pgsize);
00419 #endif
00420                 page = (PAGE *)buf;
00421                 P_INIT(page,
00422                     dbp->pgsize, lpgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
00423                 LSN_NOT_LOGGED(page->lsn);
00424                 if ((ret = __db_pgout(dbenv, lpgno, buf, &pdbt)) != 0)
00425                         goto err;
00426                 if ((ret = __fop_write(dbenv, txn, name, DB_APP_DATA, fhp,
00427                     dbp->pgsize, lpgno, 0, buf, dbp->pgsize, 1, F_ISSET(
00428                     dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0)) != 0)
00429                         goto err;
00430                 page = NULL;
00431         }
00432 
00433 err:    if (buf != NULL)
00434                 __os_free(dbenv, buf);
00435         else {
00436                 if (meta != NULL)
00437                         (void)__memp_fput(mpf, meta, 0);
00438                 if (page != NULL)
00439                         (void)__memp_fput(mpf, page, 0);
00440         }
00441         return (ret);
00442 }
00443 
00444 /*
00445  * __ham_new_subdb --
00446  *      Create the necessary pages to begin a new subdatabase.
00447  *
00448  * PUBLIC: int __ham_new_subdb __P((DB *, DB *, DB_TXN *));
00449  */
00450 int
00451 __ham_new_subdb(mdbp, dbp, txn)
00452         DB *mdbp, *dbp;
00453         DB_TXN *txn;
00454 {
00455         DBC *dbc;
00456         DB_ENV *dbenv;
00457         DB_LOCK metalock, mmlock;
00458         DB_LSN lsn;
00459         DB_MPOOLFILE *mpf;
00460         DBMETA *mmeta;
00461         HMETA *meta;
00462         PAGE *h;
00463         int i, ret, t_ret;
00464         db_pgno_t lpgno, mpgno;
00465 
00466         dbenv = mdbp->dbenv;
00467         mpf = mdbp->mpf;
00468         dbc = NULL;
00469         meta = NULL;
00470         mmeta = NULL;
00471         LOCK_INIT(metalock);
00472         LOCK_INIT(mmlock);
00473 
00474         if ((ret = __db_cursor(mdbp, txn,
00475             &dbc, CDB_LOCKING(dbenv) ?  DB_WRITECURSOR : 0)) != 0)
00476                 return (ret);
00477 
00478         /* Get and lock the new meta data page. */
00479         if ((ret = __db_lget(dbc,
00480             0, dbp->meta_pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
00481                 goto err;
00482         if ((ret =
00483             __memp_fget(mpf, &dbp->meta_pgno, DB_MPOOL_CREATE, &meta)) != 0)
00484                 goto err;
00485 
00486         /* Initialize the new meta-data page. */
00487         lsn = meta->dbmeta.lsn;
00488         lpgno = __ham_init_meta(dbp, meta, dbp->meta_pgno, &lsn);
00489 
00490         /*
00491          * We are about to allocate a set of contiguous buckets (lpgno
00492          * worth).  We need to get the master meta-data page to figure
00493          * out where these pages are and to allocate them.  So, lock and
00494          * get the master meta data page.
00495          */
00496         mpgno = PGNO_BASE_MD;
00497         if ((ret = __db_lget(dbc, 0, mpgno, DB_LOCK_WRITE, 0, &mmlock)) != 0)
00498                 goto err;
00499         if ((ret = __memp_fget(mpf, &mpgno, 0, &mmeta)) != 0)
00500                 goto err;
00501 
00502         /*
00503          * Now update the hash meta-data page to reflect where the first
00504          * set of buckets are actually located.
00505          */
00506         meta->spares[0] = mmeta->last_pgno + 1;
00507         for (i = 0; i < NCACHED && meta->spares[i] != PGNO_INVALID; i++)
00508                 meta->spares[i] = meta->spares[0];
00509 
00510         /* The new meta data page is now complete; log it. */
00511         if ((ret = __db_log_page(mdbp,
00512             txn, &meta->dbmeta.lsn, dbp->meta_pgno, (PAGE *)meta)) != 0)
00513                 goto err;
00514 
00515         /* Reflect the group allocation. */
00516         if (DBENV_LOGGING(dbenv))
00517                 if ((ret = __ham_groupalloc_log(mdbp, txn,
00518                     &LSN(mmeta), 0, &LSN(mmeta), meta->spares[0],
00519                     meta->max_bucket + 1, mmeta->free, mmeta->last_pgno)) != 0)
00520                         goto err;
00521 
00522         /* Release the new meta-data page. */
00523         if ((ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY)) != 0)
00524                 goto err;
00525         meta = NULL;
00526 
00527         lpgno += mmeta->last_pgno;
00528 
00529         /* Now allocate the final hash bucket. */
00530         if ((ret = __memp_fget(mpf, &lpgno, DB_MPOOL_CREATE, &h)) != 0)
00531                 goto err;
00532 
00533         mmeta->last_pgno = lpgno;
00534         P_INIT(h, dbp->pgsize, lpgno, PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
00535         LSN(h) = LSN(mmeta);
00536         if ((ret = __memp_fput(mpf, h, DB_MPOOL_DIRTY)) != 0)
00537                 goto err;
00538 
00539         /* Now put the master-metadata page back. */
00540         if ((ret = __memp_fput(mpf, mmeta, DB_MPOOL_DIRTY)) != 0)
00541                 goto err;
00542         mmeta = NULL;
00543 
00544 err:
00545         if (mmeta != NULL)
00546                 if ((t_ret = __memp_fput(mpf, mmeta, 0)) != 0 && ret == 0)
00547                         ret = t_ret;
00548         if ((t_ret = __LPUT(dbc, mmlock)) != 0 && ret == 0)
00549                 ret = t_ret;
00550         if (meta != NULL)
00551                 if ((t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
00552                         ret = t_ret;
00553         if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0)
00554                 ret = t_ret;
00555         if (dbc != NULL)
00556                 if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)
00557                         ret = t_ret;
00558         return (ret);
00559 }

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