blob: ac8c44395f7ebe197baece010d349603e49b6126 [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
Jeremy Hylton938ace62002-07-17 16:30:39 +000042static 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) {
Neal Norwitzb82d34f2002-03-31 15:43:28 +0000473 if (!PyArg_ParseTuple(args, "i;key type must be integer",
474 &recno)) {
Fred Drakeed5e8232001-02-27 18:56:46 +0000475 return NULL;
476 }
477 krec.data = &recno;
478 krec.size = sizeof(recno);
479 }
480 else {
Neal Norwitzb82d34f2002-03-31 15:43:28 +0000481 if (!PyArg_ParseTuple(args, "s#;key type must be string",
482 &data, &size)) {
Fred Drakeed5e8232001-02-27 18:56:46 +0000483 return NULL;
484 }
485 krec.data = data;
486 krec.size = size;
487 }
488 check_bsddbobject_open(dp, NULL);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000489
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000490 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000491 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000492 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000493 if (status < 0) {
494 PyErr_SetFromErrno(BsddbError);
495 return NULL;
496 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000497
Roger E. Massed9240d11997-01-16 22:05:33 +0000498 return PyInt_FromLong(status == 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000499}
500
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000501static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000502bsddb_set_location(bsddbobject *dp, PyObject *key)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000503{
Roger E. Massed9240d11997-01-16 22:05:33 +0000504 int status;
505 DBT krec, drec;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000506 char *data,buf[4096];
Roger E. Massed9240d11997-01-16 22:05:33 +0000507 int size;
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000508 PyObject *result;
Fred Drakeed5e8232001-02-27 18:56:46 +0000509 recno_t recno;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000510
Fred Drakeed5e8232001-02-27 18:56:46 +0000511 if (dp->di_type == DB_RECNO) {
Neal Norwitzb82d34f2002-03-31 15:43:28 +0000512 if (!PyArg_ParseTuple(key, "i;key type must be integer",
513 &recno)) {
Fred Drakeed5e8232001-02-27 18:56:46 +0000514 return NULL;
515 }
516 krec.data = &recno;
517 krec.size = sizeof(recno);
518 }
519 else {
Neal Norwitzb82d34f2002-03-31 15:43:28 +0000520 if (!PyArg_ParseTuple(key, "s#;key type must be string",
521 &data, &size)) {
Fred Drakeed5e8232001-02-27 18:56:46 +0000522 return NULL;
523 }
524 krec.data = data;
525 krec.size = size;
526 }
527 check_bsddbobject_open(dp, NULL);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000528
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000529 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000530 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000531 if (status == 0) {
532 if (drec.size > sizeof(buf)) data = malloc(drec.size);
533 else data = buf;
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000534 if (data!=NULL) memcpy(data,drec.data,drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000535 }
536 BSDDB_END_SAVE(dp)
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000537 if (data==NULL) return PyErr_NoMemory();
Roger E. Massed9240d11997-01-16 22:05:33 +0000538 if (status != 0) {
539 if (status < 0)
540 PyErr_SetFromErrno(BsddbError);
541 else
542 PyErr_SetObject(PyExc_KeyError, key);
543 return NULL;
544 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000545
Fred Drakeed5e8232001-02-27 18:56:46 +0000546 if (dp->di_type == DB_RECNO)
547 result = Py_BuildValue("is#", *((int*)krec.data),
548 data, drec.size);
549 else
550 result = Py_BuildValue("s#s#", krec.data, krec.size,
551 data, drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000552 if (data != buf) free(data);
553 return result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000554}
555
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000556static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000557bsddb_seq(bsddbobject *dp, int sequence_request)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000558{
Roger E. Massed9240d11997-01-16 22:05:33 +0000559 int status;
560 DBT krec, drec;
Guido van Rossum730806d1998-04-10 22:27:42 +0000561 char *kdata=NULL,kbuf[4096];
562 char *ddata=NULL,dbuf[4096];
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000563 PyObject *result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000564
Fred Drakeed5e8232001-02-27 18:56:46 +0000565 check_bsddbobject_open(dp, NULL);
Roger E. Massed9240d11997-01-16 22:05:33 +0000566 krec.data = 0;
567 krec.size = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000568
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000569 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000570 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec,
571 &drec, sequence_request);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000572 if (status == 0) {
573 if (krec.size > sizeof(kbuf)) kdata = malloc(krec.size);
574 else kdata = kbuf;
Fred Drakeed5e8232001-02-27 18:56:46 +0000575 if (kdata != NULL) memcpy(kdata,krec.data,krec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000576 if (drec.size > sizeof(dbuf)) ddata = malloc(drec.size);
577 else ddata = dbuf;
Fred Drakeed5e8232001-02-27 18:56:46 +0000578 if (ddata != NULL) memcpy(ddata,drec.data,drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000579 }
580 BSDDB_END_SAVE(dp)
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000581 if (status == 0) {
Fred Drakeed5e8232001-02-27 18:56:46 +0000582 if ((kdata == NULL) || (ddata == NULL))
Andrew M. Kuchling2e095302000-12-15 00:59:32 +0000583 return PyErr_NoMemory();
584 }
585 else {
586 /* (status != 0) */
Roger E. Massed9240d11997-01-16 22:05:33 +0000587 if (status < 0)
588 PyErr_SetFromErrno(BsddbError);
589 else
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000590 PyErr_SetString(PyExc_KeyError, "no key/data pairs");
Roger E. Massed9240d11997-01-16 22:05:33 +0000591 return NULL;
592 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000593
Fred Drakeed5e8232001-02-27 18:56:46 +0000594 if (dp->di_type == DB_RECNO)
595 result = Py_BuildValue("is#", *((int*)kdata),
596 ddata, drec.size);
597 else
598 result = Py_BuildValue("s#s#", kdata, krec.size,
599 ddata, drec.size);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000600 if (kdata != kbuf) free(kdata);
601 if (ddata != dbuf) free(ddata);
602 return result;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000603}
604
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000605static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000606bsddb_next(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000607{
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000608 return bsddb_seq(dp, R_NEXT);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000609}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000610static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000611bsddb_previous(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000612{
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000613 return bsddb_seq(dp, R_PREV);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000614}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000615static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000616bsddb_first(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000617{
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000618 return bsddb_seq(dp, R_FIRST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000619}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000620static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000621bsddb_last(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000622{
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000623 return bsddb_seq(dp, R_LAST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000624}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000625static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000626bsddb_sync(bsddbobject *dp)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000627{
Roger E. Massed9240d11997-01-16 22:05:33 +0000628 int status;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000629
Fred Drakeed5e8232001-02-27 18:56:46 +0000630 check_bsddbobject_open(dp, NULL);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000631 BSDDB_BGN_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000632 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
Guido van Rossum4f199ea1998-04-09 20:56:35 +0000633 BSDDB_END_SAVE(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000634 if (status != 0) {
635 PyErr_SetFromErrno(BsddbError);
636 return NULL;
637 }
638 return PyInt_FromLong(status = 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000639}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000640static PyMethodDef bsddb_methods[] = {
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000641 {"close", (PyCFunction)bsddb_close, METH_NOARGS},
642 {"keys", (PyCFunction)bsddb_keys, METH_NOARGS},
Neal Norwitzb82d34f2002-03-31 15:43:28 +0000643 {"has_key", (PyCFunction)bsddb_has_key, METH_VARARGS},
644 {"set_location", (PyCFunction)bsddb_set_location, METH_VARARGS},
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000645 {"next", (PyCFunction)bsddb_next, METH_NOARGS},
646 {"previous", (PyCFunction)bsddb_previous, METH_NOARGS},
647 {"first", (PyCFunction)bsddb_first, METH_NOARGS},
648 {"last", (PyCFunction)bsddb_last, METH_NOARGS},
649 {"sync", (PyCFunction)bsddb_sync, METH_NOARGS},
Roger E. Massed9240d11997-01-16 22:05:33 +0000650 {NULL, NULL} /* sentinel */
Guido van Rossum1100dca1995-08-30 23:43:03 +0000651};
652
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000653static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000654bsddb_getattr(PyObject *dp, char *name)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000655{
Roger E. Massed9240d11997-01-16 22:05:33 +0000656 return Py_FindMethod(bsddb_methods, dp, name);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000657}
658
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000659static PyTypeObject Bsddbtype = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000660 PyObject_HEAD_INIT(NULL)
661 0,
Guido van Rossum14648392001-12-08 18:02:58 +0000662 "bsddb.bsddb",
Roger E. Massed9240d11997-01-16 22:05:33 +0000663 sizeof(bsddbobject),
664 0,
665 (destructor)bsddb_dealloc, /*tp_dealloc*/
666 0, /*tp_print*/
667 (getattrfunc)bsddb_getattr, /*tp_getattr*/
668 0, /*tp_setattr*/
669 0, /*tp_compare*/
670 0, /*tp_repr*/
671 0, /*tp_as_number*/
672 0, /*tp_as_sequence*/
673 &bsddb_as_mapping, /*tp_as_mapping*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000674};
675
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000676static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000677bsdhashopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000678{
Roger E. Massed9240d11997-01-16 22:05:33 +0000679 char *file;
680 char *flag = NULL;
681 int flags = O_RDONLY;
682 int mode = 0666;
683 int bsize = 0;
684 int ffactor = 0;
685 int nelem = 0;
686 int cachesize = 0;
687 int hash = 0; /* XXX currently ignored */
688 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000689
Anthony Baxter83888952002-04-23 02:11:05 +0000690 if (!PyArg_ParseTuple(args, "z|siiiiiii:hashopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000691 &file, &flag, &mode,
692 &bsize, &ffactor, &nelem, &cachesize,
693 &hash, &lorder))
694 return NULL;
695 if (flag != NULL) {
696 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
697 if (flag[0] == 'r')
698 flags = O_RDONLY;
699 else if (flag[0] == 'w')
700 flags = O_RDWR;
701 else if (flag[0] == 'c')
702 flags = O_RDWR|O_CREAT;
703 else if (flag[0] == 'n')
704 flags = O_RDWR|O_CREAT|O_TRUNC;
705 else {
706 PyErr_SetString(BsddbError,
707 "Flag should begin with 'r', 'w', 'c' or 'n'");
708 return NULL;
709 }
710 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000711#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000712 if (flag[0] == 'r')
713 flags |= O_SHLOCK;
714 else
715 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000716#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000717 PyErr_SetString(BsddbError,
718 "locking not supported on this platform");
719 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000720#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000721 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000722 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000723 return newdbhashobject(file, flags, mode,
724 bsize, ffactor, nelem, cachesize, hash, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000725}
726
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000727static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000728bsdbtopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000729{
Roger E. Massed9240d11997-01-16 22:05:33 +0000730 char *file;
731 char *flag = NULL;
732 int flags = O_RDONLY;
733 int mode = 0666;
734 int cachesize = 0;
735 int maxkeypage = 0;
736 int minkeypage = 0;
737 int btflags = 0;
738 unsigned int psize = 0;
739 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000740
Anthony Baxter83888952002-04-23 02:11:05 +0000741 if (!PyArg_ParseTuple(args, "z|siiiiiii:btopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000742 &file, &flag, &mode,
743 &btflags, &cachesize, &maxkeypage, &minkeypage,
744 &psize, &lorder))
745 return NULL;
746 if (flag != NULL) {
747 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
748 if (flag[0] == 'r')
749 flags = O_RDONLY;
750 else if (flag[0] == 'w')
751 flags = O_RDWR;
752 else if (flag[0] == 'c')
753 flags = O_RDWR|O_CREAT;
754 else if (flag[0] == 'n')
755 flags = O_RDWR|O_CREAT|O_TRUNC;
756 else {
757 PyErr_SetString(BsddbError,
758 "Flag should begin with 'r', 'w', 'c' or 'n'");
759 return NULL;
760 }
761 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000762#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000763 if (flag[0] == 'r')
764 flags |= O_SHLOCK;
765 else
766 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000767#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000768 PyErr_SetString(BsddbError,
769 "locking not supported on this platform");
770 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000771#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000772 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000773 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000774 return newdbbtobject(file, flags, mode,
775 btflags, cachesize, maxkeypage, minkeypage,
776 psize, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000777}
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000778
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000779static PyObject *
Peter Schneider-Kampcb27c352000-07-10 17:06:38 +0000780bsdrnopen(PyObject *self, PyObject *args)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000781{
Roger E. Massed9240d11997-01-16 22:05:33 +0000782 char *file;
783 char *flag = NULL;
784 int flags = O_RDONLY;
785 int mode = 0666;
786 int cachesize = 0;
787 int rnflags = 0;
788 unsigned int psize = 0;
789 int lorder = 0;
790 size_t reclen = 0;
791 char *bval = "";
792 char *bfname = NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000793
Anthony Baxter83888952002-04-23 02:11:05 +0000794 if (!PyArg_ParseTuple(args, "z|siiiiiiss:rnopen",
Roger E. Massed9240d11997-01-16 22:05:33 +0000795 &file, &flag, &mode,
796 &rnflags, &cachesize, &psize, &lorder,
797 &reclen, &bval, &bfname))
798 return NULL;
799
Roger E. Massed9240d11997-01-16 22:05:33 +0000800 if (flag != NULL) {
801 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
802 if (flag[0] == 'r')
803 flags = O_RDONLY;
804 else if (flag[0] == 'w')
805 flags = O_RDWR;
806 else if (flag[0] == 'c')
807 flags = O_RDWR|O_CREAT;
808 else if (flag[0] == 'n')
809 flags = O_RDWR|O_CREAT|O_TRUNC;
810 else {
811 PyErr_SetString(BsddbError,
812 "Flag should begin with 'r', 'w', 'c' or 'n'");
813 return NULL;
814 }
815 if (flag[1] == 'l') {
816#if defined(O_EXLOCK) && defined(O_SHLOCK)
817 if (flag[0] == 'r')
818 flags |= O_SHLOCK;
819 else
820 flags |= O_EXLOCK;
821#else
822 PyErr_SetString(BsddbError,
823 "locking not supported on this platform");
824 return NULL;
825#endif
826 }
827 else if (flag[1] != '\0') {
828 PyErr_SetString(BsddbError,
829 "Flag char 2 should be 'l' or absent");
830 return NULL;
831 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000832 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000833 return newdbrnobject(file, flags, mode, rnflags, cachesize,
834 psize, lorder, reclen, bval[0], bfname);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000835}
836
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000837static PyMethodDef bsddbmodule_methods[] = {
Martin v. Löwis43b936d2002-01-17 23:15:58 +0000838 {"hashopen", (PyCFunction)bsdhashopen, METH_VARARGS},
839 {"btopen", (PyCFunction)bsdbtopen, METH_VARARGS},
840 {"rnopen", (PyCFunction)bsdrnopen, METH_VARARGS},
Skip Montanaroc797ceb2003-05-06 20:38:52 +0000841 /* strictly for use by dbhhash!!! */
842 {"open", (PyCFunction)bsdhashopen, METH_VARARGS},
Roger E. Massed9240d11997-01-16 22:05:33 +0000843 {0, 0},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000844};
845
Mark Hammond62b1ab12002-07-23 06:31:15 +0000846PyMODINIT_FUNC
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000847initbsddb185(void) {
Roger E. Massed9240d11997-01-16 22:05:33 +0000848 PyObject *m, *d;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000849
Roger E. Massed9240d11997-01-16 22:05:33 +0000850 Bsddbtype.ob_type = &PyType_Type;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000851 m = Py_InitModule("bsddb185", bsddbmodule_methods);
Roger E. Massed9240d11997-01-16 22:05:33 +0000852 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000853 BsddbError = PyErr_NewException("bsddb.error", NULL, NULL);
854 if (BsddbError != NULL)
855 PyDict_SetItemString(d, "error", BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000856}