~ubuntu-branches/ubuntu/natty/evolution-data-server/natty

« back to all changes in this revision

Viewing changes to libdb/examples_c/ex_tpcb.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-05-17 17:02:06 UTC
  • mfrom: (1.1.79 upstream) (1.6.12 experimental)
  • Revision ID: james.westby@ubuntu.com-20100517170206-4ufr52vwrhh26yh0
Tags: 2.30.1-1ubuntu1
* Merge from debian experimental. Remaining change:
  (LP: #42199, #229669, #173703, #360344, #508494)
  + debian/control:
    - add Vcs-Bzr tag
    - don't use libgnome
    - Use Breaks instead of Conflicts against evolution 2.25 and earlier.
  + debian/evolution-data-server.install,
    debian/patches/45_libcamel_providers_version.patch:
    - use the upstream versioning, not a Debian-specific one 
  + debian/libedata-book1.2-dev.install, debian/libebackend-1.2-dev.install,
    debian/libcamel1.2-dev.install, debian/libedataserverui1.2-dev.install:
    - install html documentation
  + debian/rules:
    - don't build documentation it's shipped with the tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*-
2
 
 * See the file LICENSE for redistribution information.
3
 
 *
4
 
 * Copyright (c) 1997-2002
5
 
 *      Sleepycat Software.  All rights reserved.
6
 
 *
7
 
 * $Id$
8
 
 */
9
 
 
10
 
#include <sys/types.h>
11
 
 
12
 
#include <errno.h>
13
 
#include <stdlib.h>
14
 
#include <string.h>
15
 
#include <time.h>
16
 
 
17
 
#ifdef _WIN32
18
 
extern int getopt(int, char * const *, const char *);
19
 
#else
20
 
#include <unistd.h>
21
 
#endif
22
 
 
23
 
#include <db.h>
24
 
 
25
 
typedef enum { ACCOUNT, BRANCH, TELLER } FTYPE;
26
 
 
27
 
DB_ENV   *db_init __P((const char *, const char *, int, int, u_int32_t));
28
 
int       hpopulate __P((DB *, int, int, int, int));
29
 
int       populate __P((DB *, u_int32_t, u_int32_t, int, const char *));
30
 
u_int32_t random_id __P((FTYPE, int, int, int));
31
 
u_int32_t random_int __P((u_int32_t, u_int32_t));
32
 
int       tp_populate __P((DB_ENV *, int, int, int, int, int));
33
 
int       tp_run __P((DB_ENV *, int, int, int, int, int));
34
 
int       tp_txn __P((DB_ENV *, DB *, DB *, DB *, DB *, int, int, int, int));
35
 
 
36
 
int       invarg __P((const char *, int, const char *));
37
 
int       main __P((int, char *[]));
38
 
int       usage __P((const char *));
39
 
 
40
 
/*
41
 
 * This program implements a basic TPC/B driver program.  To create the
42
 
 * TPC/B database, run with the -i (init) flag.  The number of records
43
 
 * with which to populate the account, history, branch, and teller tables
44
 
 * is specified by the a, s, b, and t flags respectively.  To run a TPC/B
45
 
 * test, use the n flag to indicate a number of transactions to run (note
46
 
 * that you can run many of these processes in parallel to simulate a
47
 
 * multiuser test run).
48
 
 */
49
 
#define TELLERS_PER_BRANCH      10
50
 
#define ACCOUNTS_PER_TELLER     10000
51
 
#define HISTORY_PER_BRANCH      2592000
52
 
 
53
 
/*
54
 
 * The default configuration that adheres to TPCB scaling rules requires
55
 
 * nearly 3 GB of space.  To avoid requiring that much space for testing,
56
 
 * we set the parameters much lower.  If you want to run a valid 10 TPS
57
 
 * configuration, define VALID_SCALING.
58
 
 */
59
 
#ifdef  VALID_SCALING
60
 
#define ACCOUNTS         1000000
61
 
#define BRANCHES              10
62
 
#define TELLERS              100
63
 
#define HISTORY         25920000
64
 
#endif
65
 
 
66
 
#ifdef  TINY
67
 
#define ACCOUNTS            1000
68
 
#define BRANCHES              10
69
 
#define TELLERS              100
70
 
#define HISTORY            10000
71
 
#endif
72
 
 
73
 
#ifdef  VERY_TINY
74
 
#define ACCOUNTS             500
75
 
#define BRANCHES              10
76
 
#define TELLERS               50
77
 
#define HISTORY             5000
78
 
#endif
79
 
 
80
 
#if !defined(VALID_SCALING) && !defined(TINY) && !defined(VERY_TINY)
81
 
#define ACCOUNTS          100000
82
 
#define BRANCHES              10
83
 
#define TELLERS              100
84
 
#define HISTORY           259200
85
 
#endif
86
 
 
87
 
#define HISTORY_LEN         100
88
 
#define RECLEN              100
89
 
#define BEGID           1000000
90
 
 
91
 
typedef struct _defrec {
92
 
        u_int32_t       id;
93
 
        u_int32_t       balance;
94
 
        u_int8_t        pad[RECLEN - sizeof(u_int32_t) - sizeof(u_int32_t)];
95
 
} defrec;
96
 
 
97
 
typedef struct _histrec {
98
 
        u_int32_t       aid;
99
 
        u_int32_t       bid;
100
 
        u_int32_t       tid;
101
 
        u_int32_t       amount;
102
 
        u_int8_t        pad[RECLEN - 4 * sizeof(u_int32_t)];
103
 
} histrec;
104
 
 
105
 
int
106
 
main(argc, argv)
107
 
        int argc;
108
 
        char *argv[];
109
 
{
110
 
        extern char *optarg;
111
 
        extern int optind;
112
 
        DB_ENV *dbenv;
113
 
        int accounts, branches, seed, tellers, history;
114
 
        int ch, iflag, mpool, ntxns, ret, txn_no_sync, verbose;
115
 
        const char *home, *progname;
116
 
 
117
 
        home = "TESTDIR";
118
 
        progname = "ex_tpcb";
119
 
        accounts = branches = history = tellers = 0;
120
 
        iflag = mpool = ntxns = txn_no_sync = verbose = 0;
121
 
        seed = (int)time(NULL);
122
 
 
123
 
        while ((ch = getopt(argc, argv, "a:b:c:fh:in:S:s:t:v")) != EOF)
124
 
                switch (ch) {
125
 
                case 'a':                       /* Number of account records */
126
 
                        if ((accounts = atoi(optarg)) <= 0)
127
 
                                return (invarg(progname, ch, optarg));
128
 
                        break;
129
 
                case 'b':                       /* Number of branch records */
130
 
                        if ((branches = atoi(optarg)) <= 0)
131
 
                                return (invarg(progname, ch, optarg));
132
 
                        break;
133
 
                case 'c':                       /* Cachesize in bytes */
134
 
                        if ((mpool = atoi(optarg)) <= 0)
135
 
                                return (invarg(progname, ch, optarg));
136
 
                        break;
137
 
                case 'f':                       /* Fast mode: no txn sync. */
138
 
                        txn_no_sync = 1;
139
 
                        break;
140
 
                case 'h':                       /* DB  home. */
141
 
                        home = optarg;
142
 
                        break;
143
 
                case 'i':                       /* Initialize the test. */
144
 
                        iflag = 1;
145
 
                        break;
146
 
                case 'n':                       /* Number of transactions */
147
 
                        if ((ntxns = atoi(optarg)) <= 0)
148
 
                                return (invarg(progname, ch, optarg));
149
 
                        break;
150
 
                case 'S':                       /* Random number seed. */
151
 
                        if ((seed = atoi(optarg)) <= 0)
152
 
                                return (invarg(progname, ch, optarg));
153
 
                        break;
154
 
                case 's':                       /* Number of history records */
155
 
                        if ((history = atoi(optarg)) <= 0)
156
 
                                return (invarg(progname, ch, optarg));
157
 
                        break;
158
 
                case 't':                       /* Number of teller records */
159
 
                        if ((tellers = atoi(optarg)) <= 0)
160
 
                                return (invarg(progname, ch, optarg));
161
 
                        break;
162
 
                case 'v':                       /* Verbose option. */
163
 
                        verbose = 1;
164
 
                        break;
165
 
                case '?':
166
 
                default:
167
 
                        return (usage(progname));
168
 
                }
169
 
        argc -= optind;
170
 
        argv += optind;
171
 
 
172
 
        srand((u_int)seed);
173
 
 
174
 
        /* Initialize the database environment. */
175
 
        if ((dbenv = db_init(home,
176
 
            progname, mpool, iflag, txn_no_sync ? DB_TXN_NOSYNC : 0)) == NULL)
177
 
                return (EXIT_FAILURE);
178
 
 
179
 
        accounts = accounts == 0 ? ACCOUNTS : accounts;
180
 
        branches = branches == 0 ? BRANCHES : branches;
181
 
        tellers = tellers == 0 ? TELLERS : tellers;
182
 
        history = history == 0 ? HISTORY : history;
183
 
 
184
 
        if (verbose)
185
 
                printf("%ld Accounts, %ld Branches, %ld Tellers, %ld History\n",
186
 
                    (long)accounts, (long)branches,
187
 
                    (long)tellers, (long)history);
188
 
 
189
 
        if (iflag) {
190
 
                if (ntxns != 0)
191
 
                        return (usage(progname));
192
 
                tp_populate(dbenv,
193
 
                    accounts, branches, history, tellers, verbose);
194
 
        } else {
195
 
                if (ntxns == 0)
196
 
                        return (usage(progname));
197
 
                tp_run(dbenv, ntxns, accounts, branches, tellers, verbose);
198
 
        }
199
 
 
200
 
        if ((ret = dbenv->close(dbenv, 0)) != 0) {
201
 
                fprintf(stderr, "%s: dbenv->close failed: %s\n",
202
 
                    progname, db_strerror(ret));
203
 
                return (EXIT_FAILURE);
204
 
        }
205
 
 
206
 
        return (EXIT_SUCCESS);
207
 
}
208
 
 
209
 
int
210
 
invarg(progname, arg, str)
211
 
        const char *progname;
212
 
        int arg;
213
 
        const char *str;
214
 
{
215
 
        (void)fprintf(stderr,
216
 
            "%s: invalid argument for -%c: %s\n", progname, arg, str);
217
 
        return (EXIT_FAILURE);
218
 
}
219
 
 
220
 
int
221
 
usage(progname)
222
 
        const char *progname;
223
 
{
224
 
        const char *a1, *a2;
225
 
 
226
 
        a1 = "[-fv] [-a accounts] [-b branches]\n";
227
 
        a2 = "\t[-c cache_size] [-h home] [-S seed] [-s history] [-t tellers]";
228
 
        (void)fprintf(stderr, "usage: %s -i %s %s\n", progname, a1, a2);
229
 
        (void)fprintf(stderr,
230
 
            "       %s -n transactions %s %s\n", progname, a1, a2);
231
 
        return (EXIT_FAILURE);
232
 
}
233
 
 
234
 
/*
235
 
 * db_init --
236
 
 *      Initialize the environment.
237
 
 */
238
 
DB_ENV *
239
 
db_init(home, prefix, cachesize, initializing, flags)
240
 
        const char *home, *prefix;
241
 
        int cachesize, initializing;
242
 
        u_int32_t flags;
243
 
{
244
 
        DB_ENV *dbenv;
245
 
        u_int32_t local_flags;
246
 
        int ret;
247
 
 
248
 
        if ((ret = db_env_create(&dbenv, 0)) != 0) {
249
 
                dbenv->err(dbenv, ret, "db_env_create");
250
 
                return (NULL);
251
 
        }
252
 
        dbenv->set_errfile(dbenv, stderr);
253
 
        dbenv->set_errpfx(dbenv, prefix);
254
 
        (void)dbenv->set_cachesize(dbenv, 0,
255
 
            cachesize == 0 ? 4 * 1024 * 1024 : (u_int32_t)cachesize, 0);
256
 
 
257
 
        if (flags & (DB_TXN_NOSYNC))
258
 
                (void)dbenv->set_flags(dbenv, DB_TXN_NOSYNC, 1);
259
 
        flags &= ~(DB_TXN_NOSYNC);
260
 
 
261
 
        local_flags = flags | DB_CREATE | (initializing ? DB_INIT_MPOOL :
262
 
            DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL);
263
 
        if ((ret = dbenv->open(dbenv, home, local_flags, 0)) != 0) {
264
 
                dbenv->err(dbenv, ret, "DB_ENV->open: %s", home);
265
 
                (void)dbenv->close(dbenv, 0);
266
 
                return (NULL);
267
 
        }
268
 
        return (dbenv);
269
 
}
270
 
 
271
 
/*
272
 
 * Initialize the database to the specified number of accounts, branches,
273
 
 * history records, and tellers.
274
 
 */
275
 
int
276
 
tp_populate(env, accounts, branches, history, tellers, verbose)
277
 
        DB_ENV *env;
278
 
        int accounts, branches, history, tellers, verbose;
279
 
{
280
 
        DB *dbp;
281
 
        u_int32_t balance, idnum, oflags;
282
 
        u_int32_t end_anum, end_bnum, end_tnum;
283
 
        u_int32_t start_anum, start_bnum, start_tnum;
284
 
        int ret;
285
 
 
286
 
        idnum = BEGID;
287
 
        balance = 500000;
288
 
        oflags = DB_CREATE | DB_TRUNCATE;
289
 
 
290
 
        if ((ret = db_create(&dbp, env, 0)) != 0) {
291
 
                env->err(env, ret, "db_create");
292
 
                return (1);
293
 
        }
294
 
        (void)dbp->set_h_nelem(dbp, (u_int32_t)accounts);
295
 
 
296
 
        if ((ret = dbp->open(dbp, NULL, "account", NULL,
297
 
            DB_HASH, oflags, 0644)) != 0) {
298
 
                env->err(env, ret, "DB->open: account");
299
 
                return (1);
300
 
        }
301
 
 
302
 
        start_anum = idnum;
303
 
        populate(dbp, idnum, balance, accounts, "account");
304
 
        idnum += accounts;
305
 
        end_anum = idnum - 1;
306
 
        if ((ret = dbp->close(dbp, 0)) != 0) {
307
 
                env->err(env, ret, "DB->close: account");
308
 
                return (1);
309
 
        }
310
 
        if (verbose)
311
 
                printf("Populated accounts: %ld - %ld\n",
312
 
                    (long)start_anum, (long)end_anum);
313
 
 
314
 
        /*
315
 
         * Since the number of branches is very small, we want to use very
316
 
         * small pages and only 1 key per page, i.e., key-locking instead
317
 
         * of page locking.
318
 
         */
319
 
        if ((ret = db_create(&dbp, env, 0)) != 0) {
320
 
                env->err(env, ret, "db_create");
321
 
                return (1);
322
 
        }
323
 
        (void)dbp->set_h_ffactor(dbp, 1);
324
 
        (void)dbp->set_h_nelem(dbp, (u_int32_t)branches);
325
 
        (void)dbp->set_pagesize(dbp, 512);
326
 
        if ((ret = dbp->open(dbp, NULL, "branch", NULL,
327
 
            DB_HASH, oflags, 0644)) != 0) {
328
 
                env->err(env, ret, "DB->open: branch");
329
 
                return (1);
330
 
        }
331
 
        start_bnum = idnum;
332
 
        populate(dbp, idnum, balance, branches, "branch");
333
 
        idnum += branches;
334
 
        end_bnum = idnum - 1;
335
 
        if ((ret = dbp->close(dbp, 0)) != 0) {
336
 
                env->err(env, ret, "DB->close: branch");
337
 
                return (1);
338
 
        }
339
 
        if (verbose)
340
 
                printf("Populated branches: %ld - %ld\n",
341
 
                    (long)start_bnum, (long)end_bnum);
342
 
 
343
 
        /*
344
 
         * In the case of tellers, we also want small pages, but we'll let
345
 
         * the fill factor dynamically adjust itself.
346
 
         */
347
 
        if ((ret = db_create(&dbp, env, 0)) != 0) {
348
 
                env->err(env, ret, "db_create");
349
 
                return (1);
350
 
        }
351
 
        (void)dbp->set_h_ffactor(dbp, 0);
352
 
        (void)dbp->set_h_nelem(dbp, (u_int32_t)tellers);
353
 
        (void)dbp->set_pagesize(dbp, 512);
354
 
        if ((ret = dbp->open(dbp, NULL, "teller", NULL,
355
 
            DB_HASH, oflags, 0644)) != 0) {
356
 
                env->err(env, ret, "DB->open: teller");
357
 
                return (1);
358
 
        }
359
 
 
360
 
        start_tnum = idnum;
361
 
        populate(dbp, idnum, balance, tellers, "teller");
362
 
        idnum += tellers;
363
 
        end_tnum = idnum - 1;
364
 
        if ((ret = dbp->close(dbp, 0)) != 0) {
365
 
                env->err(env, ret, "DB->close: teller");
366
 
                return (1);
367
 
        }
368
 
        if (verbose)
369
 
                printf("Populated tellers: %ld - %ld\n",
370
 
                    (long)start_tnum, (long)end_tnum);
371
 
 
372
 
        if ((ret = db_create(&dbp, env, 0)) != 0) {
373
 
                env->err(env, ret, "db_create");
374
 
                return (1);
375
 
        }
376
 
        (void)dbp->set_re_len(dbp, HISTORY_LEN);
377
 
        if ((ret = dbp->open(dbp, NULL, "history", NULL,
378
 
            DB_RECNO, oflags, 0644)) != 0) {
379
 
                env->err(env, ret, "DB->open: history");
380
 
                return (1);
381
 
        }
382
 
 
383
 
        hpopulate(dbp, history, accounts, branches, tellers);
384
 
        if ((ret = dbp->close(dbp, 0)) != 0) {
385
 
                env->err(env, ret, "DB->close: history");
386
 
                return (1);
387
 
        }
388
 
        return (0);
389
 
}
390
 
 
391
 
int
392
 
populate(dbp, start_id, balance, nrecs, msg)
393
 
        DB *dbp;
394
 
        u_int32_t start_id, balance;
395
 
        int nrecs;
396
 
        const char *msg;
397
 
{
398
 
        DBT kdbt, ddbt;
399
 
        defrec drec;
400
 
        int i, ret;
401
 
 
402
 
        kdbt.flags = 0;
403
 
        kdbt.data = &drec.id;
404
 
        kdbt.size = sizeof(u_int32_t);
405
 
        ddbt.flags = 0;
406
 
        ddbt.data = &drec;
407
 
        ddbt.size = sizeof(drec);
408
 
        memset(&drec.pad[0], 1, sizeof(drec.pad));
409
 
 
410
 
        for (i = 0; i < nrecs; i++) {
411
 
                drec.id = start_id + (u_int32_t)i;
412
 
                drec.balance = balance;
413
 
                if ((ret =
414
 
                    (dbp->put)(dbp, NULL, &kdbt, &ddbt, DB_NOOVERWRITE)) != 0) {
415
 
                        dbp->err(dbp,
416
 
                            ret, "Failure initializing %s file\n", msg);
417
 
                        return (1);
418
 
                }
419
 
        }
420
 
        return (0);
421
 
}
422
 
 
423
 
int
424
 
hpopulate(dbp, history, accounts, branches, tellers)
425
 
        DB *dbp;
426
 
        int history, accounts, branches, tellers;
427
 
{
428
 
        DBT kdbt, ddbt;
429
 
        histrec hrec;
430
 
        db_recno_t key;
431
 
        int i, ret;
432
 
 
433
 
        memset(&kdbt, 0, sizeof(kdbt));
434
 
        memset(&ddbt, 0, sizeof(ddbt));
435
 
        ddbt.data = &hrec;
436
 
        ddbt.size = sizeof(hrec);
437
 
        kdbt.data = &key;
438
 
        kdbt.size = sizeof(key);
439
 
        memset(&hrec.pad[0], 1, sizeof(hrec.pad));
440
 
        hrec.amount = 10;
441
 
 
442
 
        for (i = 1; i <= history; i++) {
443
 
                hrec.aid = random_id(ACCOUNT, accounts, branches, tellers);
444
 
                hrec.bid = random_id(BRANCH, accounts, branches, tellers);
445
 
                hrec.tid = random_id(TELLER, accounts, branches, tellers);
446
 
                if ((ret = dbp->put(dbp, NULL, &kdbt, &ddbt, DB_APPEND)) != 0) {
447
 
                        dbp->err(dbp, ret, "dbp->put");
448
 
                        return (1);
449
 
                }
450
 
        }
451
 
        return (0);
452
 
}
453
 
 
454
 
u_int32_t
455
 
random_int(lo, hi)
456
 
        u_int32_t lo, hi;
457
 
{
458
 
        u_int32_t ret;
459
 
        int t;
460
 
 
461
 
#ifndef RAND_MAX
462
 
#define RAND_MAX        0x7fffffff
463
 
#endif
464
 
        t = rand();
465
 
        ret = (u_int32_t)(((double)t / ((double)(RAND_MAX) + 1)) *
466
 
            (hi - lo + 1));
467
 
        ret += lo;
468
 
        return (ret);
469
 
}
470
 
 
471
 
u_int32_t
472
 
random_id(type, accounts, branches, tellers)
473
 
        FTYPE type;
474
 
        int accounts, branches, tellers;
475
 
{
476
 
        u_int32_t min, max, num;
477
 
 
478
 
        max = min = BEGID;
479
 
        num = accounts;
480
 
        switch(type) {
481
 
        case TELLER:
482
 
                min += branches;
483
 
                num = tellers;
484
 
                /* FALLTHROUGH */
485
 
        case BRANCH:
486
 
                if (type == BRANCH)
487
 
                        num = branches;
488
 
                min += accounts;
489
 
                /* FALLTHROUGH */
490
 
        case ACCOUNT:
491
 
                max = min + num - 1;
492
 
        }
493
 
        return (random_int(min, max));
494
 
}
495
 
 
496
 
int
497
 
tp_run(dbenv, n, accounts, branches, tellers, verbose)
498
 
        DB_ENV *dbenv;
499
 
        int n, accounts, branches, tellers, verbose;
500
 
{
501
 
        DB *adb, *bdb, *hdb, *tdb;
502
 
        double gtps, itps;
503
 
        int failed, ifailed, ret, txns;
504
 
        time_t starttime, curtime, lasttime;
505
 
 
506
 
        adb = bdb = hdb = tdb = NULL;
507
 
        txns = failed = 0;
508
 
 
509
 
        /*
510
 
         * Open the database files.
511
 
         */
512
 
        if ((ret = db_create(&adb, dbenv, 0)) != 0) {
513
 
                dbenv->err(dbenv, ret, "db_create");
514
 
                goto err;
515
 
        }
516
 
        if ((ret = adb->open(adb, NULL, "account", NULL, DB_UNKNOWN,
517
 
            DB_AUTO_COMMIT, 0)) != 0) {
518
 
                dbenv->err(dbenv, ret, "DB->open: account");
519
 
                goto err;
520
 
        }
521
 
        if ((ret = db_create(&bdb, dbenv, 0)) != 0) {
522
 
                dbenv->err(dbenv, ret, "db_create");
523
 
                goto err;
524
 
        }
525
 
        if ((ret = bdb->open(bdb, NULL, "branch", NULL, DB_UNKNOWN,
526
 
            DB_AUTO_COMMIT, 0)) != 0) {
527
 
                dbenv->err(dbenv, ret, "DB->open: branch");
528
 
                goto err;
529
 
        }
530
 
        if ((ret = db_create(&hdb, dbenv, 0)) != 0) {
531
 
                dbenv->err(dbenv, ret, "db_create");
532
 
                goto err;
533
 
        }
534
 
        if ((ret = hdb->open(hdb, NULL, "history", NULL, DB_UNKNOWN,
535
 
            DB_AUTO_COMMIT, 0)) != 0) {
536
 
                dbenv->err(dbenv, ret, "DB->open: history");
537
 
                goto err;
538
 
        }
539
 
        if ((ret = db_create(&tdb, dbenv, 0)) != 0) {
540
 
                dbenv->err(dbenv, ret, "db_create");
541
 
                goto err;
542
 
        }
543
 
        if ((ret = tdb->open(tdb, NULL, "teller", NULL, DB_UNKNOWN,
544
 
            DB_AUTO_COMMIT, 0)) != 0) {
545
 
                dbenv->err(dbenv, ret, "DB->open: teller");
546
 
                goto err;
547
 
        }
548
 
 
549
 
        starttime = time(NULL);
550
 
        lasttime = starttime;
551
 
        for (ifailed = 0; n-- > 0;) {
552
 
                txns++;
553
 
                ret = tp_txn(dbenv, adb, bdb, tdb, hdb,
554
 
                    accounts, branches, tellers, verbose);
555
 
                if (ret != 0) {
556
 
                        failed++;
557
 
                        ifailed++;
558
 
                }
559
 
                if (n % 5000 == 0) {
560
 
                        curtime = time(NULL);
561
 
                        gtps = (double)(txns - failed) / (curtime - starttime);
562
 
                        itps = (double)(5000 - ifailed) / (curtime - lasttime);
563
 
                        printf("%d txns %d failed ", txns, failed);
564
 
                        printf("%6.2f TPS (gross) %6.2f TPS (interval)\n",
565
 
                           gtps, itps);
566
 
                        lasttime = curtime;
567
 
                        ifailed = 0;
568
 
                }
569
 
        }
570
 
 
571
 
err:    if (adb != NULL)
572
 
                (void)adb->close(adb, 0);
573
 
        if (bdb != NULL)
574
 
                (void)bdb->close(bdb, 0);
575
 
        if (tdb != NULL)
576
 
                (void)tdb->close(tdb, 0);
577
 
        if (hdb != NULL)
578
 
                (void)hdb->close(hdb, 0);
579
 
 
580
 
        printf("%ld transactions begun %ld failed\n", (long)txns, (long)failed);
581
 
        return (ret == 0 ? 0 : 1);
582
 
}
583
 
 
584
 
/*
585
 
 * XXX Figure out the appropriate way to pick out IDs.
586
 
 */
587
 
int
588
 
tp_txn(dbenv, adb, bdb, tdb, hdb, accounts, branches, tellers, verbose)
589
 
        DB_ENV *dbenv;
590
 
        DB *adb, *bdb, *tdb, *hdb;
591
 
        int accounts, branches, tellers, verbose;
592
 
{
593
 
        DBC *acurs, *bcurs, *tcurs;
594
 
        DBT d_dbt, d_histdbt, k_dbt, k_histdbt;
595
 
        DB_TXN *t;
596
 
        db_recno_t key;
597
 
        defrec rec;
598
 
        histrec hrec;
599
 
        int account, branch, teller, ret;
600
 
 
601
 
        t = NULL;
602
 
        acurs = bcurs = tcurs = NULL;
603
 
 
604
 
        /*
605
 
         * XXX We could move a lot of this into the driver to make this
606
 
         * faster.
607
 
         */
608
 
        account = random_id(ACCOUNT, accounts, branches, tellers);
609
 
        branch = random_id(BRANCH, accounts, branches, tellers);
610
 
        teller = random_id(TELLER, accounts, branches, tellers);
611
 
 
612
 
        memset(&d_histdbt, 0, sizeof(d_histdbt));
613
 
 
614
 
        memset(&k_histdbt, 0, sizeof(k_histdbt));
615
 
        k_histdbt.data = &key;
616
 
        k_histdbt.size = sizeof(key);
617
 
 
618
 
        memset(&k_dbt, 0, sizeof(k_dbt));
619
 
        k_dbt.size = sizeof(int);
620
 
 
621
 
        memset(&d_dbt, 0, sizeof(d_dbt));
622
 
        d_dbt.flags = DB_DBT_USERMEM;
623
 
        d_dbt.data = &rec;
624
 
        d_dbt.ulen = sizeof(rec);
625
 
 
626
 
        hrec.aid = account;
627
 
        hrec.bid = branch;
628
 
        hrec.tid = teller;
629
 
        hrec.amount = 10;
630
 
        /* Request 0 bytes since we're just positioning. */
631
 
        d_histdbt.flags = DB_DBT_PARTIAL;
632
 
 
633
 
        /* START TIMING */
634
 
        if (dbenv->txn_begin(dbenv, NULL, &t, 0) != 0)
635
 
                goto err;
636
 
 
637
 
        if (adb->cursor(adb, t, &acurs, 0) != 0 ||
638
 
            bdb->cursor(bdb, t, &bcurs, 0) != 0 ||
639
 
            tdb->cursor(tdb, t, &tcurs, 0) != 0)
640
 
                goto err;
641
 
 
642
 
        /* Account record */
643
 
        k_dbt.data = &account;
644
 
        if (acurs->c_get(acurs, &k_dbt, &d_dbt, DB_SET) != 0)
645
 
                goto err;
646
 
        rec.balance += 10;
647
 
        if (acurs->c_put(acurs, &k_dbt, &d_dbt, DB_CURRENT) != 0)
648
 
                goto err;
649
 
 
650
 
        /* Branch record */
651
 
        k_dbt.data = &branch;
652
 
        if (bcurs->c_get(bcurs, &k_dbt, &d_dbt, DB_SET) != 0)
653
 
                goto err;
654
 
        rec.balance += 10;
655
 
        if (bcurs->c_put(bcurs, &k_dbt, &d_dbt, DB_CURRENT) != 0)
656
 
                goto err;
657
 
 
658
 
        /* Teller record */
659
 
        k_dbt.data = &teller;
660
 
        if (tcurs->c_get(tcurs, &k_dbt, &d_dbt, DB_SET) != 0)
661
 
                goto err;
662
 
        rec.balance += 10;
663
 
        if (tcurs->c_put(tcurs, &k_dbt, &d_dbt, DB_CURRENT) != 0)
664
 
                goto err;
665
 
 
666
 
        /* History record */
667
 
        d_histdbt.flags = 0;
668
 
        d_histdbt.data = &hrec;
669
 
        d_histdbt.ulen = sizeof(hrec);
670
 
        if (hdb->put(hdb, t, &k_histdbt, &d_histdbt, DB_APPEND) != 0)
671
 
                goto err;
672
 
 
673
 
        if (acurs->c_close(acurs) != 0 || bcurs->c_close(bcurs) != 0 ||
674
 
            tcurs->c_close(tcurs) != 0)
675
 
                goto err;
676
 
 
677
 
        ret = t->commit(t, 0);
678
 
        t = NULL;
679
 
        if (ret != 0)
680
 
                goto err;
681
 
 
682
 
        /* END TIMING */
683
 
        return (0);
684
 
 
685
 
err:    if (acurs != NULL)
686
 
                (void)acurs->c_close(acurs);
687
 
        if (bcurs != NULL)
688
 
                (void)bcurs->c_close(bcurs);
689
 
        if (tcurs != NULL)
690
 
                (void)tcurs->c_close(tcurs);
691
 
        if (t != NULL)
692
 
                (void)t->abort(t);
693
 
 
694
 
        if (verbose)
695
 
                printf("Transaction A=%ld B=%ld T=%ld failed\n",
696
 
                    (long)account, (long)branch, (long)teller);
697
 
        return (-1);
698
 
}