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