1/* 2 * $Id: b_curwalk.c,v 1.12 2008/02/05 20:43:41 bostic Exp $ 3 */ 4#include "bench.h" 5 6static int b_curwalk_usage(void); 7 8int 9b_curwalk(int argc, char *argv[]) 10{ 11 extern char *optarg; 12 extern int optind, __db_getopt_reset; 13 DB *dbp; 14 DBTYPE type; 15 DBC *dbc; 16 DBT key, data; 17 db_recno_t recno; 18 u_int32_t cachesize, pagesize, walkflags; 19 int ch, i, count, dupcount, j; 20 int prev, ret, skipdupwalk, sorted, walkcount; 21 char *ts, dbuf[32], kbuf[32]; 22 23 type = DB_BTREE; 24 cachesize = 10 * MEGABYTE; 25 pagesize = 16 * 1024; 26 count = 100000; 27 dupcount = prev = skipdupwalk = sorted = 0; 28 walkcount = 1000; 29 ts = "Btree"; 30 __db_getopt_reset = 1; 31 while ((ch = getopt(argc, argv, "C:c:d:P:pSst:w:")) != EOF) 32 switch (ch) { 33 case 'C': 34 cachesize = (u_int32_t)atoi(optarg); 35 break; 36 case 'c': 37 count = atoi(optarg); 38 break; 39 case 'd': 40 dupcount = atoi(optarg); 41 break; 42 case 'P': 43 pagesize = (u_int32_t)atoi(optarg); 44 break; 45 case 'p': 46 prev = 1; 47 break; 48 case 'S': 49 skipdupwalk = 1; 50 break; 51 case 's': 52 sorted = 1; 53 break; 54 case 't': 55 switch (optarg[0]) { 56 case 'B': case 'b': 57 ts = "Btree"; 58 type = DB_BTREE; 59 break; 60 case 'H': case 'h': 61 if (b_util_have_hash()) 62 return (0); 63 ts = "Hash"; 64 type = DB_HASH; 65 break; 66 case 'Q': case 'q': 67 if (b_util_have_queue()) 68 return (0); 69 ts = "Queue"; 70 type = DB_QUEUE; 71 break; 72 case 'R': case 'r': 73 ts = "Recno"; 74 type = DB_RECNO; 75 break; 76 default: 77 return (b_curwalk_usage()); 78 } 79 break; 80 case 'w': 81 walkcount = atoi(optarg); 82 break; 83 case '?': 84 default: 85 return (b_curwalk_usage()); 86 } 87 argc -= optind; 88 argv += optind; 89 if (argc != 0) 90 return (b_curwalk_usage()); 91 92 /* 93 * Queue and Recno don't support duplicates. 94 */ 95 if (dupcount != 0 && (type == DB_QUEUE || type == DB_RECNO)) { 96 fprintf(stderr, 97 "b_curwalk: Queue and Recno don't support duplicates\n"); 98 return (b_curwalk_usage()); 99 } 100 101#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0 102#define DB_PREV_NODUP 0 103 /* 104 * DB_PREV_NODUP wasn't available until after 3.0.55. 105 * 106 * For some reason, testing sorted duplicates doesn't work either. 107 * I don't really care about 3.0.55 any more, just ignore it. 108 */ 109 return (0); 110#endif 111 /* Create the database. */ 112 DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0); 113 DB_BENCH_ASSERT(dbp->set_cachesize(dbp, 0, cachesize, 0) == 0); 114 DB_BENCH_ASSERT(dbp->set_pagesize(dbp, pagesize) == 0); 115 dbp->set_errfile(dbp, stderr); 116 117 /* Set record length for Queue. */ 118 if (type == DB_QUEUE) 119 DB_BENCH_ASSERT(dbp->set_re_len(dbp, 20) == 0); 120 121 /* Set duplicates flag. */ 122 if (dupcount != 0) 123 DB_BENCH_ASSERT( 124 dbp->set_flags(dbp, sorted ? DB_DUPSORT : DB_DUP) == 0); 125 126#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1 127 DB_BENCH_ASSERT(dbp->open( 128 dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0); 129#else 130 DB_BENCH_ASSERT(dbp->open( 131 dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0); 132#endif 133 134 /* Initialize the data. */ 135 memset(&key, 0, sizeof(key)); 136 memset(&data, 0, sizeof(data)); 137 138 /* Insert count in-order key/data pairs. */ 139 data.data = dbuf; 140 data.size = 20; 141 if (type == DB_BTREE || type == DB_HASH) { 142 key.size = 10; 143 key.data = kbuf; 144 for (i = 0; i < count; ++i) { 145 (void)snprintf(kbuf, sizeof(kbuf), "%010d", i); 146 for (j = 0; j <= dupcount; ++j) { 147 (void)snprintf(dbuf, sizeof(dbuf), "%020d", j); 148 DB_BENCH_ASSERT( 149 dbp->put(dbp, NULL, &key, &data, 0) == 0); 150 } 151 } 152 } else { 153 key.data = &recno; 154 key.size = sizeof(recno); 155 for (i = 0, recno = 1; i < count; ++i, ++recno) 156 DB_BENCH_ASSERT( 157 dbp->put(dbp, NULL, &key, &data, 0) == 0); 158 } 159 160 walkflags = prev ? 161 (skipdupwalk ? DB_PREV_NODUP : DB_PREV) : 162 (skipdupwalk ? DB_NEXT_NODUP : DB_NEXT); 163 164 /* Walk the cursor through the tree N times. */ 165 TIMER_START; 166 for (i = 0; i < walkcount; ++i) { 167 DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0); 168 while ((ret = dbc->c_get(dbc, &key, &data, walkflags)) == 0) 169 ; 170 DB_BENCH_ASSERT(ret == DB_NOTFOUND); 171 DB_BENCH_ASSERT(dbc->c_close(dbc) == 0); 172 } 173 TIMER_STOP; 174 175 printf("# %d %s %s cursor of %d 10/20 byte key/data items", 176 walkcount, ts, prev ? 177 (skipdupwalk ? "DB_PREV_NODUP" : "DB_PREV") : 178 (skipdupwalk ? "DB_NEXT_NODUP" : "DB_NEXT"), 179 count); 180 if (dupcount != 0) 181 printf(" with %d dups", dupcount); 182 printf("\n"); 183 184 /* 185 * An "operation" is traversal of a single key/data pair -- not a 186 * return of the key/data pair, since some versions of this test 187 * skip duplicate key/data pairs. 188 * 189 * Use a "double" so we don't overflow. 190 */ 191 TIMER_DISPLAY((double)count * walkcount); 192 193 DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0); 194 195 return (EXIT_SUCCESS); 196} 197 198static int 199b_curwalk_usage() 200{ 201 (void)fprintf(stderr, "%s\n\t%s\n", 202 "usage: b_curwalk [-pSs] [-C cachesz]", 203 "[-c cnt] [-d dupcnt] [-P pagesz] [-t type] [-w walkcnt]"); 204 return (EXIT_FAILURE); 205} 206