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

« back to all changes in this revision

Viewing changes to libdb/txn/txn_util.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) 2001-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_shash.h"
21
 
#include "dbinc/lock.h"
22
 
#include "dbinc/txn.h"
23
 
 
24
 
typedef struct __txn_event TXN_EVENT;
25
 
struct __txn_event {
26
 
        TXN_EVENT_T op;
27
 
        TAILQ_ENTRY(__txn_event) links;
28
 
        union {
29
 
                struct {
30
 
                        /* Delayed remove. */
31
 
                        char *name;
32
 
                        u_int8_t *fileid;
33
 
                } r;
34
 
                struct {
35
 
                        /* Lock event. */
36
 
                        DB_LOCK lock;
37
 
                        u_int32_t locker;
38
 
                        DB *dbp;
39
 
                } t;
40
 
        } u;
41
 
};
42
 
 
43
 
/*
44
 
 * __txn_remevent --
45
 
 *
46
 
 * Creates a remove event that can be added to the commit list.
47
 
 *
48
 
 * PUBLIC: int __txn_remevent __P((DB_ENV *,
49
 
 * PUBLIC:       DB_TXN *, const char *, u_int8_t*));
50
 
 */
51
 
int
52
 
__txn_remevent(dbenv, txn, name, fileid)
53
 
        DB_ENV *dbenv;
54
 
        DB_TXN *txn;
55
 
        const char *name;
56
 
        u_int8_t *fileid;
57
 
{
58
 
        int ret;
59
 
        TXN_EVENT *e;
60
 
 
61
 
        e = NULL;
62
 
        if ((ret = __os_calloc(dbenv, 1, sizeof(TXN_EVENT), &e)) != 0)
63
 
                return (ret);
64
 
 
65
 
        if ((ret = __os_strdup(dbenv, name, &e->u.r.name)) != 0)
66
 
                goto err;
67
 
 
68
 
        if (fileid != NULL) {
69
 
                if ((ret = __os_calloc(dbenv,
70
 
                    1, DB_FILE_ID_LEN, &e->u.r.fileid)) != 0)
71
 
                        return (ret);
72
 
                memcpy(e->u.r.fileid, fileid, DB_FILE_ID_LEN);
73
 
        }
74
 
 
75
 
        e->op = TXN_REMOVE;
76
 
        TAILQ_INSERT_TAIL(&txn->events, e, links);
77
 
 
78
 
        return (0);
79
 
 
80
 
err:    if (e != NULL)
81
 
                __os_free(dbenv, e);
82
 
 
83
 
        return (ret);
84
 
}
85
 
 
86
 
/*
87
 
 * __txn_lockevent --
88
 
 *
89
 
 * Add a lockevent to the commit-queue.  The lock event indicates a locker
90
 
 * trade.
91
 
 *
92
 
 * PUBLIC: int __txn_lockevent __P((DB_ENV *,
93
 
 * PUBLIC:     DB_TXN *, DB *, DB_LOCK *, u_int32_t));
94
 
 */
95
 
int
96
 
__txn_lockevent(dbenv, txn, dbp, lock, locker)
97
 
        DB_ENV *dbenv;
98
 
        DB_TXN *txn;
99
 
        DB *dbp;
100
 
        DB_LOCK *lock;
101
 
        u_int32_t locker;
102
 
{
103
 
        int ret;
104
 
        TXN_EVENT *e;
105
 
 
106
 
        if (!LOCKING_ON(dbenv))
107
 
                return (0);
108
 
 
109
 
        e = NULL;
110
 
        if ((ret = __os_calloc(dbenv, 1, sizeof(TXN_EVENT), &e)) != 0)
111
 
                return (ret);
112
 
 
113
 
        e->u.t.locker = locker;
114
 
        e->u.t.lock = *lock;
115
 
        e->u.t.dbp = dbp;
116
 
        e->op = TXN_TRADE;
117
 
        TAILQ_INSERT_TAIL(&txn->events, e, links);
118
 
 
119
 
        return (0);
120
 
}
121
 
 
122
 
/*
123
 
 * __txn_remlock --
124
 
 *      Remove a lock event because the locker is going away.  We can remove
125
 
 * by lock (using offset) or by locker_id (or by both).
126
 
 *
127
 
 * PUBLIC: void __txn_remlock __P((DB_ENV *, DB_TXN *, DB_LOCK *, u_int32_t));
128
 
 */
129
 
void
130
 
__txn_remlock(dbenv, txn, lock, locker)
131
 
        DB_ENV *dbenv;
132
 
        DB_TXN *txn;
133
 
        DB_LOCK *lock;
