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

« back to all changes in this revision

Viewing changes to libdb/rpc_client/client.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
 
#ifdef HAVE_RPC
15
 
#ifndef NO_SYSTEM_INCLUDES
16
 
#include <sys/types.h>
17
 
 
18
 
#ifdef HAVE_VXWORKS
19
 
#include <rpcLib.h>
20
 
#endif
21
 
#include <rpc/rpc.h>
22
 
 
23
 
#include <ctype.h>
24
 
#include <stdlib.h>
25
 
#include <string.h>
26
 
#include <unistd.h>
27
 
#endif
28
 
 
29
 
#include "db_int.h"
30
 
#include "dbinc/db_page.h"
31
 
#include "dbinc/db_am.h"
32
 
#include "dbinc/txn.h"
33
 
 
34
 
#include "dbinc_auto/db_server.h"
35
 
#include "dbinc_auto/rpc_client_ext.h"
36
 
 
37
 
static int __dbcl_c_destroy __P((DBC *));
38
 
static int __dbcl_txn_close __P((DB_ENV *));
39
 
 
40
 
/*
41
 
 * __dbcl_envrpcserver --
42
 
 *      Initialize an environment's server.
43
 
 *
44
 
 * PUBLIC: int __dbcl_envrpcserver
45
 
 * PUBLIC:     __P((DB_ENV *, void *, const char *, long, long, u_int32_t));
46
 
 */
47
 
int
48
 
__dbcl_envrpcserver(dbenv, clnt, host, tsec, ssec, flags)
49
 
        DB_ENV *dbenv;
50
 
        void *clnt;
51
 
        const char *host;
52
 
        long tsec, ssec;
53
 
        u_int32_t flags;
54
 
{
55
 
        CLIENT *cl;
56
 
        struct timeval tp;
57
 
 
58
 
        COMPQUIET(flags, 0);
59
 
 
60
 
#ifdef HAVE_VXWORKS
61
 
        if (rpcTaskInit() != 0) {
62
 
                __db_err(dbenv, "Could not initialize VxWorks RPC");
63
 
                return (ERROR);
64
 
        }
65
 
#endif
66
 
        if (RPC_ON(dbenv)) {
67
 
                __db_err(dbenv, "Already set an RPC handle");
68
 
                return (EINVAL);
69
 
        }
70
 
        /*
71
 
         * Only create the client and set its timeout if the user
72
 
         * did not pass us a client structure to begin with.
73
 
         */
74
 
        if (clnt == NULL) {
75
 
                if ((cl = clnt_create((char *)host, DB_RPC_SERVERPROG,
76
 
                    DB_RPC_SERVERVERS, "tcp")) == NULL) {
77
 
                        __db_err(dbenv, clnt_spcreateerror((char *)host));
78
 
                        return (DB_NOSERVER);
79
 
                }
80
 
                if (tsec != 0) {
81
 
                        tp.tv_sec = tsec;
82
 
                        tp.tv_usec = 0;
83
 
                        (void)clnt_control(cl, CLSET_TIMEOUT, (char *)&tp);
84
 
                }
85
 
        } else {
86
 
                cl = (CLIENT *)clnt;
87
 
                F_SET(dbenv, DB_ENV_RPCCLIENT_GIVEN);
88
 
        }
89
 
        dbenv->cl_handle = cl;
90
 
 
91
 
        return (__dbcl_env_create(dbenv, ssec));
92
 
}
93
 
 
94
 
/*
95
 
 * __dbcl_env_open_wrap --
96
 
 *      Wrapper function for DB_ENV->open function for clients.
97
 
 *      We need a wrapper function to deal with DB_USE_ENVIRON* flags
98
 
 *      and we don't want to complicate the generated code for env_open.
99
 
 *
100
 
 * PUBLIC: int __dbcl_env_open_wrap
101
 
 * PUBLIC:     __P((DB_ENV *, const char *, u_int32_t, int));
102
 
 */
