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