blob: ecfb653d8e44f0796e962b5c8855788f29d8f6d3 [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
Fred Drakeed5e8232001-02-27 18:56:46 +000021#ifdef HAVE_UNISTD_H
22#include <unistd.h>
23#endif
24
Guido van Rossum1100dca1995-08-30 23:43:03 +000025#include <sys/types.h>
26#include <sys/stat.h>
27#include <fcntl.h>
Fred Drakec9cb8472000-08-31 16:11:07 +000028#ifdef HAVE_DB_185_H
29#include <db_185.h>
30#else
Guido van Rossum1100dca1995-08-30 23:43:03 +000031#include <db.h>
Fred Drakec9cb8472000-08-31 16:11:07 +000032#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +000033/* Please don't include internal header files of the Berkeley db package
34 (it messes up the info required in the Setup file) */
35
36typedef struct {
Roger E. Massed9240d11997-01-16 22:05:33 +000037 PyObject_HEAD
38 DB *di_bsddb;
39 int di_size; /* -1 means recompute */
Fred Drakeed5e8232001-02-27 18:56:46 +000040 int di_type;
Guido van Rossum4f199ea1998-04-09 20:56:35 +000041#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +000042 PyThread_type_lock di_lock;
Guido van Rossum4f199ea1998-04-09 20:56:35 +000043#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +000044} bsddbobject;
45
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000046staticforward PyTypeObject Bsddbtype;
Guido van Rossum1100dca1995-08-30 23:43:03 +000047
48#define is_bsddbobject(v) ((v)->ob_type == &Bsddbtype)
Fred Drakeed5e8232001-02-27 18:56:46 +000049#define check_bsddbobject_open(v, r) if ((v)->di_bsddb == NULL) \
Fred Drakec9f7c262001-02-19 21:16:00 +000050 { PyErr_SetString(BsddbError, \
51 "BSDDB object has already been closed"); \
Fred Drakeed5e8232001-02-27 18:56:46 +000052 return r; }
Guido van Rossum1100dca1995-08-30 23:43:03 +000053
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000054static PyObject *BsddbError;
Guido van Rossum1100dca1995-08-30 23:43:03 +000055
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000056static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +000057newdbhashobject(char *file, int flags, int mode,
Fred Drakec9f7c262001-02-19 21:16:00 +000058 int bsize, int ffactor, int nelem, int cachesize,
59 int hash, int lorder)
Guido van Rossum1100dca1995-08-30 23:43:03 +000060{
Roger E. Massed9240d11997-01-16 22:05:33 +000061 bsddbobject *dp;
62 HASHINFO info;
Guido van Rossum1100dca1995-08-30 23:43:03 +000063
Guido van Rossumb18618d2000-05-03 23:44:39 +000064 if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
Roger E. Massed9240d11997-01-16 22:05:33 +000065 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +000066
Roger E. Massed9240d11997-01-16 22:05:33 +000067 info.bsize = bsize;
68 info.ffactor = ffactor;
69 info.nelem = nelem;
70 info.cachesize = cachesize;
71 info.hash = NULL; /* XXX should derive from hash argument */
72 info.lorder = lorder;
Guido van Rossum1100dca1995-08-30 23:43:03 +000073
Guido van Rossum6beb4791996-09-11 23:22:25 +000074#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +000075 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +000076#endif
Guido van Rossum4f199ea1998-04-09 20:56:35 +000077 Py_BEGIN_ALLOW_THREADS
78 dp->di_bsddb = dbopen(file, flags, mode, DB_HASH, &info);
79 Py_END_ALLOW_THREADS
80 if (dp->di_bsddb == NULL) {
Roger E. Massed9240d11997-01-16 22:05:33 +000081 PyErr_SetFromErrno(BsddbError);
Guido van Rossum4f199ea1998-04-09 20:56:35 +000082#ifdef WITH_THREAD
83 dp->di_lock = NULL;
84#endif
Roger E. Massed9240d11997-01-16 22:05:33 +000085 Py_DECREF(dp);
86 return NULL;
87 }
Guido van Rossum1100dca1995-08-30 23:43:03 +000088
Roger E. Massed9240d11997-01-16 22:05:33 +000089 dp->di_size = -1;
Fred Drakeed5e8232001-02-27 18:56:46 +000090 dp->di_type = DB_HASH;
91
Guido van Rossum4f199ea1998-04-09 20:56:35 +000092#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +000093 dp->di_lock = PyThread_allocate_lock();
Guido van Rossum4f199ea1998-04-09 20:56:35 +000094 if (dp->di_lock == NULL) {
95 PyErr_SetString(BsddbError, "can't allocate lock");
96 Py_DECREF(dp);
97 return NULL;
98 }
99#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +0000100
Roger E. Massed9240d11997-01-16 22:05:33 +0000101 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000102}
103
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000104static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000105newdbbtobject(char *file, int flags, int mode,
Fred Drakec9f7c262001-02-19 21:16:00 +0000106 int btflags, int cachesize, int maxkeypage,
107 int minkeypage, int psize, int lorder)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000108{
Roger E. Massed9240d11997-01-16 22:05:33 +0000109 bsddbobject *dp;
110 BTREEINFO info;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000111
Guido van Rossumb18618d2000-05-03 23:44:39 +0000112 if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
Roger E. Massed9240d11997-01-16 22:05:33 +0000113 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000114
Roger E. Massed9240d11997-01-16 22:05:33 +0000115 info.flags = btflags;
116 info.cachesize = cachesize;
117 info.maxkeypage = maxkeypage;
118 info.minkeypage = minkeypage;
119 info.psize = psize;
120 info.lorder = lorder;
121 info.compare = 0; /* Use default comparison functions, for now..*/
122 info.prefix = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000123
Guido van Rossum6beb4791996-09-11 23:22:25 +0000124#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +0000125 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +0000126#endif
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000127 Py_BEGIN_ALLOW_THREADS
128 dp->di_bsddb = dbopen(file, flags, mode, DB_BTREE, &info);
129 Py_END_ALLOW_THREADS
130 if (dp->di_bsddb == NULL) {
Roger E. Massed9240d11997-01-16 22:05:33 +0000131 PyErr_SetFromErrno(BsddbError);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000132#ifdef WITH_THREAD
133 dp->di_lock = NULL;
134#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000135 Py_DECREF(dp);
136 return NULL;
137 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000138
Roger E. Massed9240d11997-01-16 22:05:33 +0000139 dp->di_size = -1;
Fred Drakeed5e8232001-02-27 18:56:46 +0000140 dp->di_type = DB_BTREE;
141
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000142#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +0000143 dp->di_lock = PyThread_allocate_lock();
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000144 if (dp->di_lock == NULL) {
145 PyErr_SetString(BsddbError, "can't allocate lock");
146 Py_DECREF(dp);
147 return NULL;
148 }
149#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +0000150
Roger E. Massed9240d11997-01-16 22:05:33 +0000151 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000152}
153
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000154static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000155newdbrnobject(char *file, int flags, int mode,
Fred Drakec9f7c262001-02-19 21:16:00 +0000156 int rnflags, int cachesize, int psize, int lorder,
157 size_t reclen, u_char bval, char *bfname)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000158{
Roger E. Massed9240d11997-01-16 22:05:33 +0000159 bsddbobject *dp;
160 RECNOINFO info;
Fred Drakeed5e8232001-02-27 18:56:46 +0000161 int fd;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000162
Guido van Rossumb18618d2000-05-03 23:44:39 +0000163 if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
Roger E. Massed9240d11997-01-16 22:05:33 +0000164 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000165
Roger E. Massed9240d11997-01-16 22:05:33 +0000166 info.flags = rnflags;
167 info.cachesize = cachesize;
168 info.psize = psize;
169 info.lorder = lorder;
170 info.reclen = reclen;
171 info.bval = bval;
172 info.bfname = bfname;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000173
Guido van Rossum6beb4791996-09-11 23:22:25 +0000174#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +0000175 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +0000176#endif
Fred Drakeed5e8232001-02-27 18:56:46 +0000177 /* This is a hack to avoid a dbopen() bug that happens when
178 * it fails. */
179 fd = open(file, flags);
180 if (fd == -1) {
181 dp->di_bsddb = NULL;
182 }
183 else {
184 close(fd);
185 Py_BEGIN_ALLOW_THREADS
186 dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info);
187 Py_END_ALLOW_THREADS
188 }
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000189 if (dp->di_bsddb == NULL) {
Roger E. Massed9240d11997-01-16 22:05:33 +0000190 PyErr_SetFromErrno(BsddbError);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000191#ifdef WITH_THREAD
192 dp->di_lock = NULL;
193#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000194 Py_DECREF(dp);
195 return NULL;
196 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000197
Roger E. Massed9240d11997-01-16 22:05:33 +0000198 dp->di_size = -1;
Fred Drakeed5e8232001-02-27 18:56:46 +0000199 dp->di_type = DB_RECNO;
200
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000201#ifdef WITH_THREAD
Guido van Rossum65d5b571998-12-21 19:32:43 +0000202 dp->di_lock = PyThread_allocate_lock();
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000203 if (dp->di_lock == NULL) {
204 PyErr_SetString(BsddbError, "can't allocate lock");
205 Py_DECREF(dp);
206 return NULL;
207 }
208#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +0000209
Roger E. Massed9240d11997-01-16 22:05:33 +0000210 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000211}
212
Guido van Rossum1100dca1995-08-30 23:43:03 +0000213static void
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000214bsddb_dealloc(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000215{
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000216#ifdef WITH_THREAD
217 if (dp->di_lock) {
Guido van Rossum65d5b571998-12-21 19:32:43 +0000218 PyThread_acquire_lock(dp->di_lock, 0);
219 PyThread_release_lock(dp->di_lock);
220 PyThread_free_lock(dp->di_lock);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000221 dp->di_lock = NULL;
222 }
223#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000224 if (dp->di_bsddb != NULL) {
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000225 int status;
226 Py_BEGIN_ALLOW_THREADS
227 status = (dp->di_bsddb->close)(dp->di_bsddb);
228 Py_END_ALLOW_THREADS
229 if (status != 0)
Roger E. Massed9240d11997-01-16 22:05:33 +0000230 fprintf(stderr,
231 "Python bsddb: close errno %d in dealloc\n",
232 errno);
233 }
Guido van Rossumb18618d2000-05-03 23:44:39 +0000234 PyObject_Del(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000235}
236
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000237#ifdef WITH_THREAD
Fred Drakec9f7c262001-02-19 21:16:00 +0000238#define BSDDB_BGN_SAVE(_dp) \
239 Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(_dp->di_lock,1);
240#define BSDDB_END_SAVE(_dp) \
241 PyThread_release_lock(_dp->di_lock); Py_END_ALLOW_THREADS
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000242#else
243#define BSDDB_BGN_SAVE(_dp) Py_BEGIN_ALLOW_THREADS
244#define BSDDB_END_SAVE(_dp) Py_END_ALLOW_THREADS
245#endif
246
Guido van Rossum1100dca1995-08-30 23:43:03 +0000247static int
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000248bsddb_length(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000249{
Fred Drakeed5e8232001-02-27 18:56:46 +0000250 check_bsddbobject_open(dp, -1);
Roger E. Massed9240d11997-01-16 22:05:33 +0000251 if (dp->di_size < 0) {
252 DBT krec, drec;
253 int status;
254 int size = 0;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000255 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000256 for (status = (dp->di_bsddb->seq)(dp->di_bsddb,
257 &krec, &drec,R_FIRST);
258 status == 0;
259 status = (dp->di_bsddb->seq)(dp->di_bsddb,
260 &krec, &drec, R_NEXT))
261 size++;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000262 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000263 if (status < 0) {
264 PyErr_SetFromErrno(BsddbError);
265 return -1;
266 }
267 dp->di_size = size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000268 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000269 return dp->di_size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000270}
271
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000272static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000273bsddb_subscript(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000274{
Roger E. Massed9240d11997-01-16 22:05:33 +0000275 int status;
276 DBT krec, drec;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000277 char *data,buf[4096];
Roger E. Massed9240d11997-01-16 22:05:33 +0000278 int size;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000279 PyObject *result;
Fred Drakeed5e8232001-02-27 18:56:46 +0000280 recno_t recno;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000281
Fred Drakeed5e8232001-02-27 18:56:46 +0000282 if (dp->di_type == DB_RECNO) {
283 if (!PyArg_Parse(key, "i", &recno)) {
284 PyErr_SetString(PyExc_TypeError,
285 "key type must be integer");
286 return NULL;
287 }
288 krec.data = &recno;
289 krec.size = sizeof(recno);
290 }
291 else {
292 if (!PyArg_Parse(key, "s#", &data, &size)) {
293 PyErr_SetString(PyExc_TypeError,
294 "key type must be string");
295 return NULL;
296 }
297 krec.data = data;
298 krec.size = size;
299 }
300 check_bsddbobject_open(dp, NULL);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000301
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000302 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000303 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000304 if (status == 0) {
305 if (drec.size > sizeof(buf)) data = malloc(drec.size);
306 else data = buf;
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000307 if (data!=NULL) memcpy(data,drec.data,drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000308 }
309 BSDDB_END_SAVE(dp)
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000310 if (data==NULL) return PyErr_NoMemory();
Roger E. Massed9240d11997-01-16 22:05:33 +0000311 if (status != 0) {
312 if (status < 0)
313 PyErr_SetFromErrno(BsddbError);
314 else
315 PyErr_SetObject(PyExc_KeyError, key);
316 return NULL;
317 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000318
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000319 result = PyString_FromStringAndSize(data, (int)drec.size);
320 if (data != buf) free(data);
321 return result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000322}
323
324static int
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000325bsddb_ass_sub(bsddbobject *dp, PyObject *key, PyObject *value)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000326{
Roger E. Massed9240d11997-01-16 22:05:33 +0000327 int status;
328 DBT krec, drec;
329 char *data;
330 int size;
Fred Drakeed5e8232001-02-27 18:56:46 +0000331 recno_t recno;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000332
Fred Drakeed5e8232001-02-27 18:56:46 +0000333 if (dp->di_type == DB_RECNO) {
334 if (!PyArg_Parse(key, "i", &recno)) {
335 PyErr_SetString(PyExc_TypeError,
336 "bsddb key type must be integer");
337 return -1;
338 }
339 krec.data = &recno;
340 krec.size = sizeof(recno);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000341 }
Fred Drakeed5e8232001-02-27 18:56:46 +0000342 else {
343 if (!PyArg_Parse(key, "s#", &data, &size)) {
344 PyErr_SetString(PyExc_TypeError,
345 "bsddb key type must be string");
346 return -1;
347 }
348 krec.data = data;
349 krec.size = size;
350 }
351 check_bsddbobject_open(dp, -1);
Roger E. Massed9240d11997-01-16 22:05:33 +0000352 dp->di_size = -1;
353 if (value == NULL) {
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000354 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000355 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000356 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000357 }
358 else {
359 if (!PyArg_Parse(value, "s#", &data, &size)) {
360 PyErr_SetString(PyExc_TypeError,
361 "bsddb value type must be string");
362 return -1;
363 }
364 drec.data = data;
365 drec.size = size;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000366 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000367 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000368 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000369 }
370 if (status != 0) {
371 if (status < 0)
372 PyErr_SetFromErrno(BsddbError);
373 else
374 PyErr_SetObject(PyExc_KeyError, key);
375 return -1;
376 }
377 return 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000378}
379
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000380static PyMappingMethods bsddb_as_mapping = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000381 (inquiry)bsddb_length, /*mp_length*/
382 (binaryfunc)bsddb_subscript, /*mp_subscript*/
383 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000384};
385
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000386static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000387bsddb_close(bsddbobject *dp, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000388{
Roger E. Massed9240d11997-01-16 22:05:33 +0000389 if (!PyArg_NoArgs(args))
390 return NULL;
391 if (dp->di_bsddb != NULL) {
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000392 int status;
393 BSDDB_BGN_SAVE(dp)
394 status = (dp->di_bsddb->close)(dp->di_bsddb);
395 BSDDB_END_SAVE(dp)
396 if (status != 0) {
Roger E. Massed9240d11997-01-16 22:05:33 +0000397 dp->di_bsddb = NULL;
398 PyErr_SetFromErrno(BsddbError);
399 return NULL;
400 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000401 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000402 dp->di_bsddb = NULL;
403 Py_INCREF(Py_None);
404 return Py_None;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000405}
406
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000407static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000408bsddb_keys(bsddbobject *dp, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000409{
Fred Drakeed5e8232001-02-27 18:56:46 +0000410 PyObject *list, *item=NULL;
Roger E. Massed9240d11997-01-16 22:05:33 +0000411 DBT krec, drec;
Guido van Rossum730806d1998-04-10 22:27:42 +0000412 char *data=NULL,buf[4096];
Roger E. Massed9240d11997-01-16 22:05:33 +0000413 int status;
414 int err;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000415
Roger E. Massed9240d11997-01-16 22:05:33 +0000416 if (!PyArg_NoArgs(args))
417 return NULL;
Fred Drakeed5e8232001-02-27 18:56:46 +0000418 check_bsddbobject_open(dp, NULL);
Roger E. Massed9240d11997-01-16 22:05:33 +0000419 list = PyList_New(0);
420 if (list == NULL)
421 return NULL;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000422 BSDDB_BGN_SAVE(dp)
423 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
424 if (status == 0) {
425 if (krec.size > sizeof(buf)) data = malloc(krec.size);
426 else data = buf;
Fred Drakeed5e8232001-02-27 18:56:46 +0000427 if (data != NULL) memcpy(data,krec.data,krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000428 }
429 BSDDB_END_SAVE(dp)
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000430 if (data==NULL) return PyErr_NoMemory();
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000431 while (status == 0) {
Fred Drakeed5e8232001-02-27 18:56:46 +0000432 if (dp->di_type == DB_RECNO)
433 item = PyInt_FromLong(*((int*)data));
434 else
435 item = PyString_FromStringAndSize(data,
436 (int)krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000437 if (data != buf) free(data);
Roger E. Massed9240d11997-01-16 22:05:33 +0000438 if (item == NULL) {
439 Py_DECREF(list);
440 return NULL;
441 }
442 err = PyList_Append(list, item);
443 Py_DECREF(item);
444 if (err != 0) {
445 Py_DECREF(list);
446 return NULL;
447 }
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000448 BSDDB_BGN_SAVE(dp)
Fred Drakec9f7c262001-02-19 21:16:00 +0000449 status = (dp->di_bsddb->seq)
450 (dp->di_bsddb, &krec, &drec, R_NEXT);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000451 if (status == 0) {
Fred Drakec9f7c262001-02-19 21:16:00 +0000452 if (krec.size > sizeof(buf))
453 data = malloc(krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000454 else data = buf;
Fred Drakec9f7c262001-02-19 21:16:00 +0000455 if (data != NULL)
456 memcpy(data,krec.data,krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000457 }
458 BSDDB_END_SAVE(dp)
Fred Drakec9f7c262001-02-19 21:16:00 +0000459 if (data == NULL) return PyErr_NoMemory();
Guido van Rossum1100dca1995-08-30 23:43:03 +0000460 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000461 if (status < 0) {
462 PyErr_SetFromErrno(BsddbError);
463 Py_DECREF(list);
464 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000465 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000466 if (dp->di_size < 0)
467 dp->di_size = PyList_Size(list); /* We just did the work */
468 return list;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000469}
470
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000471static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000472bsddb_has_key(bsddbobject *dp, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000473{
Roger E. Massed9240d11997-01-16 22:05:33 +0000474 DBT krec, drec;
475 int status;
476 char *data;
477 int size;
Fred Drakeed5e8232001-02-27 18:56:46 +0000478 recno_t recno;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000479
Fred Drakeed5e8232001-02-27 18:56:46 +0000480 if (dp->di_type == DB_RECNO) {
481 if (!PyArg_Parse(args, "i", &recno)) {
482 PyErr_SetString(PyExc_TypeError,
483 "key type must be integer");
484 return NULL;
485 }
486 krec.data = &recno;
487 krec.size = sizeof(recno);
488 }
489 else {
490 if (!PyArg_Parse(args, "s#", &data, &size)) {
491 PyErr_SetString(PyExc_TypeError,
492 "key type must be string");
493 return NULL;
494 }
495 krec.data = data;
496 krec.size = size;
497 }
498 check_bsddbobject_open(dp, NULL);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000499
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000500 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000501 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000502 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000503 if (status < 0) {
504 PyErr_SetFromErrno(BsddbError);
505 return NULL;
506 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000507
Roger E. Massed9240d11997-01-16 22:05:33 +0000508 return PyInt_FromLong(status == 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000509}
510
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000511static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000512bsddb_set_location(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000513{
Roger E. Massed9240d11997-01-16 22:05:33 +0000514 int status;
515 DBT krec, drec;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000516 char *data,buf[4096];
Roger E. Massed9240d11997-01-16 22:05:33 +0000517 int size;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000518 PyObject *result;
Fred Drakeed5e8232001-02-27 18:56:46 +0000519 recno_t recno;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000520
Fred Drakeed5e8232001-02-27 18:56:46 +0000521 if (dp->di_type == DB_RECNO) {
522 if (!PyArg_Parse(key, "i", &recno)) {
523 PyErr_SetString(PyExc_TypeError,
524 "key type must be integer");
525 return NULL;
526 }
527 krec.data = &recno;
528 krec.size = sizeof(recno);
529 }
530 else {
531 if (!PyArg_Parse(key, "s#", &data, &size)) {
532 PyErr_SetString(PyExc_TypeError,
533 "key type must be string");
534 return NULL;
535 }
536 krec.data = data;
537 krec.size = size;
538 }
539 check_bsddbobject_open(dp, NULL);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000540
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000541 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000542 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000543 if (status == 0) {
544 if (drec.size > sizeof(buf)) data = malloc(drec.size);
545 else data = buf;
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000546 if (data!=NULL) memcpy(data,drec.data,drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000547 }
548 BSDDB_END_SAVE(dp)
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000549 if (data==NULL) return PyErr_NoMemory();
Roger E. Massed9240d11997-01-16 22:05:33 +0000550 if (status != 0) {
551 if (status < 0)
552 PyErr_SetFromErrno(BsddbError);
553 else
554 PyErr_SetObject(PyExc_KeyError, key);
555 return NULL;
556 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000557
Fred Drakeed5e8232001-02-27 18:56:46 +0000558 if (dp->di_type == DB_RECNO)
559 result = Py_BuildValue("is#", *((int*)krec.data),
560 data, drec.size);
561 else
562 result = Py_BuildValue("s#s#", krec.data, krec.size,
563 data, drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000564 if (data != buf) free(data);
565 return result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000566}
567
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000568static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000569bsddb_seq(bsddbobject *dp, PyObject *args, int sequence_request)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000570{
Roger E. Massed9240d11997-01-16 22:05:33 +0000571 int status;
572 DBT krec, drec;
Guido van Rossum730806d1998-04-10 22:27:42 +0000573 char *kdata=NULL,kbuf[4096];
574 char *ddata=NULL,dbuf[4096];
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000575 PyObject *result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000576
Roger E. Massed9240d11997-01-16 22:05:33 +0000577 if (!PyArg_NoArgs(args))
578 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000579
Fred Drakeed5e8232001-02-27 18:56:46 +0000580 check_bsddbobject_open(dp, NULL);
Roger E. Massed9240d11997-01-16 22:05:33 +0000581 krec.data = 0;
582 krec.size = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000583
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000584 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000585 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec,
586 &drec, sequence_request);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000587 if (status == 0) {
588 if (krec.size > sizeof(kbuf)) kdata = malloc(krec.size);
589 else kdata = kbuf;
Fred Drakeed5e8232001-02-27 18:56:46 +0000590 if (kdata != NULL) memcpy(kdata,krec.data,krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000591 if (drec.size > sizeof(dbuf)) ddata = malloc(drec.size);
592 else ddata = dbuf;
Fred Drakeed5e8232001-02-27 18:56:46 +0000593 if (ddata != NULL) memcpy(ddata,drec.data,drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000594 }
595 BSDDB_END_SAVE(dp)
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000596 if (status == 0) {
Fred Drakeed5e8232001-02-27 18:56:46 +0000597 if ((kdata == NULL) || (ddata == NULL))
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000598 return PyErr_NoMemory();
599 }
600 else {
601 /* (status != 0) */
Roger E. Massed9240d11997-01-16 22:05:33 +0000602 if (status < 0)
603 PyErr_SetFromErrno(BsddbError);
604 else
605 PyErr_SetObject(PyExc_KeyError, args);
606 return NULL;
607 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000608
Fred Drakeed5e8232001-02-27 18:56:46 +0000609
610 if (dp->di_type == DB_RECNO)
611 result = Py_BuildValue("is#", *((int*)kdata),
612 ddata, drec.size);
613 else
614 result = Py_BuildValue("s#s#", kdata, krec.size,
615 ddata, drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000616 if (kdata != kbuf) free(kdata);
617 if (ddata != dbuf) free(ddata);
618 return result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000619}
620
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000621static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000622bsddb_next(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000623{
Roger E. Massed9240d11997-01-16 22:05:33 +0000624 return bsddb_seq(dp, key, R_NEXT);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000625}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000626static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000627bsddb_previous(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000628{
Roger E. Massed9240d11997-01-16 22:05:33 +0000629 return bsddb_seq(dp, key, R_PREV);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000630}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000631static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000632bsddb_first(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000633{
Roger E. Massed9240d11997-01-16 22:05:33 +0000634 return bsddb_seq(dp, key, R_FIRST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000635}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000636static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000637bsddb_last(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000638{
Roger E. Massed9240d11997-01-16 22:05:33 +0000639 return bsddb_seq(dp, key, R_LAST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000640}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000641static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000642bsddb_sync(bsddbobject *dp, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000643{
Roger E. Massed9240d11997-01-16 22:05:33 +0000644 int status;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000645
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000646 if (!PyArg_NoArgs(args))
647 return NULL;
Fred Drakeed5e8232001-02-27 18:56:46 +0000648 check_bsddbobject_open(dp, NULL);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000649 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000650 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000651 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000652 if (status != 0) {
653 PyErr_SetFromErrno(BsddbError);
654 return NULL;
655 }
656 return PyInt_FromLong(status = 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000657}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000658static PyMethodDef bsddb_methods[] = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000659 {"close", (PyCFunction)bsddb_close},
660 {"keys", (PyCFunction)bsddb_keys},
661 {"has_key", (PyCFunction)bsddb_has_key},
662 {"set_location", (PyCFunction)bsddb_set_location},
663 {"next", (PyCFunction)bsddb_next},
664 {"previous", (PyCFunction)bsddb_previous},
665 {"first", (PyCFunction)bsddb_first},
666 {"last", (PyCFunction)bsddb_last},
667 {"sync", (PyCFunction)bsddb_sync},
668 {NULL, NULL} /* sentinel */
Guido van Rossum1100dca1995-08-30 23:43:03 +0000669};
670
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000671static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000672bsddb_getattr(PyObject *dp, char *name)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000673{
Roger E. Massed9240d11997-01-16 22:05:33 +0000674 return Py_FindMethod(bsddb_methods, dp, name);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000675}
676
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000677static PyTypeObject Bsddbtype = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000678 PyObject_HEAD_INIT(NULL)
679 0,
680 "bsddb",
681 sizeof(bsddbobject),
682 0,
683 (destructor)bsddb_dealloc, /*tp_dealloc*/
684 0, /*tp_print*/
685 (getattrfunc)bsddb_getattr, /*tp_getattr*/
686 0, /*tp_setattr*/
687 0, /*tp_compare*/
688 0, /*tp_repr*/
689 0, /*tp_as_number*/
690 0, /*tp_as_sequence*/
691 &bsddb_as_mapping, /*tp_as_mapping*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000692};
693
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000694static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000695bsdhashopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000696{
Roger E. Massed9240d11997-01-16 22:05:33 +0000697 char *file;
698 char *flag = NULL;
699 int flags = O_RDONLY;
700 int mode = 0666;
701 int bsize = 0;
702 int ffactor = 0;
703 int nelem = 0;
704 int cachesize = 0;
705 int hash = 0; /* XXX currently ignored */
706 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000707
Guido van Rossum43713e52000-02-29 13:59:29 +0000708 if (!PyArg_ParseTuple(args, "s|siiiiiii:hashopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000709 &file, &flag, &mode,
710 &bsize, &ffactor, &nelem, &cachesize,
711 &hash, &lorder))
712 return NULL;
713 if (flag != NULL) {
714 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
715 if (flag[0] == 'r')
716 flags = O_RDONLY;
717 else if (flag[0] == 'w')
718 flags = O_RDWR;
719 else if (flag[0] == 'c')
720 flags = O_RDWR|O_CREAT;
721 else if (flag[0] == 'n')
722 flags = O_RDWR|O_CREAT|O_TRUNC;
723 else {
724 PyErr_SetString(BsddbError,
725 "Flag should begin with 'r', 'w', 'c' or 'n'");
726 return NULL;
727 }
728 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000729#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000730 if (flag[0] == 'r')
731 flags |= O_SHLOCK;
732 else
733 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000734#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000735 PyErr_SetString(BsddbError,
736 "locking not supported on this platform");
737 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000738#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000739 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000740 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000741 return newdbhashobject(file, flags, mode,
742 bsize, ffactor, nelem, cachesize, hash, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000743}
744
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000745static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000746bsdbtopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000747{
Roger E. Massed9240d11997-01-16 22:05:33 +0000748 char *file;
749 char *flag = NULL;
750 int flags = O_RDONLY;
751 int mode = 0666;
752 int cachesize = 0;
753 int maxkeypage = 0;
754 int minkeypage = 0;
755 int btflags = 0;
756 unsigned int psize = 0;
757 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000758
Guido van Rossum43713e52000-02-29 13:59:29 +0000759 if (!PyArg_ParseTuple(args, "s|siiiiiii:btopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000760 &file, &flag, &mode,
761 &btflags, &cachesize, &maxkeypage, &minkeypage,
762 &psize, &lorder))
763 return NULL;
764 if (flag != NULL) {
765 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
766 if (flag[0] == 'r')
767 flags = O_RDONLY;
768 else if (flag[0] == 'w')
769 flags = O_RDWR;
770 else if (flag[0] == 'c')
771 flags = O_RDWR|O_CREAT;
772 else if (flag[0] == 'n')
773 flags = O_RDWR|O_CREAT|O_TRUNC;
774 else {
775 PyErr_SetString(BsddbError,
776 "Flag should begin with 'r', 'w', 'c' or 'n'");
777 return NULL;
778 }
779 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000780#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000781 if (flag[0] == 'r')
782 flags |= O_SHLOCK;
783 else
784 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000785#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000786 PyErr_SetString(BsddbError,
787 "locking not supported on this platform");
788 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000789#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000790 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000791 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000792 return newdbbtobject(file, flags, mode,
793 btflags, cachesize, maxkeypage, minkeypage,
794 psize, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000795}
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000796
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000797static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000798bsdrnopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000799{
Roger E. Massed9240d11997-01-16 22:05:33 +0000800 char *file;
801 char *flag = NULL;
802 int flags = O_RDONLY;
803 int mode = 0666;
804 int cachesize = 0;
805 int rnflags = 0;
806 unsigned int psize = 0;
807 int lorder = 0;
808 size_t reclen = 0;
809 char *bval = "";
810 char *bfname = NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000811
Guido van Rossum43713e52000-02-29 13:59:29 +0000812 if (!PyArg_ParseTuple(args, "s|siiiiiiss:rnopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000813 &file, &flag, &mode,
814 &rnflags, &cachesize, &psize, &lorder,
815 &reclen, &bval, &bfname))
816 return NULL;
817
Roger E. Massed9240d11997-01-16 22:05:33 +0000818 if (flag != NULL) {
819 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
820 if (flag[0] == 'r')
821 flags = O_RDONLY;
822 else if (flag[0] == 'w')
823 flags = O_RDWR;
824 else if (flag[0] == 'c')
825 flags = O_RDWR|O_CREAT;
826 else if (flag[0] == 'n')
827 flags = O_RDWR|O_CREAT|O_TRUNC;
828 else {
829 PyErr_SetString(BsddbError,
830 "Flag should begin with 'r', 'w', 'c' or 'n'");
831 return NULL;
832 }
833 if (flag[1] == 'l') {
834#if defined(O_EXLOCK) && defined(O_SHLOCK)
835 if (flag[0] == 'r')
836 flags |= O_SHLOCK;
837 else
838 flags |= O_EXLOCK;
839#else
840 PyErr_SetString(BsddbError,
841 "locking not supported on this platform");
842 return NULL;
843#endif
844 }
845 else if (flag[1] != '\0') {
846 PyErr_SetString(BsddbError,
847 "Flag char 2 should be 'l' or absent");
848 return NULL;
849 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000850 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000851 return newdbrnobject(file, flags, mode, rnflags, cachesize,
852 psize, lorder, reclen, bval[0], bfname);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000853}
854
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000855static PyMethodDef bsddbmodule_methods[] = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000856 {"hashopen", (PyCFunction)bsdhashopen, 1},
857 {"btopen", (PyCFunction)bsdbtopen, 1},
858 {"rnopen", (PyCFunction)bsdrnopen, 1},
859 {0, 0},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000860};
861
Guido van Rossum3886bb61998-12-04 18:50:17 +0000862DL_EXPORT(void)
Thomas Wouters58d05102000-07-24 14:43:35 +0000863initbsddb(void) {
Roger E. Massed9240d11997-01-16 22:05:33 +0000864 PyObject *m, *d;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000865
Roger E. Massed9240d11997-01-16 22:05:33 +0000866 Bsddbtype.ob_type = &PyType_Type;
867 m = Py_InitModule("bsddb", bsddbmodule_methods);
868 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000869 BsddbError = PyErr_NewException("bsddb.error", NULL, NULL);
870 if (BsddbError != NULL)
871 PyDict_SetItemString(d, "error", BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000872}