134
 
        u_int32_t locker;
135
 
{
136
 
        TXN_EVENT *e, *next_e;
137
 
 
138
 
        for (e = TAILQ_FIRST(&txn->events); e != NULL; e = next_e) {
139
 
                next_e = TAILQ_NEXT(e, links);
140
 
                if ((e->op != TXN_TRADE && e->op != TXN_TRADED) ||
141
 
                    (e->u.t.lock.off != lock->off && e->u.t.locker != locker))
142
 
                        continue;
143
 
                TAILQ_REMOVE(&txn->events, e, links);
144
 
                __os_free(dbenv, e);
145
 
        }
146
 
 
147
 
        return;
148
 
}
149
 
 
150
 
/*
151
 
 * __txn_doevents --
152
 
 * Process the list of events associated with a transaction.  On commit,
153
 
 * apply the events; on abort, just toss the entries.
154
 
 *
155
 
 * PUBLIC: int __txn_doevents __P((DB_ENV *, DB_TXN *, int, int));
156
 
 */
157
 
#define DO_TRADE do {                                                   \
158
 
        memset(&req, 0, sizeof(req));                                   \
159
 
        req.lock = e->u.t.lock;                                         \
160
 
        req.op = DB_LOCK_TRADE;                                         \
161
 
        t_ret = __lock_vec(dbenv, e->u.t.locker, 0, &req, 1, NULL);     \
162
 
        if (t_ret == 0)                                                 \
163
 
                e->u.t.dbp->cur_lid = e->u.t.locker;                    \
164
 
        else if (t_ret == DB_NOTFOUND)                                  \
165
 
                t_ret = 0;                                              \
166
 
        if (t_ret != 0 && ret == 0)                                     \
167
 
                ret = t_ret;                                            \
168
 
        e->op = TXN_TRADED;                                             \
169
 
} while (0)
170
 
 
171
 
int
172
 
__txn_doevents(dbenv, txn, is_commit, preprocess)
173
 
        DB_ENV *dbenv;
174
 
        DB_TXN *txn;
175
 
        int is_commit, preprocess;
176
 
{
177
 
        DB_LOCKREQ req;
178
 
        TXN_EVENT *e;
179
 
        int ret, t_ret;
180
 
 
181
 
        ret = 0;
182
 
 
183
 
        /*
184
 
         * This phase only gets called if we have a phase where we
185
 
         * release read locks.  Since not all paths will call this
186
 
         * phase, we have to check for it below as well.  So, when
187
 
         * we do the trade, we update the opcode of the entry so that
188
 
         * we don't try the trade again.
189
 
         */
190
 
        if (preprocess) {
191
 
                for (e = TAILQ_FIRST(&txn->events);
192
 
                    e != NULL; e = TAILQ_NEXT(e, links)) {
193
 
                        if (e->op != TXN_TRADE)
194
 
                                continue;
195
 
                        DO_TRADE;
196
 
                }
197
 
                return (ret);
198
 
        }
199
 
 
200
 
        while ((e = TAILQ_FIRST(&txn->events)) != NULL) {
201
 
                TAILQ_REMOVE(&txn->events, e, links);
202
 
                if (!is_commit)
203
 
                        goto dofree;
204
 
                switch (e->op) {
205
 
                case TXN_REMOVE:
206
 
                        if (e->u.r.fileid != NULL) {
207
 
                                if ((t_ret = dbenv->memp_nameop(dbenv,
208
 
                                    e->u.r.fileid,
209
 
                                    NULL, e->u.r.name, NULL)) != 0 && ret == 0)
210
 
                                        ret = t_ret;
211
 
                                __os_free(dbenv, e->u.r.fileid);
212
 
                        } else if ((t_ret =
213
 
                            __os_unlink(dbenv, e->u.r.name)) != 0 && ret == 0)
214
 
                                ret = t_ret;
215
 
                        __os_free(dbenv, e->u.r.name);
216
 
                        break;
217
 
                case TXN_TRADE:
218
 
                        DO_TRADE;
219
 
                        /* Fall through */
220
 
                case TXN_TRADED:
221
 
                        /* Downgrade the lock. */
222
 
                        if ((t_ret = __lock_downgrade(dbenv,
223
 
                            &e->u.t.lock, DB_LOCK_READ, 0)) != 0 && ret == 0)
224
 
                                ret = t_ret;
225
 
                        break;
226
 
                default:
227
 
                        /* This had better never happen. */
228
 
                        DB_ASSERT(0);
229
 
                }
230
 
dofree:         __os_free(dbenv, e);
231
 
        }
232
 
 
233
 
        return (ret);
234
 
}