00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <string.h>
00016 #endif
00017
00018 #include "db_int.h"
00019 #include "dbinc/db_page.h"
00020 #include "dbinc/db_shash.h"
00021 #include "dbinc/btree.h"
00022 #include "dbinc/hash.h"
00023 #include "dbinc/lock.h"
00024 #include "dbinc/mp.h"
00025 #include "dbinc/qam.h"
00026
00027 static int __db_buildpartial __P((DB *, DBT *, DBT *, DBT *));
00028 static int __db_c_cleanup __P((DBC *, DBC *, int));
00029 static int __db_c_del_secondary __P((DBC *));
00030 static int __db_c_pget_recno __P((DBC *, DBT *, DBT *, u_int32_t));
00031 static int __db_wrlock_err __P((DB_ENV *));
00032
00033 #define CDB_LOCKING_INIT(dbp, dbc) \
00034
00035
00036
00037
00038
00039 \
00040 if (CDB_LOCKING((dbp)->dbenv)) { \
00041 if (!F_ISSET(dbc, DBC_WRITECURSOR | DBC_WRITER)) \
00042 return (__db_wrlock_err(dbp->dbenv)); \
00043 \
00044 if (F_ISSET(dbc, DBC_WRITECURSOR) && \
00045 (ret = __lock_get((dbp)->dbenv, \
00046 (dbc)->locker, DB_LOCK_UPGRADE, &(dbc)->lock_dbt, \
00047 DB_LOCK_WRITE, &(dbc)->mylock)) != 0) \
00048 return (ret); \
00049 }
00050 #define CDB_LOCKING_DONE(dbp, dbc) \
00051 \
00052 if (F_ISSET(dbc, DBC_WRITECURSOR)) \
00053 (void)__lock_downgrade( \
00054 (dbp)->dbenv, &(dbc)->mylock, DB_LOCK_IWRITE, 0);
00055
00056
00057
00058
00059
00060
00061
00062 int
00063 __db_c_close(dbc)
00064 DBC *dbc;
00065 {
00066 DB *dbp;
00067 DBC *opd;
00068 DBC_INTERNAL *cp;
00069 DB_ENV *dbenv;
00070 int ret, t_ret;
00071
00072 dbp = dbc->dbp;
00073 dbenv = dbp->dbenv;
00074 cp = dbc->internal;
00075 opd = cp->opd;
00076 ret = 0;
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 MUTEX_LOCK(dbenv, dbp->mutex);
00090
00091 if (opd != NULL) {
00092 DB_ASSERT(F_ISSET(opd, DBC_ACTIVE));
00093 F_CLR(opd, DBC_ACTIVE);
00094 TAILQ_REMOVE(&dbp->active_queue, opd, links);
00095 }
00096 DB_ASSERT(F_ISSET(dbc, DBC_ACTIVE));
00097 F_CLR(dbc, DBC_ACTIVE);
00098 TAILQ_REMOVE(&dbp->active_queue, dbc, links);
00099
00100 MUTEX_UNLOCK(dbenv, dbp->mutex);
00101
00102
00103 if ((t_ret =
00104 dbc->c_am_close(dbc, PGNO_INVALID, NULL)) != 0 && ret == 0)
00105 ret = t_ret;
00106
00107
00108
00109
00110
00111 if (CDB_LOCKING(dbenv)) {
00112
00113
00114
00115
00116
00117
00118 if ((t_ret = __LPUT(dbc, dbc->mylock)) != 0 && ret == 0)
00119 ret = t_ret;
00120
00121
00122 memset(&dbc->mylock, 0, sizeof(dbc->mylock));
00123 if (opd != NULL)
00124 memset(&opd->mylock, 0, sizeof(opd->mylock));
00125 }
00126
00127 if (dbc->txn != NULL)
00128 dbc->txn->cursors--;
00129
00130
00131 MUTEX_LOCK(dbenv, dbp->mutex);
00132 if (opd != NULL) {
00133 if (dbc->txn != NULL)
00134 dbc->txn->cursors--;
00135 TAILQ_INSERT_TAIL(&dbp->free_queue, opd, links);
00136 opd = NULL;
00137 }
00138 TAILQ_INSERT_TAIL(&dbp->free_queue, dbc, links);
00139 MUTEX_UNLOCK(dbenv, dbp->mutex);
00140
00141 return (ret);
00142 }
00143
00144
00145
00146
00147
00148
00149
00150 int
00151 __db_c_destroy(dbc)
00152 DBC *dbc;
00153 {
00154 DB *dbp;
00155 DB_ENV *dbenv;
00156 int ret, t_ret;
00157
00158 dbp = dbc->dbp;
00159 dbenv = dbp->dbenv;
00160
00161
00162 MUTEX_LOCK(dbenv, dbp->mutex);
00163 TAILQ_REMOVE(&dbp->free_queue, dbc, links);
00164 MUTEX_UNLOCK(dbenv, dbp->mutex);
00165
00166
00167 if (dbc->my_rskey.data != NULL)
00168 __os_free(dbenv, dbc->my_rskey.data);
00169 if (dbc->my_rkey.data != NULL)
00170 __os_free(dbenv, dbc->my_rkey.data);
00171 if (dbc->my_rdata.data != NULL)
00172 __os_free(dbenv, dbc->my_rdata.data);
00173
00174
00175 ret = dbc->c_am_destroy == NULL ? 0 : dbc->c_am_destroy(dbc);
00176
00177
00178
00179
00180 if (LOCKING_ON(dbenv) &&
00181 F_ISSET(dbc, DBC_OWN_LID) &&
00182 (t_ret = __lock_id_free(dbenv,
00183 ((DB_LOCKER *)dbc->lref)->id)) != 0 && ret == 0)
00184 ret = t_ret;
00185
00186 __os_free(dbenv, dbc);
00187
00188 return (ret);
00189 }
00190
00191
00192
00193
00194
00195
00196
00197 int
00198 __db_c_count(dbc, recnop)
00199 DBC *dbc;
00200 db_recno_t *recnop;
00201 {
00202 DB_ENV *dbenv;
00203 int ret;
00204
00205 dbenv = dbc->dbp->dbenv;
00206
00207
00208
00209
00210
00211
00212
00213
00214 switch (dbc->dbtype) {
00215 case DB_QUEUE:
00216 case DB_RECNO:
00217 *recnop = 1;
00218 break;
00219 case DB_HASH:
00220 if (dbc->internal->opd == NULL) {
00221 if ((ret = __ham_c_count(dbc, recnop)) != 0)
00222 return (ret);
00223 break;
00224 }
00225
00226 case DB_BTREE:
00227 if ((ret = __bam_c_count(dbc, recnop)) != 0)
00228 return (ret);
00229 break;
00230 case DB_UNKNOWN:
00231 default:
00232 return (__db_unknown_type(dbenv, "__db_c_count", dbc->dbtype));
00233 }
00234 return (0);
00235 }
00236
00237
00238
00239
00240
00241
00242
00243 int
00244 __db_c_del(dbc, flags)
00245 DBC *dbc;
00246 u_int32_t flags;
00247 {
00248 DB *dbp;
00249 DBC *opd;
00250 int ret, t_ret;
00251
00252 dbp = dbc->dbp;
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 CDB_LOCKING_INIT(dbp, dbc);
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 if (flags != DB_UPDATE_SECONDARY && F_ISSET(dbp, DB_AM_SECONDARY)) {
00273 ret = __db_c_del_secondary(dbc);
00274 goto done;
00275 }
00276
00277
00278
00279
00280
00281 if (LIST_FIRST(&dbp->s_secondaries) != NULL &&
00282 (ret = __db_c_del_primary(dbc)) != 0)
00283 goto done;
00284
00285
00286
00287
00288
00289
00290
00291 opd = dbc->internal->opd;
00292 if (opd == NULL)
00293 ret = dbc->c_am_del(dbc);
00294 else
00295 if ((ret = dbc->c_am_writelock(dbc)) == 0)
00296 ret = opd->c_am_del(opd);
00297
00298
00299
00300
00301
00302
00303
00304
00305 if (F_ISSET(dbc->dbp, DB_AM_READ_UNCOMMITTED) &&
00306 dbc->internal->lock_mode == DB_LOCK_WRITE) {
00307 if ((t_ret =
00308 __TLPUT(dbc, dbc->internal->lock)) != 0 && ret == 0)
00309 ret = t_ret;
00310 if (t_ret == 0)
00311 dbc->internal->lock_mode = DB_LOCK_WWRITE;
00312 }
00313
00314 done: CDB_LOCKING_DONE(dbp, dbc);
00315
00316 return (ret);
00317 }
00318
00319
00320
00321
00322
00323
00324
00325 int
00326 __db_c_dup(dbc_orig, dbcp, flags)
00327 DBC *dbc_orig;
00328 DBC **dbcp;
00329 u_int32_t flags;
00330 {
00331 DBC *dbc_n, *dbc_nopd;
00332 int ret;
00333
00334 dbc_n = dbc_nopd = NULL;
00335
00336
00337 if ((ret = __db_c_idup(dbc_orig, &dbc_n, flags)) != 0)
00338 goto err;
00339 *dbcp = dbc_n;
00340
00341
00342
00343
00344
00345 if (dbc_orig->internal->opd != NULL) {
00346 if ((ret =
00347 __db_c_idup(dbc_orig->internal->opd, &dbc_nopd, flags)) != 0)
00348 goto err;
00349 dbc_n->internal->opd = dbc_nopd;
00350 }
00351 return (0);
00352
00353 err: if (dbc_n != NULL)
00354 (void)__db_c_close(dbc_n);
00355 if (dbc_nopd != NULL)
00356 (void)__db_c_close(dbc_nopd);
00357
00358 return (ret);
00359 }
00360
00361
00362
00363
00364
00365
00366
00367 int
00368 __db_c_idup(dbc_orig, dbcp, flags)
00369 DBC *dbc_orig, **dbcp;
00370 u_int32_t flags;
00371 {
00372 DB *dbp;
00373 DBC *dbc_n;
00374 DBC_INTERNAL *int_n, *int_orig;
00375 int ret;
00376
00377 dbp = dbc_orig->dbp;
00378 dbc_n = *dbcp;
00379
00380 if ((ret = __db_cursor_int(dbp, dbc_orig->txn, dbc_orig->dbtype,
00381 dbc_orig->internal->root, F_ISSET(dbc_orig, DBC_OPD),
00382 dbc_orig->locker, &dbc_n)) != 0)
00383 return (ret);
00384
00385
00386 if (flags == DB_POSITION) {
00387 int_n = dbc_n->internal;
00388 int_orig = dbc_orig->internal;
00389
00390 dbc_n->flags |= dbc_orig->flags & ~DBC_OWN_LID;
00391
00392 int_n->indx = int_orig->indx;
00393 int_n->pgno = int_orig->pgno;
00394 int_n->root = int_orig->root;
00395 int_n->lock_mode = int_orig->lock_mode;
00396
00397 switch (dbc_orig->dbtype) {
00398 case DB_QUEUE:
00399 if ((ret = __qam_c_dup(dbc_orig, dbc_n)) != 0)
00400 goto err;
00401 break;
00402 case DB_BTREE:
00403 case DB_RECNO:
00404 if ((ret = __bam_c_dup(dbc_orig, dbc_n)) != 0)
00405 goto err;
00406 break;
00407 case DB_HASH:
00408 if ((ret = __ham_c_dup(dbc_orig, dbc_n)) != 0)
00409 goto err;
00410 break;
00411 case DB_UNKNOWN:
00412 default:
00413 ret = __db_unknown_type(dbp->dbenv,
00414 "__db_c_idup", dbc_orig->dbtype);
00415 goto err;
00416 }
00417 }
00418
00419
00420 F_SET(dbc_n, F_ISSET(dbc_orig,
00421 DBC_READ_COMMITTED | DBC_READ_UNCOMMITTED | DBC_WRITECURSOR));
00422
00423
00424
00425
00426
00427 if (CDB_LOCKING(dbp->dbenv) && !F_ISSET(dbc_n, DBC_OPD) &&
00428 (ret = __lock_get(dbp->dbenv, dbc_n->locker, 0,
00429 &dbc_n->lock_dbt, F_ISSET(dbc_orig, DBC_WRITECURSOR) ?
00430 DB_LOCK_IWRITE : DB_LOCK_READ, &dbc_n->mylock)) != 0)
00431 goto err;
00432
00433 *dbcp = dbc_n;
00434 return (0);
00435
00436 err: (void)__db_c_close(dbc_n);
00437 return (ret);
00438 }
00439
00440
00441
00442
00443
00444
00445
00446 int
00447 __db_c_newopd(dbc_parent, root, oldopd, dbcp)
00448 DBC *dbc_parent;
00449 db_pgno_t root;
00450 DBC *oldopd;
00451 DBC **dbcp;
00452 {
00453 DB *dbp;
00454 DBC *opd;
00455 DBTYPE dbtype;
00456 int ret;
00457
00458 dbp = dbc_parent->dbp;
00459 dbtype = (dbp->dup_compare == NULL) ? DB_RECNO : DB_BTREE;
00460
00461
00462
00463
00464
00465
00466
00467
00468 *dbcp = oldopd;
00469
00470 if ((ret = __db_cursor_int(dbp,
00471 dbc_parent->txn, dbtype, root, 1, dbc_parent->locker, &opd)) != 0)
00472 return (ret);
00473
00474 *dbcp = opd;
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 if (oldopd != NULL && (ret = __db_c_close(oldopd)) != 0)
00489 return (ret);
00490
00491 return (0);
00492 }
00493
00494
00495
00496
00497
00498
00499
00500 int
00501 __db_c_get(dbc_arg, key, data, flags)
00502 DBC *dbc_arg;
00503 DBT *key, *data;
00504 u_int32_t flags;
00505 {
00506 DB *dbp;
00507 DBC *dbc, *dbc_n, *opd;
00508 DBC_INTERNAL *cp, *cp_n;
00509 DB_MPOOLFILE *mpf;
00510 db_pgno_t pgno;
00511 u_int32_t multi, orig_ulen, tmp_flags, tmp_read_uncommitted, tmp_rmw;
00512 u_int8_t type;
00513 int key_small, ret, t_ret;
00514
00515 COMPQUIET(orig_ulen, 0);
00516
00517 key_small = 0;
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 dbp = dbc_arg->dbp;
00529 mpf = dbp->mpf;
00530 dbc_n = NULL;
00531 opd = NULL;
00532
00533
00534 tmp_rmw = LF_ISSET(DB_RMW);
00535 LF_CLR(DB_RMW);
00536
00537 tmp_read_uncommitted =
00538 LF_ISSET(DB_READ_UNCOMMITTED) &&
00539 !F_ISSET(dbc_arg, DBC_READ_UNCOMMITTED);
00540 LF_CLR(DB_READ_UNCOMMITTED);
00541
00542 multi = LF_ISSET(DB_MULTIPLE|DB_MULTIPLE_KEY);
00543 LF_CLR(DB_MULTIPLE|DB_MULTIPLE_KEY);
00544
00545
00546
00547
00548
00549 if (flags == DB_GET_RECNO) {
00550 if (tmp_rmw)
00551 F_SET(dbc_arg, DBC_RMW);
00552 if (tmp_read_uncommitted)
00553 F_SET(dbc_arg, DBC_READ_UNCOMMITTED);
00554 ret = __bam_c_rget(dbc_arg, data);
00555 if (tmp_rmw)
00556 F_CLR(dbc_arg, DBC_RMW);
00557 if (tmp_read_uncommitted)
00558 F_CLR(dbc_arg, DBC_READ_UNCOMMITTED);
00559 return (ret);
00560 }
00561
00562 if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
00563 CDB_LOCKING_INIT(dbp, dbc_arg);
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 cp = dbc_arg->internal;
00577 if (cp->opd != NULL &&
00578 (flags == DB_CURRENT || flags == DB_GET_BOTHC ||
00579 flags == DB_NEXT || flags == DB_NEXT_DUP || flags == DB_PREV)) {
00580 if (tmp_rmw && (ret = dbc_arg->c_am_writelock(dbc_arg)) != 0)
00581 return (ret);
00582 if ((ret = __db_c_idup(cp->opd, &opd, DB_POSITION)) != 0)
00583 return (ret);
00584
00585 switch (ret =
00586 opd->c_am_get(opd, key, data, flags, NULL)) {
00587 case 0:
00588 goto done;
00589 case DB_NOTFOUND:
00590
00591
00592
00593
00594
00595 if (flags == DB_NEXT || flags == DB_PREV) {
00596 if ((ret = __db_c_close(opd)) != 0)
00597 goto err;
00598 opd = NULL;
00599 break;
00600 }
00601 goto err;
00602 default:
00603 goto err;
00604 }
00605 }
00606
00607
00608
00609
00610
00611 switch (flags) {
00612 case DB_CURRENT:
00613 case DB_GET_BOTHC:
00614 case DB_NEXT:
00615 case DB_NEXT_DUP:
00616 case DB_NEXT_NODUP:
00617 case DB_PREV:
00618 case DB_PREV_NODUP:
00619 tmp_flags = DB_POSITION;
00620 break;
00621 default:
00622 tmp_flags = 0;
00623 break;
00624 }
00625
00626 if (tmp_read_uncommitted)
00627 F_SET(dbc_arg, DBC_READ_UNCOMMITTED);
00628
00629
00630
00631
00632
00633 if (F_ISSET(dbc_arg, DBC_TRANSIENT))
00634 dbc_n = dbc_arg;
00635 else {
00636 ret = __db_c_idup(dbc_arg, &dbc_n, tmp_flags);
00637 if (tmp_read_uncommitted)
00638 F_CLR(dbc_arg, DBC_READ_UNCOMMITTED);
00639
00640 if (ret != 0)
00641 goto err;
00642 COPY_RET_MEM(dbc_arg, dbc_n);
00643 }
00644
00645 if (tmp_rmw)
00646 F_SET(dbc_n, DBC_RMW);
00647
00648 switch (multi) {
00649 case DB_MULTIPLE:
00650 F_SET(dbc_n, DBC_MULTIPLE);
00651 break;
00652 case DB_MULTIPLE_KEY:
00653 F_SET(dbc_n, DBC_MULTIPLE_KEY);
00654 break;
00655 case DB_MULTIPLE | DB_MULTIPLE_KEY:
00656 F_SET(dbc_n, DBC_MULTIPLE|DBC_MULTIPLE_KEY);
00657 break;
00658 case 0:
00659 default:
00660 break;
00661 }
00662
00663 pgno = PGNO_INVALID;
00664 ret = dbc_n->c_am_get(dbc_n, key, data, flags, &pgno);
00665 if (tmp_rmw)
00666 F_CLR(dbc_n, DBC_RMW);
00667 if (tmp_read_uncommitted)
00668 F_CLR(dbc_arg, DBC_READ_UNCOMMITTED);
00669 F_CLR(dbc_n, DBC_MULTIPLE|DBC_MULTIPLE_KEY);
00670 if (ret != 0)
00671 goto err;
00672
00673 cp_n = dbc_n->internal;
00674
00675
00676
00677
00678
00679 if (pgno != PGNO_INVALID) {
00680 if ((ret = __db_c_newopd(dbc_arg,
00681 pgno, cp_n->opd, &cp_n->opd)) != 0)
00682 goto err;
00683
00684 switch (flags) {
00685 case DB_FIRST:
00686 case DB_NEXT:
00687 case DB_NEXT_NODUP:
00688 case DB_SET:
00689 case DB_SET_RECNO:
00690 case DB_SET_RANGE:
00691 tmp_flags = DB_FIRST;
00692 break;
00693 case DB_LAST:
00694 case DB_PREV:
00695 case DB_PREV_NODUP:
00696 tmp_flags = DB_LAST;
00697 break;
00698 case DB_GET_BOTH:
00699 case DB_GET_BOTHC:
00700 case DB_GET_BOTH_RANGE:
00701 tmp_flags = flags;
00702 break;
00703 default:
00704 ret =
00705 __db_unknown_flag(dbp->dbenv, "__db_c_get", flags);
00706 goto err;
00707 }
00708 if ((ret = cp_n->opd->c_am_get(
00709 cp_n->opd, key, data, tmp_flags, NULL)) != 0)
00710 goto err;
00711 }
00712
00713 done:
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727 cp_n = dbc_n == NULL ? dbc_arg->internal : dbc_n->internal;
00728 if (!F_ISSET(key, DB_DBT_ISSET)) {
00729 if (cp_n->page == NULL && (ret =
00730 __memp_fget(mpf, &cp_n->pgno, 0, &cp_n->page)) != 0)
00731 goto err;
00732
00733 if ((ret = __db_ret(dbp, cp_n->page, cp_n->indx,
00734 key, &dbc_arg->rkey->data, &dbc_arg->rkey->ulen)) != 0) {
00735
00736
00737
00738
00739
00740
00741
00742 if (ret == DB_BUFFER_SMALL &&
00743 F_ISSET(data, DB_DBT_USERMEM)) {
00744 key_small = 1;
00745 orig_ulen = data->ulen;
00746 data->ulen = 0;
00747 } else
00748 goto err;
00749 }
00750 }
00751 if (multi != 0) {
00752
00753
00754
00755
00756 if (dbc_n == NULL) {
00757
00758
00759
00760
00761
00762
00763 if ((!(multi & DB_MULTIPLE_KEY) &&
00764 dbc_arg->internal->opd == NULL) ||
00765 F_ISSET(dbc_arg, DBC_TRANSIENT))
00766 dbc_n = dbc_arg;
00767 else {
00768 if ((ret = __db_c_idup(dbc_arg,
00769 &dbc_n, DB_POSITION)) != 0)
00770 goto err;
00771 if ((ret = dbc_n->c_am_get(dbc_n,
00772 key, data, DB_CURRENT, &pgno)) != 0)
00773 goto err;
00774 }
00775 cp_n = dbc_n->internal;
00776 }
00777
00778
00779
00780
00781
00782
00783 if (opd != NULL) {
00784 DB_ASSERT(cp_n->opd == NULL);
00785 cp_n->opd = opd;
00786 opd = NULL;
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 data->size = data->ulen;
00798 ret = dbc_n->c_am_bulk(dbc_n, data, flags | multi);
00799 } else if (!F_ISSET(data, DB_DBT_ISSET)) {
00800 dbc = opd != NULL ? opd : cp_n->opd != NULL ? cp_n->opd : dbc_n;
00801 type = TYPE(dbc->internal->page);
00802 ret = __db_ret(dbp, dbc->internal->page, dbc->internal->indx +
00803 (type == P_LBTREE || type == P_HASH ? O_INDX : 0),
00804 data, &dbc_arg->rdata->data, &dbc_arg->rdata->ulen);
00805 }
00806
00807 err:
00808 F_CLR(key, DB_DBT_ISSET);
00809 F_CLR(data, DB_DBT_ISSET);
00810
00811
00812 if (opd != NULL) {
00813
00814
00815
00816
00817
00818
00819
00820 if (F_ISSET(dbc_arg->dbp, DB_AM_READ_UNCOMMITTED) &&
00821 F_ISSET((BTREE_CURSOR *)
00822 dbc_arg->internal->opd->internal, C_DELETED))
00823 if ((t_ret =
00824 dbc_arg->c_am_writelock(dbc_arg)) != 0 && ret == 0)
00825 ret = t_ret;
00826 if ((t_ret = __db_c_cleanup(
00827 dbc_arg->internal->opd, opd, ret)) != 0 && ret == 0)
00828 ret = t_ret;
00829
00830 }
00831
00832 if ((t_ret = __db_c_cleanup(dbc_arg, dbc_n, ret)) != 0 && ret == 0)
00833 ret = t_ret;
00834
00835 if (key_small) {
00836 data->ulen = orig_ulen;
00837 if (ret == 0)
00838 ret = DB_BUFFER_SMALL;
00839 }
00840
00841 if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
00842 CDB_LOCKING_DONE(dbp, dbc_arg);
00843 return (ret);
00844 }
00845
00846
00847
00848
00849
00850
00851
00852 int
00853 __db_c_put(dbc_arg, key, data, flags)
00854 DBC *dbc_arg;
00855 DBT *key, *data;
00856 u_int32_t flags;
00857 {
00858 DB_ENV *dbenv;
00859 DB *dbp, *sdbp;
00860 DBC *dbc_n, *oldopd, *opd, *sdbc, *pdbc;
00861 DBT olddata, oldpkey, oldskey, newdata, pkey, skey, temppkey, tempskey;
00862 db_pgno_t pgno;
00863 int cmp, have_oldrec, ispartial, nodel, re_pad, ret, rmw, t_ret;
00864 u_int32_t re_len, size, tmp_flags;
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 dbp = dbc_arg->dbp;
00876 dbenv = dbp->dbenv;
00877 sdbp = NULL;
00878 pdbc = dbc_n = NULL;
00879 memset(&newdata, 0, sizeof(DBT));
00880 ret = 0;
00881
00882
00883
00884
00885
00886
00887 memset(&olddata, 0, sizeof(DBT));
00888 F_SET(&olddata, DB_DBT_MALLOC);
00889
00890
00891
00892
00893
00894
00895
00896 if (flags == DB_UPDATE_SECONDARY)
00897 flags = DB_KEYLAST;
00898
00899 CDB_LOCKING_INIT(dbp, dbc_arg);
00900
00901
00902
00903
00904
00905
00906 if (LIST_FIRST(&dbp->s_secondaries) == NULL)
00907 goto skip_s_update;
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 memset(&pkey, 0, sizeof(DBT));
00967 have_oldrec = nodel = 0;
00968
00969
00970
00971
00972
00973
00974
00975 DB_ASSERT(flags == DB_CURRENT ||
00976 flags == DB_KEYFIRST || flags == DB_KEYLAST);
00977
00978
00979
00980
00981
00982 rmw = STD_LOCKING(dbc_arg) ? DB_RMW : 0;
00983
00984 if (flags == DB_CURRENT) {
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997 ret = __db_c_get(dbc_arg, &pkey, &olddata, rmw | DB_CURRENT);
00998 if (ret == DB_KEYEMPTY)
00999 ret = DB_NOTFOUND;
01000 if (ret != 0)
01001 goto err;
01002
01003 have_oldrec = 1;
01004 } else {
01005
01006
01007
01008
01009
01010 pkey.data = key->data;
01011 pkey.size = key->size;
01012 }
01013
01014
01015
01016
01017 if (F_ISSET(data, DB_DBT_PARTIAL)) {
01018 if (!have_oldrec && !nodel) {
01019
01020
01021
01022
01023
01024 if ((ret = __db_c_idup(dbc_arg, &pdbc, 0)) != 0)
01025 goto err;
01026
01027
01028 DB_ASSERT(flags != DB_CURRENT);
01029
01030 ret = __db_c_get(pdbc, &pkey, &olddata, rmw | DB_SET);
01031 if (ret == DB_KEYEMPTY || ret == DB_NOTFOUND) {
01032 nodel = 1;
01033 ret = 0;
01034 }
01035 if ((t_ret = __db_c_close(pdbc)) != 0)
01036 ret = t_ret;
01037 if (ret != 0)
01038 goto err;
01039
01040 have_oldrec = 1;
01041 }
01042
01043
01044
01045
01046
01047
01048
01049 if ((ret =
01050 __db_buildpartial(dbp, &olddata, data, &newdata)) != 0)
01051 goto err;
01052 ispartial = 1;
01053 } else
01054 ispartial = 0;
01055
01056
01057
01058
01059
01060
01061
01062 if ((dbp->type == DB_RECNO && F_ISSET(dbp, DB_AM_FIXEDLEN)) ||
01063 (dbp->type == DB_QUEUE)) {
01064 if (dbp->type == DB_QUEUE) {
01065 re_len = ((QUEUE *)dbp->q_internal)->re_len;
01066 re_pad = ((QUEUE *)dbp->q_internal)->re_pad;
01067 } else {
01068 re_len = ((BTREE *)dbp->bt_internal)->re_len;
01069 re_pad = ((BTREE *)dbp->bt_internal)->re_pad;
01070 }
01071
01072 size = ispartial ? newdata.size : data->size;
01073 if (size > re_len) {
01074 ret = __db_rec_toobig(dbenv, size, re_len);
01075 goto err;
01076 } else if (size < re_len) {
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088 if ((ret =
01089 __os_realloc(dbenv, re_len, &newdata.data)) != 0)
01090 goto err;
01091 if (!ispartial)
01092 memcpy(newdata.data, data->data, size);
01093 memset((u_int8_t *)newdata.data + size, re_pad,
01094 re_len - size);
01095 newdata.size = re_len;
01096 ispartial = 1;
01097 }
01098 }
01099
01100
01101
01102
01103
01104
01105
01106 if ((ret = __db_s_first(dbp, &sdbp)) != 0)
01107 goto err;
01108 for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
01109
01110
01111
01112
01113
01114 if (have_oldrec && !nodel &&
01115 FLD_ISSET(sdbp->s_assoc_flags, DB_ASSOC_IMMUTABLE_KEY))
01116 continue;
01117
01118
01119
01120
01121
01122 memset(&skey, 0, sizeof(DBT));
01123 if ((ret = sdbp->s_callback(sdbp,
01124 &pkey, ispartial ? &newdata : data, &skey)) != 0) {
01125 if (ret == DB_DONOTINDEX)
01126
01127
01128
01129
01130
01131
01132 continue;
01133 goto err;
01134 }
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144 if ((ret = __db_cursor_int(sdbp, dbc_arg->txn, sdbp->type,
01145 PGNO_INVALID, 0, dbc_arg->locker, &sdbc)) != 0)
01146 goto err;
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157 if (CDB_LOCKING(dbenv)) {
01158 DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
01159 F_SET(sdbc, DBC_WRITER);
01160 }
01161
01162
01163
01164
01165
01166
01167
01168 SWAP_IF_NEEDED(dbp, sdbp, &pkey);
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199 if (!F_ISSET(sdbp, DB_AM_DUP)) {
01200
01201 memset(&oldpkey, 0, sizeof(DBT));
01202 F_SET(&oldpkey, DB_DBT_MALLOC);
01203 ret = __db_c_get(sdbc,
01204 &skey, &oldpkey, rmw | DB_SET);
01205 if (ret == 0) {
01206 cmp = __bam_defcmp(sdbp, &oldpkey, &pkey);
01207 __os_ufree(dbenv, oldpkey.data);
01208 if (cmp != 0) {
01209 __db_err(dbenv, "%s%s",
01210 "Put results in a non-unique secondary key in an ",
01211 "index not configured to support duplicates");
01212 ret = EINVAL;
01213 }
01214 }
01215 if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)
01216 goto skipput;
01217 } else if (!F_ISSET(sdbp, DB_AM_DUPSORT)) {
01218
01219 memset(&tempskey, 0, sizeof(DBT));
01220 tempskey.data = skey.data;
01221 tempskey.size = skey.size;
01222 memset(&temppkey, 0, sizeof(DBT));
01223 temppkey.data = pkey.data;
01224 temppkey.size = pkey.size;
01225 ret = __db_c_get(sdbc, &tempskey, &temppkey,
01226 rmw | DB_GET_BOTH);
01227 if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)
01228 goto skipput;
01229 }
01230
01231 ret = __db_c_put(sdbc, &skey, &pkey, DB_UPDATE_SECONDARY);
01232
01233
01234
01235
01236
01237
01238 if (ret == DB_KEYEXIST)
01239 ret = 0;
01240
01241 skipput: FREE_IF_NEEDED(sdbp, &skey)
01242
01243
01244 SWAP_IF_NEEDED(dbp, sdbp, &pkey);
01245
01246 if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
01247 ret = t_ret;
01248
01249 if (ret != 0)
01250 goto err;
01251 }
01252 if (ret != 0)
01253 goto err;
01254
01255
01256 if (!have_oldrec) {
01257
01258 if ((ret = __db_c_idup(dbc_arg, &pdbc, 0)) != 0)
01259 goto err;
01260 DB_ASSERT(flags != DB_CURRENT);
01261 pkey.data = key->data;
01262 pkey.size = key->size;
01263 ret = __db_c_get(pdbc, &pkey, &olddata, rmw | DB_SET);
01264 if (ret == DB_KEYEMPTY || ret == DB_NOTFOUND) {
01265 nodel = 1;
01266 ret = 0;
01267 }
01268 if ((t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
01269 ret = t_ret;
01270 if (ret != 0)
01271 goto err;
01272 have_oldrec = 1;
01273 }
01274
01275
01276
01277
01278
01279 if (nodel)
01280 goto skip_s_update;
01281
01282 if ((ret = __db_s_first(dbp, &sdbp)) != 0)
01283 goto err;
01284 for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
01285
01286
01287
01288
01289
01290 if (FLD_ISSET(sdbp->s_assoc_flags, DB_ASSOC_IMMUTABLE_KEY))
01291 continue;
01292
01293
01294
01295
01296
01297 memset(&oldskey, 0, sizeof(DBT));
01298 if ((ret = sdbp->s_callback(sdbp,
01299 &pkey, &olddata, &oldskey)) != 0) {
01300 if (ret == DB_DONOTINDEX)
01301
01302
01303
01304
01305
01306 continue;
01307 goto err;
01308 }
01309 memset(&skey, 0, sizeof(DBT));
01310 if ((ret = sdbp->s_callback(sdbp,
01311 &pkey, ispartial ? &newdata : data, &skey)) != 0 &&
01312 ret != DB_DONOTINDEX)
01313 goto err;
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323 sdbc = NULL;
01324 if (ret == DB_DONOTINDEX ||
01325 ((BTREE *)sdbp->bt_internal)->bt_compare(sdbp,
01326 &oldskey, &skey) != 0) {
01327 if ((ret = __db_cursor_int(
01328 sdbp, dbc_arg->txn, sdbp->type,
01329 PGNO_INVALID, 0, dbc_arg->locker, &sdbc)) != 0)
01330 goto err;
01331 if (CDB_LOCKING(dbenv)) {
01332 DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
01333 F_SET(sdbc, DBC_WRITER);
01334 }
01335
01336
01337
01338
01339
01340 memset(&tempskey, 0, sizeof(DBT));
01341 tempskey.data = oldskey.data;
01342 tempskey.size = oldskey.size;
01343 SWAP_IF_NEEDED(dbp, sdbp, &pkey);
01344 memset(&temppkey, 0, sizeof(DBT));
01345 temppkey.data = pkey.data;
01346 temppkey.size = pkey.size;
01347 if ((ret = __db_c_get(sdbc,
01348 &tempskey, &temppkey, rmw | DB_GET_BOTH)) == 0)
01349 ret = __db_c_del(sdbc, DB_UPDATE_SECONDARY);
01350 else if (ret == DB_NOTFOUND)
01351 ret = __db_secondary_corrupt(dbp);
01352 SWAP_IF_NEEDED(dbp, sdbp, &pkey);
01353 }
01354
01355 FREE_IF_NEEDED(sdbp, &skey);
01356 FREE_IF_NEEDED(sdbp, &oldskey);
01357 if (sdbc != NULL && (t_ret = __db_c_close(sdbc)) != 0 &&
01358 ret == 0)
01359 ret = t_ret;
01360 if (ret != 0)
01361 goto err;
01362 }
01363
01364
01365
01366 skip_s_update:
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377 if (dbc_arg->internal->opd != NULL &&
01378 (flags == DB_AFTER || flags == DB_BEFORE || flags == DB_CURRENT)) {
01379
01380
01381
01382
01383
01384
01385
01386 if (dbc_arg->dbtype == DB_HASH && F_ISSET(
01387 ((BTREE_CURSOR *)(dbc_arg->internal->opd->internal)),
01388 C_DELETED)) {
01389 ret = DB_NOTFOUND;
01390 goto err;
01391 }
01392
01393 if ((ret = dbc_arg->c_am_writelock(dbc_arg)) != 0 ||
01394 (ret = __db_c_dup(dbc_arg, &dbc_n, DB_POSITION)) != 0)
01395 goto err;
01396 opd = dbc_n->internal->opd;
01397 if ((ret = opd->c_am_put(
01398 opd, key, data, flags, NULL)) != 0)
01399 goto err;
01400 goto done;
01401 }
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412 tmp_flags = DB_POSITION;
01413
01414
01415
01416
01417
01418 if (F_ISSET(dbc_arg, DBC_TRANSIENT))
01419 dbc_n = dbc_arg;
01420 else if ((ret = __db_c_idup(dbc_arg, &dbc_n, tmp_flags)) != 0)
01421 goto err;
01422
01423 pgno = PGNO_INVALID;
01424 if ((ret = dbc_n->c_am_put(dbc_n, key, data, flags, &pgno)) != 0)
01425 goto err;
01426
01427
01428
01429
01430
01431 if (pgno != PGNO_INVALID) {
01432 oldopd = dbc_n->internal->opd;
01433 if ((ret = __db_c_newopd(dbc_arg, pgno, oldopd, &opd)) != 0) {
01434 dbc_n->internal->opd = opd;
01435 goto err;
01436 }
01437
01438 dbc_n->internal->opd = opd;
01439
01440 if ((ret = opd->c_am_put(
01441 opd, key, data, flags, NULL)) != 0)
01442 goto err;
01443 }
01444
01445 done:
01446 err:
01447 if ((t_ret = __db_c_cleanup(dbc_arg, dbc_n, ret)) != 0 && ret == 0)
01448 ret = t_ret;
01449
01450
01451 if (newdata.data != NULL)
01452 __os_free(dbenv, newdata.data);
01453 if (olddata.data != NULL)
01454 __os_ufree(dbenv, olddata.data);
01455
01456 CDB_LOCKING_DONE(dbp, dbc_arg);
01457
01458 if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
01459 ret = t_ret;
01460
01461 return (ret);
01462 }
01463
01464
01465
01466
01467
01468
01469 int
01470 __db_duperr(dbp, flags)
01471 DB *dbp;
01472 u_int32_t flags;
01473 {
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487 if (flags != DB_NODUPDATA && !F_ISSET(dbp, DB_AM_SECONDARY))
01488 __db_err(dbp->dbenv,
01489 "Duplicate data items are not supported with sorted data");
01490 return (DB_KEYEXIST);
01491 }
01492
01493
01494
01495
01496
01497 static int
01498 __db_c_cleanup(dbc, dbc_n, failed)
01499 DBC *dbc, *dbc_n;
01500 int failed;
01501 {
01502 DB *dbp;
01503 DBC *opd;
01504 DBC_INTERNAL *internal;
01505 DB_MPOOLFILE *mpf;
01506 int ret, t_ret;
01507
01508 dbp = dbc->dbp;
01509 mpf = dbp->mpf;
01510 internal = dbc->internal;
01511 ret = 0;
01512
01513
01514 if (internal->page != NULL) {
01515 if ((t_ret =
01516 __memp_fput(mpf, internal->page, 0)) != 0 && ret == 0)
01517 ret = t_ret;
01518 internal->page = NULL;
01519 }
01520 opd = internal->opd;
01521 if (opd != NULL && opd->internal->page != NULL) {
01522 if ((t_ret =
01523 __memp_fput(mpf, opd->internal->page, 0)) != 0 && ret == 0)
01524 ret = t_ret;
01525 opd->internal->page = NULL;
01526 }
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542 if (dbc_n == NULL || dbc == dbc_n)
01543 return (ret);
01544
01545 if (dbc_n->internal->page != NULL) {
01546 if ((t_ret = __memp_fput(
01547 mpf, dbc_n->internal->page, 0)) != 0 && ret == 0)
01548 ret = t_ret;
01549 dbc_n->internal->page = NULL;
01550 }
01551 opd = dbc_n->internal->opd;
01552 if (opd != NULL && opd->internal->page != NULL) {
01553 if ((t_ret =
01554 __memp_fput(mpf, opd->internal->page, 0)) != 0 && ret == 0)
01555 ret = t_ret;
01556 opd->internal->page = NULL;
01557 }
01558
01559
01560
01561
01562
01563
01564 if (!failed && ret == 0) {
01565 dbc->internal = dbc_n->internal;
01566 dbc_n->internal = internal;
01567 }
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584 if ((t_ret = __db_c_close(dbc_n)) != 0 && ret == 0)
01585 ret = t_ret;
01586
01587
01588
01589
01590
01591
01592
01593
01594 if (F_ISSET(dbp, DB_AM_READ_UNCOMMITTED) &&
01595 dbc->internal->lock_mode == DB_LOCK_WRITE) {
01596 if ((t_ret =
01597 __TLPUT(dbc, dbc->internal->lock)) != 0 && ret == 0)
01598 ret = t_ret;
01599 if (t_ret == 0)
01600 dbc->internal->lock_mode = DB_LOCK_WWRITE;
01601 }
01602
01603 return (ret);
01604 }
01605
01606
01607
01608
01609
01610
01611
01612
01613 int
01614 __db_c_secondary_get_pp(dbc, skey, data, flags)
01615 DBC *dbc;
01616 DBT *skey, *data;
01617 u_int32_t flags;
01618 {
01619
01620 DB_ASSERT(F_ISSET(dbc->dbp, DB_AM_SECONDARY));
01621 return (__db_c_pget_pp(dbc, skey, NULL, data, flags));
01622 }
01623
01624
01625
01626
01627
01628
01629
01630 int
01631 __db_c_pget(dbc, skey, pkey, data, flags)
01632 DBC *dbc;
01633 DBT *skey, *pkey, *data;
01634 u_int32_t flags;
01635 {
01636 DB *pdbp, *sdbp;
01637 DBC *dbc_n, *pdbc;
01638 DBT nullpkey;
01639 u_int32_t save_pkey_flags, tmp_flags, tmp_read_uncommitted, tmp_rmw;
01640 int pkeymalloc, ret, t_ret;
01641
01642 sdbp = dbc->dbp;
01643 pdbp = sdbp->s_primary;
01644 dbc_n = NULL;
01645 pkeymalloc = t_ret = 0;
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659 if (pkey == NULL) {
01660 memset(&nullpkey, 0, sizeof(DBT));
01661 pkey = &nullpkey;
01662 }
01663
01664
01665 tmp_rmw = LF_ISSET(DB_RMW);
01666 LF_CLR(DB_RMW);
01667
01668 tmp_read_uncommitted =
01669 LF_ISSET(DB_READ_UNCOMMITTED) &&
01670 !F_ISSET(dbc, DBC_READ_UNCOMMITTED);
01671 LF_CLR(DB_READ_UNCOMMITTED);
01672
01673
01674
01675
01676
01677
01678 if (flags == DB_GET_RECNO) {
01679 if (tmp_rmw)
01680 F_SET(dbc, DBC_RMW);
01681 if (tmp_read_uncommitted)
01682 F_SET(dbc, DBC_READ_UNCOMMITTED);
01683 ret = __db_c_pget_recno(dbc, pkey, data, flags);
01684 if (tmp_rmw)
01685 F_CLR(dbc, DBC_RMW);
01686 if (tmp_read_uncommitted)
01687 F_CLR(dbc, DBC_READ_UNCOMMITTED);
01688 return (ret);
01689 }
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725 save_pkey_flags = pkey->flags;
01726 F_CLR(pkey, DB_DBT_PARTIAL);
01727
01728
01729
01730
01731
01732
01733
01734
01735 switch (flags) {
01736 case DB_CURRENT:
01737 case DB_GET_BOTHC:
01738 case DB_NEXT:
01739 case DB_NEXT_DUP:
01740 case DB_NEXT_NODUP:
01741 case DB_PREV:
01742 case DB_PREV_NODUP:
01743 tmp_flags = DB_POSITION;
01744 break;
01745 default:
01746 tmp_flags = 0;
01747 break;
01748 }
01749
01750 if (tmp_read_uncommitted)
01751 F_SET(dbc, DBC_READ_UNCOMMITTED);
01752
01753 if ((ret = __db_c_dup(dbc, &dbc_n, tmp_flags)) != 0) {
01754 if (tmp_read_uncommitted)
01755 F_CLR(dbc, DBC_READ_UNCOMMITTED);
01756
01757 return (ret);
01758 }
01759
01760 F_SET(dbc_n, DBC_TRANSIENT);
01761
01762 if (tmp_rmw)
01763 F_SET(dbc_n, DBC_RMW);
01764
01765
01766
01767
01768
01769 if (flags == DB_GET_BOTH || flags == DB_GET_BOTHC ||
01770 flags == DB_GET_BOTH_RANGE)
01771 SWAP_IF_NEEDED(pdbp, sdbp, pkey);
01772
01773
01774 dbc_n->rdata = dbc->rkey;
01775 dbc_n->rkey = dbc->rskey;
01776 ret = __db_c_get(dbc_n, skey, pkey, flags);
01777
01778 pkey->flags = save_pkey_flags;
01779
01780 if (tmp_read_uncommitted)
01781 F_CLR(dbc_n, DBC_READ_UNCOMMITTED);
01782 if (tmp_rmw)
01783 F_CLR(dbc_n, DBC_RMW);
01784
01785
01786
01787
01788
01789
01790 if (ret == 0 || flags == DB_GET_BOTH || flags == DB_GET_BOTHC ||
01791 flags == DB_GET_BOTH_RANGE)
01792 SWAP_IF_NEEDED(pdbp, sdbp, pkey);
01793
01794 if (ret != 0)
01795 goto err;
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819 if ((ret = __db_cursor_int(pdbp,
01820 dbc->txn, pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)
01821 goto err;
01822
01823 if (tmp_read_uncommitted)
01824 F_SET(pdbc, DBC_READ_UNCOMMITTED);
01825 if (tmp_rmw)
01826 F_SET(pdbc, DBC_RMW);
01827 if (F_ISSET(dbc, DBC_READ_COMMITTED))
01828 F_SET(pdbc, DBC_READ_COMMITTED);
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841 if (F_ISSET(pkey, DB_DBT_MALLOC)) {
01842 F_CLR(pkey, DB_DBT_MALLOC);
01843 F_SET(pkey, DB_DBT_REALLOC);
01844 pkeymalloc = 1;
01845 }
01846
01847
01848
01849
01850
01851
01852 F_SET(pdbc, DBC_TRANSIENT);
01853 SET_RET_MEM(pdbc, dbc);
01854 ret = __db_c_get(pdbc, pkey, data, DB_SET);
01855
01856
01857
01858
01859
01860
01861 if (ret == DB_NOTFOUND)
01862 ret = __db_secondary_corrupt(pdbp);
01863
01864
01865 if ((t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
01866 ret = t_ret;
01867
01868 err:
01869 if ((t_ret = __db_c_cleanup(dbc, dbc_n, ret)) != 0 && ret == 0)
01870 ret = t_ret;
01871 if (pkeymalloc) {
01872
01873
01874
01875
01876
01877
01878 F_CLR(pkey, DB_DBT_REALLOC);
01879 F_SET(pkey, DB_DBT_MALLOC);
01880 }
01881
01882 return (ret);
01883 }
01884
01885
01886
01887
01888
01889
01890
01891 static int
01892 __db_c_pget_recno(sdbc, pkey, data, flags)
01893 DBC *sdbc;
01894 DBT *pkey, *data;
01895 u_int32_t flags;
01896 {
01897 DB *pdbp, *sdbp;
01898 DB_ENV *dbenv;
01899 DBC *pdbc;
01900 DBT discardme, primary_key;
01901 db_recno_t oob;
01902 u_int32_t rmw;
01903 int ret, t_ret;
01904
01905 sdbp = sdbc->dbp;
01906 pdbp = sdbp->s_primary;
01907 dbenv = sdbp->dbenv;
01908 pdbc = NULL;
01909 ret = t_ret = 0;
01910
01911 rmw = LF_ISSET(DB_RMW);
01912
01913 memset(&discardme, 0, sizeof(DBT));
01914 F_SET(&discardme, DB_DBT_USERMEM | DB_DBT_PARTIAL);
01915
01916 oob = RECNO_OOB;
01917
01918
01919
01920
01921
01922
01923
01924 if (F_ISSET(pdbp, DB_AM_RECNUM)) {
01925
01926
01927
01928
01929 memset(&primary_key, 0, sizeof(DBT));
01930 F_SET(&primary_key, DB_DBT_MALLOC);
01931 if ((ret = __db_c_get(sdbc,
01932 &discardme, &primary_key, rmw | DB_CURRENT)) != 0)
01933 return (ret);
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944 if ((ret = __db_cursor_int(pdbp, sdbc->txn,
01945 pdbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0)
01946 goto perr;
01947 SET_RET_MEM(pdbc, sdbc);
01948 if ((ret = __db_c_get(pdbc,
01949 &primary_key, &discardme, rmw | DB_SET)) != 0)
01950 goto perr;
01951
01952 ret = __db_c_get(pdbc, &discardme, data, rmw | DB_GET_RECNO);
01953
01954 perr: __os_ufree(sdbp->dbenv, primary_key.data);
01955 if (pdbc != NULL &&
01956 (t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
01957 ret = t_ret;
01958 if (ret != 0)
01959 return (ret);
01960 } else if ((ret = __db_retcopy(dbenv, data, &oob,
01961 sizeof(oob), &sdbc->rkey->data, &sdbc->rkey->ulen)) != 0)
01962 return (ret);
01963
01964
01965
01966
01967
01968
01969
01970 if (F_ISSET(sdbp, DB_AM_RECNUM))
01971 return (__db_c_get(sdbc, &discardme, pkey, flags));
01972 else
01973 return (__db_retcopy(dbenv, pkey, &oob,
01974 sizeof(oob), &sdbc->rdata->data, &sdbc->rdata->ulen));
01975 }
01976
01977
01978
01979
01980 static int
01981 __db_wrlock_err(dbenv)
01982 DB_ENV *dbenv;
01983 {
01984 __db_err(dbenv, "Write attempted on read-only cursor");
01985 return (EPERM);
01986 }
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998 static int
01999 __db_c_del_secondary(dbc)
02000 DBC *dbc;
02001 {
02002 DB *pdbp;
02003 DBC *pdbc;
02004 DBT skey, pkey;
02005 int ret, t_ret;
02006
02007 memset(&skey, 0, sizeof(DBT));
02008 memset(&pkey, 0, sizeof(DBT));
02009 pdbp = dbc->dbp->s_primary;
02010
02011
02012
02013
02014
02015
02016 F_SET(&skey, DB_DBT_PARTIAL | DB_DBT_USERMEM);
02017 if ((ret = __db_c_get(dbc, &skey, &pkey, DB_CURRENT)) != 0)
02018 return (ret);
02019
02020 SWAP_IF_NEEDED(pdbp, dbc->dbp, &pkey);
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032 if ((ret = __db_cursor_int(pdbp, dbc->txn,
02033 pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0)
02034 return (ret);
02035
02036
02037
02038
02039
02040
02041
02042 if (CDB_LOCKING(pdbp->dbenv)) {
02043 DB_ASSERT(pdbc->mylock.off == LOCK_INVALID);
02044 F_SET(pdbc, DBC_WRITER);
02045 }
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056 if ((ret = __db_c_get(pdbc, &pkey, &skey,
02057 (STD_LOCKING(dbc) ? DB_RMW : 0) | DB_SET)) == 0)
02058 ret = __db_c_del(pdbc, 0);
02059 else if (ret == DB_NOTFOUND)
02060 ret = __db_secondary_corrupt(pdbp);
02061
02062 if ((t_ret = __db_c_close(pdbc)) != 0 && ret == 0)
02063 ret = t_ret;
02064
02065 return (ret);
02066 }
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077 int
02078 __db_c_del_primary(dbc)
02079 DBC *dbc;
02080 {
02081 DB *dbp, *sdbp;
02082 DBC *sdbc;
02083 DBT data, pkey, skey, temppkey, tempskey;
02084 int ret, t_ret;
02085
02086 dbp = dbc->dbp;
02087
02088
02089
02090
02091
02092
02093
02094 memset(&pkey, 0, sizeof(DBT));
02095 memset(&data, 0, sizeof(DBT));
02096 if ((ret = __db_c_get(dbc, &pkey, &data, DB_CURRENT)) != 0)
02097 return (ret);
02098
02099 if ((ret = __db_s_first(dbp, &sdbp)) != 0)
02100 goto err;
02101 for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {
02102
02103
02104
02105
02106 memset(&skey, 0, sizeof(DBT));
02107 if ((ret = sdbp->s_callback(sdbp, &pkey, &data, &skey)) != 0) {
02108
02109
02110
02111
02112 if (ret == DB_DONOTINDEX)
02113 continue;
02114
02115
02116 FREE_IF_NEEDED(sdbp, &skey);
02117 goto err;
02118 }
02119
02120
02121 if ((ret = __db_cursor_int(sdbp, dbc->txn, sdbp->type,
02122 PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0)
02123 goto err;
02124
02125 if (CDB_LOCKING(sdbp->dbenv)) {
02126 DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);
02127 F_SET(sdbc, DBC_WRITER);
02128 }
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143 memset(&tempskey, 0, sizeof(DBT));
02144 tempskey.data = skey.data;
02145 tempskey.size = skey.size;
02146 SWAP_IF_NEEDED(dbp, sdbp, &pkey);
02147 memset(&temppkey, 0, sizeof(DBT));
02148 temppkey.data = pkey.data;
02149 temppkey.size = pkey.size;
02150 if ((ret = __db_c_get(sdbc, &tempskey, &temppkey,
02151 (STD_LOCKING(dbc) ? DB_RMW : 0) | DB_GET_BOTH)) == 0)
02152 ret = __db_c_del(sdbc, DB_UPDATE_SECONDARY);
02153 else if (ret == DB_NOTFOUND)
02154 ret = __db_secondary_corrupt(dbp);
02155 SWAP_IF_NEEDED(dbp, sdbp, &pkey);
02156
02157 FREE_IF_NEEDED(sdbp, &skey);
02158
02159 if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)
02160 ret = t_ret;
02161 if (ret != 0)
02162 goto err;
02163 }
02164
02165 err: if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)
02166 ret = t_ret;
02167 return (ret);
02168 }
02169
02170
02171
02172
02173
02174
02175
02176 int
02177 __db_s_first(pdbp, sdbpp)
02178 DB *pdbp, **sdbpp;
02179 {
02180 DB *sdbp;
02181
02182 MUTEX_LOCK(pdbp->dbenv, pdbp->mutex);
02183 sdbp = LIST_FIRST(&pdbp->s_secondaries);
02184
02185
02186 if (sdbp != NULL)
02187 sdbp->s_refcnt++;
02188 MUTEX_UNLOCK(pdbp->dbenv, pdbp->mutex);
02189
02190 *sdbpp = sdbp;
02191
02192 return (0);
02193 }
02194
02195
02196
02197
02198
02199
02200
02201 int
02202 __db_s_next(sdbpp)
02203 DB **sdbpp;
02204 {
02205 DB *sdbp, *pdbp, *closeme;
02206 int ret;
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231 sdbp = *sdbpp;
02232 pdbp = sdbp->s_primary;
02233 closeme = NULL;
02234
02235 MUTEX_LOCK(pdbp->dbenv, pdbp->mutex);
02236 DB_ASSERT(sdbp->s_refcnt != 0);
02237 if (--sdbp->s_refcnt == 0) {
02238 LIST_REMOVE(sdbp, s_links);
02239 closeme = sdbp;
02240 }
02241 sdbp = LIST_NEXT(sdbp, s_links);
02242 if (sdbp != NULL)
02243 sdbp->s_refcnt++;
02244 MUTEX_UNLOCK(pdbp->dbenv, pdbp->mutex);
02245
02246 *sdbpp = sdbp;
02247
02248
02249
02250
02251 ret = closeme != NULL ? __db_close(closeme, NULL, 0) : 0;
02252 return (ret);
02253 }
02254
02255
02256
02257
02258
02259
02260
02261
02262 int
02263 __db_s_done(sdbp)
02264 DB *sdbp;
02265 {
02266 DB *pdbp;
02267 int doclose;
02268
02269 pdbp = sdbp->s_primary;
02270 doclose = 0;
02271
02272 MUTEX_LOCK(pdbp->dbenv, pdbp->mutex);
02273 DB_ASSERT(sdbp->s_refcnt != 0);
02274 if (--sdbp->s_refcnt == 0) {
02275 LIST_REMOVE(sdbp, s_links);
02276 doclose = 1;
02277 }
02278 MUTEX_UNLOCK(pdbp->dbenv, pdbp->mutex);
02279
02280 return (doclose ? __db_close(sdbp, NULL, 0) : 0);
02281 }
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292 static int
02293 __db_buildpartial(dbp, oldrec, partial, newrec)
02294 DB *dbp;
02295 DBT *oldrec, *partial, *newrec;
02296 {
02297 int ret;
02298 u_int8_t *buf;
02299 u_int32_t len, nbytes;
02300
02301 DB_ASSERT(F_ISSET(partial, DB_DBT_PARTIAL));
02302
02303 memset(newrec, 0, sizeof(DBT));
02304
02305 nbytes = __db_partsize(oldrec->size, partial);
02306 newrec->size = nbytes;
02307
02308 if ((ret = __os_malloc(dbp->dbenv, nbytes, &buf)) != 0)
02309 return (ret);
02310 newrec->data = buf;
02311
02312
02313 memset(buf,
02314 F_ISSET(dbp, DB_AM_FIXEDLEN) ? ((BTREE *)dbp->bt_internal)->re_pad :
02315 0, nbytes);
02316
02317
02318 memcpy(buf, oldrec->data,
02319 partial->doff > oldrec->size ? oldrec->size : partial->doff);
02320
02321
02322 memcpy(buf + partial->doff, partial->data, partial->size);
02323
02324
02325 len = partial->doff + partial->dlen;
02326 if (oldrec->size > len)
02327 memcpy(buf + partial->doff + partial->size,
02328 (u_int8_t *)oldrec->data + len, oldrec->size - len);
02329
02330 return (0);
02331 }
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343 u_int32_t
02344 __db_partsize(nbytes, data)
02345 u_int32_t nbytes;
02346 DBT *data;
02347 {
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363 if (nbytes < data->doff + data->dlen)
02364 return (data->doff + data->size);
02365
02366 return (nbytes + data->size - data->dlen);
02367 }