~ubuntu-branches/ubuntu/maverick/evolution-data-server/maverick-proposed

« back to all changes in this revision

Viewing changes to libdb/db/db_reclaim.c

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-05-17 17:02:06 UTC
  • mfrom: (1.1.79 upstream) (1.6.12 experimental)
  • Revision ID: james.westby@ubuntu.com-20100517170206-4ufr52vwrhh26yh0
Tags: 2.30.1-1ubuntu1
* Merge from debian experimental. Remaining change:
  (LP: #42199, #229669, #173703, #360344, #508494)
  + debian/control:
    - add Vcs-Bzr tag
    - don't use libgnome
    - Use Breaks instead of Conflicts against evolution 2.25 and earlier.
  + debian/evolution-data-server.install,
    debian/patches/45_libcamel_providers_version.patch:
    - use the upstream versioning, not a Debian-specific one 
  + debian/libedata-book1.2-dev.install, debian/libebackend-1.2-dev.install,
    debian/libcamel1.2-dev.install, debian/libedataserverui1.2-dev.install:
    - install html documentation
  + debian/rules:
    - don't build documentation it's shipped with the tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*-
2
 
 * See the file LICENSE for redistribution information.
3
 
 *
4
 
 * Copyright (c) 1996-2002
5
 
 *      Sleepycat Software.  All rights reserved.
6
 
 */
7
 
 
8
 
#include "db_config.h"
9
 
 
10
 
#ifndef lint
11
 
static const char revid[] = "$Id$";
12
 
#endif /* not lint */
13
 
 
14
 
#ifndef NO_SYSTEM_INCLUDES
15
 
#include <sys/types.h>
16
 
#include <string.h>
17
 
#endif
18
 
 
19
 
#include "db_int.h"
20
 
#include "dbinc/db_page.h"
21
 
#include "dbinc/db_shash.h"
22
 
#include "dbinc/btree.h"
23
 
#include "dbinc/lock.h"
24
 
 
25
 
/*
26
 
 * __db_traverse_big
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.
32
 
 *
33
 
 * PUBLIC: int __db_traverse_big __P((DB *,
34
 
 * PUBLIC:     db_pgno_t, int (*)(DB *, PAGE *, void *, int *), void *));
35
 
 */
36
 
int
37
 
__db_traverse_big(dbp, pgno, callback, cookie)
38
 
        DB *dbp;
39
 
        db_pgno_t pgno;
40
 
        int (*callback) __P((DB *, PAGE *, void *, int *));
41
 
        void *cookie;
42
 
{
43
 
        DB_MPOOLFILE *mpf;
44
 
        PAGE *p;
45
 
        int did_put, ret;
46
 
 
47
 
        mpf = dbp->mpf;
48
 
 
49
 
        do {
50
 
                did_put = 0;
51
 
                if ((ret = mpf->get(mpf, &pgno, 0, &p)) != 0)
52
 
                        return (ret);
53
 
                pgno = NEXT_PGNO(p);
54
 
                if ((ret = callback(dbp, p, cookie, &did_put)) == 0 &&
55
 
                    !did_put)
56
 
                        ret = mpf->put(mpf, p, 0);
57
 
        } while (ret == 0 && pgno != PGNO_INVALID);
58
 
 
59
 
        return (ret);
60
 
}
61
 
 
62
 
/*
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.
70
 
 *
71
 
 * PUBLIC: int __db_reclaim_callback __P((DB *, PAGE *, void *, int *));
72
 
 */
73
 
int
74
 
__db_reclaim_callback(dbp, p, cookie, putp)
75
 
        DB *dbp;
76
 
        PAGE *p;
77
 
        void *cookie;
78
 
        int *putp;
79
 
{
80
 
        int ret;
81
 
 
82
 
        COMPQUIET(dbp, NULL);
83
 
 
84
 
        if ((ret = __db_free(cookie, p)) != 0)
85
 
                return (ret);
86
 
        *putp = 1;
87
 
 
88
 
        return (0);
89
 
}
90
 
 
91
 
/*
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
95
 
 * pages.
96
 
 *
97
 
 * PUBLIC: int __db_truncate_callback __P((DB *, PAGE *, void *, int *));
98
 
 */
99
 
int
100
 
__db_truncate_callback(dbp, p, cookie, putp)
101
 
        DB *dbp;
102
 
        PAGE *p;
103
 
        void *cookie;
104
 
        int *putp;
105
 
{
106
 
        DBMETA *meta;
107
 
        DBT ldbt;
108
 
        DB_LOCK metalock;
109
 
        DB_MPOOLFILE *mpf;
110
 
        db_indx_t indx, len, off, tlen, top;
111
 
        db_pgno_t pgno;
112
 
        db_trunc_param *param;
113
 
        u_int8_t *hk, type;
114
 
        int ret;
115
 
 
116
 
        top = NUM_ENT(p);
117
 
        mpf = dbp->mpf;
118
 
        param = cookie;
119
 
        *putp = 1;
120
 
 
121
 
        switch (TYPE(p)) {
122
 
        case P_LBTREE:
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)
127
 
                                ++param->count;
128
 
                }
129
 
                /* FALLTHROUGH */
130
 
        case P_IBTREE:
131
 
        case P_IRECNO:
132
 
        case P_INVALID:
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;
136
 
                        goto reinit;
137
 
                }
