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

« back to all changes in this revision

Viewing changes to libdb/db/db_dup.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
 
 
17
 
#include <string.h>
18
 
#endif
19
 
 
20
 
#include "db_int.h"
21
 
#include "dbinc/db_page.h"
22
 
#include "dbinc/db_shash.h"
23
 
#include "dbinc/lock.h"
24
 
#include "dbinc/db_am.h"
25
 
 
26
 
/*
27
 
 * __db_ditem --
28
 
 *      Remove an item from a page.
29
 
 *
30
 
 * PUBLIC:  int __db_ditem __P((DBC *, PAGE *, u_int32_t, u_int32_t));
31
 
 */
32
 
int
33
 
__db_ditem(dbc, pagep, indx, nbytes)
34
 
        DBC *dbc;
35
 
        PAGE *pagep;
36
 
        u_int32_t indx, nbytes;
37
 
{
38
 
        DB *dbp;
39
 
        DBT ldbt;
40
 
        db_indx_t cnt, *inp, offset;
41
 
        int ret;
42
 
        u_int8_t *from;
43
 
 
44
 
        dbp = dbc->dbp;
45
 
        if (DBC_LOGGING(dbc)) {
46
 
                ldbt.data = P_ENTRY(dbp, pagep, indx);
47
 
                ldbt.size = nbytes;
48
 
                if ((ret = __db_addrem_log(dbp, dbc->txn,
49
 
                    &LSN(pagep), 0, DB_REM_DUP, PGNO(pagep),
50
 
                    (u_int32_t)indx, nbytes, &ldbt, NULL, &LSN(pagep))) != 0)
51
 
                        return (ret);
52
 
        } else
53
 
                LSN_NOT_LOGGED(LSN(pagep));
54
 
 
55
 
        /*
56
 
         * If there's only a single item on the page, we don't have to
57
 
         * work hard.
58
 
         */
59
 
        if (NUM_ENT(pagep) == 1) {
60
 
                NUM_ENT(pagep) = 0;
61
 
                HOFFSET(pagep) = dbp->pgsize;
62
 
                return (0);
63
 
        }
64
 
 
65
 
        inp = P_INP(dbp, pagep);
66
 
        /*
67
 
         * Pack the remaining key/data items at the end of the page.  Use
68
 
         * memmove(3), the regions may overlap.
69
 
         */
70
 
        from = (u_int8_t *)pagep + HOFFSET(pagep);
71
 
        DB_ASSERT((int)inp[indx] - HOFFSET(pagep) >= 0);
72
 
        memmove(from + nbytes, from, inp[indx] - HOFFSET(pagep));
73
 
        HOFFSET(pagep) += nbytes;
74
 
 
75
 
        /* Adjust the indices' offsets. */
76
 
        offset = inp[indx];
77
 
        for (cnt = 0; cnt < NUM_ENT(pagep); ++cnt)
78
 
                if (inp[cnt] < offset)
79
 
                        inp[cnt] += nbytes;
80
 
 
81
 
        /* Shift the indices down. */
82
 
        --NUM_ENT(pagep);
83
 
        if (indx != NUM_ENT(pagep))
84
 
                memmove(&inp[indx], &inp[indx + 1],
85
 
                    sizeof(db_indx_t) * (NUM_ENT(pagep) - indx));
86
 
 
87
 
        return (0);
88
 
}
89
 
 
90
 
/*
91
 
 * __db_pitem --
92
 
 *      Put an item on a page.
93
 
 *
94
 
 * PUBLIC: int __db_pitem
95
 
 * PUBLIC:     __P((DBC *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *));
96
 
 */
97
 
int
98
 
__db_pitem(dbc, pagep, indx, nbytes, hdr, data)
99
 
        DBC *dbc;
100
 
        PAGE *pagep;
101
 
        u_int32_t indx;
102
 
        u_int32_t nbytes;
103
 
        DBT *hdr, *data;
104
 
