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