blob: 85dfa8329c1ce0f610c1fa5c8cc299d1ab2757b2 [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 *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000383bsddb_close(bsddbobject *dp, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000384{
Roger E. Massed9240d11997-01-16 22:05:33 +0000385 if (!PyArg_NoArgs(args))
386 return NULL;
387 if (dp->di_bsddb != NULL) {
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000388 int status;
389 BSDDB_BGN_SAVE(dp)
390 status = (dp->di_bsddb->close)(dp->di_bsddb);
391 BSDDB_END_SAVE(dp)
392 if (status != 0) {
Roger E. Massed9240d11997-01-16 22:05:33 +0000393 dp->di_bsddb = NULL;
394 PyErr_SetFromErrno(BsddbError);
395 return NULL;
396 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000397 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000398 dp->di_bsddb = NULL;
399 Py_INCREF(Py_None);
400 return Py_None;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000401}
402
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000403static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000404bsddb_keys(bsddbobject *dp, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000405{
Fred Drakeed5e8232001-02-27 18:56:46 +0000406 PyObject *list, *item=NULL;
Roger E. Massed9240d11997-01-16 22:05:33 +0000407 DBT krec, drec;
Guido van Rossum730806d1998-04-10 22:27:42 +0000408 char *data=NULL,buf[4096];
Roger E. Massed9240d11997-01-16 22:05:33 +0000409 int status;
410 int err;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000411
Roger E. Massed9240d11997-01-16 22:05:33 +0000412 if (!PyArg_NoArgs(args))
413 return NULL;
Fred Drakeed5e8232001-02-27 18:56:46 +0000414 check_bsddbobject_open(dp, NULL);
Roger E. Massed9240d11997-01-16 22:05:33 +0000415 list = PyList_New(0);
416 if (list == NULL)
417 return NULL;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000418 BSDDB_BGN_SAVE(dp)
419 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
420 if (status == 0) {
421 if (krec.size > sizeof(buf)) data = malloc(krec.size);
422 else data = buf;
Fred Drakeed5e8232001-02-27 18:56:46 +0000423 if (data != NULL) memcpy(data,krec.data,krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000424 }
425 BSDDB_END_SAVE(dp)
Guido van Rossumec24c1b2001-03-22 00:19:22 +0000426 if (status == 0 && data==NULL) return PyErr_NoMemory();
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000427 while (status == 0) {
Fred Drakeed5e8232001-02-27 18:56:46 +0000428 if (dp->di_type == DB_RECNO)
429 item = PyInt_FromLong(*((int*)data));
430 else
431 item = PyString_FromStringAndSize(data,
432 (int)krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000433 if (data != buf) free(data);
Roger E. Massed9240d11997-01-16 22:05:33 +0000434 if (item == NULL) {
435 Py_DECREF(list);
436 return NULL;
437 }
438 err = PyList_Append(list, item);
439 Py_DECREF(item);
440 if (err != 0) {
441 Py_DECREF(list);
442 return NULL;
443 }
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000444 BSDDB_BGN_SAVE(dp)
Fred Drakec9f7c262001-02-19 21:16:00 +0000445 status = (dp->di_bsddb->seq)
446 (dp->di_bsddb, &krec, &drec, R_NEXT);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000447 if (status == 0) {
Fred Drakec9f7c262001-02-19 21:16:00 +0000448 if (krec.size > sizeof(buf))
449 data = malloc(krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000450 else data = buf;
Fred Drakec9f7c262001-02-19 21:16:00 +0000451 if (data != NULL)
452 memcpy(data,krec.data,krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000453 }
454 BSDDB_END_SAVE(dp)
Fred Drakec9f7c262001-02-19 21:16:00 +0000455 if (data == NULL) return PyErr_NoMemory();
Guido van Rossum1100dca1995-08-30 23:43:03 +0000456 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000457 if (status < 0) {
458 PyErr_SetFromErrno(BsddbError);
459 Py_DECREF(list);
460 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000461 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000462 if (dp->di_size < 0)
463 dp->di_size = PyList_Size(list); /* We just did the work */
464 return list;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000465}
466
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000467static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000468bsddb_has_key(bsddbobject *dp, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000469{
Roger E. Massed9240d11997-01-16 22:05:33 +0000470 DBT krec, drec;
471 int status;
472 char *data;
473 int size;
Fred Drakeed5e8232001-02-27 18:56:46 +0000474 recno_t recno;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000475
Fred Drakeed5e8232001-02-27 18:56:46 +0000476 if (dp->di_type == DB_RECNO) {
477 if (!PyArg_Parse(args, "i", &recno)) {
478 PyErr_SetString(PyExc_TypeError,
479 "key type must be integer");
480 return NULL;
481 }
482 krec.data = &recno;
483 krec.size = sizeof(recno);
484 }
485 else {
486 if (!PyArg_Parse(args, "s#", &data, &size)) {
487 PyErr_SetString(PyExc_TypeError,
488 "key type must be string");
489 return NULL;
490 }
491 krec.data = data;
492 krec.size = size;
493 }
494 check_bsddbobject_open(dp, NULL);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000495
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000496 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000497 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000498 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000499 if (status < 0) {
500 PyErr_SetFromErrno(BsddbError);
501 return NULL;
502 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000503
Roger E. Massed9240d11997-01-16 22:05:33 +0000504 return PyInt_FromLong(status == 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000505}
506
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000507static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000508bsddb_set_location(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000509{
Roger E. Massed9240d11997-01-16 22:05:33 +0000510 int status;
511 DBT krec, drec;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000512 char *data,buf[4096];
Roger E. Massed9240d11997-01-16 22:05:33 +0000513 int size;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000514 PyObject *result;
Fred Drakeed5e8232001-02-27 18:56:46 +0000515 recno_t recno;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000516
Fred Drakeed5e8232001-02-27 18:56:46 +0000517 if (dp->di_type == DB_RECNO) {
518 if (!PyArg_Parse(key, "i", &recno)) {
519 PyErr_SetString(PyExc_TypeError,
520 "key type must be integer");
521 return NULL;
522 }
523 krec.data = &recno;
524 krec.size = sizeof(recno);
525 }
526 else {
527 if (!PyArg_Parse(key, "s#", &data, &size)) {
528 PyErr_SetString(PyExc_TypeError,
529 "key type must be string");
530 return NULL;
531 }
532 krec.data = data;
533 krec.size = size;
534 }
535 check_bsddbobject_open(dp, NULL);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000536
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000537 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000538 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000539 if (status == 0) {
540 if (drec.size > sizeof(buf)) data = malloc(drec.size);
541 else data = buf;
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000542 if (data!=NULL) memcpy(data,drec.data,drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000543 }
544 BSDDB_END_SAVE(dp)
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000545 if (data==NULL) return PyErr_NoMemory();
Roger E. Massed9240d11997-01-16 22:05:33 +0000546 if (status != 0) {
547 if (status < 0)
548 PyErr_SetFromErrno(BsddbError);
549 else
550 PyErr_SetObject(PyExc_KeyError, key);
551 return NULL;
552 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000553
Fred Drakeed5e8232001-02-27 18:56:46 +0000554 if (dp->di_type == DB_RECNO)
555 result = Py_BuildValue("is#", *((int*)krec.data),
556 data, drec.size);
557 else
558 result = Py_BuildValue("s#s#", krec.data, krec.size,
559 data, drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000560 if (data != buf) free(data);
561 return result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000562}
563
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000564static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000565bsddb_seq(bsddbobject *dp, PyObject *args, int sequence_request)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000566{
Roger E. Massed9240d11997-01-16 22:05:33 +0000567 int status;
568 DBT krec, drec;
Guido van Rossum730806d1998-04-10 22:27:42 +0000569 char *kdata=NULL,kbuf[4096];
570 char *ddata=NULL,dbuf[4096];
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000571 PyObject *result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000572
Roger E. Massed9240d11997-01-16 22:05:33 +0000573 if (!PyArg_NoArgs(args))
574 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000575
Fred Drakeed5e8232001-02-27 18:56:46 +0000576 check_bsddbobject_open(dp, NULL);
Roger E. Massed9240d11997-01-16 22:05:33 +0000577 krec.data = 0;
578 krec.size = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000579
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000580 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000581 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec,
582 &drec, sequence_request);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000583 if (status == 0) {
584 if (krec.size > sizeof(kbuf)) kdata = malloc(krec.size);
585 else kdata = kbuf;
Fred Drakeed5e8232001-02-27 18:56:46 +0000586 if (kdata != NULL) memcpy(kdata,krec.data,krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000587 if (drec.size > sizeof(dbuf)) ddata = malloc(drec.size);
588 else ddata = dbuf;
Fred Drakeed5e8232001-02-27 18:56:46 +0000589 if (ddata != NULL) memcpy(ddata,drec.data,drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000590 }
591 BSDDB_END_SAVE(dp)
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000592 if (status == 0) {
Fred Drakeed5e8232001-02-27 18:56:46 +0000593 if ((kdata == NULL) || (ddata == NULL))
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000594 return PyErr_NoMemory();
595 }
596 else {
597 /* (status != 0) */
Roger E. Massed9240d11997-01-16 22:05:33 +0000598 if (status < 0)
599 PyErr_SetFromErrno(BsddbError);
600 else
601 PyErr_SetObject(PyExc_KeyError, args);
602 return NULL;
603 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000604
Fred Drakeed5e8232001-02-27 18:56:46 +0000605
606 if (dp->di_type == DB_RECNO)
607 result = Py_BuildValue("is#", *((int*)kdata),
608 ddata, drec.size);
609 else
610 result = Py_BuildValue("s#s#", kdata, krec.size,
611 ddata, drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000612 if (kdata != kbuf) free(kdata);
613 if (ddata != dbuf) free(ddata);
614 return result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000615}
616
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000617static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000618bsddb_next(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000619{
Roger E. Massed9240d11997-01-16 22:05:33 +0000620 return bsddb_seq(dp, key, R_NEXT);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000621}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000622static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000623bsddb_previous(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000624{
Roger E. Massed9240d11997-01-16 22:05:33 +0000625 return bsddb_seq(dp, key, R_PREV);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000626}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000627static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000628bsddb_first(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000629{
Roger E. Massed9240d11997-01-16 22:05:33 +0000630 return bsddb_seq(dp, key, R_FIRST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000631}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000632static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000633bsddb_last(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000634{
Roger E. Massed9240d11997-01-16 22:05:33 +0000635 return bsddb_seq(dp, key, R_LAST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000636}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000637static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000638bsddb_sync(bsddbobject *dp, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000639{
Roger E. Massed9240d11997-01-16 22:05:33 +0000640 int status;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000641
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000642 if (!PyArg_NoArgs(args))
643 return NULL;
Fred Drakeed5e8232001-02-27 18:56:46 +0000644 check_bsddbobject_open(dp, NULL);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000645 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000646 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000647 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000648 if (status != 0) {
649 PyErr_SetFromErrno(BsddbError);
650 return NULL;
651 }
652 return PyInt_FromLong(status = 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000653}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000654static PyMethodDef bsddb_methods[] = {
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000655 {"close", (PyCFunction)bsddb_close, METH_OLDARGS},
656 {"keys", (PyCFunction)bsddb_keys, METH_OLDARGS},
657 {"has_key", (PyCFunction)bsddb_has_key, METH_OLDARGS},
658 {"set_location", (PyCFunction)bsddb_set_location, METH_OLDARGS},
659 {"next", (PyCFunction)bsddb_next, METH_OLDARGS},
660 {"previous", (PyCFunction)bsddb_previous, METH_OLDARGS},
661 {"first", (PyCFunction)bsddb_first, METH_OLDARGS},
662 {"last", (PyCFunction)bsddb_last, METH_OLDARGS},
663 {"sync", (PyCFunction)bsddb_sync, METH_OLDARGS},
Roger E. Massed9240d11997-01-16 22:05:33 +0000664 {NULL, NULL} /* sentinel */
Guido van Rossum1100dca1995-08-30 23:43:03 +0000665};
666
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000667static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000668bsddb_getattr(PyObject *dp, char *name)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000669{
Roger E. Massed9240d11997-01-16 22:05:33 +0000670 return Py_FindMethod(bsddb_methods, dp, name);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000671}
672
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000673static PyTypeObject Bsddbtype = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000674 PyObject_HEAD_INIT(NULL)
675 0,
Guido van Rossum14648392001-12-08 18:02:58 +0000676 "bsddb.bsddb",
Roger E. Massed9240d11997-01-16 22:05:33 +0000677 sizeof(bsddbobject),
678 0,
679 (destructor)bsddb_dealloc, /*tp_dealloc*/
680 0, /*tp_print*/
681 (getattrfunc)bsddb_getattr, /*tp_getattr*/
682 0, /*tp_setattr*/
683 0, /*tp_compare*/
684 0, /*tp_repr*/
685 0, /*tp_as_number*/
686 0, /*tp_as_sequence*/
687 &bsddb_as_mapping, /*tp_as_mapping*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000688};
689
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000690static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000691bsdhashopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000692{
Roger E. Massed9240d11997-01-16 22:05:33 +0000693 char *file;
694 char *flag = NULL;
695 int flags = O_RDONLY;
696 int mode = 0666;
697 int bsize = 0;
698 int ffactor = 0;
699 int nelem = 0;
700 int cachesize = 0;
701 int hash = 0; /* XXX currently ignored */
702 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000703
Guido van Rossum43713e52000-02-29 13:59:29 +0000704 if (!PyArg_ParseTuple(args, "s|siiiiiii:hashopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000705 &file, &flag, &mode,
706 &bsize, &ffactor, &nelem, &cachesize,
707 &hash, &lorder))
708 return NULL;
709 if (flag != NULL) {
710 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
711 if (flag[0] == 'r')
712 flags = O_RDONLY;
713 else if (flag[0] == 'w')
714 flags = O_RDWR;
715 else if (flag[0] == 'c')
716 flags = O_RDWR|O_CREAT;
717 else if (flag[0] == 'n')
718 flags = O_RDWR|O_CREAT|O_TRUNC;
719 else {
720 PyErr_SetString(BsddbError,
721 "Flag should begin with 'r', 'w', 'c' or 'n'");
722 return NULL;
723 }
724 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000725#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000726 if (flag[0] == 'r')
727 flags |= O_SHLOCK;
728 else
729 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000730#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000731 PyErr_SetString(BsddbError,
732 "locking not supported on this platform");
733 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000734#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000735 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000736 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000737 return newdbhashobject(file, flags, mode,
738 bsize, ffactor, nelem, cachesize, hash, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000739}
740
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000741static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000742bsdbtopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000743{
Roger E. Massed9240d11997-01-16 22:05:33 +0000744 char *file;
745 char *flag = NULL;
746 int flags = O_RDONLY;
747 int mode = 0666;
748 int cachesize = 0;
749 int maxkeypage = 0;
750 int minkeypage = 0;
751 int btflags = 0;
752 unsigned int psize = 0;
753 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000754
Guido van Rossum43713e52000-02-29 13:59:29 +0000755 if (!PyArg_ParseTuple(args, "s|siiiiiii:btopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000756 &file, &flag, &mode,
757 &btflags, &cachesize, &maxkeypage, &minkeypage,
758 &psize, &lorder))
759 return NULL;
760 if (flag != NULL) {
761 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
762 if (flag[0] == 'r')
763 flags = O_RDONLY;
764 else if (flag[0] == 'w')
765 flags = O_RDWR;
766 else if (flag[0] == 'c')
767 flags = O_RDWR|O_CREAT;
768 else if (flag[0] == 'n')
769 flags = O_RDWR|O_CREAT|O_TRUNC;
770 else {
771 PyErr_SetString(BsddbError,
772 "Flag should begin with 'r', 'w', 'c' or 'n'");
773 return NULL;
774 }
775 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000776#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000777 if (flag[0] == 'r')
778 flags |= O_SHLOCK;
779 else
780 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000781#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000782 PyErr_SetString(BsddbError,
783 "locking not supported on this platform");
784 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000785#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000786 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000787 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000788 return newdbbtobject(file, flags, mode,
789 btflags, cachesize, maxkeypage, minkeypage,
790 psize, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000791}
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000792
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000793static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000794bsdrnopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000795{
Roger E. Massed9240d11997-01-16 22:05:33 +0000796 char *file;
797 char *flag = NULL;
798 int flags = O_RDONLY;
799 int mode = 0666;
800 int cachesize = 0;
801 int rnflags = 0;
802 unsigned int psize = 0;
803 int lorder = 0;
804 size_t reclen = 0;
805 char *bval = "";
806 char *bfname = NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000807
Guido van Rossum43713e52000-02-29 13:59:29 +0000808 if (!PyArg_ParseTuple(args, "s|siiiiiiss:rnopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000809 &file, &flag, &mode,
810 &rnflags, &cachesize, &psize, &lorder,
811 &reclen, &bval, &bfname))
812 return NULL;
813
Roger E. Massed9240d11997-01-16 22:05:33 +0000814 if (flag != NULL) {
815 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
816 if (flag[0] == 'r')
817 flags = O_RDONLY;
818 else if (flag[0] == 'w')
819 flags = O_RDWR;
820 else if (flag[0] == 'c')
821 flags = O_RDWR|O_CREAT;
822 else if (flag[0] == 'n')
823 flags = O_RDWR|O_CREAT|O_TRUNC;
824 else {
825 PyErr_SetString(BsddbError,
826 "Flag should begin with 'r', 'w', 'c' or 'n'");
827 return NULL;
828 }
829 if (flag[1] == 'l') {
830#if defined(O_EXLOCK) && defined(O_SHLOCK)
831 if (flag[0] == 'r')
832 flags |= O_SHLOCK;
833 else
834 flags |= O_EXLOCK;
835#else
836 PyErr_SetString(BsddbError,
837 "locking not supported on this platform");
838 return NULL;
839#endif
840 }
841 else if (flag[1] != '\0') {
842 PyErr_SetString(BsddbError,
843 "Flag char 2 should be 'l' or absent");
844 return NULL;
845 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000846 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000847 return newdbrnobject(file, flags, mode, rnflags, cachesize,
848 psize, lorder, reclen, bval[0], bfname);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000849}
850
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000851static PyMethodDef bsddbmodule_methods[] = {
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000852 {"hashopen", (PyCFunction)bsdhashopen, METH_VARARGS},
853 {"btopen", (PyCFunction)bsdbtopen, METH_VARARGS},
854 {"rnopen", (PyCFunction)bsdrnopen, METH_VARARGS},
Roger E. Massed9240d11997-01-16 22:05:33 +0000855 {0, 0},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000856};
857
Guido van Rossum3886bb61998-12-04 18:50:17 +0000858DL_EXPORT(void)
Thomas Wouters58d05102000-07-24 14:43:35 +0000859initbsddb(void) {
Roger E. Massed9240d11997-01-16 22:05:33 +0000860 PyObject *m, *d;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000861
Roger E. Massed9240d11997-01-16 22:05:33 +0000862 Bsddbtype.ob_type = &PyType_Type;
863 m = Py_InitModule("bsddb", bsddbmodule_methods);
864 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000865 BsddbError = PyErr_NewException("bsddb.error", NULL, NULL);
866 if (BsddbError != NULL)
867 PyDict_SetItemString(d, "error", BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000868}