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

« back to all changes in this revision

Viewing changes to libdb/db/db_cam.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) 2000-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/btree.h"
24
 
#include "dbinc/hash.h"
25
 
#include "dbinc/lock.h"
26
 
#include "dbinc/log.h"
27
 
#include "dbinc/qam.h"
28
 
 
29
 
static int __db_buildpartial __P((DB *, DBT *, DBT *, DBT *));
30
 
static int __db_c_cleanup __P((DBC *, DBC *, int));
31
 
static int __db_c_del_secondary __P((DBC *));
32
 
static int __db_c_pget_recno __P((DBC *, DBT *, DBT *, u_int32_t));
33
 
static int __db_wrlock_err __P((DB_ENV *));
34
 
 
35
 
#define CDB_LOCKING_INIT(dbp, dbc)                                      \
36
 
        /*                                                              \
37
 
         * If we are running CDB, this had better be either a write     \
38
 
         * cursor or an immediate writer.  If it's a regular writer,    \
39
 
         * that means we have an IWRITE lock and we need to upgrade     \
40
 
         * it to a write lock.                                          \
41
 
         */                                                             \
42
 
        if (CDB_LOCKING((dbp)->dbenv)) {                                \
43
 
                if (!F_ISSET(dbc, DBC_WRITECURSOR | DBC_WRITER))        \
44
 
                        return (__db_wrlock_err(dbp->dbenv));           \
45
 
                                                                        \
46
 
                if (F_ISSET(dbc, DBC_WRITECURSOR) &&                    \
47
 
                    (ret = (dbp)->dbenv->lock_get((dbp)->dbenv,         \
48
 
                    (dbc)->locker, DB_LOCK_UPGRADE, &(dbc)->lock_dbt,   \
49
 
                    DB_LOCK_WRITE, &(dbc)->mylock)) != 0)               \
50
 
                        return (ret);                                   \
51
 
        }
52
 
#define CDB_LOCKING_DONE(dbp, dbc)                                      \
53
 
        /* Release the upgraded lock. */                                \
54
 
        if (F_ISSET(dbc, DBC_WRITECURSOR))                              \
55
 
                (void)__lock_downgrade(                                 \
56
 
                    (dbp)->dbenv, &(dbc)->mylock, DB_LOCK_IWRITE, 0);
57
 
/*
58
 
 * Copy the lock info from one cursor to another, so that locking
59
 
 * in CDB can be done in the context of an internally-duplicated
60
 
 * or off-page-duplicate cursor.
61
 
 */
62
 
#define CDB_LOCKING_COPY(dbp, dbc_o, dbc_n)                             \
63
 
        if (CDB_LOCKING((dbp)->dbenv) &&                                \
64
 
            F_ISSET((dbc_o), DBC_WRITECURSOR | DBC_WRITEDUP)) { \
65
 
                memcpy(&(dbc_n)->mylock, &(dbc_o)->mylock,              \
66
 
                    sizeof((dbc_o)->mylock));                           \
67
 
                /* This lock isn't ours to put--just discard it on close. */ \
68
 
                F_SET((dbc_n), DBC_WRITEDUP);                           \
69
 
        }
70
 
 
71
 
/*
72
 
 * __db_c_close --
73
 
 *      Close the cursor.
74
 
 *
75
 
 * PUBLIC: int __db_c_close __P((DBC *));
76
 
 */
77
 
int
78
 
__db_c_close(dbc)
79
 
        DBC *dbc;
80
 
{
81
 
        DB *dbp;
82
 
        DBC *opd;
83
 
        DBC_INTERNAL *cp;
84
 
        DB_ENV *dbenv;
85
 
        int ret, t_ret;
86
 
 
87
 
        dbp = dbc->dbp;
88
 
        dbenv = dbp->dbenv;
89
 
        ret = 0;
90
 
 
91
 
        PANIC_CHECK(dbenv);
92
 
 
93
 
        /*
94
 
         * If the cursor is already closed we have a serious problem, and we
95
 
         * assume that the cursor isn't on the active queue.  Don't do any of
96
 
         * the remaining cursor close processing.
97
 
         */
98
 
        if (!F_ISSET(dbc, DBC_ACTIVE)) {
99
 
                if (dbp != NULL)
100
 
                        __db_err(dbenv, "Closing already-closed cursor");
101
 
 
102
 
                DB_ASSERT(0);
103
 
                return (EINVAL);
104
 
        }
105
 
 
106
 
        cp = dbc->internal;
107
 
        opd = cp->opd;
108
 
 
109
 
        /*
110
 
         * Remove the cursor(s) from the active queue.  We may be closing two
111
 
         * cursors at once here, a top-level one and a lower-level, off-page
112
 
         * duplicate one.  The acess-method specific cursor close routine must
113
 
         * close both of them in a single call.
114
 
         *
115
 
         * !!!
116
 
         * Cursors must be removed from the active queue before calling the
117
 
         * access specific cursor close routine, btree depends on having that
118
 
         * order of operations.
119
 
         */
120
 
        MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
121
 
 
122
 
        if (opd != NULL) {
123
 
                F_CLR(opd, DBC_ACTIVE);
124
 
                TAILQ_REMOVE(&dbp->active_queue, opd, links);
125
 
        }
126
 
        F_CLR(dbc, DBC_ACTIVE);
127
 
        TAILQ_REMOVE(&dbp->active_queue, dbc, links);
128
 
 
129
 
        MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
130
 
 
131
 
        /* Call the access specific cursor close routine. */
132
 
        if ((t_ret =
133
 
            dbc->c_am_close(dbc, PGNO_INVALID, NULL)) != 0 && ret == 0)
134
 
                ret = t_ret;
135
 
 
136
 
        /*
137
 
         * Release the lock after calling the access method specific close
138
 
         * routine, a Btree cursor may have had pending deletes.
139
 
         */
140
 
        if (CDB_LOCKING(dbenv)) {
141
 
                /*
142
 
                 * If DBC_WRITEDUP is set, the cursor is an internally
143
 
                 * duplicated write cursor and the lock isn't ours to put.
144
 
                 *
145
 
                 * Also, be sure not to free anything if mylock.off is
146
 
                 * INVALID;  in some cases, such as idup'ed read cursors
147
 
                 * and secondary update cursors, a cursor in a CDB
148
 
                 * environment may not have a lock at all.
149
 
                 */
150
 
                if (!F_ISSET(dbc, DBC_WRITEDUP) && LOCK_ISSET(dbc->mylock)) {
151
 
                        if ((t_ret = dbenv->lock_put(
152
 
                            dbenv, &dbc->mylock)) != 0 && ret == 0)
153
 
                                ret = t_ret;
154
 
                }
155
 
 
156
 
                /* For safety's sake, since this is going on the free queue. */
157
 
                memset(&dbc->mylock, 0, sizeof(dbc->mylock));
158
 
                F_CLR(dbc, DBC_WRITEDUP);
159
 
        }
160
 
 
161
 
        if (dbc->txn != NULL)
162
 
                dbc->txn->cursors--;
163
 
 
164
 
        /* Move the cursor(s) to the free queue. */
165
 
        MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
166
 
        if (opd != NULL) {
167
 
                if (dbc->txn != NULL)
168
 
                        dbc->txn->cursors--;
169
 
                TAILQ_INSERT_TAIL(&dbp->free_queue, opd, links);
170
 
                opd = NULL;
171
 
        }
172
 
        TAILQ_INSERT_TAIL(&dbp->free_queue, dbc, links);
173
 
        MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
174
 
 
175
 
        return (ret);
176
 
}
177
 
 
178
 
/*
179
 
 * __db_c_destroy --
180
 
 *      Destroy the cursor, called after DBC->c_close.
181
 
 *
182
 
 * PUBLIC: int __db_c_destroy __P((DBC *));
183
 
 */
184
 
int
185
 
__db_c_destroy(dbc)
186
 
        DBC *dbc;
187
 
{
188
 
        DB *dbp;
189
 
        DB_ENV *dbenv;
190
 
        int ret, t_ret;
191
 
 
192
 
        dbp = dbc->dbp;
193
 
        dbenv = dbp->dbenv;
194
 
 
195
 
        /* Remove the cursor from the free queue. */
196
 
        MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
197
 
        TAILQ_REMOVE(&dbp->free_queue, dbc, links);
198
 
        MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);
199
 
 
200
 
        /* Free up allocated memory. */
201
 
        if (dbc->my_rskey.data != NULL)
202
 
                __os_free(dbenv, dbc->my_rskey.data);
203
 
        if (dbc->my_rkey.data != NULL)
204
 
                __os_free(dbenv, dbc->my_rkey.data);
205
 
        if (dbc->my_rdata.data != NULL)
206
 
                __os_free(dbenv, dbc->my_rdata.data);
207
 
 
208
 
        /* Call the access specific cursor destroy routine. */
209
 
        ret = dbc->c_am_destroy == NULL ? 0 : dbc->c_am_destroy(dbc);
210
 
 
211
 
        /*
212
 
         * Release the lock id for this cursor.
213
 
         */
214
 
        if (LOCKING_ON(dbenv) &&
215
 
            F_ISSET(dbc, DBC_OWN_LID) &&
216
 
            (t_ret = dbenv->lock_id_free(dbenv, dbc->lid)) != 0 && ret == 0)
217
 
                ret = t_ret;
218
 
 
219
 
        __os_free(dbenv, dbc);
220
 
 
221
 
        return (ret);
222
 
}
223
 
 
224
 
/*
225
 
 * __db_c_count --
226
 
 *      Return a count of duplicate data items.
227
 
 *
228
 
 * PUBLIC: int __db_c_count __P((DBC *, db_recno_t *, u_int32_t));
229
 
 */
230
 
int
231
 
__db_c_count(dbc, recnop, flags)
232
 
        DBC *dbc;
233
 
        db_recno_t *recnop;
234
 
        u_int32_t flags;
235
 
{
236
 
        DB *dbp;
237
 
        int ret;
238
 
 
239
 
        /*
240
 
         * Cursor Cleanup Note:
241
 
         * All of the cursors passed to the underlying access methods by this
242
 
         * routine are not duplicated and will not be cleaned up on return.
243
 
         * So, pages/locks that the cursor references must be resolved by the
244
 
         * underlying functions.
245
 
         */
246
 
        dbp = dbc->dbp;
247
 
 
248
 
        PANIC_CHECK(dbp->dbenv);
249
 
 
250
 
        /* Check for invalid flags. */
251
 
        if ((ret = __db_ccountchk(dbp, flags, IS_INITIALIZED(dbc))) != 0)
252
 
                return (ret);
253
 
 
254
 
        switch (dbc->dbtype) {
255
 
        case DB_QUEUE:
256
 
        case DB_RECNO:
257
 
                *recnop = 1;
258
 
                break;
259
 
        case DB_HASH:
260
 
                if (dbc->internal->opd == NULL) {
261
 
                        if ((ret = __ham_c_count(dbc, recnop)) != 0)
262
 
                                return (ret);
263
 
                        break;
264
 
                }
265
 
                /* FALLTHROUGH */
266
 
        case DB_BTREE:
267
 
                if ((ret = __bam_c_count(dbc, recnop)) != 0)
268
 
                        return (ret);
269
 
                break;
270
 
        default:
271
 
                return (__db_unknown_type(dbp->dbenv,
272
 
                    "__db_c_count", dbp->type));
273
 
        }
274
 
        return (0);
275
 
}
276
 
 
277
 
/*
278
 
 * __db_c_del --
279
 
 *      Delete using a cursor.
280
 
 *
281
 
 * PUBLIC: int __db_c_del __P((DBC *, u_int32_t));
282
 
 */
283
 
int
284
 
__db_c_del(dbc, flags)
285
 
        DBC *dbc;
286
 
        u_int32_t flags;
287
 
