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