root/libdb/bt_overflow.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __ovfl_get
  2. __ovfl_put
  3. __ovfl_delete

   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  * 3. 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_overflow.c       8.5 (Berkeley) 7/16/94";
  35 #endif /* LIBC_SCCS and not lint */
  36 
  37 #ifdef HAVE_CONFIG_H
  38 #include <config.h>
  39 #endif
  40 #include <stdio.h>
  41 #ifdef STDC_HEADERS
  42 #include <stdlib.h>
  43 #endif
  44 #ifdef HAVE_STRING_H
  45 #include <string.h>
  46 #else
  47 #include <strings.h>
  48 #endif
  49 
  50 #include "db.h"
  51 #include "btree.h"
  52 
  53 /**
  54  * @file
  55  * Big key/data code.
  56  *
  57  * Big key and data entries are stored on linked lists of pages.  The initial
  58  * reference is byte string stored with the key or data and is the page number
  59  * and size.  The actual record is stored in a chain of pages linked by the
  60  * nextpg field of the #PAGE header.
  61  *
  62  * The first page of the chain has a special property.  If the record is used
  63  * by an internal page, it cannot be deleted and the #P_PRESERVE bit will be set
  64  * in the header.
  65  *
  66  * @par XXX
  67  * A single #DBT is written to each chain, so a lot of space on the last page
  68  * is wasted.  This is a fairly major bug for some data sets.
  69  */
  70 
  71 /**
  72  * __OVFL_GET -- Get an overflow key/data item.
  73  *
  74  *      @param t        tree
  75  *      @param p        pointer to {#pgno_t, @CODE{u_int32_t}}
  76  *      @param ssz
  77  *      @param buf      storage address
  78  *      @param bufsz    storage size
  79  *
  80  * @return #RET_ERROR, #RET_SUCCESS
  81  */
  82 int
  83 __ovfl_get(t, p, ssz, buf, bufsz)
  84         BTREE *t;
  85         void *p;
  86         size_t *ssz;
  87         void **buf;
  88         size_t *bufsz;
  89 {
  90         PAGE *h;
  91         pgno_t pg;
  92         size_t nb, plen;
  93         u_int32_t sz;
  94 
  95         memmove(&pg, p, sizeof(pgno_t));
  96         memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
  97         *ssz = sz;
  98 
  99 #ifdef DEBUG
 100         if (pg == P_INVALID || sz == 0)
 101                 abort();
 102 #endif
 103         /* Make the buffer bigger as necessary. */
 104         if (*bufsz < sz) {
 105                 *buf = (char *)(*buf == NULL ? malloc(sz) : realloc(*buf, sz));
 106                 if (*buf == NULL)
 107                         return (RET_ERROR);
 108                 *bufsz = sz;
 109         }
 110 
 111         /*
 112          * Step through the linked list of pages, copying the data on each one
 113          * into the buffer.  Never copy more than the data's length.
 114          */
 115         plen = t->bt_psize - BTDATAOFF;
 116         for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) {
 117                 if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
 118                         return (RET_ERROR);
 119 
 120                 nb = MIN(sz, plen);
 121                 memmove(p, (char *)h + BTDATAOFF, nb);
 122                 mpool_put(t->bt_mp, h, 0);
 123 
 124                 if ((sz -= nb) == 0)
 125                         break;
 126         }
 127         return (RET_SUCCESS);
 128 }
 129 
 130 /**
 131  * __OVFL_PUT -- Store an overflow key/data item.
 132  *
 133  *      @param t        tree
 134  *      @param dbt      #DBT to store
 135  *      @param pg       storage page number
 136  *
 137  * @return #RET_ERROR, #RET_SUCCESS
 138  */
 139 int
 140 __ovfl_put(t, dbt, pg)
 141         BTREE *t;
 142         const DBT *dbt;
 143         pgno_t *pg;
 144 {
 145         PAGE *h, *last;
 146         void *p;
 147         pgno_t npg;
 148         size_t nb, plen;
 149         u_int32_t sz;
 150 
 151         /*
 152          * Allocate pages and copy the key/data record into them.  Store the
 153          * number of the first page in the chain.
 154          */
 155         plen = t->bt_psize - BTDATAOFF;
 156         for (last = NULL, p = dbt->data, sz = dbt->size;;
 157             p = (char *)p + plen, last = h) {
 158                 if ((h = __bt_new(t, &npg)) == NULL)
 159                         return (RET_ERROR);
 160 
 161                 h->pgno = npg;
 162                 h->nextpg = h->prevpg = P_INVALID;
 163                 h->flags = P_OVERFLOW;
 164                 h->lower = h->upper = 0;
 165 
 166                 nb = MIN(sz, plen);
 167                 memmove((char *)h + BTDATAOFF, p, nb);
 168 
 169                 if (last) {
 170                         last->nextpg = h->pgno;
 171                         mpool_put(t->bt_mp, last, MPOOL_DIRTY);
 172                 } else
 173                         *pg = h->pgno;
 174 
 175                 if ((sz -= nb) == 0) {
 176                         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
 177                         break;
 178                 }
 179         }
 180         return (RET_SUCCESS);
 181 }
 182 
 183 /**
 184  * __OVFL_DELETE -- Delete an overflow chain.
 185  *
 186  *      @param t        tree
 187  *      @param p        pointer to {#pgno_t, @CODE{u_int32_t}}
 188  *
 189  * @return #RET_ERROR, #RET_SUCCESS
 190  */
 191 int
 192 __ovfl_delete(t, p)
 193         BTREE *t;
 194         void *p;
 195 {
 196         PAGE *h;
 197         pgno_t pg;
 198         size_t plen;
 199         u_int32_t sz;
 200 
 201         memmove(&pg, p, sizeof(pgno_t));
 202         memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
 203 
 204 #ifdef DEBUG
 205         if (pg == P_INVALID || sz == 0)
 206                 abort();
 207 #endif
 208         if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
 209                 return (RET_ERROR);
 210 
 211         /* Don't delete chains used by internal pages. */
 212         if (h->flags & P_PRESERVE) {
 213                 mpool_put(t->bt_mp, h, 0);
 214                 return (RET_SUCCESS);
 215         }
 216 
 217         /* Step through the chain, calling the free routine for each page. */
 218         for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) {
 219                 pg = h->nextpg;
 220                 __bt_free(t, h);
 221                 if (sz <= plen)
 222                         break;
 223                 if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
 224                         return (RET_ERROR);
 225         }
 226         return (RET_SUCCESS);
 227 }

/* [previous][next][first][last][top][bottom][index][help] */