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