blob: 3007d3ddb3c0c2e84d5168fde7e724ce84a7a00f [file] [log] [blame]
Guido van Rossum1100dca1995-08-30 23:43:03 +00001/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Berkeley DB interface.
26 Author: Michael McLay
27 Hacked: Guido van Rossum
28 Btree and Recno additions plus sequence methods: David Ely
29
30 XXX To do:
31 - provide interface to the B-tree and record libraries too
32 - provide a way to access the various hash functions
33 - support more open flags
34 */
35
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000036#include "Python.h"
Guido van Rossum1100dca1995-08-30 23:43:03 +000037
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <db.h>
42/* Please don't include internal header files of the Berkeley db package
43 (it messes up the info required in the Setup file) */
44
45typedef struct {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000046 PyObject_HEAD
Guido van Rossum1100dca1995-08-30 23:43:03 +000047 DB *di_bsddb;
48 int di_size; /* -1 means recompute */
49} bsddbobject;
50
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000051staticforward PyTypeObject Bsddbtype;
Guido van Rossum1100dca1995-08-30 23:43:03 +000052
53#define is_bsddbobject(v) ((v)->ob_type == &Bsddbtype)
54
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000055static PyObject *BsddbError;
Guido van Rossum1100dca1995-08-30 23:43:03 +000056
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000057static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +000058newdbhashobject(file, flags, mode,
59 bsize, ffactor, nelem, cachesize, hash, lorder)
60 char *file;
61 int flags;
62 int mode;
63 int bsize;
64 int ffactor;
65 int nelem;
66 int cachesize;
67 int hash; /* XXX ignored */
68 int lorder;
69{
70 bsddbobject *dp;
71 HASHINFO info;
72
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000073 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
Guido van Rossum1100dca1995-08-30 23:43:03 +000074 return NULL;
75
76 info.bsize = bsize;
77 info.ffactor = ffactor;
78 info.nelem = nelem;
79 info.cachesize = cachesize;
80 info.hash = NULL; /* XXX should derive from hash argument */
81 info.lorder = lorder;
82
83 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_HASH, &info)) == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000084 PyErr_SetFromErrno(BsddbError);
85 Py_DECREF(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +000086 return NULL;
87 }
88
89 dp->di_size = -1;
90
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000091 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +000092}
93
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000094static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +000095newdbbtobject(file, flags, mode,
96 btflags, cachesize, maxkeypage, minkeypage, psize, lorder)
97 char *file;
98 int flags;
99 int mode;
100 int btflags;
101 int cachesize;
102 int maxkeypage;
103 int minkeypage;
104 int psize;
105 int lorder;
106{
107 bsddbobject *dp;
108 BTREEINFO info;
109
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000110 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000111 return NULL;
112
113 info.flags = btflags;
114 info.cachesize = cachesize;
115 info.maxkeypage = maxkeypage;
116 info.minkeypage = minkeypage;
117 info.psize = psize;
118 info.lorder = lorder;
119 info.compare = 0; /* Use default comparison functions, for now..*/
120 info.prefix = 0;
121
122 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_BTREE, &info)) == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000123 PyErr_SetFromErrno(BsddbError);
124 Py_DECREF(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000125 return NULL;
126 }
127
128 dp->di_size = -1;
129
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000130 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000131}
132
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000133static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000134newdbrnobject(file, flags, mode,
135 rnflags, cachesize, psize, lorder, reclen, bval, bfname)
136 char *file;
137 int flags;
138 int mode;
139 int rnflags;
140 int cachesize;
141 int psize;
142 int lorder;
143 size_t reclen;
144 u_char bval;
145 char *bfname;
146{
147 bsddbobject *dp;
148 RECNOINFO info;
149
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000150 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000151 return NULL;
152
153 info.flags = rnflags;
154 info.cachesize = cachesize;
155 info.psize = psize;
156 info.lorder = lorder;
157 info.reclen = reclen;
158 info.bval = bval;
159 info.bfname = bfname;
160
161 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info)) == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000162 PyErr_SetFromErrno(BsddbError);
163 Py_DECREF(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000164 return NULL;
165 }
166
167 dp->di_size = -1;
168
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000169 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000170}
171
172
173static void
174bsddb_dealloc(dp)
175 bsddbobject *dp;
176{
177 if (dp->di_bsddb != NULL) {
178 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0)
179 fprintf(stderr,
180 "Python bsddb: close errno %s in dealloc\n", errno);
181 }
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000182 PyMem_DEL(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000183}
184
185static int
186bsddb_length(dp)
187 bsddbobject *dp;
188{
189 if (dp->di_size < 0) {
190 DBT krec, drec;
191 int status;
192 int size = 0;
193 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec,R_FIRST);
194 status == 0;
195 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT))
196 size++;
197 if (status < 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000198 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000199 return -1;
200 }
201 dp->di_size = size;
202 }
203 return dp->di_size;
204}
205
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000206static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000207bsddb_subscript(dp, key)
208 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000209 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000210{
211 int status;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000212 PyObject *v;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000213 DBT krec, drec;
214 char *data;
215 int size;
216
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000217 if (!PyArg_Parse(key, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000218 return NULL;
219 krec.data = data;
220 krec.size = size;
221
222 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
223 if (status != 0) {
224 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000225 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000226 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000227 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000228 return NULL;
229 }
230
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000231 return PyString_FromStringAndSize((char *)drec.data, (int)drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000232}
233
234static int
235bsddb_ass_sub(dp, key, value)
236 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000237 PyObject *key, *value;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000238{
239 int status;
240 DBT krec, drec;
241 char *data;
242 int size;
243
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000244 if (!PyArg_Parse(key, "s#", &data, &size)) {
245 PyErr_SetString(PyExc_TypeError, "bsddb key type must be string");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000246 return -1;
247 }
248 krec.data = data;
249 krec.size = size;
250 dp->di_size = -1;
251 if (value == NULL) {
252 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
253 }
254 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000255 if (!PyArg_Parse(value, "s#", &data, &size)) {
256 PyErr_SetString(PyExc_TypeError, "bsddb value type must be string");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000257 return -1;
258 }
259 drec.data = data;
260 drec.size = size;
261 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
262 }
263 if (status != 0) {
264 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000265 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000266 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000267 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000268 return -1;
269 }
270 return 0;
271}
272
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000273static PyMappingMethods bsddb_as_mapping = {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000274 (inquiry)bsddb_length, /*mp_length*/
275 (binaryfunc)bsddb_subscript, /*mp_subscript*/
276 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
277};
278
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000279static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000280bsddb_close(dp, args)
281 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000282 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000283{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000284 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000285 return NULL;
286 if (dp->di_bsddb != NULL) {
287 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0) {
288 dp->di_bsddb = NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000289 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000290 return NULL;
291 }
292 }
293 dp->di_bsddb = NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000294 Py_INCREF(Py_None);
295 return Py_None;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000296}
297
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000298static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000299bsddb_keys(dp, args)
300 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000301 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000302{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000303 PyObject *list, *item;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000304 DBT krec, drec;
305 int status;
306 int err;
307
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000308 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000309 return NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000310 list = PyList_New(0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000311 if (list == NULL)
312 return NULL;
313 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
314 status == 0;
315 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT)) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000316 item = PyString_FromStringAndSize((char *)krec.data, (int)krec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000317 if (item == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000318 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000319 return NULL;
320 }
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000321 err = PyList_Append(list, item);
322 Py_DECREF(item);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000323 if (err != 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000324 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000325 return NULL;
326 }
327 }
328 if (status < 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000329 PyErr_SetFromErrno(BsddbError);
330 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000331 return NULL;
332 }
333 if (dp->di_size < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000334 dp->di_size = PyList_Size(list); /* We just did the work for this... */
Guido van Rossum1100dca1995-08-30 23:43:03 +0000335 return list;
336}
337
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000338static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000339bsddb_has_key(dp, args)
340 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000341 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000342{
343 DBT krec, drec;
344 int status;
345 char *data;
346 int size;
347
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000348 if (!PyArg_Parse(args, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000349 return NULL;
350 krec.data = data;
351 krec.size = size;
352
353 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
354 if (status < 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000355 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000356 return NULL;
357 }
358
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000359 return PyInt_FromLong(status == 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000360}
361
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000362static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000363bsddb_set_location(dp, key)
364 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000365 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000366{
367 int status;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000368 PyObject *v;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000369 DBT krec, drec;
370 char *data;
371 int size;
372
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000373 if (!PyArg_Parse(key, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000374 return NULL;
375 krec.data = data;
376 krec.size = size;
377
378 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
379 if (status != 0) {
380 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000381 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000382 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000383 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000384 return NULL;
385 }
386
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000387 return Py_BuildValue("s#s#", krec.data, krec.size, drec.data, drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000388}
389
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000390static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000391bsddb_seq(dp, args, sequence_request)
392 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000393 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000394 int sequence_request;
395{
396 int status;
397 DBT krec, drec;
398
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000399 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000400 return NULL;
401
402 krec.data = 0;
403 krec.size = 0;
404
405 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, sequence_request);
406 if (status != 0) {
407 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000408 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000409 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000410 PyErr_SetObject(PyExc_KeyError, args);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000411 return NULL;
412 }
413
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000414 return Py_BuildValue("s#s#", krec.data, krec.size, drec.data, drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000415}
416
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000417static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000418bsddb_next(dp, key)
419 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000420 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000421{
422 return bsddb_seq(dp, key, R_NEXT);
423}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000424static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000425bsddb_previous(dp, key)
426 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000427 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000428{
429 return bsddb_seq(dp, key, R_PREV);
430}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000431static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000432bsddb_first(dp, key)
433 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000434 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000435{
436 return bsddb_seq(dp, key, R_FIRST);
437}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000438static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000439bsddb_last(dp, key)
440 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000441 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000442{
443 return bsddb_seq(dp, key, R_LAST);
444}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000445static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000446bsddb_sync(dp, args)
447 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000448 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000449{
450 int status;
451
452 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
453 if (status != 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000454 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000455 return NULL;
456 }
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000457 return PyInt_FromLong(status = 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000458}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000459static PyMethodDef bsddb_methods[] = {
460 {"close", (PyCFunction)bsddb_close},
461 {"keys", (PyCFunction)bsddb_keys},
462 {"has_key", (PyCFunction)bsddb_has_key},
463 {"set_location", (PyCFunction)bsddb_set_location},
464 {"next", (PyCFunction)bsddb_next},
465 {"previous", (PyCFunction)bsddb_previous},
466 {"first", (PyCFunction)bsddb_first},
467 {"last", (PyCFunction)bsddb_last},
468 {"sync", (PyCFunction)bsddb_sync},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000469 {NULL, NULL} /* sentinel */
470};
471
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000472static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000473bsddb_getattr(dp, name)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000474 PyObject *dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000475 char *name;
476{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000477 return Py_FindMethod(bsddb_methods, dp, name);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000478}
479
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000480static PyTypeObject Bsddbtype = {
481 PyObject_HEAD_INIT(&PyType_Type)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000482 0,
483 "bsddb",
484 sizeof(bsddbobject),
485 0,
486 (destructor)bsddb_dealloc, /*tp_dealloc*/
487 0, /*tp_print*/
488 (getattrfunc)bsddb_getattr, /*tp_getattr*/
489 0, /*tp_setattr*/
490 0, /*tp_compare*/
491 0, /*tp_repr*/
492 0, /*tp_as_number*/
493 0, /*tp_as_sequence*/
494 &bsddb_as_mapping, /*tp_as_mapping*/
495};
496
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000497static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000498bsdhashopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000499 PyObject *self;
500 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000501{
502 char *file;
503 char *flag = NULL;
504 int flags = O_RDONLY;
505 int mode = 0666;
506 int bsize = 0;
507 int ffactor = 0;
508 int nelem = 0;
509 int cachesize = 0;
510 int hash = 0; /* XXX currently ignored */
511 int lorder = 0;
512
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000513 if (!PyArg_ParseTuple(args, "s|siiiiiii",
Guido van Rossum1100dca1995-08-30 23:43:03 +0000514 &file, &flag, &mode,
515 &bsize, &ffactor, &nelem, &cachesize, &hash, &lorder))
516 return NULL;
517 if (flag != NULL) {
518 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
519 if (flag[0] == 'r')
520 flags = O_RDONLY;
521 else if (flag[0] == 'w')
522 flags = O_RDWR;
523 else if (flag[0] == 'c')
524 flags = O_RDWR|O_CREAT;
525 else if (flag[0] == 'n')
526 flags = O_RDWR|O_CREAT|O_TRUNC;
527 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000528 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000529 "Flag should begin with 'r', 'w', 'c' or 'n'");
530 return NULL;
531 }
532 if (flag[1] == 'l') {
533#if defined(O_EXLOCK) && defined(O_SHLOCK)
534 if (flag[0] == 'r')
535 flags |= O_SHLOCK;
536 else
537 flags |= O_EXLOCK;
538#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000539 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000540 return NULL;
541#endif
542 }
543 }
544 return newdbhashobject(file, flags, mode,
545 bsize, ffactor, nelem, cachesize, hash, lorder);
546}
547
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000548static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000549bsdbtopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000550 PyObject *self;
551 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000552{
553 char *file;
554 char *flag = NULL;
555 int flags = O_RDONLY;
556 int mode = 0666;
557 int cachesize = 0;
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000558 int maxkeypage = 0;
559 int minkeypage = 0;
560 int btflags = 0;
561 unsigned int psize = 0;
562 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000563
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000564 if (!PyArg_ParseTuple(args, "s|siiiiiii",
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000565 &file, &flag, &mode,
566 &btflags, &cachesize, &maxkeypage, &minkeypage,
567 &psize, &lorder))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000568 return NULL;
569 if (flag != NULL) {
570 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
571 if (flag[0] == 'r')
572 flags = O_RDONLY;
573 else if (flag[0] == 'w')
574 flags = O_RDWR;
575 else if (flag[0] == 'c')
576 flags = O_RDWR|O_CREAT;
577 else if (flag[0] == 'n')
578 flags = O_RDWR|O_CREAT|O_TRUNC;
579 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000580 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000581 "Flag should begin with 'r', 'w', 'c' or 'n'");
582 return NULL;
583 }
584 if (flag[1] == 'l') {
585#if defined(O_EXLOCK) && defined(O_SHLOCK)
586 if (flag[0] == 'r')
587 flags |= O_SHLOCK;
588 else
589 flags |= O_EXLOCK;
590#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000591 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000592 return NULL;
593#endif
594 }
595 }
596 return newdbbtobject(file, flags, mode,
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000597 btflags, cachesize, maxkeypage, minkeypage,
598 psize, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000599}
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000600
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000601static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000602bsdrnopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000603 PyObject *self;
604 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000605{
606 char *file;
607 char *flag = NULL;
608 int flags = O_RDONLY;
609 int mode = 0666;
610 int cachesize = 0;
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000611 int rnflags = 0;
612 unsigned int psize = 0;
613 int lorder = 0;
614 size_t reclen = 0;
615 char *bval = "";
616 char *bfname = NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000617
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000618 if (!PyArg_ParseTuple(args, "s|siiiiiiss",
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000619 &file, &flag, &mode,
620 &rnflags, &cachesize, &psize, &lorder,
621 &reclen, &bval, &bfname))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000622 return NULL;
623 if (flag != NULL) {
624 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
625 if (flag[0] == 'r')
626 flags = O_RDONLY;
627 else if (flag[0] == 'w')
628 flags = O_RDWR;
629 else if (flag[0] == 'c')
630 flags = O_RDWR|O_CREAT;
631 else if (flag[0] == 'n')
632 flags = O_RDWR|O_CREAT|O_TRUNC;
633 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000634 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000635 "Flag should begin with 'r', 'w', 'c' or 'n'");
636 return NULL;
637 }
638 if (flag[1] == 'l') {
639#if defined(O_EXLOCK) && defined(O_SHLOCK)
640 if (flag[0] == 'r')
641 flags |= O_SHLOCK;
642 else
643 flags |= O_EXLOCK;
644#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000645 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000646 return NULL;
647#endif
648 }
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000649 else if (flag[1] != '\0') {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000650 PyErr_SetString(BsddbError,
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000651 "Flag char 2 should be 'l' or absent");
652 return NULL;
653 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000654 }
655 return newdbrnobject(file, flags, mode,
656 rnflags, cachesize, psize, lorder, bval[0], bfname);
657}
658
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000659static PyMethodDef bsddbmodule_methods[] = {
660 {"hashopen", (PyCFunction)bsdhashopen, 1},
661 {"btopen", (PyCFunction)bsdbtopen, 1},
662 {"rnopen", (PyCFunction)bsdrnopen, 1},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000663 {0, 0},
664};
665
666void
667initbsddb() {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000668 PyObject *m, *d;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000669
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000670 m = Py_InitModule("bsddb", bsddbmodule_methods);
671 d = PyModule_GetDict(m);
672 BsddbError = PyString_FromString("bsddb.error");
673 if (BsddbError == NULL || PyDict_SetItemString(d, "error", BsddbError))
674 Py_FatalError("can't define bsddb.error");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000675}