103
 
int
104
 
__dbcl_env_open_wrap(dbenv, home, flags, mode)
105
 
        DB_ENV * dbenv;
106
 
        const char * home;
107
 
        u_int32_t flags;
108
 
        int mode;
109
 
{
110
 
        int ret;
111
 
 
112
 
        if (LF_ISSET(DB_THREAD)) {
113
 
                __db_err(dbenv, "DB_THREAD not allowed on RPC clients");
114
 
                return (EINVAL);
115
 
        }
116
 
        if ((ret = __db_home(dbenv, home, flags)) != 0)
117
 
                return (ret);
118
 
        return (__dbcl_env_open(dbenv, dbenv->db_home, flags, mode));
119
 
}
120
 
 
121
 
/*
122
 
 * __dbcl_db_open_wrap --
123
 
 *      Wrapper function for DB->open function for clients.
124
 
 *      We need a wrapper function to error on DB_THREAD flag.
125
 
 *      and we don't want to complicate the generated code.
126
 
 *
127
 
 * PUBLIC: int __dbcl_db_open_wrap
128
 
 * PUBLIC:     __P((DB *, DB_TXN *, const char *, const char *,
129
 
 * PUBLIC:     DBTYPE, u_int32_t, int));
130
 
 */
131
 
int
132
 
__dbcl_db_open_wrap(dbp, txnp, name, subdb, type, flags, mode)
133
 
        DB * dbp;
134
 
        DB_TXN * txnp;
135
 
        const char * name;
136
 
        const char * subdb;
137
 
        DBTYPE type;
138
 
        u_int32_t flags;
139
 
        int mode;
140
 
{
141
 
        if (LF_ISSET(DB_THREAD)) {
142
 
                __db_err(dbp->dbenv, "DB_THREAD not allowed on RPC clients");
143
 
                return (EINVAL);
144
 
        }
145
 
        return (__dbcl_db_open(dbp, txnp, name, subdb, type, flags, mode));
146
 
}
147
 
 
148
 
/*
149
 
 * __dbcl_refresh --
150
 
 *      Clean up an environment.
151
 
 *
152
 
 * PUBLIC: int __dbcl_refresh __P((DB_ENV *));
153
 
 */
154
 
int
155
 
__dbcl_refresh(dbenv)
156
 
        DB_ENV *dbenv;
157
 
{
158
 
        CLIENT *cl;
159
 
        int ret;
160
 
 
161
 
        cl = (CLIENT *)dbenv->cl_handle;
162
 
 
163
 
        ret = 0;
164
 
        if (dbenv->tx_handle != NULL) {
165
 
                /*
166
 
                 * We only need to free up our stuff, the caller
167
 
                 * of this function will call the server who will
168
 
                 * do all the real work.
169
 
                 */
170
 
                ret = __dbcl_txn_close(dbenv);
171
 
                dbenv->tx_handle = NULL;
172
 
        }
173
 
        if (!F_ISSET(dbenv, DB_ENV_RPCCLIENT_GIVEN) && cl != NULL)
174
 
                clnt_destroy(cl);
175
 
        dbenv->cl_handle = NULL;
176
 
        if (dbenv->db_home != NULL) {
177
 
                __os_free(dbenv, dbenv->db_home);
178
 
                dbenv->db_home = NULL;
179
 
        }
180
 
        return (ret);
181
 
}
182
 
 
183
 
/*
184
 
 * __dbcl_retcopy --
185
 
 *      Copy the returned data into the user's DBT, handling allocation flags,
186
 
 *      but not DB_DBT_PARTIAL.
187
 
 *
188
 
 * PUBLIC: int __dbcl_retcopy __P((DB_ENV *, DBT *,
189
 
 * PUBLIC:    void *, u_int32_t, void **, u_int32_t *));
190
 
 */
191
 
int
192
 
