1 | /*- |
---|
2 | * See the file LICENSE for redistribution information. |
---|
3 | * |
---|
4 | * Copyright (c) 1999-2002 |
---|
5 | * Sleepycat Software. All rights reserved. |
---|
6 | */ |
---|
7 | |
---|
8 | #include "db_config.h" |
---|
9 | |
---|
10 | #ifndef lint |
---|
11 | static const char revid[] = "Id: bt_method.c,v 11.29 2002/04/21 13:17:04 margo Exp "; |
---|
12 | #endif /* not lint */ |
---|
13 | |
---|
14 | #ifndef NO_SYSTEM_INCLUDES |
---|
15 | #include <sys/types.h> |
---|
16 | #endif |
---|
17 | |
---|
18 | #include "db_int.h" |
---|
19 | #include "dbinc/db_page.h" |
---|
20 | #include "dbinc/btree.h" |
---|
21 | #include "dbinc/qam.h" |
---|
22 | |
---|
23 | static int __bam_set_bt_compare |
---|
24 | __P((DB *, int (*)(DB *, const DBT *, const DBT *))); |
---|
25 | static int __bam_set_bt_maxkey __P((DB *, u_int32_t)); |
---|
26 | static int __bam_set_bt_minkey __P((DB *, u_int32_t)); |
---|
27 | static int __bam_set_bt_prefix |
---|
28 | __P((DB *, size_t(*)(DB *, const DBT *, const DBT *))); |
---|
29 | static int __ram_set_re_delim __P((DB *, int)); |
---|
30 | static int __ram_set_re_len __P((DB *, u_int32_t)); |
---|
31 | static int __ram_set_re_pad __P((DB *, int)); |
---|
32 | static int __ram_set_re_source __P((DB *, const char *)); |
---|
33 | |
---|
34 | /* |
---|
35 | * __bam_db_create -- |
---|
36 | * Btree specific initialization of the DB structure. |
---|
37 | * |
---|
38 | * PUBLIC: int __bam_db_create __P((DB *)); |
---|
39 | */ |
---|
40 | int |
---|
41 | __bam_db_create(dbp) |
---|
42 | DB *dbp; |
---|
43 | { |
---|
44 | BTREE *t; |
---|
45 | int ret; |
---|
46 | |
---|
47 | /* Allocate and initialize the private btree structure. */ |
---|
48 | if ((ret = __os_calloc(dbp->dbenv, 1, sizeof(BTREE), &t)) != 0) |
---|
49 | return (ret); |
---|
50 | dbp->bt_internal = t; |
---|
51 | |
---|
52 | t->bt_minkey = DEFMINKEYPAGE; /* Btree */ |
---|
53 | t->bt_compare = __bam_defcmp; |
---|
54 | t->bt_prefix = __bam_defpfx; |
---|
55 | |
---|
56 | dbp->set_bt_compare = __bam_set_bt_compare; |
---|
57 | dbp->set_bt_maxkey = __bam_set_bt_maxkey; |
---|
58 | dbp->set_bt_minkey = __bam_set_bt_minkey; |
---|
59 | dbp->set_bt_prefix = __bam_set_bt_prefix; |
---|
60 | |
---|
61 | t->re_pad = ' '; /* Recno */ |
---|
62 | t->re_delim = '\n'; |
---|
63 | t->re_eof = 1; |
---|
64 | |
---|
65 | dbp->set_re_delim = __ram_set_re_delim; |
---|
66 | dbp->set_re_len = __ram_set_re_len; |
---|
67 | dbp->set_re_pad = __ram_set_re_pad; |
---|
68 | dbp->set_re_source = __ram_set_re_source; |
---|
69 | |
---|
70 | return (0); |
---|
71 | } |
---|
72 | |
---|
73 | /* |
---|
74 | * __bam_db_close -- |
---|
75 | * Btree specific discard of the DB structure. |
---|
76 | * |
---|
77 | * PUBLIC: int __bam_db_close __P((DB *)); |
---|
78 | */ |
---|
79 | int |
---|
80 | __bam_db_close(dbp) |
---|
81 | DB *dbp; |
---|
82 | { |
---|
83 | BTREE *t; |
---|
84 | |
---|
85 | if ((t = dbp->bt_internal) == NULL) |
---|
86 | return (0); |
---|
87 | /* Recno */ |
---|
88 | /* Close any backing source file descriptor. */ |
---|
89 | if (t->re_fp != NULL) |
---|
90 | (void)fclose(t->re_fp); |
---|
91 | |
---|
92 | /* Free any backing source file name. */ |
---|
93 | if (t->re_source != NULL) |
---|
94 | __os_free(dbp->dbenv, t->re_source); |
---|
95 | |
---|
96 | __os_free(dbp->dbenv, t); |
---|
97 | dbp->bt_internal = NULL; |
---|
98 | |
---|
99 | return (0); |
---|
100 | } |
---|
101 | |
---|
102 | /* |
---|
103 | * __bam_set_flags -- |
---|
104 | * Set Btree specific flags. |
---|
105 | * |
---|
106 | * PUBLIC: int __bam_set_flags __P((DB *, u_int32_t *flagsp)); |
---|
107 | */ |
---|
108 | int |
---|
109 | __bam_set_flags(dbp, flagsp) |
---|
110 | DB *dbp; |
---|
111 | u_int32_t *flagsp; |
---|
112 | { |
---|
113 | u_int32_t flags; |
---|
114 | |
---|
115 | flags = *flagsp; |
---|
116 | if (LF_ISSET(DB_DUP | DB_DUPSORT | DB_RECNUM | DB_REVSPLITOFF)) { |
---|
117 | DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags"); |
---|
118 | |
---|
119 | /* |
---|
120 | * The DB_DUP and DB_DUPSORT flags are shared by the Hash |
---|
121 | * and Btree access methods. |
---|
122 | */ |
---|
123 | if (LF_ISSET(DB_DUP | DB_DUPSORT)) |
---|
124 | DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH); |
---|
125 | |
---|
126 | if (LF_ISSET(DB_RECNUM | DB_REVSPLITOFF)) |
---|
127 | DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); |
---|
128 | |
---|
129 | if (LF_ISSET(DB_DUP | DB_DUPSORT)) { |
---|
130 | /* DB_DUP/DB_DUPSORT is incompatible with DB_RECNUM. */ |
---|
131 | if (F_ISSET(dbp, DB_AM_RECNUM)) |
---|
132 | goto incompat; |
---|
133 | |
---|
134 | if (LF_ISSET(DB_DUPSORT)) { |
---|
135 | if (dbp->dup_compare == NULL) |
---|
136 | dbp->dup_compare = __bam_defcmp; |
---|
137 | F_SET(dbp, DB_AM_DUPSORT); |
---|
138 | } |
---|
139 | |
---|
140 | F_SET(dbp, DB_AM_DUP); |
---|
141 | LF_CLR(DB_DUP | DB_DUPSORT); |
---|
142 | } |
---|
143 | |
---|
144 | if (LF_ISSET(DB_RECNUM)) { |
---|
145 | /* DB_RECNUM is incompatible with DB_DUP/DB_DUPSORT. */ |
---|
146 | if (F_ISSET(dbp, DB_AM_DUP)) |
---|
147 | goto incompat; |
---|
148 | |
---|
149 | F_SET(dbp, DB_AM_RECNUM); |
---|
150 | LF_CLR(DB_RECNUM); |
---|
151 | } |
---|
152 | |
---|
153 | if (LF_ISSET(DB_REVSPLITOFF)) { |
---|
154 | F_SET(dbp, DB_AM_REVSPLITOFF); |
---|
155 | LF_CLR(DB_REVSPLITOFF); |
---|
156 | } |
---|
157 | |
---|
158 | *flagsp = flags; |
---|
159 | } |
---|
160 | return (0); |
---|
161 | |
---|
162 | incompat: |
---|
163 | return (__db_ferr(dbp->dbenv, "DB->set_flags", 1)); |
---|
164 | } |
---|
165 | |
---|
166 | /* |
---|
167 | * __bam_set_bt_compare -- |
---|
168 | * Set the comparison function. |
---|
169 | */ |
---|
170 | static int |
---|
171 | __bam_set_bt_compare(dbp, func) |
---|
172 | DB *dbp; |
---|
173 | int (*func) __P((DB *, const DBT *, const DBT *)); |
---|
174 | { |
---|
175 | BTREE *t; |
---|
176 | |
---|
177 | DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_compare"); |
---|
178 | DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); |
---|
179 | |
---|
180 | t = dbp->bt_internal; |
---|
181 | |
---|
182 | /* |
---|
183 | * Can't default the prefix routine if the user supplies a comparison |
---|
184 | * routine; shortening the keys can break their comparison algorithm. |
---|
185 | */ |
---|
186 | t->bt_compare = func; |
---|
187 | if (t->bt_prefix == __bam_defpfx) |
---|
188 | t->bt_prefix = NULL; |
---|
189 | |
---|
190 | return (0); |
---|
191 | } |
---|
192 | |
---|
193 | /* |
---|
194 | * __bam_set_bt_maxkey -- |
---|
195 | * Set the maximum keys per page. |
---|
196 | */ |
---|
197 | static int |
---|
198 | __bam_set_bt_maxkey(dbp, bt_maxkey) |
---|
199 | DB *dbp; |
---|
200 | u_int32_t bt_maxkey; |
---|
201 | { |
---|
202 | BTREE *t; |
---|
203 | |
---|
204 | DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_maxkey"); |
---|
205 | DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); |
---|
206 | |
---|
207 | t = dbp->bt_internal; |
---|
208 | |
---|
209 | if (bt_maxkey < 1) { |
---|
210 | __db_err(dbp->dbenv, "minimum bt_maxkey value is 1"); |
---|
211 | return (EINVAL); |
---|
212 | } |
---|
213 | |
---|
214 | t->bt_maxkey = bt_maxkey; |
---|
215 | return (0); |
---|
216 | } |
---|
217 | |
---|
218 | /* |
---|
219 | * __bam_set_bt_minkey -- |
---|
220 | * Set the minimum keys per page. |
---|
221 | */ |
---|
222 | static int |
---|
223 | __bam_set_bt_minkey(dbp, bt_minkey) |
---|
224 | DB *dbp; |
---|
225 | u_int32_t bt_minkey; |
---|
226 | { |
---|
227 | BTREE *t; |
---|
228 | |
---|
229 | DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_minkey"); |
---|
230 | DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); |
---|
231 | |
---|
232 | t = dbp->bt_internal; |
---|
233 | |
---|
234 | if (bt_minkey < 2) { |
---|
235 | __db_err(dbp->dbenv, "minimum bt_minkey value is 2"); |
---|
236 | return (EINVAL); |
---|
237 | } |
---|
238 | |
---|
239 | t->bt_minkey = bt_minkey; |
---|
240 | return (0); |
---|
241 | } |
---|
242 | |
---|
243 | /* |
---|
244 | * __bam_set_bt_prefix -- |
---|
245 | * Set the prefix function. |
---|
246 | */ |
---|
247 | static int |
---|
248 | __bam_set_bt_prefix(dbp, func) |
---|
249 | DB *dbp; |
---|
250 | size_t (*func) __P((DB *, const DBT *, const DBT *)); |
---|
251 | { |
---|
252 | BTREE *t; |
---|
253 | |
---|
254 | DB_ILLEGAL_AFTER_OPEN(dbp, "set_bt_prefix"); |
---|
255 | DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); |
---|
256 | |
---|
257 | t = dbp->bt_internal; |
---|
258 | |
---|
259 | t->bt_prefix = func; |
---|
260 | return (0); |
---|
261 | } |
---|
262 | |
---|
263 | /* |
---|
264 | * __ram_set_flags -- |
---|
265 | * Set Recno specific flags. |
---|
266 | * |
---|
267 | * PUBLIC: int __ram_set_flags __P((DB *, u_int32_t *flagsp)); |
---|
268 | */ |
---|
269 | int |
---|
270 | __ram_set_flags(dbp, flagsp) |
---|
271 | DB *dbp; |
---|
272 | u_int32_t *flagsp; |
---|
273 | { |
---|
274 | u_int32_t flags; |
---|
275 | |
---|
276 | flags = *flagsp; |
---|
277 | if (LF_ISSET(DB_RENUMBER | DB_SNAPSHOT)) { |
---|
278 | DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags"); |
---|
279 | |
---|
280 | DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); |
---|
281 | |
---|
282 | if (LF_ISSET(DB_RENUMBER)) { |
---|
283 | F_SET(dbp, DB_AM_RENUMBER); |
---|
284 | LF_CLR(DB_RENUMBER); |
---|
285 | } |
---|
286 | |
---|
287 | if (LF_ISSET(DB_SNAPSHOT)) { |
---|
288 | F_SET(dbp, DB_AM_SNAPSHOT); |
---|
289 | LF_CLR(DB_SNAPSHOT); |
---|
290 | } |
---|
291 | |
---|
292 | *flagsp = flags; |
---|
293 | } |
---|
294 | return (0); |
---|
295 | } |
---|
296 | |
---|
297 | /* |
---|
298 | * __ram_set_re_delim -- |
---|
299 | * Set the variable-length input record delimiter. |
---|
300 | */ |
---|
301 | static int |
---|
302 | __ram_set_re_delim(dbp, re_delim) |
---|
303 | DB *dbp; |
---|
304 | int re_delim; |
---|
305 | { |
---|
306 | BTREE *t; |
---|
307 | |
---|
308 | DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_delim"); |
---|
309 | DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); |
---|
310 | |
---|
311 | t = dbp->bt_internal; |
---|
312 | |
---|
313 | t->re_delim = re_delim; |
---|
314 | F_SET(dbp, DB_AM_DELIMITER); |
---|
315 | |
---|
316 | return (0); |
---|
317 | } |
---|
318 | |
---|
319 | /* |
---|
320 | * __ram_set_re_len -- |
---|
321 | * Set the variable-length input record length. |
---|
322 | */ |
---|
323 | static int |
---|
324 | __ram_set_re_len(dbp, re_len) |
---|
325 | DB *dbp; |
---|
326 | u_int32_t re_len; |
---|
327 | { |
---|
328 | BTREE *t; |
---|
329 | QUEUE *q; |
---|
330 | |
---|
331 | DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_len"); |
---|
332 | DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); |
---|
333 | |
---|
334 | t = dbp->bt_internal; |
---|
335 | t->re_len = re_len; |
---|
336 | |
---|
337 | q = dbp->q_internal; |
---|
338 | q->re_len = re_len; |
---|
339 | |
---|
340 | F_SET(dbp, DB_AM_FIXEDLEN); |
---|
341 | |
---|
342 | return (0); |
---|
343 | } |
---|
344 | |
---|
345 | /* |
---|
346 | * __ram_set_re_pad -- |
---|
347 | * Set the fixed-length record pad character. |
---|
348 | */ |
---|
349 | static int |
---|
350 | __ram_set_re_pad(dbp, re_pad) |
---|
351 | DB *dbp; |
---|
352 | int re_pad; |
---|
353 | { |
---|
354 | BTREE *t; |
---|
355 | QUEUE *q; |
---|
356 | |
---|
357 | DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_pad"); |
---|
358 | DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); |
---|
359 | |
---|
360 | t = dbp->bt_internal; |
---|
361 | t->re_pad = re_pad; |
---|
362 | |
---|
363 | q = dbp->q_internal; |
---|
364 | q->re_pad = re_pad; |
---|
365 | |
---|
366 | F_SET(dbp, DB_AM_PAD); |
---|
367 | |
---|
368 | return (0); |
---|
369 | } |
---|
370 | |
---|
371 | /* |
---|
372 | * __ram_set_re_source -- |
---|
373 | * Set the backing source file name. |
---|
374 | */ |
---|
375 | static int |
---|
376 | __ram_set_re_source(dbp, re_source) |
---|
377 | DB *dbp; |
---|
378 | const char *re_source; |
---|
379 | { |
---|
380 | BTREE *t; |
---|
381 | |
---|
382 | DB_ILLEGAL_AFTER_OPEN(dbp, "set_re_source"); |
---|
383 | DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); |
---|
384 | |
---|
385 | t = dbp->bt_internal; |
---|
386 | |
---|
387 | return (__os_strdup(dbp->dbenv, re_source, &t->re_source)); |
---|
388 | } |
---|