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

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1996, 1997, 1998, 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: db_iface.c,v 11.34 2001/01/11 18:19:51 bostic Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <errno.h>
  14. #endif
  15. #include "db_int.h"
  16. #include "db_page.h"
  17. #include "db_am.h"
  18. #include "btree.h"
  19. static int __db_curinval __P((const DB_ENV *));
  20. static int __db_rdonly __P((const DB_ENV *, const char *));
  21. static int __dbt_ferr __P((const DB *, const char *, const DBT *, int));
  22. /*
  23.  * __db_cursorchk --
  24.  * Common cursor argument checking routine.
  25.  *
  26.  * PUBLIC: int __db_cursorchk __P((const DB *, u_int32_t, int));
  27.  */
  28. int
  29. __db_cursorchk(dbp, flags, isrdonly)
  30. const DB *dbp;
  31. u_int32_t flags;
  32. int isrdonly;
  33. {
  34. /* Check for invalid function flags. */
  35. switch (flags) {
  36. case 0:
  37. break;
  38. case DB_WRITECURSOR:
  39. if (isrdonly)
  40. return (__db_rdonly(dbp->dbenv, "DB->cursor"));
  41. if (!CDB_LOCKING(dbp->dbenv))
  42. return (__db_ferr(dbp->dbenv, "DB->cursor", 0));
  43. break;
  44. case DB_WRITELOCK:
  45. if (isrdonly)
  46. return (__db_rdonly(dbp->dbenv, "DB->cursor"));
  47. break;
  48. default:
  49. return (__db_ferr(dbp->dbenv, "DB->cursor", 0));
  50. }
  51. return (0);
  52. }
  53. /*
  54.  * __db_ccountchk --
  55.  * Common cursor count argument checking routine.
  56.  *
  57.  * PUBLIC: int __db_ccountchk __P((const DB *, u_int32_t, int));
  58.  */
  59. int
  60. __db_ccountchk(dbp, flags, isvalid)
  61. const DB *dbp;
  62. u_int32_t flags;
  63. int isvalid;
  64. {
  65. /* Check for invalid function flags. */
  66. switch (flags) {
  67. case 0:
  68. break;
  69. default:
  70. return (__db_ferr(dbp->dbenv, "DBcursor->c_count", 0));
  71. }
  72. /*
  73.  * The cursor must be initialized, return EINVAL for an invalid cursor,
  74.  * otherwise 0.
  75.  */
  76. return (isvalid ? 0 : __db_curinval(dbp->dbenv));
  77. }
  78. /*
  79.  * __db_cdelchk --
  80.  * Common cursor delete argument checking routine.
  81.  *
  82.  * PUBLIC: int __db_cdelchk __P((const DB *, u_int32_t, int, int));
  83.  */
  84. int
  85. __db_cdelchk(dbp, flags, isrdonly, isvalid)
  86. const DB *dbp;
  87. u_int32_t flags;
  88. int isrdonly, isvalid;
  89. {
  90. /* Check for changes to a read-only tree. */
  91. if (isrdonly)
  92. return (__db_rdonly(dbp->dbenv, "c_del"));
  93. /* Check for invalid function flags. */
  94. switch (flags) {
  95. case 0:
  96. break;
  97. default:
  98. return (__db_ferr(dbp->dbenv, "DBcursor->c_del", 0));
  99. }
  100. /*
  101.  * The cursor must be initialized, return EINVAL for an invalid cursor,
  102.  * otherwise 0.
  103.  */
  104. return (isvalid ? 0 : __db_curinval(dbp->dbenv));
  105. }
  106. /*
  107.  * __db_cgetchk --
  108.  * Common cursor get argument checking routine.
  109.  *
  110.  * PUBLIC: int __db_cgetchk __P((const DB *, DBT *, DBT *, u_int32_t, int));
  111.  */
  112. int
  113. __db_cgetchk(dbp, key, data, flags, isvalid)
  114. const DB *dbp;
  115. DBT *key, *data;
  116. u_int32_t flags;
  117. int isvalid;
  118. {
  119. int ret;
  120. /*
  121.  * Check for read-modify-write validity.  DB_RMW doesn't make sense
  122.  * with CDB cursors since if you're going to write the cursor, you
  123.  * had to create it with DB_WRITECURSOR.  Regardless, we check for
  124.  * LOCKING_ON and not STD_LOCKING, as we don't want to disallow it.
  125.  * If this changes, confirm that DB does not itself set the DB_RMW
  126.  * flag in a path where CDB may have been configured.
  127.  */
  128. if (LF_ISSET(DB_RMW)) {
  129. if (!LOCKING_ON(dbp->dbenv)) {
  130. __db_err(dbp->dbenv,
  131.     "the DB_RMW flag requires locking");
  132. return (EINVAL);
  133. }
  134. LF_CLR(DB_RMW);
  135. }
  136. /* Check for invalid function flags. */
  137. switch (flags) {
  138. case DB_CONSUME:
  139. case DB_CONSUME_WAIT:
  140. if (dbp->type != DB_QUEUE)
  141. goto err;
  142. break;
  143. case DB_CURRENT:
  144. case DB_FIRST:
  145. case DB_GET_BOTH:
  146. case DB_LAST:
  147. case DB_NEXT:
  148. case DB_NEXT_DUP:
  149. case DB_NEXT_NODUP:
  150. case DB_PREV:
  151. case DB_PREV_NODUP:
  152. case DB_SET:
  153. case DB_SET_RANGE:
  154. break;
  155. case DB_GET_BOTHC:
  156. if (dbp->type == DB_QUEUE)
  157. goto err;
  158. break;
  159. case DB_GET_RECNO:
  160. if (!F_ISSET(dbp, DB_BT_RECNUM))
  161. goto err;
  162. break;
  163. case DB_SET_RECNO:
  164. if (!F_ISSET(dbp, DB_BT_RECNUM))
  165. goto err;
  166. break;
  167. default:
  168. err: return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
  169. }
  170. /* Check for invalid key/data flags. */
  171. if ((ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
  172. return (ret);
  173. if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
  174. return (ret);
  175. /*
  176.  * The cursor must be initialized for DB_CURRENT or DB_NEXT_DUP,
  177.  * return EINVAL for an invalid cursor, otherwise 0.
  178.  */
  179. if (isvalid || (flags != DB_CURRENT && flags != DB_NEXT_DUP))
  180. return (0);
  181. return (__db_curinval(dbp->dbenv));
  182. }
  183. /*
  184.  * __db_cputchk --
  185.  * Common cursor put argument checking routine.
  186.  *
  187.  * PUBLIC: int __db_cputchk __P((const DB *,
  188.  * PUBLIC:    const DBT *, DBT *, u_int32_t, int, int));
  189.  */
  190. int
  191. __db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
  192. const DB *dbp;
  193. const DBT *key;
  194. DBT *data;
  195. u_int32_t flags;
  196. int isrdonly, isvalid;
  197. {
  198. int key_flags, ret;
  199. key_flags = 0;
  200. /* Check for changes to a read-only tree. */
  201. if (isrdonly)
  202. return (__db_rdonly(dbp->dbenv, "c_put"));
  203. /* Check for invalid function flags. */
  204. switch (flags) {
  205. case DB_AFTER:
  206. case DB_BEFORE:
  207. switch (dbp->type) {
  208. case DB_BTREE:
  209. case DB_HASH: /* Only with unsorted duplicates. */
  210. if (!F_ISSET(dbp, DB_AM_DUP))
  211. goto err;
  212. if (dbp->dup_compare != NULL)
  213. goto err;
  214. break;
  215. case DB_QUEUE: /* Not permitted. */
  216. goto err;
  217. case DB_RECNO: /* Only with mutable record numbers. */
  218. if (!F_ISSET(dbp, DB_RE_RENUMBER))
  219. goto err;
  220. key_flags = 1;
  221. break;
  222. default:
  223. goto err;
  224. }
  225. break;
  226. case DB_CURRENT:
  227. /*
  228.  * If there is a comparison function, doing a DB_CURRENT
  229.  * must not change the part of the data item that is used
  230.  * for the comparison.
  231.  */
  232. break;
  233. case DB_NODUPDATA:
  234. if (!F_ISSET(dbp, DB_AM_DUPSORT))
  235. goto err;
  236. /* FALLTHROUGH */
  237. case DB_KEYFIRST:
  238. case DB_KEYLAST:
  239. if (dbp->type == DB_QUEUE || dbp->type == DB_RECNO)
  240. goto err;
  241. key_flags = 1;
  242. break;
  243. default:
  244. err: return (__db_ferr(dbp->dbenv, "DBcursor->c_put", 0));
  245. }
  246. /* Check for invalid key/data flags. */
  247. if (key_flags && (ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
  248. return (ret);
  249. if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
  250. return (ret);
  251. /*
  252.  * The cursor must be initialized for anything other than DB_KEYFIRST
  253.  * and DB_KEYLAST, return EINVAL for an invalid cursor, otherwise 0.
  254.  */
  255. if (isvalid || flags == DB_KEYFIRST ||
  256.     flags == DB_KEYLAST || flags == DB_NODUPDATA)
  257. return (0);
  258. return (__db_curinval(dbp->dbenv));
  259. }
  260. /*
  261.  * __db_closechk --
  262.  * DB->close flag check.
  263.  *
  264.  * PUBLIC: int __db_closechk __P((const DB *, u_int32_t));
  265.  */
  266. int
  267. __db_closechk(dbp, flags)
  268. const DB *dbp;
  269. u_int32_t flags;
  270. {
  271. /* Check for invalid function flags. */
  272. switch (flags) {
  273. case 0:
  274. case DB_NOSYNC:
  275. break;
  276. default:
  277. return (__db_ferr(dbp->dbenv, "DB->close", 0));
  278. }
  279. return (0);
  280. }
  281. /*
  282.  * __db_delchk --
  283.  * Common delete argument checking routine.
  284.  *
  285.  * PUBLIC: int __db_delchk __P((const DB *, DBT *, u_int32_t, int));
  286.  */
  287. int
  288. __db_delchk(dbp, key, flags, isrdonly)
  289. const DB *dbp;
  290. DBT *key;
  291. u_int32_t flags;
  292. int isrdonly;
  293. {
  294. COMPQUIET(key, NULL);
  295. /* Check for changes to a read-only tree. */
  296. if (isrdonly)
  297. return (__db_rdonly(dbp->dbenv, "delete"));
  298. /* Check for invalid function flags. */
  299. switch (flags) {
  300. case 0:
  301. break;
  302. default:
  303. return (__db_ferr(dbp->dbenv, "DB->del", 0));
  304. }
  305. return (0);
  306. }
  307. /*
  308.  * __db_getchk --
  309.  * Common get argument checking routine.
  310.  *
  311.  * PUBLIC: int __db_getchk __P((const DB *, const DBT *, DBT *, u_int32_t));
  312.  */
  313. int
  314. __db_getchk(dbp, key, data, flags)
  315. const DB *dbp;
  316. const DBT *key;
  317. DBT *data;
  318. u_int32_t flags;
  319. {
  320. int ret;
  321. /*
  322.  * Check for read-modify-write validity.  DB_RMW doesn't make sense
  323.  * with CDB cursors since if you're going to write the cursor, you
  324.  * had to create it with DB_WRITECURSOR.  Regardless, we check for
  325.  * LOCKING_ON and not STD_LOCKING, as we don't want to disallow it.
  326.  * If this changes, confirm that DB does not itself set the DB_RMW
  327.  * flag in a path where CDB may have been configured.
  328.  */
  329. if (LF_ISSET(DB_RMW)) {
  330. if (!LOCKING_ON(dbp->dbenv)) {
  331. __db_err(dbp->dbenv,
  332.     "the DB_RMW flag requires locking");
  333. return (EINVAL);
  334. }
  335. LF_CLR(DB_RMW);
  336. }
  337. /* Check for invalid function flags. */
  338. switch (flags) {
  339. case 0:
  340. case DB_GET_BOTH:
  341. break;
  342. case DB_SET_RECNO:
  343. if (!F_ISSET(dbp, DB_BT_RECNUM))
  344. goto err;
  345. break;
  346. case DB_CONSUME:
  347. case DB_CONSUME_WAIT:
  348. if (dbp->type == DB_QUEUE)
  349. break;
  350. /* Fall through */
  351. default:
  352. err: return (__db_ferr(dbp->dbenv, "DB->get", 0));
  353. }
  354. /* Check for invalid key/data flags. */
  355. if ((ret = __dbt_ferr(dbp, "key", key, flags == DB_SET_RECNO)) != 0)
  356. return (ret);
  357. if ((ret = __dbt_ferr(dbp, "data", data, 1)) != 0)
  358. return (ret);
  359. return (0);
  360. }
  361. /*
  362.  * __db_joinchk --
  363.  * Common join argument checking routine.
  364.  *
  365.  * PUBLIC: int __db_joinchk __P((const DB *, DBC * const *, u_int32_t));
  366.  */
  367. int
  368. __db_joinchk(dbp, curslist, flags)
  369. const DB *dbp;
  370. DBC * const *curslist;
  371. u_int32_t flags;
  372. {
  373. DB_TXN *txn;
  374. int i;
  375. switch (flags) {
  376. case 0:
  377. case DB_JOIN_NOSORT:
  378. break;
  379. default:
  380. return (__db_ferr(dbp->dbenv, "DB->join", 0));
  381. }
  382. if (curslist == NULL || curslist[0] == NULL) {
  383. __db_err(dbp->dbenv,
  384.     "At least one secondary cursor must be specified to DB->join");
  385. return (EINVAL);
  386. }
  387. txn = curslist[0]->txn;
  388. for (i = 1; curslist[i] != NULL; i++)
  389. if (curslist[i]->txn != txn) {
  390. __db_err(dbp->dbenv,
  391.     "All secondary cursors must share the same transaction");
  392. return (EINVAL);
  393. }
  394. return (0);
  395. }
  396. /*
  397.  * __db_joingetchk --
  398.  * Common join_get argument checking routine.
  399.  *
  400.  * PUBLIC: int __db_joingetchk __P((const DB *, DBT *, u_int32_t));
  401.  */
  402. int
  403. __db_joingetchk(dbp, key, flags)
  404. const DB *dbp;
  405. DBT *key;
  406. u_int32_t flags;
  407. {
  408. if (LF_ISSET(DB_RMW)) {
  409. if (!LOCKING_ON(dbp->dbenv)) {
  410. __db_err(dbp->dbenv,
  411.     "the DB_RMW flag requires locking");
  412. return (EINVAL);
  413. }
  414. LF_CLR(DB_RMW);
  415. }
  416. switch (flags) {
  417. case 0:
  418. case DB_JOIN_ITEM:
  419. break;
  420. default:
  421. return (__db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
  422. }
  423. /*
  424.  * A partial get of the key of a join cursor don't make much sense;
  425.  * the entire key is necessary to query the primary database
  426.  * and find the datum, and so regardless of the size of the key
  427.  * it would not be a performance improvement.  Since it would require
  428.  * special handling, we simply disallow it.
  429.  *
  430.  * A partial get of the data, however, potentially makes sense (if
  431.  * all possible data are a predictable large structure, for instance)
  432.  * and causes us no headaches, so we permit it.
  433.  */
  434. if (F_ISSET(key, DB_DBT_PARTIAL)) {
  435. __db_err(dbp->dbenv,
  436.     "DB_DBT_PARTIAL may not be set on key during join_get");
  437. return (EINVAL);
  438. }
  439. return (0);
  440. }
  441. /*
  442.  * __db_putchk --
  443.  * Common put argument checking routine.
  444.  *
  445.  * PUBLIC: int __db_putchk
  446.  * PUBLIC:    __P((const DB *, DBT *, const DBT *, u_int32_t, int, int));
  447.  */
  448. int
  449. __db_putchk(dbp, key, data, flags, isrdonly, isdup)
  450. const DB *dbp;
  451. DBT *key;
  452. const DBT *data;
  453. u_int32_t flags;
  454. int isrdonly, isdup;
  455. {
  456. int ret;
  457. /* Check for changes to a read-only tree. */
  458. if (isrdonly)
  459. return (__db_rdonly(dbp->dbenv, "put"));
  460. /* Check for invalid function flags. */
  461. switch (flags) {
  462. case 0:
  463. case DB_NOOVERWRITE:
  464. break;
  465. case DB_APPEND:
  466. if (dbp->type != DB_RECNO && dbp->type != DB_QUEUE)
  467. goto err;
  468. break;
  469. case DB_NODUPDATA:
  470. if (F_ISSET(dbp, DB_AM_DUPSORT))
  471. break;
  472. /* FALLTHROUGH */
  473. default:
  474. err: return (__db_ferr(dbp->dbenv, "DB->put", 0));
  475. }
  476. /* Check for invalid key/data flags. */
  477. if ((ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
  478. return (ret);
  479. if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
  480. return (ret);
  481. /* Check for partial puts in the presence of duplicates. */
  482. if (isdup && F_ISSET(data, DB_DBT_PARTIAL)) {
  483. __db_err(dbp->dbenv,
  484. "a partial put in the presence of duplicates requires a cursor operation");
  485. return (EINVAL);
  486. }
  487. return (0);
  488. }
  489. /*
  490.  * __db_removechk --
  491.  * DB->remove flag check.
  492.  *
  493.  * PUBLIC: int __db_removechk __P((const DB *, u_int32_t));
  494.  */
  495. int
  496. __db_removechk(dbp, flags)
  497. const DB *dbp;
  498. u_int32_t flags;
  499. {
  500. /* Check for invalid function flags. */
  501. switch (flags) {
  502. case 0:
  503. break;
  504. default:
  505. return (__db_ferr(dbp->dbenv, "DB->remove", 0));
  506. }
  507. return (0);
  508. }
  509. /*
  510.  * __db_statchk --
  511.  * Common stat argument checking routine.
  512.  *
  513.  * PUBLIC: int __db_statchk __P((const DB *, u_int32_t));
  514.  */
  515. int
  516. __db_statchk(dbp, flags)
  517. const DB *dbp;
  518. u_int32_t flags;
  519. {
  520. /* Check for invalid function flags. */
  521. switch (flags) {
  522. case 0:
  523. case DB_CACHED_COUNTS:
  524. break;
  525. case DB_RECORDCOUNT:
  526. if (dbp->type == DB_RECNO)
  527. break;
  528. if (dbp->type == DB_BTREE && F_ISSET(dbp, DB_BT_RECNUM))
  529. break;
  530. goto err;
  531. default:
  532. err: return (__db_ferr(dbp->dbenv, "DB->stat", 0));
  533. }
  534. return (0);
  535. }
  536. /*
  537.  * __db_syncchk --
  538.  * Common sync argument checking routine.
  539.  *
  540.  * PUBLIC: int __db_syncchk __P((const DB *, u_int32_t));
  541.  */
  542. int
  543. __db_syncchk(dbp, flags)
  544. const DB *dbp;
  545. u_int32_t flags;
  546. {
  547. /* Check for invalid function flags. */
  548. switch (flags) {
  549. case 0:
  550. break;
  551. default:
  552. return (__db_ferr(dbp->dbenv, "DB->sync", 0));
  553. }
  554. return (0);
  555. }
  556. /*
  557.  * __dbt_ferr --
  558.  * Check a DBT for flag errors.
  559.  */
  560. static int
  561. __dbt_ferr(dbp, name, dbt, check_thread)
  562. const DB *dbp;
  563. const char *name;
  564. const DBT *dbt;
  565. int check_thread;
  566. {
  567. DB_ENV *dbenv;
  568. int ret;
  569. dbenv = dbp->dbenv;
  570. /*
  571.  * Check for invalid DBT flags.  We allow any of the flags to be
  572.  * specified to any DB or DBcursor call so that applications can
  573.  * set DB_DBT_MALLOC when retrieving a data item from a secondary
  574.  * database and then specify that same DBT as a key to a primary
  575.  * database, without having to clear flags.
  576.  */
  577. if ((ret = __db_fchk(dbenv, name, dbt->flags,
  578.     DB_DBT_MALLOC | DB_DBT_DUPOK |
  579.     DB_DBT_REALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL)) != 0)
  580. return (ret);
  581. switch (F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM)) {
  582. case 0:
  583. case DB_DBT_MALLOC:
  584. case DB_DBT_REALLOC:
  585. case DB_DBT_USERMEM:
  586. break;
  587. default:
  588. return (__db_ferr(dbenv, name, 1));
  589. }
  590. if (check_thread && DB_IS_THREADED(dbp) &&
  591.     !F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM)) {
  592. __db_err(dbenv,
  593.     "DB_THREAD mandates memory allocation flag on DBT %s",
  594.     name);
  595. return (EINVAL);
  596. }
  597. return (0);
  598. }
  599. /*
  600.  * __db_rdonly --
  601.  * Common readonly message.
  602.  */
  603. static int
  604. __db_rdonly(dbenv, name)
  605. const DB_ENV *dbenv;
  606. const char *name;
  607. {
  608. __db_err(dbenv, "%s: attempt to modify a read-only tree", name);
  609. return (EACCES);
  610. }
  611. /*
  612.  * __db_curinval
  613.  * Report that a cursor is in an invalid state.
  614.  */
  615. static int
  616. __db_curinval(dbenv)
  617. const DB_ENV *dbenv;
  618. {
  619. __db_err(dbenv,
  620.     "Cursor position must be set before performing this operation");
  621. return (EINVAL);
  622. }