1/*
2 * $Id: b_put.c,v 1.15 2008/01/31 17:01:22 bostic Exp $
3 */
4#include "bench.h"
5
6static int usage(void);
7static int b_put_secondary(DB *, const DBT *, const DBT *, DBT *);
8
9int
10b_put(int argc, char *argv[])
11{
12	extern char *optarg;
13	extern int optind;
14	DB_ENV *dbenv;
15	DB *dbp, **second;
16	DBTYPE type;
17	DBT key, data;
18	db_recno_t recno;
19	u_int32_t cachesize;
20	int ch, dsize, i, count, secondaries;
21	char *ts, buf[64];
22
23	second = NULL;
24	type = DB_BTREE;
25	cachesize = MEGABYTE;
26	dsize = 20;
27	count = 100000;
28	secondaries = 0;
29	ts = "Btree";
30	while ((ch = getopt(argc, argv, "C:c:d:s:t:")) != 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			dsize = atoi(optarg);
40			break;
41		case 's':
42			secondaries = atoi(optarg);
43			break;
44		case 't':
45			switch (optarg[0]) {
46			case 'B': case 'b':
47				ts = "Btree";
48				type = DB_BTREE;
49				break;
50			case 'H': case 'h':
51				if (b_util_have_hash())
52					return (0);
53				ts = "Hash";
54				type = DB_HASH;
55				break;
56			case 'Q': case 'q':
57				if (b_util_have_queue())
58					return (0);
59				ts = "Queue";
60				type = DB_QUEUE;
61				break;
62			case 'R': case 'r':
63				ts = "Recno";
64				type = DB_RECNO;
65				break;
66			default:
67				return (usage());
68			}
69			break;
70		case '?':
71		default:
72			return (usage());
73		}
74	argc -= optind;
75	argv += optind;
76	if (argc != 0)
77		return (usage());
78
79#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 3
80	/*
81	 * Secondaries were added after DB 3.2.9.
82	 */
83	if (secondaries)
84		return (0);
85#endif
86
87	/* Create the environment. */
88	DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
89	dbenv->set_errfile(dbenv, stderr);
90	DB_BENCH_ASSERT(dbenv->set_cachesize(dbenv, 0, cachesize, 0) == 0);
91#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 1
92	DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
93	    NULL, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
94#else
95	DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
96	    DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
97#endif
98
99	/*
100	 * Create the database.
101	 * Optionally set the record length for Queue.
102	 */
103	DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
104	if (type == DB_QUEUE)
105		DB_BENCH_ASSERT(dbp->set_re_len(dbp, (u_int32_t)dsize) == 0);
106#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
107	DB_BENCH_ASSERT(
108	    dbp->open(dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
109#else
110	DB_BENCH_ASSERT(
111	    dbp->open(dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
112#endif
113
114	/* Optionally create the secondaries. */
115	if (secondaries != 0) {
116		DB_BENCH_ASSERT((second =
117		    calloc(sizeof(DB *), (size_t)secondaries)) != NULL);
118		for (i = 0; i < secondaries; ++i) {
119			DB_BENCH_ASSERT(db_create(&second[i], dbenv, 0) == 0);
120			snprintf(buf, sizeof(buf), "%d.db", i);
121#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
122			DB_BENCH_ASSERT(second[i]->open(second[i], NULL,
123			    buf, NULL, DB_BTREE, DB_CREATE, 0600) == 0);
124#else
125			DB_BENCH_ASSERT(second[i]->open(second[i],
126			    buf, NULL, DB_BTREE, DB_CREATE, 0600) == 0);
127#endif
128#if DB_VERSION_MAJOR > 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 3
129#if DB_VERSION_MAJOR > 3 && DB_VERSION_MINOR > 0
130			/*
131			 * The DB_TXN argument to Db.associate was added in
132			 * 4.1.25.
133			 */
134			DB_BENCH_ASSERT(dbp->associate(
135			    dbp, NULL, second[i], b_put_secondary, 0) == 0);
136#else
137			DB_BENCH_ASSERT(dbp->associate(
138			    dbp, second[i], b_put_secondary, 0) == 0);
139#endif
140#endif
141		}
142	}
143
144	/* Store a key/data pair. */
145	memset(&key, 0, sizeof(key));
146	memset(&data, 0, sizeof(data));
147	switch (type) {
148	case DB_BTREE:
149	case DB_HASH:
150		key.data = "01234567890123456789";
151		key.size = 20;
152		break;
153	case DB_QUEUE:
154	case DB_RECNO:
155		recno = 1;
156		key.data = &recno;
157		key.size = sizeof(recno);
158		break;
159	case DB_UNKNOWN:
160		b_util_abort();
161		break;
162	}
163
164	DB_BENCH_ASSERT(
165	    (data.data = malloc(data.size = (size_t)dsize)) != NULL);
166
167	/* Store the key/data pair count times. */
168	TIMER_START;
169	for (i = 0; i < count; ++i)
170		DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
171	TIMER_STOP;
172
173	if (type == DB_BTREE || type == DB_HASH)
174		printf(
175		    "# %d %s database put of 10 byte key, %lu byte data",
176		    count, ts, (u_long)dsize);
177	else
178		printf("# %d %s database put of key, %lu byte data",
179		    count, ts, (u_long)dsize);
180	if (secondaries)
181		printf(" with %d secondaries", secondaries);
182	printf("\n");
183	TIMER_DISPLAY(count);
184
185	if (second != NULL) {
186		for (i = 0; i < secondaries; ++i)
187			DB_BENCH_ASSERT(second[i]->close(second[i], 0) == 0);
188		free(second);
189	}
190
191	DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
192	DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
193
194	return (0);
195}
196
197static int
198b_put_secondary(dbp, pkey, pdata, skey)
199	DB *dbp;
200	const DBT *pkey, *pdata;
201	DBT *skey;
202{
203	skey->data = pkey->data;
204	skey->size = pkey->size;
205
206	COMPQUIET(dbp, NULL);
207	COMPQUIET(pdata, NULL);
208	return (0);
209}
210
211static int
212usage()
213{
214	(void)fprintf(stderr, "usage: b_put %s\n",
215	    "[-C cachesz] [-c count] [-d bytes] [-s secondaries] [-t type]");
216	return (EXIT_FAILURE);
217}
218