~ubuntu-branches/ubuntu/vivid/db/vivid-proposed

« back to all changes in this revision

Viewing changes to hash/hash_rec.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Adams
  • Date: 2010-04-04 09:37:47 UTC
  • mto: This revision was merged to the branch mainline in revision 20.
  • Revision ID: james.westby@ubuntu.com-20100404093747-7x3j05svjdoy8tdi
Tags: upstream-5.0.21
ImportĀ upstreamĀ versionĀ 5.0.21

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*-
2
2
 * See the file LICENSE for redistribution information.
3
3
 *
4
 
 * Copyright (c) 1996-2009 Oracle.  All rights reserved.
 
4
 * Copyright (c) 1996, 2010 Oracle and/or its affiliates.  All rights reserved.
5
5
 */
6
6
/*
7
7
 * Copyright (c) 1995, 1996
47
47
#include "dbinc/db_page.h"
48
48
#include "dbinc/btree.h"
49
49
#include "dbinc/hash.h"
50
 
#include "dbinc/log.h"
51
50
#include "dbinc/mp.h"
52
51
 
53
52
static int __ham_alloc_pages __P((DBC *, __ham_groupalloc_args *, DB_LSN *));
54
53
static int __ham_alloc_pages_42
55
54
    __P((DBC *, __ham_groupalloc_42_args *, DB_LSN *));
 
55
static int __ham_chgpg_recover_func
 
56
    __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *));
56
57
 
57
58
/*
58
59
 * __ham_insdel_recover --
75
76
        DB_MPOOLFILE *mpf;
76
77
        PAGE *pagep;
77
78
        db_indx_t dindx;
78
 
        u_int32_t opcode;
79
 
        int cmp_n, cmp_p, dtype, ktype, ret;
 
79
        int cmp_n, cmp_p, ret;
80
80
 
81
81
        ip = ((DB_TXNHEAD *)info)->thread_info;
82
82
        pagep = NULL;
122
122
         * We do this by calling __insertpair with the type H_OFFPAGE instead
123
123
         * of H_KEYDATA.
124
124
         */
 
125
        if ((argp->opcode == DELPAIR && cmp_n == 0 && DB_UNDO(op)) ||
 
126
            (argp->opcode == PUTPAIR && cmp_p == 0 && DB_REDO(op))) {
 
127
                /*
 
128
                 * Need to redo a PUT or undo a delete.
 
129
                 */
 
130
                REC_DIRTY(mpf, ip, file_dbp->priority, &pagep);
 
131
                dindx = (db_indx_t)argp->ndx;
 
132
                if ((ret = __ham_insertpair(dbc, pagep, &dindx, &argp->key,
 
133
                    &argp->data, OP_MODE_GET(argp->keytype),
 
134
                    OP_MODE_GET(argp->datatype))) != 0)
 
135
                        goto out;
 
136
                LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
 
137
        } else if ((argp->opcode == DELPAIR && cmp_p == 0 && DB_REDO(op)) ||
 
138
            (argp->opcode == PUTPAIR && cmp_n == 0 && DB_UNDO(op))) {
 
139
                /* Need to undo a put or redo a delete. */
 
140
                REC_DIRTY(mpf, ip, file_dbp->priority, &pagep);
 
141
                __ham_dpair(file_dbp, pagep, argp->ndx);
 
142
                LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;
 
143
        }
 
144
 
 
145
        if ((ret = __memp_fput(mpf, ip, pagep, file_dbp->priority)) != 0)
 
146
                goto out;
 
147
        pagep = NULL;
 
148
 
 
149
        /* Return the previous LSN. */
 
150
done:   *lsnp = argp->prev_lsn;
 
151
        ret = 0;
 
152
 
 
153
out:    if (pagep != NULL)
 
154
                (void)__memp_fput(mpf, ip, pagep, file_dbp->priority);
 
155
        REC_CLOSE;
 
156
}
 
157
 
 
158
/*
 
159
 * __ham_insdel_42_recover --
 
160
 *
 
161
 * PUBLIC: int __ham_insdel_42_recover
 
162
 * PUBLIC:     __P((ENV *, DBT *, DB_LSN *, db_recops, void *));
 
163
 */
 
164
int
 
