Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/db/test/btree.tests/main.c
39583 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 1990, 1993
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
#include <fcntl.h>
37
#include <db.h>
38
#include <errno.h>
39
#include <stdio.h>
40
#include <ctype.h>
41
#include <stdlib.h>
42
#include <string.h>
43
#include "btree.h"
44
45
typedef struct cmd_table {
46
char *cmd;
47
int nargs;
48
int rconv;
49
void (*func)(DB *, char **);
50
char *usage, *descrip;
51
} cmd_table;
52
53
int stopstop;
54
DB *globaldb;
55
56
void append(DB *, char **);
57
void bstat(DB *, char **);
58
void cursor(DB *, char **);
59
void delcur(DB *, char **);
60
void delete(DB *, char **);
61
void dump(DB *, char **);
62
void first(DB *, char **);
63
void get(DB *, char **);
64
void help(DB *, char **);
65
void iafter(DB *, char **);
66
void ibefore(DB *, char **);
67
void icursor(DB *, char **);
68
void insert(DB *, char **);
69
void keydata(DBT *, DBT *);
70
void last(DB *, char **);
71
void list(DB *, char **);
72
void load(DB *, char **);
73
void mstat(DB *, char **);
74
void next(DB *, char **);
75
int parse(char *, char **, int);
76
void previous(DB *, char **);
77
void show(DB *, char **);
78
void usage(void);
79
void user(DB *);
80
81
cmd_table commands[] = {
82
"?", 0, 0, help, "help", NULL,
83
"a", 2, 1, append, "append key def", "append key with data def",
84
"b", 0, 0, bstat, "bstat", "stat btree",
85
"c", 1, 1, cursor, "cursor word", "move cursor to word",
86
"delc", 0, 0, delcur, "delcur", "delete key the cursor references",
87
"dele", 1, 1, delete, "delete word", "delete word",
88
"d", 0, 0, dump, "dump", "dump database",
89
"f", 0, 0, first, "first", "move cursor to first record",
90
"g", 1, 1, get, "get key", "locate key",
91
"h", 0, 0, help, "help", "print command summary",
92
"ia", 2, 1, iafter, "iafter key data", "insert data after key",
93
"ib", 2, 1, ibefore, "ibefore key data", "insert data before key",
94
"ic", 2, 1, icursor, "icursor key data", "replace cursor",
95
"in", 2, 1, insert, "insert key def", "insert key with data def",
96
"la", 0, 0, last, "last", "move cursor to last record",
97
"li", 1, 1, list, "list file", "list to a file",
98
"loa", 1, 0, load, "load file", NULL,
99
"loc", 1, 1, get, "get key", NULL,
100
"m", 0, 0, mstat, "mstat", "stat memory pool",
101
"n", 0, 0, next, "next", "move cursor forward one record",
102
"p", 0, 0, previous, "previous", "move cursor back one record",
103
"q", 0, 0, NULL, "quit", "quit",
104
"sh", 1, 0, show, "show page", "dump a page",
105
{ NULL },
106
};
107
108
int recno; /* use record numbers */
109
char *dict = "words"; /* default dictionary */
110
char *progname;
111
112
int
113
main(argc, argv)
114
int argc;
115
char **argv;
116
{
117
int c;
118
DB *db;
119
BTREEINFO b;
120
121
progname = *argv;
122
123
b.flags = 0;
124
b.cachesize = 0;
125
b.maxkeypage = 0;
126
b.minkeypage = 0;
127
b.psize = 0;
128
b.compare = NULL;
129
b.prefix = NULL;
130
b.lorder = 0;
131
132
while ((c = getopt(argc, argv, "bc:di:lp:ru")) != -1) {
133
switch (c) {
134
case 'b':
135
b.lorder = BIG_ENDIAN;
136
break;
137
case 'c':
138
b.cachesize = atoi(optarg);
139
break;
140
case 'd':
141
b.flags |= R_DUP;
142
break;
143
case 'i':
144
dict = optarg;
145
break;
146
case 'l':
147
b.lorder = LITTLE_ENDIAN;
148
break;
149
case 'p':
150
b.psize = atoi(optarg);
151
break;
152
case 'r':
153
recno = 1;
154
break;
155
case 'u':
156
b.flags = 0;
157
break;
158
default:
159
usage();
160
}
161
}
162
argc -= optind;
163
argv += optind;
164
165
if (recno)
166
db = dbopen(*argv == NULL ? NULL : *argv, O_RDWR,
167
0, DB_RECNO, NULL);
168
else
169
db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|O_RDWR,
170
0600, DB_BTREE, &b);
171
172
if (db == NULL) {
173
(void)fprintf(stderr, "dbopen: %s\n", strerror(errno));
174
exit(1);
175
}
176
globaldb = db;
177
user(db);
178
exit(0);
179
/* NOTREACHED */
180
}
181
182
void
183
user(db)
184
DB *db;
185
{
186
FILE *ifp;
187
int argc, i, last;
188
char *lbuf, *argv[4], buf[512];
189
190
if ((ifp = fopen("/dev/tty", "r")) == NULL) {
191
(void)fprintf(stderr,
192
"/dev/tty: %s\n", strerror(errno));
193
exit(1);
194
}
195
for (last = 0;;) {
196
(void)printf("> ");
197
(void)fflush(stdout);
198
if ((lbuf = fgets(&buf[0], 512, ifp)) == NULL)
199
break;
200
if (lbuf[0] == '\n') {
201
i = last;
202
goto uselast;
203
}
204
lbuf[strlen(lbuf) - 1] = '\0';
205
206
if (lbuf[0] == 'q')
207
break;
208
209
argc = parse(lbuf, &argv[0], 3);
210
if (argc == 0)
211
continue;
212
213
for (i = 0; commands[i].cmd != NULL; i++)
214
if (strncmp(commands[i].cmd, argv[0],
215
strlen(commands[i].cmd)) == 0)
216
break;
217
218
if (commands[i].cmd == NULL) {
219
(void)fprintf(stderr,
220
"%s: command unknown ('help' for help)\n", lbuf);
221
continue;
222
}
223
224
if (commands[i].nargs != argc - 1) {
225
(void)fprintf(stderr, "usage: %s\n", commands[i].usage);
226
continue;
227
}
228
229
if (recno && commands[i].rconv) {
230
static recno_t nlong;
231
nlong = atoi(argv[1]);
232
argv[1] = (char *)&nlong;
233
}
234
uselast: last = i;
235
(*commands[i].func)(db, argv);
236
}
237
if ((db->sync)(db) == RET_ERROR)
238
perror("dbsync");
239
else if ((db->close)(db) == RET_ERROR)
240
perror("dbclose");
241
}
242
243
int
244
parse(lbuf, argv, maxargc)
245
char *lbuf, **argv;
246
int maxargc;
247
{
248
int argc = 0;
249
char *c;
250
251
c = lbuf;
252
while (isspace(*c))
253
c++;
254
while (*c != '\0' && argc < maxargc) {
255
*argv++ = c;
256
argc++;
257
while (!isspace(*c) && *c != '\0') {
258
c++;
259
}
260
while (isspace(*c))
261
*c++ = '\0';
262
}
263
return (argc);
264
}
265
266
void
267
append(db, argv)
268
DB *db;
269
char **argv;
270
{
271
DBT key, data;
272
int status;
273
274
if (!recno) {
275
(void)fprintf(stderr,
276
"append only available for recno db's.\n");
277
return;
278
}
279
key.data = argv[1];
280
key.size = sizeof(recno_t);
281
data.data = argv[2];
282
data.size = strlen(data.data);
283
status = (db->put)(db, &key, &data, R_APPEND);
284
switch (status) {
285
case RET_ERROR:
286
perror("append/put");
287
break;
288
case RET_SPECIAL:
289
(void)printf("%s (duplicate key)\n", argv[1]);
290
break;
291
case RET_SUCCESS:
292
break;
293
}
294
}
295
296
void
297
cursor(db, argv)
298
DB *db;
299
char **argv;
300
{
301
DBT data, key;
302
int status;
303
304
key.data = argv[1];
305
if (recno)
306
key.size = sizeof(recno_t);
307
else
308
key.size = strlen(argv[1]) + 1;
309
status = (*db->seq)(db, &key, &data, R_CURSOR);
310
switch (status) {
311
case RET_ERROR:
312
perror("cursor/seq");
313
break;
314
case RET_SPECIAL:
315
(void)printf("key not found\n");
316
break;
317
case RET_SUCCESS:
318
keydata(&key, &data);
319
break;
320
}
321
}
322
323
void
324
delcur(db, argv)
325
DB *db;
326
char **argv;
327
{
328
int status;
329
330
status = (*db->del)(db, NULL, R_CURSOR);
331
332
if (status == RET_ERROR)
333
perror("delcur/del");
334
}
335
336
void
337
delete(db, argv)
338
DB *db;
339
char **argv;
340
{
341
DBT key;
342
int status;
343
344
key.data = argv[1];
345
if (recno)
346
key.size = sizeof(recno_t);
347
else
348
key.size = strlen(argv[1]) + 1;
349
350
status = (*db->del)(db, &key, 0);
351
switch (status) {
352
case RET_ERROR:
353
perror("delete/del");
354
break;
355
case RET_SPECIAL:
356
(void)printf("key not found\n");
357
break;
358
case RET_SUCCESS:
359
break;
360
}
361
}
362
363
void
364
dump(db, argv)
365
DB *db;
366
char **argv;
367
{
368
__bt_dump(db);
369
}
370
371
void
372
first(db, argv)
373
DB *db;
374
char **argv;
375
{
376
DBT data, key;
377
int status;
378
379
status = (*db->seq)(db, &key, &data, R_FIRST);
380
381
switch (status) {
382
case RET_ERROR:
383
perror("first/seq");
384
break;
385
case RET_SPECIAL:
386
(void)printf("no more keys\n");
387
break;
388
case RET_SUCCESS:
389
keydata(&key, &data);
390
break;
391
}
392
}
393
394
void
395
get(db, argv)
396
DB *db;
397
char **argv;
398
{
399
DBT data, key;
400
int status;
401
402
key.data = argv[1];
403
if (recno)
404
key.size = sizeof(recno_t);
405
else
406
key.size = strlen(argv[1]) + 1;
407
408
status = (*db->get)(db, &key, &data, 0);
409
410
switch (status) {
411
case RET_ERROR:
412
perror("get/get");
413
break;
414
case RET_SPECIAL:
415
(void)printf("key not found\n");
416
break;
417
case RET_SUCCESS:
418
keydata(&key, &data);
419
break;
420
}
421
}
422
423
void
424
help(db, argv)
425
DB *db;
426
char **argv;
427
{
428
int i;
429
430
for (i = 0; commands[i].cmd; i++)
431
if (commands[i].descrip)
432
(void)printf("%s: %s\n",
433
commands[i].usage, commands[i].descrip);
434
}
435
436
void
437
iafter(db, argv)
438
DB *db;
439
char **argv;
440
{
441
DBT key, data;
442
int status;
443
444
if (!recno) {
445
(void)fprintf(stderr,
446
"iafter only available for recno db's.\n");
447
return;
448
}
449
key.data = argv[1];
450
key.size = sizeof(recno_t);
451
data.data = argv[2];
452
data.size = strlen(data.data);
453
status = (db->put)(db, &key, &data, R_IAFTER);
454
switch (status) {
455
case RET_ERROR:
456
perror("iafter/put");
457
break;
458
case RET_SPECIAL:
459
(void)printf("%s (duplicate key)\n", argv[1]);
460
break;
461
case RET_SUCCESS:
462
break;
463
}
464
}
465
466
void
467
ibefore(db, argv)
468
DB *db;
469
char **argv;
470
{
471
DBT key, data;
472
int status;
473
474
if (!recno) {
475
(void)fprintf(stderr,
476
"ibefore only available for recno db's.\n");
477
return;
478
}
479
key.data = argv[1];
480
key.size = sizeof(recno_t);
481
data.data = argv[2];
482
data.size = strlen(data.data);
483
status = (db->put)(db, &key, &data, R_IBEFORE);
484
switch (status) {
485
case RET_ERROR:
486
perror("ibefore/put");
487
break;
488
case RET_SPECIAL:
489
(void)printf("%s (duplicate key)\n", argv[1]);
490
break;
491
case RET_SUCCESS:
492
break;
493
}
494
}
495
496
void
497
icursor(db, argv)
498
DB *db;
499
char **argv;
500
{
501
int status;
502
DBT data, key;
503
504
key.data = argv[1];
505
if (recno)
506
key.size = sizeof(recno_t);
507
else
508
key.size = strlen(argv[1]) + 1;
509
data.data = argv[2];
510
data.size = strlen(argv[2]) + 1;
511
512
status = (*db->put)(db, &key, &data, R_CURSOR);
513
switch (status) {
514
case RET_ERROR:
515
perror("icursor/put");
516
break;
517
case RET_SPECIAL:
518
(void)printf("%s (duplicate key)\n", argv[1]);
519
break;
520
case RET_SUCCESS:
521
break;
522
}
523
}
524
525
void
526
insert(db, argv)
527
DB *db;
528
char **argv;
529
{
530
int status;
531
DBT data, key;
532
533
key.data = argv[1];
534
if (recno)
535
key.size = sizeof(recno_t);
536
else
537
key.size = strlen(argv[1]) + 1;
538
data.data = argv[2];
539
data.size = strlen(argv[2]) + 1;
540
541
status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
542
switch (status) {
543
case RET_ERROR:
544
perror("insert/put");
545
break;
546
case RET_SPECIAL:
547
(void)printf("%s (duplicate key)\n", argv[1]);
548
break;
549
case RET_SUCCESS:
550
break;
551
}
552
}
553
554
void
555
last(db, argv)
556
DB *db;
557
char **argv;
558
{
559
DBT data, key;
560
int status;
561
562
status = (*db->seq)(db, &key, &data, R_LAST);
563
564
switch (status) {
565
case RET_ERROR:
566
perror("last/seq");
567
break;
568
case RET_SPECIAL:
569
(void)printf("no more keys\n");
570
break;
571
case RET_SUCCESS:
572
keydata(&key, &data);
573
break;
574
}
575
}
576
577
void
578
list(db, argv)
579
DB *db;
580
char **argv;
581
{
582
DBT data, key;
583
FILE *fp;
584
int status;
585
586
if ((fp = fopen(argv[1], "w")) == NULL) {
587
(void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
588
return;
589
}
590
status = (*db->seq)(db, &key, &data, R_FIRST);
591
while (status == RET_SUCCESS) {
592
(void)fprintf(fp, "%s\n", key.data);
593
status = (*db->seq)(db, &key, &data, R_NEXT);
594
}
595
if (status == RET_ERROR)
596
perror("list/seq");
597
}
598
599
DB *BUGdb;
600
void
601
load(db, argv)
602
DB *db;
603
char **argv;
604
{
605
char *p, *t;
606
FILE *fp;
607
DBT data, key;
608
recno_t cnt;
609
size_t len;
610
int status;
611
char *lp, buf[16 * 1024];
612
613
BUGdb = db;
614
if ((fp = fopen(argv[1], "r")) == NULL) {
615
(void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
616
return;
617
}
618
(void)printf("loading %s...\n", argv[1]);
619
620
for (cnt = 1; (lp = fgetline(fp, &len)) != NULL; ++cnt) {
621
if (recno) {
622
key.data = &cnt;
623
key.size = sizeof(recno_t);
624
data.data = lp;
625
data.size = len + 1;
626
} else {
627
key.data = lp;
628
key.size = len + 1;
629
for (p = lp + len - 1, t = buf; p >= lp; *t++ = *p--);
630
*t = '\0';
631
data.data = buf;
632
data.size = len + 1;
633
}
634
635
status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
636
switch (status) {
637
case RET_ERROR:
638
perror("load/put");
639
exit(1);
640
case RET_SPECIAL:
641
if (recno)
642
(void)fprintf(stderr,
643
"duplicate: %ld {%s}\n", cnt, data.data);
644
else
645
(void)fprintf(stderr,
646
"duplicate: %ld {%s}\n", cnt, key.data);
647
exit(1);
648
case RET_SUCCESS:
649
break;
650
}
651
}
652
(void)fclose(fp);
653
}
654
655
void
656
next(db, argv)
657
DB *db;
658
char **argv;
659
{
660
DBT data, key;
661
int status;
662
663
status = (*db->seq)(db, &key, &data, R_NEXT);
664
665
switch (status) {
666
case RET_ERROR:
667
perror("next/seq");
668
break;
669
case RET_SPECIAL:
670
(void)printf("no more keys\n");
671
break;
672
case RET_SUCCESS:
673
keydata(&key, &data);
674
break;
675
}
676
}
677
678
void
679
previous(db, argv)
680
DB *db;
681
char **argv;
682
{
683
DBT data, key;
684
int status;
685
686
status = (*db->seq)(db, &key, &data, R_PREV);
687
688
switch (status) {
689
case RET_ERROR:
690
perror("previous/seq");
691
break;
692
case RET_SPECIAL:
693
(void)printf("no more keys\n");
694
break;
695
case RET_SUCCESS:
696
keydata(&key, &data);
697
break;
698
}
699
}
700
701
void
702
show(db, argv)
703
DB *db;
704
char **argv;
705
{
706
BTREE *t;
707
PAGE *h;
708
pgno_t pg;
709
710
pg = atoi(argv[1]);
711
t = db->internal;
712
if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) {
713
(void)printf("getpage of %ld failed\n", pg);
714
return;
715
}
716
if (pg == 0)
717
__bt_dmpage(h);
718
else
719
__bt_dpage(h);
720
mpool_put(t->bt_mp, h, 0);
721
}
722
723
void
724
bstat(db, argv)
725
DB *db;
726
char **argv;
727
{
728
(void)printf("BTREE\n");
729
__bt_stat(db);
730
}
731
732
void
733
mstat(db, argv)
734
DB *db;
735
char **argv;
736
{
737
(void)printf("MPOOL\n");
738
mpool_stat(((BTREE *)db->internal)->bt_mp);
739
}
740
741
void
742
keydata(key, data)
743
DBT *key, *data;
744
{
745
if (!recno && key->size > 0)
746
(void)printf("%s/", key->data);
747
if (data->size > 0)
748
(void)printf("%s", data->data);
749
(void)printf("\n");
750
}
751
752
void
753
usage()
754
{
755
(void)fprintf(stderr,
756
"usage: %s [-bdlu] [-c cache] [-i file] [-p page] [file]\n",
757
progname);
758
exit (1);
759
}
760
761