bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr-util / test / testdbm.c
1 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
2  * applicable.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /* This file came from the SDBM package (written by oz@nexus.yorku.ca).
17  * That package was under public domain. This file has been ported to
18  * APR, updated to ANSI C and other, newer idioms, and added to the Apache
19  * codebase under the above copyright and license.
20  */
21
22 /*
23  * testdbm: Simple APR dbm tester.
24  * Automatic test case: ./testdbm auto foo
25  *  - Attempts to store and fetch values from the DBM.
26  *
27  * Run the program for more help.
28  */
29
30 #include "apr.h"
31 #include "apr_general.h"
32 #include "apr_pools.h"
33 #include "apr_errno.h"
34 #include "apr_getopt.h"
35 #include "apr_time.h"
36 #define APR_WANT_STRFUNC
37 #include "apr_want.h"
38
39 #if APR_HAVE_STDIO_H
40 #include <stdio.h>
41 #endif
42 #if APR_HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45 #include <stdlib.h>     /* for atexit(), malloc() */
46 #include <string.h>
47
48 #include "apr_dbm.h"
49
50 static const char *progname;
51 static int rflag;
52
53 #define DERROR      0
54 #define DLOOK       1
55
56 #define DDELETE     3
57 #define DCAT        4
58 #define DBUILD      5
59 #define DPRESS      6
60 #define DCREAT      7
61 #define DNAME       8
62 #define DTRUNC      9
63 #define DAUTO      10
64
65 #define LINEMAX     8192
66
67 typedef struct {
68     const char *sname;
69     int scode;
70     int flags;
71 } cmd;
72
73 static const cmd cmds[] = {
74
75     { "fetch",   DLOOK,   APR_DBM_READONLY },
76     { "get",     DLOOK,   APR_DBM_READONLY },
77     { "look",    DLOOK,   APR_DBM_READONLY },
78     { "add",     DBUILD,  APR_DBM_READWRITE },
79     { "insert",  DBUILD,  APR_DBM_READWRITE },
80     { "store",   DBUILD,  APR_DBM_READWRITE },
81     { "delete",  DDELETE, APR_DBM_READWRITE },
82     { "remove",  DDELETE, APR_DBM_READWRITE },
83     { "dump",    DCAT,    APR_DBM_READONLY },
84     { "list",    DCAT,    APR_DBM_READONLY },
85     { "cat",     DCAT,    APR_DBM_READONLY },
86     { "build",   DBUILD,  APR_DBM_RWCREATE },    /** this one creates the DB */
87     { "creat",   DCREAT,  APR_DBM_RWCREATE },
88     { "trunc",   DTRUNC,  APR_DBM_RWTRUNC },
89     { "new",     DCREAT,  APR_DBM_RWCREATE },
90     { "names",   DNAME,   APR_DBM_READONLY },
91 #if 0
92     {"squash",   DPRESS,  APR_DBM_READWRITE, },
93     {"compact",  DPRESS,  APR_DBM_READWRITE, },
94     {"compress", DPRESS,  APR_DBM_READWRITE, },
95 #endif
96     { "auto",    DAUTO,   APR_DBM_RWCREATE },
97 };
98
99 #define CMD_SIZE (sizeof(cmds)/sizeof(cmd))
100
101 static void doit(const cmd *act, const char*type, const char *file, apr_pool_t *pool);
102 static const cmd *parse_command(const char *str);
103 static void prdatum(FILE *stream, apr_datum_t d);
104 static void oops(apr_dbm_t *dbm, apr_status_t rv, const char *s1,
105                  const char *s2);
106 static void show_usage(void);
107
108 int main(int argc, const char * const * argv)
109 {
110     apr_pool_t *pool;
111     const cmd *act;
112     apr_getopt_t *os;
113     char optch;
114     const char *optarg;
115     const char*dbtype;
116
117     (void) apr_initialize();
118     apr_pool_create(&pool, NULL);
119     atexit(apr_terminate);
120
121     (void) apr_getopt_init(&os, pool, argc, argv);
122
123     progname = argv[0];
124     dbtype = "default";
125
126     while (apr_getopt(os, "Rt:", &optch, &optarg) == APR_SUCCESS) {
127         switch (optch) {
128         case 'R':       /* raw processing  */
129             rflag++;
130             break;
131         case 't':
132             dbtype = optarg;
133             break;
134         default:
135             show_usage();
136             fputs("unknown option.",stderr);
137             exit(-1);
138             break;
139         }
140     }
141
142     if (argc <= os->ind) {
143         show_usage();
144         fputs("Note: If you have no clue what this program is, start with:\n", stderr);
145         fputs("      ./testdbm auto foo\n", stderr);
146         fputs("      where foo is the DBM prefix.\n", stderr);
147         exit(-2);
148     }
149
150     if ((act = parse_command(argv[os->ind])) == NULL) {
151         show_usage();
152         fprintf(stderr, "unrecognized command: %s\n", argv[os->ind]);
153         exit(-3);
154     }
155
156     if (++os->ind >= argc) {
157         show_usage();
158         fputs("please supply a DB file to use (may be created)\n", stderr);
159         exit(-4);
160     }
161
162     doit(act, dbtype, argv[os->ind], pool);
163
164     apr_pool_destroy(pool);
165
166     return 0;
167 }
168
169 static void doit(const cmd *act, const char*type, const char *file, 
170                  apr_pool_t *pool)
171 {
172     apr_status_t rv;
173     apr_datum_t key;
174     apr_datum_t val;
175     apr_dbm_t *db;
176     char *op;
177     int n;
178     char *line;
179     const char *use1;
180     const char *use2;
181 #ifdef TIME
182     long start;
183     extern long time();
184 #endif
185
186     rv = apr_dbm_open_ex(&db, type, file, act->flags, APR_OS_DEFAULT, pool);
187     if (rv != APR_SUCCESS)
188         oops(db, rv, "cannot open: %s", file);
189
190     line = (char *) apr_palloc(pool,LINEMAX);
191
192     switch (act->scode) {
193
194     case DLOOK:
195         while (fgets(line, LINEMAX, stdin) != NULL) {
196             n = strlen(line) - 1;
197             line[n] = 0;
198             if (n == 0)
199                 break;
200
201             key.dptr = line;
202             key.dsize = n;
203             rv = apr_dbm_fetch(db, key, &val);
204             if (rv == APR_SUCCESS) {
205                 prdatum(stdout, val);
206                 putchar('\n');
207                 continue;
208             }
209             prdatum(stderr, key);
210             fprintf(stderr, ": not found.\n");
211         }
212         break;
213
214     case DDELETE:
215         while (fgets(line, LINEMAX, stdin) != NULL) {
216             n = strlen(line) - 1;
217             line[n] = 0;
218             if (n == 0)
219                 break;
220
221             key.dptr = line;
222             key.dsize = n;
223             if (apr_dbm_delete(db, key) != APR_SUCCESS) {
224                 prdatum(stderr, key);
225                 fprintf(stderr, ": not found.\n");
226             }
227         }
228         break;
229     case DCAT:
230         rv = apr_dbm_firstkey(db, &key);
231         if (rv != APR_SUCCESS)
232             oops(db, rv, "could not fetch first key: %s", file);
233
234         while (key.dptr != NULL) {
235             prdatum(stdout, key);
236             putchar('\t');
237             rv = apr_dbm_fetch(db, key, &val);
238             if (rv != APR_SUCCESS)
239                 oops(db, rv, "apr_dbm_fetch", "failure");
240             prdatum(stdout, val);
241             putchar('\n');
242             rv = apr_dbm_nextkey(db, &key);
243             if (rv != APR_SUCCESS)
244                 oops(db, rv, "NextKey", "failure");
245         }
246         break;
247     case DBUILD:
248 #ifdef TIME
249         start = time(0);
250 #endif
251         while (fgets(line, LINEMAX, stdin) != NULL) {
252             n = strlen(line) - 1;
253             line[n] = 0;
254             if (n == 0)
255                 break;
256
257             key.dptr = line;
258             if ((op = strchr(line, '\t')) != 0) {
259                 key.dsize = op - line;
260                 *op++ = 0;
261                 val.dptr = op;
262                 val.dsize = line + n - op;
263             }
264             else
265                 oops(NULL, APR_EGENERAL, "bad input: %s", line);
266
267             rv = apr_dbm_store(db, key, val);
268             if (rv != APR_SUCCESS) {
269                 prdatum(stderr, key);
270                 fprintf(stderr, ": ");
271                 oops(db, rv, "store: %s", "failed");
272             }
273         }
274 #ifdef TIME
275         printf("done: %d seconds.\n", time(0) - start);
276 #endif
277         break;
278     case DPRESS:
279         break;
280     case DCREAT:
281         break;
282     case DTRUNC:
283         break;
284     case DNAME:
285         apr_dbm_get_usednames(pool, file, &use1, &use2);
286         fprintf(stderr, "%s %s\n", use1, use2);
287         break;
288     case DAUTO:
289         {
290             int i;
291             char *valdata = "0123456789";
292             fprintf(stderr, "Generating data: ");
293             for (i = 0; i < 10; i++) {
294                 int j;
295                 char c, keydata[10];
296                 for (j = 0, c = 'A' + (i % 16); j < 10; j++, c++) {
297                     keydata[j] = c;
298                 }
299                 key.dptr = keydata;
300                 key.dsize = 10;
301                 val.dptr = valdata;
302                 val.dsize = 10;
303                 rv = apr_dbm_store(db, key, val);
304                 if (rv != APR_SUCCESS) {
305                     prdatum(stderr, key);
306                     fprintf(stderr, ": ");
307                     oops(db, rv, "store: %s", "failed");
308                 }
309             }
310             fputs("OK\n", stderr);
311             fputs("Testing existence/retrieval: ", stderr);
312             for (i = 0; i < 10; i++) {
313                 int j;
314                 char c, keydata[10];
315                 for (j = 0, c = 'A' + (i % 16); j < 10; j++, c++) {
316                     keydata[j] = c;
317                 }
318                 key.dptr = keydata;
319                 key.dsize = 10;
320                 if (!apr_dbm_exists(db, key)) {
321                     prdatum(stderr, key);
322                     oops(db, 0, "exists: %s", "failed");
323                 }
324                 rv = apr_dbm_fetch(db, key, &val);
325                 if (rv != APR_SUCCESS || val.dsize != 10 ||
326                     (strncmp(val.dptr, valdata, 10) != 0) ) { 
327                     prdatum(stderr, key);
328                     fprintf(stderr, ": ");
329                     oops(db, rv, "fetch: %s", "failed");
330                 }
331             }
332             fputs("OK\n", stderr);
333         }
334         break;
335     }
336
337     apr_dbm_close(db);
338 }
339
340 static const cmd *parse_command(const char *str)
341 {
342     int i;
343
344     for (i = 0; i < CMD_SIZE; i++)
345         if (strcasecmp(cmds[i].sname, str) == 0)
346             return &cmds[i];
347
348     return NULL;
349 }
350
351 static void prdatum(FILE *stream, apr_datum_t d)
352 {
353     int c;
354     const char *p = d.dptr;
355     int n = d.dsize;
356
357     while (n--) {
358         c = *p++ & 0377;
359         if (c & 0200) {
360             fprintf(stream, "M-");
361             c &= 0177;
362         }
363         if (c == 0177 || c < ' ') 
364             fprintf(stream, "^%c", (c == 0177) ? '?' : c + '@');
365         else
366             putc(c, stream);
367     }
368 }
369
370 static void oops(apr_dbm_t * dbm, apr_status_t rv, const char *s1,
371                  const char *s2)
372 {
373     char errbuf[200];
374
375     if (progname) {
376         fprintf(stderr, "%s: ", progname);
377     }
378     fprintf(stderr, s1, s2);
379     fprintf(stderr, "\n");
380
381     if (rv != APR_SUCCESS) {
382         apr_strerror(rv, errbuf, sizeof(errbuf));
383         fprintf(stderr, "APR Error %d - %s\n", rv, errbuf);
384
385         if (dbm) {
386             apr_dbm_geterror(dbm, &rv, errbuf, sizeof(errbuf));
387             fprintf(stderr, "APR_DB Error %d - %s\n", rv, errbuf);
388         }
389     }
390     exit(1);
391 }
392
393 static void show_usage(void)
394 {
395     int i;
396
397     if (!progname) {
398         progname = "testdbm";
399     }
400
401     fprintf(stderr, "%s [-t DBM-type] [-R] [commands] dbm-file-path\n", 
402             progname);
403
404     fputs("Available DBM-types:", stderr);
405 #if APU_HAVE_GDBM
406     fputs(" GDBM", stderr);
407 #endif
408 #if APU_HAVE_NDBM
409     fputs(" NDBM", stderr);
410 #endif
411 #if APU_HAVE_SDBM
412     fputs(" SDBM", stderr);
413 #endif
414 #if APU_HAVE_DB
415     fputs(" DB", stderr);
416 #endif
417     fputs(" default\n", stderr);
418
419     fputs("Available commands:\n", stderr);
420     for (i = 0; i < CMD_SIZE; i++) {
421         fprintf(stderr, "%-8s%c", cmds[i].sname,
422                 ((i + 1) % 6 == 0) ? '\n' : ' ');
423     }
424     fputs("\n", stderr);
425 }