1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2000, 2013 Oracle and/or its affiliates.  All rights reserved.
5  *
6  * $Id$
7  */
8 
9 #include "db_config.h"
10 
11 #include "db_int.h"
12 #include "dbinc/db_page.h"
13 #include "dbinc/db_am.h"
14 #include "dbinc/mp.h"
15 #include "dbinc/partition.h"
16 #include "dbinc/qam.h"
17 
18 static int __env_lsn_reset __P((ENV *, DB_THREAD_INFO *, const char *, int));
19 
20 /*
21  * __env_lsn_reset_pp --
22  *	ENV->lsn_reset pre/post processing.
23  *
24  * PUBLIC: int __env_lsn_reset_pp __P((DB_ENV *, const char *, u_int32_t));
25  */
26 int
__env_lsn_reset_pp(dbenv,name,flags)27 __env_lsn_reset_pp(dbenv, name, flags)
28 	DB_ENV *dbenv;
29 	const char *name;
30 	u_int32_t flags;
31 {
32 	DB_THREAD_INFO *ip;
33 	ENV *env;
34 	int ret;
35 
36 	env = dbenv->env;
37 
38 	ENV_ILLEGAL_BEFORE_OPEN(env, "DB_ENV->lsn_reset");
39 
40 	/*
41 	 * !!!
42 	 * The actual argument checking is simple, do it inline, outside of
43 	 * the replication block.
44 	 */
45 	if (flags != 0 && flags != DB_ENCRYPT)
46 		return (__db_ferr(env, "DB_ENV->lsn_reset", 0));
47 
48 	ENV_ENTER(env, ip);
49 	REPLICATION_WRAP(env,
50 	    (__env_lsn_reset(env, ip, name, LF_ISSET(DB_ENCRYPT) ? 1 : 0)),
51 	    1, ret);
52 	ENV_LEAVE(env, ip);
53 	return (ret);
54 }
55 
56 /*
57  * __env_lsn_reset --
58  *	Reset the LSNs for every page in the file.
59  */
60 static int
__env_lsn_reset(env,ip,name,encrypted)61 __env_lsn_reset(env, ip, name, encrypted)
62 	ENV *env;
63 	DB_THREAD_INFO *ip;
64 	const char *name;
65 	int encrypted;
66 {
67 	DB *dbp;
68 	int t_ret, ret;
69 
70 	/* Create the DB object. */
71 	if ((ret = __db_create_internal(&dbp, env, 0)) != 0)
72 		return (ret);
73 
74 	/* If configured with a password, the databases are encrypted. */
75 	if (encrypted && (ret = __db_set_flags(dbp, DB_ENCRYPT)) != 0)
76 		goto err;
77 
78 	/*
79 	 * Open the DB file.
80 	 *
81 	 * !!!
82 	 * Note DB_RDWRMASTER flag, we need to open the master database file
83 	 * for writing in this case.
84 	 */
85 	if ((ret = __db_open(dbp, ip, NULL,
86 	    name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0, PGNO_BASE_MD)) != 0) {
87 		__db_err(env, ret, "%s", name);
88 		goto err;
89 	}
90 
91 	ret = __db_lsn_reset(dbp->mpf, ip);
92 #ifdef HAVE_PARTITION
93 	if (ret == 0 && DB_IS_PARTITIONED(dbp))
94 		ret = __part_lsn_reset(dbp, ip);
95 	else
96 #endif
97 	if (ret == 0 && dbp->type == DB_QUEUE)
98 #ifdef HAVE_QUEUE
99 		ret = __qam_lsn_reset(dbp, ip);
100 #else
101 		ret = __db_no_queue_am(env);
102 #endif
103 
104 err:	if ((t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0)
105 		ret = t_ret;
106 	return (ret);
107 }
108 
109 /*
110  * __db_lsn_reset -- reset the lsn for a db mpool handle.
111  * PUBLIC: int __db_lsn_reset __P((DB_MPOOLFILE *, DB_THREAD_INFO *));
112  */
113 int
__db_lsn_reset(mpf,ip)114 __db_lsn_reset(mpf, ip)
115 	DB_MPOOLFILE *mpf;
116 	DB_THREAD_INFO *ip;
117 {
118 	PAGE *pagep;
119 	db_pgno_t pgno;
120 	int ret;
121 
122 	/* Reset the LSN on every page of the database file. */
123 	for (pgno = 0;
124 	    (ret = __memp_fget(mpf,
125 	    &pgno, ip, NULL, DB_MPOOL_DIRTY, &pagep)) == 0;
126 	    ++pgno) {
127 		LSN_NOT_LOGGED(pagep->lsn);
128 		if ((ret = __memp_fput(mpf,
129 		    ip, pagep, DB_PRIORITY_UNCHANGED)) != 0)
130 			break;
131 	}
132 
133 	if (ret == DB_PAGE_NOTFOUND)
134 		ret = 0;
135 
136 	return (ret);
137 }
138