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

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 copyright[] =
  10.     "Copyright (c) 1996-2000nSleepycat Software Inc.  All rights reserved.n";
  11. static const char revid[] =
  12.     "$Id: db185.c,v 11.15 2001/01/23 21:27:03 bostic Exp $";
  13. #endif
  14. #ifndef NO_SYSTEM_INCLUDES
  15. #include <sys/types.h>
  16. #include <fcntl.h>
  17. #include <string.h>
  18. #include <unistd.h>
  19. #endif
  20. #include "db_int.h"
  21. #include "db185_int.h"
  22. static int db185_close __P((DB185 *));
  23. static int db185_compare __P((DB *, const DBT *, const DBT *));
  24. static int db185_del __P((const DB185 *, const DBT185 *, u_int));
  25. static int db185_fd __P((const DB185 *));
  26. static int db185_get __P((const DB185 *, const DBT185 *, DBT185 *, u_int));
  27. static u_int32_t
  28. db185_hash __P((DB *, const void *, u_int32_t));
  29. static void db185_openstderr __P((DB_FH *));
  30. static size_t db185_prefix __P((DB *, const DBT *, const DBT *));
  31. static int db185_put __P((const DB185 *, DBT185 *, const DBT185 *, u_int));
  32. static int db185_seq __P((const DB185 *, DBT185 *, DBT185 *, u_int));
  33. static int db185_sync __P((const DB185 *, u_int));
  34. DB185 *
  35. __db185_open(file, oflags, mode, type, openinfo)
  36. const char *file;
  37. int oflags, mode;
  38. DBTYPE type;
  39. const void *openinfo;
  40. {
  41. const BTREEINFO *bi;
  42. const HASHINFO *hi;
  43. const RECNOINFO *ri;
  44. DB *dbp;
  45. DB185 *db185p;
  46. DB_FH fh;
  47. size_t nw;
  48. int ret;
  49. dbp = NULL;
  50. db185p = NULL;
  51. if ((ret = db_create(&dbp, NULL, 0)) != 0)
  52. goto err;
  53. if ((ret = __os_calloc(NULL, 1, sizeof(DB185), &db185p)) != 0)
  54. goto err;
  55. /*
  56.  * !!!
  57.  * The DBTYPE enum wasn't initialized in DB 185, so it's off-by-one
  58.  * from DB 2.0.
  59.  */
  60. switch (type) {
  61. case 0: /* DB_BTREE */
  62. type = DB_BTREE;
  63. if ((bi = openinfo) != NULL) {
  64. if (bi->flags & ~R_DUP)
  65. goto einval;
  66. if (bi->flags & R_DUP)
  67. (void)dbp->set_flags(dbp, DB_DUP);
  68. if (bi->cachesize != 0)
  69. (void)dbp->set_cachesize
  70.     (dbp, 0, bi->cachesize, 0);
  71. if (bi->minkeypage != 0)
  72. (void)dbp->set_bt_minkey(dbp, bi->minkeypage);
  73. if (bi->psize != 0)
  74. (void)dbp->set_pagesize(dbp, bi->psize);
  75. /*
  76.  * !!!
  77.  * Comparisons and prefix calls work because the DBT
  78.  * structures in 1.85 and 2.0 have the same initial
  79.  * fields.
  80.  */
  81. if (bi->prefix != NULL) {
  82. db185p->prefix = bi->prefix;
  83. dbp->set_bt_prefix(dbp, db185_prefix);
  84. }
  85. if (bi->compare != NULL) {
  86. db185p->compare = bi->compare;
  87. dbp->set_bt_compare(dbp, db185_compare);
  88. }
  89. if (bi->lorder != 0)
  90. dbp->set_lorder(dbp, bi->lorder);
  91. }
  92. break;
  93. case 1: /* DB_HASH */
  94. type = DB_HASH;
  95. if ((hi = openinfo) != NULL) {
  96. if (hi->bsize != 0)
  97. (void)dbp->set_pagesize(dbp, hi->bsize);
  98. if (hi->ffactor != 0)
  99. (void)dbp->set_h_ffactor(dbp, hi->ffactor);
  100. if (hi->nelem != 0)
  101. (void)dbp->set_h_nelem(dbp, hi->nelem);
  102. if (hi->cachesize != 0)
  103. (void)dbp->set_cachesize
  104.     (dbp, 0, hi->cachesize, 0);
  105. if (hi->hash != NULL) {
  106. db185p->hash = hi->hash;
  107. (void)dbp->set_h_hash(dbp, db185_hash);
  108. }
  109. if (hi->lorder != 0)
  110. dbp->set_lorder(dbp, hi->lorder);
  111. }
  112. break;
  113. case 2: /* DB_RECNO */
  114. type = DB_RECNO;
  115. /* DB 1.85 did renumbering by default. */
  116. (void)dbp->set_flags(dbp, DB_RENUMBER);
  117. /*
  118.  * !!!
  119.  * The file name given to DB 1.85 recno is the name of the DB
  120.  * 2.0 backing file.  If the file doesn't exist, create it if
  121.  * the user has the O_CREAT flag set, DB 1.85 did it for you,
  122.  * and DB 2.0 doesn't.
  123.  *
  124.  * !!!
  125.  * Setting the file name to NULL specifies that we're creating
  126.  * a temporary backing file, in DB 2.X.  If we're opening the
  127.  * DB file read-only, change the flags to read-write, because
  128.  * temporary backing files cannot be opened read-only, and DB
  129.  * 2.X will return an error.  We are cheating here -- if the
  130.  * application does a put on the database, it will succeed --
  131.  * although that would be a stupid thing for the application
  132.  * to do.
  133.  *
  134.  * !!!
  135.  * Note, the file name in DB 1.85 was a const -- we don't do
  136.  * that in DB 2.0, so do that cast.
  137.  */
  138. if (file != NULL) {
  139. if (oflags & O_CREAT && __os_exists(file, NULL) != 0)
  140. if (__os_openhandle(NULL, file,
  141.     oflags, mode, &fh) == 0)
  142. (void)__os_closehandle(&fh);
  143. (void)dbp->set_re_source(dbp, file);
  144. if (O_RDONLY)
  145. oflags &= ~O_RDONLY;
  146. oflags |= O_RDWR;
  147. file = NULL;
  148. }
  149. if ((ri = openinfo) != NULL) {
  150. /*
  151.  * !!!
  152.  * We can't support the bfname field.
  153.  */
  154. #define BFMSG "DB: DB 1.85's recno bfname field is not supported.n"
  155. if (ri->bfname != NULL) {
  156. db185_openstderr(&fh);
  157. (void)__os_write(NULL, &fh,
  158.     BFMSG, sizeof(BFMSG) - 1, &nw);
  159. goto einval;
  160. }
  161. if (ri->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
  162. goto einval;
  163. if (ri->flags & R_FIXEDLEN) {
  164. if (ri->bval != 0)
  165. (void)dbp->set_re_pad(dbp, ri->bval);
  166. if (ri->reclen != 0)
  167. (void)dbp->set_re_len(dbp, ri->reclen);
  168. } else
  169. if (ri->bval != 0)
  170. (void)dbp->set_re_delim(dbp, ri->bval);
  171. /*
  172.  * !!!
  173.  * We ignore the R_NOKEY flag, but that's okay, it was
  174.  * only an optimization that was never implemented.
  175.  */
  176. if (ri->flags & R_SNAPSHOT)
  177. (void)dbp->set_flags(dbp, DB_SNAPSHOT);
  178. if (ri->cachesize != 0)
  179. (void)dbp->set_cachesize
  180.     (dbp, 0, ri->cachesize, 0);
  181. if (ri->psize != 0)
  182. (void)dbp->set_pagesize(dbp, ri->psize);
  183. if (ri->lorder != 0)
  184. dbp->set_lorder(dbp, ri->lorder);
  185. }
  186. break;
  187. default:
  188. goto einval;
  189. }
  190. db185p->close = db185_close;
  191. db185p->del = db185_del;
  192. db185p->fd = db185_fd;
  193. db185p->get = db185_get;
  194. db185p->put = db185_put;
  195. db185p->seq = db185_seq;
  196. db185p->sync = db185_sync;
  197. /*
  198.  * Store a reference so we can indirect from the DB 1.85 structure
  199.  * to the underlying DB structure, and vice-versa.  This has to be
  200.  * done BEFORE the DB::open method call because the hash callback
  201.  * is exercised as part of hash database initialiation.
  202.  *
  203.  * XXX
  204.  * Overload the cj_internal field for this purpose.
  205.  */
  206. db185p->dbp = dbp;
  207. dbp->cj_internal = db185p;
  208. /* Open the database. */
  209. if ((ret = dbp->open(dbp,
  210.     file, NULL, type, __db_oflags(oflags), mode)) != 0)
  211. goto err;
  212. /* Create the cursor used for sequential ops. */
  213. if ((ret = dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc, 0)) != 0)
  214. goto err;
  215. return (db185p);
  216. einval: ret = EINVAL;
  217. err: if (db185p != NULL)
  218. __os_free(db185p, sizeof(DB185));
  219. if (dbp != NULL)
  220. (void)dbp->close(dbp, 0);
  221. __os_set_errno(ret);
  222. return (NULL);
  223. }
  224. static int
  225. db185_close(db185p)
  226. DB185 *db185p;
  227. {
  228. DB *dbp;
  229. int ret;
  230. dbp = db185p->dbp;
  231. ret = dbp->close(dbp, 0);
  232. __os_free(db185p, sizeof(DB185));
  233. if (ret == 0)
  234. return (0);
  235. __os_set_errno(ret);
  236. return (-1);
  237. }
  238. static int
  239. db185_del(db185p, key185, flags)
  240. const DB185 *db185p;
  241. const DBT185 *key185;
  242. u_int flags;
  243. {
  244. DB *dbp;
  245. DBT key;
  246. int ret;
  247. dbp = db185p->dbp;
  248. memset(&key, 0, sizeof(key));
  249. key.data = key185->data;
  250. key.size = key185->size;
  251. if (flags & ~R_CURSOR)
  252. goto einval;
  253. if (flags & R_CURSOR)
  254. ret = db185p->dbc->c_del(db185p->dbc, 0);
  255. else
  256. ret = dbp->del(dbp, NULL, &key, 0);
  257. switch (ret) {
  258. case 0:
  259. return (0);
  260. case DB_NOTFOUND:
  261. return (1);
  262. }
  263. __os_set_errno(ret);
  264. return (-1);
  265. einval: __os_set_errno(EINVAL);
  266. return (-1);
  267. }
  268. static int
  269. db185_fd(db185p)
  270. const DB185 *db185p;
  271. {
  272. DB *dbp;
  273. int fd, ret;
  274. dbp = db185p->dbp;
  275. if ((ret = dbp->fd(dbp, &fd)) == 0)
  276. return (fd);
  277. __os_set_errno(ret);
  278. return (-1);
  279. }
  280. static int
  281. db185_get(db185p, key185, data185, flags)
  282. const DB185 *db185p;
  283. const DBT185 *key185;
  284. DBT185 *data185;
  285. u_int flags;
  286. {
  287. DB *dbp;
  288. DBT key, data;
  289. int ret;
  290. dbp = db185p->dbp;
  291. memset(&key, 0, sizeof(key));
  292. key.data = key185->data;
  293. key.size = key185->size;
  294. memset(&data, 0, sizeof(data));
  295. data.data = data185->data;
  296. data.size = data185->size;
  297. if (flags)
  298. goto einval;
  299. switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) {
  300. case 0:
  301. data185->data = data.data;
  302. data185->size = data.size;
  303. return (0);
  304. case DB_NOTFOUND:
  305. return (1);
  306. }
  307. __os_set_errno(ret);
  308. return (-1);
  309. einval: __os_set_errno(EINVAL);
  310. return (-1);
  311. }
  312. static int
  313. db185_put(db185p, key185, data185, flags)
  314. const DB185 *db185p;
  315. DBT185 *key185;
  316. const DBT185 *data185;
  317. u_int flags;
  318. {
  319. DB *dbp;
  320. DBC *dbcp_put;
  321. DBT key, data;
  322. int ret;
  323. dbp = db185p->dbp;
  324. memset(&key, 0, sizeof(key));
  325. key.data = key185->data;
  326. key.size = key185->size;
  327. memset(&data, 0, sizeof(data));
  328. data.data = data185->data;
  329. data.size = data185->size;
  330. switch (flags) {
  331. case 0:
  332. ret = dbp->put(dbp, NULL, &key, &data, 0);
  333. break;
  334. case R_CURSOR:
  335. ret = db185p->dbc->c_put(db185p->dbc, &key, &data, DB_CURRENT);
  336. break;
  337. case R_IAFTER:
  338. case R_IBEFORE:
  339. if (dbp->type != DB_RECNO)
  340. goto einval;
  341. if ((ret = dbp->cursor(dbp, NULL, &dbcp_put, 0)) != 0) {
  342. __os_set_errno(ret);
  343. return (-1);
  344. }
  345. if ((ret =
  346.     dbcp_put->c_get(dbcp_put, &key, &data, DB_SET)) != 0) {
  347. (void)dbcp_put->c_close(dbcp_put);
  348. __os_set_errno(ret);
  349. return (-1);
  350. }
  351. memset(&data, 0, sizeof(data));
  352. data.data = data185->data;
  353. data.size = data185->size;
  354. ret = dbcp_put->c_put(dbcp_put,
  355.     &key, &data, flags == R_IAFTER ? DB_AFTER : DB_BEFORE);
  356. (void)dbcp_put->c_close(dbcp_put);
  357. __os_set_errno(ret);
  358. break;
  359. case R_NOOVERWRITE:
  360. ret = dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE);
  361. break;
  362. case R_SETCURSOR:
  363. if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
  364. goto einval;
  365. if ((ret = dbp->put(dbp, NULL, &key, &data, 0)) != 0)
  366. break;
  367. ret =
  368.     db185p->dbc->c_get(db185p->dbc, &key, &data, DB_SET_RANGE);
  369. break;
  370. default:
  371. goto einval;
  372. }
  373. switch (ret) {
  374. case 0:
  375. key185->data = key.data;
  376. key185->size = key.size;
  377. return (0);
  378. case DB_KEYEXIST:
  379. return (1);
  380. }
  381. __os_set_errno(ret);
  382. return (-1);
  383. einval: __os_set_errno(EINVAL);
  384. return (-1);
  385. }
  386. static int
  387. db185_seq(db185p, key185, data185, flags)
  388. const DB185 *db185p;
  389. DBT185 *key185, *data185;
  390. u_int flags;
  391. {
  392. DB *dbp;
  393. DBT key, data;
  394. int ret;
  395. dbp = db185p->dbp;
  396. memset(&key, 0, sizeof(key));
  397. key.data = key185->data;
  398. key.size = key185->size;
  399. memset(&data, 0, sizeof(data));
  400. data.data = data185->data;
  401. data.size = data185->size;
  402. switch (flags) {
  403. case R_CURSOR:
  404. flags = DB_SET_RANGE;
  405. break;
  406. case R_FIRST:
  407. flags = DB_FIRST;
  408. break;
  409. case R_LAST:
  410. if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
  411. goto einval;
  412. flags = DB_LAST;
  413. break;
  414. case R_NEXT:
  415. flags = DB_NEXT;
  416. break;
  417. case R_PREV:
  418. if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
  419. goto einval;
  420. flags = DB_PREV;
  421. break;
  422. default:
  423. goto einval;
  424. }
  425. switch (ret = db185p->dbc->c_get(db185p->dbc, &key, &data, flags)) {
  426. case 0:
  427. key185->data = key.data;
  428. key185->size = key.size;
  429. data185->data = data.data;
  430. data185->size = data.size;
  431. return (0);
  432. case DB_NOTFOUND:
  433. return (1);
  434. }
  435. __os_set_errno(ret);
  436. return (-1);
  437. einval: __os_set_errno(EINVAL);
  438. return (-1);
  439. }
  440. static int
  441. db185_sync(db185p, flags)
  442. const DB185 *db185p;
  443. u_int flags;
  444. {
  445. DB *dbp;
  446. DB_FH fh;
  447. size_t nw;
  448. int ret;
  449. dbp = db185p->dbp;
  450. switch (flags) {
  451. case 0:
  452. break;
  453. case R_RECNOSYNC:
  454. /*
  455.  * !!!
  456.  * We can't support the R_RECNOSYNC flag.
  457.  */
  458. #define RSMSG "DB: DB 1.85's R_RECNOSYNC sync flag is not supported.n"
  459. db185_openstderr(&fh);
  460. (void)__os_write(NULL, &fh, RSMSG, sizeof(RSMSG) - 1, &nw);
  461. goto einval;
  462. default:
  463. goto einval;
  464. }
  465. if ((ret = dbp->sync(dbp, 0)) == 0)
  466. return (0);
  467. __os_set_errno(ret);
  468. return (-1);
  469. einval: __os_set_errno(EINVAL);
  470. return (-1);
  471. }
  472. static void
  473. db185_openstderr(fhp)
  474. DB_FH *fhp;
  475. {
  476. /* Dummy up the results of an __os_openhandle() on stderr. */
  477. memset(fhp, 0, sizeof(*fhp));
  478. F_SET(fhp, DB_FH_VALID);
  479. #ifndef STDERR_FILENO
  480. #define STDERR_FILENO 2
  481. #endif
  482. fhp->fd = STDERR_FILENO;
  483. }
  484. /*
  485.  * db185_compare --
  486.  * Cutout routine to call the user's Btree comparison function.
  487.  */
  488. static int
  489. db185_compare(dbp, a, b)
  490. DB *dbp;
  491. const DBT *a, *b;
  492. {
  493. return (((DB185 *)dbp->cj_internal)->compare(a, b));
  494. }
  495. /*
  496.  * db185_prefix --
  497.  * Cutout routine to call the user's Btree prefix function.
  498.  */
  499. static size_t
  500. db185_prefix(dbp, a, b)
  501. DB *dbp;
  502. const DBT *a, *b;
  503. {
  504. return (((DB185 *)dbp->cj_internal)->prefix(a, b));
  505. }
  506. /*
  507.  * db185_hash --
  508.  * Cutout routine to call the user's hash function.
  509.  */
  510. static u_int32_t
  511. db185_hash(dbp, key, len)
  512. DB *dbp;
  513. const void *key;
  514. u_int32_t len;
  515. {
  516. return (((DB185 *)dbp->cj_internal)->hash(key, (size_t)len));
  517. }