__dbcl_retcopy(dbenv, dbt, data, len, memp, memsize)
193
 
        DB_ENV *dbenv;
194
 
        DBT *dbt;
195
 
        void *data;
196
 
        u_int32_t len;
197
 
        void **memp;
198
 
        u_int32_t *memsize;
199
 
{
200
 
        int ret;
201
 
        u_int32_t orig_flags;
202
 
 
203
 
        /*
204
 
         * The RPC server handles DB_DBT_PARTIAL, so we mask it out here to
205
 
         * avoid the handling of partials in __db_retcopy.
206
 
         */
207
 
        orig_flags = dbt->flags;
208
 
        F_CLR(dbt, DB_DBT_PARTIAL);
209
 
        ret = __db_retcopy(dbenv, dbt, data, len, memp, memsize);
210
 
        dbt->flags = orig_flags;
211
 
        return (ret);
212
 
}
213
 
 
214
 
/*
215
 
 * __dbcl_txn_close --
216
 
 *      Clean up an environment's transactions.
217
 
 */
218
 
int
219
 
__dbcl_txn_close(dbenv)
220
 
        DB_ENV *dbenv;
221
 
{
222
 
        DB_TXN *txnp;
223
 
        DB_TXNMGR *tmgrp;
224
 
        int ret;
225
 
 
226
 
        ret = 0;
227
 
        tmgrp = dbenv->tx_handle;
228
 
 
229
 
        /*
230
 
         * This function can only be called once per process (i.e., not
231
 
         * once per thread), so no synchronization is required.
232
 
         * Also this function is called *after* the server has been called,
233
 
         * so the server has already closed/aborted any transactions that
234
 
         * were open on its side.  We only need to do local cleanup.
235
 
         */
236
 
        while ((txnp = TAILQ_FIRST(&tmgrp->txn_chain)) != NULL)
237
 
                __dbcl_txn_end(txnp);
238
 
 
239
 
        __os_free(dbenv, tmgrp);
240
 
        return (ret);
241
 
 
242
 
}
243
 
 
244
 
/*
245
 
 * __dbcl_txn_end --
246
 
 *      Clean up an transaction.
247
 
 * RECURSIVE FUNCTION:  Clean up nested transactions.
248
 
 *
249
 
 * PUBLIC: void __dbcl_txn_end __P((DB_TXN *));
250
 
 */
251
 
void
252
 
__dbcl_txn_end(txnp)
253
 
        DB_TXN *txnp;
254
 
{
255
 
        DB_ENV *dbenv;
256
 
        DB_TXN *kids;
257
 
        DB_TXNMGR *mgr;
258
 
 
259
 
        mgr = txnp->mgrp;
260
 
        dbenv = mgr->dbenv;
261
 
 
262
 
        /*
263
 
         * First take care of any kids we have
264
 
         */
265
 
        for (kids = TAILQ_FIRST(&txnp->kids);
266
 
            kids != NULL;
267
 
            kids = TAILQ_FIRST(&txnp->kids))
268
 
                __dbcl_txn_end(kids);
269
 
 
270
 
        /*
271
 
         * We are ending this transaction no matter what the parent
272
 
         * may eventually do, if we have a parent.  All those details
273
 
         * are taken care of by the server.  We only need to make sure
274
 
         * that we properly release resources.
275
 
         */
276
 
        if (txnp->parent != NULL)
277
 
                TAILQ_REMOVE(&txnp->parent->kids, txnp, klinks);
278
 
        TAILQ_REMOVE(&mgr->txn_chain, txnp, links);
279
 
        __os_free(dbenv, txnp);
280
 
}
281
 
 
282
 
/*
283
 
 * __dbcl_txn_setup --
284
 
 *      Setup a client transaction structure.
285
 
 *
286
 
 * PUBLIC: void __dbcl_txn_setup __P((DB_ENV *, DB_TXN *, DB_TXN *, u_int32_t));
287
 
 */
288
 
