style: compare return value of getopt() against -1 rather than EOF
[dragonfly.git] / lib / libc / db / test / btree.tests / main.c
blob3f2dfb8e476da72b6139c125b1220c14393de3dc
1 /*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Mike Olson.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
32 * @(#)main.c 8.1 (Berkeley) 6/4/93
33 * $DragonFly: src/lib/libc/db/test/btree.tests/main.c,v 1.8 2008/07/10 18:29:51 swildner Exp $
36 #include <sys/param.h>
37 #include <fcntl.h>
38 #include <db.h>
39 #include <errno.h>
40 #include <stdio.h>
41 #include <ctype.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include "btree.h"
46 typedef struct cmd_table {
47 char *cmd;
48 int nargs;
49 int rconv;
50 void (*func) (DB *, char **);
51 char *usage, *descrip;
52 } cmd_table;
54 int stopstop;
55 DB *globaldb;
57 void append (DB *, char **);
58 void bstat (DB *, char **);
59 void cursor (DB *, char **);
60 void delcur (DB *, char **);
61 void delete (DB *, char **);
62 void dump (DB *, char **);
63 void first (DB *, char **);
64 void get (DB *, char **);
65 void help (DB *, char **);
66 void iafter (DB *, char **);
67 void ibefore (DB *, char **);
68 void icursor (DB *, char **);
69 void insert (DB *, char **);
70 void keydata (DBT *, DBT *);
71 void last (DB *, char **);
72 void list (DB *, char **);
73 void load (DB *, char **);
74 void mstat (DB *, char **);
75 void next (DB *, char **);
76 int parse (char *, char **, int);
77 void previous (DB *, char **);
78 void show (DB *, char **);
79 void usage (void);
80 void user (DB *);
82 cmd_table commands[] = {
83 "?", 0, 0, help, "help", NULL,
84 "a", 2, 1, append, "append key def", "append key with data def",
85 "b", 0, 0, bstat, "bstat", "stat btree",
86 "c", 1, 1, cursor, "cursor word", "move cursor to word",
87 "delc", 0, 0, delcur, "delcur", "delete key the cursor references",
88 "dele", 1, 1, delete, "delete word", "delete word",
89 "d", 0, 0, dump, "dump", "dump database",
90 "f", 0, 0, first, "first", "move cursor to first record",
91 "g", 1, 1, get, "get key", "locate key",
92 "h", 0, 0, help, "help", "print command summary",
93 "ia", 2, 1, iafter, "iafter key data", "insert data after key",
94 "ib", 2, 1, ibefore, "ibefore key data", "insert data before key",
95 "ic", 2, 1, icursor, "icursor key data", "replace cursor",
96 "in", 2, 1, insert, "insert key def", "insert key with data def",
97 "la", 0, 0, last, "last", "move cursor to last record",
98 "li", 1, 1, list, "list file", "list to a file",
99 "loa", 1, 0, load, "load file", NULL,
100 "loc", 1, 1, get, "get key", NULL,
101 "m", 0, 0, mstat, "mstat", "stat memory pool",
102 "n", 0, 0, next, "next", "move cursor forward one record",
103 "p", 0, 0, previous, "previous", "move cursor back one record",
104 "q", 0, 0, NULL, "quit", "quit",
105 "sh", 1, 0, show, "show page", "dump a page",
106 { NULL },
109 int recno; /* use record numbers */
110 char *dict = "words"; /* default dictionary */
111 char *progname;
114 main(int argc, char **argv)
116 int c;
117 DB *db;
118 BTREEINFO b;
120 progname = *argv;
122 b.flags = 0;
123 b.cachesize = 0;
124 b.maxkeypage = 0;
125 b.minkeypage = 0;
126 b.psize = 0;
127 b.compare = NULL;
128 b.prefix = NULL;
129 b.lorder = 0;
131 while ((c = getopt(argc, argv, "bc:di:lp:ru")) != -1) {
132 switch (c) {
133 case 'b':
134 b.lorder = BIG_ENDIAN;
135 break;
136 case 'c':
137 b.cachesize = atoi(optarg);
138 break;
139 case 'd':
140 b.flags |= R_DUP;
141 break;
142 case 'i':
143 dict = optarg;
144 break;
145 case 'l':
146 b.lorder = LITTLE_ENDIAN;
147 break;
148 case 'p':
149 b.psize = atoi(optarg);
150 break;
151 case 'r':
152 recno = 1;
153 break;
154 case 'u':
155 b.flags = 0;
156 break;
157 default:
158 usage();
161 argc -= optind;
162 argv += optind;
164 if (recno)
165 db = dbopen(*argv == NULL ? NULL : *argv, O_RDWR,
166 0, DB_RECNO, NULL);
167 else
168 db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|O_RDWR,
169 0600, DB_BTREE, &b);
171 if (db == NULL) {
172 fprintf(stderr, "dbopen: %s\n", strerror(errno));
173 exit(1);
175 globaldb = db;
176 user(db);
177 exit(0);
178 /* NOTREACHED */
181 void
182 user(DB *db)
184 FILE *ifp;
185 int argc, i, last;
186 char *lbuf, *argv[4], buf[512];
188 if ((ifp = fopen("/dev/tty", "r")) == NULL) {
189 fprintf(stderr,
190 "/dev/tty: %s\n", strerror(errno));
191 exit(1);
193 for (last = 0;;) {
194 printf("> ");
195 fflush(stdout);
196 if ((lbuf = fgets(&buf[0], 512, ifp)) == NULL)
197 break;
198 if (lbuf[0] == '\n') {
199 i = last;
200 goto uselast;
202 lbuf[strlen(lbuf) - 1] = '\0';
204 if (lbuf[0] == 'q')
205 break;
207 argc = parse(lbuf, &argv[0], 3);
208 if (argc == 0)
209 continue;
211 for (i = 0; commands[i].cmd != NULL; i++)
212 if (strncmp(commands[i].cmd, argv[0],
213 strlen(commands[i].cmd)) == 0)
214 break;
216 if (commands[i].cmd == NULL) {
217 fprintf(stderr,
218 "%s: command unknown ('help' for help)\n", lbuf);
219 continue;
222 if (commands[i].nargs != argc - 1) {
223 fprintf(stderr, "usage: %s\n", commands[i].usage);
224 continue;
227 if (recno && commands[i].rconv) {
228 static recno_t nlong;
229 nlong = atoi(argv[1]);
230 argv[1] = (char *)&nlong;
232 uselast: last = i;
233 (*commands[i].func)(db, argv);
235 if ((db->sync)(db) == RET_ERROR)
236 perror("dbsync");
237 else if ((db->close)(db) == RET_ERROR)
238 perror("dbclose");
242 parse(char *lbuf, char **argv, int maxargc)
244 int argc = 0;
245 char *c;
247 c = lbuf;
248 while (isspace(*c))
249 c++;
250 while (*c != '\0' && argc < maxargc) {
251 *argv++ = c;
252 argc++;
253 while (!isspace(*c) && *c != '\0') {
254 c++;
256 while (isspace(*c))
257 *c++ = '\0';
259 return (argc);
262 void
263 append(DB *db, char **argv)
265 DBT key, data;
266 int status;
268 if (!recno) {
269 fprintf(stderr,
270 "append only available for recno db's.\n");
271 return;
273 key.data = argv[1];
274 key.size = sizeof(recno_t);
275 data.data = argv[2];
276 data.size = strlen(data.data);
277 status = (db->put)(db, &key, &data, R_APPEND);
278 switch (status) {
279 case RET_ERROR:
280 perror("append/put");
281 break;
282 case RET_SPECIAL:
283 printf("%s (duplicate key)\n", argv[1]);
284 break;
285 case RET_SUCCESS:
286 break;
290 void
291 cursor(DB *db, char **argv)
293 DBT data, key;
294 int status;
296 key.data = argv[1];
297 if (recno)
298 key.size = sizeof(recno_t);
299 else
300 key.size = strlen(argv[1]) + 1;
301 status = (*db->seq)(db, &key, &data, R_CURSOR);
302 switch (status) {
303 case RET_ERROR:
304 perror("cursor/seq");
305 break;
306 case RET_SPECIAL:
307 printf("key not found\n");
308 break;
309 case RET_SUCCESS:
310 keydata(&key, &data);
311 break;
315 void
316 delcur(DB *db, char **argv)
318 int status;
320 status = (*db->del)(db, NULL, R_CURSOR);
322 if (status == RET_ERROR)
323 perror("delcur/del");
326 void
327 delete(DB *db, char **argv)
329 DBT key;
330 int status;
332 key.data = argv[1];
333 if (recno)
334 key.size = sizeof(recno_t);
335 else
336 key.size = strlen(argv[1]) + 1;
338 status = (*db->del)(db, &key, 0);
339 switch (status) {
340 case RET_ERROR:
341 perror("delete/del");
342 break;
343 case RET_SPECIAL:
344 printf("key not found\n");
345 break;
346 case RET_SUCCESS:
347 break;
351 void
352 dump(DB *db, char **argv)
354 __bt_dump(db);
357 void
358 first(DB *db, char **argv)
360 DBT data, key;
361 int status;
363 status = (*db->seq)(db, &key, &data, R_FIRST);
365 switch (status) {
366 case RET_ERROR:
367 perror("first/seq");
368 break;
369 case RET_SPECIAL:
370 printf("no more keys\n");
371 break;
372 case RET_SUCCESS:
373 keydata(&key, &data);
374 break;
378 void
379 get(DB *db, char **argv)
381 DBT data, key;
382 int status;
384 key.data = argv[1];
385 if (recno)
386 key.size = sizeof(recno_t);
387 else
388 key.size = strlen(argv[1]) + 1;
390 status = (*db->get)(db, &key, &data, 0);
392 switch (status) {
393 case RET_ERROR:
394 perror("get/get");
395 break;
396 case RET_SPECIAL:
397 printf("key not found\n");
398 break;
399 case RET_SUCCESS:
400 keydata(&key, &data);
401 break;
405 void
406 help(DB *db, char **argv)
408 int i;
410 for (i = 0; commands[i].cmd; i++)
411 if (commands[i].descrip)
412 printf("%s: %s\n",
413 commands[i].usage, commands[i].descrip);
416 void
417 iafter(DB *db, char **argv)
419 DBT key, data;
420 int status;
422 if (!recno) {
423 fprintf(stderr,
424 "iafter only available for recno db's.\n");
425 return;
427 key.data = argv[1];
428 key.size = sizeof(recno_t);
429 data.data = argv[2];
430 data.size = strlen(data.data);
431 status = (db->put)(db, &key, &data, R_IAFTER);
432 switch (status) {
433 case RET_ERROR:
434 perror("iafter/put");
435 break;
436 case RET_SPECIAL:
437 printf("%s (duplicate key)\n", argv[1]);
438 break;
439 case RET_SUCCESS:
440 break;
444 void
445 ibefore(DB *db, char **argv)
447 DBT key, data;
448 int status;
450 if (!recno) {
451 fprintf(stderr,
452 "ibefore only available for recno db's.\n");
453 return;
455 key.data = argv[1];
456 key.size = sizeof(recno_t);
457 data.data = argv[2];
458 data.size = strlen(data.data);
459 status = (db->put)(db, &key, &data, R_IBEFORE);
460 switch (status) {
461 case RET_ERROR:
462 perror("ibefore/put");
463 break;
464 case RET_SPECIAL:
465 printf("%s (duplicate key)\n", argv[1]);
466 break;
467 case RET_SUCCESS:
468 break;
472 void
473 icursor(DB *db, char **argv)
475 int status;
476 DBT data, key;
478 key.data = argv[1];
479 if (recno)
480 key.size = sizeof(recno_t);
481 else
482 key.size = strlen(argv[1]) + 1;
483 data.data = argv[2];
484 data.size = strlen(argv[2]) + 1;
486 status = (*db->put)(db, &key, &data, R_CURSOR);
487 switch (status) {
488 case RET_ERROR:
489 perror("icursor/put");
490 break;
491 case RET_SPECIAL:
492 printf("%s (duplicate key)\n", argv[1]);
493 break;
494 case RET_SUCCESS:
495 break;
499 void
500 insert(DB *db, char **argv)
502 int status;
503 DBT data, key;
505 key.data = argv[1];
506 if (recno)
507 key.size = sizeof(recno_t);
508 else
509 key.size = strlen(argv[1]) + 1;
510 data.data = argv[2];
511 data.size = strlen(argv[2]) + 1;
513 status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
514 switch (status) {
515 case RET_ERROR:
516 perror("insert/put");
517 break;
518 case RET_SPECIAL:
519 printf("%s (duplicate key)\n", argv[1]);
520 break;
521 case RET_SUCCESS:
522 break;
526 void
527 last(DB *db, char **argv)
529 DBT data, key;
530 int status;
532 status = (*db->seq)(db, &key, &data, R_LAST);
534 switch (status) {
535 case RET_ERROR:
536 perror("last/seq");
537 break;
538 case RET_SPECIAL:
539 printf("no more keys\n");
540 break;
541 case RET_SUCCESS:
542 keydata(&key, &data);
543 break;
547 void
548 list(DB *db, char **argv)
550 DBT data, key;
551 FILE *fp;
552 int status;
554 if ((fp = fopen(argv[1], "w")) == NULL) {
555 fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
556 return;
558 status = (*db->seq)(db, &key, &data, R_FIRST);
559 while (status == RET_SUCCESS) {
560 fprintf(fp, "%s\n", key.data);
561 status = (*db->seq)(db, &key, &data, R_NEXT);
563 if (status == RET_ERROR)
564 perror("list/seq");
567 DB *BUGdb;
568 void
569 load(DB *db, char **argv)
571 char *p, *t;
572 FILE *fp;
573 DBT data, key;
574 recno_t cnt;
575 size_t len;
576 int status;
577 char *lp, buf[16 * 1024];
579 BUGdb = db;
580 if ((fp = fopen(argv[1], "r")) == NULL) {
581 fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
582 return;
584 printf("loading %s...\n", argv[1]);
586 for (cnt = 1; (lp = fgetline(fp, &len)) != NULL; ++cnt) {
587 if (recno) {
588 key.data = &cnt;
589 key.size = sizeof(recno_t);
590 data.data = lp;
591 data.size = len + 1;
592 } else {
593 key.data = lp;
594 key.size = len + 1;
595 for (p = lp + len - 1, t = buf; p >= lp; *t++ = *p--);
596 *t = '\0';
597 data.data = buf;
598 data.size = len + 1;
601 status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
602 switch (status) {
603 case RET_ERROR:
604 perror("load/put");
605 exit(1);
606 case RET_SPECIAL:
607 if (recno)
608 fprintf(stderr,
609 "duplicate: %ld {%s}\n", cnt, data.data);
610 else
611 fprintf(stderr,
612 "duplicate: %ld {%s}\n", cnt, key.data);
613 exit(1);
614 case RET_SUCCESS:
615 break;
618 fclose(fp);
621 void
622 next(DB *db, char **argv)
624 DBT data, key;
625 int status;
627 status = (*db->seq)(db, &key, &data, R_NEXT);
629 switch (status) {
630 case RET_ERROR:
631 perror("next/seq");
632 break;
633 case RET_SPECIAL:
634 printf("no more keys\n");
635 break;
636 case RET_SUCCESS:
637 keydata(&key, &data);
638 break;
642 void
643 previous(DB *db, char **argv)
645 DBT data, key;
646 int status;
648 status = (*db->seq)(db, &key, &data, R_PREV);
650 switch (status) {
651 case RET_ERROR:
652 perror("previous/seq");
653 break;
654 case RET_SPECIAL:
655 printf("no more keys\n");
656 break;
657 case RET_SUCCESS:
658 keydata(&key, &data);
659 break;
663 void
664 show(DB *db, char **argv)
666 BTREE *t;
667 PAGE *h;
668 pgno_t pg;
670 pg = atoi(argv[1]);
671 t = db->internal;
672 if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) {
673 printf("getpage of %ld failed\n", pg);
674 return;
676 if (pg == 0)
677 __bt_dmpage(h);
678 else
679 __bt_dpage(h);
680 mpool_put(t->bt_mp, h, 0);
683 void
684 bstat(DB *db, char **argv)
686 printf("BTREE\n");
687 __bt_stat(db);
690 void
691 mstat(DB *db, char **argv)
693 printf("MPOOL\n");
694 mpool_stat(((BTREE *)db->internal)->bt_mp);
697 void
698 keydata(DBT *key, DBT *data)
700 if (!recno && key->size > 0)
701 printf("%s/", key->data);
702 if (data->size > 0)
703 printf("%s", data->data);
704 printf("\n");
707 void
708 usage(void)
710 fprintf(stderr,
711 "usage: %s [-bdlu] [-c cache] [-i file] [-p page] [file]\n",
712 progname);
713 exit (1);