• 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/ex_apprec/
1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1996,2008 Oracle.  All rights reserved.
5 *
6 * $Id: ex_apprec.c,v 12.9 2008/04/16 13:27:33 margo Exp $
7 */
8
9#include <sys/types.h>
10#include <sys/stat.h>
11
12#include <errno.h>
13#include <stddef.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <unistd.h>
18
19#include "db_config.h"
20#include "db.h"
21#include "db_int.h"
22#include "dbinc/db_swap.h"
23
24#include "ex_apprec.h"
25
26int	apprec_dispatch __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
27int	open_env __P((const char *, FILE *, const char *, DB_ENV **));
28int	verify_absence __P((DB_ENV *, const char *));
29int	verify_presence __P((DB_ENV *, const char *));
30
31int
32main(argc, argv)
33	int argc;
34	char *argv[];
35{
36	extern char *optarg;
37	DB_ENV *dbenv;
38	DB_LSN lsn;
39	DB_TXN *txn;
40	DBT dirnamedbt;
41	int ret;
42	const char *home;
43	char ch, dirname[256];
44	const char *progname = "ex_apprec";		/* Program name. */
45
46	/* Default home. */
47	home = "TESTDIR";
48
49	while ((ch = getopt(argc, argv, "h:")) != EOF)
50		switch (ch) {
51		case 'h':
52			home = optarg;
53			break;
54		default:
55			fprintf(stderr, "usage: %s [-h home]", progname);
56			exit(EXIT_FAILURE);
57		}
58
59	printf("Set up environment.\n");
60	if ((ret = open_env(home, stderr, progname, &dbenv)) != 0)
61		return (EXIT_FAILURE);
62
63	printf("Create a directory in a transaction.\n");
64	/*
65	 * This application's convention is to log the full directory name,
66	 * including trailing nul.
67	 */
68	memset(&dirnamedbt, 0, sizeof(dirnamedbt));
69	sprintf(dirname, "%s/MYDIRECTORY", home);
70	dirnamedbt.data = dirname;
71	dirnamedbt.size = strlen(dirname) + 1;
72
73	if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0) {
74		dbenv->err(dbenv, ret, "txn_begin");
75		return (EXIT_FAILURE);
76	}
77
78	/*
79	 * Remember, always log actions before you execute them!
80	 * Since this log record is describing a file system operation and
81	 * we have no control over when file system operations go to disk,
82	 * we need to flush the log record immediately to ensure that the
83	 * log record is on disk before the operation it describes.  The
84	 * flush would not be necessary were we doing an operation into the
85	 * BDB mpool and using LSNs that mpool knew about.
86	 */
87	memset(&lsn, 0, sizeof(lsn));
88	if ((ret =
89	    ex_apprec_mkdir_log(dbenv,
90	        txn, &lsn, DB_FLUSH, &dirnamedbt)) != 0) {
91		dbenv->err(dbenv, ret, "mkdir_log");
92		return (EXIT_FAILURE);
93	}
94	if (mkdir(dirname, 0755) != 0) {
95		dbenv->err(dbenv, errno, "mkdir");
96		return (EXIT_FAILURE);
97	}
98
99	printf("Verify the directory's presence: ");
100	verify_presence(dbenv, dirname);
101	printf("check.\n");
102
103	/* Now abort the transaction and verify that the directory goes away. */
104	printf("Abort the transaction.\n");
105	if ((ret = txn->abort(txn)) != 0) {
106		dbenv->err(dbenv, ret, "txn_abort");
107		return (EXIT_FAILURE);
108	}
109
110	printf("Verify the directory's absence: ");
111	verify_absence(dbenv, dirname);
112	printf("check.\n");
113
114	/* Now do the same thing over again, only with a commit this time. */
115	printf("Create a directory in a transaction.\n");
116	memset(&dirnamedbt, 0, sizeof(dirnamedbt));
117	sprintf(dirname, "%s/MYDIRECTORY", home);
118	dirnamedbt.data = dirname;
119	dirnamedbt.size = strlen(dirname) + 1;
120	if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0) {
121		dbenv->err(dbenv, ret, "txn_begin");
122		return (EXIT_FAILURE);
123	}
124
125	memset(&lsn, 0, sizeof(lsn));
126	if ((ret =
127	    ex_apprec_mkdir_log(dbenv, txn, &lsn, 0, &dirnamedbt)) != 0) {
128		dbenv->err(dbenv, ret, "mkdir_log");
129		return (EXIT_FAILURE);
130	}
131	if (mkdir(dirname, 0755) != 0) {
132		dbenv->err(dbenv, errno, "mkdir");
133		return (EXIT_FAILURE);
134	}
135
136	printf("Verify the directory's presence: ");
137	verify_presence(dbenv, dirname);
138	printf("check.\n");
139
140	/* Now abort the transaction and verify that the directory goes away. */
141	printf("Commit the transaction.\n");
142	if ((ret = txn->commit(txn, 0)) != 0) {
143		dbenv->err(dbenv, ret, "txn_commit");
144		return (EXIT_FAILURE);
145	}
146
147	printf("Verify the directory's presence: ");
148	verify_presence(dbenv, dirname);
149	printf("check.\n");
150
151	printf("Now remove the directory, then run recovery.\n");
152	if ((ret = dbenv->close(dbenv, 0)) != 0) {
153		fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
154		return (EXIT_FAILURE);
155	}
156	if (rmdir(dirname) != 0) {
157		fprintf(stderr,
158		    "%s: rmdir failed with error %s", progname,
159		    strerror(errno));
160	}
161	verify_absence(dbenv, dirname);
162
163	/* Opening with DB_RECOVER runs recovery. */
164	if ((ret = open_env(home, stderr, progname, &dbenv)) != 0)
165		return (EXIT_FAILURE);
166
167	printf("Verify the directory's presence: ");
168	verify_presence(dbenv, dirname);
169	printf("check.\n");
170
171	/* Close the handle. */
172	if ((ret = dbenv->close(dbenv, 0)) != 0) {
173		fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
174		return (EXIT_FAILURE);
175	}
176
177	return (EXIT_SUCCESS);
178}
179
180int
181open_env(home, errfp, progname, dbenvp)
182	const char *home, *progname;
183	FILE *errfp;
184	DB_ENV **dbenvp;
185{
186	DB_ENV *dbenv;
187	int ret;
188
189	/*
190	 * Create an environment object and initialize it for error
191	 * reporting.
192	 */
193	if ((ret = db_env_create(&dbenv, 0)) != 0) {
194		fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
195		return (ret);
196	}
197	dbenv->set_errfile(dbenv, errfp);
198	dbenv->set_errpfx(dbenv, progname);
199
200	/* Set up our custom recovery dispatch function. */
201	if ((ret = dbenv->set_app_dispatch(dbenv, apprec_dispatch)) != 0) {
202		dbenv->err(dbenv, ret, "set_app_dispatch");
203		return (ret);
204	}
205
206	/*
207	 * Open the environment with full transactional support, running
208	 * recovery.
209	 */
210	if ((ret =
211	    dbenv->open(dbenv, home, DB_CREATE | DB_RECOVER | DB_INIT_LOCK |
212	    DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0)) != 0) {
213		dbenv->err(dbenv, ret, "environment open: %s", home);
214		dbenv->close(dbenv, 0);
215		return (ret);
216	}
217
218	*dbenvp = dbenv;
219	return (0);
220}
221
222/*
223 * Sample application dispatch function to handle user-specified log record
224 * types.
225 */
226int
227apprec_dispatch(dbenv, dbt, lsn, op)
228	DB_ENV *dbenv;
229	DBT *dbt;
230	DB_LSN *lsn;
231	db_recops op;
232{
233	u_int32_t rectype;
234
235	/* Pull the record type out of the log record. */
236	LOGCOPY_32(dbenv->env, &rectype, dbt->data);
237
238	switch (rectype) {
239	case DB_ex_apprec_mkdir:
240		return (ex_apprec_mkdir_recover(dbenv, dbt, lsn, op));
241	default:
242		/*
243		 * We've hit an unexpected, allegedly user-defined record
244		 * type.
245		 */
246		dbenv->errx(dbenv, "Unexpected log record type encountered");
247		return (EINVAL);
248	}
249}
250
251int
252verify_absence(dbenv, dirname)
253	DB_ENV *dbenv;
254	const char *dirname;
255{
256
257	if (access(dirname, F_OK) == 0) {
258		dbenv->errx(dbenv, "Error--directory present!");
259		exit(EXIT_FAILURE);
260	}
261
262	return (0);
263}
264
265int
266verify_presence(dbenv, dirname)
267	DB_ENV *dbenv;
268	const char *dirname;
269{
270
271	if (access(dirname, F_OK) != 0) {
272		dbenv->errx(dbenv, "Error--directory not present!");
273		exit(EXIT_FAILURE);
274	}
275
276	return (0);
277}
278