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