00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <sys/types.h>
00034 #include <sys/time.h>
00035
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <unistd.h>
00039
00040 #include <db.h>
00041
00042 #define DATABASE "bench_001.db"
00043
00044 int compare_int(DB *, const DBT *, const DBT *);
00045 DB_ENV *db_init(char *, char *, u_int, int);
00046 int fill(DB_ENV *, DB *, int, u_int, int, int);
00047 int get(DB *, int, u_int, int, int, int, int *);
00048 int main(int, char *[]);
00049 void usage(void);
00050
00051 const char
00052 *progname = "bench_001";
00053
00054
00055
00056
00057 DB_ENV *
00058 db_init(home, prefix, cachesize, txn)
00059 char *home, *prefix;
00060 u_int cachesize;
00061 int txn;
00062 {
00063 DB_ENV *dbenv;
00064 u_int32_t flags;
00065 int ret;
00066
00067 if ((ret = db_env_create(&dbenv, 0)) != 0) {
00068 dbenv->err(dbenv, ret, "db_env_create");
00069 return (NULL);
00070 }
00071 dbenv->set_errfile(dbenv, stderr);
00072 dbenv->set_errpfx(dbenv, prefix);
00073 (void)dbenv->set_cachesize(dbenv, 0,
00074 cachesize == 0 ? 50 * 1024 * 1024 : (u_int32_t)cachesize, 0);
00075
00076 flags = DB_CREATE | DB_INIT_MPOOL;
00077 if (txn)
00078 flags |= DB_INIT_TXN | DB_INIT_LOCK;
00079 if ((ret = dbenv->open(dbenv, home, flags, 0)) != 0) {
00080 dbenv->err(dbenv, ret, "DB_ENV->open: %s", home);
00081 (void)dbenv->close(dbenv, 0);
00082 return (NULL);
00083 }
00084 return (dbenv);
00085 }
00086
00087
00088
00089
00090
00091 int
00092 get(dbp, txn, datalen, num, dups, iter, countp)
00093 DB *dbp;
00094 u_int datalen;
00095 int txn, num, dups, iter, *countp;
00096 {
00097 DBC *dbcp;
00098 DBT key, data;
00099 DB_ENV *dbenv;
00100 DB_TXN *txnp;
00101 u_int32_t flags, len, klen;
00102 int count, i, j, ret;
00103 void *pointer, *dp, *kp;
00104
00105 dbenv = dbp->dbenv;
00106
00107 klen = 0;
00108 klen = klen;
00109
00110 memset(&key, 0, sizeof(key));
00111 key.data = &j;
00112 key.size = sizeof(j);
00113 memset(&data, 0, sizeof(data));
00114 data.flags = DB_DBT_USERMEM;
00115 data.data = malloc(datalen*1024*1024);
00116 data.ulen = data.size = datalen*1024*1024;
00117
00118 count = 0;
00119 flags = DB_SET;
00120 if (!dups)
00121 flags |= DB_MULTIPLE_KEY;
00122 else
00123 flags |= DB_MULTIPLE;
00124 for (i = 0; i < iter; i++) {
00125 txnp = NULL;
00126 if (txn)
00127 if ((ret =
00128 dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
00129 goto err;
00130 if ((ret = dbp->cursor(dbp, txnp, &dbcp, 0)) != 0)
00131 goto err;
00132
00133 j = random() % num;
00134 if ((ret = dbcp->c_get(dbcp, &key, &data, flags)) != 0)
00135 goto err;
00136 DB_MULTIPLE_INIT(pointer, &data);
00137 if (dups)
00138 while (pointer != NULL) {
00139 DB_MULTIPLE_NEXT(pointer, &data, dp, len);
00140 if (dp != NULL)
00141 count++;
00142 }
00143 else
00144 while (pointer != NULL) {
00145 DB_MULTIPLE_KEY_NEXT(pointer,
00146 &data, kp, klen, dp, len);
00147 if (kp != NULL)
00148 count++;
00149 }
00150 if ((ret = dbcp->c_close(dbcp)) != 0)
00151 goto err;
00152 if (txn)
00153 if ((ret = txnp->commit(txnp, 0)) != 0)
00154 goto err;
00155 }
00156
00157 *countp = count;
00158 return (0);
00159
00160 err: dbp->err(dbp, ret, "get");
00161 return (ret);
00162 }
00163
00164
00165
00166
00167
00168
00169
00170 #define PUTS_PER_TXN 10
00171 int
00172 fill(dbenv, dbp, txn, datalen, num, dups)
00173 DB_ENV *dbenv;
00174 DB *dbp;
00175 u_int datalen;
00176 int txn, num, dups;
00177 {
00178 DBT key, data;
00179 DB_TXN *txnp;
00180 struct data {
00181 int id;
00182 char str[1];
00183 } *data_val;
00184 int count, i, ret;
00185
00186
00187
00188
00189
00190 txnp = NULL;
00191 ret = 0;
00192 count = 0;
00193 memset(&key, 0, sizeof(DBT));
00194 memset(&data, 0, sizeof(DBT));
00195 key.data = &i;
00196 key.size = sizeof(i);
00197 data.data = data_val = malloc(datalen);
00198 memcpy(data_val->str, "0123456789012345678901234567890123456789",
00199 datalen - sizeof(data_val->id));
00200 data.size = datalen;
00201 data.flags = DB_DBT_USERMEM;
00202
00203 for (i = 0; i < num; i++) {
00204 if (txn != 0 && i % PUTS_PER_TXN == 0) {
00205 if (txnp != NULL) {
00206 ret = txnp->commit(txnp, 0);
00207 txnp = NULL;
00208 if (ret != 0)
00209 goto err;
00210 }
00211 if ((ret =
00212 dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
00213 goto err;
00214 }
00215 data_val->id = 0;
00216 do {
00217 switch (ret = dbp->put(dbp, txnp, &key, &data, 0)) {
00218 case 0:
00219 count++;
00220 break;
00221 default:
00222 dbp->err(dbp, ret, "DB->put");
00223 goto err;
00224 }
00225 } while (++data_val->id < dups);
00226 }
00227 if (txnp != NULL)
00228 ret = txnp->commit(txnp, 0);
00229
00230 printf("%d\n", count);
00231 return (ret);
00232
00233 err: if (txnp != NULL)
00234 (void)txnp->abort(txnp);
00235 return (ret);
00236 }
00237
00238 int
00239 main(argc, argv)
00240 int argc;
00241 char *argv[];
00242 {
00243 extern char *optarg;
00244 extern int optind;
00245 DB *dbp;
00246 DB_ENV *dbenv;
00247 DB_TXN *txnp;
00248 struct timeval start_time, end_time;
00249 double secs;
00250 u_int cache, datalen, pagesize;
00251 int ch, count, dups, env, init, iter, num;
00252 int ret, rflag, txn;
00253
00254 txnp = NULL;
00255 datalen = 20;
00256 iter = num = 1000000;
00257 env = 1;
00258 dups = init = rflag = txn = 0;
00259
00260 pagesize = 65536;
00261 cache = 1000 * pagesize;
00262
00263 while ((ch = getopt(argc, argv, "c:d:EIi:l:n:p:RT")) != EOF)
00264 switch (ch) {
00265 case 'c':
00266 cache = (u_int)atoi(optarg);
00267 break;
00268 case 'd':
00269 dups = atoi(optarg);
00270 break;
00271 case 'E':
00272 env = 0;
00273 break;
00274 case 'I':
00275 init = 1;
00276 break;
00277 case 'i':
00278 iter = atoi(optarg);
00279 break;
00280 case 'l':
00281 datalen = (u_int)atoi(optarg);
00282 break;
00283 case 'n':
00284 num = atoi(optarg);
00285 break;
00286 case 'p':
00287 pagesize = (u_int)atoi(optarg);
00288 break;
00289 case 'R':
00290 rflag = 1;
00291 break;
00292 case 'T':
00293 txn = 1;
00294 break;
00295 case '?':
00296 default:
00297 usage();
00298 }
00299 argc -= optind;
00300 argv += optind;
00301
00302
00303 if (!rflag) {
00304 if (env)
00305 (void)system("rm -rf BENCH_001; mkdir BENCH_001");
00306 else
00307 (void)unlink(DATABASE);
00308 }
00309
00310 dbenv = NULL;
00311 if (env == 1 &&
00312 (dbenv = db_init("BENCH_001", "bench_001", cache, txn)) == NULL)
00313 return (-1);
00314 if (init)
00315 exit(0);
00316
00317 if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
00318 fprintf(stderr,
00319 "%s: db_create: %s\n", progname, db_strerror(ret));
00320 exit(EXIT_FAILURE);
00321 }
00322 dbp->set_errfile(dbp, stderr);
00323 dbp->set_errpfx(dbp, progname);
00324 if ((ret = dbp->set_bt_compare(dbp, compare_int)) != 0) {
00325 dbp->err(dbp, ret, "set_bt_compare");
00326 goto err;
00327 }
00328 if ((ret = dbp->set_pagesize(dbp, pagesize)) != 0) {
00329 dbp->err(dbp, ret, "set_pagesize");
00330 goto err;
00331 }
00332 if (dups && (ret = dbp->set_flags(dbp, DB_DUP)) != 0) {
00333 dbp->err(dbp, ret, "set_flags");
00334 goto err;
00335 }
00336
00337 if (env == 0 && (ret = dbp->set_cachesize(dbp, 0, cache, 0)) != 0) {
00338 dbp->err(dbp, ret, "set_cachesize");
00339 goto err;
00340 }
00341
00342 if ((ret = dbp->set_flags(dbp, DB_DUP)) != 0) {
00343 dbp->err(dbp, ret, "set_flags");
00344 goto err;
00345 }
00346
00347 if (txn != 0)
00348 if ((ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
00349 goto err;
00350
00351 if ((ret = dbp->open(
00352 dbp, txnp, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
00353 dbp->err(dbp, ret, "%s: open", DATABASE);
00354 if (txnp != NULL)
00355 (void)txnp->abort(txnp);
00356 goto err;
00357 }
00358
00359 if (txnp != NULL)
00360 ret = txnp->commit(txnp, 0);
00361 txnp = NULL;
00362 if (ret != 0)
00363 goto err;
00364
00365 if (rflag) {
00366
00367 if (!env && (ret =
00368 get(dbp, txn, datalen, num, dups, iter, &count)) != 0)
00369 goto err;
00370
00371
00372 (void)gettimeofday(&start_time, NULL);
00373 if ((ret =
00374 get(dbp, txn, datalen, num, dups, iter, &count)) != 0)
00375 goto err;
00376 (void)gettimeofday(&end_time, NULL);
00377 secs =
00378 (((double)end_time.tv_sec * 1000000 + end_time.tv_usec) -
00379 ((double)start_time.tv_sec * 1000000 + start_time.tv_usec))
00380 / 1000000;
00381 printf("%d records read using %d batches in %.2f seconds: ",
00382 count, iter, secs);
00383 printf("%.0f records/second\n", (double)count / secs);
00384
00385 } else if ((ret = fill(dbenv, dbp, txn, datalen, num, dups)) != 0)
00386 goto err;
00387
00388
00389 if ((ret = dbp->close(dbp, rflag ? DB_NOSYNC : 0)) != 0) {
00390 fprintf(stderr,
00391 "%s: DB->close: %s\n", progname, db_strerror(ret));
00392 return (1);
00393 }
00394 return (ret);
00395
00396 err: (void)dbp->close(dbp, 0);
00397 return (1);
00398 }
00399
00400 int
00401 compare_int(dbp, a, b)
00402 DB *dbp;
00403 const DBT *a, *b;
00404 {
00405 int ai, bi;
00406
00407 dbp = dbp;
00408
00409
00410
00411
00412
00413
00414
00415 memcpy(&ai, a->data, sizeof(int));
00416 memcpy(&bi, b->data, sizeof(int));
00417 return (ai - bi);
00418 }
00419
00420 void
00421 usage()
00422 {
00423 (void)fprintf(stderr, "usage: %s %s\n\t%s\n",
00424 progname, "[-EIRT] [-c cachesize] [-d dups]",
00425 "[-i iterations] [-l datalen] [-n keys] [-p pagesize]");
00426 exit(EXIT_FAILURE);
00427 }