• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/db-4.7.25.NC/examples_c/csv/
1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2005,2008 Oracle.  All rights reserved.
5 *
6 * $Id: db.c,v 1.18 2008/01/08 20:58:23 bostic Exp $
7 */
8
9#include "csv.h"
10#include "csv_local.h"
11#include "csv_extern.h"
12
13static int compare_uint32(DB *, const DBT *, const DBT *);
14
15/*
16 * csv_env_init --
17 *	Initialize the database environment.
18 */
19int
20csv_env_open(const char *home, int is_rdonly)
21{
22	int ret;
23
24	dbenv = NULL;
25	db = NULL;
26
27	/* Create a database environment handle. */
28	if ((ret = db_env_create(&dbenv, 0)) != 0) {
29		fprintf(stderr,
30		    "%s: db_env_create: %s\n", progname, db_strerror(ret));
31		return (1);
32	}
33
34	/*
35	 * Configure Berkeley DB error reporting to stderr, with our program
36	 * name as the prefix.
37	 */
38	dbenv->set_errfile(dbenv, stderr);
39	dbenv->set_errpfx(dbenv, progname);
40
41	/*
42	 * The default Berkeley DB cache size is fairly small; configure a
43	 * 1MB cache for now.  This value will require tuning in the future.
44	 */
45	if ((ret = dbenv->set_cachesize(dbenv, 0, 1048576, 1)) != 0) {
46		dbenv->err(dbenv, ret, "DB_ENV->set_cachesize");
47		return (1);
48	}
49
50	/*
51	 * We may be working with an existing environment -- try and join it.
52	 * If that fails, create a new database environment; for now, we only
53	 * need a cache, no logging, locking, or transactions.
54	 */
55	if ((ret = dbenv->open(dbenv, home,
56	    DB_JOINENV | DB_USE_ENVIRON, 0)) != 0 &&
57	    (ret = dbenv->open(dbenv, home,
58	    DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) != 0) {
59		dbenv->err(dbenv, ret, "DB_ENV->open");
60		return (1);
61	}
62
63	/* Create the primary database handle. */
64	if ((ret = db_create(&db, dbenv, 0)) != 0) {
65		dbenv->err(dbenv, ret, "db_create");
66		return (1);
67	}
68
69	/*
70	 * Records may be relatively large -- use a large page size.
71	 */
72	if ((ret = db->set_pagesize(db, 32 * 1024)) != 0) {
73		dbenv->err(dbenv, ret, "DB->set_pagesize");
74		return (1);
75	}
76
77	/*
78	 * The primary database uses an integer as its key; on little-endian
79	 * machines, integers sort badly using the default Berkeley DB sort
80	 * function (which is lexicographic).  Specify a comparison function
81	 * for the database.
82	 */
83	if ((ret = db->set_bt_compare(db, compare_uint32)) != 0) {
84		dbenv->err(dbenv, ret, "DB->set_bt_compare");
85		return (1);
86	}
87
88	/* Open the primary database. */
89	if ((ret = db->open(db, NULL,
90	    "primary", NULL, DB_BTREE, is_rdonly ? 0 : DB_CREATE, 0)) != 0) {
91		dbenv->err(dbenv, ret, "DB->open: primary");
92		return (1);
93	}
94
95	/* Open the secondaries.  */
96	if ((ret = csv_secondary_open()) != 0)
97		return (1);
98
99	return (0);
100}
101
102/*
103 * csv_env_close --
104 *	Discard the database environment.
105 */
106int
107csv_env_close()
108{
109	int ret, t_ret;
110
111	ret = 0;
112
113	/* Close the secondaries. */
114	ret = csv_secondary_close();
115
116	/* Close the primary handle. */
117	if (db != NULL && (t_ret = db->close(db, 0)) != 0) {
118		dbenv->err(dbenv, ret, "DB->close");
119		if (ret == 0)
120			ret = t_ret;
121	}
122	if ((t_ret = dbenv->close(dbenv, 0)) != 0) {
123		fprintf(stderr,
124		    "%s: DB_ENV->close: %s\n", progname, db_strerror(ret));
125		if (ret == 0)
126			ret = t_ret;
127	}
128
129	return (ret);
130}
131
132/*
133 * csv_secondary_open --
134 *	Open any secondary indices.
135 */
136int
137csv_secondary_open()
138{
139	DB *sdb;
140	DbField *f;
141	int ret, (*fcmp)(DB *, const DBT *, const DBT *);
142
143	/*
144	 * Create secondary database handles.
145	 */
146	for (f = fieldlist; f->name != NULL; ++f) {
147		if (f->indx == 0)
148			continue;
149
150		if ((ret = db_create(&sdb, dbenv, 0)) != 0) {
151			dbenv->err(dbenv, ret, "db_create");
152			return (1);
153		}
154		sdb->app_private = f;
155
156		/* Keys are small, use a relatively small page size. */
157		if ((ret = sdb->set_pagesize(sdb, 8 * 1024)) != 0) {
158			dbenv->err(dbenv, ret, "DB->set_pagesize");
159			return (1);
160		}
161
162		/*
163		 * Sort the database based on the underlying type.  Skip
164		 * strings, Berkeley DB defaults to lexicographic sort.
165		 */
166		switch (f->type) {
167		case DOUBLE:
168			fcmp = compare_double;
169			break;
170		case UNSIGNED_LONG:
171			fcmp = compare_ulong;
172			break;
173		case NOTSET:
174		case STRING:
175		default:
176			fcmp = NULL;
177			break;
178		}
179		if (fcmp != NULL &&
180		    (ret = sdb->set_bt_compare(sdb, fcmp)) != 0) {
181			dbenv->err(dbenv, ret, "DB->set_bt_compare");
182			return (1);
183		}
184
185		/* Always configure secondaries for sorted duplicates. */
186		if ((ret = sdb->set_flags(sdb, DB_DUPSORT)) != 0) {
187			dbenv->err(dbenv, ret, "DB->set_flags");
188			return (1);
189		}
190		if ((ret = sdb->set_dup_compare(sdb, compare_ulong)) != 0) {
191			dbenv->err(dbenv, ret, "DB->set_dup_compare");
192			return (1);
193		}
194
195		if ((ret = sdb->open(
196		    sdb, NULL, f->name, NULL, DB_BTREE, DB_CREATE, 0)) != 0) {
197			dbenv->err(dbenv, ret, "DB->open: %s", f->name);
198			return (1);
199		}
200		if ((ret = sdb->associate(
201		    db, NULL, sdb, secondary_callback, DB_CREATE)) != 0) {
202			dbenv->err(dbenv, ret, "DB->set_associate");
203			return (1);
204		}
205		f->secondary = sdb;
206	}
207
208	return (0);
209}
210
211/*
212 * csv_secondary_close --
213 *	Close any secondary indices.
214 */
215int
216csv_secondary_close()
217{
218	DbField *f;
219	int ret, t_ret;
220
221	ret = 0;
222	for (f = fieldlist; f->name != NULL; ++f)
223		if (f->secondary != NULL && (t_ret =
224		    f->secondary->close(f->secondary, 0)) != 0 && ret == 0)
225			ret = t_ret;
226
227	return (ret);
228}
229
230/*
231 * compare_uint32 --
232 *	Compare two keys.
233 */
234static int
235compare_uint32(DB *db_arg, const DBT *a_arg, const DBT *b_arg)
236{
237	u_int32_t a, b;
238
239	db_arg = db_arg;			/* Quiet compiler. */
240
241	memcpy(&a, a_arg->data, sizeof(u_int32_t));
242	memcpy(&b, b_arg->data, sizeof(u_int32_t));
243	return (a > b ? 1 : ((a < b) ? -1 : 0));
244}
245