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