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