165
__ham_insdel_42_recover(env, dbtp, lsnp, op, info)
 
166
        ENV *env;
 
167
        DBT *dbtp;
 
168
        DB_LSN *lsnp;
 
169
        db_recops op;
 
170
        void *info;
 
171
{
 
172
        __ham_insdel_42_args *argp;
 
173
        DB_THREAD_INFO *ip;
 
174
        DB *file_dbp;
 
175
        DBC *dbc;
 
176
        DB_MPOOLFILE *mpf;
 
177
        PAGE *pagep;
 
178
        db_indx_t dindx;
 
179
        u_int32_t dtype, ktype, opcode;
 
180
        int cmp_n, cmp_p, ret;
 
181
 
 
182
        ip = ((DB_TXNHEAD *)info)->thread_info;
 
183
        pagep = NULL;
 
184
        REC_PRINT(__ham_insdel_print);
 
185
        REC_INTRO(__ham_insdel_42_read, ip, 1);
 
186
 
 
187
        if ((ret = __memp_fget(mpf, &argp->pgno, ip, NULL,
 
188
            0, &pagep)) != 0) {
 
189
                if (DB_UNDO(op)) {
 
190
                        if (ret == DB_PAGE_NOTFOUND)
 
191
                                goto done;
 
192
                        else {
 
193
                                ret = __db_pgerr(file_dbp, argp->pgno, ret);
 
194
                                goto out;
 
195
                        }
 
196
                }
 
197
                /* If the page is not here then it was later truncated. */
 
198
                if (!IS_ZERO_LSN(argp->pagelsn))
 
199
                        goto done;
 
200
                /*
 
201
                 * This page was created by a group allocation and
 
202
                 * the file may not have been extend yet.
 
203
                 * Create the page if necessary.
 
204
                 */
 
205
                if ((ret = __memp_fget(mpf, &argp->pgno, ip, NULL,
 
206
                    DB_MPOOL_CREATE, &pagep)) != 0) {
 
207
                        ret = __db_pgerr(file_dbp, argp->pgno, ret);
 
208
                        goto out;
 
209
                }
 
210
        }
 
211
 
 
212
        cmp_n = LOG_COMPARE(lsnp, &LSN(pagep));
 
213
        cmp_p = LOG_COMPARE(&LSN(pagep), &argp->pagelsn);
 
214
        CHECK_LSN(env, op, cmp_p, &LSN(pagep), &argp->pagelsn);
 
215
 
 
216
        /*
 
217
         * Two possible things going on:
 
218
         * redo a delete/undo a put: delete the item from the page.
 
219
         * redo a put/undo a delete: add the item to the page.
 
220
         * If we are undoing a delete, then the information logged is the
 
221
         * entire entry off the page, not just the data of a dbt.  In
 
222
         * this case, we want to copy it back onto the page verbatim.
 
223
         * We do this by calling __insertpair with the type H_OFFPAGE instead
 
224
         * of H_KEYDATA.
 
225
         */
125
226
        opcode = OPCODE_OF(argp->opcode);
126
227
        if ((opcode == DELPAIR && cmp_n == 0 && DB_UNDO(op)) ||
127
228
            (opcode == PUTPAIR && cmp_p == 0 && DB_REDO(op))) {
330
431
        DBT dbt;
331
432
        PAGE *pagep;
332
433
        u_int32_t change;
 
434
        int cmp_n, cmp_p, is_plus, modified, off, ret;
 
435
        u_int8_t *hk;
 
436
 
 
437
        ip = ((DB_TXNHEAD *)info)->thread_info;
 
438
        pagep = NULL;
 
439
        REC_PRINT(__ham_replace_print);
 
440
        REC_INTRO(__ham_replace_read, ip, 0);
 
441
 
 
442
        REC_FGET(mpf, ip, argp->pgno, &pagep, done);
 
443
 
 
444
        cmp_n = LOG_COMPARE(lsnp, &LSN(pagep));
 
445
        cmp_p = LOG_COMPARE(&LSN(pagep), &argp->pagelsn);
 
446
        CHECK_LSN(env, op, cmp_p, &LSN(pagep), &argp->pagelsn);
 
447
        CHECK_ABORT(env, op, cmp_n, &LSN(pagep), lsnp);
 
448
 
 
449
        memset(&dbt, 0, sizeof(dbt));
 
450
        modified = 0;
 
451
 
 
452
        /*
 
453
         * Before we know the direction of the transformation we will
 
454
         * determine the size differential; then once we know if we are
 
455
         * redoing or undoing, we'll adjust the sign (is_plus) appropriately.
 
456
         */
 
457
        if (argp->newitem.size > argp->olditem.size) {
 
458
                change = argp->newitem.size - argp->olditem.size;
 
459
                is_plus = 1;
 
460
        } else {
 
461
                change = argp->olditem.size - argp->newitem.size;
 
462
                is_plus = 0;
 
463
        }
 
464
        /*
 
465
         * When chaning from a "regular" record to an off page record
 
466
         * the old record does not contain a header while the new record
 
467
         * does and is at an offset of -1 relative to the data part of
 
468
         * the record. We add this to the amount of the change (which is
 
469
         * an absolute value).  If we are undoing then the offset is not
 
470
         * used in the placement of the data.
 
471
         */
 
472
        off = argp->off;
 
473
        if (off < 0 &&
 
474
             (OP_MODE_GET(argp->oldtype) == H_DUPLICATE ||
 
475
             OP_MODE_GET(argp->oldtype) == H_KEYDATA)) {
 
476
                change -= (u_int32_t)off;
 
477
                if (DB_UNDO(op))
 
478
                        off = 0;
 
479
        }
 
480
        if (cmp_p == 0 && DB_REDO(op)) {
 
481
                /* Reapply the change as specified. */
 
482
                dbt.data = argp->newitem.data;
 
483
                dbt.size = argp->newitem.size;
 
484
                REC_DIRTY(mpf, ip, file_dbp->priority, &pagep);
 
485
                LSN(pagep) = *lsnp;
 
486
                /*
 
487
                 * The is_plus flag is set properly to reflect
 
488
                 * newitem.size - olditem.size.
 
489
                 */
 
490
                modified = 1;
 
491
        } else if (cmp_n == 0 && DB_UNDO(op)) {
 
492
                /* Undo the already applied change. */
 
493
                dbt.data = argp->olditem.data;
 
494
                dbt.size = argp->olditem.size;
 
495
                /*
 
496
                 * Invert is_plus to reflect sign of
 
497
                 * olditem.size - newitem.size.
 
498
                 */
 
499
                is_plus = !is_plus;
 
500
                REC_DIRTY(mpf, ip, file_dbp->priority, &pagep);
 
501
                LSN(pagep) = argp->pagelsn;
 
502
                modified = 1;
 
503
        }
 
504
 
 
505
        if (modified) {
 
506
                __ham_onpage_replace(file_dbp, pagep,
 
507
                    argp->ndx, off, change, is_plus, &dbt);
 
508
                if (argp->oldtype != argp->newtype) {
 
509
                        hk = P_ENTRY(file_dbp, pagep, argp->ndx);
 
510
                        if (DB_REDO(op))
 
511
                                HPAGE_PTYPE(hk) = OP_MODE_GET(argp->newtype);
 
512
                        else
 
513
                                HPAGE_PTYPE(hk) = OP_MODE_GET(argp->oldtype);
 
514
                }
 
515
        }
 
516
 
 
517
        if ((ret = __memp_fput(mpf, ip, pagep, file_dbp->priority)) != 0)
 
518
                goto out;
 
519
        pagep = NULL;
 
520
 
 
521
done:   *lsnp = argp->prev_lsn;
 
522
        ret = 0;
 
523
 
 
524
out:    if (pagep != NULL)
 
525
                (void)__memp_fput(mpf, ip, pagep, file_dbp->priority);
 
526
        REC_CLOSE;
 
527
}
 
528
 
 
529
/*
 
530
 * __ham_replace_42_recover --
 
531
 *      This log message refers to partial puts that are local to a single
 
532
 *      page.  You can think of them as special cases of the more general
 
533
 *      insdel log message.
 
534
 *
 
535
 * PUBLIC: int __ham_replace_42_recover
 
536
 * PUBLIC:    __P((ENV *, DBT *, DB_LSN *, db_recops, void *));
 
537
 */
 
538
int
 
539
__ham_replace_42_recover(env, dbtp, lsnp, op, info)
 
540
        ENV *env;
 
541
        DBT *dbtp;
 
542
        DB_LSN *lsnp;
 
543
        db_recops op;
 
544
        void *info;
 
545
{
 
546
        __ham_replace_42_args *argp;
 
547
        DB_THREAD_INFO *ip;
 
548
        DB *file_dbp;
 
549
        DBC *dbc;
 
550
        DB_MPOOLFILE *mpf;
 
551
        DBT dbt;
 
552
        PAGE *pagep;
 
553
        u_int32_t change;
333
554
        int cmp_n, cmp_p, is_plus, modified, ret;
334
555
        u_int8_t *hk;
335
556
 
336
557
        ip = ((DB_TXNHEAD *)info)->thread_info;
337
558
        pagep = NULL;
338
559
        REC_PRINT(__ham_replace_print);
339
 
        REC_INTRO(__ham_replace_read, ip, 0);
 
560
        REC_INTRO(__ham_replace_42_read, ip, 0);
340
561
 
341
562
        REC_FGET(mpf, ip, argp->pgno, &pagep, done);
342
563
 
734
955
                            &pgno, ip, NULL, DB_MPOOL_CREATE, &pagep)) != 0)
