1*7c478bd9Sstevel@tonic-gate /*-
2*7c478bd9Sstevel@tonic-gate  * See the file LICENSE for redistribution information.
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1996, 1997, 1998
5*7c478bd9Sstevel@tonic-gate  *	Sleepycat Software.  All rights reserved.
6*7c478bd9Sstevel@tonic-gate  */
7*7c478bd9Sstevel@tonic-gate /*
8*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1995, 1996
9*7c478bd9Sstevel@tonic-gate  *	Margo Seltzer.  All rights reserved.
10*7c478bd9Sstevel@tonic-gate  */
11*7c478bd9Sstevel@tonic-gate /*
12*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1995, 1996
13*7c478bd9Sstevel@tonic-gate  *	The President and Fellows of Harvard University.  All rights reserved.
14*7c478bd9Sstevel@tonic-gate  *
15*7c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
16*7c478bd9Sstevel@tonic-gate  * Margo Seltzer.
17*7c478bd9Sstevel@tonic-gate  *
18*7c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
19*7c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
20*7c478bd9Sstevel@tonic-gate  * are met:
21*7c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
22*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
23*7c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
24*7c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
25*7c478bd9Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
26*7c478bd9Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
27*7c478bd9Sstevel@tonic-gate  *    must display the following acknowledgement:
28*7c478bd9Sstevel@tonic-gate  *	This product includes software developed by the University of
29*7c478bd9Sstevel@tonic-gate  *	California, Berkeley and its contributors.
30*7c478bd9Sstevel@tonic-gate  * 4. Neither the name of the University nor the names of its contributors
31*7c478bd9Sstevel@tonic-gate  *    may be used to endorse or promote products derived from this software
32*7c478bd9Sstevel@tonic-gate  *    without specific prior written permission.
33*7c478bd9Sstevel@tonic-gate  *
34*7c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
35*7c478bd9Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36*7c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37*7c478bd9Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38*7c478bd9Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39*7c478bd9Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40*7c478bd9Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41*7c478bd9Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42*7c478bd9Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43*7c478bd9Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44*7c478bd9Sstevel@tonic-gate  * SUCH DAMAGE.
45*7c478bd9Sstevel@tonic-gate  */
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate #include "config.h"
48*7c478bd9Sstevel@tonic-gate 
49*7c478bd9Sstevel@tonic-gate #ifndef lint
50*7c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)hash_rec.c	10.22 (Sleepycat) 10/21/98";
51*7c478bd9Sstevel@tonic-gate #endif /* not lint */
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate #ifndef NO_SYSTEM_INCLUDES
54*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate #include <errno.h>
57*7c478bd9Sstevel@tonic-gate #include <string.h>
58*7c478bd9Sstevel@tonic-gate #endif
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate #include "db_int.h"
61*7c478bd9Sstevel@tonic-gate #include "shqueue.h"
62*7c478bd9Sstevel@tonic-gate #include "db_page.h"
63*7c478bd9Sstevel@tonic-gate #include "hash.h"
64*7c478bd9Sstevel@tonic-gate #include "btree.h"
65*7c478bd9Sstevel@tonic-gate #include "log.h"
66*7c478bd9Sstevel@tonic-gate #include "common_ext.h"
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate /*
69*7c478bd9Sstevel@tonic-gate  * __ham_insdel_recover --
70*7c478bd9Sstevel@tonic-gate  *
71*7c478bd9Sstevel@tonic-gate  * PUBLIC: int __ham_insdel_recover
72*7c478bd9Sstevel@tonic-gate  * PUBLIC:     __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
73*7c478bd9Sstevel@tonic-gate  */
74*7c478bd9Sstevel@tonic-gate int
__ham_insdel_recover(logp,dbtp,lsnp,redo,info)75*7c478bd9Sstevel@tonic-gate __ham_insdel_recover(logp, dbtp, lsnp, redo, info)
76*7c478bd9Sstevel@tonic-gate 	DB_LOG *logp;
77*7c478bd9Sstevel@tonic-gate 	DBT *dbtp;
78*7c478bd9Sstevel@tonic-gate 	DB_LSN *lsnp;
79*7c478bd9Sstevel@tonic-gate 	int redo;
80*7c478bd9Sstevel@tonic-gate 	void *info;
81*7c478bd9Sstevel@tonic-gate {
82*7c478bd9Sstevel@tonic-gate 	__ham_insdel_args *argp;
83*7c478bd9Sstevel@tonic-gate 	DB *file_dbp;
84*7c478bd9Sstevel@tonic-gate 	DBC *dbc;
85*7c478bd9Sstevel@tonic-gate 	HASH_CURSOR *hcp;
86*7c478bd9Sstevel@tonic-gate 	DB_MPOOLFILE *mpf;
87*7c478bd9Sstevel@tonic-gate 	PAGE *pagep;
88*7c478bd9Sstevel@tonic-gate 	u_int32_t op;
89*7c478bd9Sstevel@tonic-gate 	int cmp_n, cmp_p, getmeta, ret;
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate 	getmeta = 0;
92*7c478bd9Sstevel@tonic-gate 	hcp = NULL;
93*7c478bd9Sstevel@tonic-gate 	REC_PRINT(__ham_insdel_print);
94*7c478bd9Sstevel@tonic-gate 	REC_INTRO(__ham_insdel_read);
95*7c478bd9Sstevel@tonic-gate 	hcp = (HASH_CURSOR *)dbc->internal;
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 	ret = memp_fget(mpf, &argp->pgno, 0, &pagep);
98*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
99*7c478bd9Sstevel@tonic-gate 		if (!redo) {
100*7c478bd9Sstevel@tonic-gate 			/*
101*7c478bd9Sstevel@tonic-gate 			 * We are undoing and the page doesn't exist.  That
102*7c478bd9Sstevel@tonic-gate 			 * is equivalent to having a pagelsn of 0, so we
103*7c478bd9Sstevel@tonic-gate 			 * would not have to undo anything.  In this case,
104*7c478bd9Sstevel@tonic-gate 			 * don't bother creating a page.
105*7c478bd9Sstevel@tonic-gate 			 */
106*7c478bd9Sstevel@tonic-gate 			goto done;
107*7c478bd9Sstevel@tonic-gate 		} else if ((ret = memp_fget(mpf, &argp->pgno,
108*7c478bd9Sstevel@tonic-gate 		    DB_MPOOL_CREATE, &pagep)) != 0)
109*7c478bd9Sstevel@tonic-gate 			goto out;
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	GET_META(file_dbp, hcp, ret);
113*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
114*7c478bd9Sstevel@tonic-gate 		goto out;
115*7c478bd9Sstevel@tonic-gate 	getmeta = 1;
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 	cmp_n = log_compare(lsnp, &LSN(pagep));
118*7c478bd9Sstevel@tonic-gate 	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
119*7c478bd9Sstevel@tonic-gate 	/*
120*7c478bd9Sstevel@tonic-gate 	 * Two possible things going on:
121*7c478bd9Sstevel@tonic-gate 	 * redo a delete/undo a put: delete the item from the page.
122*7c478bd9Sstevel@tonic-gate 	 * redo a put/undo a delete: add the item to the page.
123*7c478bd9Sstevel@tonic-gate 	 * If we are undoing a delete, then the information logged is the
124*7c478bd9Sstevel@tonic-gate 	 * entire entry off the page, not just the data of a dbt.  In
125*7c478bd9Sstevel@tonic-gate 	 * this case, we want to copy it back onto the page verbatim.
126*7c478bd9Sstevel@tonic-gate 	 * We do this by calling __putitem with the type H_OFFPAGE instead
127*7c478bd9Sstevel@tonic-gate 	 * of H_KEYDATA.
128*7c478bd9Sstevel@tonic-gate 	 */
129*7c478bd9Sstevel@tonic-gate 	op = OPCODE_OF(argp->opcode);
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate 	if ((op == DELPAIR && cmp_n == 0 && !redo) ||
132*7c478bd9Sstevel@tonic-gate 	    (op == PUTPAIR && cmp_p == 0 && redo)) {
133*7c478bd9Sstevel@tonic-gate 		/*
134*7c478bd9Sstevel@tonic-gate 		 * Need to redo a PUT or undo a delete.  If we are undoing a
135*7c478bd9Sstevel@tonic-gate 		 * delete, we've got to restore the item back to its original
136*7c478bd9Sstevel@tonic-gate 		 * position.  That's a royal pain in the butt (because we do
137*7c478bd9Sstevel@tonic-gate 		 * not store item lengths on the page), but there's no choice.
138*7c478bd9Sstevel@tonic-gate 		 */
139*7c478bd9Sstevel@tonic-gate 		if (op != DELPAIR ||
140*7c478bd9Sstevel@tonic-gate 		    argp->ndx == (u_int32_t)H_NUMPAIRS(pagep)) {
141*7c478bd9Sstevel@tonic-gate 			__ham_putitem(pagep, &argp->key,
142*7c478bd9Sstevel@tonic-gate 			    !redo || PAIR_ISKEYBIG(argp->opcode) ?
143*7c478bd9Sstevel@tonic-gate 			    H_OFFPAGE : H_KEYDATA);
144*7c478bd9Sstevel@tonic-gate 			__ham_putitem(pagep, &argp->data,
145*7c478bd9Sstevel@tonic-gate 			    !redo || PAIR_ISDATABIG(argp->opcode) ?
146*7c478bd9Sstevel@tonic-gate 			    H_OFFPAGE : H_KEYDATA);
147*7c478bd9Sstevel@tonic-gate 		} else
148*7c478bd9Sstevel@tonic-gate 			(void) __ham_reputpair(pagep, hcp->hdr->pagesize,
149*7c478bd9Sstevel@tonic-gate 			    argp->ndx, &argp->key, &argp->data);
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = redo ? *lsnp : argp->pagelsn;
152*7c478bd9Sstevel@tonic-gate 		if ((ret = __ham_put_page(file_dbp, pagep, 1)) != 0)
153*7c478bd9Sstevel@tonic-gate 			goto out;
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate 	} else if ((op == DELPAIR && cmp_p == 0 && redo)
156*7c478bd9Sstevel@tonic-gate 	    || (op == PUTPAIR && cmp_n == 0 && !redo)) {
157*7c478bd9Sstevel@tonic-gate 		/* Need to undo a put or redo a delete. */
158*7c478bd9Sstevel@tonic-gate 		__ham_dpair(file_dbp, pagep, argp->ndx);
159*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = redo ? *lsnp : argp->pagelsn;
160*7c478bd9Sstevel@tonic-gate 		if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0)
161*7c478bd9Sstevel@tonic-gate 			goto out;
162*7c478bd9Sstevel@tonic-gate 	} else
163*7c478bd9Sstevel@tonic-gate 		if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0)
164*7c478bd9Sstevel@tonic-gate 			goto out;
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	/* Return the previous LSN. */
167*7c478bd9Sstevel@tonic-gate done:	*lsnp = argp->prev_lsn;
168*7c478bd9Sstevel@tonic-gate 	ret = 0;
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate out:	if (getmeta)
171*7c478bd9Sstevel@tonic-gate 		RELEASE_META(file_dbp, hcp);
172*7c478bd9Sstevel@tonic-gate 	REC_CLOSE;
173*7c478bd9Sstevel@tonic-gate }
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate /*
176*7c478bd9Sstevel@tonic-gate  * __ham_newpage_recover --
177*7c478bd9Sstevel@tonic-gate  *	This log message is used when we add/remove overflow pages.  This
178*7c478bd9Sstevel@tonic-gate  *	message takes care of the pointer chains, not the data on the pages.
179*7c478bd9Sstevel@tonic-gate  *
180*7c478bd9Sstevel@tonic-gate  * PUBLIC: int __ham_newpage_recover
181*7c478bd9Sstevel@tonic-gate  * PUBLIC:     __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
182*7c478bd9Sstevel@tonic-gate  */
183*7c478bd9Sstevel@tonic-gate int
__ham_newpage_recover(logp,dbtp,lsnp,redo,info)184*7c478bd9Sstevel@tonic-gate __ham_newpage_recover(logp, dbtp, lsnp, redo, info)
185*7c478bd9Sstevel@tonic-gate 	DB_LOG *logp;
186*7c478bd9Sstevel@tonic-gate 	DBT *dbtp;
187*7c478bd9Sstevel@tonic-gate 	DB_LSN *lsnp;
188*7c478bd9Sstevel@tonic-gate 	int redo;
189*7c478bd9Sstevel@tonic-gate 	void *info;
190*7c478bd9Sstevel@tonic-gate {
191*7c478bd9Sstevel@tonic-gate 	__ham_newpage_args *argp;
192*7c478bd9Sstevel@tonic-gate 	DB *file_dbp;
193*7c478bd9Sstevel@tonic-gate 	DBC *dbc;
194*7c478bd9Sstevel@tonic-gate 	HASH_CURSOR *hcp;
195*7c478bd9Sstevel@tonic-gate 	DB_MPOOLFILE *mpf;
196*7c478bd9Sstevel@tonic-gate 	PAGE *pagep;
197*7c478bd9Sstevel@tonic-gate 	int cmp_n, cmp_p, change, getmeta, ret;
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	getmeta = 0;
200*7c478bd9Sstevel@tonic-gate 	hcp = NULL;
201*7c478bd9Sstevel@tonic-gate 	REC_PRINT(__ham_newpage_print);
202*7c478bd9Sstevel@tonic-gate 	REC_INTRO(__ham_newpage_read);
203*7c478bd9Sstevel@tonic-gate 	hcp = (HASH_CURSOR *)dbc->internal;
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 	ret = memp_fget(mpf, &argp->new_pgno, 0, &pagep);
206*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
207*7c478bd9Sstevel@tonic-gate 		if (!redo) {
208*7c478bd9Sstevel@tonic-gate 			/*
209*7c478bd9Sstevel@tonic-gate 			 * We are undoing and the page doesn't exist.  That
210*7c478bd9Sstevel@tonic-gate 			 * is equivalent to having a pagelsn of 0, so we
211*7c478bd9Sstevel@tonic-gate 			 * would not have to undo anything.  In this case,
212*7c478bd9Sstevel@tonic-gate 			 * don't bother creating a page.
213*7c478bd9Sstevel@tonic-gate 			 */
214*7c478bd9Sstevel@tonic-gate 			ret = 0;
215*7c478bd9Sstevel@tonic-gate 			goto ppage;
216*7c478bd9Sstevel@tonic-gate 		} else if ((ret = memp_fget(mpf, &argp->new_pgno,
217*7c478bd9Sstevel@tonic-gate 		    DB_MPOOL_CREATE, &pagep)) != 0)
218*7c478bd9Sstevel@tonic-gate 			goto out;
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
221*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
222*7c478bd9Sstevel@tonic-gate 		goto out;
223*7c478bd9Sstevel@tonic-gate 	getmeta = 1;
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	/*
226*7c478bd9Sstevel@tonic-gate 	 * There are potentially three pages we need to check: the one
227*7c478bd9Sstevel@tonic-gate 	 * that we created/deleted, the one before it and the one after
228*7c478bd9Sstevel@tonic-gate 	 * it.
229*7c478bd9Sstevel@tonic-gate 	 */
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	cmp_n = log_compare(lsnp, &LSN(pagep));
232*7c478bd9Sstevel@tonic-gate 	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
233*7c478bd9Sstevel@tonic-gate 	change = 0;
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) ||
236*7c478bd9Sstevel@tonic-gate 	    (cmp_n == 0 && !redo && argp->opcode == DELOVFL)) {
237*7c478bd9Sstevel@tonic-gate 		/* Redo a create new page or undo a delete new page. */
238*7c478bd9Sstevel@tonic-gate 		P_INIT(pagep, file_dbp->pgsize, argp->new_pgno,
239*7c478bd9Sstevel@tonic-gate 		    argp->prev_pgno, argp->next_pgno, 0, P_HASH);
240*7c478bd9Sstevel@tonic-gate 		change = 1;
241*7c478bd9Sstevel@tonic-gate 	} else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) ||
242*7c478bd9Sstevel@tonic-gate 	    (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) {
243*7c478bd9Sstevel@tonic-gate 		/*
244*7c478bd9Sstevel@tonic-gate 		 * Redo a delete or undo a create new page.  All we
245*7c478bd9Sstevel@tonic-gate 		 * really need to do is change the LSN.
246*7c478bd9Sstevel@tonic-gate 		 */
247*7c478bd9Sstevel@tonic-gate 		change = 1;
248*7c478bd9Sstevel@tonic-gate 	}
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	if (!change) {
251*7c478bd9Sstevel@tonic-gate 		if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0)
252*7c478bd9Sstevel@tonic-gate 			goto out;
253*7c478bd9Sstevel@tonic-gate 	} else {
254*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = redo ? *lsnp : argp->pagelsn;
255*7c478bd9Sstevel@tonic-gate 		if ((ret = __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0)
256*7c478bd9Sstevel@tonic-gate 			goto out;
257*7c478bd9Sstevel@tonic-gate 	}
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate 	/* Now do the prev page. */
260*7c478bd9Sstevel@tonic-gate ppage:	if (argp->prev_pgno != PGNO_INVALID) {
261*7c478bd9Sstevel@tonic-gate 		ret = memp_fget(mpf, &argp->prev_pgno, 0, &pagep);
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 		if (ret != 0)
264*7c478bd9Sstevel@tonic-gate 			if (!redo) {
265*7c478bd9Sstevel@tonic-gate 				/*
266*7c478bd9Sstevel@tonic-gate 				 * We are undoing and the page doesn't exist.
267*7c478bd9Sstevel@tonic-gate 				 * That is equivalent to having a pagelsn of 0,
268*7c478bd9Sstevel@tonic-gate 				 * so we would not have to undo anything.  In
269*7c478bd9Sstevel@tonic-gate 				 * this case, don't bother creating a page.
270*7c478bd9Sstevel@tonic-gate 				 */
271*7c478bd9Sstevel@tonic-gate 				ret = 0;
272*7c478bd9Sstevel@tonic-gate 				goto npage;
273*7c478bd9Sstevel@tonic-gate 			} else if ((ret =
274*7c478bd9Sstevel@tonic-gate 			    memp_fget(mpf, &argp->prev_pgno,
275*7c478bd9Sstevel@tonic-gate 			    DB_MPOOL_CREATE, &pagep)) != 0)
276*7c478bd9Sstevel@tonic-gate 				goto out;
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 		cmp_n = log_compare(lsnp, &LSN(pagep));
279*7c478bd9Sstevel@tonic-gate 		cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);
280*7c478bd9Sstevel@tonic-gate 		change = 0;
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 		if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) ||
283*7c478bd9Sstevel@tonic-gate 		    (cmp_n == 0 && !redo && argp->opcode == DELOVFL)) {
284*7c478bd9Sstevel@tonic-gate 			/* Redo a create new page or undo a delete new page. */
285*7c478bd9Sstevel@tonic-gate 			pagep->next_pgno = argp->new_pgno;
286*7c478bd9Sstevel@tonic-gate 			change = 1;
287*7c478bd9Sstevel@tonic-gate 		} else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) ||
288*7c478bd9Sstevel@tonic-gate 		    (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) {
289*7c478bd9Sstevel@tonic-gate 			/* Redo a delete or undo a create new page. */
290*7c478bd9Sstevel@tonic-gate 			pagep->next_pgno = argp->next_pgno;
291*7c478bd9Sstevel@tonic-gate 			change = 1;
292*7c478bd9Sstevel@tonic-gate 		}
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 		if (!change) {
295*7c478bd9Sstevel@tonic-gate 			if ((ret =
296*7c478bd9Sstevel@tonic-gate 			    __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0)
297*7c478bd9Sstevel@tonic-gate 				goto out;
298*7c478bd9Sstevel@tonic-gate 		} else {
299*7c478bd9Sstevel@tonic-gate 			LSN(pagep) = redo ? *lsnp : argp->prevlsn;
300*7c478bd9Sstevel@tonic-gate 			if ((ret =
301*7c478bd9Sstevel@tonic-gate 			    __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0)
302*7c478bd9Sstevel@tonic-gate 				goto out;
303*7c478bd9Sstevel@tonic-gate 		}
304*7c478bd9Sstevel@tonic-gate 	}
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 	/* Now time to do the next page */
307*7c478bd9Sstevel@tonic-gate npage:	if (argp->next_pgno != PGNO_INVALID) {
308*7c478bd9Sstevel@tonic-gate 		ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep);
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 		if (ret != 0)
311*7c478bd9Sstevel@tonic-gate 			if (!redo) {
312*7c478bd9Sstevel@tonic-gate 				/*
313*7c478bd9Sstevel@tonic-gate 				 * We are undoing and the page doesn't exist.
314*7c478bd9Sstevel@tonic-gate 				 * That is equivalent to having a pagelsn of 0,
315*7c478bd9Sstevel@tonic-gate 				 * so we would not have to undo anything.  In
316*7c478bd9Sstevel@tonic-gate 				 * this case, don't bother creating a page.
317*7c478bd9Sstevel@tonic-gate 				 */
318*7c478bd9Sstevel@tonic-gate 				goto done;
319*7c478bd9Sstevel@tonic-gate 			} else if ((ret =
320*7c478bd9Sstevel@tonic-gate 			    memp_fget(mpf, &argp->next_pgno,
321*7c478bd9Sstevel@tonic-gate 			    DB_MPOOL_CREATE, &pagep)) != 0)
322*7c478bd9Sstevel@tonic-gate 				goto out;
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate 		cmp_n = log_compare(lsnp, &LSN(pagep));
325*7c478bd9Sstevel@tonic-gate 		cmp_p = log_compare(&LSN(pagep), &argp->nextlsn);
326*7c478bd9Sstevel@tonic-gate 		change = 0;
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 		if ((cmp_p == 0 && redo && argp->opcode == PUTOVFL) ||
329*7c478bd9Sstevel@tonic-gate 		    (cmp_n == 0 && !redo && argp->opcode == DELOVFL)) {
330*7c478bd9Sstevel@tonic-gate 			/* Redo a create new page or undo a delete new page. */
331*7c478bd9Sstevel@tonic-gate 			pagep->prev_pgno = argp->new_pgno;
332*7c478bd9Sstevel@tonic-gate 			change = 1;
333*7c478bd9Sstevel@tonic-gate 		} else if ((cmp_p == 0 && redo && argp->opcode == DELOVFL) ||
334*7c478bd9Sstevel@tonic-gate 		    (cmp_n == 0 && !redo && argp->opcode == PUTOVFL)) {
335*7c478bd9Sstevel@tonic-gate 			/* Redo a delete or undo a create new page. */
336*7c478bd9Sstevel@tonic-gate 			pagep->prev_pgno = argp->prev_pgno;
337*7c478bd9Sstevel@tonic-gate 			change = 1;
338*7c478bd9Sstevel@tonic-gate 		}
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate 		if (!change) {
341*7c478bd9Sstevel@tonic-gate 			if ((ret =
342*7c478bd9Sstevel@tonic-gate 			    __ham_put_page(file_dbp, (PAGE *)pagep, 0)) != 0)
343*7c478bd9Sstevel@tonic-gate 				goto out;
344*7c478bd9Sstevel@tonic-gate 		} else {
345*7c478bd9Sstevel@tonic-gate 			LSN(pagep) = redo ? *lsnp : argp->nextlsn;
346*7c478bd9Sstevel@tonic-gate 			if ((ret =
347*7c478bd9Sstevel@tonic-gate 			    __ham_put_page(file_dbp, (PAGE *)pagep, 1)) != 0)
348*7c478bd9Sstevel@tonic-gate 				goto out;
349*7c478bd9Sstevel@tonic-gate 		}
350*7c478bd9Sstevel@tonic-gate 	}
351*7c478bd9Sstevel@tonic-gate done:	*lsnp = argp->prev_lsn;
352*7c478bd9Sstevel@tonic-gate 	ret = 0;
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate out:	if (getmeta)
355*7c478bd9Sstevel@tonic-gate 		RELEASE_META(file_dbp, hcp);
356*7c478bd9Sstevel@tonic-gate 	REC_CLOSE;
357*7c478bd9Sstevel@tonic-gate }
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate /*
361*7c478bd9Sstevel@tonic-gate  * __ham_replace_recover --
362*7c478bd9Sstevel@tonic-gate  *	This log message refers to partial puts that are local to a single
363*7c478bd9Sstevel@tonic-gate  *	page.  You can think of them as special cases of the more general
364*7c478bd9Sstevel@tonic-gate  *	insdel log message.
365*7c478bd9Sstevel@tonic-gate  *
366*7c478bd9Sstevel@tonic-gate  * PUBLIC: int __ham_replace_recover
367*7c478bd9Sstevel@tonic-gate  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
368*7c478bd9Sstevel@tonic-gate  */
369*7c478bd9Sstevel@tonic-gate int
__ham_replace_recover(logp,dbtp,lsnp,redo,info)370*7c478bd9Sstevel@tonic-gate __ham_replace_recover(logp, dbtp, lsnp, redo, info)
371*7c478bd9Sstevel@tonic-gate 	DB_LOG *logp;
372*7c478bd9Sstevel@tonic-gate 	DBT *dbtp;
373*7c478bd9Sstevel@tonic-gate 	DB_LSN *lsnp;
374*7c478bd9Sstevel@tonic-gate 	int redo;
375*7c478bd9Sstevel@tonic-gate 	void *info;
376*7c478bd9Sstevel@tonic-gate {
377*7c478bd9Sstevel@tonic-gate 	__ham_replace_args *argp;
378*7c478bd9Sstevel@tonic-gate 	DB *file_dbp;
379*7c478bd9Sstevel@tonic-gate 	DBC *dbc;
380*7c478bd9Sstevel@tonic-gate 	HASH_CURSOR *hcp;
381*7c478bd9Sstevel@tonic-gate 	DB_MPOOLFILE *mpf;
382*7c478bd9Sstevel@tonic-gate 	DBT dbt;
383*7c478bd9Sstevel@tonic-gate 	PAGE *pagep;
384*7c478bd9Sstevel@tonic-gate 	int32_t grow;
385*7c478bd9Sstevel@tonic-gate 	int change, cmp_n, cmp_p, getmeta, ret;
386*7c478bd9Sstevel@tonic-gate 	u_int8_t *hk;
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate 	getmeta = 0;
389*7c478bd9Sstevel@tonic-gate 	hcp = NULL;
390*7c478bd9Sstevel@tonic-gate 	REC_PRINT(__ham_replace_print);
391*7c478bd9Sstevel@tonic-gate 	REC_INTRO(__ham_replace_read);
392*7c478bd9Sstevel@tonic-gate 	hcp = (HASH_CURSOR *)dbc->internal;
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 	ret = memp_fget(mpf, &argp->pgno, 0, &pagep);
395*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
396*7c478bd9Sstevel@tonic-gate 		if (!redo) {
397*7c478bd9Sstevel@tonic-gate 			/*
398*7c478bd9Sstevel@tonic-gate 			 * We are undoing and the page doesn't exist.  That
399*7c478bd9Sstevel@tonic-gate 			 * is equivalent to having a pagelsn of 0, so we
400*7c478bd9Sstevel@tonic-gate 			 * would not have to undo anything.  In this case,
401*7c478bd9Sstevel@tonic-gate 			 * don't bother creating a page.
402*7c478bd9Sstevel@tonic-gate 			 */
403*7c478bd9Sstevel@tonic-gate 			goto done;
404*7c478bd9Sstevel@tonic-gate 		} else if ((ret = memp_fget(mpf, &argp->pgno,
405*7c478bd9Sstevel@tonic-gate 		    DB_MPOOL_CREATE, &pagep)) != 0)
406*7c478bd9Sstevel@tonic-gate 			goto out;
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 	GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
409*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
410*7c478bd9Sstevel@tonic-gate 		goto out;
411*7c478bd9Sstevel@tonic-gate 	getmeta = 1;
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 	cmp_n = log_compare(lsnp, &LSN(pagep));
414*7c478bd9Sstevel@tonic-gate 	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 	if (cmp_p == 0 && redo) {
417*7c478bd9Sstevel@tonic-gate 		change = 1;
418*7c478bd9Sstevel@tonic-gate 		/* Reapply the change as specified. */
419*7c478bd9Sstevel@tonic-gate 		dbt.data = argp->newitem.data;
420*7c478bd9Sstevel@tonic-gate 		dbt.size = argp->newitem.size;
421*7c478bd9Sstevel@tonic-gate 		grow = argp->newitem.size - argp->olditem.size;
422*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = *lsnp;
423*7c478bd9Sstevel@tonic-gate 	} else if (cmp_n == 0 && !redo) {
424*7c478bd9Sstevel@tonic-gate 		change = 1;
425*7c478bd9Sstevel@tonic-gate 		/* Undo the already applied change. */
426*7c478bd9Sstevel@tonic-gate 		dbt.data = argp->olditem.data;
427*7c478bd9Sstevel@tonic-gate 		dbt.size = argp->olditem.size;
428*7c478bd9Sstevel@tonic-gate 		grow = argp->olditem.size - argp->newitem.size;
429*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = argp->pagelsn;
430*7c478bd9Sstevel@tonic-gate 	} else {
431*7c478bd9Sstevel@tonic-gate 		change = 0;
432*7c478bd9Sstevel@tonic-gate 		grow = 0;
433*7c478bd9Sstevel@tonic-gate 	}
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate 	if (change) {
436*7c478bd9Sstevel@tonic-gate 		__ham_onpage_replace(pagep,
437*7c478bd9Sstevel@tonic-gate 		    file_dbp->pgsize, argp->ndx, argp->off, grow, &dbt);
438*7c478bd9Sstevel@tonic-gate 		if (argp->makedup) {
439*7c478bd9Sstevel@tonic-gate 			hk = P_ENTRY(pagep, argp->ndx);
440*7c478bd9Sstevel@tonic-gate 			if (redo)
441*7c478bd9Sstevel@tonic-gate 				HPAGE_PTYPE(hk) = H_DUPLICATE;
442*7c478bd9Sstevel@tonic-gate 			else
443*7c478bd9Sstevel@tonic-gate 				HPAGE_PTYPE(hk) = H_KEYDATA;
444*7c478bd9Sstevel@tonic-gate 		}
445*7c478bd9Sstevel@tonic-gate 	}
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 	if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0)
448*7c478bd9Sstevel@tonic-gate 		goto out;
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate done:	*lsnp = argp->prev_lsn;
451*7c478bd9Sstevel@tonic-gate 	ret = 0;
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate out:	if (getmeta)
454*7c478bd9Sstevel@tonic-gate 		RELEASE_META(file_dbp, hcp);
455*7c478bd9Sstevel@tonic-gate 	REC_CLOSE;
456*7c478bd9Sstevel@tonic-gate }
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate /*
459*7c478bd9Sstevel@tonic-gate  * __ham_newpgno_recover --
460*7c478bd9Sstevel@tonic-gate  *	This log message is used when allocating or deleting an overflow
461*7c478bd9Sstevel@tonic-gate  *	page.  It takes care of modifying the meta data.
462*7c478bd9Sstevel@tonic-gate  *
463*7c478bd9Sstevel@tonic-gate  * PUBLIC: int __ham_newpgno_recover
464*7c478bd9Sstevel@tonic-gate  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
465*7c478bd9Sstevel@tonic-gate  */
466*7c478bd9Sstevel@tonic-gate int
__ham_newpgno_recover(logp,dbtp,lsnp,redo,info)467*7c478bd9Sstevel@tonic-gate __ham_newpgno_recover(logp, dbtp, lsnp, redo, info)
468*7c478bd9Sstevel@tonic-gate 	DB_LOG *logp;
469*7c478bd9Sstevel@tonic-gate 	DBT *dbtp;
470*7c478bd9Sstevel@tonic-gate 	DB_LSN *lsnp;
471*7c478bd9Sstevel@tonic-gate 	int redo;
472*7c478bd9Sstevel@tonic-gate 	void *info;
473*7c478bd9Sstevel@tonic-gate {
474*7c478bd9Sstevel@tonic-gate 	__ham_newpgno_args *argp;
475*7c478bd9Sstevel@tonic-gate 	DB *file_dbp;
476*7c478bd9Sstevel@tonic-gate 	DBC *dbc;
477*7c478bd9Sstevel@tonic-gate 	HASH_CURSOR *hcp;
478*7c478bd9Sstevel@tonic-gate 	DB_MPOOLFILE *mpf;
479*7c478bd9Sstevel@tonic-gate 	PAGE *pagep;
480*7c478bd9Sstevel@tonic-gate 	int change, cmp_n, cmp_p, getmeta, ret;
481*7c478bd9Sstevel@tonic-gate 
482*7c478bd9Sstevel@tonic-gate 	getmeta = 0;
483*7c478bd9Sstevel@tonic-gate 	hcp = NULL;
484*7c478bd9Sstevel@tonic-gate 	REC_PRINT(__ham_newpgno_print);
485*7c478bd9Sstevel@tonic-gate 	REC_INTRO(__ham_newpgno_read);
486*7c478bd9Sstevel@tonic-gate 	hcp = (HASH_CURSOR *)dbc->internal;
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 	GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
489*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
490*7c478bd9Sstevel@tonic-gate 		goto out;
491*7c478bd9Sstevel@tonic-gate 	getmeta = 1;
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 	/*
494*7c478bd9Sstevel@tonic-gate 	 * There are two phases to the recovery here.  First we need
495*7c478bd9Sstevel@tonic-gate 	 * to update the meta data; then we need to update the page.
496*7c478bd9Sstevel@tonic-gate 	 * We'll do the meta-data first.
497*7c478bd9Sstevel@tonic-gate 	 */
498*7c478bd9Sstevel@tonic-gate 	cmp_n = log_compare(lsnp, &hcp->hdr->lsn);
499*7c478bd9Sstevel@tonic-gate 	cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn);
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate 	change = 0;
502*7c478bd9Sstevel@tonic-gate 	if ((cmp_p == 0 && redo && argp->opcode == ALLOCPGNO) ||
503*7c478bd9Sstevel@tonic-gate 	    (cmp_n == 0 && !redo && argp->opcode == DELPGNO)) {
504*7c478bd9Sstevel@tonic-gate 		/* Need to redo an allocation or undo a deletion. */
505*7c478bd9Sstevel@tonic-gate 		hcp->hdr->last_freed = argp->free_pgno;
506*7c478bd9Sstevel@tonic-gate 		if (redo && argp->old_pgno != 0) /* Must be ALLOCPGNO */
507*7c478bd9Sstevel@tonic-gate 			hcp->hdr->spares[hcp->hdr->ovfl_point]++;
508*7c478bd9Sstevel@tonic-gate 		change = 1;
509*7c478bd9Sstevel@tonic-gate 	} else if (cmp_p == 0 && redo && argp->opcode == DELPGNO) {
510*7c478bd9Sstevel@tonic-gate 		/* Need to redo a deletion */
511*7c478bd9Sstevel@tonic-gate 		hcp->hdr->last_freed = argp->pgno;
512*7c478bd9Sstevel@tonic-gate 		change = 1;
513*7c478bd9Sstevel@tonic-gate 	} else if (cmp_n == 0 && !redo && argp->opcode == ALLOCPGNO) {
514*7c478bd9Sstevel@tonic-gate 		/* undo an allocation. */
515*7c478bd9Sstevel@tonic-gate 		if (argp->old_pgno == 0)
516*7c478bd9Sstevel@tonic-gate 			hcp->hdr->last_freed = argp->pgno;
517*7c478bd9Sstevel@tonic-gate 		else {
518*7c478bd9Sstevel@tonic-gate 			hcp->hdr->spares[hcp->hdr->ovfl_point]--;
519*7c478bd9Sstevel@tonic-gate 			hcp->hdr->last_freed = 0;
520*7c478bd9Sstevel@tonic-gate 		}
521*7c478bd9Sstevel@tonic-gate 		change = 1;
522*7c478bd9Sstevel@tonic-gate 	}
523*7c478bd9Sstevel@tonic-gate 	if (change) {
524*7c478bd9Sstevel@tonic-gate 		hcp->hdr->lsn = redo ? *lsnp : argp->metalsn;
525*7c478bd9Sstevel@tonic-gate 		F_SET(hcp, H_DIRTY);
526*7c478bd9Sstevel@tonic-gate 	}
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate 	/* Now check the newly allocated/freed page. */
530*7c478bd9Sstevel@tonic-gate 	ret = memp_fget(mpf, &argp->pgno, 0, &pagep);
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
533*7c478bd9Sstevel@tonic-gate 		if (!redo) {
534*7c478bd9Sstevel@tonic-gate 			/*
535*7c478bd9Sstevel@tonic-gate 			 * We are undoing and the page doesn't exist.  That
536*7c478bd9Sstevel@tonic-gate 			 * is equivalent to having a pagelsn of 0, so we
537*7c478bd9Sstevel@tonic-gate 			 * would not have to undo anything.  In this case,
538*7c478bd9Sstevel@tonic-gate 			 * don't bother creating a page.
539*7c478bd9Sstevel@tonic-gate 			 */
540*7c478bd9Sstevel@tonic-gate 			goto done;
541*7c478bd9Sstevel@tonic-gate 		} else if ((ret = memp_fget(mpf, &argp->pgno,
542*7c478bd9Sstevel@tonic-gate 		    DB_MPOOL_CREATE, &pagep)) != 0)
543*7c478bd9Sstevel@tonic-gate 			goto out;
544*7c478bd9Sstevel@tonic-gate 
545*7c478bd9Sstevel@tonic-gate 	cmp_n = log_compare(lsnp, &LSN(pagep));
546*7c478bd9Sstevel@tonic-gate 	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
547*7c478bd9Sstevel@tonic-gate 
548*7c478bd9Sstevel@tonic-gate 	change = 0;
549*7c478bd9Sstevel@tonic-gate 	if (cmp_p == 0 && redo && argp->opcode == ALLOCPGNO) {
550*7c478bd9Sstevel@tonic-gate 		/* Need to redo an allocation. */
551*7c478bd9Sstevel@tonic-gate 		P_INIT(pagep, file_dbp->pgsize, argp->pgno, PGNO_INVALID,
552*7c478bd9Sstevel@tonic-gate 		    PGNO_INVALID, 0, argp->new_type);
553*7c478bd9Sstevel@tonic-gate 		change = 1;
554*7c478bd9Sstevel@tonic-gate 	} else if (cmp_n == 0 && !redo && argp->opcode == DELPGNO) {
555*7c478bd9Sstevel@tonic-gate 		/* Undoing a delete. */
556*7c478bd9Sstevel@tonic-gate 		P_INIT(pagep, file_dbp->pgsize, argp->pgno, PGNO_INVALID,
557*7c478bd9Sstevel@tonic-gate 		    argp->old_pgno, 0, argp->old_type);
558*7c478bd9Sstevel@tonic-gate 		change = 1;
559*7c478bd9Sstevel@tonic-gate 	} else if ((cmp_p == 0 && redo && argp->opcode == DELPGNO) ||
560*7c478bd9Sstevel@tonic-gate 	    (cmp_n == 0 && !redo && argp->opcode == ALLOCPGNO)) {
561*7c478bd9Sstevel@tonic-gate 		/* Need to redo a deletion or undo an allocation. */
562*7c478bd9Sstevel@tonic-gate 		NEXT_PGNO(pagep) = argp->free_pgno;
563*7c478bd9Sstevel@tonic-gate 		TYPE(pagep) = P_INVALID;
564*7c478bd9Sstevel@tonic-gate 		change = 1;
565*7c478bd9Sstevel@tonic-gate 	}
566*7c478bd9Sstevel@tonic-gate 	if (change)
567*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = redo ? *lsnp : argp->pagelsn;
568*7c478bd9Sstevel@tonic-gate 
569*7c478bd9Sstevel@tonic-gate 	if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0)
570*7c478bd9Sstevel@tonic-gate 		goto out;
571*7c478bd9Sstevel@tonic-gate 
572*7c478bd9Sstevel@tonic-gate done:	*lsnp = argp->prev_lsn;
573*7c478bd9Sstevel@tonic-gate 	ret = 0;
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate out:	if (getmeta)
576*7c478bd9Sstevel@tonic-gate 		RELEASE_META(file_dbp, hcp);
577*7c478bd9Sstevel@tonic-gate 	REC_CLOSE;
578*7c478bd9Sstevel@tonic-gate 
579*7c478bd9Sstevel@tonic-gate }
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate /*
582*7c478bd9Sstevel@tonic-gate  * __ham_splitmeta_recover --
583*7c478bd9Sstevel@tonic-gate  *	This is the meta-data part of the split.  Records the new and old
584*7c478bd9Sstevel@tonic-gate  *	bucket numbers and the new/old mask information.
585*7c478bd9Sstevel@tonic-gate  *
586*7c478bd9Sstevel@tonic-gate  * PUBLIC: int __ham_splitmeta_recover
587*7c478bd9Sstevel@tonic-gate  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
588*7c478bd9Sstevel@tonic-gate  */
589*7c478bd9Sstevel@tonic-gate int
__ham_splitmeta_recover(logp,dbtp,lsnp,redo,info)590*7c478bd9Sstevel@tonic-gate __ham_splitmeta_recover(logp, dbtp, lsnp, redo, info)
591*7c478bd9Sstevel@tonic-gate 	DB_LOG *logp;
592*7c478bd9Sstevel@tonic-gate 	DBT *dbtp;
593*7c478bd9Sstevel@tonic-gate 	DB_LSN *lsnp;
594*7c478bd9Sstevel@tonic-gate 	int redo;
595*7c478bd9Sstevel@tonic-gate 	void *info;
596*7c478bd9Sstevel@tonic-gate {
597*7c478bd9Sstevel@tonic-gate 	__ham_splitmeta_args *argp;
598*7c478bd9Sstevel@tonic-gate 	DB *file_dbp;
599*7c478bd9Sstevel@tonic-gate 	DBC *dbc;
600*7c478bd9Sstevel@tonic-gate 	HASH_CURSOR *hcp;
601*7c478bd9Sstevel@tonic-gate 	DB_MPOOLFILE *mpf;
602*7c478bd9Sstevel@tonic-gate 	int change, cmp_n, cmp_p, getmeta, ret;
603*7c478bd9Sstevel@tonic-gate 	u_int32_t pow;
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate 	getmeta = 0;
606*7c478bd9Sstevel@tonic-gate 	hcp = NULL;
607*7c478bd9Sstevel@tonic-gate 	REC_PRINT(__ham_splitmeta_print);
608*7c478bd9Sstevel@tonic-gate 	REC_INTRO(__ham_splitmeta_read);
609*7c478bd9Sstevel@tonic-gate 	hcp = (HASH_CURSOR *)dbc->internal;
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate 	GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
612*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
613*7c478bd9Sstevel@tonic-gate 		goto out;
614*7c478bd9Sstevel@tonic-gate 	getmeta = 1;
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	/*
617*7c478bd9Sstevel@tonic-gate 	 * There are two phases to the recovery here.  First we need
618*7c478bd9Sstevel@tonic-gate 	 * to update the meta data; then we need to update the page.
619*7c478bd9Sstevel@tonic-gate 	 * We'll do the meta-data first.
620*7c478bd9Sstevel@tonic-gate 	 */
621*7c478bd9Sstevel@tonic-gate 	cmp_n = log_compare(lsnp, &hcp->hdr->lsn);
622*7c478bd9Sstevel@tonic-gate 	cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn);
623*7c478bd9Sstevel@tonic-gate 
624*7c478bd9Sstevel@tonic-gate 	change = 0;
625*7c478bd9Sstevel@tonic-gate 	if (cmp_p == 0 && redo) {
626*7c478bd9Sstevel@tonic-gate 		/* Need to redo the split information. */
627*7c478bd9Sstevel@tonic-gate 		hcp->hdr->max_bucket = argp->bucket + 1;
628*7c478bd9Sstevel@tonic-gate 		pow = __db_log2(hcp->hdr->max_bucket + 1);
629*7c478bd9Sstevel@tonic-gate 		if (pow > hcp->hdr->ovfl_point) {
630*7c478bd9Sstevel@tonic-gate 			hcp->hdr->spares[pow] =
631*7c478bd9Sstevel@tonic-gate 				hcp->hdr->spares[hcp->hdr->ovfl_point];
632*7c478bd9Sstevel@tonic-gate 			hcp->hdr->ovfl_point = pow;
633*7c478bd9Sstevel@tonic-gate 		}
634*7c478bd9Sstevel@tonic-gate 		if (hcp->hdr->max_bucket > hcp->hdr->high_mask) {
635*7c478bd9Sstevel@tonic-gate 			hcp->hdr->low_mask = hcp->hdr->high_mask;
636*7c478bd9Sstevel@tonic-gate 			hcp->hdr->high_mask =
637*7c478bd9Sstevel@tonic-gate 			    hcp->hdr->max_bucket | hcp->hdr->low_mask;
638*7c478bd9Sstevel@tonic-gate 		}
639*7c478bd9Sstevel@tonic-gate 		change = 1;
640*7c478bd9Sstevel@tonic-gate 	} else if (cmp_n == 0 && !redo) {
641*7c478bd9Sstevel@tonic-gate 		/* Need to undo the split information. */
642*7c478bd9Sstevel@tonic-gate 		hcp->hdr->max_bucket = argp->bucket;
643*7c478bd9Sstevel@tonic-gate 		hcp->hdr->ovfl_point = argp->ovflpoint;
644*7c478bd9Sstevel@tonic-gate 		hcp->hdr->spares[hcp->hdr->ovfl_point] = argp->spares;
645*7c478bd9Sstevel@tonic-gate 		pow = 1 << __db_log2(hcp->hdr->max_bucket + 1);
646*7c478bd9Sstevel@tonic-gate 		hcp->hdr->high_mask = pow - 1;
647*7c478bd9Sstevel@tonic-gate 		hcp->hdr->low_mask = (pow >> 1) - 1;
648*7c478bd9Sstevel@tonic-gate 		change = 1;
649*7c478bd9Sstevel@tonic-gate 	}
650*7c478bd9Sstevel@tonic-gate 	if (change) {
651*7c478bd9Sstevel@tonic-gate 		hcp->hdr->lsn = redo ? *lsnp : argp->metalsn;
652*7c478bd9Sstevel@tonic-gate 		F_SET(hcp, H_DIRTY);
653*7c478bd9Sstevel@tonic-gate 	}
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate done:	*lsnp = argp->prev_lsn;
656*7c478bd9Sstevel@tonic-gate 	ret = 0;
657*7c478bd9Sstevel@tonic-gate 
658*7c478bd9Sstevel@tonic-gate out:	if (getmeta)
659*7c478bd9Sstevel@tonic-gate 		RELEASE_META(file_dbp, hcp);
660*7c478bd9Sstevel@tonic-gate 	REC_CLOSE;
661*7c478bd9Sstevel@tonic-gate }
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate /*
664*7c478bd9Sstevel@tonic-gate  * __ham_splitdata_recover --
665*7c478bd9Sstevel@tonic-gate  *
666*7c478bd9Sstevel@tonic-gate  * PUBLIC: int __ham_splitdata_recover
667*7c478bd9Sstevel@tonic-gate  * PUBLIC:    __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
668*7c478bd9Sstevel@tonic-gate  */
669*7c478bd9Sstevel@tonic-gate int
__ham_splitdata_recover(logp,dbtp,lsnp,redo,info)670*7c478bd9Sstevel@tonic-gate __ham_splitdata_recover(logp, dbtp, lsnp, redo, info)
671*7c478bd9Sstevel@tonic-gate 	DB_LOG *logp;
672*7c478bd9Sstevel@tonic-gate 	DBT *dbtp;
673*7c478bd9Sstevel@tonic-gate 	DB_LSN *lsnp;
674*7c478bd9Sstevel@tonic-gate 	int redo;
675*7c478bd9Sstevel@tonic-gate 	void *info;
676*7c478bd9Sstevel@tonic-gate {
677*7c478bd9Sstevel@tonic-gate 	__ham_splitdata_args *argp;
678*7c478bd9Sstevel@tonic-gate 	DB *file_dbp;
679*7c478bd9Sstevel@tonic-gate 	DBC *dbc;
680*7c478bd9Sstevel@tonic-gate 	HASH_CURSOR *hcp;
681*7c478bd9Sstevel@tonic-gate 	DB_MPOOLFILE *mpf;
682*7c478bd9Sstevel@tonic-gate 	PAGE *pagep;
683*7c478bd9Sstevel@tonic-gate 	int change, cmp_n, cmp_p, getmeta, ret;
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate 	getmeta = 0;
686*7c478bd9Sstevel@tonic-gate 	hcp = NULL;
687*7c478bd9Sstevel@tonic-gate 	REC_PRINT(__ham_splitdata_print);
688*7c478bd9Sstevel@tonic-gate 	REC_INTRO(__ham_splitdata_read);
689*7c478bd9Sstevel@tonic-gate 	hcp = (HASH_CURSOR *)dbc->internal;
690*7c478bd9Sstevel@tonic-gate 
691*7c478bd9Sstevel@tonic-gate 	ret = memp_fget(mpf, &argp->pgno, 0, &pagep);
692*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
693*7c478bd9Sstevel@tonic-gate 		if (!redo) {
694*7c478bd9Sstevel@tonic-gate 			/*
695*7c478bd9Sstevel@tonic-gate 			 * We are undoing and the page doesn't exist.  That
696*7c478bd9Sstevel@tonic-gate 			 * is equivalent to having a pagelsn of 0, so we
697*7c478bd9Sstevel@tonic-gate 			 * would not have to undo anything.  In this case,
698*7c478bd9Sstevel@tonic-gate 			 * don't bother creating a page.
699*7c478bd9Sstevel@tonic-gate 			 */
700*7c478bd9Sstevel@tonic-gate 			goto done;
701*7c478bd9Sstevel@tonic-gate 		} else if ((ret = memp_fget(mpf, &argp->pgno,
702*7c478bd9Sstevel@tonic-gate 		    DB_MPOOL_CREATE, &pagep)) != 0)
703*7c478bd9Sstevel@tonic-gate 			goto out;
704*7c478bd9Sstevel@tonic-gate 
705*7c478bd9Sstevel@tonic-gate 	GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
706*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
707*7c478bd9Sstevel@tonic-gate 		goto out;
708*7c478bd9Sstevel@tonic-gate 	getmeta = 1;
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate 	cmp_n = log_compare(lsnp, &LSN(pagep));
711*7c478bd9Sstevel@tonic-gate 	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 	/*
714*7c478bd9Sstevel@tonic-gate 	 * There are two types of log messages here, one for the old page
715*7c478bd9Sstevel@tonic-gate 	 * and one for the new pages created.  The original image in the
716*7c478bd9Sstevel@tonic-gate 	 * SPLITOLD record is used for undo.  The image in the SPLITNEW
717*7c478bd9Sstevel@tonic-gate 	 * is used for redo.  We should never have a case where there is
718*7c478bd9Sstevel@tonic-gate 	 * a redo operation and the SPLITOLD record is on disk, but not
719*7c478bd9Sstevel@tonic-gate 	 * the SPLITNEW record.  Therefore, we only have work to do when
720*7c478bd9Sstevel@tonic-gate 	 * redo NEW messages and undo OLD messages, but we have to update
721*7c478bd9Sstevel@tonic-gate 	 * LSNs in both cases.
722*7c478bd9Sstevel@tonic-gate 	 */
723*7c478bd9Sstevel@tonic-gate 	change = 0;
724*7c478bd9Sstevel@tonic-gate 	if (cmp_p == 0 && redo) {
725*7c478bd9Sstevel@tonic-gate 		if (argp->opcode == SPLITNEW)
726*7c478bd9Sstevel@tonic-gate 			/* Need to redo the split described. */
727*7c478bd9Sstevel@tonic-gate 			memcpy(pagep, argp->pageimage.data,
728*7c478bd9Sstevel@tonic-gate 			    argp->pageimage.size);
729*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = *lsnp;
730*7c478bd9Sstevel@tonic-gate 		change = 1;
731*7c478bd9Sstevel@tonic-gate 	} else if (cmp_n == 0 && !redo) {
732*7c478bd9Sstevel@tonic-gate 		if (argp->opcode == SPLITOLD) {
733*7c478bd9Sstevel@tonic-gate 			/* Put back the old image. */
734*7c478bd9Sstevel@tonic-gate 			memcpy(pagep, argp->pageimage.data,
735*7c478bd9Sstevel@tonic-gate 			    argp->pageimage.size);
736*7c478bd9Sstevel@tonic-gate 		} else
737*7c478bd9Sstevel@tonic-gate 			P_INIT(pagep, file_dbp->pgsize, argp->pgno,
738*7c478bd9Sstevel@tonic-gate 			    PGNO_INVALID, PGNO_INVALID, 0, P_HASH);
739*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = argp->pagelsn;
740*7c478bd9Sstevel@tonic-gate 		change = 1;
741*7c478bd9Sstevel@tonic-gate 	}
742*7c478bd9Sstevel@tonic-gate 	if ((ret = __ham_put_page(file_dbp, pagep, change)) != 0)
743*7c478bd9Sstevel@tonic-gate 		goto out;
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate done:	*lsnp = argp->prev_lsn;
746*7c478bd9Sstevel@tonic-gate 	ret = 0;
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate out:	if (getmeta)
749*7c478bd9Sstevel@tonic-gate 		RELEASE_META(file_dbp, hcp);
750*7c478bd9Sstevel@tonic-gate 	REC_CLOSE;
751*7c478bd9Sstevel@tonic-gate }
752*7c478bd9Sstevel@tonic-gate 
753*7c478bd9Sstevel@tonic-gate /*
754*7c478bd9Sstevel@tonic-gate  * __ham_ovfl_recover --
755*7c478bd9Sstevel@tonic-gate  *	This message is generated when we initialize a set of overflow pages.
756*7c478bd9Sstevel@tonic-gate  *
757*7c478bd9Sstevel@tonic-gate  * PUBLIC: int __ham_ovfl_recover
758*7c478bd9Sstevel@tonic-gate  * PUBLIC:     __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
759*7c478bd9Sstevel@tonic-gate  */
760*7c478bd9Sstevel@tonic-gate int
__ham_ovfl_recover(logp,dbtp,lsnp,redo,info)761*7c478bd9Sstevel@tonic-gate __ham_ovfl_recover(logp, dbtp, lsnp, redo, info)
762*7c478bd9Sstevel@tonic-gate 	DB_LOG *logp;
763*7c478bd9Sstevel@tonic-gate 	DBT *dbtp;
764*7c478bd9Sstevel@tonic-gate 	DB_LSN *lsnp;
765*7c478bd9Sstevel@tonic-gate 	int redo;
766*7c478bd9Sstevel@tonic-gate 	void *info;
767*7c478bd9Sstevel@tonic-gate {
768*7c478bd9Sstevel@tonic-gate 	__ham_ovfl_args *argp;
769*7c478bd9Sstevel@tonic-gate 	DB *file_dbp;
770*7c478bd9Sstevel@tonic-gate 	DBC *dbc;
771*7c478bd9Sstevel@tonic-gate 	HASH_CURSOR *hcp;
772*7c478bd9Sstevel@tonic-gate 	DB_MPOOLFILE *mpf;
773*7c478bd9Sstevel@tonic-gate 	PAGE *pagep;
774*7c478bd9Sstevel@tonic-gate 	db_pgno_t max_pgno, pgno;
775*7c478bd9Sstevel@tonic-gate 	int cmp_n, cmp_p, getmeta, ret;
776*7c478bd9Sstevel@tonic-gate 
777*7c478bd9Sstevel@tonic-gate 	getmeta = 0;
778*7c478bd9Sstevel@tonic-gate 	hcp = NULL;
779*7c478bd9Sstevel@tonic-gate 	REC_PRINT(__ham_ovfl_print);
780*7c478bd9Sstevel@tonic-gate 	REC_INTRO(__ham_ovfl_read);
781*7c478bd9Sstevel@tonic-gate 	hcp = (HASH_CURSOR *)dbc->internal;
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate 	GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
784*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
785*7c478bd9Sstevel@tonic-gate 		goto out;
786*7c478bd9Sstevel@tonic-gate 	getmeta = 1;
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate 	cmp_n = log_compare(lsnp, &hcp->hdr->lsn);
789*7c478bd9Sstevel@tonic-gate 	cmp_p = log_compare(&hcp->hdr->lsn, &argp->metalsn);
790*7c478bd9Sstevel@tonic-gate 
791*7c478bd9Sstevel@tonic-gate 	if (cmp_p == 0 && redo) {
792*7c478bd9Sstevel@tonic-gate 		/* Redo the allocation. */
793*7c478bd9Sstevel@tonic-gate 		hcp->hdr->last_freed = argp->start_pgno;
794*7c478bd9Sstevel@tonic-gate 		hcp->hdr->spares[argp->ovflpoint] += argp->npages;
795*7c478bd9Sstevel@tonic-gate 		hcp->hdr->lsn = *lsnp;
796*7c478bd9Sstevel@tonic-gate 		F_SET(hcp, H_DIRTY);
797*7c478bd9Sstevel@tonic-gate 	} else if (cmp_n == 0 && !redo) {
798*7c478bd9Sstevel@tonic-gate 		hcp->hdr->last_freed = argp->free_pgno;
799*7c478bd9Sstevel@tonic-gate 		hcp->hdr->spares[argp->ovflpoint] -= argp->npages;
800*7c478bd9Sstevel@tonic-gate 		hcp->hdr->lsn = argp->metalsn;
801*7c478bd9Sstevel@tonic-gate 		F_SET(hcp, H_DIRTY);
802*7c478bd9Sstevel@tonic-gate 	}
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate 	max_pgno = argp->start_pgno + argp->npages - 1;
805*7c478bd9Sstevel@tonic-gate 	ret = 0;
806*7c478bd9Sstevel@tonic-gate 	for (pgno = argp->start_pgno; pgno <= max_pgno; pgno++) {
807*7c478bd9Sstevel@tonic-gate 		if ((ret = memp_fget(mpf, &pgno, 0, &pagep)) != 0) {
808*7c478bd9Sstevel@tonic-gate 			if (!redo) {
809*7c478bd9Sstevel@tonic-gate 				ret = 0;
810*7c478bd9Sstevel@tonic-gate 				continue;
811*7c478bd9Sstevel@tonic-gate 			}
812*7c478bd9Sstevel@tonic-gate 			if ((ret = memp_fget(mpf,
813*7c478bd9Sstevel@tonic-gate 			    &pgno, DB_MPOOL_CREATE, &pagep)) != 0)
814*7c478bd9Sstevel@tonic-gate 				goto out;
815*7c478bd9Sstevel@tonic-gate 		}
816*7c478bd9Sstevel@tonic-gate 		if (redo && log_compare((const DB_LSN *)lsnp,
817*7c478bd9Sstevel@tonic-gate 		    (const DB_LSN *)&LSN(pagep)) > 0) {
818*7c478bd9Sstevel@tonic-gate 			P_INIT(pagep, file_dbp->pgsize, pgno, PGNO_INVALID,
819*7c478bd9Sstevel@tonic-gate 			    pgno == max_pgno ? argp->free_pgno : pgno + 1,
820*7c478bd9Sstevel@tonic-gate 			    0, P_HASH);
821*7c478bd9Sstevel@tonic-gate 			LSN(pagep) = *lsnp;
822*7c478bd9Sstevel@tonic-gate 			ret = __ham_put_page(file_dbp, pagep, 1);
823*7c478bd9Sstevel@tonic-gate 		} else if (!redo) {
824*7c478bd9Sstevel@tonic-gate 			ZERO_LSN(pagep->lsn);
825*7c478bd9Sstevel@tonic-gate 			ret = __ham_put_page(file_dbp, pagep, 1);
826*7c478bd9Sstevel@tonic-gate 		} else
827*7c478bd9Sstevel@tonic-gate 			ret = __ham_put_page(file_dbp, pagep, 0);
828*7c478bd9Sstevel@tonic-gate 		if (ret)
829*7c478bd9Sstevel@tonic-gate 			goto out;
830*7c478bd9Sstevel@tonic-gate 	}
831*7c478bd9Sstevel@tonic-gate 
832*7c478bd9Sstevel@tonic-gate done:	*lsnp = argp->prev_lsn;
833*7c478bd9Sstevel@tonic-gate 	ret = 0;
834*7c478bd9Sstevel@tonic-gate 
835*7c478bd9Sstevel@tonic-gate out:	if (getmeta)
836*7c478bd9Sstevel@tonic-gate 		RELEASE_META(file_dbp, hcp);
837*7c478bd9Sstevel@tonic-gate 	REC_CLOSE;
838*7c478bd9Sstevel@tonic-gate }
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate /*
841*7c478bd9Sstevel@tonic-gate  * __ham_copypage_recover --
842*7c478bd9Sstevel@tonic-gate  *	Recovery function for copypage.
843*7c478bd9Sstevel@tonic-gate  *
844*7c478bd9Sstevel@tonic-gate  * PUBLIC: int __ham_copypage_recover
845*7c478bd9Sstevel@tonic-gate  * PUBLIC:   __P((DB_LOG *, DBT *, DB_LSN *, int, void *));
846*7c478bd9Sstevel@tonic-gate  */
847*7c478bd9Sstevel@tonic-gate int
__ham_copypage_recover(logp,dbtp,lsnp,redo,info)848*7c478bd9Sstevel@tonic-gate __ham_copypage_recover(logp, dbtp, lsnp, redo, info)
849*7c478bd9Sstevel@tonic-gate 	DB_LOG *logp;
850*7c478bd9Sstevel@tonic-gate 	DBT *dbtp;
851*7c478bd9Sstevel@tonic-gate 	DB_LSN *lsnp;
852*7c478bd9Sstevel@tonic-gate 	int redo;
853*7c478bd9Sstevel@tonic-gate 	void *info;
854*7c478bd9Sstevel@tonic-gate {
855*7c478bd9Sstevel@tonic-gate 	__ham_copypage_args *argp;
856*7c478bd9Sstevel@tonic-gate 	DB *file_dbp;
857*7c478bd9Sstevel@tonic-gate 	DBC *dbc;
858*7c478bd9Sstevel@tonic-gate 	HASH_CURSOR *hcp;
859*7c478bd9Sstevel@tonic-gate 	DB_MPOOLFILE *mpf;
860*7c478bd9Sstevel@tonic-gate 	PAGE *pagep;
861*7c478bd9Sstevel@tonic-gate 	int cmp_n, cmp_p, getmeta, modified, ret;
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 	getmeta = 0;
864*7c478bd9Sstevel@tonic-gate 	hcp = NULL;
865*7c478bd9Sstevel@tonic-gate 	REC_PRINT(__ham_copypage_print);
866*7c478bd9Sstevel@tonic-gate 	REC_INTRO(__ham_copypage_read);
867*7c478bd9Sstevel@tonic-gate 	hcp = (HASH_CURSOR *)dbc->internal;
868*7c478bd9Sstevel@tonic-gate 
869*7c478bd9Sstevel@tonic-gate 	GET_META(file_dbp, (HASH_CURSOR *)dbc->internal, ret);
870*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
871*7c478bd9Sstevel@tonic-gate 		goto out;
872*7c478bd9Sstevel@tonic-gate 	getmeta = 1;
873*7c478bd9Sstevel@tonic-gate 	modified = 0;
874*7c478bd9Sstevel@tonic-gate 
875*7c478bd9Sstevel@tonic-gate 	/* This is the bucket page. */
876*7c478bd9Sstevel@tonic-gate 	ret = memp_fget(mpf, &argp->pgno, 0, &pagep);
877*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
878*7c478bd9Sstevel@tonic-gate 		if (!redo) {
879*7c478bd9Sstevel@tonic-gate 			/*
880*7c478bd9Sstevel@tonic-gate 			 * We are undoing and the page doesn't exist.  That
881*7c478bd9Sstevel@tonic-gate 			 * is equivalent to having a pagelsn of 0, so we
882*7c478bd9Sstevel@tonic-gate 			 * would not have to undo anything.  In this case,
883*7c478bd9Sstevel@tonic-gate 			 * don't bother creating a page.
884*7c478bd9Sstevel@tonic-gate 			 */
885*7c478bd9Sstevel@tonic-gate 			ret = 0;
886*7c478bd9Sstevel@tonic-gate 			goto donext;
887*7c478bd9Sstevel@tonic-gate 		} else if ((ret = memp_fget(mpf, &argp->pgno,
888*7c478bd9Sstevel@tonic-gate 		    DB_MPOOL_CREATE, &pagep)) != 0)
889*7c478bd9Sstevel@tonic-gate 			goto out;
890*7c478bd9Sstevel@tonic-gate 
891*7c478bd9Sstevel@tonic-gate 	cmp_n = log_compare(lsnp, &LSN(pagep));
892*7c478bd9Sstevel@tonic-gate 	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);
893*7c478bd9Sstevel@tonic-gate 
894*7c478bd9Sstevel@tonic-gate 	if (cmp_p == 0 && redo) {
895*7c478bd9Sstevel@tonic-gate 		/* Need to redo update described. */
896*7c478bd9Sstevel@tonic-gate 		memcpy(pagep, argp->page.data, argp->page.size);
897*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = *lsnp;
898*7c478bd9Sstevel@tonic-gate 		modified = 1;
899*7c478bd9Sstevel@tonic-gate 	} else if (cmp_n == 0 && !redo) {
900*7c478bd9Sstevel@tonic-gate 		/* Need to undo update described. */
901*7c478bd9Sstevel@tonic-gate 		P_INIT(pagep, hcp->hdr->pagesize, argp->pgno, PGNO_INVALID,
902*7c478bd9Sstevel@tonic-gate 		    argp->next_pgno, 0, P_HASH);
903*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = argp->pagelsn;
904*7c478bd9Sstevel@tonic-gate 		modified = 1;
905*7c478bd9Sstevel@tonic-gate 	}
906*7c478bd9Sstevel@tonic-gate 	if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
907*7c478bd9Sstevel@tonic-gate 		goto out;
908*7c478bd9Sstevel@tonic-gate 
909*7c478bd9Sstevel@tonic-gate 	/* Now fix up the "next" page. */
910*7c478bd9Sstevel@tonic-gate donext:	ret = memp_fget(mpf, &argp->next_pgno, 0, &pagep);
911*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
912*7c478bd9Sstevel@tonic-gate 		if (!redo) {
913*7c478bd9Sstevel@tonic-gate 			/*
914*7c478bd9Sstevel@tonic-gate 			 * We are undoing and the page doesn't exist.  That
915*7c478bd9Sstevel@tonic-gate 			 * is equivalent to having a pagelsn of 0, so we
916*7c478bd9Sstevel@tonic-gate 			 * would not have to undo anything.  In this case,
917*7c478bd9Sstevel@tonic-gate 			 * don't bother creating a page.
918*7c478bd9Sstevel@tonic-gate 			 */
919*7c478bd9Sstevel@tonic-gate 			ret = 0;
920*7c478bd9Sstevel@tonic-gate 			goto do_nn;
921*7c478bd9Sstevel@tonic-gate 		} else if ((ret = memp_fget(mpf, &argp->next_pgno,
922*7c478bd9Sstevel@tonic-gate 		    DB_MPOOL_CREATE, &pagep)) != 0)
923*7c478bd9Sstevel@tonic-gate 			goto out;
924*7c478bd9Sstevel@tonic-gate 
925*7c478bd9Sstevel@tonic-gate 	/* There is nothing to do in the REDO case; only UNDO. */
926*7c478bd9Sstevel@tonic-gate 
927*7c478bd9Sstevel@tonic-gate 	cmp_n = log_compare(lsnp, &LSN(pagep));
928*7c478bd9Sstevel@tonic-gate 	if (cmp_n == 0 && !redo) {
929*7c478bd9Sstevel@tonic-gate 		/* Need to undo update described. */
930*7c478bd9Sstevel@tonic-gate 		memcpy(pagep, argp->page.data, argp->page.size);
931*7c478bd9Sstevel@tonic-gate 		modified = 1;
932*7c478bd9Sstevel@tonic-gate 	}
933*7c478bd9Sstevel@tonic-gate 	if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
934*7c478bd9Sstevel@tonic-gate 		goto out;
935*7c478bd9Sstevel@tonic-gate 
936*7c478bd9Sstevel@tonic-gate 	/* Now fix up the next's next page. */
937*7c478bd9Sstevel@tonic-gate do_nn:	if (argp->nnext_pgno == PGNO_INVALID)
938*7c478bd9Sstevel@tonic-gate 		goto done;
939*7c478bd9Sstevel@tonic-gate 
940*7c478bd9Sstevel@tonic-gate 	ret = memp_fget(mpf, &argp->nnext_pgno, 0, &pagep);
941*7c478bd9Sstevel@tonic-gate 	if (ret != 0)
942*7c478bd9Sstevel@tonic-gate 		if (!redo) {
943*7c478bd9Sstevel@tonic-gate 			/*
944*7c478bd9Sstevel@tonic-gate 			 * We are undoing and the page doesn't exist.  That
945*7c478bd9Sstevel@tonic-gate 			 * is equivalent to having a pagelsn of 0, so we
946*7c478bd9Sstevel@tonic-gate 			 * would not have to undo anything.  In this case,
947*7c478bd9Sstevel@tonic-gate 			 * don't bother creating a page.
948*7c478bd9Sstevel@tonic-gate 			 */
949*7c478bd9Sstevel@tonic-gate 			goto done;
950*7c478bd9Sstevel@tonic-gate 		} else if ((ret = memp_fget(mpf, &argp->nnext_pgno,
951*7c478bd9Sstevel@tonic-gate 		    DB_MPOOL_CREATE, &pagep)) != 0)
952*7c478bd9Sstevel@tonic-gate 			goto out;
953*7c478bd9Sstevel@tonic-gate 
954*7c478bd9Sstevel@tonic-gate 	cmp_n = log_compare(lsnp, &LSN(pagep));
955*7c478bd9Sstevel@tonic-gate 	cmp_p = log_compare(&LSN(pagep), &argp->nnextlsn);
956*7c478bd9Sstevel@tonic-gate 
957*7c478bd9Sstevel@tonic-gate 	if (cmp_p == 0 && redo) {
958*7c478bd9Sstevel@tonic-gate 		/* Need to redo update described. */
959*7c478bd9Sstevel@tonic-gate 		PREV_PGNO(pagep) = argp->pgno;
960*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = *lsnp;
961*7c478bd9Sstevel@tonic-gate 		modified = 1;
962*7c478bd9Sstevel@tonic-gate 	} else if (cmp_n == 0 && !redo) {
963*7c478bd9Sstevel@tonic-gate 		/* Need to undo update described. */
964*7c478bd9Sstevel@tonic-gate 		PREV_PGNO(pagep) = argp->next_pgno;
965*7c478bd9Sstevel@tonic-gate 		LSN(pagep) = argp->nnextlsn;
966*7c478bd9Sstevel@tonic-gate 		modified = 1;
967*7c478bd9Sstevel@tonic-gate 	}
968*7c478bd9Sstevel@tonic-gate 	if ((ret = memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
969*7c478bd9Sstevel@tonic-gate 		goto out;
970*7c478bd9Sstevel@tonic-gate 
971*7c478bd9Sstevel@tonic-gate done:	*lsnp = argp->prev_lsn;
972*7c478bd9Sstevel@tonic-gate 	ret = 0;
973*7c478bd9Sstevel@tonic-gate 
974*7c478bd9Sstevel@tonic-gate out:	if (getmeta)
975*7c478bd9Sstevel@tonic-gate 		RELEASE_META(file_dbp, hcp);
976*7c478bd9Sstevel@tonic-gate 	REC_CLOSE;
977*7c478bd9Sstevel@tonic-gate }
978