{
105
 
        DB *dbp;
106
 
        BKEYDATA bk;
107
 
        DBT thdr;
108
 
        db_indx_t *inp;
109
 
        int ret;
110
 
        u_int8_t *p;
111
 
 
112
 
        dbp = dbc->dbp;
113
 
        if (nbytes > P_FREESPACE(dbp, pagep)) {
114
 
                DB_ASSERT(nbytes <= P_FREESPACE(dbp, pagep));
115
 
                return (EINVAL);
116
 
        }
117
 
        /*
118
 
         * Put a single item onto a page.  The logic figuring out where to
119
 
         * insert and whether it fits is handled in the caller.  All we do
120
 
         * here is manage the page shuffling.  We cheat a little bit in that
121
 
         * we don't want to copy the dbt on a normal put twice.  If hdr is
122
 
         * NULL, we create a BKEYDATA structure on the page, otherwise, just
123
 
         * copy the caller's information onto the page.
124
 
         *
125
 
         * This routine is also used to put entries onto the page where the
126
 
         * entry is pre-built, e.g., during recovery.  In this case, the hdr
127
 
         * will point to the entry, and the data argument will be NULL.
128
 
         *
129
 
         * !!!
130
 
         * There's a tremendous potential for off-by-one errors here, since
131
 
         * the passed in header sizes must be adjusted for the structure's
132
 
         * placeholder for the trailing variable-length data field.
133
 
         */
134
 
        if (DBC_LOGGING(dbc)) {
135
 
                if ((ret = __db_addrem_log(dbp, dbc->txn,
136
 
                    &LSN(pagep), 0, DB_ADD_DUP, PGNO(pagep),
137
 
                    (u_int32_t)indx, nbytes, hdr, data, &LSN(pagep))) != 0)
138
 
                        return (ret);
139
 
        } else
140
 
                LSN_NOT_LOGGED(LSN(pagep));
141
 
 
142
 
        if (hdr == NULL) {
143
 
                B_TSET(bk.type, B_KEYDATA, 0);
144
 
                bk.len = data == NULL ? 0 : data->size;
145
 
 
146
 
                thdr.data = &bk;
147
 
                thdr.size = SSZA(BKEYDATA, data);
148
 
                hdr = &thdr;
149
 
        }
150
 
        inp = P_INP(dbp, pagep);
151
 
 
152
 
        /* Adjust the index table, then put the item on the page. */
153
 
        if (indx != NUM_ENT(pagep))
154
 
                memmove(&inp[indx + 1], &inp[indx],
155
 
                    sizeof(db_indx_t) * (NUM_ENT(pagep) - indx));
156
 
        HOFFSET(pagep) -= nbytes;
157
 
        inp[indx] = HOFFSET(pagep);
158
 
        ++NUM_ENT(pagep);
159
 
 
160
 
        p = P_ENTRY(dbp, pagep, indx);
161
 
        memcpy(p, hdr->data, hdr->size);
162
 
        if (data != NULL)
163
 
                memcpy(p + hdr->size, data->data, data->size);
164
 
 
165
 
        return (0);
166
 
}
167
 
 
168
 
/*
169
 
 * __db_relink --
170
 
 *      Relink around a deleted page.
171
 
 *
172
 
 * PUBLIC: int __db_relink __P((DBC *, u_int32_t, PAGE *, PAGE **, int));
173
 
 */
174
 
int
175
 
__db_relink(dbc, add_rem, pagep, new_next, needlock)
176
 
        DBC *dbc;
177
 
        u_int32_t add_rem;
178
 
        PAGE *pagep, **new_next;
179
 
        int needlock;
180
 
