db_cam.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:24k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: db_cam.c,v 11.52 2001/01/18 15:11:16 bostic Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <string.h>
  14. #endif
  15. #include "db_int.h"
  16. #include "db_page.h"
  17. #include "db_shash.h"
  18. #include "lock.h"
  19. #include "btree.h"
  20. #include "hash.h"
  21. #include "qam.h"
  22. #include "txn.h"
  23. #include "db_ext.h"
  24. static int __db_c_cleanup __P((DBC *, DBC *, int));
  25. static int __db_c_idup __P((DBC *, DBC **, u_int32_t));
  26. static int __db_wrlock_err __P((DB_ENV *));
  27. #define CDB_LOCKING_INIT(dbp, dbc)
  28. /*
  29.  * If we are running CDB, this had better be either a write
  30.  * cursor or an immediate writer.  If it's a regular writer,
  31.  * that means we have an IWRITE lock and we need to upgrade
  32.  * it to a write lock.
  33.  */
  34. if (CDB_LOCKING((dbp)->dbenv)) {
  35. if (!F_ISSET(dbc, DBC_WRITECURSOR | DBC_WRITER))
  36. return (__db_wrlock_err(dbp->dbenv));
  37. if (F_ISSET(dbc, DBC_WRITECURSOR) &&
  38.     (ret = lock_get((dbp)->dbenv, (dbc)->locker,
  39.     DB_LOCK_UPGRADE, &(dbc)->lock_dbt, DB_LOCK_WRITE,
  40.     &(dbc)->mylock)) != 0)
  41. return (ret);
  42. }
  43. #define CDB_LOCKING_DONE(dbp, dbc)
  44. /* Release the upgraded lock. */
  45. if (F_ISSET(dbc, DBC_WRITECURSOR))
  46. (void)__lock_downgrade(
  47.     (dbp)->dbenv, &(dbc)->mylock, DB_LOCK_IWRITE, 0);
  48. /*
  49.  * Copy the lock info from one cursor to another, so that locking
  50.  * in CDB can be done in the context of an internally-duplicated
  51.  * or off-page-duplicate cursor.
  52.  */
  53. #define CDB_LOCKING_COPY(dbp, dbc_o, dbc_n)
  54. if (CDB_LOCKING((dbp)->dbenv) &&
  55.     F_ISSET((dbc_o), DBC_WRITECURSOR | DBC_WRITEDUP)) { 
  56. memcpy(&(dbc_n)->mylock, &(dbc_o)->mylock,
  57.     sizeof((dbc_o)->mylock));
  58. (dbc_n)->locker = (dbc_o)->locker;
  59.     /* This lock isn't ours to put--just discard it on close. */ 
  60.     F_SET((dbc_n), DBC_WRITEDUP);
  61. }
  62. /*
  63.  * __db_c_close --
  64.  * Close the cursor.
  65.  *
  66.  * PUBLIC: int __db_c_close __P((DBC *));
  67.  */
  68. int
  69. __db_c_close(dbc)
  70. DBC *dbc;
  71. {
  72. DB *dbp;
  73. DBC *opd;
  74. DBC_INTERNAL *cp;
  75. int ret, t_ret;
  76. dbp = dbc->dbp;
  77. ret = 0;
  78. PANIC_CHECK(dbp->dbenv);
  79. /*
  80.  * If the cursor is already closed we have a serious problem, and we
  81.  * assume that the cursor isn't on the active queue.  Don't do any of
  82.  * the remaining cursor close processing.
  83.  */
  84. if (!F_ISSET(dbc, DBC_ACTIVE)) {
  85. if (dbp != NULL)
  86. __db_err(dbp->dbenv, "Closing closed cursor");
  87. DB_ASSERT(0);
  88. return (EINVAL);
  89. }
  90. cp = dbc->internal;
  91. opd = cp->opd;
  92. /*
  93.  * Remove the cursor(s) from the active queue.  We may be closing two
  94.  * cursors at once here, a top-level one and a lower-level, off-page
  95.  * duplicate one.  The acess-method specific cursor close routine must
  96.  * close both of them in a single call.
  97.  *
  98.  * !!!
  99.  * Cursors must be removed from the active queue before calling the
  100.  * access specific cursor close routine, btree depends on having that
  101.  * order of operations.  It must also happen before any action that
  102.  * can fail and cause __db_c_close to return an error, or else calls
  103.  * here from __db_close may loop indefinitely.
  104.  */
  105. MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
  106. if (opd != NULL) {
  107. F_CLR(opd, DBC_ACTIVE);
  108. TAILQ_REMOVE(&dbp->active_queue, opd, links);
  109. }
  110. F_CLR(dbc, DBC_ACTIVE);
  111. TAILQ_REMOVE(&dbp->active_queue, dbc, links);
  112. MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
  113. /* Call the access specific cursor close routine. */
  114. if ((t_ret =
  115.     dbc->c_am_close(dbc, PGNO_INVALID, NULL)) != 0 && ret == 0)
  116. ret = t_ret;
  117. /*
  118.  * Release the lock after calling the access method specific close
  119.  * routine, a Btree cursor may have had pending deletes.
  120.  */
  121. if (CDB_LOCKING(dbc->dbp->dbenv)) {
  122. /*
  123.  * If DBC_WRITEDUP is set, the cursor is an internally
  124.  * duplicated write cursor and the lock isn't ours to put.
  125.  */
  126. if (!F_ISSET(dbc, DBC_WRITEDUP) &&
  127.     dbc->mylock.off != LOCK_INVALID) {
  128. if ((t_ret = lock_put(dbc->dbp->dbenv,
  129.     &dbc->mylock)) != 0 && ret == 0)
  130. ret = t_ret;
  131. dbc->mylock.off = LOCK_INVALID;
  132. }
  133. /* For safety's sake, since this is going on the free queue. */
  134. memset(&dbc->mylock, 0, sizeof(dbc->mylock));
  135. F_CLR(dbc, DBC_WRITEDUP);
  136. }
  137. if (dbc->txn != NULL)
  138. dbc->txn->cursors--;
  139. /* Move the cursor(s) to the free queue. */
  140. MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
  141. if (opd != NULL) {
  142. if (dbc->txn != NULL)
  143. dbc->txn->cursors--;
  144. TAILQ_INSERT_TAIL(&dbp->free_queue, opd, links);
  145. opd = NULL;
  146. }
  147. TAILQ_INSERT_TAIL(&dbp->free_queue, dbc, links);
  148. MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
  149. return (ret);
  150. }
  151. /*
  152.  * __db_c_destroy --
  153.  * Destroy the cursor, called after DBC->c_close.
  154.  *
  155.  * PUBLIC: int __db_c_destroy __P((DBC *));
  156.  */
  157. int
  158. __db_c_destroy(dbc)
  159. DBC *dbc;
  160. {
  161. DB *dbp;
  162. DBC_INTERNAL *cp;
  163. int ret;
  164. dbp = dbc->dbp;
  165. cp =  dbc->internal;
  166. /* Remove the cursor from the free queue. */
  167. MUTEX_THREAD_LOCK(dbp->dbenv, dbp->mutexp);
  168. TAILQ_REMOVE(&dbp->free_queue, dbc, links);
  169. MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp);
  170. /* Free up allocated memory. */
  171. if (dbc->rkey.data != NULL)
  172. __os_free(dbc->rkey.data, dbc->rkey.ulen);
  173. if (dbc->rdata.data != NULL)
  174. __os_free(dbc->rdata.data, dbc->rdata.ulen);
  175. /* Call the access specific cursor destroy routine. */
  176. ret = dbc->c_am_destroy == NULL ? 0 : dbc->c_am_destroy(dbc);
  177. __os_free(dbc, sizeof(*dbc));
  178. return (ret);
  179. }
  180. /*
  181.  * __db_c_count --
  182.  * Return a count of duplicate data items.
  183.  *
  184.  * PUBLIC: int __db_c_count __P((DBC *, db_recno_t *, u_int32_t));
  185.  */
  186. int
  187. __db_c_count(dbc, recnop, flags)
  188. DBC *dbc;
  189. db_recno_t *recnop;
  190. u_int32_t flags;
  191. {
  192. DB *dbp;
  193. int ret;
  194. /*
  195.  * Cursor Cleanup Note:
  196.  * All of the cursors passed to the underlying access methods by this
  197.  * routine are not duplicated and will not be cleaned up on return.
  198.  * So, pages/locks that the cursor references must be resolved by the
  199.  * underlying functions.
  200.  */
  201. dbp = dbc->dbp;
  202. PANIC_CHECK(dbp->dbenv);
  203. /* Check for invalid flags. */
  204. if ((ret = __db_ccountchk(dbp, flags, IS_INITIALIZED(dbc))) != 0)
  205. return (ret);
  206. switch (dbc->dbtype) {
  207. case DB_QUEUE:
  208. case DB_RECNO:
  209. *recnop = 1;
  210. break;
  211. case DB_HASH:
  212. if (dbc->internal->opd == NULL) {
  213. if ((ret = __ham_c_count(dbc, recnop)) != 0)
  214. return (ret);
  215. break;
  216. }
  217. /* FALLTHROUGH */
  218. case DB_BTREE:
  219. if ((ret = __bam_c_count(dbc, recnop)) != 0)
  220. return (ret);
  221. break;
  222. default:
  223. return (__db_unknown_type(dbp->dbenv,
  224.      "__db_c_count", dbp->type));
  225. }
  226. return (0);
  227. }
  228. /*
  229.  * __db_c_del --
  230.  * Delete using a cursor.
  231.  *
  232.  * PUBLIC: int __db_c_del __P((DBC *, u_int32_t));
  233.  */
  234. int
  235. __db_c_del(dbc, flags)
  236. DBC *dbc;
  237. u_int32_t flags;
  238. {
  239. DB *dbp;
  240. DBC *opd;
  241. int ret;
  242. /*
  243.  * Cursor Cleanup Note:
  244.  * All of the cursors passed to the underlying access methods by this
  245.  * routine are not duplicated and will not be cleaned up on return.
  246.  * So, pages/locks that the cursor references must be resolved by the
  247.  * underlying functions.
  248.  */
  249. dbp = dbc->dbp;
  250. PANIC_CHECK(dbp->dbenv);
  251. DB_CHECK_TXN(dbp, dbc->txn);
  252. /* Check for invalid flags. */
  253. if ((ret = __db_cdelchk(dbp, flags,
  254.     F_ISSET(dbp, DB_AM_RDONLY), IS_INITIALIZED(dbc))) != 0)
  255. return (ret);
  256. DEBUG_LWRITE(dbc, dbc->txn, "db_c_del", NULL, NULL, flags);
  257. CDB_LOCKING_INIT(dbp, dbc);
  258. /*
  259.  * Off-page duplicate trees are locked in the primary tree, that is,
  260.  * we acquire a write lock in the primary tree and no locks in the
  261.  * off-page dup tree.  If the del operation is done in an off-page
  262.  * duplicate tree, call the primary cursor's upgrade routine first.
  263.  */
  264. opd = dbc->internal->opd;
  265. if (opd == NULL)
  266. ret = dbc->c_am_del(dbc);
  267. else
  268. if ((ret = dbc->c_am_writelock(dbc)) == 0)
  269. ret = opd->c_am_del(opd);
  270. CDB_LOCKING_DONE(dbp, dbc);
  271. return (ret);
  272. }
  273. /*
  274.  * __db_c_dup --
  275.  * Duplicate a cursor
  276.  *
  277.  * PUBLIC: int __db_c_dup __P((DBC *, DBC **, u_int32_t));
  278.  */
  279. int
  280. __db_c_dup(dbc_orig, dbcp, flags)
  281. DBC *dbc_orig;
  282. DBC **dbcp;
  283. u_int32_t flags;
  284. {
  285. DB_ENV *dbenv;
  286. DB *dbp;
  287. DBC *dbc_n, *dbc_nopd;
  288. int ret;
  289. dbp = dbc_orig->dbp;
  290. dbenv = dbp->dbenv;
  291. dbc_n = dbc_nopd = NULL;
  292. PANIC_CHECK(dbp->dbenv);
  293. /*
  294.  * We can never have two write cursors open in CDB, so do not
  295.  * allow duplication of a write cursor.
  296.  */
  297. if (flags != DB_POSITIONI &&
  298.     F_ISSET(dbc_orig, DBC_WRITER | DBC_WRITECURSOR)) {
  299. __db_err(dbenv, "Cannot duplicate writeable cursor");
  300. return (EINVAL);
  301. }
  302. /* Allocate a new cursor and initialize it. */
  303. if ((ret = __db_c_idup(dbc_orig, &dbc_n, flags)) != 0)
  304. goto err;
  305. *dbcp = dbc_n;
  306. /*
  307.  * If we're in CDB, and this isn't an internal duplication (in which
  308.  * case we're explicitly overriding CDB locking), the duplicated
  309.  * cursor needs its own read lock.  (We know it's not a write cursor
  310.  * because we wouldn't have made it this far;  you can't dup them.)
  311.  */
  312. if (CDB_LOCKING(dbenv) && flags != DB_POSITIONI) {
  313. DB_ASSERT(!F_ISSET(dbc_orig, DBC_WRITER | DBC_WRITECURSOR));
  314. if ((ret = lock_get(dbenv, dbc_n->locker, 0,
  315.     &dbc_n->lock_dbt, DB_LOCK_READ, &dbc_n->mylock)) != 0) {
  316. (void)__db_c_close(dbc_n);
  317. return (ret);
  318. }
  319. }
  320. /*
  321.  * If the cursor references an off-page duplicate tree, allocate a
  322.  * new cursor for that tree and initialize it.
  323.  */
  324. if (dbc_orig->internal->opd != NULL) {
  325. if ((ret =
  326.    __db_c_idup(dbc_orig->internal->opd, &dbc_nopd, flags)) != 0)
  327. goto err;
  328. dbc_n->internal->opd = dbc_nopd;
  329. }
  330. return (0);
  331. err: if (dbc_n != NULL)
  332. (void)dbc_n->c_close(dbc_n);
  333. if (dbc_nopd != NULL)
  334. (void)dbc_nopd->c_close(dbc_nopd);
  335. return (ret);
  336. }
  337. /*
  338.  * __db_c_idup --
  339.  * Internal version of __db_c_dup.
  340.  */
  341. static int
  342. __db_c_idup(dbc_orig, dbcp, flags)
  343. DBC *dbc_orig, **dbcp;
  344. u_int32_t flags;
  345. {
  346. DB *dbp;
  347. DBC *dbc_n;
  348. DBC_INTERNAL *int_n, *int_orig;
  349. int ret;
  350. dbp = dbc_orig->dbp;
  351. dbc_n = *dbcp;
  352. if ((ret = __db_icursor(dbp, dbc_orig->txn, dbc_orig->dbtype,
  353.     dbc_orig->internal->root, F_ISSET(dbc_orig, DBC_OPD), &dbc_n)) != 0)
  354. return (ret);
  355. dbc_n->locker = dbc_orig->locker;
  356. /* If the user wants the cursor positioned, do it here.  */
  357. if (flags == DB_POSITION || flags == DB_POSITIONI) {
  358. int_n = dbc_n->internal;
  359. int_orig = dbc_orig->internal;
  360. dbc_n->flags = dbc_orig->flags;
  361. int_n->indx = int_orig->indx;
  362. int_n->pgno = int_orig->pgno;
  363. int_n->root = int_orig->root;
  364. int_n->lock_mode = int_orig->lock_mode;
  365. switch (dbc_orig->dbtype) {
  366. case DB_QUEUE:
  367. if ((ret = __qam_c_dup(dbc_orig, dbc_n)) != 0)
  368. goto err;
  369. break;
  370. case DB_BTREE:
  371. case DB_RECNO:
  372. if ((ret = __bam_c_dup(dbc_orig, dbc_n)) != 0)
  373. goto err;
  374. break;
  375. case DB_HASH:
  376. if ((ret = __ham_c_dup(dbc_orig, dbc_n)) != 0)
  377. goto err;
  378. break;
  379. default:
  380. ret = __db_unknown_type(dbp->dbenv,
  381.     "__db_c_idup", dbc_orig->dbtype);
  382. goto err;
  383. }
  384. }
  385. /* Now take care of duping the CDB information. */
  386. CDB_LOCKING_COPY(dbp, dbc_orig, dbc_n);
  387. *dbcp = dbc_n;
  388. return (0);
  389. err: (void)dbc_n->c_close(dbc_n);
  390. return (ret);
  391. }
  392. /*
  393.  * __db_c_newopd --
  394.  * Create a new off-page duplicate cursor.
  395.  *
  396.  * PUBLIC: int __db_c_newopd __P((DBC *, db_pgno_t, DBC **));
  397.  */
  398. int
  399. __db_c_newopd(dbc_parent, root, dbcp)
  400. DBC *dbc_parent;
  401. db_pgno_t root;
  402. DBC **dbcp;
  403. {
  404. DB *dbp;
  405. DBC *opd;
  406. DBTYPE dbtype;
  407. int ret;
  408. dbp = dbc_parent->dbp;
  409. dbtype = (dbp->dup_compare == NULL) ? DB_RECNO : DB_BTREE;
  410. if ((ret = __db_icursor(dbp,
  411.     dbc_parent->txn, dbtype, root, 1, &opd)) != 0)
  412. return (ret);
  413. CDB_LOCKING_COPY(dbp, dbc_parent, opd);
  414. *dbcp = opd;
  415. return (0);
  416. }
  417. /*
  418.  * __db_c_get --
  419.  * Get using a cursor.
  420.  *
  421.  * PUBLIC: int __db_c_get __P((DBC *, DBT *, DBT *, u_int32_t));
  422.  */
  423. int
  424. __db_c_get(dbc_arg, key, data, flags)
  425. DBC *dbc_arg;
  426. DBT *key, *data;
  427. u_int32_t flags;
  428. {
  429. DB *dbp;
  430. DBC *dbc, *dbc_n, *opd;
  431. DBC_INTERNAL *cp, *cp_n;
  432. db_pgno_t pgno;
  433. u_int32_t tmp_flags, tmp_rmw;
  434. u_int8_t type;
  435. int ret, t_ret;
  436. /*
  437.  * Cursor Cleanup Note:
  438.  * All of the cursors passed to the underlying access methods by this
  439.  * routine are duplicated cursors.  On return, any referenced pages
  440.  * will be discarded, and, if the cursor is not intended to be used
  441.  * again, the close function will be called.  So, pages/locks that
  442.  * the cursor references do not need to be resolved by the underlying
  443.  * functions.
  444.  */
  445. dbp = dbc_arg->dbp;
  446. dbc_n = NULL;
  447. opd = NULL;
  448. PANIC_CHECK(dbp->dbenv);
  449. /* Check for invalid flags. */
  450. if ((ret =
  451.     __db_cgetchk(dbp, key, data, flags, IS_INITIALIZED(dbc_arg))) != 0)
  452. return (ret);
  453. /* Clear OR'd in additional bits so we can check for flag equality. */
  454. tmp_rmw = LF_ISSET(DB_RMW);
  455. LF_CLR(DB_RMW);
  456. DEBUG_LREAD(dbc_arg, dbc_arg->txn, "db_c_get",
  457.     flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, NULL, flags);
  458. /*
  459.  * Return a cursor's record number.  It has nothing to do with the
  460.  * cursor get code except that it was put into the interface.
  461.  */
  462. if (flags == DB_GET_RECNO)
  463. return (__bam_c_rget(dbc_arg, data, flags | tmp_rmw));
  464. if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
  465. CDB_LOCKING_INIT(dbp, dbc_arg);
  466. /*
  467.  * If we have an off-page duplicates cursor, and the operation applies
  468.  * to it, perform the operation.  Duplicate the cursor and call the
  469.  * underlying function.
  470.  *
  471.  * Off-page duplicate trees are locked in the primary tree, that is,
  472.  * we acquire a write lock in the primary tree and no locks in the
  473.  * off-page dup tree.  If the DB_RMW flag was specified and the get
  474.  * operation is done in an off-page duplicate tree, call the primary
  475.  * cursor's upgrade routine first.
  476.  */
  477. cp = dbc_arg->internal;
  478. if (cp->opd != NULL &&
  479.     (flags == DB_CURRENT || flags == DB_GET_BOTHC ||
  480.     flags == DB_NEXT || flags == DB_NEXT_DUP || flags == DB_PREV)) {
  481. if (tmp_rmw && (ret = dbc_arg->c_am_writelock(dbc_arg)) != 0)
  482. return (ret);
  483. if ((ret = __db_c_idup(cp->opd, &opd, DB_POSITIONI)) != 0)
  484. return (ret);
  485. switch (ret = opd->c_am_get(
  486.     opd, key, data, flags, NULL)) {
  487. case 0:
  488. goto done;
  489. case DB_NOTFOUND:
  490. /*
  491.  * Translate DB_NOTFOUND failures for the DB_NEXT and
  492.  * DB_PREV operations into a subsequent operation on
  493.  * the parent cursor.
  494.  */
  495. if (flags == DB_NEXT || flags == DB_PREV) {
  496. if ((ret = opd->c_close(opd)) != 0)
  497. goto err;
  498. opd = NULL;
  499. break;
  500. }
  501. goto err;
  502. default:
  503. goto err;
  504. }
  505. }
  506. /*
  507.  * Perform an operation on the main cursor.  Duplicate the cursor,
  508.  * upgrade the lock as required, and call the underlying function.
  509.  */
  510. switch (flags) {
  511. case DB_CURRENT:
  512. case DB_GET_BOTHC:
  513. case DB_NEXT:
  514. case DB_NEXT_DUP:
  515. case DB_NEXT_NODUP:
  516. case DB_PREV:
  517. case DB_PREV_NODUP:
  518. tmp_flags = DB_POSITIONI;
  519. break;
  520. default:
  521. tmp_flags = 0;
  522. break;
  523. }
  524. /*
  525.  * If this cursor is going to be closed immediately, we don't
  526.  * need to take precautions to clean it up on error.
  527.  */
  528. if (F_ISSET(dbc_arg, DBC_TRANSIENT))
  529. dbc_n = dbc_arg;
  530. else if ((ret = __db_c_idup(dbc_arg, &dbc_n, tmp_flags)) != 0)
  531. goto err;
  532. if (tmp_rmw)
  533. F_SET(dbc_n, DBC_RMW);
  534. pgno = PGNO_INVALID;
  535. ret = dbc_n->c_am_get(dbc_n, key, data, flags, &pgno);
  536. if (tmp_rmw)
  537. F_CLR(dbc_n, DBC_RMW);
  538. if (ret != 0)
  539. goto err;
  540. cp_n = dbc_n->internal;
  541. /*
  542.  * We may be referencing a new off-page duplicates tree.  Acquire
  543.  * a new cursor and call the underlying function.
  544.  */
  545. if (pgno != PGNO_INVALID) {
  546. if ((ret = __db_c_newopd(dbc_arg, pgno, &cp_n->opd)) != 0)
  547. goto err;
  548. switch (flags) {
  549. case DB_FIRST:
  550. case DB_NEXT:
  551. case DB_NEXT_NODUP:
  552. case DB_SET:
  553. case DB_SET_RECNO:
  554. case DB_SET_RANGE:
  555. tmp_flags = DB_FIRST;
  556. break;
  557. case DB_LAST:
  558. case DB_PREV:
  559. case DB_PREV_NODUP:
  560. tmp_flags = DB_LAST;
  561. break;
  562. case DB_GET_BOTH:
  563. tmp_flags = DB_GET_BOTH;
  564. break;
  565. case DB_GET_BOTHC:
  566. tmp_flags = DB_GET_BOTHC;
  567. break;
  568. default:
  569. ret =
  570.     __db_unknown_flag(dbp->dbenv, "__db_c_get", flags);
  571. goto err;
  572. }
  573. if ((ret = cp_n->opd->c_am_get(
  574.     cp_n->opd, key, data, tmp_flags, NULL)) != 0)
  575. goto err;
  576. }
  577. done: /*
  578.  * Return a key/data item.  The only exception is that we don't return
  579.  * a key if the user already gave us one, that is, if the DB_SET flag
  580.  * was set.  The DB_SET flag is necessary.  In a Btree, the user's key
  581.  * doesn't have to be the same as the key stored the tree, depending on
  582.  * the magic performed by the comparison function.  As we may not have
  583.  * done any key-oriented operation here, the page reference may not be
  584.  * valid.  Fill it in as necessary.  We don't have to worry about any
  585.  * locks, the cursor must already be holding appropriate locks.
  586.  *
  587.  * XXX
  588.  * If not a Btree and DB_SET_RANGE is set, we shouldn't return a key
  589.  * either, should we?
  590.  */
  591. cp_n = dbc_n == NULL ? dbc_arg->internal : dbc_n->internal;
  592. if (!F_ISSET(key, DB_DBT_ISSET)) {
  593. if (cp_n->page == NULL && (ret =
  594.     memp_fget(dbp->mpf, &cp_n->pgno, 0, &cp_n->page)) != 0)
  595. goto err;
  596. if ((ret = __db_ret(dbp, cp_n->page, cp_n->indx,
  597.     key, &dbc_arg->rkey.data, &dbc_arg->rkey.ulen)) != 0)
  598. goto err;
  599. }
  600. dbc = opd != NULL ? opd : cp_n->opd != NULL ? cp_n->opd : dbc_n;
  601. if (!F_ISSET(data, DB_DBT_ISSET)) {
  602. type = TYPE(dbc->internal->page);
  603. ret = __db_ret(dbp, dbc->internal->page, dbc->internal->indx +
  604.     (type == P_LBTREE || type == P_HASH ? O_INDX : 0),
  605.     data, &dbc_arg->rdata.data, &dbc_arg->rdata.ulen);
  606. }
  607. err: /* Don't pass DB_DBT_ISSET back to application level, error or no. */
  608. F_CLR(key, DB_DBT_ISSET);
  609. F_CLR(data, DB_DBT_ISSET);
  610. /* Cleanup and cursor resolution. */
  611. if (opd != NULL) {
  612. if ((t_ret =
  613.      __db_c_cleanup(dbc_arg->internal->opd,
  614.      opd, ret)) != 0 && ret == 0)
  615. ret = t_ret;
  616. }
  617. if ((t_ret = __db_c_cleanup(dbc_arg, dbc_n, ret)) != 0 && ret == 0)
  618. ret = t_ret;
  619. if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT)
  620. CDB_LOCKING_DONE(dbp, dbc_arg);
  621. return (ret);
  622. }
  623. /*
  624.  * __db_c_put --
  625.  * Put using a cursor.
  626.  *
  627.  * PUBLIC: int __db_c_put __P((DBC *, DBT *, DBT *, u_int32_t));
  628.  */
  629. int
  630. __db_c_put(dbc_arg, key, data, flags)
  631. DBC *dbc_arg;
  632. DBT *key, *data;
  633. u_int32_t flags;
  634. {
  635. DB *dbp;
  636. DBC *dbc_n, *opd;
  637. db_pgno_t pgno;
  638. u_int32_t tmp_flags;
  639. int ret, t_ret;
  640. /*
  641.  * Cursor Cleanup Note:
  642.  * All of the cursors passed to the underlying access methods by this
  643.  * routine are duplicated cursors.  On return, any referenced pages
  644.  * will be discarded, and, if the cursor is not intended to be used
  645.  * again, the close function will be called.  So, pages/locks that
  646.  * the cursor references do not need to be resolved by the underlying
  647.  * functions.
  648.  */
  649. dbp = dbc_arg->dbp;
  650. dbc_n = NULL;
  651. PANIC_CHECK(dbp->dbenv);
  652. DB_CHECK_TXN(dbp, dbc_arg->txn);
  653. /* Check for invalid flags. */
  654. if ((ret = __db_cputchk(dbp, key, data, flags,
  655.     F_ISSET(dbp, DB_AM_RDONLY), IS_INITIALIZED(dbc_arg))) != 0)
  656. return (ret);
  657. DEBUG_LWRITE(dbc_arg, dbc_arg->txn, "db_c_put",
  658.     flags == DB_KEYFIRST || flags == DB_KEYLAST ||
  659.     flags == DB_NODUPDATA ? key : NULL, data, flags);
  660. CDB_LOCKING_INIT(dbp, dbc_arg);
  661. /*
  662.  * If we have an off-page duplicates cursor, and the operation applies
  663.  * to it, perform the operation.  Duplicate the cursor and call the
  664.  * underlying function.
  665.  *
  666.  * Off-page duplicate trees are locked in the primary tree, that is,
  667.  * we acquire a write lock in the primary tree and no locks in the
  668.  * off-page dup tree.  If the put operation is done in an off-page
  669.  * duplicate tree, call the primary cursor's upgrade routine first.
  670.  */
  671. if (dbc_arg->internal->opd != NULL &&
  672.     (flags == DB_AFTER || flags == DB_BEFORE || flags == DB_CURRENT)) {
  673. /*
  674.  * A special case for hash off-page duplicates.  Hash doesn't
  675.  * support (and is documented not to support) put operations
  676.  * relative to a cursor which references an already deleted
  677.  * item.  For consistency, apply the same criteria to off-page
  678.  * duplicates as well.
  679.  */
  680. if (dbc_arg->dbtype == DB_HASH && F_ISSET(
  681.     ((BTREE_CURSOR *)(dbc_arg->internal->opd->internal)),
  682.     C_DELETED)) {
  683. ret = DB_NOTFOUND;
  684. goto err;
  685. }
  686. if ((ret = dbc_arg->c_am_writelock(dbc_arg)) != 0)
  687. return (ret);
  688. if ((ret = __db_c_dup(dbc_arg, &dbc_n, DB_POSITIONI)) != 0)
  689. goto err;
  690. opd = dbc_n->internal->opd;
  691. if ((ret = opd->c_am_put(
  692.     opd, key, data, flags, NULL)) != 0)
  693. goto err;
  694. goto done;
  695. }
  696. /*
  697.  * Perform an operation on the main cursor.  Duplicate the cursor,
  698.  * and call the underlying function.
  699.  *
  700.  * XXX: MARGO
  701.  *
  702. tmp_flags = flags == DB_AFTER ||
  703.     flags == DB_BEFORE || flags == DB_CURRENT ? DB_POSITIONI : 0;
  704.  */
  705. tmp_flags = DB_POSITIONI;
  706. /*
  707.  * If this cursor is going to be closed immediately, we don't
  708.  * need to take precautions to clean it up on error.
  709.  */
  710. if (F_ISSET(dbc_arg, DBC_TRANSIENT))
  711. dbc_n = dbc_arg;
  712. else if ((ret = __db_c_idup(dbc_arg, &dbc_n, tmp_flags)) != 0)
  713. goto err;
  714. pgno = PGNO_INVALID;
  715. if ((ret = dbc_n->c_am_put(dbc_n, key, data, flags, &pgno)) != 0)
  716. goto err;
  717. /*
  718.  * We may be referencing a new off-page duplicates tree.  Acquire
  719.  * a new cursor and call the underlying function.
  720.  */
  721. if (pgno != PGNO_INVALID) {
  722. if ((ret = __db_c_newopd(dbc_arg, pgno, &opd)) != 0)
  723. goto err;
  724. dbc_n->internal->opd = opd;
  725. if ((ret = opd->c_am_put(
  726.     opd, key, data, flags, NULL)) != 0)
  727. goto err;
  728. }
  729. done:
  730. err: /* Cleanup and cursor resolution. */
  731. if ((t_ret = __db_c_cleanup(dbc_arg, dbc_n, ret)) != 0 && ret == 0)
  732. ret = t_ret;
  733. CDB_LOCKING_DONE(dbp, dbc_arg);
  734. return (ret);
  735. }
  736. /*
  737.  * __db_duperr()
  738.  * Error message: we don't currently support sorted duplicate duplicates.
  739.  * PUBLIC: int __db_duperr __P((DB *, u_int32_t));
  740.  */
  741. int
  742. __db_duperr(dbp, flags)
  743. DB *dbp;
  744. u_int32_t flags;
  745. {
  746. if (flags != DB_NODUPDATA)
  747. __db_err(dbp->dbenv,
  748.     "Duplicate data items are not supported with sorted data");
  749. return (DB_KEYEXIST);
  750. }
  751. /*
  752.  * __db_c_cleanup --
  753.  * Clean up duplicate cursors.
  754.  */
  755. static int
  756. __db_c_cleanup(dbc, dbc_n, failed)
  757. DBC *dbc, *dbc_n;
  758. int failed;
  759. {
  760. DB *dbp;
  761. DBC *opd;
  762. DBC_INTERNAL *internal;
  763. int ret, t_ret;
  764. dbp = dbc->dbp;
  765. internal = dbc->internal;
  766. ret = 0;
  767. /* Discard any pages we're holding. */
  768. if (internal->page != NULL) {
  769. if ((t_ret =
  770.     memp_fput(dbp->mpf, internal->page, 0)) != 0 && ret == 0)
  771. ret = t_ret;
  772. internal->page = NULL;
  773. }
  774. opd = internal->opd;
  775. if (opd != NULL && opd->internal->page != NULL) {
  776. if ((t_ret = memp_fput(dbp->mpf,
  777.      opd->internal->page, 0)) != 0 && ret == 0)
  778. ret = t_ret;
  779.  opd->internal->page = NULL;
  780. }
  781. /*
  782.  * If dbc_n is NULL, there's no internal cursor swapping to be
  783.  * done and no dbc_n to close--we probably did the entire
  784.  * operation on an offpage duplicate cursor.  Just return.
  785.  */
  786. if (dbc_n == NULL)
  787. return (ret);
  788. /*
  789.  * If dbc is marked DBC_TRANSIENT, we're inside a DB->{put/get}
  790.  * operation, and as an optimization we performed the operation on
  791.  * the main cursor rather than on a duplicated one.  Assert
  792.  * that dbc_n == dbc (i.e., that we really did skip the
  793.  * duplication).  Then just do nothing--even if there was
  794.  * an error, we're about to close the cursor, and the fact that we
  795.  * moved it isn't a user-visible violation of our "cursor
  796.  * stays put on error" rule.
  797.  */
  798. if (F_ISSET(dbc, DBC_TRANSIENT)) {
  799. DB_ASSERT(dbc == dbc_n);
  800. return (ret);
  801. }
  802. if (dbc_n->internal->page != NULL) {
  803. if ((t_ret = memp_fput(dbp->mpf,
  804.     dbc_n->internal->page, 0)) != 0 && ret == 0)
  805. ret = t_ret;
  806. dbc_n->internal->page = NULL;
  807. }
  808. opd = dbc_n->internal->opd;
  809. if (opd != NULL && opd->internal->page != NULL) {
  810. if ((t_ret = memp_fput(dbp->mpf,
  811.      opd->internal->page, 0)) != 0 && ret == 0)
  812. ret = t_ret;
  813. opd->internal->page = NULL;
  814. }
  815. /*
  816.  * If we didn't fail before entering this routine or just now when
  817.  * freeing pages, swap the interesting contents of the old and new
  818.  * cursors.
  819.  */
  820. if (!failed && ret == 0) {
  821. dbc->internal = dbc_n->internal;
  822. dbc_n->internal = internal;
  823. }
  824. /*
  825.  * Close the cursor we don't care about anymore.  The close can fail,
  826.  * but we only expect DB_LOCK_DEADLOCK failures.  This violates our
  827.  * "the cursor is unchanged on error" semantics, but since all you can
  828.  * do with a DB_LOCK_DEADLOCK failure is close the cursor, I believe
  829.  * that's OK.
  830.  *
  831.  * XXX
  832.  * There's no way to recover from failure to close the old cursor.
  833.  * All we can do is move to the new position and return an error.
  834.  *
  835.  * XXX
  836.  * We might want to consider adding a flag to the cursor, so that any
  837.  * subsequent operations other than close just return an error?
  838.  */
  839. if ((t_ret = dbc_n->c_close(dbc_n)) != 0 && ret == 0)
  840. ret = t_ret;
  841. return (ret);
  842. }
  843. /*
  844.  * __db_wrlock_err -- do not have a write lock.
  845.  */
  846. static int
  847. __db_wrlock_err(dbenv)
  848. DB_ENV *dbenv;
  849. {
  850. __db_err(dbenv, "Write attempted on read-only cursor");
  851. return (EPERM);
  852. }