{
288
 
        DB *dbp;
289
 
        DBC *opd;
290
 
        int ret;
291
 
 
292
 
        /*
293
 
         * Cursor Cleanup Note:
294
 
         * All of the cursors passed to the underlying access methods by this
295
 
         * routine are not duplicated and will not be cleaned up on return.
296
 
         * So, pages/locks that the cursor references must be resolved by the
297
 
         * underlying functions.
298
 
         */
299
 
        dbp = dbc->dbp;
300
 
 
301
 
        PANIC_CHECK(dbp->dbenv);
302
 
 
303
 
        /* Check for invalid flags. */
304
 
        if ((ret = __db_cdelchk(dbp, flags, IS_INITIALIZED(dbc))) != 0)
305
 
                return (ret);
306
 
 
307
 
        /* Check for consistent transaction usage. */
308
 
        if ((ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0)
309
 
                return (ret);
310
 
 
311
 
        DEBUG_LWRITE(dbc, dbc->txn, "db_c_del", NULL, NULL, flags);
312
 
 
313
 
        CDB_LOCKING_INIT(dbp, dbc);
314
 
 
315
 
        /*
316
 
         * If we're a secondary index, and DB_UPDATE_SECONDARY isn't set
317
 
         * (which it only is if we're being called from a primary update),
318
 
         * then we need to call through to the primary and delete the item.
319
 
         *
320
 
         * Note that this will delete the current item;  we don't need to
321
 
         * delete it ourselves as well, so we can just goto done.
322
 
         */
323
 
        if (flags != DB_UPDATE_SECONDARY && F_ISSET(dbp, DB_AM_SECONDARY)) {
324
 
                ret = __db_c_del_secondary(dbc);
325
 
                goto done;
326
 
        }
327
 
 
328
 
        /*
329
 
         * If we are a primary and have secondary indices, go through
330
 
         * and delete any secondary keys that point at the current record.
331
 
         */
332
 
        if (LIST_FIRST(&dbp->s_secondaries) != NULL &&
333
 
            (ret = __db_c_del_primary(dbc)) != 0)
334
 
                goto done;
335
 
 
336
 
        /*
337
 
         * Off-page duplicate trees are locked in the primary tree, that is,
338
 
         * we acquire a write lock in the primary tree and no locks in the
339
 
         * off-page dup tree.  If the del operation is done in an off-page
340
 
         * duplicate tree, call the primary cursor's upgrade routine first.
341
 
         */
342
 
        opd = dbc->internal->opd;
343
 
        if (opd == NULL)
344
 
                ret = dbc->c_am_del(dbc);
345
 
        else
346
 
                if ((ret = dbc->c_am_writelock(dbc)) == 0)
347
 
                        ret = opd->c_am_del(opd);
348
 
 
349
 
done:   CDB_LOCKING_DONE(dbp, dbc);
350
 
 
351
 
        return (ret);
352
 
}
353
 
 
354
 
/*
355
 
 * __db_c_dup --
356
 
 *      Duplicate a cursor
357
 
 *
358
 
 * PUBLIC: int __db_c_dup __P((DBC *, DBC **, u_int32_t));
359
 
 */
360
 
int
361
 
__db_c_dup(dbc_orig, dbcp, flags)
362
 
        DBC *dbc_orig;
363
 
        DBC **dbcp;
364
 
        u_int32_t flags;
365
 
{
366
 
        DB_ENV *dbenv;
367
 
        DB *dbp;
368
 
        DBC *dbc_n, *dbc_nopd;
369
 
        int ret;
370
 
 
371
 
        dbp = dbc_orig->dbp;
372
 
        dbenv = dbp->dbenv;
373
 
        dbc_n = dbc_nopd = NULL;
374
 
 
375
 
        PANIC_CHECK(dbp->dbenv);
376
 
 
377
 
        /*
378
 
         * We can never have two write cursors open in CDB, so do not
379
 
         * allow duplication of a write cursor.
380
 
         */
381
 
        if (flags != DB_POSITIONI &&
382
 
            F_ISSET(dbc_orig, DBC_WRITER | DBC_WRITECURSOR)) {
383
 
                __db_err(dbenv, "Cannot duplicate writeable cursor");
384
 
                return (EINVAL);
385
 
        }
386
 
 
387
 
        /* Allocate a new cursor and initialize it. */
388
 
        if ((ret = __db_c_idup(dbc_orig, &dbc_n, flags)) != 0)
389
 
                goto err;
390
 
        *dbcp = dbc_n;
391
 
 
392
 
        /*
393
 
         * If we're in CDB, and this isn't an internal duplication (in which
394
 
         * case we're explicitly overriding CDB locking), the duplicated
395
 
         * cursor needs its own read lock.  (We know it's not a write cursor
396
 
         * because we wouldn't have made it this far;  you can't dup them.)
397
 
         */
398
 
        if (CDB_LOCKING(dbenv) && flags != DB_POSITIONI) {
399
 
                DB_ASSERT(!F_ISSET(dbc_orig, DBC_WRITER | DBC_WRITECURSOR));
400
 
 
401
 
                if ((ret = dbenv->lock_get(dbenv, dbc_n->locker, 0,
402
 
                    &dbc_n->lock_dbt, DB_LOCK_READ, &dbc_n->mylock)) != 0) {
403
 
                        (void)__db_c_close(dbc_n);
404
 
                        return (ret);
405
 
                }
406
 
        }
407
 
 
408
 
        /*
409
 
         * If the cursor references an off-page duplicate tree, allocate a
410
 
         * new cursor for that tree and initialize it.
411
 
         */
412
 
        if (dbc_orig->internal->opd != NULL) {
413
 
                if ((ret =
414
 
                   __db_c_idup(dbc_orig->internal->opd, &dbc_nopd, flags)) != 0)
415
 
                        goto err;
416
 
                dbc_n->internal->opd = dbc_nopd;
417
 
        }
418
 
 
419
 
        /* Copy the dirty read flag to the new cursor. */
420
 
        F_SET(dbc_n, F_ISSET(dbc_orig, DBC_DIRTY_READ));
421
 
        return (0);
422
 
 
423
 
err:    if (dbc_n != NULL)
424
 
                (void)dbc_n->c_close(dbc_n);
425
 
        if (dbc_nopd != NULL)
426
 
                (void)dbc_nopd->c_close(dbc_nopd);
427
 
 
428
 
        return (ret);
429
 
}
430
 
 
431
 
/*
432
 
 * __db_c_idup --
433
 
 *      Internal version of __db_c_dup.
434
 
 *
435
 
 * PUBLIC: int __db_c_idup __P((DBC *, DBC **, u_int32_t));
436
 
 */
437
 
int
438
 
__db_c_idup(dbc_orig, dbcp, flags)
439
 
        DBC *dbc_orig, **dbcp;
440
 
        u_int32_t flags;
441
 
{
442
 
        DB *dbp;
443
 
        DBC *dbc_n;
444
 
        DBC_INTERNAL *int_n, *int_orig;
445
 
        int ret;
446
 
 
447
 
        dbp = dbc_orig->dbp;
448
 
        dbc_n = *dbcp;
449
 
 
450
 
        if ((ret = __db_icursor(dbp, dbc_orig->txn, dbc_orig->dbtype,
451
 
            dbc_orig->internal->root, F_ISSET(dbc_orig, DBC_OPD),
452
 
            dbc_orig->locker, &dbc_n)) != 0)
453
 
                return (ret);
454
 
 
455
 
        /* If the user wants the cursor positioned, do it here.  */
456
 
        if (flags == DB_POSITION || flags == DB_POSITIONI) {
457
 
                int_n = dbc_n->internal;
458
 
                int_orig = dbc_orig->internal;
459
 
 
460
 
                dbc_n->flags |= dbc_orig->flags & ~DBC_OWN_LID;
461
 
 
462
 
                int_n->indx = int_orig->indx;
463
 
                int_n->pgno = int_orig->pgno;
464
 
                int_n->root = int_orig->root;
465
 
                int_n->lock_mode = int_orig->lock_mode;
466
 
 
467
 
                switch (dbc_orig->dbtype) {
468
 
                case DB_QUEUE:
469
 
                        if ((ret = __qam_c_dup(dbc_orig, dbc_n)) != 0)
470
 
                                goto err;
471
 
                        break;
472
 
                case DB_BTREE:
473
 
                case DB_RECNO:
474
 
                        if ((ret = __bam_c_dup(dbc_orig, dbc_n)) != 0)
475
 
                                goto err;
476
 
                        break;
477
 
                case DB_HASH:
478
 
                        if ((ret = __ham_c_dup(dbc_orig, dbc_n)) != 0)
479
 
                                goto err;
480
 
                        break;
481
 
                default:
482
 
                        ret = __db_unknown_type(dbp->dbenv,
483
 
                            "__db_c_idup", dbc_orig->dbtype);
484
 
                        goto err;
485
 
                }
486
 
        }
487
 
 
488
 
        /* Now take care of duping the CDB information. */
489
 
        CDB_LOCKING_COPY(dbp, dbc_orig, dbc_n);
490
 
 
491
 
        /* Copy the dirty read flag to the new cursor. */
492
 
        F_SET(dbc_n, F_ISSET(dbc_orig, DBC_DIRTY_READ));
493
 
 
494
 
        *dbcp = dbc_n;
495
 
        return (0);
496
 
 
497
 
err:    (void)dbc_n->c_close(dbc_n);
498
 
        return (ret);
499
 
}
500
 
 
501
 
/*
502
 
 * __db_c_newopd --
503
 
 *      Create a new off-page duplicate cursor.
504
 
 *
505
 
 * PUBLIC: int __db_c_newopd __P((DBC *, db_pgno_t, DBC *, DBC **));
506
 
 */
507
 
int
508
 
__db_c_newopd(dbc_parent, root, oldopd, dbcp)
509
 
        DBC *dbc_parent;
510
 
        db_pgno_t root;
511
 
        DBC *oldopd;
512
 
        DBC **dbcp;
513
 
{
514
 
        DB *dbp;
515
 
        DBC *opd;
516
 
        DBTYPE dbtype;
517
 
        int ret;
518
 
 
519
 
        dbp = dbc_parent->dbp;
520
 
        dbtype = (dbp->dup_compare == NULL) ? DB_RECNO : DB_BTREE;
521
 
 
522
 
        /*
523
 
         * On failure, we want to default to returning the old off-page dup
524
 
         * cursor, if any;  our caller can't be left with a dangling pointer
525
 
         * to a freed cursor.  On error the only allowable behavior is to
526
 
         * close the cursor (and the old OPD cursor it in turn points to), so
527
 
         * this should be safe.
528
 
         */
529
 
        *dbcp = oldopd;
530
 
 
531
 
        if ((ret = __db_icursor(dbp,
532
 
            dbc_parent->txn, dbtype, root, 1, dbc_parent->locker, &opd)) != 0)
533
 
                return (ret);
534
 
 
535
 
        /* !!!
536
 
         * If the parent is a DBC_WRITER, this won't copy anything.  That's
537
 
         * not actually a problem--we only need lock information in an
538
 
         * off-page dup cursor in order to upgrade at cursor close time
539
 
         * if we've done a delete, but WRITERs don't need to upgrade.
540
 
         */
541
 
        CDB_LOCKING_COPY(dbp, dbc_parent, opd);
542
 
 
543
 
        *dbcp = opd;
544
 
 
545
 
        /*
546
 
         * Check to see if we already have an off-page dup cursor that we've
547
 
         * passed in.  If we do, close it.  It'd be nice to use it again
548
 
         * if it's a cursor belonging to the right tree, but if we're doing
549
 
         * a cursor-relative operation this might not be safe, so for now
550
 
         * we'll take the easy way out and always close and reopen.
551
 
         *
552
 
         * Note that under no circumstances do we want to close the old
553
 
         * cursor without returning a valid new one;  we don't want to
554
 
         * leave the main cursor in our caller with a non-NULL pointer
555
 
         * to a freed off-page dup cursor.
556
 
         */
557
 
        if (oldopd != NULL && (ret = oldopd->c_close(oldopd)) != 0)
558
 
                return (ret);
559
 
 
560
 
        return (0);
561
 
}
562
 
 
563
 
/*
564
 
 * __db_c_get --
565
 
 *      Get using a cursor.
566
 
 *
567
 
 * PUBLIC: int __db_c_get __P((DBC *, DBT *, DBT *, u_int32_t));
568
 
 */
569
 
int
570
 
__db_c_get(dbc_arg, key, data, flags)
571
 
        DBC *dbc_arg;
572
 
        DBT *key, *data;
573
 
        u_int32_t flags;
574
 
{
575
 
        DB *dbp;
576
 
        DBC *dbc, *dbc_n, *opd;
577
 
        DBC_INTERNAL *cp, *cp_n;
578
 
        DB_MPOOLFILE *mpf;
579
 
        db_pgno_t pgno;
580
 
        u_int32_t multi, tmp_dirty, tmp_flags, tmp_rmw;
581
 
        u_int8_t type;
582
 
        int ret, t_ret;
583
 
 
584
 
        /*
585
 
         * Cursor Cleanup Note:
586
 
         * All of the cursors passed to the underlying access methods by this
587
 
         * routine are duplicated cursors.  On return, any referenced pages
588
 
         * will be discarded, and, if the cursor is not intended to be used
589
 
         * again, the close function will be called.  So, pages/locks that
590
 
         * the cursor references do not need to be resolved by the underlying
591
 
         * functions.
592
 
         */
593
 
        dbp = dbc_arg->dbp;
594
 
        mpf = dbp->mpf;
595
 
        dbc_n = NULL;
596
 
        opd = NULL;
597
 
 
598
 
        PANIC_CHECK(dbp->dbenv);
599
 
 
600
 
        /* Check for invalid flags. */
601
 
        if ((ret =
602
 
            __db_cgetchk(dbp, key, data, flags, IS_INITIALIZED(dbc_arg))) != 0)
603
 
                return (ret);
604
 
 
605
 
        /* Clear OR'd in additional bits so we can check for flag equality. */
606
 
        tmp_rmw = LF_ISSET(DB_RMW);
607
 
        LF_CLR(DB_RMW);
608
 
 
609
 
        tmp_dirty = LF_ISSET(DB_DIRTY_READ);
610
 
        LF_CLR(DB_DIRTY_READ);
611
 
 
612
 
        multi = LF_ISSET(DB_MULTIPLE|DB_MULTIPLE_KEY);
613
 
        LF_CLR(DB_MULTIPLE|DB_MULTIPLE_KEY);
614
 
 
615
 
        DEBUG_LREAD(dbc_arg, dbc_arg->txn, "db_c_get",
616
 
            flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, NULL, flags);
617
 
 
618
 
        /*
619
 
         * Return a cursor's record number.  It has nothing to do with the
620
 
         * cursor get code except that it was put into the interface.
621
 
         */
622
 
        if (flags == DB_GET_RECNO) {
623
 
                if (tmp_rmw)
624
 
                        F_SET(dbc_arg, DBC_RMW);
625
 
                if (tmp_dirty)
626
 
                        F_SET(dbc_arg, DBC_DIRTY_READ);
627
 
                ret = __bam_c_rget(dbc_arg, data);
628
 
                if (tmp_rmw)
629
 
                        F_CLR(dbc_arg, DBC_RMW);
630
 
                if (tmp_dirty)
631
 
                        F_CLR(dbc_arg, DBC_DIRTY_READ);
632
 
                return (ret);
633
 
        }
634
 
 
635
 
        if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
636
 
                CDB_LOCKING_INIT(dbp, dbc_arg);
637
 
 
638
 
        /*
639
 
         * If we have an off-page duplicates cursor, and the operation applies
640
 
         * to it, perform the operation.  Duplicate the cursor and call the
641
 
         * underlying function.
642
 
         *
643
 
         * Off-page duplicate trees are locked in the primary tree, that is,
644
 
         * we acquire a write lock in the primary tree and no locks in the
645
 
         * off-page dup tree.  If the DB_RMW flag was specified and the get
646
 
         * operation is done in an off-page duplicate tree, call the primary
647
 
         * cursor's upgrade routine first.
648
 
         */
649
 
        cp = dbc_arg->internal;
650
 
        if (cp->opd != NULL &&
651
 
            (flags == DB_CURRENT || flags == DB_GET_BOTHC ||
652
 
            flags == DB_NEXT || flags == DB_NEXT_DUP || flags == DB_PREV)) {
653
 
                if (tmp_rmw && (ret = dbc_arg->c_am_writelock(dbc_arg)) != 0)
654
 
                        return (ret);
655
 
                if ((ret = __db_c_idup(cp->opd, &opd, DB_POSITIONI)) != 0)
656
 
                        return (ret);
657
 
 
658
 
                switch (ret =
659
 
                    opd->c_am_get(opd, key, data, flags, NULL)) {
660
 
                case 0:
661
 
                        goto done;
662
 
                case DB_NOTFOUND:
663
 
                        /*
664
 
                         * Translate DB_NOTFOUND failures for the DB_NEXT and
665
 
                         * DB_PREV operations into a subsequent operation on
666
 
                         * the parent cursor.
667
 
                         */
668
 
                        if (flags == DB_NEXT || flags == DB_PREV) {
669
 
                                if ((ret = opd->c_close(opd)) != 0)
670
 
                                        goto err;
671
 
                                opd = NULL;
672
 
                                break;
673
 
                        }
674
 
                        goto err;
675
 
                default:
676
 
                        goto err;
677
 
                }
678
 
        }
679
 
 
680
 
        /*
681
 
         * Perform an operation on the main cursor.  Duplicate the cursor,
682
 
         * upgrade the lock as required, and call the underlying function.
683
 
         */
684
 
        switch (flags) {
685
 
        case DB_CURRENT:
686
 
        case DB_GET_BOTHC:
687
 
        case DB_NEXT:
688
 
        case DB_NEXT_DUP:
689
 
        case DB_NEXT_NODUP:
690
 
        case DB_PREV:
691
 
        case DB_PREV_NODUP:
692
 
                tmp_flags = DB_POSITIONI;
693
 
                break;
694
 
        default:
695
 
                tmp_flags = 0;
696
 
                break;
697
 
        }
698
 
 
699
 
        if (tmp_dirty)
700
 
                F_SET(dbc_arg, DBC_DIRTY_READ);
701
 
 
702
 
        /*
703
 
         * If this cursor is going to be closed immediately, we don't
704
 
         * need to take precautions to clean it up on error.
705
 
         */
706
 
        if (F_ISSET(dbc_arg, DBC_TRANSIENT))
707
 
                dbc_n = dbc_arg;
708
 
        else {
709
 
                ret = __db_c_idup(dbc_arg, &dbc_n, tmp_flags);
710
 
                if (tmp_dirty)
711
 
                        F_CLR(dbc_arg, DBC_DIRTY_READ);
712
 
 
713
 
                if (ret != 0)
714
 
                        goto err;
715
 
                COPY_RET_MEM(dbc_arg, dbc_n);
716
 
        }
717
 
 
718
 
        if (tmp_rmw)
719
 
                F_SET(dbc_n, DBC_RMW);
720
 
 
721
 
        switch (multi) {
722
 
        case DB_MULTIPLE:
723
 
                F_SET(dbc_n, DBC_MULTIPLE);
724
 
                break;
725
 
        case DB_MULTIPLE_KEY:
726
 
                F_SET(dbc_n, DBC_MULTIPLE_KEY);
727
 
                break;
728
 
        case DB_MULTIPLE | DB_MULTIPLE_KEY:
729
 
                F_SET(dbc_n, DBC_MULTIPLE|DBC_MULTIPLE_KEY);
730
 
                break;
731
 
        case 0:
732
 
                break;
733
 
        }
734
 
 
735
 
        pgno = PGNO_INVALID;
736
 
        ret = dbc_n->c_am_get(dbc_n, key, data, flags, &pgno);
737
 
        if (tmp_rmw)
738
 
                F_CLR(dbc_n, DBC_RMW);
739
 
        if (tmp_dirty)
740
 
                F_CLR(dbc_arg, DBC_DIRTY_READ);
741
 
        F_CLR(dbc_n, DBC_MULTIPLE|DBC_MULTIPLE_KEY);
742
 
        if (ret != 0)
743
 
                goto err;
744
 
 
745
 
        cp_n = dbc_n->internal;
746
 
 
747
 
        /*
748
 
         * We may be referencing a new off-page duplicates tree.  Acquire
749
 
         * a new cursor and call the underlying function.
750
 
         */
751
 
        if (pgno != PGNO_INVALID) {
752
 
                if ((ret = __db_c_newopd(dbc_arg,
753
 
                    pgno, cp_n->opd, &cp_n->opd)) != 0)
754
 
                        goto err;
755
 
 
756
 
                switch (flags) {
757
 
                case DB_FIRST:
758
 
                case DB_NEXT:
759
 
                case DB_NEXT_NODUP:
760
 
                case DB_SET:
761
 
                case DB_SET_RECNO:
762
 
                case DB_SET_RANGE:
763
 
                        tmp_flags = DB_FIRST;
764
 
                        break;
765
 
                case DB_LAST:
766
 
                case DB_PREV:
767
 
                case DB_PREV_NODUP:
768
 
                        tmp_flags = DB_LAST;
769
 
                        break;
770
 
                case DB_GET_BOTH:
771
 
                case DB_GET_BOTHC:
772
 
                case DB_GET_BOTH_RANGE:
773
 
                        tmp_flags = flags;
774
 
                        break;
775
 
                default:
776
 
                        ret =
777
 
                            __db_unknown_flag(dbp->dbenv, "__db_c_get", flags);
778
 
                        goto err;
779
 
                }
780
 
                if ((ret = cp_n->opd->c_am_get(
781
 
                    cp_n->opd, key, data, tmp_flags, NULL)) != 0)
782
 
                        goto err;
783
 
        }
784
 
 
785
 
done:   /*
786
 
         * Return a key/data item.  The only exception is that we don't return
787
 
         * a key if the user already gave us one, that is, if the DB_SET flag
788
 
         * was set.  The DB_SET flag is necessary.  In a Btree, the user's key
789
 
         * doesn't have to be the same as the key stored the tree, depending on
790
 
         * the magic performed by the comparison function.  As we may not have
791
 
         * done any key-oriented operation here, the page reference may not be
792
 
         * valid.  Fill it in as necessary.  We don't have to worry about any
793
 
         * locks, the cursor must already be holding appropriate locks.
794
 
         *
795
 
         * XXX
796
 
         * If not a Btree and DB_SET_RANGE is set, we shouldn't return a key
797
 
         * either, should we?
798
 
         */
799
 
        cp_n = dbc_n == NULL ? dbc_arg->internal : dbc_n->internal;
800
 
        if (!F_ISSET(key, DB_DBT_ISSET)) {
801
 
                if (cp_n->page == NULL && (ret =
802
 
                    mpf->get(mpf, &cp_n->pgno, 0, &cp_n->page)) != 0)
803
 
                        goto err;
804
 
 
805
 
                if ((ret = __db_ret(dbp, cp_n->page, cp_n->indx,
806
 
                    key, &dbc_arg->rkey->data, &dbc_arg->rkey->ulen)) != 0)
807
 
                        goto err;
808
 
        }
809
 
        if (multi != 0) {
810
 
                /*
811
 
                 * Even if fetching from the OPD cursor we need a duplicate
812
 
                 * primary cursor if we are going after multiple keys.
813
 
                 */
814
 
                if (dbc_n == NULL) {
815
 
                        /*
816
 
                         * Non-"_KEY" DB_MULTIPLE doesn't move the main cursor,
817
 
                         * so it's safe to just use dbc_arg, unless dbc_arg
818
 
                         * has an open OPD cursor whose state might need to
819
 
                         * be preserved.
820
 
                         */
821
 
                        if ((!(multi & DB_MULTIPLE_KEY) &&
822
 
                            dbc_arg->internal->opd == NULL) ||
823
 
                            F_ISSET(dbc_arg, DBC_TRANSIENT))
824
 
                                dbc_n = dbc_arg;
825
 
                        else {
826
 
                                if ((ret = __db_c_idup(dbc_arg,
827
 
                                    &dbc_n, DB_POSITIONI)) != 0)
828
 
                                        goto err;
829
 
                                if ((ret = dbc_n->c_am_get(dbc_n,
830
 
                                    key, data, DB_CURRENT, &pgno)) != 0)
831
 
                                        goto err;
832
 
                        }
833
 
                        cp_n = dbc_n->internal;
834
 
                }
835
 
 
836
 
                /*
837
 
                 * If opd is set then we dupped the opd that we came in with.
838
 
                 * When we return we may have a new opd if we went to another
839
 
                 * key.
840
 
                 */
841
 
                if (opd != NULL) {
842
 
                        DB_ASSERT(cp_n->opd == NULL);
843
 
                        cp_n->opd = opd;
844
 
                        opd = NULL;
845
 
                }
846
 
 
847
 
                /*
848
 
                 * Bulk get doesn't use __db_retcopy, so data.size won't
849
 
                 * get set up unless there is an error.  Assume success
850
 
                 * here.  This is the only call to c_am_bulk, and it avoids
851
 
                 * setting it exactly the same everywhere.  If we have an
852
 
                 * ENOMEM error, it'll get overwritten with the needed value.
853
 
                 */
854
 
                data->size = data->ulen;
855
 
                ret = dbc_n->c_am_bulk(dbc_n, data, flags | multi);
856
 
        } else if (!F_ISSET(data, DB_DBT_ISSET)) {
857
 
                dbc = opd != NULL ? opd : cp_n->opd != NULL ? cp_n->opd : dbc_n;
858
 
                type = TYPE(dbc->internal->page);
859
 
                ret = __db_ret(dbp, dbc->internal->page, dbc->internal->indx +
860
 
                    (type == P_LBTREE || type == P_HASH ? O_INDX : 0),
861
 
                    data, &dbc_arg->rdata->data, &dbc_arg->rdata->ulen);
862
 
        }
863
 
 
864
 
err:    /* Don't pass DB_DBT_ISSET back to application level, error or no. */
865
 
        F_CLR(key, DB_DBT_ISSET);
866
 
        F_CLR(data, DB_DBT_ISSET);
867
 
 
868
 
        /* Cleanup and cursor resolution. */
869
 
        if (opd != NULL) {
870
 
                if ((t_ret = __db_c_cleanup(
871
 
                    dbc_arg->internal->opd, opd, ret)) != 0 && ret == 0)
872
 
                        ret = t_ret;
873
 
 
874
 
        }
875
 
 
876
 
        if ((t_ret = __db_c_cleanup(dbc_arg, dbc_n, ret)) != 0 && ret == 0)
877
 
                ret = t_ret;
878
 
 
879
 
        if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
880
 
                CDB_LOCKING_DONE(dbp, dbc_arg);
881
 
        return (ret);
882
 
}
883
 
 
884
 
/*
885
 
 * __db_c_put --
886
 
 *      Put using a cursor.
887
 
 *
888
 
 * PUBLIC: int __db_c_put __P((DBC *, DBT *, DBT *, u_int32_t));
889
 
 */
890
 
int
891
 
__db_c_put(dbc_arg, key, data, flags)
892
 
        DBC *dbc_arg;
893
 
        DBT *key, *data;
894
 
        u_int32_t flags;
895
 
{
896
 
        DB *dbp, *sdbp;
897
 
        DBC *dbc_n, *oldopd, *opd, *sdbc, *pdbc;
898
 
        DBT olddata, oldpkey, oldskey, newdata, pkey, save_skey, skey, temp;
899
 
        db_pgno_t pgno;
900
 
        int cmp, have_oldrec, ispartial, nodel, re_pad, ret, rmw, t_ret;
901
 
        u_int32_t re_len, size, tmp_flags;
902
 
 
903
 
        /*
904
 
         * Cursor Cleanup Note:
905
 
         * All of the cursors passed to the underlying access methods by this
906
 
         * routine are duplicated cursors.  On return, any referenced pages
907
 
         * will be discarded, and, if the cursor is not intended to be used
908
 
         * again, the close function will be called.  So, pages/locks that
909
 
         * the cursor references do not need to be resolved by the underlying
910
 
         * functions.
911
 
         */
912
 
        dbp = dbc_arg->dbp;
913
 
        sdbp = NULL;
914
 
        pdbc = dbc_n = NULL;
915
 
        memset(&newdata, 0, sizeof(DBT));
916
 
 
917
 
        PANIC_CHECK(dbp->dbenv);
918
 
 
919
 
        /* Check for invalid flags. */
920
 
        if ((ret = __db_cputchk(dbp,
921
 
            key, data, flags, IS_INITIALIZED(dbc_arg))) != 0)
922
 
                return (ret);
923
 
 
924
 
        /* Check for consistent transaction usage. */
925
 
        if ((ret = __db_check_txn(dbp, dbc_arg->txn, dbc_arg->locker, 0)) != 0)
926
 
                return (ret);
927
 
 
928
 
        /*
929
 
         * Putting to secondary indices is forbidden;  when we need
930
 
         * to internally update one, we'll call this with a private
931
 
         * synonym for DB_KEYLAST, DB_UPDATE_SECONDARY, which does
932
 
         * the right thing but won't return an error from cputchk().
933
 
         */
934
 
        if (flags == DB_UPDATE_SECONDARY)
935
 
                flags = DB_KEYLAST;
936
 
 
937
 
        DEBUG_LWRITE(dbc_arg, dbc_arg->txn, "db_c_put",
938
 
            flags == DB_KEYFIRST || flags == DB_KEYLAST ||
939
 
            flags == DB_NODUPDATA ? key : NULL, data, flags);
940
 
 
941
 
        CDB_LOCKING_INIT(dbp, dbc_arg);
942
 
 
943
 
        /*
944
 
         * Check to see if we are a primary and have secondary indices.
945
 
         * If we are not, we save ourselves a good bit of trouble and
946
 
         * just skip to the "normal" put.
947
 
         */
948
 
        if (LIST_FIRST(&dbp->s_secondaries) == NULL)
949
 
                goto skip_s_update;
950
 
 
951
 
        /*
952
 
         * We have at least one secondary which we may need to update.
953
 
         *
954
 
         * There is a rather vile locking issue here.  Secondary gets
955
 
         * will always involve acquiring a read lock in the secondary,
956
 
         * then acquiring a read lock in the primary.  Ideally, we
957
 
         * would likewise perform puts by updating all the secondaries
958
 
         * first, then doing the actual put in the primary, to avoid
959
 
         * deadlock (since having multiple threads doing secondary
960
 
         * gets and puts simultaneously is probably a common case).
961
 
         *
962
 
         * However, if this put is a put-overwrite--and we have no way to
963
 
         * tell in advance whether it will be--we may need to delete
964
 
         * an outdated secondary key.  In order to find that old
965
 
         * secondary key, we need to get the record we're overwriting,
966
 
         * before we overwrite it.
967
 
         *
968
 
         * (XXX: It would be nice to avoid this extra get, and have the
969
 
         * underlying put routines somehow pass us the old record
970
 
         * since they need to traverse the tree anyway.  I'm saving
971
 
         * this optimization for later, as it's a lot of work, and it
972
 
         * would be hard to fit into this locking paradigm anyway.)
973
 
         *
974
 
         * The simple thing to do would be to go get the old record before
975
 
         * we do anything else.  Unfortunately, though, doing so would
976
 
         * violate our "secondary, then primary" lock acquisition
977
 
         * ordering--even in the common case where no old primary record
978
 
         * exists, we'll still acquire and keep a lock on the page where
979
 
         * we're about to do the primary insert.
980
 
         *
981
 
         * To get around this, we do the following gyrations, which
982
 
         * hopefully solve this problem in the common case:
983
 
         *
984
 
         * 1) If this is a c_put(DB_CURRENT), go ahead and get the
985
 
         *    old record.  We already hold the lock on this page in
986
 
         *    the primary, so no harm done, and we'll need the primary
987
 
         *    key (which we weren't passed in this case) to do any
988
 
         *    secondary puts anyway.
989
 
         *
990
 
         * 2) If we're doing a partial put, we need to perform the
991
 
         *    get on the primary key right away, since we don't have
992
 
         *    the whole datum that the secondary key is based on.
993
 
         *    We may also need to pad out the record if the primary
994
 
         *    has a fixed record length.
995
 
         *
996
 
         * 3) Loop through the secondary indices, putting into each a
997
 
         *    new secondary key that corresponds to the new record.
998
 
         *
999
 
         * 4) If we haven't done so in (1) or (2), get the old primary
1000
 
         *    key/data pair.  If one does not exist--the common case--we're
1001
 
         *    done with secondary indices, and can go straight on to the
1002
 
         *    primary put.
1003
 
         *
1004
 
         * 5) If we do have an old primary key/data pair, however, we need
1005
 
         *    to loop through all the secondaries a second time and delete
1006
 
         *    the old secondary in each.
1007
 
         */
1008
 
        memset(&pkey, 0, sizeof(DBT));
1009
 
        memset(&olddata, 0, sizeof(DBT));
1010
 
        have_oldrec = nodel = 0;
1011
 
 
1012
 
        /*
1013
 
         * Primary indices can't have duplicates, so only DB_CURRENT,
1014
 
         * DB_KEYFIRST, and DB_KEYLAST make any sense.  Other flags
1015
 
         * should have been caught by the checking routine, but
1016
 
         * add a sprinkling of paranoia.
1017
 
         */
1018
 
        DB_ASSERT(flags == DB_CURRENT ||
1019
 
            flags == DB_KEYFIRST || flags == DB_KEYLAST);
1020
 
 
1021
 
        /*
1022
 
         * We'll want to use DB_RMW in a few places, but it's only legal
1023
 
         * when locking is on.
1024
 
         */
1025
 
        rmw = STD_LOCKING(dbc_arg) ? DB_RMW : 0;
1026
 
 
1027
 
        if (flags == DB_CURRENT) {              /* Step 1. */
1028
 
                /*
1029
 
                 * This is safe to do on the cursor we already have;
1030
 
                 * error or no, it won't move.
1031
 
                 *
1032
 
                 * We use DB_RMW for all of these gets because we'll be
1033
 
                 * writing soon enough in the "normal" put code.  In
1034
 
                 * transactional databases we'll hold those write locks
1035
 
                 * even if we close the cursor we're reading with.
1036
 
                 */
1037
 
                ret = dbc_arg->c_get(dbc_arg,
1038
 
                    &pkey, &olddata, rmw | DB_CURRENT);
1039
 
                if (ret == DB_KEYEMPTY) {
1040
 
                        nodel = 1;       /*
1041
 
                                          * We know we don't need a delete
1042
 
                                          * in the secondary.
1043
 
                                          */
1044
 
                        have_oldrec = 1; /* We've looked for the old record. */
1045
 
                } else if (ret != 0)
1046
 
                        goto err;
1047
 
                else
1048
 
                        have_oldrec = 1;
1049
 
 
1050
 
        } else {
1051
 
                /* So we can just use &pkey everywhere instead of key. */
1052
 
                pkey.data = key->data;
1053
 
                pkey.size = key->size;
1054
 
        }
1055
 
 
1056
 
        /*
1057
 
         * Check for partial puts (step 2).
1058
 
         */
1059
 
        if (F_ISSET(data, DB_DBT_PARTIAL)) {
1060
 
                if (!have_oldrec && !nodel) {
1061
 
                        /*
1062
 
                         * We're going to have to search the tree for the
1063
 
                         * specified key.  Dup a cursor (so we have the same
1064
 
                         * locking info) and do a c_get.
1065
 
                         */
1066
 
                        if ((ret = __db_c_idup(dbc_arg, &pdbc, 0)) != 0)
1067
 
                                goto err;
1068
 
 
1069
 
                        /* We should have gotten DB_CURRENT in step 1. */
1070
 
                        DB_ASSERT(flags != DB_CURRENT);
1071
 
 
1072
 
                        ret = pdbc->c_get(pdbc,
1073
 
                            &pkey, &olddata, rmw | DB_SET);
1074
 
                        if (ret == DB_KEYEMPTY || ret == DB_NOTFOUND) {
1075
 
                                nodel = 1;
1076
 
                                ret = 0;
1077
 
                        }
1078
 
                        if ((t_ret = pdbc->c_close(pdbc)) != 0)
1079
 
                                ret = t_ret;
1080
 
                        if (ret != 0)
1081
 
                                goto err;
1082
 
 
1083
 
                        have_oldrec = 1;
1084
 
                }
1085
 
 
1086
 
                /*
1087
 
                 * Now build the new datum from olddata and the partial
1088
 
                 * data we were given.
1089
 
                 */
1090
 
                if ((ret =
1091
 
                    __db_buildpartial(dbp, &olddata, data, &newdata)) != 0)
1092
 
                        goto err;
1093
 
                ispartial = 1;
1094
 
        } else
1095
 
                ispartial = 0;
1096
 
 
1097
 
        /*
1098
 
         * Handle fixed-length records.  If the primary database has
1099
 
         * fixed-length records, we need to pad out the datum before
1100
 
         * we pass it into the callback function;  we always index the
1101
 
         * "real" record.
1102
 
         */
1103
 
        if ((dbp->type == DB_RECNO && F_ISSET(dbp, DB_AM_FIXEDLEN)) ||
1104
 
            (dbp->type == DB_QUEUE)) {
1105
 
                if (dbp->type == DB_QUEUE) {
1106
 
                        re_len = ((QUEUE *)dbp->q_internal)->re_len;
1107
 
                        re_pad = ((QUEUE *)dbp->q_internal)->re_pad;
1108
 
                } else {
1109
 
                        re_len = ((BTREE *)dbp->bt_internal)->re_len;
1110
 
                        re_pad = ((BTREE *)dbp->bt_internal)->re_pad;
1111
 
                }
1112
 
 
1113
 
                size = ispartial ? newdata.size : data->size;
1114
 
                if (size > re_len) {
1115
 
                        __db_err(dbp->dbenv,
1116
 
                            "Length improper for fixed length record %lu",
1117
 
                            (u_long)size);
1118
 
                        ret = EINVAL;
1119
 
                        goto err;
1120
 
                } else if (size < re_len) {
1121
 
                        /*
1122
 
                         * If we're not doing a partial put, copy
1123
 
                         * data->data into newdata.data, then pad out
1124
 
                         * newdata.data.
1125
 
                         *
1126
 
                         * If we're doing a partial put, the data
1127
 
                         * we want are already in newdata.data;  we
1128
 
                         * just need to pad.
1129
 
                         *
1130
 
                         * Either way, realloc is safe.
1131
 
                         */
1132
 
                        if ((ret = __os_realloc(dbp->dbenv, re_len,
1133
 
                            &newdata.data)) != 0)
1134
 
                                goto err;
1135
 
                        if (!ispartial)
1136
 
                                memcpy(newdata.data, data->data, size);
1137
 
                        memset((u_int8_t *)newdata.data + size, re_pad,
1138
 
                            re_len - size);
1139
 
                        newdata.size = re_len;
1140
 
                        ispartial = 1;
1141
 
                }
1142
 
        }
1143
 
 
1144
 
        /*
1145
 
         * Loop through the secondaries.  (Step 3.)
1146
 
         *
1147
 
         * Note that __db_s_first and __db_s_next will take care of
1148
 
         * thread-locking and refcounting issues.
1149
 
         */
1150
 
        for (sdbp = __db_s_first(dbp);
1151
 
            sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
1152
 
                /*
1153
 
                 * Call the callback for this secondary, to get the
1154
 
                 * appropriate secondary key.
1155
 
                 */
1156
 
                memset(&skey, 0, sizeof(DBT));
1157
 
                if ((ret = sdbp->s_callback(sdbp,
1158
 
                    &pkey, ispartial ? &newdata : data, &skey)) != 0) {
1159
 
                        if (ret == DB_DONOTINDEX)
1160
 
                                /*
1161
 
                                 * The callback returned a null value--don't
1162
 
                                 * put this key in the secondary.  Just
1163
 
                                 * move on to the next one--we'll handle
1164
 
                                 * any necessary deletes in step 5.
1165
 
                                 */
1166
 
                                continue;
1167
 
                        else
1168
 
                                goto err;
1169
 
                }
1170
 
 
1171
 
                /*
1172
 
                 * Save the DBT we just got back from the callback function
1173
 
                 * off;  we want to pass its value into c_get functions
1174
 
                 * that may stomp on a buffer the callback function
1175
 
                 * allocated.
1176
 
                 */
1177
 
                memset(&save_skey, 0, sizeof(DBT));     /* Paranoia. */
1178
 
                save_skey = skey;
1179
 
 
1180
 
                /*
1181
 
                 * Open a cursor in this secondary.
1182
 
                 *
1183
 
                 * Use the same locker ID as our primary cursor, so that
1184
 
                 * we're guaranteed that the locks don't conflict (e.g. in CDB
1185
 
                 * or if we're subdatabases that share and want to lock a
1186
 
                 * metadata page).
1187
 
                 */
1188
 
                if ((ret = __db_icursor(sdbp, dbc_arg->txn, sdbp->type,
1189
 
                    PGNO_INVALID, 0, dbc_arg->locker, &sdbc)) != 0)
1190
 
                        goto err;
1191
 
 
1192
 
                /*
1193
 
                 * If we're in CDB, updates will fail since the new cursor
1194
 
                 * isn't a writer.  However, we hold the WRITE lock in the
1195
 
                 * primary and will for as long as our new cursor lasts,
1196
 
                 * and the primary and secondary share a lock file ID,
1197
 
                 * so it's safe to consider this a WRITER.  The close
1198
 
                 * routine won't try to put anything because we don't
1199
 
                 * really have a lock.
1200
 
                 */
1201
 
                if (CDB_LOCKING(sdbp->dbenv)) {
1202
 
                        DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
1203
 
                        F_SET(sdbc, DBC_WRITER);
1204
 
                }
1205
 
 
1206
 
                /*
1207
 
                 * There are three cases here--
1208
 
                 * 1) The secondary supports sorted duplicates.
1209
 
                 *      If we attempt to put a secondary/primary pair
1210
 
                 *      that already exists, that's a duplicate duplicate,
1211
 
                 *      and c_put will return DB_KEYEXIST (see __db_duperr).
1212
 
                 *      This will leave us with exactly one copy of the
1213
 
                 *      secondary/primary pair, and this is just right--we'll
1214
 
                 *      avoid deleting it later, as the old and new secondaries
1215
 
                 *      will match (since the old secondary is the dup dup
1216
 
                 *      that's already there).
1217
 
                 * 2) The secondary supports duplicates, but they're not
1218
 
                 *      sorted.  We need to avoid putting a duplicate
1219
 
                 *      duplicate, because the matching old and new secondaries
1220
 
                 *      will prevent us from deleting anything and we'll
1221
 
                 *      wind up with two secondary records that point to the
1222
 
                 *      same primary key.  Do a c_get(DB_GET_BOTH);  if
1223
 
                 *      that returns 0, skip the put.
1224
 
                 * 3) The secondary doesn't support duplicates at all.
1225
 
                 *      In this case, secondary keys must be unique;  if
1226
 
                 *      another primary key already exists for this
1227
 
                 *      secondary key, we have to either overwrite it or
1228
 
                 *      not put this one, and in either case we've
1229
 
                 *      corrupted the secondary index.  Do a c_get(DB_SET).
1230
 
                 *      If the secondary/primary pair already exists, do
1231
 
                 *      nothing;  if the secondary exists with a different
1232
 
                 *      primary, return an error;  and if the secondary
1233
 
                 *      does not exist, put it.
1234
 
                 */
1235
 
                if (!F_ISSET(sdbp, DB_AM_DUP)) {
1236
 
                        /* Case 3. */
1237
 
                        memset(&oldpkey, 0, sizeof(DBT));
1238
 
                        F_SET(&oldpkey, DB_DBT_MALLOC);
1239
 
                        ret = sdbc->c_real_get(sdbc,
1240
 
                            &skey, &oldpkey, rmw | DB_SET);
1241
 
                        if (ret == 0) {
1242
 
                                cmp = __bam_defcmp(sdbp, &oldpkey, &pkey);
1243
 
                                __os_ufree(sdbp->dbenv, oldpkey.data);
1244
 
                                if (cmp != 0) {
1245
 
                                        __db_err(sdbp->dbenv, "%s%s",
1246
 
                            "Put results in a non-unique secondary key in an ",
1247
 
                            "index not configured to support duplicates");
1248
 
                                        ret = EINVAL;
1249
 
                                        goto skipput;
1250
 
                                }
1251
 
                        } else if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)
1252
 
                                goto skipput;
1253
 
                } else if (!F_ISSET(sdbp, DB_AM_DUPSORT))
1254
 
                        /* Case 2. */
1255
 
                        if ((ret = sdbc->c_real_get(sdbc,
1256
 
                            &skey, &pkey, rmw | DB_GET_BOTH)) == 0)
1257
 
                                goto skipput;
1258
 
 
1259
 
                ret = sdbc->c_put(sdbc, &skey, &pkey, DB_UPDATE_SECONDARY);
1260
 
 
1261
 
                /*
1262
 
                 * We don't know yet whether this was a put-overwrite that
1263
 
                 * in fact changed nothing.  If it was, we may get DB_KEYEXIST.
1264
 
                 * This is not an error.
1265
 
                 */
1266
 
                if (ret == DB_KEYEXIST)
1267
 
                        ret = 0;
1268
 
 
1269
 
skipput:        FREE_IF_NEEDED(sdbp, &save_skey)
1270
 
 
1271
 
                if ((t_ret = sdbc->c_close(sdbc)) != 0)
1272
 
                        ret = t_ret;
1273
 
 
1274
 
                if (ret != 0)
1275
 
                        goto err;
1276
 
        }
1277
 
        if (ret != 0)
1278
 
                goto err;
1279
 
 
1280
 
        /* If still necessary, go get the old primary key/data.  (Step 4.) */
1281
 
        if (!have_oldrec) {
1282
 
                /* See the comments in step 2.  This is real familiar. */
1283
 
                if ((ret = __db_c_idup(dbc_arg, &pdbc, 0)) != 0)
1284
 
                        goto err;
1285
 
                DB_ASSERT(flags != DB_CURRENT);
1286
 
                pkey.data = key->data;
1287
 
                pkey.size = key->size;
1288
 
                ret = pdbc->c_get(pdbc, &pkey, &olddata, rmw | DB_SET);
1289
 
                if (ret == DB_KEYEMPTY || ret == DB_NOTFOUND) {
1290
 
                        nodel = 1;
1291
 
                        ret = 0;
1292
 
                }
1293
 
                if ((t_ret = pdbc->c_close(pdbc)) != 0)
1294
 
                        ret = t_ret;
1295
 
                if (ret != 0)
1296
 
                        goto err;
1297
 
                have_oldrec = 1;
1298
 
        }
1299
 
 
1300
 
        /*
1301
 
         * If we don't follow this goto, we do in fact have an old record
1302
 
         * we may need to go delete.  (Step 5).
1303
 
         */
1304
 
        if (nodel)
1305
 
                goto skip_s_update;
1306
 
 
1307
 
        for (sdbp = __db_s_first(dbp);
1308
 
            sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
1309
 
                /*
1310
 
                 * Call the callback for this secondary to get the
1311
 
                 * old secondary key.
1312
 
                 */
1313
 
                memset(&oldskey, 0, sizeof(DBT));
1314
 
                if ((ret = sdbp->s_callback(sdbp,
1315
 
                    &pkey, &olddata, &oldskey)) != 0) {
1316
 
                        if (ret == DB_DONOTINDEX)
1317
 
                                /*
1318
 
                                 * The callback returned a null value--there's
1319
 
                                 * nothing to delete.  Go on to the next
1320
 
                                 * secondary.
1321
 
                                 */
1322
 
                                continue;
1323
 
                        else
1324
 
                                goto err;
1325
 
                }
1326
 
                if ((ret = sdbp->s_callback(sdbp,
1327
 
                    &pkey, ispartial ? &newdata : data, &skey)) != 0 &&
1328
 
                    ret != DB_DONOTINDEX)
1329
 
                        goto err;
1330
 
 
1331
 
                /*
1332
 
                 * If there is no new secondary key, or if the old secondary
1333
 
                 * key is different from the new secondary key, then
1334
 
                 * we need to delete the old one.
1335
 
                 *
1336
 
                 * Note that bt_compare is (and must be) set no matter
1337
 
                 * what access method we're in.
1338
 
                 */
1339
 
                sdbc = NULL;
1340
 
                if (ret == DB_DONOTINDEX ||
1341
 
                    ((BTREE *)sdbp->bt_internal)->bt_compare(sdbp,
1342
 
                    &oldskey, &skey) != 0) {
1343
 
                        if ((ret = __db_icursor(sdbp, dbc_arg->txn, sdbp->type,
1344
 
                            PGNO_INVALID, 0, dbc_arg->locker, &sdbc)) != 0)
1345
 
                                goto err;
1346
 
                        if (CDB_LOCKING(sdbp->dbenv)) {
1347
 
                                DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
1348
 
                                F_SET(sdbc, DBC_WRITER);
1349
 
                        }
1350
 
 
1351
 
                        /*
1352
 
                         * Don't let c_get(DB_GET_BOTH) stomp on
1353
 
                         * any secondary key value that the callback
1354
 
                         * function may have allocated.  Use a temp
1355
 
                         * DBT instead.
1356
 
                         */
1357
 
                        memset(&temp, 0, sizeof(DBT));
1358
 
                        temp.data = oldskey.data;
1359
 
                        temp.size = oldskey.size;
1360
 
                        if ((ret = sdbc->c_real_get(sdbc,
1361
 
                            &temp, &pkey, rmw | DB_GET_BOTH)) == 0)
1362
 
                                ret = sdbc->c_del(sdbc, DB_UPDATE_SECONDARY);
1363
 
                }
1364
 
 
1365
 
                FREE_IF_NEEDED(sdbp, &skey);
1366
 
                FREE_IF_NEEDED(sdbp, &oldskey);
1367
 
                if (sdbc != NULL && (t_ret = sdbc->c_close(sdbc)) != 0)
1368
 
                        ret = t_ret;
1369
 
                if (ret != 0)
1370
 
                        goto err;
1371
 
        }
1372
 
 
1373
 
        /* Secondary index updates are now done.  On to the "real" stuff. */
1374
 
 
1375
 
skip_s_update:
1376
 
        /*
1377
 
         * If we have an off-page duplicates cursor, and the operation applies
1378
 
         * to it, perform the operation.  Duplicate the cursor and call the
1379
 
         * underlying function.
1380
 
         *
1381
 
         * Off-page duplicate trees are locked in the primary tree, that is,
1382
 
         * we acquire a write lock in the primary tree and no locks in the
1383
 
         * off-page dup tree.  If the put operation is done in an off-page
1384
 
         * duplicate tree, call the primary cursor's upgrade routine first.
1385
 
         */
1386
 
        if (dbc_arg->internal->opd != NULL &&
1387
 
            (flags == DB_AFTER || flags == DB_BEFORE || flags == DB_CURRENT)) {
1388
 
                /*
1389
 
                 * A special case for hash off-page duplicates.  Hash doesn't
1390
 
                 * support (and is documented not to support) put operations
1391
 
                 * relative to a cursor which references an already deleted
1392
 
                 * item.  For consistency, apply the same criteria to off-page
1393
 
                 * duplicates as well.
1394
 
                 */
1395
 
                if (dbc_arg->dbtype == DB_HASH && F_ISSET(
1396
 
                    ((BTREE_CURSOR *)(dbc_arg->internal->opd->internal)),
1397
 
                    C_DELETED)) {
1398
 
                        ret = DB_NOTFOUND;
1399
 
                        goto err;
1400
 
                }
1401
 
 
1402
 
                if ((ret = dbc_arg->c_am_writelock(dbc_arg)) != 0)
1403
 
                        return (ret);
1404
 
                if ((ret = __db_c_dup(dbc_arg, &dbc_n, DB_POSITIONI)) != 0)
1405
 
                        goto err;
1406
 
                opd = dbc_n->internal->opd;
1407
 
                if ((ret = opd->c_am_put(
1408
 
                    opd, key, data, flags, NULL)) != 0)
1409
 
                        goto err;
1410
 
                goto done;
1411
 
        }
1412
 
 
1413
 
        /*
1414
 
         * Perform an operation on the main cursor.  Duplicate the cursor,
1415
 
         * and call the underlying function.
1416
 
         *
1417
 
         * XXX: MARGO
1418
 
         *
1419
 
        tmp_flags = flags == DB_AFTER ||
1420
 
            flags == DB_BEFORE || flags == DB_CURRENT ? DB_POSITIONI : 0;
1421
 
         */
1422
 
        tmp_flags = DB_POSITIONI;
1423
 
 
1424
 
        /*
1425
 
         * If this cursor is going to be closed immediately, we don't
1426
 
         * need to take precautions to clean it up on error.
1427
 
         */
1428
 
        if (F_ISSET(dbc_arg, DBC_TRANSIENT))
1429
 
                dbc_n = dbc_arg;
1430
 
        else if ((ret = __db_c_idup(dbc_arg, &dbc_n, tmp_flags)) != 0)
1431
 
                goto err;
1432
 
 
1433
 
        pgno = PGNO_INVALID;
1434
 
        if ((ret = dbc_n->c_am_put(dbc_n, key, data, flags, &pgno)) != 0)
1435
 
                goto err;
1436
 
 
1437
 
        /*
1438
 
         * We may be referencing a new off-page duplicates tree.  Acquire
1439
 
         * a new cursor and call the underlying function.
1440
 
         */
1441
 
        if (pgno != PGNO_INVALID) {
1442
 
                oldopd = dbc_n->internal->opd;
1443
 
                if ((ret = __db_c_newopd(dbc_arg, pgno, oldopd, &opd)) != 0) {
1444
 
                        dbc_n->internal->opd = opd;
1445
 
                        goto err;
1446
 
                }
1447
 
 
1448
 
                dbc_n->internal->opd = opd;
1449
 
 
1450
 
                if ((ret = opd->c_am_put(
1451
 
                    opd, key, data, flags, NULL)) != 0)
1452
 
                        goto err;
1453
 
        }
1454
 
 
1455
 
done:
1456
 
err:    /* Cleanup and cursor resolution. */
1457
 
        if ((t_ret = __db_c_cleanup(dbc_arg, dbc_n, ret)) != 0 && ret == 0)
1458
 
                ret = t_ret;
1459
 
 
1460
 
        /* If newdata was used, free its buffer. */
1461
 
        if (newdata.data != NULL)
1462
 
                __os_free(dbp->dbenv, newdata.data);
1463
 
 
1464
 
        CDB_LOCKING_DONE(dbp, dbc_arg);
1465
 
 
1466
 
        if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0)
