bt_overflow.c revision 1.16.6.2 1 1.16.6.2 joerg /* $NetBSD: bt_overflow.c,v 1.16.6.2 2008/09/11 12:58:01 joerg Exp $ */
2 1.16.6.2 joerg
3 1.16.6.2 joerg /*-
4 1.16.6.2 joerg * Copyright (c) 1990, 1993, 1994
5 1.16.6.2 joerg * The Regents of the University of California. All rights reserved.
6 1.16.6.2 joerg *
7 1.16.6.2 joerg * This code is derived from software contributed to Berkeley by
8 1.16.6.2 joerg * Mike Olson.
9 1.16.6.2 joerg *
10 1.16.6.2 joerg * Redistribution and use in source and binary forms, with or without
11 1.16.6.2 joerg * modification, are permitted provided that the following conditions
12 1.16.6.2 joerg * are met:
13 1.16.6.2 joerg * 1. Redistributions of source code must retain the above copyright
14 1.16.6.2 joerg * notice, this list of conditions and the following disclaimer.
15 1.16.6.2 joerg * 2. Redistributions in binary form must reproduce the above copyright
16 1.16.6.2 joerg * notice, this list of conditions and the following disclaimer in the
17 1.16.6.2 joerg * documentation and/or other materials provided with the distribution.
18 1.16.6.2 joerg * 3. Neither the name of the University nor the names of its contributors
19 1.16.6.2 joerg * may be used to endorse or promote products derived from this software
20 1.16.6.2 joerg * without specific prior written permission.
21 1.16.6.2 joerg *
22 1.16.6.2 joerg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 1.16.6.2 joerg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.16.6.2 joerg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.16.6.2 joerg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 1.16.6.2 joerg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.16.6.2 joerg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.16.6.2 joerg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.16.6.2 joerg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.16.6.2 joerg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.16.6.2 joerg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.16.6.2 joerg * SUCH DAMAGE.
33 1.16.6.2 joerg */
34 1.16.6.2 joerg
35 1.16.6.2 joerg #if HAVE_NBTOOL_CONFIG_H
36 1.16.6.2 joerg #include "nbtool_config.h"
37 1.16.6.2 joerg #endif
38 1.16.6.2 joerg
39 1.16.6.2 joerg #include <sys/cdefs.h>
40 1.16.6.2 joerg __RCSID("$NetBSD: bt_overflow.c,v 1.16.6.2 2008/09/11 12:58:01 joerg Exp $");
41 1.16.6.2 joerg
42 1.16.6.2 joerg #include "namespace.h"
43 1.16.6.2 joerg #include <sys/param.h>
44 1.16.6.2 joerg
45 1.16.6.2 joerg #include <assert.h>
46 1.16.6.2 joerg #include <stdio.h>
47 1.16.6.2 joerg #include <stdlib.h>
48 1.16.6.2 joerg #include <string.h>
49 1.16.6.2 joerg
50 1.16.6.2 joerg #include <db.h>
51 1.16.6.2 joerg #include "btree.h"
52 1.16.6.2 joerg
53 1.16.6.2 joerg /*
54 1.16.6.2 joerg * Big key/data code.
55 1.16.6.2 joerg *
56 1.16.6.2 joerg * Big key and data entries are stored on linked lists of pages. The initial
57 1.16.6.2 joerg * reference is byte string stored with the key or data and is the page number
58 1.16.6.2 joerg * and size. The actual record is stored in a chain of pages linked by the
59 1.16.6.2 joerg * nextpg field of the PAGE header.
60 1.16.6.2 joerg *
61 1.16.6.2 joerg * The first page of the chain has a special property. If the record is used
62 1.16.6.2 joerg * by an internal page, it cannot be deleted and the P_PRESERVE bit will be set
63 1.16.6.2 joerg * in the header.
64 1.16.6.2 joerg *
65 1.16.6.2 joerg * XXX
66 1.16.6.2 joerg * A single DBT is written to each chain, so a lot of space on the last page
67 1.16.6.2 joerg * is wasted. This is a fairly major bug for some data sets.
68 1.16.6.2 joerg */
69 1.16.6.2 joerg
70 1.16.6.2 joerg /*
71 1.16.6.2 joerg * __OVFL_GET -- Get an overflow key/data item.
72 1.16.6.2 joerg *
73 1.16.6.2 joerg * Parameters:
74 1.16.6.2 joerg * t: tree
75 1.16.6.2 joerg * p: pointer to { pgno_t, uint32_t }
76 1.16.6.2 joerg * buf: storage address
77 1.16.6.2 joerg * bufsz: storage size
78 1.16.6.2 joerg *
79 1.16.6.2 joerg * Returns:
80 1.16.6.2 joerg * RET_ERROR, RET_SUCCESS
81 1.16.6.2 joerg */
82 1.16.6.2 joerg int
83 1.16.6.2 joerg __ovfl_get(BTREE *t, void *p, size_t *ssz, void **buf, size_t *bufsz)
84 1.16.6.2 joerg {
85 1.16.6.2 joerg PAGE *h;
86 1.16.6.2 joerg pgno_t pg;
87 1.16.6.2 joerg uint32_t sz, nb, plen;
88 1.16.6.2 joerg size_t temp;
89 1.16.6.2 joerg
90 1.16.6.2 joerg memmove(&pg, p, sizeof(pgno_t));
91 1.16.6.2 joerg memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(uint32_t));
92 1.16.6.2 joerg *ssz = sz;
93 1.16.6.2 joerg
94 1.16.6.2 joerg #ifdef DEBUG
95 1.16.6.2 joerg if (pg == P_INVALID || sz == 0)
96 1.16.6.2 joerg abort();
97 1.16.6.2 joerg #endif
98 1.16.6.2 joerg /* Make the buffer bigger as necessary. */
99 1.16.6.2 joerg if (*bufsz < sz) {
100 1.16.6.2 joerg *buf = (char *)(*buf == NULL ? malloc(sz) : realloc(*buf, sz));
101 1.16.6.2 joerg if (*buf == NULL)
102 1.16.6.2 joerg return (RET_ERROR);
103 1.16.6.2 joerg *bufsz = sz;
104 1.16.6.2 joerg }
105 1.16.6.2 joerg
106 1.16.6.2 joerg /*
107 1.16.6.2 joerg * Step through the linked list of pages, copying the data on each one
108 1.16.6.2 joerg * into the buffer. Never copy more than the data's length.
109 1.16.6.2 joerg */
110 1.16.6.2 joerg temp = t->bt_psize - BTDATAOFF;
111 1.16.6.2 joerg _DBFIT(temp, uint32_t);
112 1.16.6.2 joerg plen = (uint32_t)temp;
113 1.16.6.2 joerg for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) {
114 1.16.6.2 joerg if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
115 1.16.6.2 joerg return (RET_ERROR);
116 1.16.6.2 joerg
117 1.16.6.2 joerg nb = MIN(sz, plen);
118 1.16.6.2 joerg memmove(p, (char *)(void *)h + BTDATAOFF, nb);
119 1.16.6.2 joerg mpool_put(t->bt_mp, h, 0);
120 1.16.6.2 joerg
121 1.16.6.2 joerg if ((sz -= nb) == 0)
122 1.16.6.2 joerg break;
123 1.16.6.2 joerg }
124 1.16.6.2 joerg return (RET_SUCCESS);
125 1.16.6.2 joerg }
126 1.16.6.2 joerg
127 1.16.6.2 joerg /*
128 1.16.6.2 joerg * __OVFL_PUT -- Store an overflow key/data item.
129 1.16.6.2 joerg *
130 1.16.6.2 joerg * Parameters:
131 1.16.6.2 joerg * t: tree
132 1.16.6.2 joerg * data: DBT to store
133 1.16.6.2 joerg * pgno: storage page number
134 1.16.6.2 joerg *
135 1.16.6.2 joerg * Returns:
136 1.16.6.2 joerg * RET_ERROR, RET_SUCCESS
137 1.16.6.2 joerg */
138 1.16.6.2 joerg int
139 1.16.6.2 joerg __ovfl_put(BTREE *t, const DBT *dbt, pgno_t *pg)
140 1.16.6.2 joerg {
141 1.16.6.2 joerg PAGE *h, *last;
142 1.16.6.2 joerg void *p;
143 1.16.6.2 joerg pgno_t npg;
144 1.16.6.2 joerg uint32_t sz, nb, plen;
145 1.16.6.2 joerg size_t temp;
146 1.16.6.2 joerg
147 1.16.6.2 joerg /*
148 1.16.6.2 joerg * Allocate pages and copy the key/data record into them. Store the
149 1.16.6.2 joerg * number of the first page in the chain.
150 1.16.6.2 joerg */
151 1.16.6.2 joerg temp = t->bt_psize - BTDATAOFF;
152 1.16.6.2 joerg _DBFIT(temp, uint32_t);
153 1.16.6.2 joerg plen = (uint32_t)temp;
154 1.16.6.2 joerg last = NULL;
155 1.16.6.2 joerg p = dbt->data;
156 1.16.6.2 joerg temp = dbt->size;
157 1.16.6.2 joerg _DBFIT(temp, uint32_t);
158 1.16.6.2 joerg sz = temp;
159 1.16.6.2 joerg for (;; p = (char *)p + plen, last = h) {
160 1.16.6.2 joerg if ((h = __bt_new(t, &npg)) == NULL)
161 1.16.6.2 joerg return (RET_ERROR);
162 1.16.6.2 joerg
163 1.16.6.2 joerg h->pgno = npg;
164 1.16.6.2 joerg h->nextpg = h->prevpg = P_INVALID;
165 1.16.6.2 joerg h->flags = P_OVERFLOW;
166 1.16.6.2 joerg h->lower = h->upper = 0;
167 1.16.6.2 joerg
168 1.16.6.2 joerg nb = MIN(sz, plen);
169 1.16.6.2 joerg (void)memmove((char *)(void *)h + BTDATAOFF, p, (size_t)nb);
170 1.16.6.2 joerg
171 1.16.6.2 joerg if (last) {
172 1.16.6.2 joerg last->nextpg = h->pgno;
173 1.16.6.2 joerg mpool_put(t->bt_mp, last, MPOOL_DIRTY);
174 1.16.6.2 joerg } else
175 1.16.6.2 joerg *pg = h->pgno;
176 1.16.6.2 joerg
177 1.16.6.2 joerg if ((sz -= nb) == 0) {
178 1.16.6.2 joerg mpool_put(t->bt_mp, h, MPOOL_DIRTY);
179 1.16.6.2 joerg break;
180 1.16.6.2 joerg }
181 1.16.6.2 joerg }
182 1.16.6.2 joerg return (RET_SUCCESS);
183 1.16.6.2 joerg }
184 1.16.6.2 joerg
185 1.16.6.2 joerg /*
186 1.16.6.2 joerg * __OVFL_DELETE -- Delete an overflow chain.
187 1.16.6.2 joerg *
188 1.16.6.2 joerg * Parameters:
189 1.16.6.2 joerg * t: tree
190 1.16.6.2 joerg * p: pointer to { pgno_t, uint32_t }
191 1.16.6.2 joerg *
192 1.16.6.2 joerg * Returns:
193 1.16.6.2 joerg * RET_ERROR, RET_SUCCESS
194 1.16.6.2 joerg */
195 1.16.6.2 joerg int
196 1.16.6.2 joerg __ovfl_delete(BTREE *t, void *p)
197 1.16.6.2 joerg {
198 1.16.6.2 joerg PAGE *h;
199 1.16.6.2 joerg pgno_t pg;
200 1.16.6.2 joerg uint32_t sz, plen;
201 1.16.6.2 joerg size_t temp;
202 1.16.6.2 joerg
203 1.16.6.2 joerg (void)memmove(&pg, p, sizeof(pgno_t));
204 1.16.6.2 joerg (void)memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(uint32_t));
205 1.16.6.2 joerg
206 1.16.6.2 joerg #ifdef DEBUG
207 1.16.6.2 joerg if (pg == P_INVALID || sz == 0)
208 1.16.6.2 joerg abort();
209 1.16.6.2 joerg #endif
210 1.16.6.2 joerg if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
211 1.16.6.2 joerg return (RET_ERROR);
212 1.16.6.2 joerg
213 1.16.6.2 joerg /* Don't delete chains used by internal pages. */
214 1.16.6.2 joerg if (h->flags & P_PRESERVE) {
215 1.16.6.2 joerg mpool_put(t->bt_mp, h, 0);
216 1.16.6.2 joerg return (RET_SUCCESS);
217 1.16.6.2 joerg }
218 1.16.6.2 joerg
219 1.16.6.2 joerg /* Step through the chain, calling the free routine for each page. */
220 1.16.6.2 joerg temp = t->bt_psize - BTDATAOFF;
221 1.16.6.2 joerg _DBFIT(temp, uint32_t);
222 1.16.6.2 joerg plen = (uint32_t)temp;
223 1.16.6.2 joerg for (;; sz -= plen) {
224 1.16.6.2 joerg pg = h->nextpg;
225 1.16.6.2 joerg __bt_free(t, h);
226 1.16.6.2 joerg if (sz <= plen)
227 1.16.6.2 joerg break;
228 1.16.6.2 joerg if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
229 1.16.6.2 joerg return (RET_ERROR);
230 1.16.6.2 joerg }
231 1.16.6.2 joerg return (RET_SUCCESS);
232 1.16.6.2 joerg }
233