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

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. /*
  8.  * Copyright (c) 1990, 1993
  9.  * Margo Seltzer.  All rights reserved.
  10.  */
  11. /*
  12.  * Copyright (c) 1990, 1993
  13.  * The Regents of the University of California.  All rights reserved.
  14.  *
  15.  * This code is derived from software contributed to Berkeley by
  16.  * Margo Seltzer.
  17.  *
  18.  * Redistribution and use in source and binary forms, with or without
  19.  * modification, are permitted provided that the following conditions
  20.  * are met:
  21.  * 1. Redistributions of source code must retain the above copyright
  22.  *    notice, this list of conditions and the following disclaimer.
  23.  * 2. Redistributions in binary form must reproduce the above copyright
  24.  *    notice, this list of conditions and the following disclaimer in the
  25.  *    documentation and/or other materials provided with the distribution.
  26.  * 3. Neither the name of the University nor the names of its contributors
  27.  *    may be used to endorse or promote products derived from this software
  28.  *    without specific prior written permission.
  29.  *
  30.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  31.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  34.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  38.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  39.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  40.  * SUCH DAMAGE.
  41.  */
  42. #include "db_config.h"
  43. #ifndef lint
  44. static const char revid[] = "$Id: dbm.c,v 11.14 2002/02/22 16:11:10 bostic Exp $";
  45. #endif /* not lint */
  46. #ifndef NO_SYSTEM_INCLUDES
  47. #include <sys/types.h>
  48. #include <fcntl.h>
  49. #include <string.h>
  50. #endif
  51. #define DB_DBM_HSEARCH 1
  52. #include "db_int.h"
  53. /*
  54.  *
  55.  * This package provides dbm and ndbm compatible interfaces to DB.
  56.  *
  57.  * EXTERN: #if DB_DBM_HSEARCH != 0
  58.  *
  59.  * EXTERN: int  __db_ndbm_clearerr __P((DBM *));
  60.  * EXTERN: void  __db_ndbm_close __P((DBM *));
  61.  * EXTERN: int  __db_ndbm_delete __P((DBM *, datum));
  62.  * EXTERN: int  __db_ndbm_dirfno __P((DBM *));
  63.  * EXTERN: int  __db_ndbm_error __P((DBM *));
  64.  * EXTERN: datum __db_ndbm_fetch __P((DBM *, datum));
  65.  * EXTERN: datum __db_ndbm_firstkey __P((DBM *));
  66.  * EXTERN: datum __db_ndbm_nextkey __P((DBM *));
  67.  * EXTERN: DBM *__db_ndbm_open __P((const char *, int, int));
  68.  * EXTERN: int  __db_ndbm_pagfno __P((DBM *));
  69.  * EXTERN: int  __db_ndbm_rdonly __P((DBM *));
  70.  * EXTERN: int  __db_ndbm_store __P((DBM *, datum, datum, int));
  71.  *
  72.  * EXTERN: int  __db_dbm_close __P((void));
  73.  * EXTERN: int  __db_dbm_dbrdonly __P((void));
  74.  * EXTERN: int  __db_dbm_delete __P((datum));
  75.  * EXTERN: int  __db_dbm_dirf __P((void));
  76.  * EXTERN: datum __db_dbm_fetch __P((datum));
  77.  * EXTERN: datum __db_dbm_firstkey __P((void));
  78.  * EXTERN: int  __db_dbm_init __P((char *));
  79.  * EXTERN: datum __db_dbm_nextkey __P((datum));
  80.  * EXTERN: int  __db_dbm_pagf __P((void));
  81.  * EXTERN: int  __db_dbm_store __P((datum, datum));
  82.  *
  83.  * EXTERN: #endif
  84.  */
  85. /*
  86.  * The DBM routines, which call the NDBM routines.
  87.  */
  88. static DBM *__cur_db;
  89. static void __db_no_open __P((void));
  90. int
  91. __db_dbm_init(file)
  92. char *file;
  93. {
  94. if (__cur_db != NULL)
  95. (void)dbm_close(__cur_db);
  96. if ((__cur_db =
  97.     dbm_open(file, O_CREAT | O_RDWR, __db_omode("rw----"))) != NULL)
  98. return (0);
  99. if ((__cur_db = dbm_open(file, O_RDONLY, 0)) != NULL)
  100. return (0);
  101. return (-1);
  102. }
  103. int
  104. __db_dbm_close()
  105. {
  106. if (__cur_db != NULL) {
  107. dbm_close(__cur_db);
  108. __cur_db = NULL;
  109. }
  110. return (0);
  111. }
  112. datum
  113. __db_dbm_fetch(key)
  114. datum key;
  115. {
  116. datum item;
  117. if (__cur_db == NULL) {
  118. __db_no_open();
  119. item.dptr = 0;
  120. return (item);
  121. }
  122. return (dbm_fetch(__cur_db, key));
  123. }
  124. datum
  125. __db_dbm_firstkey()
  126. {
  127. datum item;
  128. if (__cur_db == NULL) {
  129. __db_no_open();
  130. item.dptr = 0;
  131. return (item);
  132. }
  133. return (dbm_firstkey(__cur_db));
  134. }
  135. datum
  136. __db_dbm_nextkey(key)
  137. datum key;
  138. {
  139. datum item;
  140. COMPQUIET(key.dsize, 0);
  141. if (__cur_db == NULL) {
  142. __db_no_open();
  143. item.dptr = 0;
  144. return (item);
  145. }
  146. return (dbm_nextkey(__cur_db));
  147. }
  148. int
  149. __db_dbm_delete(key)
  150. datum key;
  151. {
  152. if (__cur_db == NULL) {
  153. __db_no_open();
  154. return (-1);
  155. }
  156. return (dbm_delete(__cur_db, key));
  157. }
  158. int
  159. __db_dbm_store(key, dat)
  160. datum key, dat;
  161. {
  162. if (__cur_db == NULL) {
  163. __db_no_open();
  164. return (-1);
  165. }
  166. return (dbm_store(__cur_db, key, dat, DBM_REPLACE));
  167. }
  168. static void
  169. __db_no_open()
  170. {
  171. (void)fprintf(stderr, "dbm: no open database.n");
  172. }
  173. /*
  174.  * This package provides dbm and ndbm compatible interfaces to DB.
  175.  *
  176.  * The NDBM routines, which call the DB routines.
  177.  */
  178. /*
  179.  * Returns:
  180.  * *DBM on success
  181.  *  NULL on failure
  182.  */
  183. DBM *
  184. __db_ndbm_open(file, oflags, mode)
  185. const char *file;
  186. int oflags, mode;
  187. {
  188. DB *dbp;
  189. DBC *dbc;
  190. int ret;
  191. char path[MAXPATHLEN];
  192. /*
  193.  * !!!
  194.  * Don't use sprintf(3)/snprintf(3) -- the former is dangerous, and
  195.  * the latter isn't standard, and we're manipulating strings handed
  196.  * us by the application.
  197.  */
  198. if (strlen(file) + strlen(DBM_SUFFIX) + 1 > sizeof(path)) {
  199. __os_set_errno(ENAMETOOLONG);
  200. return (NULL);
  201. }
  202. (void)strcpy(path, file);
  203. (void)strcat(path, DBM_SUFFIX);
  204. if ((ret = db_create(&dbp, NULL, 0)) != 0) {
  205. __os_set_errno(ret);
  206. return (NULL);
  207. }
  208. /*
  209.  * !!!
  210.  * The historic ndbm library corrected for opening O_WRONLY.
  211.  */
  212. if (oflags & O_WRONLY) {
  213. oflags &= ~O_WRONLY;
  214. oflags |= O_RDWR;
  215. }
  216. if ((ret = dbp->set_pagesize(dbp, 4096)) != 0 ||
  217.     (ret = dbp->set_h_ffactor(dbp, 40)) != 0 ||
  218.     (ret = dbp->set_h_nelem(dbp, 1)) != 0 ||
  219.     (ret = dbp->open(dbp, NULL,
  220.     path, NULL, DB_HASH, __db_oflags(oflags), mode)) != 0) {
  221. __os_set_errno(ret);
  222. return (NULL);
  223. }
  224. if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) {
  225. (void)dbp->close(dbp, 0);
  226. __os_set_errno(ret);
  227. return (NULL);
  228. }
  229. return ((DBM *)dbc);
  230. }
  231. /*
  232.  * Returns:
  233.  * Nothing.
  234.  */
  235. void
  236. __db_ndbm_close(dbm)
  237. DBM *dbm;
  238. {
  239. DBC *dbc;
  240. dbc = (DBC *)dbm;
  241. (void)dbc->dbp->close(dbc->dbp, 0);
  242. }
  243. /*
  244.  * Returns:
  245.  * DATUM on success
  246.  * NULL on failure
  247.  */
  248. datum
  249. __db_ndbm_fetch(dbm, key)
  250. DBM *dbm;
  251. datum key;
  252. {
  253. DBC *dbc;
  254. DBT _key, _data;
  255. datum data;
  256. int ret;
  257. dbc = (DBC *)dbm;
  258. memset(&_key, 0, sizeof(DBT));
  259. memset(&_data, 0, sizeof(DBT));
  260. _key.size = key.dsize;
  261. _key.data = key.dptr;
  262. /*
  263.  * Note that we can't simply use the dbc we have to do a c_get/SET,
  264.  * because that cursor is the one used for sequential iteration and
  265.  * it has to remain stable in the face of intervening gets and puts.
  266.  */
  267. if ((ret = dbc->dbp->get(dbc->dbp, NULL, &_key, &_data, 0)) == 0) {
  268. data.dptr = _data.data;
  269. data.dsize = _data.size;
  270. } else {
  271. data.dptr = NULL;
  272. data.dsize = 0;
  273. if (ret == DB_NOTFOUND)
  274. __os_set_errno(ENOENT);
  275. else {
  276. __os_set_errno(ret);
  277. F_SET(dbc->dbp, DB_AM_DBM_ERROR);
  278. }
  279. }
  280. return (data);
  281. }
  282. /*
  283.  * Returns:
  284.  * DATUM on success
  285.  * NULL on failure
  286.  */
  287. datum
  288. __db_ndbm_firstkey(dbm)
  289. DBM *dbm;
  290. {
  291. DBC *dbc;
  292. DBT _key, _data;
  293. datum key;
  294. int ret;
  295. dbc = (DBC *)dbm;
  296. memset(&_key, 0, sizeof(DBT));
  297. memset(&_data, 0, sizeof(DBT));
  298. if ((ret = dbc->c_get(dbc, &_key, &_data, DB_FIRST)) == 0) {
  299. key.dptr = _key.data;
  300. key.dsize = _key.size;
  301. } else {
  302. key.dptr = NULL;
  303. key.dsize = 0;
  304. if (ret == DB_NOTFOUND)
  305. __os_set_errno(ENOENT);
  306. else {
  307. __os_set_errno(ret);
  308. F_SET(dbc->dbp, DB_AM_DBM_ERROR);
  309. }
  310. }
  311. return (key);
  312. }
  313. /*
  314.  * Returns:
  315.  * DATUM on success
  316.  * NULL on failure
  317.  */
  318. datum
  319. __db_ndbm_nextkey(dbm)
  320. DBM *dbm;
  321. {
  322. DBC *dbc;
  323. DBT _key, _data;
  324. datum key;
  325. int ret;
  326. dbc = (DBC *)dbm;
  327. memset(&_key, 0, sizeof(DBT));
  328. memset(&_data, 0, sizeof(DBT));
  329. if ((ret = dbc->c_get(dbc, &_key, &_data, DB_NEXT)) == 0) {
  330. key.dptr = _key.data;
  331. key.dsize = _key.size;
  332. } else {
  333. key.dptr = NULL;
  334. key.dsize = 0;
  335. if (ret == DB_NOTFOUND)
  336. __os_set_errno(ENOENT);
  337. else {
  338. __os_set_errno(ret);
  339. F_SET(dbc->dbp, DB_AM_DBM_ERROR);
  340. }
  341. }
  342. return (key);
  343. }
  344. /*
  345.  * Returns:
  346.  *  0 on success
  347.  * <0 failure
  348.  */
  349. int
  350. __db_ndbm_delete(dbm, key)
  351. DBM *dbm;
  352. datum key;
  353. {
  354. DBC *dbc;
  355. DBT _key;
  356. int ret;
  357. dbc = (DBC *)dbm;
  358. memset(&_key, 0, sizeof(DBT));
  359. _key.data = key.dptr;
  360. _key.size = key.dsize;
  361. if ((ret = dbc->dbp->del(dbc->dbp, NULL, &_key, 0)) == 0)
  362. return (0);
  363. if (ret == DB_NOTFOUND)
  364. __os_set_errno(ENOENT);
  365. else {
  366. __os_set_errno(ret);
  367. F_SET(dbc->dbp, DB_AM_DBM_ERROR);
  368. }
  369. return (-1);
  370. }
  371. /*
  372.  * Returns:
  373.  *  0 on success
  374.  * <0 failure
  375.  *  1 if DBM_INSERT and entry exists
  376.  */
  377. int
  378. __db_ndbm_store(dbm, key, data, flags)
  379. DBM *dbm;
  380. datum key, data;
  381. int flags;
  382. {
  383. DBC *dbc;
  384. DBT _key, _data;
  385. int ret;
  386. dbc = (DBC *)dbm;
  387. memset(&_key, 0, sizeof(DBT));
  388. _key.data = key.dptr;
  389. _key.size = key.dsize;
  390. memset(&_data, 0, sizeof(DBT));
  391. _data.data = data.dptr;
  392. _data.size = data.dsize;
  393. if ((ret = dbc->dbp->put(dbc->dbp, NULL,
  394.     &_key, &_data, flags == DBM_INSERT ? DB_NOOVERWRITE : 0)) == 0)
  395. return (0);
  396. if (ret == DB_KEYEXIST)
  397. return (1);
  398. __os_set_errno(ret);
  399. F_SET(dbc->dbp, DB_AM_DBM_ERROR);
  400. return (-1);
  401. }
  402. int
  403. __db_ndbm_error(dbm)
  404. DBM *dbm;
  405. {
  406. DBC *dbc;
  407. dbc = (DBC *)dbm;
  408. return (F_ISSET(dbc->dbp, DB_AM_DBM_ERROR));
  409. }
  410. int
  411. __db_ndbm_clearerr(dbm)
  412. DBM *dbm;
  413. {
  414. DBC *dbc;
  415. dbc = (DBC *)dbm;
  416. F_CLR(dbc->dbp, DB_AM_DBM_ERROR);
  417. return (0);
  418. }
  419. /*
  420.  * Returns:
  421.  * 1 if read-only
  422.  * 0 if not read-only
  423.  */
  424. int
  425. __db_ndbm_rdonly(dbm)
  426. DBM *dbm;
  427. {
  428. DBC *dbc;
  429. dbc = (DBC *)dbm;
  430. return (F_ISSET(dbc->dbp, DB_AM_RDONLY) ? 1 : 0);
  431. }
  432. /*
  433.  * XXX
  434.  * We only have a single file descriptor that we can return, not two.  Return
  435.  * the same one for both files.  Hopefully, the user is using it for locking
  436.  * and picked one to use at random.
  437.  */
  438. int
  439. __db_ndbm_dirfno(dbm)
  440. DBM *dbm;
  441. {
  442. return (dbm_pagfno(dbm));
  443. }
  444. int
  445. __db_ndbm_pagfno(dbm)
  446. DBM *dbm;
  447. {
  448. DBC *dbc;
  449. int fd;
  450. dbc = (DBC *)dbm;
  451. (void)dbc->dbp->fd(dbc->dbp, &fd);
  452. return (fd);
  453. }