New cache subsystem
[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         );
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, quietout=0;
108
109         opentlog(TL_OPEN_STDERR,TL_DEBUG, NULL);
110
111         memset(&db, 0, sizeof(TBTree));
112
113         while((i=getopt(argn,argv,"qVbS:Dc:hrkf:i:v:d:s:L")) != EOF) {
114                 switch(i) {
115                         case 'q':
116                                 quietout=1;
117                                 break;
118                         case 'V':
119                                 verbose=1;
120                                 break;
121                         case 'r':
122                                 db.readonly=1;
123                                 break;
124                         case 'f':
125                                 file = strdup(optarg);
126                                 break;
127                         case 'k':
128                                 db.keylen=sizeof(int);
129                                 break;
130                         case 'i':
131                                 key = strdup(optarg);
132                                 mode=MODE_INSERT;
133                                 break;
134                         case 'd':
135                                 key = strdup(optarg);
136                                 mode=MODE_DELETE;
137                                 break;
138                         case 's':
139                                 key = strdup(optarg);
140                                 mode=MODE_SEARCH;
141                                 break;
142                         case 'v':
143                                 val = strdup(optarg); 
144                                 mode=MODE_INSERT;
145                                 break;
146                         case 'c':
147                                 db.npage = atoi(optarg);
148                                 break;
149                         case 'S':
150                                 db.strategy = atoi(optarg);
151                                 if ( db.strategy > 2 )
152                                         db.strategy = TBT_STATEGY_RIGHTFILL;
153                                 break;
154                         case 'D':
155                                 mode=MODE_DUMP;
156                                 break;
157                         case 'L':
158                                 mode=MODE_LIST;
159                                 break;
160                         case 'b':
161                                 mode=MODE_BULK;
162                                 break;
163                         case 'h':
164                         default:
165                                 usage();
166                                 break;
167                 }
168         }
169         
170         db.cmpkey = (db.keylen) ? cmpINT : cmpSTR;
171                         
172         if ( (rc=TBTOpen(&db, file))!= TBT_OK )
173                 exit(1);
174
175         if ( mode==MODE_INSERT && key && val ) {
176                 fillKV(db.keylen, key, val);
177                 rc = TBTInsert(&db, &K, &V);
178         } else if ( mode==MODE_SEARCH && key ) {
179                 fillKV(db.keylen, key, NULL);
180                 rc = TBTFind(&db, &K, &V);
181                 if ( rc == TBT_OK ) {
182                         if ( V.value ) {
183                                 int i;
184                                 printf("Value: '");
185                                 for(i=0;i<V.length;i++)
186                                         fputc(V.value[i], stdout);
187                                 fputc('\'', stdout);
188                                 fputc('\n', stdout);
189                         } else {
190                                 printf("Not found\n");
191                         }
192                 }
193         } else if ( mode==MODE_DELETE && key ) {
194                 fillKV(db.keylen, key, NULL);
195                 rc = TBTDelete(&db, &K);
196         } else if ( mode==MODE_DUMP ) {
197                 dumpTree(&db, TBTPAGEROOT, 0);
198         } else if ( mode==MODE_LIST ) {
199                 TBTIterator     iterator;
200                 if ( (rc=TBTInitIterator(&db, &iterator))==TBT_OK ) {
201                         TBTValue key, value;
202                         while(1) { 
203                                 rc = TBTIterate(&db, &iterator, &key, &value); 
204                                 if ( rc == TBT_OK && key.value ) {
205                                         fputs("I\t", stdout);
206                                         if ( db.keylen )
207                                                 printf("%d", *(int*)(key.value));
208                                         else 
209                                                 printLSTR(key.length, key.value);
210                                         fputc('\t', stdout);
211                                         printLSTR(value.length, value.value);
212                                         fputc('\n', stdout);
213                                 } else {
214                                         break;
215                                 }
216                         }
217
218                 }
219                 TBTFreeIterator(&db, &iterator);
220         } else if ( mode==MODE_BULK ) {
221                 char buf[TBTREEPAGESIZE];
222                 int tmp;
223                 TBTValue key, value;
224                 char *ptr ;
225
226                 rc=TBT_OK;
227                 while( rc==TBT_OK && fgets(buf, TBTREEPAGESIZE-1, stdin) ) {
228                         if ( *buf == 'I' ) {
229                                 ptr=buf+1;
230                                 while( *ptr && isspace(*ptr) ) ptr++;
231                                 key.value=ptr;
232                                 while( *ptr && !isspace(*ptr) ) ptr++;
233                                 key.length = ptr-key.value;
234                                 while( *ptr && isspace(*ptr) ) ptr++;
235                                 value.value=ptr;
236                                 while( *ptr && !isspace(*ptr) ) ptr++;
237                                 value.length = ptr-value.value;
238                                 if ( db.keylen ) {
239                                         tmp=atoi(key.value);
240                                         key.length = db.keylen;
241                                         key.value=(char*)&tmp;
242                                 }
243                                 rc=TBTInsert(&db, &key, &value);
244                         } else if ( *buf == 'D' || *buf == 'S' ) {
245                                 ptr=buf+1;
246                                 while( *ptr && isspace(*ptr) ) ptr++;
247                                 key.value=ptr;
248                                 while( *ptr && !isspace(*ptr) ) ptr++;
249                                 key.length = ptr-key.value;
250                                 if ( db.keylen ) {
251                                         tmp=atoi(key.value);
252                                         key.length = db.keylen;
253                                         key.value=(char*)&tmp;
254                                 }
255                                 if ( *buf == 'D' ) {
256                                         rc=TBTDelete(&db, &key);
257                                 } else if ( (rc=TBTFind(&db, &key, &value))==TBT_OK && quietout==0) {
258                                         if ( db.keylen )
259                                                 printf("%d", *(int*)(key.value));
260                                         else 
261                                                 printLSTR(key.length, key.value);
262                                         if ( value.value ) {
263                                                 fputc('\t', stdout);
264                                                 printLSTR(value.length, value.value);
265                                         }
266                                         fputc('\n', stdout);
267                                 }
268                                 
269                         }
270                 }  
271         } else {
272                 TBTClose(&db);
273                 usage();
274         }
275
276         if ( rc ) printf("Method returns %d\n", rc);
277
278         TBTSync(&db);
279         if ( verbose ) {
280                 printf("Page read: %d (include cache hits %d)\n", db.pageread, db.cachehits);
281                 printf("Page write: %d\n", db.pagewrite);
282         }
283
284         TBTClose(&db);
285
286         return 0;
287 }
288
289         
290