1 /* tool/tlspool_dbrecovery.c -- Run database recovery
3 * When BerkeleyDB returns DB_RUNRECOVERY, it requires explicit attention to
4 * recovery of its database(s). This program does just that.
6 * NOTE: This is a skeleton, but the recover() procedure is empty. It has
7 * been stated that BerkeleyDB does "normal recovery" on every open, which
8 * works especially well on the first DB->open() call with no contenders
9 * left. For "catastrophic recovery", pre-existing backups are needed.
10 * For this reason, the program is not built, even if included in the sources.
12 * http://docs.oracle.com/cd/E17076_04/html/gsg_txn/C/recovery.html
14 * From: Rick van Rein <rick@openfortress.nl>
23 #include <sys/types.h>
31 #include <tlspool/internal.h>
34 const char const *usage =
35 "Usage: %s tlspool.conf [--db localid] [--db disclose] [--db trust]\n"
36 " Where one or more --db options indicate the databases to recover.\n"
37 " Without such options, all database in tlspool.conf are recovered.\n";
40 /* Setup and tear down management */
41 int setup_management (DB_ENV **dbenv, DB_TXN **txn) {
42 char *dbenv_dir = cfg_dbenv_dir ();
43 char *dblid_fnm = cfg_db_localid ();
44 if (dbenv_dir == NULL) {
45 fprintf (stderr, "Please configure database environment directory\n");
48 if (dblid_fnm == NULL) {
49 fprintf (stderr, "Please configure localid database name\n");
52 if (db_env_create (dbenv, 0) != 0) {
53 fprintf (stderr, "Failed to create database environment");
56 if ((*dbenv)->open (*dbenv, dbenv_dir, DB_CREATE | DB_RECOVER | DB_INIT_TXN | DB_INIT_LOG | DB_INIT_LOCK | DB_THREAD | DB_INIT_MPOOL, S_IRUSR | S_IWUSR) != 0) {
57 fprintf (stderr, "Failed to open database environment");
60 if ((*dbenv)->txn_begin (*dbenv, NULL, txn, 0) != 0) {
61 fprintf (stderr, "Failed to start transaction\n");
67 int open_database (char *dbname, DB_ENV *dbenv, DB_TXN *txn, DB **dbh) {
68 if (db_create (dbh, *dbenv, 0) != 0) {
69 fprintf (stderr, "Failed to create %s database\n", dbname);
72 if ((*dbh)->set_flags (*dbh, DB_DUP) != 0) {
73 fprintf (stderr, "Failed to setup %s database for duplicate entries\n", dbname);
76 if ((*dbh)->open (*dbh, *txn, dbname, NULL, DB_HASH, DB_THREAD, 0) != 0) {
77 fprintf (stderr, "Failed to open %s database\n", dbname);
83 /* Close the database */
84 void close_database (DB *db) {
88 /* Cleanup maangement structures */
89 void cleanup_management (DB_ENV *dbenv) {
90 dbenv->close (dbenv, 0);
93 /* See if the given database name is wanted for recovery */
94 int wanted (int argc_opt, char *argv_opt [], char *dbkwd) {
98 while (argc_opt-- > 0) {
99 if ((argv_opt [argc_opt][0] == '-') && (argv_opt [argc_opt][1] == '-') && (strcmp (argv_opt [argc_opt] + 2, dbkwd) == )) {
107 /* Recover a named database */
108 void recover (int argc_opt, char *argv_opt [], char *dbkwd, char *dbfname) {
109 if (wanted (argc_opt, argv_opt, dbkwd)) {
110 dbenv->lsn_reset (dbenv, dbfname, 0);
114 int main (int argc, char *argv []) {
115 char *dbenvdir = NULL;
116 char *dbfname = NULL;
117 int argc_opt = argc - 2;
118 char *argv_opt = argv + 2;
125 fprintf (stderr, usage, argv [0]);
129 fprintf (stderr, "This is an interactive command. Please run it in a terminal.\n");
133 // Initialise the modules taken from the src directory
134 dbenvdir = tlspool_configvar (NULL, "dbenv_dir");
135 if (dbenvdir == NULL) {
136 fprintf (stderr, "Missing variable \"dbenv_dir\" in %s\n", argv [1]);
140 // Check if database file names are provided, and print them
141 printf ("Preparing to recover the following database structures:\n");
142 printf (" * Database environment, directory %s\n", dbenvdir);
143 if (wanted (argc_opt, argv_opt, "localid")) {
144 dbfname = cfg_db_localid ();
148 if (dbfname != NULL) {
149 printf " * Local identity database, file %s/%s\n", dbenvdir, dbfname);
151 if (wanted (argc_opt, argv_opt, "disclose")) {
152 dbfname = cfg_db_disclose ();
156 if (dbfname != NULL) {
157 printf " * Disclosure database, file %s/%s\n", dbenvdir, dbfname);
159 if (wanted (argc_opt, argv_opt, "trust")) {
160 dbfname = cfg_db_trust ();
164 if (dbfname != NULL) {
165 printf " * Trust anchor database, file %s/%s\n", dbenvdir, dbfname);
168 // Ask for confirmation
169 printf ("\nNote well:\n");
170 printf (" * Other programs should not access the database at during recovery\n");
171 printf (" * This program makes no backups; you could still do this now\n");
172 printf ("\nEnter \"yes\" to confirm: ");
173 if (fgets (inbuf, sizeof (inbuf) - 1, stdin)) {
174 if (strncmp (inbuf, "yes\n") != 0) {
175 fprintf (stderr, "Aborting, as requested. Nothing has been done to the databases.\n");
181 printf ("\nConfirmation accepted. Recovering:\n");
183 if (!setup_management (&dbenv, &txn)) {
186 recover (argc_opt, argv_opt, "localid", cfg_db_localid ());
187 recover (argc_opt, argv_opt, "disclose", cfg_db_disclose ());
188 recover (argc_opt, argv_opt, "trust", cfg_db_trust ());
191 printf ("\nIf you are happy with the foregoing, we can commit the change.\n");
192 printf ("\nEnter \"yes\" to confirm: ");
193 if (fgets (inbuf, sizeof (inbuf) - 1, stdin)) {
194 if (strncmp (inbuf, "yes\n") != 0) {
195 fprintf (stderr, "Aborting, as requested. Nothing has been done to the databases.\n");
196 if (txn->abort (txn) != 0) {
197 fprintf (stderr, "Transaction abort returned an error\n");
202 if (txn->commit (txn, 0) != 0) {
204 fprintf (stderr, "Failed to commit transaction\n");
207 fprintf (stderr, "Committed transaction\n");
210 // Finish up and report success
212 cleanup_management (dbenv);
215 // Handle failure during database interactions
217 fprintf (stderr, "Rolling back transaction\n");
219 cleanup_management (dbenv);