{
181
 
        DB *dbp;
182
 
        PAGE *np, *pp;
183
 
        DB_LOCK npl, ppl;
184
 
        DB_LSN *nlsnp, *plsnp, ret_lsn;
185
 
        DB_MPOOLFILE *mpf;
186
 
        int ret;
187
 
 
188
 
        dbp = dbc->dbp;
189
 
        np = pp = NULL;
190
 
        LOCK_INIT(npl);
191
 
        LOCK_INIT(ppl);
192
 
        nlsnp = plsnp = NULL;
193
 
        mpf = dbp->mpf;
194
 
        ret = 0;
195
 
 
196
 
        /*
197
 
         * Retrieve and lock the one/two pages.  For a remove, we may need
198
 
         * two pages (the before and after).  For an add, we only need one
199
 
         * because, the split took care of the prev.
200
 
         */
201
 
        if (pagep->next_pgno != PGNO_INVALID) {
202
 
                if (needlock && (ret = __db_lget(dbc,
203
 
                    0, pagep->next_pgno, DB_LOCK_WRITE, 0, &npl)) != 0)
204
 
                        goto err;
205
 
                if ((ret = mpf->get(mpf, &pagep->next_pgno, 0, &np)) != 0) {
206
 
                        __db_pgerr(dbp, pagep->next_pgno, ret);
207
 
                        goto err;
208
 
                }
209
 
                nlsnp = &np->lsn;
210
 
        }
211
 
        if (add_rem == DB_REM_PAGE && pagep->prev_pgno != PGNO_INVALID) {
212
 
                if (needlock && (ret = __db_lget(dbc,
213
 
                    0, pagep->prev_pgno, DB_LOCK_WRITE, 0, &ppl)) != 0)
214
 
                        goto err;
215
 
                if ((ret = mpf->get(mpf, &pagep->prev_pgno, 0, &pp)) != 0) {
216
 
                        __db_pgerr(dbp, pagep->next_pgno, ret);
217
 
                        goto err;
218
 
                }
219
 
                plsnp = &pp->lsn;
220
 
        }
221
 
 
222
 
        /* Log the change. */
223
 
        if (DBC_LOGGING(dbc)) {
224
 
                if ((ret = __db_relink_log(dbp, dbc->txn, &ret_lsn, 0, add_rem,
225
 
                    pagep->pgno, &pagep->lsn, pagep->prev_pgno, plsnp,
226
 
                    pagep->next_pgno, nlsnp)) != 0)
227
 
                        goto err;
228
 
        } else
229
 
                LSN_NOT_LOGGED(ret_lsn);
230
 
        if (np != NULL)
231
 
                np->lsn = ret_lsn;
232
 
        if (pp != NULL)
233
 
                pp->lsn = ret_lsn;
234
 
        if (add_rem == DB_REM_PAGE)
235
 
                pagep->lsn = ret_lsn;
236
 
 
237
 
        /*
238
 
         * Modify and release the two pages.
239
 
         *
240
 
         * !!!
241
 
         * The parameter new_next gets set to the page following the page we
242
 
         * are removing.  If there is no following page, then new_next gets
243
 
         * set to NULL.
244
 
         */
245
 
        if (np != NULL) {
246
 
                if (add_rem == DB_ADD_PAGE)
247
 
                        np->prev_pgno = pagep->pgno;
248
 
                else
249
 
                        np->prev_pgno = pagep->prev_pgno;
250
 
                if (new_next == NULL)
251
 
                        ret = mpf->put(mpf, np, DB_MPOOL_DIRTY);
252
 
                else {
253
 
                        *new_next = np;
254
 
                        ret = mpf->set(mpf, np, DB_MPOOL_DIRTY);
255
 
                }
256
 
                if (ret != 0)
257
 
                        goto err;
258
 
                if (needlock)
259
 
                        (void)__TLPUT(dbc, npl);
260
 
        } else if (new_next != NULL)
261
 
                *new_next = NULL;
262
 
 
263
 
        if (pp != NULL) {
264
 
                pp->next_pgno = pagep->next_pgno;
265
 
                if ((ret = mpf->put(mpf, pp, DB_MPOOL_DIRTY)) != 0)
266
 
                        goto err;
267
 
                if (needlock)
268
 
                        (void)__TLPUT(dbc, ppl);
269
 
        }
270
 
        return (0);
271
 
 
272
 
err:    if (np != NULL)
273
 
                (void)mpf->put(mpf, np, 0);
274
 
        if (needlock)
275
 
                (void)__TLPUT(dbc, npl);
276
 
        if (pp != NULL)
277
 
                (void)mpf->put(mpf, pp, 0);
278
 
        if (needlock)
279
 
                (void)__TLPUT(dbc, ppl);
280
 
        return (ret);
281
 
}