1467
 
                return (t_ret);
1468
 
 
1469
 
        return (ret);
1470
 
}
1471
 
 
1472
 
/*
1473
 
 * __db_duperr()
1474
 
 *      Error message: we don't currently support sorted duplicate duplicates.
1475
 
 * PUBLIC: int __db_duperr __P((DB *, u_int32_t));
1476
 
 */
1477
 
int
1478
 
__db_duperr(dbp, flags)
1479
 
        DB *dbp;
1480
 
        u_int32_t flags;
1481
 
{
1482
 
 
1483
 
        /*
1484
 
         * If we run into this error while updating a secondary index,
1485
 
         * don't yell--there's no clean way to pass DB_NODUPDATA in along
1486
 
         * with DB_UPDATE_SECONDARY, but we may run into this problem
1487
 
         * in a normal, non-error course of events.
1488
 
         *
1489
 
         * !!!
1490
 
         * If and when we ever permit duplicate duplicates in sorted-dup
1491
 
         * databases, we need to either change the secondary index code
1492
 
         * to check for dup dups, or we need to maintain the implicit
1493
 
         * "DB_NODUPDATA" behavior for databases with DB_AM_SECONDARY set.
1494
 
         */
1495
 
        if (flags != DB_NODUPDATA && !F_ISSET(dbp, DB_AM_SECONDARY))
1496
 
                __db_err(dbp->dbenv,
1497
 
                    "Duplicate data items are not supported with sorted data");
1498
 
        return (DB_KEYEXIST);
1499
 
}
1500
 
 
1501
 
