2
* See the file LICENSE for redistribution information.
4
* Copyright (c) 1996-2002
5
* Sleepycat Software. All rights reserved.
11
static const char revid[] = "$Id$";
14
#ifndef NO_SYSTEM_INCLUDES
15
#include <sys/types.h>
20
#include "dbinc/db_page.h"
21
#include "dbinc/db_shash.h"
22
#include "dbinc/btree.h"
23
#include "dbinc/lock.h"
27
* Traverse a chain of overflow pages and call the callback routine
28
* on each one. The calling convention for the callback is:
29
* callback(dbp, page, cookie, did_put),
30
* where did_put is a return value indicating if the page in question has
31
* already been returned to the mpool.
33
* PUBLIC: int __db_traverse_big __P((DB *,
34
* PUBLIC: db_pgno_t, int (*)(DB *, PAGE *, void *, int *), void *));
37
__db_traverse_big(dbp, pgno, callback, cookie)
40
int (*callback) __P((DB *, PAGE *, void *, int *));
51
if ((ret = mpf->get(mpf, &pgno, 0, &p)) != 0)
54
if ((ret = callback(dbp, p, cookie, &did_put)) == 0 &&
56
ret = mpf->put(mpf, p, 0);
57
} while (ret == 0 && pgno != PGNO_INVALID);
63
* __db_reclaim_callback
64
* This is the callback routine used during a delete of a subdatabase.
65
* we are traversing a btree or hash table and trying to free all the
66
* pages. Since they share common code for duplicates and overflow
67
* items, we traverse them identically and use this routine to do the
68
* actual free. The reason that this is callback is because hash uses
69
* the same traversal code for statistics gathering.
71
* PUBLIC: int __db_reclaim_callback __P((DB *, PAGE *, void *, int *));
74
__db_reclaim_callback(dbp, p, cookie, putp)
84
if ((ret = __db_free(cookie, p)) != 0)
92
* __db_truncate_callback
93
* This is the callback routine used during a truncate.
94
* we are traversing a btree or hash table and trying to free all the
97
* PUBLIC: int __db_truncate_callback __P((DB *, PAGE *, void *, int *));
100
__db_truncate_callback(dbp, p, cookie, putp)
110
db_indx_t indx, len, off, tlen, top;
112
db_trunc_param *param;
123
/* Skip for off-page duplicates and deleted items. */
124
for (indx = 0; indx < top; indx += P_INDX) {
125
type = GET_BKEYDATA(dbp, p, indx + O_INDX)->type;
126
if (!B_DISSET(type) && B_TYPE(type) != B_DUPLICATE)
133
if (dbp->type != DB_HASH &&
134
((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) {
135
type = dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE;
140
if (DBC_LOGGING(param->dbc)) {
141
if ((ret = __db_ovref_log(dbp, param->dbc->txn,
142
&LSN(p), 0, p->pgno, -1, &LSN(p))) != 0)
145
LSN_NOT_LOGGED(LSN(p));
146
if (--OV_REF(p) != 0)
151
if (((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) {
157
/* Correct for deleted items. */
158
for (indx = 0; indx < top; indx += O_INDX)
159
if (!B_DISSET(GET_BKEYDATA(dbp, p, indx)->type))
164
/* Correct for on-page duplicates and deleted items. */
165
for (indx = 0; indx < top; indx += P_INDX) {
166
switch (*H_PAIRDATA(dbp, p, indx)) {
174
tlen = LEN_HDATA(dbp, p, 0, indx);
175
hk = H_PAIRDATA(dbp, p, indx);
176
for (off = 0; off < tlen;
177
off += len + 2 * sizeof (db_indx_t)) {
181
+ off, sizeof(db_indx_t));
185
/* Don't free the head of the bucket. */
186
if (PREV_PGNO(p) == PGNO_INVALID) {
190
if (DBC_LOGGING(param->dbc)) {
192
if ((ret = __db_lget(param->dbc, LCK_ALWAYS,
193
pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
195
if ((ret = mpf->get(mpf,
196
&pgno, 0, (PAGE **)&meta)) != 0) {
199
memset(&ldbt, 0, sizeof(ldbt));
201
ldbt.size = P_OVERHEAD(dbp);
202
if ((ret = __db_pg_free_log(dbp,
203
param->dbc->txn, &LSN(meta), 0,
205
PGNO_BASE_MD, &ldbt, meta->free)) != 0)
210
__db_pg_alloc_log(dbp,
211
param->dbc->txn, &LSN(meta), 0,
212
&LSN(meta), PGNO_BASE_MD,
213
&p->lsn, p->pgno, type, meta->free)) != 0) {
214
err: (void)mpf->put(mpf, (PAGE *)meta, 0);
215
(void)__TLPUT(param->dbc, metalock);
220
if ((ret = mpf->put(mpf,
221
(PAGE *)meta, DB_MPOOL_DIRTY)) != 0) {
222
(void)__TLPUT(param->dbc, metalock);
225
if ((ret = __TLPUT(param->dbc, metalock)) != 0)
228
LSN_NOT_LOGGED(LSN(p));
230
P_INIT(p, dbp->pgsize, PGNO(p), PGNO_INVALID,
231
PGNO_INVALID, type == P_HASH ? 0 : 1, type);
235
return (__db_pgfmt(dbp->dbenv, p->pgno));
239
if ((ret = __db_free(param->dbc, p)) != 0)
242
if ((ret = mpf->put(mpf, p, DB_MPOOL_DIRTY)) != 0)