try to make display narrower
[unix-history] / usr / src / lib / libc / db / btree / bt_utils.c
CommitLineData
fb5357d5
MO
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Mike Olson.
7 *
8 * %sccs.include.redist.c%
9 */
10
11#if defined(LIBC_SCCS) && !defined(lint)
7d2840f6 12static char sccsid[] = "@(#)bt_utils.c 5.3 (Berkeley) %G%";
fb5357d5
MO
13#endif /* LIBC_SCCS and not lint */
14
15#include <sys/types.h>
16#include <db.h>
fb91cf55
KB
17#include <stdlib.h>
18#include <string.h>
fb5357d5
MO
19#include "btree.h"
20
21/*
22 * _BT_BUILDRET -- Build return key/data pair as a result of search or scan.
23 *
24 * This routine manages the statically allocated buffers in which we
25 * return data to the user.
26 *
27 * Parameters:
28 * t -- btree from which to return datum
29 * d -- DATUM to be returned to the user.
30 * data -- data argument supplied by user for return
31 * key -- key argument supplied by user for return
32 *
33 * Returns:
34 * RET_SUCCESS, RET_ERROR.
35 *
36 * Side Effects:
37 * May free and reallocate static buffers, if the data
38 * we want to return is bigger than the space we have to
39 * do so.
40 */
41
42int
43_bt_buildret(t, d, data, key)
44 BTREE_P t;
45 DATUM *d;
46 DBT *data;
47 DBT *key;
48{
49 static int _data_s = 0;
50 static int _key_s = 0;
51 static char *_data = (char *) NULL;
52 static char *_key = (char *) NULL;
53 pgno_t chain;
54
55 if (d->d_flags & D_BIGKEY) {
56 if (_key != (char *) NULL)
57 (void) free(_key);
58 (void) bcopy((char *) &(d->d_bytes[0]),
59 (char *) &chain,
60 sizeof(chain));
61 if (_bt_getbig(t, chain, &_key, &_key_s) == RET_ERROR)
62 return (RET_ERROR);
7d2840f6 63 key->data = (u_char *)_key;
fb5357d5
MO
64 key->size = _key_s;
65 } else {
66 /* need more space for key? */
67 if (d->d_ksize > _key_s) {
68 if (_key != (char *) NULL)
69 (void) free (_key);
70 if ((_key = (char *) malloc((unsigned) d->d_ksize))
71 == (char *) NULL)
72 return (RET_ERROR);
73 _key_s = d->d_ksize;
74 }
75
7d2840f6 76 key->data = (u_char *)_key;
fb5357d5
MO
77 if ((key->size = d->d_ksize) > 0)
78 (void) bcopy(&(d->d_bytes[0]),
79 _key,
80 (int) d->d_ksize);
81 }
82
83 if (d->d_flags & D_BIGDATA) {
84 if (_data != (char *) NULL)
85 (void) free(_data);
86 (void) bcopy(&(d->d_bytes[d->d_ksize]),
87 (char *) &chain,
88 sizeof(chain));
89 if (_bt_getbig(t, chain, &_data, &_data_s) == RET_ERROR)
90 return (RET_ERROR);
7d2840f6 91 data->data = (u_char *)_data;
fb5357d5
MO
92 data->size = _data_s;
93 } else {
94 /* need more space for data? */
95 if (d->d_dsize > _data_s) {
96 if (_data != (char *) NULL)
97 (void) free (_data);
98 if ((_data = (char *) malloc((unsigned) d->d_dsize))
99 == (char *) NULL)
100 return (RET_ERROR);
101 _data_s = d->d_dsize;
102 }
103
7d2840f6 104 data->data = (u_char *)_data;
fb5357d5
MO
105
106 if ((data->size = d->d_dsize) > 0)
107 (void) bcopy(&(d->d_bytes[d->d_ksize]),
108 _data,
109 (size_t) (d->d_dsize));
110 }
111
112 return (RET_SUCCESS);
113}
114
115/*
116 * _BT_CMP -- Compare a key to a given item on the current page.
117 *
118 * This routine is a wrapper for the user's comparison function.
119 *
120 * Parameters:
121 * t -- tree in which to do comparison
122 * p -- pointer to one argument for the comparison function
123 * n -- index of item to supply second arg to comparison function
124 *
125 * Returns:
126 * < 0 if p is < item at n
127 * = 0 if p is = item at n
128 * > 0 if p is > item at n
129 */
130
131int
132_bt_cmp(t, p, n)
133 BTREE_P t;
134 char *p;
135 index_t n;
136{
137 BTHEADER *h;
138 IDATUM *id;
139 DATUM *d;
140 char *arg;
141 int ignore;
142 int free_arg;
143 pgno_t chain;
144 int r;
145
146 h = t->bt_curpage;
147
148 /*
149 * The left-most key at any level of the tree on internal pages
150 * is guaranteed (artificially, by the code here) to be less than
151 * any user key. This saves us from having to update the leftmost
152 * key when the user inserts a new key in the tree smaller than
153 * anything we've seen yet.
154 */
155
156 if (h->h_prevpg == P_NONE && !(h->h_flags & F_LEAF) && n == 0)
157 return (1);
158
159 if (h->h_flags & F_LEAF) {
160 d = (DATUM *) GETDATUM(h,n);
161 if (d->d_flags & D_BIGKEY) {
162 free_arg = TRUE;
163 bcopy(&(d->d_bytes[0]), (char *) &chain, sizeof(chain));
164 if (_bt_getbig(t, chain, &arg, &ignore) == RET_ERROR)
165 return (RET_ERROR);
166 } else {
167 free_arg = FALSE;
168 arg = &(d->d_bytes[0]);
169 }
170 } else {
171 id = (IDATUM *) GETDATUM(h,n);
172 if (id->i_flags & D_BIGKEY) {
173 free_arg = TRUE;
174 bcopy(&(id->i_bytes[0]),
175 (char *) &chain,
176 sizeof(chain));
177 if (_bt_getbig(t, chain, &arg, &ignore) == RET_ERROR)
178 return (RET_ERROR);
179 } else {
180 free_arg = FALSE;
181 arg = &(id->i_bytes[0]);
182 }
183 }
184 r = (*(t->bt_compare))(p, arg);
185
186 if (free_arg)
187 (void) free(arg);
188
189 return (r);
190}
191
192/*
193 * _BT_PUSH/_BT_POP -- Push/pop a parent page number on the parent stack.
194 *
195 * When we descend the tree, we keep track of parent pages in order
196 * to handle splits on insertions.
197 *
198 * Parameters:
199 * t -- tree for which to push parent
200 * pgno -- page number to push (_bt_push only)
201 *
202 * Returns:
203 * RET_SUCCESS, RET_ERROR.
204 */
205
206int
207_bt_push(t, pgno)
208 BTREE_P t;
209 pgno_t pgno;
210{
211 BTSTACK *new;
212
213 if ((new = (BTSTACK *) malloc((unsigned) sizeof(BTSTACK)))
214 == (BTSTACK *) NULL)
215 return (RET_ERROR);
216 new->bts_pgno = pgno;
217 new->bts_next = t->bt_stack;
218 t->bt_stack = new;
219
220 return (RET_SUCCESS);
221}
222
223pgno_t
224_bt_pop(t)
225 BTREE_P t;
226{
227 BTSTACK *s;
228 pgno_t p = P_NONE;
229
230 if ((s = t->bt_stack) != (BTSTACK *) NULL) {
231 p = s->bts_pgno;
232 t->bt_stack = s->bts_next;
233 (void) free ((char *) s);
234 }
235 return (p);
236}
237
238#ifdef DEBUG
239void
240_btdump(tree)
241 BTREE tree;
242{
243 BTREE_P t = (BTREE_P) tree;
244 DATUM *d;
245 IDATUM *id;
246 BTHEADER *h;
247 pgno_t npages;
248 pgno_t i;
249 index_t cur, top;
250
251 npages = t->bt_npages;
252 (void) printf("\"%s\" fd %d pgsz %d curpg %d @ 0x%lx",
253 t->bt_fname, t->bt_s.bt_d.d_fd,
254 t->bt_psize, t->bt_curpage);
255 (void) printf("npg %d cmp 0x%lx flags=(", npages, t->bt_compare);
256 if (t->bt_flags & BTF_SEQINIT)
257 (void) printf("BTF_SEQINIT");
258 (void) printf(")\n");
259
260 for (i = P_ROOT; i <= npages; i++) {
261 if (_bt_getpage(t, i) == RET_ERROR)
262 _punt();
263 h = t->bt_curpage;
264 top = NEXTINDEX(h);
265 (void) printf(" page %d:\n", i);
266 (void) printf("\tpgno %d prev %d next %d\n",
267 h->h_pgno, h->h_prevpg, h->h_nextpg);
268 (void) printf("\tlower %d upper %d nextind %d flags (",
269 h->h_lower, h->h_upper, top);
270 if (h->h_flags & F_LEAF)
271 (void) printf("F_LEAF");
272 else
273 (void) printf("<internal>");
274 if (h->h_flags & F_DIRTY)
275 (void) printf("|F_DIRTY");
276 if (h->h_flags & F_PRESERVE)
277 (void) printf("|F_PRESERVE");
278 if (h->h_flags & F_CONT) {
279 (void) printf("|F_CONT)");
280 if (h->h_prevpg == P_NONE) {
281 size_t longsz;
282 (void) bcopy((char *) &(h->h_linp[0]),
283 (char *) &longsz,
284 sizeof(longsz));
285 printf("\n\t\t(chain start, data length %ld)",
286 longsz);
287 }
288 printf("\n");
289 continue;
290 }
291 (void) printf(")\n");
292 for (cur = 0; cur < top; cur++) {
293 (void) printf("\t [%d] off %d ", cur, h->h_linp[cur]);
294 if (h->h_flags & F_LEAF) {
295 d = (DATUM *) GETDATUM(h,cur);
296 (void) printf("ksize %d", d->d_ksize);
297 if (d->d_flags & D_BIGKEY)
298 (void) printf(" (indirect)");
299 (void) printf("; dsize %d", d->d_dsize);
300 if (d->d_flags & D_BIGDATA)
301 (void) printf(" (indirect)");
302 } else {
303 id = (IDATUM *) GETDATUM(h,cur);
304 (void) printf("size %d pgno %d",
305 id->i_size, id->i_pgno);
306 if (id->i_flags & D_BIGKEY)
307 (void) printf(" (indirect)");
308 }
309 (void) printf("\n");
310 }
311 (void) printf("\n");
312 }
313}
314#endif /* DEBUG */
315
316#ifdef DEBUG
317_punt()
318{
319 int pid;
320
321 pid = getpid();
322 (void) kill(pid, SIGILL);
323}
324#endif /* DEBUG */