cb5456e87c4d4941ab1aedc3e170d7d2ec0959a7
[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] [-q]\n"
45         "\t-c CACHESIZE    - cache size in pages (default 0)\n"
46         "\t-r              - readonly mode\n"
47         "\t-k              - fixed size key (integer)\n"
48         "\t-f FILE         - db-file (default ./BTREE)");
49         puts(
50         "\t-D              - dump data base\n"
51         "\t-L              - list all pairs (in bulk format)\n"
52         "\t-b              - bulk operations from stdin in format (insert/delete/search):\n"
53         "\t                   I KEY VALUE\n"
54         "\t                   D KEY\n"
55         "\t                   S KEY\n"
56         "\t-i KEY -v VALUE - insert KEY/VALUE\n"
57         "\t-d KEY          - delete key\n"
58         "\t-s KEY          - search key\n"
59         "\t-V              - print page read/writes at the end\n"
60         "\t-q              - do not print results of searches\n"
61         );
62         exit(1);
63 }
64
65 extern char *optarg;
66 extern int opterr;
67
68 #define MODE_NO 0
69 #define MODE_SEARCH     1
70 #define MODE_INSERT     2
71 #define MODE_DELETE     3
72 #define MODE_DUMP       4
73 #define MODE_LIST       5
74 #define MODE_BULK       6
75
76
77 static TBTValue K,V;
78 static int Ki;
79
80 static void
81 fillKV(int keylen, char *key, char *value) {
82         if ( keylen ) {
83                 Ki=atoi(key);
84                 K.value=(char*)&Ki;
85         } else {
86                 K.length = strlen(key);
87                 K.value = key;
88         }
89         if( value ) {
90                 V.length = strlen(value);
91                 V.value = value;
92         }
93 }
94
95 static int
96 cmpINT(const TBTValue *a, const TBTValue *b) {
97         if ( *(int*)(a->value) == *(int*)(b->value) ) return 0;
98         return ( *(int*)(a->value) > *(int*)(b->value) ) ? 1 : -1;
99
100
101 static int
102 cmpSTR(const TBTValue *a, const TBTValue *b) {
103         int rc = strncmp( a->value, b->value, (a->length > b->length) ?  b->length : a->length);
104         if ( rc ) return rc;
105         if ( a->length ==  b->length ) return 0;
106         return ( a->length > b->length ) ? 1 : -1;
107 }
108
109 static void
110 printLSTR(u_int32_t len, char *ptr) {
111         while(len>0) {
112                 putchar(*ptr);
113                 ptr++; len--;
114         }
115 }
116
117 int
118 main(int argn, char *argv[]) {
119         TBTree db;
120         int i;
121         int rc=0;
122         char *file="BTREE";
123         char *key=NULL, *val=NULL;
124         int mode=MODE_NO, verbose=0, quietout=0;
125
126         opentlog(TL_OPEN_STDERR,TL_DEBUG, NULL);
127
128         memset(&db, 0, sizeof(TBTree));
129
130         while((i=getopt(argn,argv,"qVbS:Dc:hrkf:i:v:d:s:L")) != EOF) {
131                 switch(i) {
132                         case 'q':
133                                 quietout=1;
134                                 break;
135                         case 'V':
136                                 verbose=1;
137                                 break;
138                         case 'r':
139                                 db.readonly=1;
140                                 break;
141                         case 'f':
142                                 file = strdup(optarg);
143                                 break;
144                         case 'k':
145                                 db.keylen=sizeof(int);
146                                 break;
147                         case 'i':
148                                 key = strdup(optarg);
149                                 mode=MODE_INSERT;
150                                 break;
151                         case 'd':
152                                 key = strdup(optarg);
153                                 mode=MODE_DELETE;
154                                 break;
155                         case 's':
156                                 key = strdup(optarg);
157                                 mode=MODE_SEARCH;
158                                 break;
159                         case 'v':
160                                 val = strdup(optarg); 
161                                 mode=MODE_INSERT;
162                                 break;
163                         case 'c':
164                                 db.npage = atoi(optarg);
165                                 break;
166                         case 'S':
167                                 db.strategy = atoi(optarg);
168                                 if ( db.strategy > 2 )
169                                         db.strategy = TBT_STATEGY_RIGHTFILL;
170                                 break;
171                         case 'D':
172                                 mode=MODE_DUMP;
173                                 break;
174                         case 'L':
175                                 mode=MODE_LIST;
176                                 break;
177                         case 'b':
178                                 mode=MODE_BULK;
179                                 break;
180                         case 'h':
181                         default:
182                                 usage();
183                                 break;
184                 }
185         }
186         
187         if ( mode==MODE_NO )
188                 usage();
189                         
190         db.cmpkey = (db.keylen) ? cmpINT : cmpSTR;
191         
192         if ( (rc=TBTOpen(&db, file))!= TBT_OK )
193                 exit(1);
194
195         if ( mode==MODE_INSERT && key && val ) {
196                 fillKV(db.keylen, key, val);
197                 rc = TBTInsert(&db, &K, &V);
198         } else if ( mode==MODE_SEARCH && key ) {
199                 fillKV(db.keylen, key, NULL);
200                 rc = TBTFind(&db, &K, &V);
201                 if ( rc == TBT_OK ) {
202                         if ( V.value ) {
203                                 int i;
204                                 printf("Value: '");
205                                 for(i=0;i<V.length;i++)
206                                         fputc(V.value[i], stdout);
207                                 fputc('\'', stdout);
208                                 fputc('\n', stdout);
209                         } else {
210                                 printf("Not found\n");
211                         }
212                 }
213         } else if ( mode==MODE_DELETE && key ) {
214                 fillKV(db.keylen, key, NULL);
215                 rc = TBTDelete(&db, &K);
216         } else if ( mode==MODE_DUMP ) {
217                 dumpTree(&db, TBTPAGEROOT, 0);
218         } else if ( mode==MODE_LIST ) {
219                 TBTIterator     iterator;
220                 if ( (rc=TBTInitIterator(&db, &iterator))==TBT_OK ) {
221                         TBTValue key, value;
222                         while(1) { 
223                                 rc = TBTIterate(&db, &iterator, &key, &value); 
224                                 if ( rc == TBT_OK && key.value ) {
225                                         fputs("I\t", stdout);
226                                         if ( db.keylen )
227                                                 printf("%d", *(int*)(key.value));
228                                         else 
229                                                 printLSTR(key.length, key.value);
230                                         fputc('\t', stdout);
231                                         printLSTR(value.length, value.value);
232                                         fputc('\n', stdout);
233                                 } else {
234                                         break;
235                                 }
236                         }
237
238                 }
239                 TBTFreeIterator(&db, &iterator);
240         } else if ( mode==MODE_BULK ) {
241                 char buf[TBTREEPAGESIZE];
242                 int tmp;
243                 TBTValue key, value;
244                 char *ptr ;
245
246                 rc=TBT_OK;
247                 while( rc==TBT_OK && fgets(buf, TBTREEPAGESIZE-1, stdin) ) {
248                         if ( *buf == 'I' ) {
249                                 ptr=buf+1;
250                                 while( *ptr && isspace(*ptr) ) ptr++;
251                                 key.value=ptr;
252                                 while( *ptr && !isspace(*ptr) ) ptr++;
253                                 key.length = ptr-key.value;
254                                 while( *ptr && isspace(*ptr) ) ptr++;
255                                 value.value=ptr;
256                                 while( *ptr && !isspace(*ptr) ) ptr++;
257                                 value.length = ptr-value.value;
258                                 if ( db.keylen ) {
259                                         tmp=atoi(key.value);
260                                         key.length = db.keylen;
261                                         key.value=(char*)&tmp;
262                                 }
263                                 rc=TBTInsert(&db, &key, &value);
264                         } else if ( *buf == 'D' || *buf == 'S' ) {
265                                 ptr=buf+1;
266                                 while( *ptr && isspace(*ptr) ) ptr++;
267                                 key.value=ptr;
268                                 while( *ptr && !isspace(*ptr) ) ptr++;
269                                 key.length = ptr-key.value;
270                                 if ( db.keylen ) {
271                                         tmp=atoi(key.value);
272                                         key.length = db.keylen;
273                                         key.value=(char*)&tmp;
274                                 }
275                                 if ( *buf == 'D' ) {
276                                         rc=TBTDelete(&db, &key);
277                                 } else if ( (rc=TBTFind(&db, &key, &value))==TBT_OK && quietout==0) {
278                                         if ( db.keylen )
279                                                 printf("%d", *(int*)(key.value));
280                                         else 
281                                                 printLSTR(key.length, key.value);
282                                         if ( value.value ) {
283                                                 fputc('\t', stdout);
284                                                 printLSTR(value.length, value.value);
285                                         }
286                                         fputc('\n', stdout);
287                                 }
288                                 
289                         }
290                 }  
291         } else {
292                 TBTClose(&db);
293                 usage();
294         }
295
296         if ( rc ) printf("Method returns %d\n", rc);
297
298         TBTSync(&db);
299         if ( verbose ) {
300                 printf("Page read: %d (include cache hits %d)\n", db.pageread, db.cachehits);
301                 printf("Page write: %d\n", db.pagewrite);
302         }
303
304         TBTClose(&db);
305
306         return 0;
307 }
308
309         
310