db185.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:13k
源码类别:

MySQL数据库

开发平台:

Visual C++

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