138
 
                break;
139
 
        case P_OVERFLOW:
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)
143
 
                                return (ret);
144
 
                } else
145
 
                        LSN_NOT_LOGGED(LSN(p));
146
 
                if (--OV_REF(p) != 0)
147
 
                        *putp = 0;
148
 
                break;
149
 
        case P_LRECNO:
150
 
                param->count += top;
151
 
                if (((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) {
152
 
                        type = P_LRECNO;
153
 
                        goto reinit;
154
 
                }
155
 
                break;
156
 
        case P_LDUP:
157
 
                /* Correct for deleted items. */
158
 
                for (indx = 0; indx < top; indx += O_INDX)
159
 
                        if (!B_DISSET(GET_BKEYDATA(dbp, p, indx)->type))
160
 
                                ++param->count;
161
 
 
162
 
                break;
163
 
        case P_HASH:
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)) {
167
 
                        case H_OFFDUP:
168
 
                        case H_OFFPAGE:
169
 
                                break;
170
 
                        case H_KEYDATA:
171
 
                                ++param->count;
172
 
                                break;
173
 
                        case H_DUPLICATE:
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)) {
178
 
                                        ++param->count;
179
 
                                        memcpy(&len,
180
 
                                            HKEYDATA_DATA(hk)
181
 
                                            + off, sizeof(db_indx_t));
182
 
                                }
183
 
                        }
184
 
                }
185
 
                /* Don't free the head of the bucket. */
186
 
                if (PREV_PGNO(p) == PGNO_INVALID) {
187
 
                        type = P_HASH;
188
 
 
189
 
reinit:                 *putp = 0;
190
 
                        if (DBC_LOGGING(param->dbc)) {
191
 
                                pgno = PGNO_BASE_MD;
192
 
                                if ((ret = __db_lget(param->dbc, LCK_ALWAYS,
193
 
                                    pgno, DB_LOCK_WRITE, 0, &metalock)) != 0)
194
 
                                        return (ret);
195
 
                                if ((ret = mpf->get(mpf,
196
 
                                    &pgno, 0, (PAGE **)&meta)) != 0) {
197
 
                                        goto err;
198
 
                                }
199
 
                                memset(&ldbt, 0, sizeof(ldbt));
200
 
                                ldbt.data = p;
201
 
                                ldbt.size = P_OVERHEAD(dbp);
202
 
                                if ((ret = __db_pg_free_log(dbp,
203
 
                                    param->dbc->txn, &LSN(meta), 0,
204
 
                                    p->pgno, &LSN(meta),
205
 
                                    PGNO_BASE_MD, &ldbt, meta->free)) != 0)
206
 
                                        goto err;
207
 
                                LSN(p) = LSN(meta);
208
 
 
209
 
                                if ((ret =
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);
216
 
                                        return (ret);
217
 
                                }
218
 
                                LSN(p) = LSN(meta);
219
 
 
220
 
                                if ((ret = mpf->put(mpf,
221
 
                                    (PAGE *)meta, DB_MPOOL_DIRTY)) != 0) {
222
 
                                        (void)__TLPUT(param->dbc, metalock);
223
 
                                        return (ret);
224
 
                                }
225
 
                                if ((ret = __TLPUT(param->dbc, metalock)) != 0)
226
 
                                        return (ret);
227
 
                        } else
228
 
                                LSN_NOT_LOGGED(LSN(p));
229
 
 
230
 
                        P_INIT(p, dbp->pgsize, PGNO(p), PGNO_INVALID,
231
 
                            PGNO_INVALID, type == P_HASH ? 0 : 1, type);
232
 
                }
233
 
                break;
234
 
        default:
235
 
                return (__db_pgfmt(dbp->dbenv, p->pgno));
236
 
        }
237
 
 
238
 
        if (*putp == 1) {
239
 
                if ((ret = __db_free(param->dbc, p)) != 0)
240
 
                        return (ret);
241
 
        } else {
242
 
                if ((ret = mpf->put(mpf, p, DB_MPOOL_DIRTY)) != 0)
243
 
                        return (ret);
244
 
                *putp = 1;
245
 
        }
246
 
 
247
 
        return (0);
248
 
}