/*
1502
 
 * __db_c_cleanup --
1503
 
 *      Clean up duplicate cursors.
1504
 
 */
1505
 
static int
1506
 
__db_c_cleanup(dbc, dbc_n, failed)
1507
 
        DBC *dbc, *dbc_n;
1508
 
        int failed;
1509
 
{
1510
 
        DB *dbp;
1511
 
        DBC *opd;
1512
 
        DBC_INTERNAL *internal;
1513
 
        DB_MPOOLFILE *mpf;
1514
 
        int ret, t_ret;
1515
 
 
1516
 
        dbp = dbc->dbp;
1517
 
        mpf = dbp->mpf;
1518
 
        internal = dbc->internal;
1519
 
        ret = 0;
1520
 
 
1521
 
        /* Discard any pages we're holding. */
1522
 
        if (internal->page != NULL) {
1523
 
                if ((t_ret = mpf->put(mpf, internal->page, 0)) != 0 && ret == 0)
1524
 
                        ret = t_ret;
1525
 
                internal->page = NULL;
1526
 
        }
1527
 
        opd = internal->opd;
1528
 
        if (opd != NULL && opd->internal->page != NULL) {
1529
 
                if ((t_ret =
1530
 
                    mpf->put(mpf, opd->internal->page, 0)) != 0 && ret == 0)
1531
 
                        ret = t_ret;
1532
 
                 opd->internal->page = NULL;
1533
 
        }
1534
 
 
1535
 
        /*
1536
 
         * If dbc_n is NULL, there's no internal cursor swapping to be done
1537
 
         * and no dbc_n to close--we probably did the entire operation on an
1538
 
         * offpage duplicate cursor.  Just return.
1539
 
         *
1540
 
         * If dbc and dbc_n are the same, we're either inside a DB->{put/get}
1541
 
         * operation, and as an optimization we performed the operation on
1542
 
         * the main cursor rather than on a duplicated one, or we're in a
1543
 
         * bulk get that can't have moved the cursor (DB_MULTIPLE with the
1544
 
         * initial c_get operation on an off-page dup cursor).  Just
1545
 
         * return--either we know we didn't move the cursor, or we're going
1546
 
         * to close it before we return to application code, so we're sure
1547
 
         * not to visibly violate the "cursor stays put on error" rule.
1548
 
         */
1549
 
        if (dbc_n == NULL || dbc == dbc_n)
1550
 
                return (ret);
1551
 
 
1552
 
        if (dbc_n->internal->page != NULL) {
1553
 
                if ((t_ret =
1554
 
                    mpf->put(mpf, dbc_n->internal->page, 0)) != 0 && ret == 0)
1555
 
                        ret = t_ret;
1556
 
                dbc_n->internal->page = NULL;
1557
 
        }
1558
 
        opd = dbc_n->internal->opd;
1559
 
        if (opd != NULL && opd->internal->page != NULL) {
1560
 
                if ((t_ret =
1561
 
                    mpf->put(mpf, opd->internal->page, 0)) != 0 && ret == 0)
1562
 
                        ret = t_ret;
1563
 
                opd->internal->page = NULL;
1564
 
        }
1565
 
 
1566
 
        /*
1567
 
         * If we didn't fail before entering this routine or just now when
1568
 
         * freeing pages, swap the interesting contents of the old and new
1569
 
         * cursors.
1570
 
         */
1571
 
        if (!failed && ret == 0) {
1572
 
                dbc->internal = dbc_n->internal;
1573
 
                dbc_n->internal = internal;
1574
 
        }
1575
 
 
1576
 
        /*
1577
 
         * Close the cursor we don't care about anymore.  The close can fail,
1578
 
         * but we only expect DB_LOCK_DEADLOCK failures.  This violates our
1579
 
         * "the cursor is unchanged on error" semantics, but since all you can
1580
 
         * do with a DB_LOCK_DEADLOCK failure is close the cursor, I believe
1581
 
         * that's OK.
1582
 
         *
1583
 
         * XXX
1584
 
         * There's no way to recover from failure to close the old cursor.
1585
 
         * All we can do is move to the new position and return an error.
1586
 
         *
1587
 
         * XXX
1588
 
         * We might want to consider adding a flag to the cursor, so that any
1589
 
         * subsequent operations other than close just return an error?
1590
 
         */
1591
 
        if ((t_ret = dbc_n->c_close(dbc_n)) != 0 && ret == 0)
1592
 
                ret = t_ret;
1593
 
 
1594
 
        return (ret);
1595
 
}
1596
 
 
1597
 