void
289
 
__dbcl_txn_setup(dbenv, txn, parent, id)
290
 
        DB_ENV *dbenv;
291
 
        DB_TXN *txn;
292
 
        DB_TXN *parent;
293
 
        u_int32_t id;
294
 
{
295
 
        txn->mgrp = dbenv->tx_handle;
296
 
        txn->parent = parent;
297
 
        txn->txnid = id;
298
 
 
299
 
        /*
300
 
         * XXX
301
 
         * In DB library the txn_chain is protected by the mgrp->mutexp.
302
 
         * However, that mutex is implemented in the environments shared
303
 
         * memory region.  The client library does not support all of the
304
 
         * region - that just get forwarded to the server.  Therefore,
305
 
         * the chain is unprotected here, but properly protected on the
306
 
         * server.
307
 
         */
308
 
        TAILQ_INSERT_TAIL(&txn->mgrp->txn_chain, txn, links);
309
 
 
310
 
        TAILQ_INIT(&txn->kids);
311
 
 
312
 
        if (parent != NULL)
313
 
                TAILQ_INSERT_HEAD(&parent->kids, txn, klinks);
314
 
 
315
 
        txn->abort = __dbcl_txn_abort;
316
 
        txn->commit = __dbcl_txn_commit;
317
 
        txn->discard = __dbcl_txn_discard;
318
 
        txn->id = __txn_id;
319
 
        txn->prepare = __dbcl_txn_prepare;
320
 
        txn->set_timeout = __dbcl_txn_timeout;
321
 
 
322
 
        txn->flags = TXN_MALLOC;
323
 
}
324
 
 
325
 
/*
326
 
 * __dbcl_c_destroy --
327
 
 *      Destroy a cursor.
328
 
 */
329
 
static int
330
 
__dbcl_c_destroy(dbc)
331
 
        DBC *dbc;
332
 
{
333
 
        DB *dbp;
334
 
 
335
 
        dbp = dbc->dbp;
336
 
 
337
 
        TAILQ_REMOVE(&dbp->free_queue, dbc, links);
338
 
        /* Discard any memory used to store returned data. */
339
 
        if (dbc->my_rskey.data != NULL)
340
 
                __os_free(dbc->dbp->dbenv, dbc->my_rskey.data);
341
 
        if (dbc->my_rkey.data != NULL)
342
 
                __os_free(dbc->dbp->dbenv, dbc->my_rkey.data);
343
 
        if (dbc->my_rdata.data != NULL)
344
 
                __os_free(dbc->dbp->dbenv, dbc->my_rdata.data);
345
 
        __os_free(NULL, dbc);
346
 
 
347
 
        return (0);
348
 
}
349
 
 
350
 
/*
351
 
 * __dbcl_c_refresh --
352
 
 *      Refresh a cursor.  Move it from the active queue to the free queue.
353
 
 *
354
 
 * PUBLIC: void __dbcl_c_refresh __P((DBC *));
355
 
 */
356
 
void
357
 
__dbcl_c_refresh(dbc)
358
 
        DBC *dbc;
359
 
{
360
 
        DB *dbp;
361
 
 
362
 
        dbp = dbc->dbp;
363
 
        dbc->flags = 0;
364
 
        dbc->cl_id = 0;
365
 
 
366
 
        /*
367
 
         * If dbp->cursor fails locally, we use a local dbc so that
368
 
         * we can close it.  In that case, dbp will be NULL.
369
 
         */
370
 
        if (dbp != NULL) {
371
 
                TAILQ_REMOVE(&dbp->active_queue, dbc, links);
372
 
                TAILQ_INSERT_TAIL(&dbp->free_queue, dbc, links);
373
 
        }
374
 
}
375
 
 
376
 
/*
377
 
 * __dbcl_c_setup --
378
 
 *      Allocate a cursor.
379
 
 *
380
 
 * PUBLIC: int __dbcl_c_setup __P((long, DB *, DBC **));
381
 
 */
