Path: blob/main/lib/libc/db/test/btree.tests/main.c
39583 views
/*-1* SPDX-License-Identifier: BSD-3-Clause2*3* Copyright (c) 1990, 19934* The Regents of the University of California. All rights reserved.5*6* This code is derived from software contributed to Berkeley by7* Mike Olson.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17* 3. Neither the name of the University nor the names of its contributors18* may be used to endorse or promote products derived from this software19* without specific prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*/3334#include <sys/param.h>35#include <fcntl.h>36#include <db.h>37#include <errno.h>38#include <stdio.h>39#include <ctype.h>40#include <stdlib.h>41#include <string.h>42#include "btree.h"4344typedef struct cmd_table {45char *cmd;46int nargs;47int rconv;48void (*func)(DB *, char **);49char *usage, *descrip;50} cmd_table;5152int stopstop;53DB *globaldb;5455void append(DB *, char **);56void bstat(DB *, char **);57void cursor(DB *, char **);58void delcur(DB *, char **);59void delete(DB *, char **);60void dump(DB *, char **);61void first(DB *, char **);62void get(DB *, char **);63void help(DB *, char **);64void iafter(DB *, char **);65void ibefore(DB *, char **);66void icursor(DB *, char **);67void insert(DB *, char **);68void keydata(DBT *, DBT *);69void last(DB *, char **);70void list(DB *, char **);71void load(DB *, char **);72void mstat(DB *, char **);73void next(DB *, char **);74int parse(char *, char **, int);75void previous(DB *, char **);76void show(DB *, char **);77void usage(void);78void user(DB *);7980cmd_table commands[] = {81"?", 0, 0, help, "help", NULL,82"a", 2, 1, append, "append key def", "append key with data def",83"b", 0, 0, bstat, "bstat", "stat btree",84"c", 1, 1, cursor, "cursor word", "move cursor to word",85"delc", 0, 0, delcur, "delcur", "delete key the cursor references",86"dele", 1, 1, delete, "delete word", "delete word",87"d", 0, 0, dump, "dump", "dump database",88"f", 0, 0, first, "first", "move cursor to first record",89"g", 1, 1, get, "get key", "locate key",90"h", 0, 0, help, "help", "print command summary",91"ia", 2, 1, iafter, "iafter key data", "insert data after key",92"ib", 2, 1, ibefore, "ibefore key data", "insert data before key",93"ic", 2, 1, icursor, "icursor key data", "replace cursor",94"in", 2, 1, insert, "insert key def", "insert key with data def",95"la", 0, 0, last, "last", "move cursor to last record",96"li", 1, 1, list, "list file", "list to a file",97"loa", 1, 0, load, "load file", NULL,98"loc", 1, 1, get, "get key", NULL,99"m", 0, 0, mstat, "mstat", "stat memory pool",100"n", 0, 0, next, "next", "move cursor forward one record",101"p", 0, 0, previous, "previous", "move cursor back one record",102"q", 0, 0, NULL, "quit", "quit",103"sh", 1, 0, show, "show page", "dump a page",104{ NULL },105};106107int recno; /* use record numbers */108char *dict = "words"; /* default dictionary */109char *progname;110111int112main(argc, argv)113int argc;114char **argv;115{116int c;117DB *db;118BTREEINFO b;119120progname = *argv;121122b.flags = 0;123b.cachesize = 0;124b.maxkeypage = 0;125b.minkeypage = 0;126b.psize = 0;127b.compare = NULL;128b.prefix = NULL;129b.lorder = 0;130131while ((c = getopt(argc, argv, "bc:di:lp:ru")) != -1) {132switch (c) {133case 'b':134b.lorder = BIG_ENDIAN;135break;136case 'c':137b.cachesize = atoi(optarg);138break;139case 'd':140b.flags |= R_DUP;141break;142case 'i':143dict = optarg;144break;145case 'l':146b.lorder = LITTLE_ENDIAN;147break;148case 'p':149b.psize = atoi(optarg);150break;151case 'r':152recno = 1;153break;154case 'u':155b.flags = 0;156break;157default:158usage();159}160}161argc -= optind;162argv += optind;163164if (recno)165db = dbopen(*argv == NULL ? NULL : *argv, O_RDWR,1660, DB_RECNO, NULL);167else168db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|O_RDWR,1690600, DB_BTREE, &b);170171if (db == NULL) {172(void)fprintf(stderr, "dbopen: %s\n", strerror(errno));173exit(1);174}175globaldb = db;176user(db);177exit(0);178/* NOTREACHED */179}180181void182user(db)183DB *db;184{185FILE *ifp;186int argc, i, last;187char *lbuf, *argv[4], buf[512];188189if ((ifp = fopen("/dev/tty", "r")) == NULL) {190(void)fprintf(stderr,191"/dev/tty: %s\n", strerror(errno));192exit(1);193}194for (last = 0;;) {195(void)printf("> ");196(void)fflush(stdout);197if ((lbuf = fgets(&buf[0], 512, ifp)) == NULL)198break;199if (lbuf[0] == '\n') {200i = last;201goto uselast;202}203lbuf[strlen(lbuf) - 1] = '\0';204205if (lbuf[0] == 'q')206break;207208argc = parse(lbuf, &argv[0], 3);209if (argc == 0)210continue;211212for (i = 0; commands[i].cmd != NULL; i++)213if (strncmp(commands[i].cmd, argv[0],214strlen(commands[i].cmd)) == 0)215break;216217if (commands[i].cmd == NULL) {218(void)fprintf(stderr,219"%s: command unknown ('help' for help)\n", lbuf);220continue;221}222223if (commands[i].nargs != argc - 1) {224(void)fprintf(stderr, "usage: %s\n", commands[i].usage);225continue;226}227228if (recno && commands[i].rconv) {229static recno_t nlong;230nlong = atoi(argv[1]);231argv[1] = (char *)&nlong;232}233uselast: last = i;234(*commands[i].func)(db, argv);235}236if ((db->sync)(db) == RET_ERROR)237perror("dbsync");238else if ((db->close)(db) == RET_ERROR)239perror("dbclose");240}241242int243parse(lbuf, argv, maxargc)244char *lbuf, **argv;245int maxargc;246{247int argc = 0;248char *c;249250c = lbuf;251while (isspace(*c))252c++;253while (*c != '\0' && argc < maxargc) {254*argv++ = c;255argc++;256while (!isspace(*c) && *c != '\0') {257c++;258}259while (isspace(*c))260*c++ = '\0';261}262return (argc);263}264265void266append(db, argv)267DB *db;268char **argv;269{270DBT key, data;271int status;272273if (!recno) {274(void)fprintf(stderr,275"append only available for recno db's.\n");276return;277}278key.data = argv[1];279key.size = sizeof(recno_t);280data.data = argv[2];281data.size = strlen(data.data);282status = (db->put)(db, &key, &data, R_APPEND);283switch (status) {284case RET_ERROR:285perror("append/put");286break;287case RET_SPECIAL:288(void)printf("%s (duplicate key)\n", argv[1]);289break;290case RET_SUCCESS:291break;292}293}294295void296cursor(db, argv)297DB *db;298char **argv;299{300DBT data, key;301int status;302303key.data = argv[1];304if (recno)305key.size = sizeof(recno_t);306else307key.size = strlen(argv[1]) + 1;308status = (*db->seq)(db, &key, &data, R_CURSOR);309switch (status) {310case RET_ERROR:311perror("cursor/seq");312break;313case RET_SPECIAL:314(void)printf("key not found\n");315break;316case RET_SUCCESS:317keydata(&key, &data);318break;319}320}321322void323delcur(db, argv)324DB *db;325char **argv;326{327int status;328329status = (*db->del)(db, NULL, R_CURSOR);330331if (status == RET_ERROR)332perror("delcur/del");333}334335void336delete(db, argv)337DB *db;338char **argv;339{340DBT key;341int status;342343key.data = argv[1];344if (recno)345key.size = sizeof(recno_t);346else347key.size = strlen(argv[1]) + 1;348349status = (*db->del)(db, &key, 0);350switch (status) {351case RET_ERROR:352perror("delete/del");353break;354case RET_SPECIAL:355(void)printf("key not found\n");356break;357case RET_SUCCESS:358break;359}360}361362void363dump(db, argv)364DB *db;365char **argv;366{367__bt_dump(db);368}369370void371first(db, argv)372DB *db;373char **argv;374{375DBT data, key;376int status;377378status = (*db->seq)(db, &key, &data, R_FIRST);379380switch (status) {381case RET_ERROR:382perror("first/seq");383break;384case RET_SPECIAL:385(void)printf("no more keys\n");386break;387case RET_SUCCESS:388keydata(&key, &data);389break;390}391}392393void394get(db, argv)395DB *db;396char **argv;397{398DBT data, key;399int status;400401key.data = argv[1];402if (recno)403key.size = sizeof(recno_t);404else405key.size = strlen(argv[1]) + 1;406407status = (*db->get)(db, &key, &data, 0);408409switch (status) {410case RET_ERROR:411perror("get/get");412break;413case RET_SPECIAL:414(void)printf("key not found\n");415break;416case RET_SUCCESS:417keydata(&key, &data);418break;419}420}421422void423help(db, argv)424DB *db;425char **argv;426{427int i;428429for (i = 0; commands[i].cmd; i++)430if (commands[i].descrip)431(void)printf("%s: %s\n",432commands[i].usage, commands[i].descrip);433}434435void436iafter(db, argv)437DB *db;438char **argv;439{440DBT key, data;441int status;442443if (!recno) {444(void)fprintf(stderr,445"iafter only available for recno db's.\n");446return;447}448key.data = argv[1];449key.size = sizeof(recno_t);450data.data = argv[2];451data.size = strlen(data.data);452status = (db->put)(db, &key, &data, R_IAFTER);453switch (status) {454case RET_ERROR:455perror("iafter/put");456break;457case RET_SPECIAL:458(void)printf("%s (duplicate key)\n", argv[1]);459break;460case RET_SUCCESS:461break;462}463}464465void466ibefore(db, argv)467DB *db;468char **argv;469{470DBT key, data;471int status;472473if (!recno) {474(void)fprintf(stderr,475"ibefore only available for recno db's.\n");476return;477}478key.data = argv[1];479key.size = sizeof(recno_t);480data.data = argv[2];481data.size = strlen(data.data);482status = (db->put)(db, &key, &data, R_IBEFORE);483switch (status) {484case RET_ERROR:485perror("ibefore/put");486break;487case RET_SPECIAL:488(void)printf("%s (duplicate key)\n", argv[1]);489break;490case RET_SUCCESS:491break;492}493}494495void496icursor(db, argv)497DB *db;498char **argv;499{500int status;501DBT data, key;502503key.data = argv[1];504if (recno)505key.size = sizeof(recno_t);506else507key.size = strlen(argv[1]) + 1;508data.data = argv[2];509data.size = strlen(argv[2]) + 1;510511status = (*db->put)(db, &key, &data, R_CURSOR);512switch (status) {513case RET_ERROR:514perror("icursor/put");515break;516case RET_SPECIAL:517(void)printf("%s (duplicate key)\n", argv[1]);518break;519case RET_SUCCESS:520break;521}522}523524void525insert(db, argv)526DB *db;527char **argv;528{529int status;530DBT data, key;531532key.data = argv[1];533if (recno)534key.size = sizeof(recno_t);535else536key.size = strlen(argv[1]) + 1;537data.data = argv[2];538data.size = strlen(argv[2]) + 1;539540status = (*db->put)(db, &key, &data, R_NOOVERWRITE);541switch (status) {542case RET_ERROR:543perror("insert/put");544break;545case RET_SPECIAL:546(void)printf("%s (duplicate key)\n", argv[1]);547break;548case RET_SUCCESS:549break;550}551}552553void554last(db, argv)555DB *db;556char **argv;557{558DBT data, key;559int status;560561status = (*db->seq)(db, &key, &data, R_LAST);562563switch (status) {564case RET_ERROR:565perror("last/seq");566break;567case RET_SPECIAL:568(void)printf("no more keys\n");569break;570case RET_SUCCESS:571keydata(&key, &data);572break;573}574}575576void577list(db, argv)578DB *db;579char **argv;580{581DBT data, key;582FILE *fp;583int status;584585if ((fp = fopen(argv[1], "w")) == NULL) {586(void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));587return;588}589status = (*db->seq)(db, &key, &data, R_FIRST);590while (status == RET_SUCCESS) {591(void)fprintf(fp, "%s\n", key.data);592status = (*db->seq)(db, &key, &data, R_NEXT);593}594if (status == RET_ERROR)595perror("list/seq");596}597598DB *BUGdb;599void600load(db, argv)601DB *db;602char **argv;603{604char *p, *t;605FILE *fp;606DBT data, key;607recno_t cnt;608size_t len;609int status;610char *lp, buf[16 * 1024];611612BUGdb = db;613if ((fp = fopen(argv[1], "r")) == NULL) {614(void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));615return;616}617(void)printf("loading %s...\n", argv[1]);618619for (cnt = 1; (lp = fgetline(fp, &len)) != NULL; ++cnt) {620if (recno) {621key.data = &cnt;622key.size = sizeof(recno_t);623data.data = lp;624data.size = len + 1;625} else {626key.data = lp;627key.size = len + 1;628for (p = lp + len - 1, t = buf; p >= lp; *t++ = *p--);629*t = '\0';630data.data = buf;631data.size = len + 1;632}633634status = (*db->put)(db, &key, &data, R_NOOVERWRITE);635switch (status) {636case RET_ERROR:637perror("load/put");638exit(1);639case RET_SPECIAL:640if (recno)641(void)fprintf(stderr,642"duplicate: %ld {%s}\n", cnt, data.data);643else644(void)fprintf(stderr,645"duplicate: %ld {%s}\n", cnt, key.data);646exit(1);647case RET_SUCCESS:648break;649}650}651(void)fclose(fp);652}653654void655next(db, argv)656DB *db;657char **argv;658{659DBT data, key;660int status;661662status = (*db->seq)(db, &key, &data, R_NEXT);663664switch (status) {665case RET_ERROR:666perror("next/seq");667break;668case RET_SPECIAL:669(void)printf("no more keys\n");670break;671case RET_SUCCESS:672keydata(&key, &data);673break;674}675}676677void678previous(db, argv)679DB *db;680char **argv;681{682DBT data, key;683int status;684685status = (*db->seq)(db, &key, &data, R_PREV);686687switch (status) {688case RET_ERROR:689perror("previous/seq");690break;691case RET_SPECIAL:692(void)printf("no more keys\n");693break;694case RET_SUCCESS:695keydata(&key, &data);696break;697}698}699700void701show(db, argv)702DB *db;703char **argv;704{705BTREE *t;706PAGE *h;707pgno_t pg;708709pg = atoi(argv[1]);710t = db->internal;711if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) {712(void)printf("getpage of %ld failed\n", pg);713return;714}715if (pg == 0)716__bt_dmpage(h);717else718__bt_dpage(h);719mpool_put(t->bt_mp, h, 0);720}721722void723bstat(db, argv)724DB *db;725char **argv;726{727(void)printf("BTREE\n");728__bt_stat(db);729}730731void732mstat(db, argv)733DB *db;734char **argv;735{736(void)printf("MPOOL\n");737mpool_stat(((BTREE *)db->internal)->bt_mp);738}739740void741keydata(key, data)742DBT *key, *data;743{744if (!recno && key->size > 0)745(void)printf("%s/", key->data);746if (data->size > 0)747(void)printf("%s", data->data);748(void)printf("\n");749}750751void752usage()753{754(void)fprintf(stderr,755"usage: %s [-bdlu] [-c cache] [-i file] [-p page] [file]\n",756progname);757exit (1);758}759760761