735
956
                                goto out;
736
957
 
737
 
                        if (IS_ZERO_LSN(LSN(pagep)))
 
958
                        if (IS_ZERO_LSN(LSN(pagep))) {
 
959
                                REC_DIRTY(mpf, ip, dbc->priority, &pagep);
738
960
                                P_INIT(pagep, file_dbp->pgsize,
739
961
                                    PGNO_INVALID, PGNO_INVALID, PGNO_INVALID,
740
962
                                    0, P_HASH);
 
963
                        }
741
964
                        if ((ret =
742
965
                            __memp_fput(mpf, ip, pagep, dbc->priority)) != 0)
743
966
                                goto out;
777
1000
        /*
778
1001
         * Now we need to fix up the spares array.  Each entry in the
779
1002
         * spares array indicates the beginning page number for the
780
 
         * indicated doubling.  We need to fill this in whenever the
781
 
         * spares array is invalid, if we never reclaim pages then
782
 
         * we have to allocate the pages to the spares array in both
783
 
         * the redo and undo cases.
 
1003
         * indicated doubling.
784
1004
         */
785
 
        if (did_alloc && !DB_UNDO(op) &&
786
 
            hcp->hdr->spares[__db_log2(argp->bucket + 1) + 1] == PGNO_INVALID) {
 
1005
        if (cmp_p == 0 && did_alloc && !DB_UNDO(op)) {
787
1006
                REC_DIRTY(mpf, ip, dbc->priority, &hcp->hdr);
788
1007
                hcp->hdr->spares[__db_log2(argp->bucket + 1) + 1] =
789
1008
                    (argp->pgno - argp->bucket) - 1;
822
1041
 
823
1042
        if (cmp_n == 0 && DB_UNDO(op))
824
1043
                mmeta->last_pgno = argp->last_pgno;
825
 
        else if (DB_REDO(op) && mmeta->last_pgno < pgno)
 
1044
        else if (cmp_p == 0 && DB_REDO(op) && mmeta->last_pgno < pgno)
826
1045
                mmeta->last_pgno = pgno;
827
1046
 
828
1047
        if (argp->mmpgno != argp->mpgno &&
842
1061
}
843
1062
 
844
1063
/*
 
1064
 * __ham_contract_recover --
 
1065
 *      Recovery function for contracting a hash table
 
1066
 *
 
1067
 * PUBLIC: int __ham_contract_recover
 
1068
 * PUBLIC:   __P((ENV *, DBT *, DB_LSN *, db_recops, void *));
 
1069
 */
 
1070
int
 
1071
__ham_contract_recover(env, dbtp, lsnp, op, info)
 
1072
        ENV *env;
 
1073
        DBT *dbtp;
 
1074
        DB_LSN *lsnp;
 
1075
        db_recops op;
 
1076
        void *info;
 
1077
{
 
1078
        __ham_contract_args *argp;
 
1079
        DB_THREAD_INFO *ip;
 
1080
        DB_MPOOLFILE *mpf;
 
1081
        DB *file_dbp;
 
1082
        DBC *dbc;
 
1083
        HASH_CURSOR *hcp;
 
1084
        HMETA *meta;
 
1085
        int cmp_n, cmp_p, ret;
 
1086
 
 
1087
        ip = ((DB_TXNHEAD *)info)->thread_info;
 
1088
        REC_PRINT(__ham_contract_print);
 
1089
        REC_INTRO(__ham_contract_read, ip, 1);
 
1090
 
 
1091
        hcp = (HASH_CURSOR *)dbc->internal;
 
1092
        if ((ret = __ham_get_meta(dbc)) != 0)
 
1093
                goto done;
 
1094
        meta = hcp->hdr;
 
1095
        cmp_n = LOG_COMPARE(lsnp, &meta->dbmeta.lsn);
 
1096
        cmp_p = LOG_COMPARE(&meta->dbmeta.lsn, &argp->meta_lsn);
 
1097
        CHECK_LSN(env, op, cmp_p, &meta->dbmeta.lsn, &argp->meta_lsn);
 
1098
        if (cmp_p == 0 && DB_REDO(op)) {
 
1099
                REC_DIRTY(mpf, ip, dbc->priority, &hcp->hdr);
 
1100
                meta = hcp->hdr;
 
1101
                meta->max_bucket = argp->bucket - 1;
 
1102
                if (argp->bucket == meta->low_mask + 1) {
 
1103
                        meta->spares[
 
1104
                            __db_log2(argp->bucket) + 1] = PGNO_INVALID;
 
1105
                        meta->high_mask = meta->low_mask;
 
1106
                        meta->low_mask >>= 1;
 
1107
                }
 
1108
                meta->dbmeta.lsn = *lsnp;
 
1109
        } else if (cmp_n == 0 && DB_UNDO(op)) {
 
1110
                REC_DIRTY(mpf, ip, dbc->priority, &hcp->hdr);
 
1111
                meta = hcp->hdr;
 
1112
                meta->max_bucket = argp->bucket;
 
1113
                if (argp->bucket == meta->high_mask + 1) {
 
1114
                        meta->spares[__db_log2(argp->bucket) + 1] =
 
1115
                            argp->pgno - argp->bucket;
 
1116
                        meta->low_mask = meta->high_mask;
 
1117
                        meta->high_mask = meta->max_bucket | meta->low_mask;
 
1118
                }
 
1119
                meta->dbmeta.lsn = argp->meta_lsn;
 
1120
        }
 
1121
        *lsnp = argp->prev_lsn;
 
1122
 
 
1123
out:    ret = __ham_release_meta(dbc);
 
1124
done:   REC_CLOSE;
 
1125
}
 
1126
 
 
1127
/*
845
1128
 * __ham_groupalloc_recover --
846
1129
 *      Recover the batch creation of a set of pages for a new database.
847
1130
 *
1018
1301
}
1019
1302
 
1020
1303
/*
 
1304
 * __ham_changeslot_recover --
 
1305
 *      Recovery function for changeslot.
 
1306
 * When we compact a hash database we may change one of the spares slots
 
1307
 * to point at a new block of pages.
 
1308
 *
 
1309
 * PUBLIC: int __ham_changeslot_recover
 
1310
 * PUBLIC:   __P((ENV *, DBT *, DB_LSN *, db_recops, void *));
 
1311
 */
 
1312
int
 
1313
__ham_changeslot_recover(env, dbtp, lsnp, op, info)
 
1314
        ENV *env;
 
1315
        DBT *dbtp;
 
1316
        DB_LSN *lsnp;
 
1317
        db_recops op;
 
1318
        void *info;
 
1319
{
 
1320
        __ham_changeslot_args *argp;
 
1321
        DB *file_dbp;
 
1322
        DBC *dbc;
 
1323
        DB_MPOOLFILE *mpf;
 
1324
        DB_THREAD_INFO *ip;
 
1325
        HASH_CURSOR *hcp;
 
1326
        HMETA *meta;
 
1327
        u_int32_t bucket;
 
1328
        int cmp_n, cmp_p, ret;
 
1329
 
 
1330
        ip = ((DB_TXNHEAD *)info)->thread_info;
 
1331
 
 
1332
        REC_PRINT(__ham_changeslot_print);
 
1333
        REC_INTRO(__ham_changeslot_read, ip, 1);
 
1334
 
 
1335
        hcp = (HASH_CURSOR *)dbc->internal;
 
1336
        if ((ret = __ham_get_meta(dbc)) != 0)
 
1337
                goto out;
 
1338
        meta = hcp->hdr;
 
1339
        cmp_n = log_compare(lsnp, &LSN(meta));
 
1340
        cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
 
1341
 
 
1342
        bucket = argp->slot == 0 ? 0 : 1 << (argp->slot - 1);
 
1343
        if (cmp_p == 0 && DB_REDO(op)) {
 
1344
                REC_DIRTY(mpf, ip, dbc->priority, &hcp->hdr);
 
1345
                meta = hcp->hdr;
 
1346
                meta->spares[argp->slot] = argp->new - bucket;
 
1347
                LSN(meta) = *lsnp;
 
1348
        } else if (cmp_n == 0 && !DB_REDO(op)) {
 
1349
                REC_DIRTY(mpf, ip, dbc->priority, &hcp->hdr);
 
1350
                meta = hcp->hdr;
 
1351
                meta->spares[argp->slot] = argp->old - bucket;
 
1352
                LSN(meta) = argp->meta_lsn;
 
1353
        }
 
1354
        *lsnp = argp->prev_lsn;
 
1355
        ret = __ham_release_meta(dbc);
 
1356
 
 
1357
done:
 
1358
out:    REC_CLOSE;
 
1359
}
 
1360
 
 
1361
/*
1021
1362
 * __ham_curadj_recover --
1022
1363
 *      Undo cursor adjustments if a subtransaction fails.
1023
1364
 *
1092
1433
out:    REC_CLOSE;
1093
1434
}
1094
1435
 
 
1436
static int
 
1437
__ham_chgpg_recover_func(cp, my_dbc, countp, pgno, indx, vargs)
 
1438
        DBC *cp, *my_dbc;
 
1439
        u_int32_t *countp;
 
1440
        db_pgno_t pgno;
 
1441
        u_int32_t indx;
 
1442
        void *vargs;
 
1443
{
 
1444
        BTREE_CURSOR *opdcp;
 
1445
        HASH_CURSOR *lcp;
 
1446
        u_int32_t order;
 
1447
        int ret;
 
1448
        __ham_chgpg_args *argp;
 
1449
 
 
1450
        COMPQUIET(my_dbc, NULL);
 
1451
        COMPQUIET(countp, NULL);
 
1452
        COMPQUIET(pgno, 0);
 
1453
        lcp = (HASH_CURSOR *)cp->internal;
 
1454
        argp = vargs;
 
1455
 
 
1456
        /* Overloaded field for DB_HAM_DEL*PG */
 
1457
        order = argp->new_indx;
 
1458
 
 
1459
        switch (argp->mode) {
 
1460
        case DB_HAM_DELFIRSTPG:
 
1461
                if (lcp->pgno != argp->new_pgno ||
 
1462
                    MVCC_SKIP_CURADJ(cp, lcp->pgno))
 
1463
                        break;
 
1464
                if (lcp->indx != indx ||
 
1465
                    !F_ISSET(lcp, H_DELETED) ||
 
1466
                    lcp->order >= order) {
 
1467
                        lcp->pgno = argp->old_pgno;
 
1468
                        if (lcp->indx == indx)
 
1469
                                lcp->order -= order;
 
1470
                }
 
1471
                break;
 
1472
        case DB_HAM_DELMIDPG:
 
1473
        case DB_HAM_DELLASTPG:
 
1474
                if (lcp->pgno == argp->new_pgno &&
 
1475
                    lcp->indx == indx &&
 
1476
                    F_ISSET(lcp, H_DELETED) &&
 
1477
                    lcp->order >= order &&
 
1478
                    !MVCC_SKIP_CURADJ(cp, lcp->pgno)) {
 
1479
                        lcp->pgno = argp->old_pgno;
 
1480
                        lcp->order -= order;
 
1481
                        lcp->indx = 0;
 
1482
                }
 
1483
                break;
 
1484
        case DB_HAM_CHGPG:
 
1485
                /*
 
1486
                 * If we're doing a CHGPG, we're undoing
 
1487
                 * the move of a non-deleted item to a
 
1488
                 * new page.  Any cursors with the deleted
 
1489
                 * flag set do not belong to this item;
 
1490
                 * don't touch them.
 
1491
                 */
 
1492
                if (F_ISSET(lcp, H_DELETED))
 
1493
                        break;
 
1494
                /* FALLTHROUGH */
 
1495
        case DB_HAM_SPLIT:
 
1496
                if (lcp->pgno == argp->new_pgno &&
 
1497
                    lcp->indx == argp->new_indx &&
 
1498
                    !MVCC_SKIP_CURADJ(cp, lcp->pgno)) {
 
1499
                        lcp->indx = argp->old_indx;
 
1500
                        lcp->pgno = argp->old_pgno;
 
1501
                }
 
1502
                break;
 
1503
        case DB_HAM_DUP:
 
1504
                if (lcp->opd == NULL)
 
1505
                        break;
 
1506
                opdcp = (BTREE_CURSOR *)lcp->opd->internal;
 
1507
                if (opdcp->pgno != argp->new_pgno ||
 
1508
                    opdcp->indx != argp->new_indx ||
 
1509
                    MVCC_SKIP_CURADJ(lcp->opd, opdcp->pgno))
 
1510
                        break;
 
1511
 
 
1512
                if (F_ISSET(opdcp, C_DELETED))
 
1513
                        F_SET(lcp, H_DELETED);
 
1514
                /*
 
1515
                 * We can't close a cursor while we have the
 
1516
                 * dbp mutex locked, since c_close reacquires
 
1517
                 * it.  It should be safe to drop the mutex
 
1518
                 * here, though, since newly opened cursors
 
1519
                 * are put only at the end of the tailq and
 
1520
                 * the cursor we're adjusting can't be closed
 
1521
                 * under us.
 
1522
                 */
 
1523
                MUTEX_UNLOCK(cp->dbp->env, cp->dbp->mutex);
 
1524
                ret = __dbc_close(lcp->opd);
 
1525
                MUTEX_LOCK(cp->dbp->env, cp->dbp->mutex);
 
1526
                if (ret != 0)
 
1527
                        return (ret);
 
1528
                lcp->opd = NULL;
 
1529
                break;
 
1530
        }
 
1531
        return (0);
 
1532
}
1095
1533
/*
1096
1534
 * __ham_chgpg_recover --
1097
1535
 *      Undo cursor adjustments if a subtransaction fails.
1109
1547
{
1110
1548
        __ham_chgpg_args *argp;
1111
1549
        DB_THREAD_INFO *ip;
1112
 
        BTREE_CURSOR *opdcp;
1113
1550
        DB_MPOOLFILE *mpf;
1114
 
        DB *file_dbp, *ldbp;
 
1551
        DB *file_dbp;
1115
1552
        DBC *dbc;
1116
 
        DBC *cp;
1117
 
        HASH_CURSOR *lcp;
1118
 
        u_int32_t order, indx;
1119
1553
        int ret;
 
1554
        u_int32_t count;
1120
1555
 
1121
1556
        ip = ((DB_TXNHEAD *)info)->thread_info;
1122
1557
        REC_PRINT(__ham_chgpg_print);
1125
1560
        if (op != DB_TXN_ABORT)
1126
1561
                goto done;
1127
1562
 
1128
 
        /* Overloaded fields for DB_HAM_DEL*PG */
1129
 
        indx = argp->old_indx;
1130
 
        order = argp->new_indx;
1131
 
 
1132
 
        MUTEX_LOCK(env, env->mtx_dblist);
1133
 
        FIND_FIRST_DB_MATCH(env, file_dbp, ldbp);
1134
 
        for (;
1135
 
            ldbp != NULL && ldbp->adj_fileid == file_dbp->adj_fileid;
1136
 
            ldbp = TAILQ_NEXT(ldbp, dblistlinks)) {
1137
 
                MUTEX_LOCK(env, file_dbp->mutex);
1138
 
                TAILQ_FOREACH(cp, &ldbp->active_queue, links) {
1139
 
                        lcp = (HASH_CURSOR *)cp->internal;
1140
 
 
1141
 
                        switch (argp->mode) {
1142
 
                        case DB_HAM_DELFIRSTPG:
1143
 
                                if (lcp->pgno != argp->new_pgno ||
1144
 
                                    MVCC_SKIP_CURADJ(cp, lcp->pgno))
1145
 
                                        break;
1146
 
                                if (lcp->indx != indx ||
1147
 
                                    !F_ISSET(lcp, H_DELETED) ||
1148
 
                                    lcp->order >= order) {
1149
 
                                        lcp->pgno = argp->old_pgno;
1150
 
                                        if (lcp->indx == indx)
1151
 
                                                lcp->order -= order;
1152
 
                                }
1153
 
                                break;
1154
 
                        case DB_HAM_DELMIDPG:
1155
 
                        case DB_HAM_DELLASTPG:
1156
 
                                if (lcp->pgno == argp->new_pgno &&
1157
 
                                    lcp->indx == indx &&
1158
 
                                    F_ISSET(lcp, H_DELETED) &&
1159
 
                                    lcp->order >= order &&
1160
 
                                    !MVCC_SKIP_CURADJ(cp, lcp->pgno)) {
1161
 
                                        lcp->pgno = argp->old_pgno;
1162
 
                                        lcp->order -= order;
1163
 
                                        lcp->indx = 0;
1164
 
                                }
1165
 
                                break;
1166
 
                        case DB_HAM_CHGPG:
1167
 
                                /*
1168
 
                                 * If we're doing a CHGPG, we're undoing
1169
 
                                 * the move of a non-deleted item to a
1170
 
                                 * new page.  Any cursors with the deleted
1171
 
                                 * flag set do not belong to this item;
1172
 
                                 * don't touch them.
1173
 
                                 */
1174
 
                                if (F_ISSET(lcp, H_DELETED))
1175
 
                                        break;
1176
 
                                /* FALLTHROUGH */
1177
 
                        case DB_HAM_SPLIT:
1178
 
                                if (lcp->pgno == argp->new_pgno &&
1179
 
                                    lcp->indx == argp->new_indx &&
1180
 
                                    !MVCC_SKIP_CURADJ(cp, lcp->pgno)) {
1181
 
                                        lcp->indx = argp->old_indx;
1182
 
                                        lcp->pgno = argp->old_pgno;
1183
 
                                }
1184
 
                                break;
1185
 
                        case DB_HAM_DUP:
1186
 
                                if (lcp->opd == NULL)
1187
 
                                        break;
1188
 
                                opdcp = (BTREE_CURSOR *)lcp->opd->internal;
1189
 
                                if (opdcp->pgno != argp->new_pgno ||
1190
 
                                    opdcp->indx != argp->new_indx ||
1191
 
                                    MVCC_SKIP_CURADJ(lcp->opd, opdcp->pgno))
1192
 
                                        break;
1193
 
 
1194
 
                                if (F_ISSET(opdcp, C_DELETED))
1195
 
                                        F_SET(lcp, H_DELETED);
1196
 
                                /*
1197
 
                                 * We can't close a cursor while we have the
1198
 
                                 * dbp mutex locked, since c_close reacquires
1199
 
                                 * it.  It should be safe to drop the mutex
1200
 
                                 * here, though, since newly opened cursors
1201
 
                                 * are put only at the end of the tailq and
1202
 
                                 * the cursor we're adjusting can't be closed
1203
 
                                 * under us.
1204
 
                                 */
1205
 
                                MUTEX_UNLOCK(env, file_dbp->mutex);
1206
 
                                if ((ret = __dbc_close(lcp->opd)) != 0)
1207
 
                                        goto out;
1208
 
                                MUTEX_LOCK(env, file_dbp->mutex);
1209
 
                                lcp->opd = NULL;
1210
 
                                break;
1211
 
                        }
1212
 
                }
1213
 
                MUTEX_UNLOCK(env, file_dbp->mutex);
1214
 
        }
1215
 
        MUTEX_UNLOCK(env, env->mtx_dblist);
 
1563
        ret = __db_walk_cursors(file_dbp, dbc,
 
1564
            __ham_chgpg_recover_func, &count, 0, argp->old_indx, argp);
1216
1565
 
1217
1566
done:   *lsnp = argp->prev_lsn;
1218
1567
out:    REC_CLOSE;