382
 
int
383
 
__dbcl_c_setup(cl_id, dbp, dbcp)
384
 
        long cl_id;
385
 
        DB *dbp;
386
 
        DBC **dbcp;
387
 
{
388
 
        DBC *dbc, tmpdbc;
389
 
        int ret;
390
 
 
391
 
        if ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL)
392
 
                TAILQ_REMOVE(&dbp->free_queue, dbc, links);
393
 
        else {
394
 
                if ((ret =
395
 
                    __os_calloc(dbp->dbenv, 1, sizeof(DBC), &dbc)) != 0) {
396
 
                        /*
397
 
                         * If we die here, set up a tmp dbc to call the
398
 
                         * server to shut down that cursor.
399
 
                         */
400
 
                        tmpdbc.dbp = NULL;
401
 
                        tmpdbc.cl_id = cl_id;
402
 
                        (void)__dbcl_dbc_close(&tmpdbc);
403
 
                        return (ret);
404
 
                }
405
 
                dbc->c_close = __dbcl_dbc_close;
406
 
                dbc->c_count = __dbcl_dbc_count;
407
 
                dbc->c_del = __dbcl_dbc_del;
408
 
                dbc->c_dup = __dbcl_dbc_dup;
409
 
                dbc->c_get = __dbcl_dbc_get;
410
 
                dbc->c_pget = __dbcl_dbc_pget;
411
 
                dbc->c_put = __dbcl_dbc_put;
412
 
                dbc->c_am_destroy = __dbcl_c_destroy;
413
 
        }
414
 
        dbc->cl_id = cl_id;
415
 
        dbc->dbp = dbp;
416
 
        TAILQ_INSERT_TAIL(&dbp->active_queue, dbc, links);
417
 
        *dbcp = dbc;
418
 
        return (0);
419
 
}
420
 
 
421
 
/*
422
 
 * __dbcl_dbclose_common --
423
 
 *      Common code for closing/cleaning a dbp.
424
 
 *
425
 
 * PUBLIC: int __dbcl_dbclose_common __P((DB *));
426
 
 */
427
 
int
428
 
__dbcl_dbclose_common(dbp)
429
 
        DB *dbp;
430
 
{
431
 
        int ret, t_ret;
432
 
        DBC *dbc;
433
 
 
434
 
        /*
435
 
         * Go through the active cursors and call the cursor recycle routine,
436
 
         * which resolves pending operations and moves the cursors onto the
437
 
         * free list.  Then, walk the free list and call the cursor destroy
438
 
         * routine.
439
 
         *
440
 
         * NOTE:  We do not need to use the join_queue for join cursors.
441
 
         * See comment in __dbcl_dbjoin_ret.
442
 
         */
443
 
        ret = 0;
444
 
        while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL)
445
 
                __dbcl_c_refresh(dbc);
446
 
        while ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL)
447
 
                if ((t_ret = __dbcl_c_destroy(dbc)) != 0 && ret == 0)
448
 
                        ret = t_ret;
449
 
 
450
 
        TAILQ_INIT(&dbp->free_queue);
451
 
        TAILQ_INIT(&dbp->active_queue);
452
 
        /* Discard any memory used to store returned data. */
453
 
        if (dbp->my_rskey.data != NULL)
454
 
                __os_free(dbp->dbenv, dbp->my_rskey.data);
455
 
        if (dbp->my_rkey.data != NULL)
456
 
                __os_free(dbp->dbenv, dbp->my_rkey.data);
457
 
        if (dbp->my_rdata.data != NULL)
458
 
                __os_free(dbp->dbenv, dbp->my_rdata.data);
459
 
 
460
 
        memset(dbp, CLEAR_BYTE, sizeof(*dbp));
461
 
        __os_free(NULL, dbp);
462
 
        return (ret);
463
 
}
464
 
#endif /* HAVE_RPC */