/*
1598
 
 * __db_c_secondary_get --
1599
 
 *      This wrapper function for DBC->c_pget() is the DBC->c_get() function
1600
 
 *      for a secondary index cursor.
1601
 
 *
1602
 
 * PUBLIC: int __db_c_secondary_get __P((DBC *, DBT *, DBT *, u_int32_t));
1603
 
 */
1604
 
int
1605
 
__db_c_secondary_get(dbc, skey, data, flags)
1606
 
        DBC *dbc;
1607
 
        DBT *skey, *data;
1608
 
        u_int32_t flags;
1609
 
{
1610
 
 
1611
 
        DB_ASSERT(F_ISSET(dbc->dbp, DB_AM_SECONDARY));
1612
 
        return (dbc->c_pget(dbc, skey, NULL, data, flags));
1613
 
}
1614
 
 
1615
 
/*
1616
 
 * __db_c_pget --
1617
 
 *      Get a primary key/data pair through a secondary index.
1618
 
 *
1619
 
 * PUBLIC: int __db_c_pget __P((DBC *, DBT *, DBT *, DBT *, u_int32_t));
1620
 
 */
1621
 
int
1622
 
__db_c_pget(dbc, skey, pkey, data, flags)
1623
 
        DBC *dbc;
1624
 
        DBT *skey, *pkey, *data;
