1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1997,2008 Oracle.  All rights reserved.
5 *
6 * $Id: AccessExample.cpp,v 12.6 2008/01/08 20:58:26 bostic Exp $
7 */
8
9#include <sys/types.h>
10
11#include <iostream>
12#include <iomanip>
13#include <errno.h>
14#include <stdlib.h>
15#include <string.h>
16
17#ifdef _WIN32
18extern "C" {
19  extern int getopt(int, char * const *, const char *);
20  extern int optind;
21}
22#else
23#include <unistd.h>
24#endif
25
26#include <db_cxx.h>
27
28#define	DATABASE	"access.db"
29
30using std::cin;
31using std::cout;
32using std::cerr;
33
34class AccessExample
35{
36public:
37	AccessExample();
38	void run(bool removeExistingDatabase, const char *fileName);
39
40private:
41	// no need for copy and assignment
42	AccessExample(const AccessExample &);
43	void operator = (const AccessExample &);
44};
45
46int
47usage()
48{
49	(void)fprintf(stderr, "usage: AccessExample [-r] [database]\n");
50	return (EXIT_FAILURE);
51}
52
53int
54main(int argc, char *argv[])
55{
56	int ch, rflag;
57	const char *database;
58
59	rflag = 0;
60	while ((ch = getopt(argc, argv, "r")) != EOF)
61		switch (ch) {
62		case 'r':
63			rflag = 1;
64			break;
65		case '?':
66		default:
67			return (usage());
68		}
69	argc -= optind;
70	argv += optind;
71
72	/* Accept optional database name. */
73	database = *argv == NULL ? DATABASE : argv[0];
74
75	// Use a try block just to report any errors.
76	// An alternate approach to using exceptions is to
77	// use error models (see DbEnv::set_error_model()) so
78	// that error codes are returned for all Berkeley DB methods.
79	//
80	try {
81		AccessExample app;
82		app.run((bool)(rflag == 1 ? true : false), database);
83		return (EXIT_SUCCESS);
84	}
85	catch (DbException &dbe) {
86		cerr << "AccessExample: " << dbe.what() << "\n";
87		return (EXIT_FAILURE);
88	}
89}
90
91AccessExample::AccessExample()
92{
93}
94
95void AccessExample::run(bool removeExistingDatabase, const char *fileName)
96{
97	// Remove the previous database.
98	if (removeExistingDatabase)
99		(void)remove(fileName);
100
101	// Create the database object.
102	// There is no environment for this simple example.
103	Db db(0, 0);
104
105	db.set_error_stream(&cerr);
106	db.set_errpfx("AccessExample");
107	db.set_pagesize(1024);		/* Page size: 1K. */
108	db.set_cachesize(0, 32 * 1024, 0);
109	db.open(NULL, fileName, NULL, DB_BTREE, DB_CREATE, 0664);
110
111	//
112	// Insert records into the database, where the key is the user
113	// input and the data is the user input in reverse order.
114	//
115	char buf[1024], rbuf[1024];
116	char *p, *t;
117	int ret;
118	u_int32_t len;
119
120	for (;;) {
121		cout << "input> ";
122		cout.flush();
123
124		cin.getline(buf, sizeof(buf));
125		if (cin.eof())
126			break;
127
128		if ((len = (u_int32_t)strlen(buf)) <= 0)
129			continue;
130		for (t = rbuf, p = buf + (len - 1); p >= buf;)
131			*t++ = *p--;
132		*t++ = '\0';
133
134		Dbt key(buf, len + 1);
135		Dbt data(rbuf, len + 1);
136
137		ret = db.put(0, &key, &data, DB_NOOVERWRITE);
138		if (ret == DB_KEYEXIST) {
139			cout << "Key " << buf << " already exists.\n";
140		}
141	}
142	cout << "\n";
143
144	// We put a try block around this section of code
145	// to ensure that our database is properly closed
146	// in the event of an error.
147	//
148	try {
149		// Acquire a cursor for the table.
150		Dbc *dbcp;
151		db.cursor(NULL, &dbcp, 0);
152
153		// Walk through the table, printing the key/data pairs.
154		Dbt key;
155		Dbt data;
156		while (dbcp->get(&key, &data, DB_NEXT) == 0) {
157			char *key_string = (char *)key.get_data();
158			char *data_string = (char *)data.get_data();
159			cout << key_string << " : " << data_string << "\n";
160		}
161		dbcp->close();
162	}
163	catch (DbException &dbe) {
164		cerr << "AccessExample: " << dbe.what() << "\n";
165	}
166
167	db.close(0);
168}
169