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