1625
 
        u_int32_t flags;
1626
 
{
1627
 
        DB *pdbp, *sdbp;
1628
 
        DBC *pdbc;
1629
 
        DBT *save_rdata, nullpkey;
1630
 
        int pkeymalloc, ret, save_pkey_flags, t_ret;
1631
 
 
1632
 
        sdbp = dbc->dbp;
1633
 
        pdbp = sdbp->s_primary;
1634
 
        pkeymalloc = t_ret = 0;
1635
 
 
1636
 
        PANIC_CHECK(sdbp->dbenv);
1637
 
        if ((ret = __db_cpgetchk(sdbp,
1638
 
            skey, pkey, data, flags, IS_INITIALIZED(dbc))) != 0)
1639
 
                return (ret);
1640
 
 
1641
 
        /*
1642
 
         * The challenging part of this function is getting the behavior
1643
 
         * right for all the various permutations of DBT flags.  The
1644
 
         * next several blocks handle the various cases we need to
1645
 
         * deal with specially.
1646
 
         */
1647
 
 
1648
 
        /*
1649
 
         * We may be called with a NULL pkey argument, if we've been
1650
 
         * wrapped by a 2-DBT get call.  If so, we need to use our
1651
 
         * own DBT.
1652
 
         */
1653
 
        if (pkey == NULL) {
1654
 
                memset(&nullpkey, 0, sizeof(DBT));
1655
 
                pkey = &nullpkey;
1656
 
        }
1657
 
 
1658
 
        /*
1659
 
         * DB_GET_RECNO is a special case, because we're interested not in
1660
 
         * the primary key/data pair, but rather in the primary's record
1661
 
         * number.
1662
 
         */
1663
 
        if ((flags & DB_OPFLAGS_MASK) == DB_GET_RECNO)
1664
 
                return (__db_c_pget_recno(dbc, pkey, data, flags));
1665
 
 
1666
 
        /*
1667
 
         * If the DBTs we've been passed don't have any of the
1668
 
         * user-specified memory management flags set, we want to make sure
1669
 
         * we return values using the DBTs dbc->rskey, dbc->rkey, and
1670
 
         * dbc->rdata, respectively.
1671
 
         *
1672
 
         * There are two tricky aspects to this:  first, we need to pass
1673
 
         * skey and pkey *in* to the initial c_get on the secondary key,
1674
 
         * since either or both may be looked at by it (depending on the
1675
 
         * get flag).  Second, we must not use a normal DB->get call
1676
 
         * on the secondary, even though that's what we want to accomplish,
1677
 
         * because the DB handle may be free-threaded.  Instead,
1678
 
         * we open a cursor, then take steps to ensure that we actually use
1679
 
         * the rkey/rdata from the *secondary* cursor.
1680
 
         *
1681
 
         * We accomplish all this by passing in the DBTs we started out
1682
 
         * with to the c_get, but having swapped the contents of rskey and
1683
 
         * rkey, respectively, into rkey and rdata;  __db_ret will treat
1684
 
         * them like the normal key/data pair in a c_get call, and will
1685
 
         * realloc them as need be (this is "step 1").  Then, for "step 2",
1686
 
         * we swap back rskey/rkey/rdata to normal, and do a get on the primary
1687
 
         * with the secondary dbc appointed as the owner of the returned-data
1688
 
         * memory.
1689
 
         *
1690
 
         * Note that in step 2, we copy the flags field in case we need to
1691
 
         * pass down a DB_DBT_PARTIAL or other flag that is compatible with
1692
 
         * letting DB do the memory management.
1693
 
         */
1694
 
        /* Step 1. */
1695
 
        save_rdata = dbc->rdata;
1696
 
        dbc->rdata = dbc->rkey;
1697
 
        dbc->rkey = dbc->rskey;
1698
 
 
1699
 
        /*
1700
 
         * It is correct, though slightly sick, to attempt a partial get
1701
 
         * of a primary key.  However, if we do so here, we'll never find the
1702
 
         * primary record;  clear the DB_DBT_PARTIAL field of pkey just
1703
 
         * for the duration of the next call.
1704
 
         */
1705
 
        save_pkey_flags = pkey->flags;
1706
 
        F_CLR(pkey, DB_DBT_PARTIAL);
1707
 
 
1708
 
        /*
1709
 
         * Now we can go ahead with the meat of this call.  First, get the
1710
 
         * primary key from the secondary index.  (What exactly we get depends
1711
 
         * on the flags, but the underlying cursor get will take care of the
1712
 
         * dirty work.)
1713
 
         */
1714
 
        if ((ret = dbc->c_real_get(dbc, skey, pkey, flags)) != 0) {
1715
 
                /* Restore rskey/rkey/rdata and return. */
1716
 
                pkey->flags = save_pkey_flags;
1717
 
                dbc->rskey = dbc->rkey;
1718
 
                dbc->rkey = dbc->rdata;
1719
 
                dbc->rdata = save_rdata;
1720
 
                goto err;
1721
 
        }
1722
 
 
1723
 
        /* Restore pkey's flags in case we stomped the PARTIAL flag. */
1724
 
        pkey->flags = save_pkey_flags;
1725
 
 
1726
 
        /*
1727
 
         * Restore the cursor's rskey, rkey, and rdata DBTs.  If DB
1728
 
         * is handling the memory management, we now have newly
1729
 
         * reallocated buffers and ulens in rkey and rdata which we want
1730
 
         * to put in rskey and rkey.  save_rdata contains the old value
1731
 
         * of dbc->rdata.
1732
 
         */
1733
 
        dbc->rskey = dbc->rkey;
1734
 
        dbc->rkey = dbc->rdata;
1735
 
        dbc->rdata = save_rdata;
1736
 
 
1737
 
        /*
1738
 
         * Now we're ready for "step 2".  If either or both of pkey and
1739
 
         * data do not have memory management flags set--that is, if DB is
1740
 
         * managing their memory--we need to swap around the rkey/rdata
1741
 
         * structures so that we don't wind up trying to use memory managed
1742
 
         * by the primary database cursor, which we'll close before we return.
1743
 
         *
1744
 
         * !!!
1745
 
         * If you're carefully following the bouncing ball, you'll note
1746
 
         * that in the DB-managed case, the buffer hanging off of pkey is
1747
 
         * the same as dbc->rkey->data.  This is just fine;  we may well
1748
 
         * realloc and stomp on it when we return, if we're going a
1749
 
         * DB_GET_BOTH and need to return a different partial or key
1750
 
         * (depending on the comparison function), but this is safe.
1751
 
         *
1752
 
         * !!!
1753
 
         * We need to use __db_icursor here rather than simply calling
1754
 
         * pdbp->cursor, because otherwise, if we're in CDB, we'll
1755
 
         * allocate a new locker ID and leave ourselves open to deadlocks.
1756
 
         * (Even though we're only acquiring read locks, we'll still block
1757
 
         * if there are any waiters.)
1758
 
         */
1759
 
        if ((ret = __db_icursor(pdbp,
1760
 
            dbc->txn, pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)
1761
 
                goto err;
1762
 
 
1763
 
        /*
1764
 
         * We're about to use pkey a second time.  If DB_DBT_MALLOC
1765
 
         * is set on it, we'll leak the memory we allocated the first time.
1766
 
         * Thus, set DB_DBT_REALLOC instead so that we reuse that memory
1767
 
         * instead of leaking it.
1768
 
         *
1769
 
         * !!!
1770
 
         * This assumes that the user must always specify a compatible
1771
 
         * realloc function if a malloc function is specified.  I think
1772
 
         * this is a reasonable requirement.
1773
 
         */
1774
 
        if (F_ISSET(pkey, DB_DBT_MALLOC)) {
1775
 
                F_CLR(pkey, DB_DBT_MALLOC);
1776
 
                F_SET(pkey, DB_DBT_REALLOC);
1777
 
                pkeymalloc = 1;
1778
 
        }
1779
 
 
1780
 
        /*
1781
 
         * Do the actual get.  Set DBC_TRANSIENT since we don't care
1782
 
         * about preserving the position on error, and it's faster.
1783
 
         * SET_RET_MEM so that the secondary DBC owns any returned-data
1784
 
         * memory.
1785
 
         */
1786
 
        F_SET(pdbc, DBC_TRANSIENT);
1787
 
        SET_RET_MEM(pdbc, dbc);
1788
 
        ret = pdbc->c_get(pdbc, pkey, data, DB_SET);
1789
 
 
1790
 
        /*
1791
 
         * If the item wasn't found in the primary, this is a bug;
1792
 
         * our secondary has somehow gotten corrupted, and contains
1793
 
         * elements that don't correspond to anything in the primary.
1794
 
         * Complain.
1795
 
         */
1796
 
        if (ret == DB_NOTFOUND)
1797
 
                ret = __db_secondary_corrupt(pdbp);
1798
 
 
1799
 
        /* Now close the primary cursor. */
1800
 
        t_ret = pdbc->c_close(pdbc);
1801
 
 
1802
 
err:    if (pkeymalloc) {
1803
 
                /*
1804
 
                 * If pkey had a MALLOC flag, we need to restore it;
1805
 
                 * otherwise, if the user frees the buffer but reuses
1806
 
                 * the DBT without NULL'ing its data field or changing
1807
 
                 * the flags, we may drop core.
1808
 
                 */
1809
 
                F_CLR(pkey, DB_DBT_REALLOC);
1810
 
                F_SET(pkey, DB_DBT_MALLOC);
1811
 
        }
1812
 
        return (t_ret == 0 ? ret : t_ret);
1813
 
}
1814
 
 
1815
 
/*
1816
 
 * __db_c_pget_recno --
1817
 
 *      Perform a DB_GET_RECNO c_pget on a secondary index.  Returns
1818
 
 * the secondary's record number in the pkey field and the primary's
1819
 
 * in the data field.
1820
 
 */
1821
 
static int
1822
 
__db_c_pget_recno(sdbc, pkey, data, flags)
1823
 
        DBC *sdbc;
1824
 
        DBT *pkey, *data;
1825
 
        u_int32_t flags;
1826
 
{
1827
 
        DB *pdbp, *sdbp;
1828
 
        DB_ENV *dbenv;
1829
 
        DBC *pdbc;
1830
 
        DBT discardme, primary_key;
1831
 
        db_recno_t oob;
1832
 
        u_int32_t rmw;
1833
 
        int ret, t_ret;
1834
 
 
1835
 
        sdbp = sdbc->dbp;
1836
 
        pdbp = sdbp->s_primary;
1837
 
        dbenv = sdbp->dbenv;
1838
 
        pdbc = NULL;
1839
 
        ret = t_ret = 0;
1840
 
 
1841
 
        rmw = LF_ISSET(DB_RMW);
1842
 
 
1843
 
        memset(&discardme, 0, sizeof(DBT));
1844
 
        F_SET(&discardme, DB_DBT_USERMEM | DB_DBT_PARTIAL);
1845
 
 
1846
 
        oob = RECNO_OOB;
1847
 
 
1848
 
        /*
1849
 
         * If the primary is an rbtree, we want its record number, whether
1850
 
         * or not the secondary is one too.  Fetch the recno into "data".
1851
 
         *
1852
 
         * If it's not an rbtree, return RECNO_OOB in "data".
1853
 
         */
1854
 
        if (F_ISSET(pdbp, DB_AM_RECNUM)) {
1855
 
                /*
1856
 
                 * Get the primary key, so we can find the record number
1857
 
                 * in the primary. (We're uninterested in the secondary key.)
1858
 
                 */
1859
 
                memset(&primary_key, 0, sizeof(DBT));
1860
 
                F_SET(&primary_key, DB_DBT_MALLOC);
1861
 
                if ((ret = sdbc->c_real_get(sdbc,
1862
 
                    &discardme, &primary_key, rmw | DB_CURRENT)) != 0)
1863
 
                        return (ret);
1864
 
 
1865
 
                /*
1866
 
                 * Open a cursor on the primary, set it to the right record,
1867
 
                 * and fetch its recno into "data".
1868
 
                 *
1869
 
                 * (See __db_c_pget for a comment on the use of __db_icursor.)
1870
 
                 *
1871
 
                 * SET_RET_MEM so that the secondary DBC owns any returned-data
1872
 
                 * memory.
1873
 
                 */
1874
 
                if ((ret = __db_icursor(pdbp, sdbc->txn,
1875
 
                    pdbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0)
1876
 
                        goto perr;
1877
 
                SET_RET_MEM(pdbc, sdbc);
1878
 
                if ((ret = pdbc->c_get(pdbc,
1879
 
                    &primary_key, &discardme, rmw | DB_SET)) != 0)
1880
 
                        goto perr;
1881
 
 
1882
 
                ret = pdbc->c_get(pdbc, &discardme, data, rmw | DB_GET_RECNO);
1883
 
 
1884
 
perr:           __os_ufree(sdbp->dbenv, primary_key.data);
1885
 
                if (pdbc != NULL &&
1886
 
                    (t_ret = pdbc->c_close(pdbc)) != 0 && ret == 0)
1887
 
                        ret = t_ret;
1888
 
                if (ret != 0)
1889
 
                        return (ret);
1890
 
        } else if ((ret = __db_retcopy(dbenv, data, &oob,
1891
 
                    sizeof(oob), &sdbc->rkey->data, &sdbc->rkey->ulen)) != 0)
1892
 
                        return (ret);
1893
 
 
1894
 
        /*
1895
 
         * If the secondary is an rbtree, we want its record number, whether
1896
 
         * or not the primary is one too.  Fetch the recno into "pkey".
1897
 
         *
1898
 
         * If it's not an rbtree, return RECNO_OOB in "pkey".
1899
 
         */
1900
 
        if (F_ISSET(sdbp, DB_AM_RECNUM))
1901
 
                return (sdbc->c_real_get(sdbc, &discardme, pkey, flags));
1902
 
        else
1903
 
                return (__db_retcopy(dbenv, pkey, &oob,
1904
 
                    sizeof(oob), &sdbc->rdata->data, &sdbc->rdata->ulen));
1905
 
}
1906
 
 
1907
 
/*
1908
 
 * __db_wrlock_err -- do not have a write lock.
1909
 
 */
1910
 
static int
1911
 
__db_wrlock_err(dbenv)
1912
 
        DB_ENV *dbenv;
1913
 
{
1914
 
        __db_err(dbenv, "Write attempted on read-only cursor");
1915
 
        return (EPERM);
1916
 
}
1917
 
 
1918
 
/*
1919
 
 * __db_c_del_secondary --
1920
 
 *      Perform a delete operation on a secondary index:  call through
1921
 
 *      to the primary and delete the primary record that this record
1922
 
 *      points to.
1923
 
 *
1924
 
 *      Note that deleting the primary record will call c_del on all
1925
 
 *      the secondaries, including this one;  thus, it is not necessary
1926
 
 *      to execute both this function and an actual delete.
1927
 
 *
1928
 
 */
1929
 
static int
1930
 
__db_c_del_secondary(dbc)
1931
 
        DBC *dbc;
1932
 
{
1933
 
        DB *pdbp;
1934
 
        DBC *pdbc;
1935
 
        DBT skey, pkey;
1936
 
        int ret, t_ret;
1937
 
 
1938
 
        memset(&skey, 0, sizeof(DBT));
1939
 
        memset(&pkey, 0, sizeof(DBT));
1940
 
 
1941
 
        /*
1942
 
         * Get the current item that we're pointing at.
1943
 
         * We don't actually care about the secondary key, just
1944
 
         * the primary.
1945
 
         */
1946
 
        F_SET(&skey, DB_DBT_PARTIAL | DB_DBT_USERMEM);
1947
 
        if ((ret = dbc->c_real_get(dbc,
1948
 
            &skey, &pkey, DB_CURRENT)) != 0)
1949
 
                return (ret);
1950
 
 
1951
 
        /*
1952
 
         * Create a cursor on the primary with our locker ID,
1953
 
         * so that when it calls back, we don't conflict.
1954
 
         *
1955
 
         * We create a cursor explicitly because there's no
1956
 
         * way to specify the same locker ID if we're using
1957
 
         * locking but not transactions if we use the DB->del
1958
 
         * interface.  This shouldn't be any less efficient
1959
 
         * anyway.
1960
 
         */
1961
 
        pdbp = dbc->dbp->s_primary;
1962
 
        if ((ret = __db_icursor(pdbp, dbc->txn,
1963
 
            pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)
1964
 
                return (ret);
1965
 
 
1966
 
        /*
1967
 
         * See comment in __db_c_put--if we're in CDB,
1968
 
         * we already hold the locks we need, and we need to flag
1969
 
         * the cursor as a WRITER so we don't run into errors
1970
 
         * when we try to delete.
1971
 
         */
1972
 
        if (CDB_LOCKING(pdbp->dbenv)) {
1973
 
                DB_ASSERT(pdbc->mylock.off == LOCK_INVALID);
1974
 
                F_SET(pdbc, DBC_WRITER);
1975
 
        }
1976
 
 
1977
 
        /*
1978
 
         * Set the new cursor to the correct primary key.  Then
1979
 
         * delete it.  We don't really care about the datum;
1980
 
         * just reuse our skey DBT.
1981
 
         *
1982
 
         * If the primary get returns DB_NOTFOUND, something is amiss--
1983
 
         * every record in the secondary should correspond to some record
1984
 
         * in the primary.
1985
 
         */
1986
 
        if ((ret = pdbc->c_get(pdbc, &pkey, &skey,
1987
 
            (STD_LOCKING(dbc) ? DB_RMW : 0) | DB_SET)) == 0)
1988
 
                ret = pdbc->c_del(pdbc, 0);
1989
 
        else if (ret == DB_NOTFOUND)
1990
 
                ret = __db_secondary_corrupt(pdbp);
1991
 
 
1992
 
        if ((t_ret = pdbc->c_close(pdbc)) != 0 && ret != 0)
1993
 
                ret = t_ret;
1994
 
 
1995
 
        return (ret);
1996
 
}
1997
 
 
1998
 
/*
1999
 
 * __db_c_del_primary --
2000
 
 *      Perform a delete operation on a primary index.  Loop through
2001
 
 *      all the secondary indices which correspond to this primary
2002
 
 *      database, and delete any secondary keys that point at the current
2003
 
 *      record.
2004
 
 *
2005
 
 * PUBLIC: int __db_c_del_primary __P((DBC *));
2006
 
 */
2007
 
int
2008
 
__db_c_del_primary(dbc)
2009
 
        DBC *dbc;
2010
 
{
2011
 
        DB *dbp, *sdbp;
2012
 
        DBC *sdbc;
2013
 
        DBT data, pkey, skey, temp;
2014
 
        int ret, t_ret;
2015
 
 
2016
 
        dbp = dbc->dbp;
2017
 
 
2018
 
        /*
2019
 
         * If we're called at all, we have at least one secondary.
2020
 
         * (Unfortunately, we can't assert this without grabbing the mutex.)
2021
 
         * Get the current record so that we can construct appropriate
2022
 
         * secondary keys as needed.
2023
 
         */
2024
 
        memset(&pkey, 0, sizeof(DBT));
2025
 
        memset(&data, 0, sizeof(DBT));
2026
 
        if ((ret = dbc->c_get(dbc, &pkey, &data, DB_CURRENT)) != 0)
2027
 
                return (ret);
2028
 
 
2029
 
        for (sdbp = __db_s_first(dbp);
2030
 
            sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
2031
 
                /*
2032
 
                 * Get the secondary key for this secondary and the current
2033
 
                 * item.
2034
 
                 */
2035
 
                memset(&skey, 0, sizeof(DBT));
2036
 
                if ((ret = sdbp->s_callback(sdbp, &pkey, &data, &skey)) != 0) {
2037
 
                        /*
2038
 
                         * If the current item isn't in this index, we
2039
 
                         * have no work to do.  Proceed.
2040
 
                         */
2041
 
                        if (ret == DB_DONOTINDEX)
2042
 
                                continue;
2043
 
 
2044
 
                        /* We had a substantive error.  Bail. */
2045
 
                        FREE_IF_NEEDED(sdbp, &skey);
2046
 
                        goto done;
2047
 
                }
2048
 
 
2049
 
                /* Open a secondary cursor. */
2050
 
                if ((ret = __db_icursor(sdbp, dbc->txn, sdbp->type,
2051
 
                    PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0)
2052
 
                        goto done;
2053
 
                /* See comment above and in __db_c_put. */
2054
 
                if (CDB_LOCKING(sdbp->dbenv)) {
2055
 
                        DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
2056
 
                        F_SET(sdbc, DBC_WRITER);
2057
 
                }
2058
 
 
2059
 
                /*
2060
 
                 * Set the secondary cursor to the appropriate item.
2061
 
                 * Delete it.
2062
 
                 *
2063
 
                 * We want to use DB_RMW if locking is on;  it's only
2064
 
                 * legal then, though.
2065
 
                 *
2066
 
                 * !!!
2067
 
                 * Don't stomp on any callback-allocated buffer in skey
2068
 
                 * when we do a c_get(DB_GET_BOTH);  use a temp DBT instead.
2069
 
                 */
2070
 
                memset(&temp, 0, sizeof(DBT));
2071
 
                temp.data = skey.data;
2072
 
                temp.size = skey.size;
2073
 
                if ((ret = sdbc->c_real_get(sdbc, &temp, &pkey,
2074
 
                    (STD_LOCKING(dbc) ? DB_RMW : 0) | DB_GET_BOTH)) == 0)
2075
 
                        ret = sdbc->c_del(sdbc, DB_UPDATE_SECONDARY);
2076
 
 
2077
 
                FREE_IF_NEEDED(sdbp, &skey);
2078
 
 
2079
 
                if ((t_ret = sdbc->c_close(sdbc)) != 0 || ret != 0) {
2080
 
                        if (ret == 0)
2081
 
                                ret = t_ret;
2082
 
                        goto done;
2083
 
                }
2084
 
        }
2085
 
 
2086
 
done:   if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
2087
 
                return (t_ret);
2088
 
        return (ret);
2089
 
}
2090
 
 
2091
 
/*
2092
 
 * __db_s_first --
2093
 
 *      Get the first secondary, if any are present, from the primary.
2094
 
 *
2095
 
 * PUBLIC: DB *__db_s_first __P((DB *));
2096
 
 */
2097
 
DB *
2098
 
__db_s_first(pdbp)
2099
 
        DB *pdbp;
2100
 
{
2101
 
        DB *sdbp;
2102
 
 
2103
 
        MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);
2104
 
        sdbp = LIST_FIRST(&pdbp->s_secondaries);
2105
 
 
2106
 
        /* See __db_s_next. */
2107
 
        if (sdbp != NULL)
2108
 
                sdbp->s_refcnt++;
2109
 
        MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);
2110
 
 
2111
 
        return (sdbp);
2112
 
}
2113
 
 
2114
 
/*
2115
 
 * __db_s_next --
2116
 
 *      Get the next secondary in the list.
2117
 
 *
2118
 
 * PUBLIC: int __db_s_next __P((DB **));
2119
 
 */
2120
 
int
2121
 
__db_s_next(sdbpp)
2122
 
        DB **sdbpp;
2123
 
{
2124
 
        DB *sdbp, *pdbp, *closeme;
2125
 
        int ret;
2126
 
 
2127
 
        /*
2128
 
         * Secondary indices are kept in a linked list, s_secondaries,
2129
 
         * off each primary DB handle.  If a primary is free-threaded,
2130
 
         * this list may only be traversed or modified while the primary's
2131
 
         * thread mutex is held.
2132
 
         *
2133
 
         * The tricky part is that we don't want to hold the thread mutex
2134
 
         * across the full set of secondary puts necessary for each primary
2135
 
         * put, or we'll wind up essentially single-threading all the puts
2136
 
         * to the handle;  the secondary puts will each take about as
2137
 
         * long as the primary does, and may require I/O.  So we instead
2138
 
         * hold the thread mutex only long enough to follow one link to the
2139
 
         * next secondary, and then we release it before performing the
2140
 
         * actual secondary put.
2141
 
         *
2142
 
         * The only danger here is that we might legitimately close a
2143
 
         * secondary index in one thread while another thread is performing
2144
 
         * a put and trying to update that same secondary index.  To
2145
 
         * prevent this from happening, we refcount the secondary handles.
2146
 
         * If close is called on a secondary index handle while we're putting
2147
 
         * to it, it won't really be closed--the refcount will simply drop,
2148
 
         * and we'll be responsible for closing it here.
2149
 
         */
2150
 
        sdbp = *sdbpp;
2151
 
        pdbp = sdbp->s_primary;
2152
 
        closeme = NULL;
2153
 
 
2154
 
        MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);
2155
 
        DB_ASSERT(sdbp->s_refcnt != 0);
2156
 
        if (--sdbp->s_refcnt == 0) {
2157
 
                LIST_REMOVE(sdbp, s_links);
2158
 
                closeme = sdbp;
2159
 
        }
2160
 
        sdbp = LIST_NEXT(sdbp, s_links);
2161
 
        if (sdbp != NULL)
2162
 
                sdbp->s_refcnt++;
2163
 
        MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);
2164
 
 
2165
 
        *sdbpp = sdbp;
2166
 
 
2167
 
        /*
2168
 
         * closeme->close() is a wrapper;  call __db_close explicitly.
2169
 
         */
2170
 
        ret = closeme != NULL ? __db_close(closeme, 0) : 0;
2171
 
        return (ret);
2172
 
}
2173
 
 
2174
 
/*
2175
 
 * __db_s_done --
2176
 
 *      Properly decrement the refcount on a secondary database handle we're
2177
 
 *      using, without calling __db_s_next.
2178
 
 *
2179
 
 * PUBLIC: int __db_s_done __P((DB *));
2180
 
 */
2181
 
int
2182
 
__db_s_done(sdbp)
2183
 
        DB *sdbp;
2184
 
{
2185
 
        DB *pdbp;
2186
 
        int doclose;
2187
 
 
2188
 
        pdbp = sdbp->s_primary;
2189
 
        doclose = 0;
2190
 
 
2191
 
        MUTEX_THREAD_LOCK(pdbp->dbenv, pdbp->mutexp);
2192
 
        DB_ASSERT(sdbp->s_refcnt != 0);
2193
 
        if (--sdbp->s_refcnt == 0) {
2194
 
                LIST_REMOVE(sdbp, s_links);
2195
 
                doclose = 1;
2196
 
        }
2197
 
        MUTEX_THREAD_UNLOCK(pdbp->dbenv, pdbp->mutexp);
2198
 
 
2199
 
        return (doclose ? __db_close(sdbp, 0) : 0);
2200
 
}
2201
 
 
2202
 
/*
2203
 
 * __db_buildpartial --
2204
 
 *      Build the record that will result after a partial put is applied to
2205
 
 *      an existing record.
2206
 
 *
2207
 
 *      This should probably be merged with __bam_build, but that requires
2208
 
 *      a little trickery if we plan to keep the overflow-record optimization
2209
 
 *      in that function.
2210
 
 */
2211
 
static int
2212
 
__db_buildpartial(dbp, oldrec, partial, newrec)
2213
 
        DB *dbp;
2214
 
        DBT *oldrec, *partial, *newrec;
2215
 
{
2216
 
        int ret;
2217
 
        u_int8_t *buf;
2218
 
        u_int32_t len, nbytes;
2219
 
 
2220
 
        DB_ASSERT(F_ISSET(partial, DB_DBT_PARTIAL));
2221
 
 
2222
 
        memset(newrec, 0, sizeof(DBT));
2223
 
 
2224
 
        nbytes = __db_partsize(oldrec->size, partial);
2225
 
        newrec->size = nbytes;
2226
 
 
2227
 
        if ((ret = __os_malloc(dbp->dbenv, nbytes, &buf)) != 0)
2228
 
                return (ret);
2229
 
        newrec->data = buf;
2230
 
 
2231
 
        /* Nul or pad out the buffer, for any part that isn't specified. */
2232
 
        memset(buf,
2233
 
            F_ISSET(dbp, DB_AM_FIXEDLEN) ? ((BTREE *)dbp->bt_internal)->re_pad :
2234
 
            0, nbytes);
2235
 
 
2236
 
        /* Copy in any leading data from the original record. */
2237
 
        memcpy(buf, oldrec->data,
2238
 
            partial->doff > oldrec->size ? oldrec->size : partial->doff);
2239
 
 
2240
 
        /* Copy the data from partial. */
2241
 
        memcpy(buf + partial->doff, partial->data, partial->size);
2242
 
 
2243
 
        /* Copy any trailing data from the original record. */
2244
 
        len = partial->doff + partial->dlen;
2245
 
        if (oldrec->size > len)
2246
 
                memcpy(buf + partial->doff + partial->size,
2247
 
                    (u_int8_t *)oldrec->data + len, oldrec->size - len);
2248
 
 
2249
 
        return (0);
2250
 
}
2251
 
 
2252
 
/*
2253
 
 * __db_partsize --
2254
 
 *      Given the number of bytes in an existing record and a DBT that
2255
 
 *      is about to be partial-put, calculate the size of the record
2256
 
 *      after the put.
2257
 
 *
2258
 
 *      This code is called from __bam_partsize.
2259
 
 *
2260
 
 * PUBLIC: u_int32_t __db_partsize __P((u_int32_t, DBT *));
2261
 
 */
2262
 
u_int32_t
2263
 
__db_partsize(nbytes, data)
2264
 
        u_int32_t nbytes;
2265
 
        DBT *data;
2266
 
{
2267
 
 
2268
 
        /*
2269
 
         * There are really two cases here:
2270
 
         *
2271
 
         * Case 1: We are replacing some bytes that do not exist (i.e., they
2272
 
         * are past the end of the record).  In this case the number of bytes
2273
 
         * we are replacing is irrelevant and all we care about is how many
2274
 
         * bytes we are going to add from offset.  So, the new record length
2275
 
         * is going to be the size of the new bytes (size) plus wherever those
2276
 
         * new bytes begin (doff).
2277
 
         *
2278
 
         * Case 2: All the bytes we are replacing exist.  Therefore, the new
2279
 
         * size is the oldsize (nbytes) minus the bytes we are replacing (dlen)
2280
 
         * plus the bytes we are adding (size).
2281
 
         */
2282
 
        if (nbytes < data->doff + data->dlen)           /* Case 1 */
2283
 
                return (data->doff + data->size);
2284
 
 
2285
 
        return (nbytes + data->size - data->dlen);      /* Case 2 */
2286
 
}