1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996, 1997, 1998, 1999, 2000
* Sleepycat Software. All rights reserved.
*/
#include "db_config.h"
#ifndef lint
static const char revid[] = "$Id: db_reclaim.c,v 11.5 2000/04/07 14:26:58 bostic Exp $";
#endif /* not lint */
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#endif
#include "db_int.h"
#include "db_page.h"
#include "db_am.h"
/*
* Assume that we enter with a valid pgno. We traverse a set of
* duplicate pages. The format of the callback routine is:
* callback(dbp, page, cookie, did_put). did_put is an output
* value that will be set to 1 by the callback routine if it
* already put the page back. Otherwise, this routine must
* put the page.
*
* PUBLIC: int __db_traverse_dup __P((DB *,
* PUBLIC: db_pgno_t, int (*)(DB *, PAGE *, void *, int *), void *));
*/
int
__db_traverse_dup(dbp, pgno, callback, cookie)
DB *dbp;
db_pgno_t pgno;
int (*callback) __P((DB *, PAGE *, void *, int *));
void *cookie;
{
PAGE *p;
int did_put, i, opgno, ret;
do {
did_put = 0;
if ((ret = memp_fget(dbp->mpf, &pgno, 0, &p)) != 0)
return (ret);
pgno = NEXT_PGNO(p);
for (i = 0; i < NUM_ENT(p); i++) {
if (B_TYPE(GET_BKEYDATA(p, i)->type) == B_OVERFLOW) {
opgno = GET_BOVERFLOW(p, i)->pgno;
if ((ret = __db_traverse_big(dbp,
opgno, callback, cookie)) != 0)
goto err;
}
}
if ((ret = callback(dbp, p, cookie, &did_put)) != 0)
goto err;
if (!did_put)
if ((ret = memp_fput(dbp->mpf, p, 0)) != 0)
return (ret);
} while (pgno != PGNO_INVALID);
if (0) {
err: if (did_put == 0)
(void)memp_fput(dbp->mpf, p, 0);
}
return (ret);
}
/*
* __db_traverse_big
* Traverse a chain of overflow pages and call the callback routine
* on each one. The calling convention for the callback is:
* callback(dbp, page, cookie, did_put),
* where did_put is a return value indicating if the page in question has
* already been returned to the mpool.
*
* PUBLIC: int __db_traverse_big __P((DB *,
* PUBLIC: db_pgno_t, int (*)(DB *, PAGE *, void *, int *), void *));
*/
int
__db_traverse_big(dbp, pgno, callback, cookie)
DB *dbp;
db_pgno_t pgno;
int (*callback) __P((DB *, PAGE *, void *, int *));
void *cookie;
{
PAGE *p;
int did_put, ret;
do {
did_put = 0;
if ((ret = memp_fget(dbp->mpf, &pgno, 0, &p)) != 0)
return (ret);
pgno = NEXT_PGNO(p);
if ((ret = callback(dbp, p, cookie, &did_put)) == 0 &&
!did_put)
ret = memp_fput(dbp->mpf, p, 0);
} while (ret == 0 && pgno != PGNO_INVALID);
return (ret);
}
/*
* __db_reclaim_callback
* This is the callback routine used during a delete of a subdatabase.
* we are traversing a btree or hash table and trying to free all the
* pages. Since they share common code for duplicates and overflow
* items, we traverse them identically and use this routine to do the
* actual free. The reason that this is callback is because hash uses
* the same traversal code for statistics gathering.
*
* PUBLIC: int __db_reclaim_callback __P((DB *, PAGE *, void *, int *));
*/
int
__db_reclaim_callback(dbp, p, cookie, putp)
DB *dbp;
PAGE *p;
void *cookie;
int *putp;
{
int ret;
COMPQUIET(dbp, NULL);
if ((ret = __db_free(cookie, p)) != 0)
return (ret);
*putp = 1;
return (0);
}
|