add verbose flag to tbtreetest, modify btree test.
[tedtools.git] / tbtreetest.c
1 /*
2  * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *      notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *      notice, this list of conditions and the following disclaimer in the
12  *      documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the author nor the names of any co-contributors
14  *      may be used to endorse or promote products derived from this software
15  *      without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <ctype.h>
35
36 #include "tlog.h"
37 #include "tmalloc.h"
38 #include "tbtree.h"
39
40 static void
41 usage() {
42         puts(
43         "Usage:\n"
44         "tbtreetest [ -c CACHESIZE ] [-r] [-k] [-f FILE] [-D | -L | -b | -i KEY -v VALUE [ -S strategynumber ] | -d KEY | -s KEY ] [-V]\n"
45         );
46         exit(1);
47 }
48
49 extern char *optarg;
50 extern int opterr;
51
52 #define MODE_SEARCH     1
53 #define MODE_INSERT     2
54 #define MODE_DELETE     3
55 #define MODE_DUMP       4
56 #define MODE_LIST       5
57 #define MODE_BULK       6
58
59
60 static TBTValue K,V;
61 static int Ki;
62
63 static void
64 fillKV(int keylen, char *key, char *value) {
65         if ( keylen ) {
66                 Ki=atoi(key);
67                 K.value=(char*)&Ki;
68         } else {
69                 K.length = strlen(key);
70                 K.value = key;
71         }
72         if( value ) {
73                 V.length = strlen(value);
74                 V.value = value;
75         }
76 }
77
78 static int
79 cmpINT(const TBTValue *a, const TBTValue *b) {
80         if ( *(int*)(a->value) == *(int*)(b->value) ) return 0;
81         return ( *(int*)(a->value) > *(int*)(b->value) ) ? 1 : -1;
82
83
84 static int
85 cmpSTR(const TBTValue *a, const TBTValue *b) {
86         int rc = strncmp( a->value, b->value, (a->length > b->length) ?  b->length : a->length);
87         if ( rc ) return rc;
88         if ( a->length ==  b->length ) return 0;
89         return ( a->length > b->length ) ? 1 : -1;
90 }
91
92 static void
93 printLSTR(u_int32_t len, char *ptr) {
94         while(len>0) {
95                 putchar(*ptr);
96                 ptr++; len--;
97         }
98 }
99
100 int
101 main(int argn, char *argv[]) {
102         TBTree db;
103         int i;
104         int rc=0;
105         char *file="BTREE";
106         char *key=NULL, *val=NULL;
107         int mode=0, verbose=0;
108
109         opentlog(TL_OPEN_STDERR,TL_DEBUG, NULL);
110
111         memset(&db, 0, sizeof(TBTree));
112
113         while((i=getopt(argn,argv,"VbS:Dc:hrkf:i:v:d:s:L")) != EOF) {
114                 switch(i) {
115                         case 'V':
116                                 verbose=1;
117                                 break;
118                         case 'r':
119                                 db.readonly=1;
120                                 break;
121                         case 'f':
122                                 file = strdup(optarg);
123                                 break;
124                         case 'k':
125                                 db.keylen=sizeof(int);
126                                 break;
127                         case 'i':
128                                 key = strdup(optarg);
129                                 mode=MODE_INSERT;
130                                 break;
131                         case 'd':
132                                 key = strdup(optarg);
133                                 mode=MODE_DELETE;
134                                 break;
135                         case 's':
136                                 key = strdup(optarg);
137                                 mode=MODE_SEARCH;
138                                 break;
139                         case 'v':
140                                 val = strdup(optarg); 
141                                 mode=MODE_INSERT;
142                                 break;
143                         case 'c':
144                                 db.npage = atoi(optarg);
145                                 break;
146                         case 'S':
147                                 db.strategy = atoi(optarg);
148                                 if ( db.strategy > 2 )
149                                         db.strategy = TBT_STATEGY_RIGHTFILL;
150                                 break;
151                         case 'D':
152                                 mode=MODE_DUMP;
153                                 break;
154                         case 'L':
155                                 mode=MODE_LIST;
156                                 break;
157                         case 'b':
158                                 mode=MODE_BULK;
159                                 break;
160                         case 'h':
161                         default:
162                                 usage();
163                                 break;
164                 }
165         }
166         
167         db.cmpkey = (db.keylen) ? cmpINT : cmpSTR;
168                         
169         if ( (rc=TBTOpen(&db, file))!= TBT_OK )
170                 exit(1);
171
172         if ( mode==MODE_INSERT && key && val ) {
173                 fillKV(db.keylen, key, val);
174                 rc = TBTInsert(&db, &K, &V);
175         } else if ( mode==MODE_SEARCH && key ) {
176                 fillKV(db.keylen, key, NULL);
177                 rc = TBTFind(&db, &K, &V);
178                 if ( rc == TBT_OK ) {
179                         if ( V.value ) {
180                                 int i;
181                                 printf("Value: '");
182                                 for(i=0;i<V.length;i++)
183                                         fputc(V.value[i], stdout);
184                                 fputc('\'', stdout);
185                                 fputc('\n', stdout);
186                         } else {
187                                 printf("Not found\n");
188                         }
189                 }
190         } else if ( mode==MODE_DELETE && key ) {
191                 fillKV(db.keylen, key, NULL);
192                 rc = TBTDelete(&db, &K);
193         } else if ( mode==MODE_DUMP ) {
194                 dumpTree(&db, TBTPAGEROOT, 0);
195         } else if ( mode==MODE_LIST ) {
196                 TBTIterator     iterator;
197                 if ( (rc=TBTInitIterator(&db, &iterator))==TBT_OK ) {
198                         TBTValue key, value;
199                         while(1) { 
200                                 rc = TBTIterate(&db, &iterator, &key, &value); 
201                                 if ( rc == TBT_OK && key.value ) {
202                                         fputs("I\t", stdout);
203                                         if ( db.keylen )
204                                                 printf("%d", *(int*)(key.value));
205                                         else 
206                                                 printLSTR(key.length, key.value);
207                                         fputc('\t', stdout);
208                                         printLSTR(value.length, value.value);
209                                         fputc('\n', stdout);
210                                 } else {
211                                         break;
212                                 }
213                         }
214
215                 }
216                 TBTFreeIterator(&db, &iterator);
217         } else if ( mode==MODE_BULK ) {
218                 char buf[TBTREEPAGESIZE];
219                 int tmp;
220                 TBTValue key, value;
221                 char *ptr ;
222
223                 rc=TBT_OK;
224                 while( rc==TBT_OK && fgets(buf, TBTREEPAGESIZE-1, stdin) ) {
225                         if ( *buf == 'I' ) {
226                                 ptr=buf+1;
227                                 while( *ptr && isspace(*ptr) ) ptr++;
228                                 key.value=ptr;
229                                 while( *ptr && !isspace(*ptr) ) ptr++;
230                                 key.length = ptr-key.value;
231                                 while( *ptr && isspace(*ptr) ) ptr++;
232                                 value.value=ptr;
233                                 while( *ptr && !isspace(*ptr) ) ptr++;
234                                 value.length = ptr-value.value;
235                                 if ( db.keylen ) {
236                                         tmp=atoi(key.value);
237                                         key.length = db.keylen;
238                                         key.value=(char*)&tmp;
239                                 }
240                                 rc=TBTInsert(&db, &key, &value);
241                         } else if ( *buf == 'D' || *buf == 'S' ) {
242                                 ptr=buf+1;
243                                 while( *ptr && isspace(*ptr) ) ptr++;
244                                 key.value=ptr;
245                                 while( *ptr && !isspace(*ptr) ) ptr++;
246                                 key.length = ptr-key.value;
247                                 if ( db.keylen ) {
248                                         tmp=atoi(key.value);
249                                         key.length = db.keylen;
250                                         key.value=(char*)&tmp;
251                                 }
252                                 if ( *buf == 'D' ) {
253                                         rc=TBTDelete(&db, &key);
254                                 } else if ( (rc=TBTFind(&db, &key, &value))==TBT_OK ) {
255                                         if ( db.keylen )
256                                                 printf("%d", *(int*)(key.value));
257                                         else 
258                                                 printLSTR(key.length, key.value);
259                                         if ( value.value ) {
260                                                 fputc('\t', stdout);
261                                                 printLSTR(value.length, value.value);
262                                         }
263                                         fputc('\n', stdout);
264                                 }
265                                 
266                         }
267                 }  
268         } else {
269                 TBTClose(&db);
270                 usage();
271         }
272
273         if ( rc ) printf("Method returns %d\n", rc);
274
275         TBTSync(&db);
276         if ( verbose ) {
277                 printf("Page read: %d (include cache hits %d)\n", db.pageread, db.cachehits);
278                 printf("Page write: %d\n", db.pagewrite);
279         }
280
281         TBTClose(&db);
282
283         return 0;
284 }
285
286         
287