/Modules/bsddbmodule.c

http://unladen-swallow.googlecode.com/ · C · 862 lines · 772 code · 67 blank · 23 comment · 215 complexity · 3a64b37be820f8880087a48014bc6938 MD5 · raw file

  1. /* Berkeley DB interface.
  2. Author: Michael McLay
  3. Hacked: Guido van Rossum
  4. Btree and Recno additions plus sequence methods: David Ely
  5. Hacked by Gustavo Niemeyer <niemeyer@conectiva.com> fixing recno
  6. support.
  7. XXX To do:
  8. - provide a way to access the various hash functions
  9. - support more open flags
  10. The windows port of the Berkeley DB code is hard to find on the web:
  11. www.nightmare.com/software.html
  12. */
  13. #include "Python.h"
  14. #ifdef WITH_THREAD
  15. #include "pythread.h"
  16. #endif
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include <fcntl.h>
  20. #ifdef HAVE_DB_185_H
  21. #include <db_185.h>
  22. #else
  23. #include <db.h>
  24. #endif
  25. /* Please don't include internal header files of the Berkeley db package
  26. (it messes up the info required in the Setup file) */
  27. typedef struct {
  28. PyObject_HEAD
  29. DB *di_bsddb;
  30. int di_size; /* -1 means recompute */
  31. int di_type;
  32. #ifdef WITH_THREAD
  33. PyThread_type_lock di_lock;
  34. #endif
  35. } bsddbobject;
  36. static PyTypeObject Bsddbtype;
  37. #define is_bsddbobject(v) ((v)->ob_type == &Bsddbtype)
  38. #define check_bsddbobject_open(v, r) if ((v)->di_bsddb == NULL) \
  39. { PyErr_SetString(BsddbError, \
  40. "BSDDB object has already been closed"); \
  41. return r; }
  42. static PyObject *BsddbError;
  43. static PyObject *
  44. newdbhashobject(char *file, int flags, int mode,
  45. int bsize, int ffactor, int nelem, int cachesize,
  46. int hash, int lorder)
  47. {
  48. bsddbobject *dp;
  49. HASHINFO info;
  50. if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
  51. return NULL;
  52. info.bsize = bsize;
  53. info.ffactor = ffactor;
  54. info.nelem = nelem;
  55. info.cachesize = cachesize;
  56. info.hash = NULL; /* XXX should derive from hash argument */
  57. info.lorder = lorder;
  58. #ifdef O_BINARY
  59. flags |= O_BINARY;
  60. #endif
  61. Py_BEGIN_ALLOW_THREADS
  62. dp->di_bsddb = dbopen(file, flags, mode, DB_HASH, &info);
  63. Py_END_ALLOW_THREADS
  64. if (dp->di_bsddb == NULL) {
  65. PyErr_SetFromErrno(BsddbError);
  66. #ifdef WITH_THREAD
  67. dp->di_lock = NULL;
  68. #endif
  69. Py_DECREF(dp);
  70. return NULL;
  71. }
  72. dp->di_size = -1;
  73. dp->di_type = DB_HASH;
  74. #ifdef WITH_THREAD
  75. dp->di_lock = PyThread_allocate_lock();
  76. if (dp->di_lock == NULL) {
  77. PyErr_SetString(BsddbError, "can't allocate lock");
  78. Py_DECREF(dp);
  79. return NULL;
  80. }
  81. #endif
  82. return (PyObject *)dp;
  83. }
  84. static PyObject *
  85. newdbbtobject(char *file, int flags, int mode,
  86. int btflags, int cachesize, int maxkeypage,
  87. int minkeypage, int psize, int lorder)
  88. {
  89. bsddbobject *dp;
  90. BTREEINFO info;
  91. if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
  92. return NULL;
  93. info.flags = btflags;
  94. info.cachesize = cachesize;
  95. info.maxkeypage = maxkeypage;
  96. info.minkeypage = minkeypage;
  97. info.psize = psize;
  98. info.lorder = lorder;
  99. info.compare = 0; /* Use default comparison functions, for now..*/
  100. info.prefix = 0;
  101. #ifdef O_BINARY
  102. flags |= O_BINARY;
  103. #endif
  104. Py_BEGIN_ALLOW_THREADS
  105. dp->di_bsddb = dbopen(file, flags, mode, DB_BTREE, &info);
  106. Py_END_ALLOW_THREADS
  107. if (dp->di_bsddb == NULL) {
  108. PyErr_SetFromErrno(BsddbError);
  109. #ifdef WITH_THREAD
  110. dp->di_lock = NULL;
  111. #endif
  112. Py_DECREF(dp);
  113. return NULL;
  114. }
  115. dp->di_size = -1;
  116. dp->di_type = DB_BTREE;
  117. #ifdef WITH_THREAD
  118. dp->di_lock = PyThread_allocate_lock();
  119. if (dp->di_lock == NULL) {
  120. PyErr_SetString(BsddbError, "can't allocate lock");
  121. Py_DECREF(dp);
  122. return NULL;
  123. }
  124. #endif
  125. return (PyObject *)dp;
  126. }
  127. static PyObject *
  128. newdbrnobject(char *file, int flags, int mode,
  129. int rnflags, int cachesize, int psize, int lorder,
  130. size_t reclen, u_char bval, char *bfname)
  131. {
  132. bsddbobject *dp;
  133. RECNOINFO info;
  134. int fd;
  135. if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
  136. return NULL;
  137. info.flags = rnflags;
  138. info.cachesize = cachesize;
  139. info.psize = psize;
  140. info.lorder = lorder;
  141. info.reclen = reclen;
  142. info.bval = bval;
  143. info.bfname = bfname;
  144. #ifdef O_BINARY
  145. flags |= O_BINARY;
  146. #endif
  147. /* This is a hack to avoid a dbopen() bug that happens when
  148. * it fails. */
  149. fd = open(file, flags);
  150. if (fd == -1) {
  151. dp->di_bsddb = NULL;
  152. }
  153. else {
  154. close(fd);
  155. Py_BEGIN_ALLOW_THREADS
  156. dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info);
  157. Py_END_ALLOW_THREADS
  158. }
  159. if (dp->di_bsddb == NULL) {
  160. PyErr_SetFromErrno(BsddbError);
  161. #ifdef WITH_THREAD
  162. dp->di_lock = NULL;
  163. #endif
  164. Py_DECREF(dp);
  165. return NULL;
  166. }
  167. dp->di_size = -1;
  168. dp->di_type = DB_RECNO;
  169. #ifdef WITH_THREAD
  170. dp->di_lock = PyThread_allocate_lock();
  171. if (dp->di_lock == NULL) {
  172. PyErr_SetString(BsddbError, "can't allocate lock");
  173. Py_DECREF(dp);
  174. return NULL;
  175. }
  176. #endif
  177. return (PyObject *)dp;
  178. }
  179. static void
  180. bsddb_dealloc(bsddbobject *dp)
  181. {
  182. #ifdef WITH_THREAD
  183. if (dp->di_lock) {
  184. PyThread_acquire_lock(dp->di_lock, 0);
  185. PyThread_release_lock(dp->di_lock);
  186. PyThread_free_lock(dp->di_lock);
  187. dp->di_lock = NULL;
  188. }
  189. #endif
  190. if (dp->di_bsddb != NULL) {
  191. int status;
  192. Py_BEGIN_ALLOW_THREADS
  193. status = (dp->di_bsddb->close)(dp->di_bsddb);
  194. Py_END_ALLOW_THREADS
  195. if (status != 0)
  196. fprintf(stderr,
  197. "Python bsddb: close errno %d in dealloc\n",
  198. errno);
  199. }
  200. PyObject_Del(dp);
  201. }
  202. #ifdef WITH_THREAD
  203. #define BSDDB_BGN_SAVE(_dp) \
  204. Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(_dp->di_lock,1);
  205. #define BSDDB_END_SAVE(_dp) \
  206. PyThread_release_lock(_dp->di_lock); Py_END_ALLOW_THREADS
  207. #else
  208. #define BSDDB_BGN_SAVE(_dp) Py_BEGIN_ALLOW_THREADS
  209. #define BSDDB_END_SAVE(_dp) Py_END_ALLOW_THREADS
  210. #endif
  211. static Py_ssize_t
  212. bsddb_length(bsddbobject *dp)
  213. {
  214. check_bsddbobject_open(dp, -1);
  215. if (dp->di_size < 0) {
  216. DBT krec, drec;
  217. int status;
  218. int size = 0;
  219. BSDDB_BGN_SAVE(dp)
  220. for (status = (dp->di_bsddb->seq)(dp->di_bsddb,
  221. &krec, &drec,R_FIRST);
  222. status == 0;
  223. status = (dp->di_bsddb->seq)(dp->di_bsddb,
  224. &krec, &drec, R_NEXT))
  225. size++;
  226. BSDDB_END_SAVE(dp)
  227. if (status < 0) {
  228. PyErr_SetFromErrno(BsddbError);
  229. return -1;
  230. }
  231. dp->di_size = size;
  232. }
  233. return dp->di_size;
  234. }
  235. static PyObject *
  236. bsddb_subscript(bsddbobject *dp, PyObject *key)
  237. {
  238. int status;
  239. DBT krec, drec;
  240. char *data,buf[4096];
  241. int size;
  242. PyObject *result;
  243. recno_t recno;
  244. if (dp->di_type == DB_RECNO) {
  245. if (!PyArg_Parse(key, "i", &recno)) {
  246. PyErr_SetString(PyExc_TypeError,
  247. "key type must be integer");
  248. return NULL;
  249. }
  250. krec.data = &recno;
  251. krec.size = sizeof(recno);
  252. }
  253. else {
  254. if (!PyArg_Parse(key, "s#", &data, &size)) {
  255. PyErr_SetString(PyExc_TypeError,
  256. "key type must be string");
  257. return NULL;
  258. }
  259. krec.data = data;
  260. krec.size = size;
  261. }
  262. check_bsddbobject_open(dp, NULL);
  263. BSDDB_BGN_SAVE(dp)
  264. status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
  265. if (status == 0) {
  266. if (drec.size > sizeof(buf)) data = malloc(drec.size);
  267. else data = buf;
  268. if (data!=NULL) memcpy(data,drec.data,drec.size);
  269. }
  270. BSDDB_END_SAVE(dp)
  271. if (data==NULL) return PyErr_NoMemory();
  272. if (status != 0) {
  273. if (status < 0)
  274. PyErr_SetFromErrno(BsddbError);
  275. else
  276. PyErr_SetObject(PyExc_KeyError, key);
  277. return NULL;
  278. }
  279. result = PyString_FromStringAndSize(data, (int)drec.size);
  280. if (data != buf) free(data);
  281. return result;
  282. }
  283. static int
  284. bsddb_ass_sub(bsddbobject *dp, PyObject *key, PyObject *value)
  285. {
  286. int status;
  287. DBT krec, drec;
  288. char *data;
  289. int size;
  290. recno_t recno;
  291. if (dp->di_type == DB_RECNO) {
  292. if (!PyArg_Parse(key, "i", &recno)) {
  293. PyErr_SetString(PyExc_TypeError,
  294. "bsddb key type must be integer");
  295. return -1;
  296. }
  297. krec.data = &recno;
  298. krec.size = sizeof(recno);
  299. }
  300. else {
  301. if (!PyArg_Parse(key, "s#", &data, &size)) {
  302. PyErr_SetString(PyExc_TypeError,
  303. "bsddb key type must be string");
  304. return -1;
  305. }
  306. krec.data = data;
  307. krec.size = size;
  308. }
  309. check_bsddbobject_open(dp, -1);
  310. dp->di_size = -1;
  311. if (value == NULL) {
  312. BSDDB_BGN_SAVE(dp)
  313. status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
  314. BSDDB_END_SAVE(dp)
  315. }
  316. else {
  317. if (!PyArg_Parse(value, "s#", &data, &size)) {
  318. PyErr_SetString(PyExc_TypeError,
  319. "bsddb value type must be string");
  320. return -1;
  321. }
  322. drec.data = data;
  323. drec.size = size;
  324. BSDDB_BGN_SAVE(dp)
  325. status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
  326. BSDDB_END_SAVE(dp)
  327. }
  328. if (status != 0) {
  329. if (status < 0)
  330. PyErr_SetFromErrno(BsddbError);
  331. else
  332. PyErr_SetObject(PyExc_KeyError, key);
  333. return -1;
  334. }
  335. return 0;
  336. }
  337. static PyMappingMethods bsddb_as_mapping = {
  338. (lenfunc)bsddb_length, /*mp_length*/
  339. (binaryfunc)bsddb_subscript, /*mp_subscript*/
  340. (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
  341. };
  342. static PyObject *
  343. bsddb_close(bsddbobject *dp)
  344. {
  345. if (dp->di_bsddb != NULL) {
  346. int status;
  347. BSDDB_BGN_SAVE(dp)
  348. status = (dp->di_bsddb->close)(dp->di_bsddb);
  349. BSDDB_END_SAVE(dp)
  350. if (status != 0) {
  351. dp->di_bsddb = NULL;
  352. PyErr_SetFromErrno(BsddbError);
  353. return NULL;
  354. }
  355. }
  356. dp->di_bsddb = NULL;
  357. Py_INCREF(Py_None);
  358. return Py_None;
  359. }
  360. static PyObject *
  361. bsddb_keys(bsddbobject *dp)
  362. {
  363. PyObject *list, *item=NULL;
  364. DBT krec, drec;
  365. char *data=NULL,buf[4096];
  366. int status;
  367. int err;
  368. check_bsddbobject_open(dp, NULL);
  369. list = PyList_New(0);
  370. if (list == NULL)
  371. return NULL;
  372. BSDDB_BGN_SAVE(dp)
  373. status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
  374. if (status == 0) {
  375. if (krec.size > sizeof(buf)) data = malloc(krec.size);
  376. else data = buf;
  377. if (data != NULL) memcpy(data,krec.data,krec.size);
  378. }
  379. BSDDB_END_SAVE(dp)
  380. if (status == 0 && data==NULL) return PyErr_NoMemory();
  381. while (status == 0) {
  382. if (dp->di_type == DB_RECNO)
  383. item = PyInt_FromLong(*((int*)data));
  384. else
  385. item = PyString_FromStringAndSize(data,
  386. (int)krec.size);
  387. if (data != buf) free(data);
  388. if (item == NULL) {
  389. Py_DECREF(list);
  390. return NULL;
  391. }
  392. err = PyList_Append(list, item);
  393. Py_DECREF(item);
  394. if (err != 0) {
  395. Py_DECREF(list);
  396. return NULL;
  397. }
  398. BSDDB_BGN_SAVE(dp)
  399. status = (dp->di_bsddb->seq)
  400. (dp->di_bsddb, &krec, &drec, R_NEXT);
  401. if (status == 0) {
  402. if (krec.size > sizeof(buf))
  403. data = malloc(krec.size);
  404. else data = buf;
  405. if (data != NULL)
  406. memcpy(data,krec.data,krec.size);
  407. }
  408. BSDDB_END_SAVE(dp)
  409. if (data == NULL) return PyErr_NoMemory();
  410. }
  411. if (status < 0) {
  412. PyErr_SetFromErrno(BsddbError);
  413. Py_DECREF(list);
  414. return NULL;
  415. }
  416. if (dp->di_size < 0)
  417. dp->di_size = PyList_Size(list); /* We just did the work */
  418. return list;
  419. }
  420. static PyObject *
  421. bsddb_has_key(bsddbobject *dp, PyObject *args)
  422. {
  423. DBT krec, drec;
  424. int status;
  425. char *data;
  426. int size;
  427. recno_t recno;
  428. if (dp->di_type == DB_RECNO) {
  429. if (!PyArg_ParseTuple(args, "i;key type must be integer",
  430. &recno)) {
  431. return NULL;
  432. }
  433. krec.data = &recno;
  434. krec.size = sizeof(recno);
  435. }
  436. else {
  437. if (!PyArg_ParseTuple(args, "s#;key type must be string",
  438. &data, &size)) {
  439. return NULL;
  440. }
  441. krec.data = data;
  442. krec.size = size;
  443. }
  444. check_bsddbobject_open(dp, NULL);
  445. BSDDB_BGN_SAVE(dp)
  446. status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
  447. BSDDB_END_SAVE(dp)
  448. if (status < 0) {
  449. PyErr_SetFromErrno(BsddbError);
  450. return NULL;
  451. }
  452. return PyInt_FromLong(status == 0);
  453. }
  454. static PyObject *
  455. bsddb_set_location(bsddbobject *dp, PyObject *key)
  456. {
  457. int status;
  458. DBT krec, drec;
  459. char *data,buf[4096];
  460. int size;
  461. PyObject *result;
  462. recno_t recno;
  463. if (dp->di_type == DB_RECNO) {
  464. if (!PyArg_ParseTuple(key, "i;key type must be integer",
  465. &recno)) {
  466. return NULL;
  467. }
  468. krec.data = &recno;
  469. krec.size = sizeof(recno);
  470. }
  471. else {
  472. if (!PyArg_ParseTuple(key, "s#;key type must be string",
  473. &data, &size)) {
  474. return NULL;
  475. }
  476. krec.data = data;
  477. krec.size = size;
  478. }
  479. check_bsddbobject_open(dp, NULL);
  480. BSDDB_BGN_SAVE(dp)
  481. status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
  482. if (status == 0) {
  483. if (drec.size > sizeof(buf)) data = malloc(drec.size);
  484. else data = buf;
  485. if (data!=NULL) memcpy(data,drec.data,drec.size);
  486. }
  487. BSDDB_END_SAVE(dp)
  488. if (data==NULL) return PyErr_NoMemory();
  489. if (status != 0) {
  490. if (status < 0)
  491. PyErr_SetFromErrno(BsddbError);
  492. else
  493. PyErr_SetObject(PyExc_KeyError, key);
  494. return NULL;
  495. }
  496. if (dp->di_type == DB_RECNO)
  497. result = Py_BuildValue("is#", *((int*)krec.data),
  498. data, drec.size);
  499. else
  500. result = Py_BuildValue("s#s#", krec.data, krec.size,
  501. data, drec.size);
  502. if (data != buf) free(data);
  503. return result;
  504. }
  505. static PyObject *
  506. bsddb_seq(bsddbobject *dp, int sequence_request)
  507. {
  508. int status;
  509. DBT krec, drec;
  510. char *kdata=NULL,kbuf[4096];
  511. char *ddata=NULL,dbuf[4096];
  512. PyObject *result;
  513. check_bsddbobject_open(dp, NULL);
  514. krec.data = 0;
  515. krec.size = 0;
  516. BSDDB_BGN_SAVE(dp)
  517. status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec,
  518. &drec, sequence_request);
  519. if (status == 0) {
  520. if (krec.size > sizeof(kbuf)) kdata = malloc(krec.size);
  521. else kdata = kbuf;
  522. if (kdata != NULL) memcpy(kdata,krec.data,krec.size);
  523. if (drec.size > sizeof(dbuf)) ddata = malloc(drec.size);
  524. else ddata = dbuf;
  525. if (ddata != NULL) memcpy(ddata,drec.data,drec.size);
  526. }
  527. BSDDB_END_SAVE(dp)
  528. if (status == 0) {
  529. if ((kdata == NULL) || (ddata == NULL))
  530. return PyErr_NoMemory();
  531. }
  532. else {
  533. /* (status != 0) */
  534. if (status < 0)
  535. PyErr_SetFromErrno(BsddbError);
  536. else
  537. PyErr_SetString(PyExc_KeyError, "no key/data pairs");
  538. return NULL;
  539. }
  540. if (dp->di_type == DB_RECNO)
  541. result = Py_BuildValue("is#", *((int*)kdata),
  542. ddata, drec.size);
  543. else
  544. result = Py_BuildValue("s#s#", kdata, krec.size,
  545. ddata, drec.size);
  546. if (kdata != kbuf) free(kdata);
  547. if (ddata != dbuf) free(ddata);
  548. return result;
  549. }
  550. static PyObject *
  551. bsddb_next(bsddbobject *dp)
  552. {
  553. return bsddb_seq(dp, R_NEXT);
  554. }
  555. static PyObject *
  556. bsddb_previous(bsddbobject *dp)
  557. {
  558. return bsddb_seq(dp, R_PREV);
  559. }
  560. static PyObject *
  561. bsddb_first(bsddbobject *dp)
  562. {
  563. return bsddb_seq(dp, R_FIRST);
  564. }
  565. static PyObject *
  566. bsddb_last(bsddbobject *dp)
  567. {
  568. return bsddb_seq(dp, R_LAST);
  569. }
  570. static PyObject *
  571. bsddb_sync(bsddbobject *dp)
  572. {
  573. int status;
  574. check_bsddbobject_open(dp, NULL);
  575. BSDDB_BGN_SAVE(dp)
  576. status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
  577. BSDDB_END_SAVE(dp)
  578. if (status != 0) {
  579. PyErr_SetFromErrno(BsddbError);
  580. return NULL;
  581. }
  582. return PyInt_FromLong(status = 0);
  583. }
  584. static PyMethodDef bsddb_methods[] = {
  585. {"close", (PyCFunction)bsddb_close, METH_NOARGS},
  586. {"keys", (PyCFunction)bsddb_keys, METH_NOARGS},
  587. {"has_key", (PyCFunction)bsddb_has_key, METH_VARARGS},
  588. {"set_location", (PyCFunction)bsddb_set_location, METH_VARARGS},
  589. {"next", (PyCFunction)bsddb_next, METH_NOARGS},
  590. {"previous", (PyCFunction)bsddb_previous, METH_NOARGS},
  591. {"first", (PyCFunction)bsddb_first, METH_NOARGS},
  592. {"last", (PyCFunction)bsddb_last, METH_NOARGS},
  593. {"sync", (PyCFunction)bsddb_sync, METH_NOARGS},
  594. {NULL, NULL} /* sentinel */
  595. };
  596. static PyObject *
  597. bsddb_getattr(PyObject *dp, char *name)
  598. {
  599. return Py_FindMethod(bsddb_methods, dp, name);
  600. }
  601. static PyTypeObject Bsddbtype = {
  602. PyObject_HEAD_INIT(NULL)
  603. 0,
  604. "bsddb.bsddb",
  605. sizeof(bsddbobject),
  606. 0,
  607. (destructor)bsddb_dealloc, /*tp_dealloc*/
  608. 0, /*tp_print*/
  609. (getattrfunc)bsddb_getattr, /*tp_getattr*/
  610. 0, /*tp_setattr*/
  611. 0, /*tp_compare*/
  612. 0, /*tp_repr*/
  613. 0, /*tp_as_number*/
  614. 0, /*tp_as_sequence*/
  615. &bsddb_as_mapping, /*tp_as_mapping*/
  616. };
  617. static PyObject *
  618. bsdhashopen(PyObject *self, PyObject *args)
  619. {
  620. char *file;
  621. char *flag = NULL;
  622. int flags = O_RDONLY;
  623. int mode = 0666;
  624. int bsize = 0;
  625. int ffactor = 0;
  626. int nelem = 0;
  627. int cachesize = 0;
  628. int hash = 0; /* XXX currently ignored */
  629. int lorder = 0;
  630. if (!PyArg_ParseTuple(args, "z|siiiiiii:hashopen",
  631. &file, &flag, &mode,
  632. &bsize, &ffactor, &nelem, &cachesize,
  633. &hash, &lorder))
  634. return NULL;
  635. if (flag != NULL) {
  636. /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
  637. if (flag[0] == 'r')
  638. flags = O_RDONLY;
  639. else if (flag[0] == 'w')
  640. flags = O_RDWR;
  641. else if (flag[0] == 'c')
  642. flags = O_RDWR|O_CREAT;
  643. else if (flag[0] == 'n')
  644. flags = O_RDWR|O_CREAT|O_TRUNC;
  645. else {
  646. PyErr_SetString(BsddbError,
  647. "Flag should begin with 'r', 'w', 'c' or 'n'");
  648. return NULL;
  649. }
  650. if (flag[1] == 'l') {
  651. #if defined(O_EXLOCK) && defined(O_SHLOCK)
  652. if (flag[0] == 'r')
  653. flags |= O_SHLOCK;
  654. else
  655. flags |= O_EXLOCK;
  656. #else
  657. PyErr_SetString(BsddbError,
  658. "locking not supported on this platform");
  659. return NULL;
  660. #endif
  661. }
  662. }
  663. return newdbhashobject(file, flags, mode,
  664. bsize, ffactor, nelem, cachesize, hash, lorder);
  665. }
  666. static PyObject *
  667. bsdbtopen(PyObject *self, PyObject *args)
  668. {
  669. char *file;
  670. char *flag = NULL;
  671. int flags = O_RDONLY;
  672. int mode = 0666;
  673. int cachesize = 0;
  674. int maxkeypage = 0;
  675. int minkeypage = 0;
  676. int btflags = 0;
  677. unsigned int psize = 0;
  678. int lorder = 0;
  679. if (!PyArg_ParseTuple(args, "z|siiiiiii:btopen",
  680. &file, &flag, &mode,
  681. &btflags, &cachesize, &maxkeypage, &minkeypage,
  682. &psize, &lorder))
  683. return NULL;
  684. if (flag != NULL) {
  685. /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
  686. if (flag[0] == 'r')
  687. flags = O_RDONLY;
  688. else if (flag[0] == 'w')
  689. flags = O_RDWR;
  690. else if (flag[0] == 'c')
  691. flags = O_RDWR|O_CREAT;
  692. else if (flag[0] == 'n')
  693. flags = O_RDWR|O_CREAT|O_TRUNC;
  694. else {
  695. PyErr_SetString(BsddbError,
  696. "Flag should begin with 'r', 'w', 'c' or 'n'");
  697. return NULL;
  698. }
  699. if (flag[1] == 'l') {
  700. #if defined(O_EXLOCK) && defined(O_SHLOCK)
  701. if (flag[0] == 'r')
  702. flags |= O_SHLOCK;
  703. else
  704. flags |= O_EXLOCK;
  705. #else
  706. PyErr_SetString(BsddbError,
  707. "locking not supported on this platform");
  708. return NULL;
  709. #endif
  710. }
  711. }
  712. return newdbbtobject(file, flags, mode,
  713. btflags, cachesize, maxkeypage, minkeypage,
  714. psize, lorder);
  715. }
  716. static PyObject *
  717. bsdrnopen(PyObject *self, PyObject *args)
  718. {
  719. char *file;
  720. char *flag = NULL;
  721. int flags = O_RDONLY;
  722. int mode = 0666;
  723. int cachesize = 0;
  724. int rnflags = 0;
  725. unsigned int psize = 0;
  726. int lorder = 0;
  727. size_t reclen = 0;
  728. char *bval = "";
  729. char *bfname = NULL;
  730. if (!PyArg_ParseTuple(args, "z|siiiiiiss:rnopen",
  731. &file, &flag, &mode,
  732. &rnflags, &cachesize, &psize, &lorder,
  733. &reclen, &bval, &bfname))
  734. return NULL;
  735. if (flag != NULL) {
  736. /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
  737. if (flag[0] == 'r')
  738. flags = O_RDONLY;
  739. else if (flag[0] == 'w')
  740. flags = O_RDWR;
  741. else if (flag[0] == 'c')
  742. flags = O_RDWR|O_CREAT;
  743. else if (flag[0] == 'n')
  744. flags = O_RDWR|O_CREAT|O_TRUNC;
  745. else {
  746. PyErr_SetString(BsddbError,
  747. "Flag should begin with 'r', 'w', 'c' or 'n'");
  748. return NULL;
  749. }
  750. if (flag[1] == 'l') {
  751. #if defined(O_EXLOCK) && defined(O_SHLOCK)
  752. if (flag[0] == 'r')
  753. flags |= O_SHLOCK;
  754. else
  755. flags |= O_EXLOCK;
  756. #else
  757. PyErr_SetString(BsddbError,
  758. "locking not supported on this platform");
  759. return NULL;
  760. #endif
  761. }
  762. else if (flag[1] != '\0') {
  763. PyErr_SetString(BsddbError,
  764. "Flag char 2 should be 'l' or absent");
  765. return NULL;
  766. }
  767. }
  768. return newdbrnobject(file, flags, mode, rnflags, cachesize,
  769. psize, lorder, reclen, bval[0], bfname);
  770. }
  771. static PyMethodDef bsddbmodule_methods[] = {
  772. {"hashopen", (PyCFunction)bsdhashopen, METH_VARARGS},
  773. {"btopen", (PyCFunction)bsdbtopen, METH_VARARGS},
  774. {"rnopen", (PyCFunction)bsdrnopen, METH_VARARGS},
  775. /* strictly for use by dbhhash!!! */
  776. {"open", (PyCFunction)bsdhashopen, METH_VARARGS},
  777. {0, 0},
  778. };
  779. PyMODINIT_FUNC
  780. initbsddb185(void) {
  781. PyObject *m, *d;
  782. if (PyErr_WarnPy3k("the bsddb185 module has been removed in "
  783. "Python 3.0", 2) < 0)
  784. return;
  785. Bsddbtype.ob_type = &PyType_Type;
  786. m = Py_InitModule("bsddb185", bsddbmodule_methods);
  787. if (m == NULL)
  788. return;
  789. d = PyModule_GetDict(m);
  790. BsddbError = PyErr_NewException("bsddb.error", NULL, NULL);
  791. if (BsddbError != NULL)
  792. PyDict_SetItemString(d, "error", BsddbError);
  793. }