1m4_ignore([dnl
2#include <sys/types.h>
3
4#include <errno.h>
5#include <stdlib.h>
6#include <string.h>
7
8#include <db.h>
9
10#define	DATABASE "access.db"
11#define	WORDLIST "../test/wordlist"
12
13int	rec_display __P((DB *));
14
15int
16main()
17{
18	DB *dbp;
19	DBT key, data;
20	FILE *fp;
21	u_int32_t len;
22	int cnt, ret;
23	char *p, *t, buf[1024], rbuf[1024];
24	const char *progname = "ex_access";		/* Program name. */
25
26	/* Open the word database. */
27	if ((fp = fopen(WORDLIST, "r")) == NULL) {
28		fprintf(stderr, "%s: open %s: %s\n",
29		    progname, WORDLIST, db_strerror(errno));
30		return (1);
31	}
32
33	/* Remove the previous database. */
34	(void)remove(DATABASE);
35
36	/* Create and initialize database object, open the database. */
37	if ((ret = db_create(&dbp, NULL, 0)) != 0) {
38		fprintf(stderr,
39		    "%s: db_create: %s\n", progname, db_strerror(ret));
40		return (1);
41	}
42	dbp->set_errfile(dbp, stderr);
43	dbp->set_errpfx(dbp, progname);
44	if ((ret = dbp->set_pagesize(dbp, 1024)) != 0) {
45		dbp->err(dbp, ret, "set_pagesize");
46		return (1);
47	}
48	if ((ret = dbp->set_cachesize(dbp, 0, 32 * 1024, 0)) != 0) {
49		dbp->err(dbp, ret, "set_cachesize");
50		return (1);
51	}
52	if ((ret = dbp->open(dbp,
53	    NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
54		dbp->err(dbp, ret, "%s: open", DATABASE);
55		return (1);
56	}
57
58	/*
59	 * Insert records into the database, where the key is the word
60	 * preceded by its record number, and the data is the same, but
61	 * in reverse order.
62	 */
63	memset(&key, 0, sizeof(DBT));
64	memset(&data, 0, sizeof(DBT));
65	for (cnt = 1; cnt <= 1000; ++cnt) {
66		(void)sprintf(buf, "%04d_", cnt);
67		if (fgets(buf + 4, sizeof(buf) - 4, fp) == NULL)
68			break;
69		len = strlen(buf);
70		for (t = rbuf, p = buf + (len - 2); p >= buf;)
71			*t++ = *p--;
72		*t++ = '\0';
73
74		key.data = buf;
75		data.data = rbuf;
76		data.size = key.size = len - 1;
77
78		if ((ret =
79		    dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE)) != 0) {
80			dbp->err(dbp, ret, "DB->put");
81			if (ret != DB_KEYEXIST)
82				return (1);
83		}
84	}
85
86	/* Close the word database. */
87	(void)fclose(fp);
88
89	rec_display(dbp);
90
91	return (0);
92}])
93m4_indent([dnl
94int
95rec_display(dbp)
96	DB *dbp;
97{
98	DBC *dbcp;
99	DBT key, data;
100	size_t retklen, retdlen;
101	char *retkey, *retdata;
102	int ret, t_ret;
103	void *p;
104m4_blank
105	memset(&key, 0, sizeof(key));
106	memset(&data, 0, sizeof(data));
107m4_blank
108	/* Review the database in 5MB chunks. */
109#define	BUFFER_LENGTH	(5 * 1024 * 1024)
110	if ((data.data = malloc(BUFFER_LENGTH)) == NULL)
111		return (errno);
112	data.ulen = BUFFER_LENGTH;
113	data.flags = DB_DBT_USERMEM;
114m4_blank
115	/* Acquire a cursor for the database. */
116	if ((ret = dbp-__GT__cursor(dbp, NULL, &dbcp, 0)) != 0) {
117		dbp-__GT__err(dbp, ret, "DB-__GT__cursor");
118		free(data.data);
119		return (ret);
120	}
121m4_blank
122	for (;;) {
123		/*
124		 * Acquire the next set of key/data pairs.  This code does
125		 * not handle single key/data pairs that won't fit in a
126		 * BUFFER_LENGTH size buffer, instead returning DB_BUFFER_SMALL
127		 * to our caller.
128		 */
129		if ((ret = dbcp-__GT__c_get(dbcp,
130		    &key, &data, DB_MULTIPLE_KEY | DB_NEXT)) != 0) {
131			if (ret != DB_NOTFOUND)
132				dbp-__GT__err(dbp, ret, "DBcursor-__GT__c_get");
133			break;
134		}
135m4_blank
136		for (DB_MULTIPLE_INIT(p, &data);;) {
137			DB_MULTIPLE_KEY_NEXT(p,
138			    &data, retkey, retklen, retdata, retdlen);
139			if (p == NULL)
140				break;
141			printf("key: %.*s, data: %.*s\n",
142			    (int)retklen, retkey, (int)retdlen, retdata);
143		}
144	}
145m4_blank
146	if ((t_ret = dbcp-__GT__c_close(dbcp)) != 0) {
147		dbp-__GT__err(dbp, ret, "DBcursor-__GT__close");
148		if (ret == 0)
149			ret = t_ret;
150	}
151m4_blank
152	free(data.data);
153m4_blank
154	return (ret);
155}])
156