blob: d76762647a7ff8db8d413e62f4206e7c426a9cf5 [file] [log] [blame]
Guido van Rossum1100dca1995-08-30 23:43:03 +00001/* Berkeley DB interface.
2 Author: Michael McLay
3 Hacked: Guido van Rossum
4 Btree and Recno additions plus sequence methods: David Ely
Fred Drakeed5e8232001-02-27 18:56:46 +00005 Hacked by Gustavo Niemeyer <niemeyer@conectiva.com> fixing recno
6 support.
Guido van Rossum1100dca1995-08-30 23:43:03 +00007
8 XXX To do:
Guido van Rossum1100dca1995-08-30 23:43:03 +00009 - provide a way to access the various hash functions
10 - support more open flags
Guido van Rossum675e9941999-09-20 13:28:18 +000011
12 The windows port of the Berkeley DB code is hard to find on the web:
13 www.nightmare.com/software.html
14*/
Guido van Rossum1100dca1995-08-30 23:43:03 +000015
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000016#include "Python.h"
Guido van Rossum4f199ea1998-04-09 20:56:35 +000017#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000018#include "pythread.h"
Guido van Rossum4f199ea1998-04-09 20:56:35 +000019#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +000020
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
Fred Drakec9cb8472000-08-31 16:11:07 +000024#ifdef HAVE_DB_185_H
25#include <db_185.h>
26#else
Guido van Rossum1100dca1995-08-30 23:43:03 +000027#include <db.h>
Fred Drakec9cb8472000-08-31 16:11:07 +000028#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +000029/* Please don't include internal header files of the Berkeley db package
30 (it messes up the info required in the Setup file) */
31
32typedef struct {
Roger E. Massed9240d11997-01-16 22:05:33 +000033 PyObject_HEAD
34 DB *di_bsddb;
35 int di_size; /* -1 means recompute */
Fred Drakeed5e8232001-02-27 18:56:46 +000036 int di_type;
Guido van Rossum4f199ea1998-04-09 20:56:35 +000037#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +000038 PyThread_type_lock di_lock;
Guido van Rossum4f199ea1998-04-09 20:56:35 +000039#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +000040} bsddbobject;
41
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000042staticforward PyTypeObject Bsddbtype;
Guido van Rossum1100dca1995-08-30 23:43:03 +000043
44#define is_bsddbobject(v) ((v)->ob_type == &Bsddbtype)
Fred Drakeed5e8232001-02-27 18:56:46 +000045#define check_bsddbobject_open(v, r) if ((v)->di_bsddb == NULL) \
Fred Drakec9f7c262001-02-19 21:16:00 +000046 { PyErr_SetString(BsddbError, \
47 "BSDDB object has already been closed"); \
Fred Drakeed5e8232001-02-27 18:56:46 +000048 return r; }
Guido van Rossum1100dca1995-08-30 23:43:03 +000049
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000050static PyObject *BsddbError;
Guido van Rossum1100dca1995-08-30 23:43:03 +000051
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000052static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +000053newdbhashobject(char *file, int flags, int mode,
Fred Drakec9f7c262001-02-19 21:16:00 +000054 int bsize, int ffactor, int nelem, int cachesize,
55 int hash, int lorder)
Guido van Rossum1100dca1995-08-30 23:43:03 +000056{
Roger E. Massed9240d11997-01-16 22:05:33 +000057 bsddbobject *dp;
58 HASHINFO info;
Guido van Rossum1100dca1995-08-30 23:43:03 +000059
Guido van Rossumb18618d2000-05-03 23:44:39 +000060 if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
Roger E. Massed9240d11997-01-16 22:05:33 +000061 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +000062
Roger E. Massed9240d11997-01-16 22:05:33 +000063 info.bsize = bsize;
64 info.ffactor = ffactor;
65 info.nelem = nelem;
66 info.cachesize = cachesize;
67 info.hash = NULL; /* XXX should derive from hash argument */
68 info.lorder = lorder;
Guido van Rossum1100dca1995-08-30 23:43:03 +000069
Guido van Rossum6beb4791996-09-11 23:22:25 +000070#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +000071 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +000072#endif
Guido van Rossum4f199ea1998-04-09 20:56:35 +000073 Py_BEGIN_ALLOW_THREADS
74 dp->di_bsddb = dbopen(file, flags, mode, DB_HASH, &info);
75 Py_END_ALLOW_THREADS
76 if (dp->di_bsddb == NULL) {
Roger E. Massed9240d11997-01-16 22:05:33 +000077 PyErr_SetFromErrno(BsddbError);
Guido van Rossum4f199ea1998-04-09 20:56:35 +000078#ifdef WITH_THREAD
79 dp->di_lock = NULL;
80#endif
Roger E. Massed9240d11997-01-16 22:05:33 +000081 Py_DECREF(dp);
82 return NULL;
83 }
Guido van Rossum1100dca1995-08-30 23:43:03 +000084
Roger E. Massed9240d11997-01-16 22:05:33 +000085 dp->di_size = -1;
Fred Drakeed5e8232001-02-27 18:56:46 +000086 dp->di_type = DB_HASH;
87
Guido van Rossum4f199ea1998-04-09 20:56:35 +000088#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +000089 dp->di_lock = PyThread_allocate_lock();
Guido van Rossum4f199ea1998-04-09 20:56:35 +000090 if (dp->di_lock == NULL) {
91 PyErr_SetString(BsddbError, "can't allocate lock");
92 Py_DECREF(dp);
93 return NULL;
94 }
95#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +000096
Roger E. Massed9240d11997-01-16 22:05:33 +000097 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +000098}
99
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000100static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000101newdbbtobject(char *file, int flags, int mode,
Fred Drakec9f7c262001-02-19 21:16:00 +0000102 int btflags, int cachesize, int maxkeypage,
103 int minkeypage, int psize, int lorder)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000104{
Roger E. Massed9240d11997-01-16 22:05:33 +0000105 bsddbobject *dp;
106 BTREEINFO info;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000107
Guido van Rossumb18618d2000-05-03 23:44:39 +0000108 if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
Roger E. Massed9240d11997-01-16 22:05:33 +0000109 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000110
Roger E. Massed9240d11997-01-16 22:05:33 +0000111 info.flags = btflags;
112 info.cachesize = cachesize;
113 info.maxkeypage = maxkeypage;
114 info.minkeypage = minkeypage;
115 info.psize = psize;
116 info.lorder = lorder;
117 info.compare = 0; /* Use default comparison functions, for now..*/
118 info.prefix = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000119
Guido van Rossum6beb4791996-09-11 23:22:25 +0000120#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +0000121 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +0000122#endif
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000123 Py_BEGIN_ALLOW_THREADS
124 dp->di_bsddb = dbopen(file, flags, mode, DB_BTREE, &info);
125 Py_END_ALLOW_THREADS
126 if (dp->di_bsddb == NULL) {
Roger E. Massed9240d11997-01-16 22:05:33 +0000127 PyErr_SetFromErrno(BsddbError);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000128#ifdef WITH_THREAD
129 dp->di_lock = NULL;
130#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000131 Py_DECREF(dp);
132 return NULL;
133 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000134
Roger E. Massed9240d11997-01-16 22:05:33 +0000135 dp->di_size = -1;
Fred Drakeed5e8232001-02-27 18:56:46 +0000136 dp->di_type = DB_BTREE;
137
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000138#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +0000139 dp->di_lock = PyThread_allocate_lock();
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000140 if (dp->di_lock == NULL) {
141 PyErr_SetString(BsddbError, "can't allocate lock");
142 Py_DECREF(dp);
143 return NULL;
144 }
145#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +0000146
Roger E. Massed9240d11997-01-16 22:05:33 +0000147 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000148}
149
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000150static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000151newdbrnobject(char *file, int flags, int mode,
Fred Drakec9f7c262001-02-19 21:16:00 +0000152 int rnflags, int cachesize, int psize, int lorder,
153 size_t reclen, u_char bval, char *bfname)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000154{
Roger E. Massed9240d11997-01-16 22:05:33 +0000155 bsddbobject *dp;
156 RECNOINFO info;
Fred Drakeed5e8232001-02-27 18:56:46 +0000157 int fd;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000158
Guido van Rossumb18618d2000-05-03 23:44:39 +0000159 if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
Roger E. Massed9240d11997-01-16 22:05:33 +0000160 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000161
Roger E. Massed9240d11997-01-16 22:05:33 +0000162 info.flags = rnflags;
163 info.cachesize = cachesize;
164 info.psize = psize;
165 info.lorder = lorder;
166 info.reclen = reclen;
167 info.bval = bval;
168 info.bfname = bfname;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000169
Guido van Rossum6beb4791996-09-11 23:22:25 +0000170#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +0000171 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +0000172#endif
Fred Drakeed5e8232001-02-27 18:56:46 +0000173 /* This is a hack to avoid a dbopen() bug that happens when
174 * it fails. */
175 fd = open(file, flags);
176 if (fd == -1) {
177 dp->di_bsddb = NULL;
178 }
179 else {
180 close(fd);
181 Py_BEGIN_ALLOW_THREADS
182 dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info);
183 Py_END_ALLOW_THREADS
184 }
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000185 if (dp->di_bsddb == NULL) {
Roger E. Massed9240d11997-01-16 22:05:33 +0000186 PyErr_SetFromErrno(BsddbError);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000187#ifdef WITH_THREAD
188 dp->di_lock = NULL;
189#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000190 Py_DECREF(dp);
191 return NULL;
192 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000193
Roger E. Massed9240d11997-01-16 22:05:33 +0000194 dp->di_size = -1;
Fred Drakeed5e8232001-02-27 18:56:46 +0000195 dp->di_type = DB_RECNO;
196
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000197#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +0000198 dp->di_lock = PyThread_allocate_lock();
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000199 if (dp->di_lock == NULL) {
200 PyErr_SetString(BsddbError, "can't allocate lock");
201 Py_DECREF(dp);
202 return NULL;
203 }
204#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +0000205
Roger E. Massed9240d11997-01-16 22:05:33 +0000206 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000207}
208
Guido van Rossum1100dca1995-08-30 23:43:03 +0000209static void
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000210bsddb_dealloc(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000211{
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000212#ifdef WITH_THREAD
213 if (dp->di_lock) {
Guido van Rossum65d5b571998-12-21 19:32:43 +0000214 PyThread_acquire_lock(dp->di_lock, 0);
215 PyThread_release_lock(dp->di_lock);
216 PyThread_free_lock(dp->di_lock);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000217 dp->di_lock = NULL;
218 }
219#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000220 if (dp->di_bsddb != NULL) {
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000221 int status;
222 Py_BEGIN_ALLOW_THREADS
223 status = (dp->di_bsddb->close)(dp->di_bsddb);
224 Py_END_ALLOW_THREADS
225 if (status != 0)
Roger E. Massed9240d11997-01-16 22:05:33 +0000226 fprintf(stderr,
227 "Python bsddb: close errno %d in dealloc\n",
228 errno);
229 }
Guido van Rossumb18618d2000-05-03 23:44:39 +0000230 PyObject_Del(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000231}
232
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000233#ifdef WITH_THREAD
Fred Drakec9f7c262001-02-19 21:16:00 +0000234#define BSDDB_BGN_SAVE(_dp) \
235 Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(_dp->di_lock,1);
236#define BSDDB_END_SAVE(_dp) \
237 PyThread_release_lock(_dp->di_lock); Py_END_ALLOW_THREADS
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000238#else
239#define BSDDB_BGN_SAVE(_dp) Py_BEGIN_ALLOW_THREADS
240#define BSDDB_END_SAVE(_dp) Py_END_ALLOW_THREADS
241#endif
242
Guido van Rossum1100dca1995-08-30 23:43:03 +0000243static int
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000244bsddb_length(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000245{
Fred Drakeed5e8232001-02-27 18:56:46 +0000246 check_bsddbobject_open(dp, -1);
Roger E. Massed9240d11997-01-16 22:05:33 +0000247 if (dp->di_size < 0) {
248 DBT krec, drec;
249 int status;
250 int size = 0;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000251 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000252 for (status = (dp->di_bsddb->seq)(dp->di_bsddb,
253 &krec, &drec,R_FIRST);
254 status == 0;
255 status = (dp->di_bsddb->seq)(dp->di_bsddb,
256 &krec, &drec, R_NEXT))
257 size++;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000258 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000259 if (status < 0) {
260 PyErr_SetFromErrno(BsddbError);
261 return -1;
262 }
263 dp->di_size = size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000264 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000265 return dp->di_size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000266}
267
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000268static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000269bsddb_subscript(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000270{
Roger E. Massed9240d11997-01-16 22:05:33 +0000271 int status;
272 DBT krec, drec;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000273 char *data,buf[4096];
Roger E. Massed9240d11997-01-16 22:05:33 +0000274 int size;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000275 PyObject *result;
Fred Drakeed5e8232001-02-27 18:56:46 +0000276 recno_t recno;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000277
Fred Drakeed5e8232001-02-27 18:56:46 +0000278 if (dp->di_type == DB_RECNO) {
279 if (!PyArg_Parse(key, "i", &recno)) {
280 PyErr_SetString(PyExc_TypeError,
281 "key type must be integer");
282 return NULL;
283 }
284 krec.data = &recno;
285 krec.size = sizeof(recno);
286 }
287 else {
288 if (!PyArg_Parse(key, "s#", &data, &size)) {
289 PyErr_SetString(PyExc_TypeError,
290 "key type must be string");
291 return NULL;
292 }
293 krec.data = data;
294 krec.size = size;
295 }
296 check_bsddbobject_open(dp, NULL);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000297
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000298 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000299 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000300 if (status == 0) {
301 if (drec.size > sizeof(buf)) data = malloc(drec.size);
302 else data = buf;
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000303 if (data!=NULL) memcpy(data,drec.data,drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000304 }
305 BSDDB_END_SAVE(dp)
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000306 if (data==NULL) return PyErr_NoMemory();
Roger E. Massed9240d11997-01-16 22:05:33 +0000307 if (status != 0) {
308 if (status < 0)
309 PyErr_SetFromErrno(BsddbError);
310 else
311 PyErr_SetObject(PyExc_KeyError, key);
312 return NULL;
313 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000314
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000315 result = PyString_FromStringAndSize(data, (int)drec.size);
316 if (data != buf) free(data);
317 return result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000318}
319
320static int
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000321bsddb_ass_sub(bsddbobject *dp, PyObject *key, PyObject *value)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000322{
Roger E. Massed9240d11997-01-16 22:05:33 +0000323 int status;
324 DBT krec, drec;
325 char *data;
326 int size;
Fred Drakeed5e8232001-02-27 18:56:46 +0000327 recno_t recno;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000328
Fred Drakeed5e8232001-02-27 18:56:46 +0000329 if (dp->di_type == DB_RECNO) {
330 if (!PyArg_Parse(key, "i", &recno)) {
331 PyErr_SetString(PyExc_TypeError,
332 "bsddb key type must be integer");
333 return -1;
334 }
335 krec.data = &recno;
336 krec.size = sizeof(recno);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000337 }
Fred Drakeed5e8232001-02-27 18:56:46 +0000338 else {
339 if (!PyArg_Parse(key, "s#", &data, &size)) {
340 PyErr_SetString(PyExc_TypeError,
341 "bsddb key type must be string");
342 return -1;
343 }
344 krec.data = data;
345 krec.size = size;
346 }
347 check_bsddbobject_open(dp, -1);
Roger E. Massed9240d11997-01-16 22:05:33 +0000348 dp->di_size = -1;
349 if (value == NULL) {
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000350 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000351 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000352 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000353 }
354 else {
355 if (!PyArg_Parse(value, "s#", &data, &size)) {
356 PyErr_SetString(PyExc_TypeError,
357 "bsddb value type must be string");
358 return -1;
359 }
360 drec.data = data;
361 drec.size = size;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000362 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000363 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000364 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000365 }
366 if (status != 0) {
367 if (status < 0)
368 PyErr_SetFromErrno(BsddbError);
369 else
370 PyErr_SetObject(PyExc_KeyError, key);
371 return -1;
372 }
373 return 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000374}
375
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000376static PyMappingMethods bsddb_as_mapping = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000377 (inquiry)bsddb_length, /*mp_length*/
378 (binaryfunc)bsddb_subscript, /*mp_subscript*/
379 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000380};
381
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000382static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000383bsddb_close(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000384{
Roger E. Massed9240d11997-01-16 22:05:33 +0000385 if (dp->di_bsddb != NULL) {
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000386 int status;
387 BSDDB_BGN_SAVE(dp)
388 status = (dp->di_bsddb->close)(dp->di_bsddb);
389 BSDDB_END_SAVE(dp)
390 if (status != 0) {
Roger E. Massed9240d11997-01-16 22:05:33 +0000391 dp->di_bsddb = NULL;
392 PyErr_SetFromErrno(BsddbError);
393 return NULL;
394 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000395 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000396 dp->di_bsddb = NULL;
397 Py_INCREF(Py_None);
398 return Py_None;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000399}
400
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000401static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000402bsddb_keys(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000403{
Fred Drakeed5e8232001-02-27 18:56:46 +0000404 PyObject *list, *item=NULL;
Roger E. Massed9240d11997-01-16 22:05:33 +0000405 DBT krec, drec;
Guido van Rossum730806d1998-04-10 22:27:42 +0000406 char *data=NULL,buf[4096];
Roger E. Massed9240d11997-01-16 22:05:33 +0000407 int status;
408 int err;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000409
Fred Drakeed5e8232001-02-27 18:56:46 +0000410 check_bsddbobject_open(dp, NULL);
Roger E. Massed9240d11997-01-16 22:05:33 +0000411 list = PyList_New(0);
412 if (list == NULL)
413 return NULL;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000414 BSDDB_BGN_SAVE(dp)
415 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
416 if (status == 0) {
417 if (krec.size > sizeof(buf)) data = malloc(krec.size);
418 else data = buf;
Fred Drakeed5e8232001-02-27 18:56:46 +0000419 if (data != NULL) memcpy(data,krec.data,krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000420 }
421 BSDDB_END_SAVE(dp)
Guido van Rossumec24c1b2001-03-22 00:19:22 +0000422 if (status == 0 && data==NULL) return PyErr_NoMemory();
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000423 while (status == 0) {
Fred Drakeed5e8232001-02-27 18:56:46 +0000424 if (dp->di_type == DB_RECNO)
425 item = PyInt_FromLong(*((int*)data));
426 else
427 item = PyString_FromStringAndSize(data,
428 (int)krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000429 if (data != buf) free(data);
Roger E. Massed9240d11997-01-16 22:05:33 +0000430 if (item == NULL) {
431 Py_DECREF(list);
432 return NULL;
433 }
434 err = PyList_Append(list, item);
435 Py_DECREF(item);
436 if (err != 0) {
437 Py_DECREF(list);
438 return NULL;
439 }
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000440 BSDDB_BGN_SAVE(dp)
Fred Drakec9f7c262001-02-19 21:16:00 +0000441 status = (dp->di_bsddb->seq)
442 (dp->di_bsddb, &krec, &drec, R_NEXT);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000443 if (status == 0) {
Fred Drakec9f7c262001-02-19 21:16:00 +0000444 if (krec.size > sizeof(buf))
445 data = malloc(krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000446 else data = buf;
Fred Drakec9f7c262001-02-19 21:16:00 +0000447 if (data != NULL)
448 memcpy(data,krec.data,krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000449 }
450 BSDDB_END_SAVE(dp)
Fred Drakec9f7c262001-02-19 21:16:00 +0000451 if (data == NULL) return PyErr_NoMemory();
Guido van Rossum1100dca1995-08-30 23:43:03 +0000452 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000453 if (status < 0) {
454 PyErr_SetFromErrno(BsddbError);
455 Py_DECREF(list);
456 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000457 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000458 if (dp->di_size < 0)
459 dp->di_size = PyList_Size(list); /* We just did the work */
460 return list;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000461}
462
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000463static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000464bsddb_has_key(bsddbobject *dp, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000465{
Roger E. Massed9240d11997-01-16 22:05:33 +0000466 DBT krec, drec;
467 int status;
468 char *data;
469 int size;
Fred Drakeed5e8232001-02-27 18:56:46 +0000470 recno_t recno;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000471
Fred Drakeed5e8232001-02-27 18:56:46 +0000472 if (dp->di_type == DB_RECNO) {
473 if (!PyArg_Parse(args, "i", &recno)) {
474 PyErr_SetString(PyExc_TypeError,
475 "key type must be integer");
476 return NULL;
477 }
478 krec.data = &recno;
479 krec.size = sizeof(recno);
480 }
481 else {
482 if (!PyArg_Parse(args, "s#", &data, &size)) {
483 PyErr_SetString(PyExc_TypeError,
484 "key type must be string");
485 return NULL;
486 }
487 krec.data = data;
488 krec.size = size;
489 }
490 check_bsddbobject_open(dp, NULL);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000491
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000492 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000493 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000494 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000495 if (status < 0) {
496 PyErr_SetFromErrno(BsddbError);
497 return NULL;
498 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000499
Roger E. Massed9240d11997-01-16 22:05:33 +0000500 return PyInt_FromLong(status == 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000501}
502
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000503static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000504bsddb_set_location(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000505{
Roger E. Massed9240d11997-01-16 22:05:33 +0000506 int status;
507 DBT krec, drec;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000508 char *data,buf[4096];
Roger E. Massed9240d11997-01-16 22:05:33 +0000509 int size;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000510 PyObject *result;
Fred Drakeed5e8232001-02-27 18:56:46 +0000511 recno_t recno;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000512
Fred Drakeed5e8232001-02-27 18:56:46 +0000513 if (dp->di_type == DB_RECNO) {
514 if (!PyArg_Parse(key, "i", &recno)) {
515 PyErr_SetString(PyExc_TypeError,
516 "key type must be integer");
517 return NULL;
518 }
519 krec.data = &recno;
520 krec.size = sizeof(recno);
521 }
522 else {
523 if (!PyArg_Parse(key, "s#", &data, &size)) {
524 PyErr_SetString(PyExc_TypeError,
525 "key type must be string");
526 return NULL;
527 }
528 krec.data = data;
529 krec.size = size;
530 }
531 check_bsddbobject_open(dp, NULL);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000532
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000533 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000534 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000535 if (status == 0) {
536 if (drec.size > sizeof(buf)) data = malloc(drec.size);
537 else data = buf;
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000538 if (data!=NULL) memcpy(data,drec.data,drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000539 }
540 BSDDB_END_SAVE(dp)
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000541 if (data==NULL) return PyErr_NoMemory();
Roger E. Massed9240d11997-01-16 22:05:33 +0000542 if (status != 0) {
543 if (status < 0)
544 PyErr_SetFromErrno(BsddbError);
545 else
546 PyErr_SetObject(PyExc_KeyError, key);
547 return NULL;
548 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000549
Fred Drakeed5e8232001-02-27 18:56:46 +0000550 if (dp->di_type == DB_RECNO)
551 result = Py_BuildValue("is#", *((int*)krec.data),
552 data, drec.size);
553 else
554 result = Py_BuildValue("s#s#", krec.data, krec.size,
555 data, drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000556 if (data != buf) free(data);
557 return result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000558}
559
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000560static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000561bsddb_seq(bsddbobject *dp, int sequence_request)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000562{
Roger E. Massed9240d11997-01-16 22:05:33 +0000563 int status;
564 DBT krec, drec;
Guido van Rossum730806d1998-04-10 22:27:42 +0000565 char *kdata=NULL,kbuf[4096];
566 char *ddata=NULL,dbuf[4096];
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000567 PyObject *result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000568
Fred Drakeed5e8232001-02-27 18:56:46 +0000569 check_bsddbobject_open(dp, NULL);
Roger E. Massed9240d11997-01-16 22:05:33 +0000570 krec.data = 0;
571 krec.size = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000572
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000573 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000574 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec,
575 &drec, sequence_request);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000576 if (status == 0) {
577 if (krec.size > sizeof(kbuf)) kdata = malloc(krec.size);
578 else kdata = kbuf;
Fred Drakeed5e8232001-02-27 18:56:46 +0000579 if (kdata != NULL) memcpy(kdata,krec.data,krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000580 if (drec.size > sizeof(dbuf)) ddata = malloc(drec.size);
581 else ddata = dbuf;
Fred Drakeed5e8232001-02-27 18:56:46 +0000582 if (ddata != NULL) memcpy(ddata,drec.data,drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000583 }
584 BSDDB_END_SAVE(dp)
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000585 if (status == 0) {
Fred Drakeed5e8232001-02-27 18:56:46 +0000586 if ((kdata == NULL) || (ddata == NULL))
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000587 return PyErr_NoMemory();
588 }
589 else {
590 /* (status != 0) */
Roger E. Massed9240d11997-01-16 22:05:33 +0000591 if (status < 0)
592 PyErr_SetFromErrno(BsddbError);
593 else
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000594 PyErr_SetString(PyExc_KeyError, "no key/data pairs");
Roger E. Massed9240d11997-01-16 22:05:33 +0000595 return NULL;
596 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000597
Fred Drakeed5e8232001-02-27 18:56:46 +0000598 if (dp->di_type == DB_RECNO)
599 result = Py_BuildValue("is#", *((int*)kdata),
600 ddata, drec.size);
601 else
602 result = Py_BuildValue("s#s#", kdata, krec.size,
603 ddata, drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000604 if (kdata != kbuf) free(kdata);
605 if (ddata != dbuf) free(ddata);
606 return result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000607}
608
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000609static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000610bsddb_next(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000611{
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000612 return bsddb_seq(dp, R_NEXT);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000613}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000614static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000615bsddb_previous(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000616{
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000617 return bsddb_seq(dp, R_PREV);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000618}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000619static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000620bsddb_first(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000621{
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000622 return bsddb_seq(dp, R_FIRST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000623}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000624static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000625bsddb_last(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000626{
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000627 return bsddb_seq(dp, R_LAST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000628}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000629static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000630bsddb_sync(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000631{
Roger E. Massed9240d11997-01-16 22:05:33 +0000632 int status;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000633
Fred Drakeed5e8232001-02-27 18:56:46 +0000634 check_bsddbobject_open(dp, NULL);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000635 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000636 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000637 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000638 if (status != 0) {
639 PyErr_SetFromErrno(BsddbError);
640 return NULL;
641 }
642 return PyInt_FromLong(status = 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000643}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000644static PyMethodDef bsddb_methods[] = {
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000645 {"close", (PyCFunction)bsddb_close, METH_NOARGS},
646 {"keys", (PyCFunction)bsddb_keys, METH_NOARGS},
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000647 {"has_key", (PyCFunction)bsddb_has_key, METH_OLDARGS},
648 {"set_location", (PyCFunction)bsddb_set_location, METH_OLDARGS},
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000649 {"next", (PyCFunction)bsddb_next, METH_NOARGS},
650 {"previous", (PyCFunction)bsddb_previous, METH_NOARGS},
651 {"first", (PyCFunction)bsddb_first, METH_NOARGS},
652 {"last", (PyCFunction)bsddb_last, METH_NOARGS},
653 {"sync", (PyCFunction)bsddb_sync, METH_NOARGS},
Roger E. Massed9240d11997-01-16 22:05:33 +0000654 {NULL, NULL} /* sentinel */
Guido van Rossum1100dca1995-08-30 23:43:03 +0000655};
656
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000657static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000658bsddb_getattr(PyObject *dp, char *name)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000659{
Roger E. Massed9240d11997-01-16 22:05:33 +0000660 return Py_FindMethod(bsddb_methods, dp, name);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000661}
662
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000663static PyTypeObject Bsddbtype = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000664 PyObject_HEAD_INIT(NULL)
665 0,
Guido van Rossum14648392001-12-08 18:02:58 +0000666 "bsddb.bsddb",
Roger E. Massed9240d11997-01-16 22:05:33 +0000667 sizeof(bsddbobject),
668 0,
669 (destructor)bsddb_dealloc, /*tp_dealloc*/
670 0, /*tp_print*/
671 (getattrfunc)bsddb_getattr, /*tp_getattr*/
672 0, /*tp_setattr*/
673 0, /*tp_compare*/
674 0, /*tp_repr*/
675 0, /*tp_as_number*/
676 0, /*tp_as_sequence*/
677 &bsddb_as_mapping, /*tp_as_mapping*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000678};
679
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000680static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000681bsdhashopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000682{
Roger E. Massed9240d11997-01-16 22:05:33 +0000683 char *file;
684 char *flag = NULL;
685 int flags = O_RDONLY;
686 int mode = 0666;
687 int bsize = 0;
688 int ffactor = 0;
689 int nelem = 0;
690 int cachesize = 0;
691 int hash = 0; /* XXX currently ignored */
692 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000693
Guido van Rossum43713e52000-02-29 13:59:29 +0000694 if (!PyArg_ParseTuple(args, "s|siiiiiii:hashopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000695 &file, &flag, &mode,
696 &bsize, &ffactor, &nelem, &cachesize,
697 &hash, &lorder))
698 return NULL;
699 if (flag != NULL) {
700 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
701 if (flag[0] == 'r')
702 flags = O_RDONLY;
703 else if (flag[0] == 'w')
704 flags = O_RDWR;
705 else if (flag[0] == 'c')
706 flags = O_RDWR|O_CREAT;
707 else if (flag[0] == 'n')
708 flags = O_RDWR|O_CREAT|O_TRUNC;
709 else {
710 PyErr_SetString(BsddbError,
711 "Flag should begin with 'r', 'w', 'c' or 'n'");
712 return NULL;
713 }
714 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000715#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000716 if (flag[0] == 'r')
717 flags |= O_SHLOCK;
718 else
719 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000720#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000721 PyErr_SetString(BsddbError,
722 "locking not supported on this platform");
723 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000724#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000725 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000726 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000727 return newdbhashobject(file, flags, mode,
728 bsize, ffactor, nelem, cachesize, hash, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000729}
730
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000731static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000732bsdbtopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000733{
Roger E. Massed9240d11997-01-16 22:05:33 +0000734 char *file;
735 char *flag = NULL;
736 int flags = O_RDONLY;
737 int mode = 0666;
738 int cachesize = 0;
739 int maxkeypage = 0;
740 int minkeypage = 0;
741 int btflags = 0;
742 unsigned int psize = 0;
743 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000744
Guido van Rossum43713e52000-02-29 13:59:29 +0000745 if (!PyArg_ParseTuple(args, "s|siiiiiii:btopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000746 &file, &flag, &mode,
747 &btflags, &cachesize, &maxkeypage, &minkeypage,
748 &psize, &lorder))
749 return NULL;
750 if (flag != NULL) {
751 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
752 if (flag[0] == 'r')
753 flags = O_RDONLY;
754 else if (flag[0] == 'w')
755 flags = O_RDWR;
756 else if (flag[0] == 'c')
757 flags = O_RDWR|O_CREAT;
758 else if (flag[0] == 'n')
759 flags = O_RDWR|O_CREAT|O_TRUNC;
760 else {
761 PyErr_SetString(BsddbError,
762 "Flag should begin with 'r', 'w', 'c' or 'n'");
763 return NULL;
764 }
765 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000766#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000767 if (flag[0] == 'r')
768 flags |= O_SHLOCK;
769 else
770 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000771#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000772 PyErr_SetString(BsddbError,
773 "locking not supported on this platform");
774 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000775#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000776 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000777 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000778 return newdbbtobject(file, flags, mode,
779 btflags, cachesize, maxkeypage, minkeypage,
780 psize, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000781}
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000782
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000783static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000784bsdrnopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000785{
Roger E. Massed9240d11997-01-16 22:05:33 +0000786 char *file;
787 char *flag = NULL;
788 int flags = O_RDONLY;
789 int mode = 0666;
790 int cachesize = 0;
791 int rnflags = 0;
792 unsigned int psize = 0;
793 int lorder = 0;
794 size_t reclen = 0;
795 char *bval = "";
796 char *bfname = NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000797
Guido van Rossum43713e52000-02-29 13:59:29 +0000798 if (!PyArg_ParseTuple(args, "s|siiiiiiss:rnopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000799 &file, &flag, &mode,
800 &rnflags, &cachesize, &psize, &lorder,
801 &reclen, &bval, &bfname))
802 return NULL;
803
Roger E. Massed9240d11997-01-16 22:05:33 +0000804 if (flag != NULL) {
805 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
806 if (flag[0] == 'r')
807 flags = O_RDONLY;
808 else if (flag[0] == 'w')
809 flags = O_RDWR;
810 else if (flag[0] == 'c')
811 flags = O_RDWR|O_CREAT;
812 else if (flag[0] == 'n')
813 flags = O_RDWR|O_CREAT|O_TRUNC;
814 else {
815 PyErr_SetString(BsddbError,
816 "Flag should begin with 'r', 'w', 'c' or 'n'");
817 return NULL;
818 }
819 if (flag[1] == 'l') {
820#if defined(O_EXLOCK) && defined(O_SHLOCK)
821 if (flag[0] == 'r')
822 flags |= O_SHLOCK;
823 else
824 flags |= O_EXLOCK;
825#else
826 PyErr_SetString(BsddbError,
827 "locking not supported on this platform");
828 return NULL;
829#endif
830 }
831 else if (flag[1] != '\0') {
832 PyErr_SetString(BsddbError,
833 "Flag char 2 should be 'l' or absent");
834 return NULL;
835 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000836 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000837 return newdbrnobject(file, flags, mode, rnflags, cachesize,
838 psize, lorder, reclen, bval[0], bfname);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000839}
840
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000841static PyMethodDef bsddbmodule_methods[] = {
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000842 {"hashopen", (PyCFunction)bsdhashopen, METH_VARARGS},
843 {"btopen", (PyCFunction)bsdbtopen, METH_VARARGS},
844 {"rnopen", (PyCFunction)bsdrnopen, METH_VARARGS},
Roger E. Massed9240d11997-01-16 22:05:33 +0000845 {0, 0},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000846};
847
Guido van Rossum3886bb61998-12-04 18:50:17 +0000848DL_EXPORT(void)
Thomas Wouters58d05102000-07-24 14:43:35 +0000849initbsddb(void) {
Roger E. Massed9240d11997-01-16 22:05:33 +0000850 PyObject *m, *d;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000851
Roger E. Massed9240d11997-01-16 22:05:33 +0000852 Bsddbtype.ob_type = &PyType_Type;
853 m = Py_InitModule("bsddb", bsddbmodule_methods);
854 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000855 BsddbError = PyErr_NewException("bsddb.error", NULL, NULL);
856 if (BsddbError != NULL)
857 PyDict_SetItemString(d, "error", BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000858}