blob: dd71005a8b139385c99dc09b8d38a17392766899 [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
Guido van Rossum6beb4791996-09-11 23:22:25 +000083#ifdef O_BINARY
84 flags |= O_BINARY;
85#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +000086 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_HASH, &info)) == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000087 PyErr_SetFromErrno(BsddbError);
88 Py_DECREF(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +000089 return NULL;
90 }
91
92 dp->di_size = -1;
93
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000094 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +000095}
96
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000097static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +000098newdbbtobject(file, flags, mode,
99 btflags, cachesize, maxkeypage, minkeypage, psize, lorder)
100 char *file;
101 int flags;
102 int mode;
103 int btflags;
104 int cachesize;
105 int maxkeypage;
106 int minkeypage;
107 int psize;
108 int lorder;
109{
110 bsddbobject *dp;
111 BTREEINFO info;
112
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000113 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000114 return NULL;
115
116 info.flags = btflags;
117 info.cachesize = cachesize;
118 info.maxkeypage = maxkeypage;
119 info.minkeypage = minkeypage;
120 info.psize = psize;
121 info.lorder = lorder;
Guido van Rossum6beb4791996-09-11 23:22:25 +0000122 info.compare = 0; /* Use default comparison functions, for now..*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000123 info.prefix = 0;
124
Guido van Rossum6beb4791996-09-11 23:22:25 +0000125#ifdef O_BINARY
126 flags |= O_BINARY;
127#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +0000128 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_BTREE, &info)) == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000129 PyErr_SetFromErrno(BsddbError);
130 Py_DECREF(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000131 return NULL;
132 }
133
134 dp->di_size = -1;
135
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000136 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000137}
138
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000139static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000140newdbrnobject(file, flags, mode,
141 rnflags, cachesize, psize, lorder, reclen, bval, bfname)
142 char *file;
143 int flags;
144 int mode;
145 int rnflags;
146 int cachesize;
147 int psize;
148 int lorder;
149 size_t reclen;
150 u_char bval;
151 char *bfname;
152{
153 bsddbobject *dp;
154 RECNOINFO info;
155
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000156 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000157 return NULL;
158
159 info.flags = rnflags;
160 info.cachesize = cachesize;
161 info.psize = psize;
162 info.lorder = lorder;
163 info.reclen = reclen;
164 info.bval = bval;
165 info.bfname = bfname;
166
Guido van Rossum6beb4791996-09-11 23:22:25 +0000167#ifdef O_BINARY
168 flags |= O_BINARY;
169#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +0000170 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info)) == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000171 PyErr_SetFromErrno(BsddbError);
172 Py_DECREF(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000173 return NULL;
174 }
175
176 dp->di_size = -1;
177
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000178 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000179}
180
181
182static void
183bsddb_dealloc(dp)
184 bsddbobject *dp;
185{
186 if (dp->di_bsddb != NULL) {
187 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0)
188 fprintf(stderr,
189 "Python bsddb: close errno %s in dealloc\n", errno);
190 }
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000191 PyMem_DEL(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000192}
193
194static int
195bsddb_length(dp)
196 bsddbobject *dp;
197{
198 if (dp->di_size < 0) {
199 DBT krec, drec;
200 int status;
201 int size = 0;
202 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec,R_FIRST);
203 status == 0;
204 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT))
205 size++;
206 if (status < 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000207 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000208 return -1;
209 }
210 dp->di_size = size;
211 }
212 return dp->di_size;
213}
214
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000215static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000216bsddb_subscript(dp, key)
217 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000218 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000219{
220 int status;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000221 PyObject *v;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000222 DBT krec, drec;
223 char *data;
224 int size;
225
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000226 if (!PyArg_Parse(key, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000227 return NULL;
228 krec.data = data;
229 krec.size = size;
230
231 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
232 if (status != 0) {
233 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000234 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000235 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000236 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000237 return NULL;
238 }
239
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000240 return PyString_FromStringAndSize((char *)drec.data, (int)drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000241}
242
243static int
244bsddb_ass_sub(dp, key, value)
245 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000246 PyObject *key, *value;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000247{
248 int status;
249 DBT krec, drec;
250 char *data;
251 int size;
252
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000253 if (!PyArg_Parse(key, "s#", &data, &size)) {
254 PyErr_SetString(PyExc_TypeError, "bsddb key type must be string");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000255 return -1;
256 }
257 krec.data = data;
258 krec.size = size;
259 dp->di_size = -1;
260 if (value == NULL) {
261 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
262 }
263 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000264 if (!PyArg_Parse(value, "s#", &data, &size)) {
265 PyErr_SetString(PyExc_TypeError, "bsddb value type must be string");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000266 return -1;
267 }
268 drec.data = data;
269 drec.size = size;
270 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
271 }
272 if (status != 0) {
273 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000274 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000275 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000276 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000277 return -1;
278 }
279 return 0;
280}
281
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000282static PyMappingMethods bsddb_as_mapping = {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000283 (inquiry)bsddb_length, /*mp_length*/
284 (binaryfunc)bsddb_subscript, /*mp_subscript*/
285 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
286};
287
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000288static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000289bsddb_close(dp, args)
290 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000291 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000292{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000293 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000294 return NULL;
295 if (dp->di_bsddb != NULL) {
296 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0) {
297 dp->di_bsddb = NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000298 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000299 return NULL;
300 }
301 }
302 dp->di_bsddb = NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000303 Py_INCREF(Py_None);
304 return Py_None;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000305}
306
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000307static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000308bsddb_keys(dp, args)
309 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000310 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000311{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000312 PyObject *list, *item;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000313 DBT krec, drec;
314 int status;
315 int err;
316
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000317 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000318 return NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000319 list = PyList_New(0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000320 if (list == NULL)
321 return NULL;
322 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
323 status == 0;
324 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT)) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000325 item = PyString_FromStringAndSize((char *)krec.data, (int)krec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000326 if (item == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000327 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000328 return NULL;
329 }
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000330 err = PyList_Append(list, item);
331 Py_DECREF(item);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000332 if (err != 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000333 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000334 return NULL;
335 }
336 }
337 if (status < 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000338 PyErr_SetFromErrno(BsddbError);
339 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000340 return NULL;
341 }
342 if (dp->di_size < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000343 dp->di_size = PyList_Size(list); /* We just did the work for this... */
Guido van Rossum1100dca1995-08-30 23:43:03 +0000344 return list;
345}
346
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000347static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000348bsddb_has_key(dp, args)
349 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000350 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000351{
352 DBT krec, drec;
353 int status;
354 char *data;
355 int size;
356
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000357 if (!PyArg_Parse(args, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000358 return NULL;
359 krec.data = data;
360 krec.size = size;
361
362 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
363 if (status < 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000364 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000365 return NULL;
366 }
367
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000368 return PyInt_FromLong(status == 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000369}
370
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000371static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000372bsddb_set_location(dp, key)
373 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000374 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000375{
376 int status;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000377 PyObject *v;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000378 DBT krec, drec;
379 char *data;
380 int size;
381
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000382 if (!PyArg_Parse(key, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000383 return NULL;
384 krec.data = data;
385 krec.size = size;
386
387 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
388 if (status != 0) {
389 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000390 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000391 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000392 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000393 return NULL;
394 }
395
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000396 return Py_BuildValue("s#s#", krec.data, krec.size, drec.data, drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000397}
398
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000399static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000400bsddb_seq(dp, args, sequence_request)
401 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000402 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000403 int sequence_request;
404{
405 int status;
406 DBT krec, drec;
407
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000408 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000409 return NULL;
410
411 krec.data = 0;
412 krec.size = 0;
413
414 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, sequence_request);
415 if (status != 0) {
416 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000417 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000418 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000419 PyErr_SetObject(PyExc_KeyError, args);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000420 return NULL;
421 }
422
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000423 return Py_BuildValue("s#s#", krec.data, krec.size, drec.data, drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000424}
425
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000426static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000427bsddb_next(dp, key)
428 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000429 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000430{
431 return bsddb_seq(dp, key, R_NEXT);
432}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000433static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000434bsddb_previous(dp, key)
435 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000436 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000437{
438 return bsddb_seq(dp, key, R_PREV);
439}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000440static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000441bsddb_first(dp, key)
442 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000443 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000444{
445 return bsddb_seq(dp, key, R_FIRST);
446}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000447static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000448bsddb_last(dp, key)
449 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000450 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000451{
452 return bsddb_seq(dp, key, R_LAST);
453}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000454static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000455bsddb_sync(dp, args)
456 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000457 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000458{
459 int status;
460
461 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
462 if (status != 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000463 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000464 return NULL;
465 }
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000466 return PyInt_FromLong(status = 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000467}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000468static PyMethodDef bsddb_methods[] = {
469 {"close", (PyCFunction)bsddb_close},
470 {"keys", (PyCFunction)bsddb_keys},
471 {"has_key", (PyCFunction)bsddb_has_key},
472 {"set_location", (PyCFunction)bsddb_set_location},
473 {"next", (PyCFunction)bsddb_next},
474 {"previous", (PyCFunction)bsddb_previous},
475 {"first", (PyCFunction)bsddb_first},
476 {"last", (PyCFunction)bsddb_last},
477 {"sync", (PyCFunction)bsddb_sync},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000478 {NULL, NULL} /* sentinel */
479};
480
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000481static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000482bsddb_getattr(dp, name)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000483 PyObject *dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000484 char *name;
485{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000486 return Py_FindMethod(bsddb_methods, dp, name);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000487}
488
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000489static PyTypeObject Bsddbtype = {
Guido van Rossum622f5771996-09-11 23:18:43 +0000490 PyObject_HEAD_INIT(NULL)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000491 0,
492 "bsddb",
493 sizeof(bsddbobject),
494 0,
495 (destructor)bsddb_dealloc, /*tp_dealloc*/
496 0, /*tp_print*/
497 (getattrfunc)bsddb_getattr, /*tp_getattr*/
498 0, /*tp_setattr*/
499 0, /*tp_compare*/
500 0, /*tp_repr*/
501 0, /*tp_as_number*/
502 0, /*tp_as_sequence*/
503 &bsddb_as_mapping, /*tp_as_mapping*/
504};
505
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000506static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000507bsdhashopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000508 PyObject *self;
509 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000510{
511 char *file;
512 char *flag = NULL;
513 int flags = O_RDONLY;
514 int mode = 0666;
515 int bsize = 0;
516 int ffactor = 0;
517 int nelem = 0;
518 int cachesize = 0;
519 int hash = 0; /* XXX currently ignored */
520 int lorder = 0;
521
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000522 if (!PyArg_ParseTuple(args, "s|siiiiiii",
Guido van Rossum1100dca1995-08-30 23:43:03 +0000523 &file, &flag, &mode,
524 &bsize, &ffactor, &nelem, &cachesize, &hash, &lorder))
525 return NULL;
526 if (flag != NULL) {
527 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
528 if (flag[0] == 'r')
529 flags = O_RDONLY;
530 else if (flag[0] == 'w')
531 flags = O_RDWR;
532 else if (flag[0] == 'c')
533 flags = O_RDWR|O_CREAT;
534 else if (flag[0] == 'n')
535 flags = O_RDWR|O_CREAT|O_TRUNC;
536 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000537 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000538 "Flag should begin with 'r', 'w', 'c' or 'n'");
539 return NULL;
540 }
541 if (flag[1] == 'l') {
542#if defined(O_EXLOCK) && defined(O_SHLOCK)
543 if (flag[0] == 'r')
544 flags |= O_SHLOCK;
545 else
546 flags |= O_EXLOCK;
547#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000548 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000549 return NULL;
550#endif
551 }
552 }
553 return newdbhashobject(file, flags, mode,
554 bsize, ffactor, nelem, cachesize, hash, lorder);
555}
556
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000557static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000558bsdbtopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000559 PyObject *self;
560 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000561{
562 char *file;
563 char *flag = NULL;
564 int flags = O_RDONLY;
565 int mode = 0666;
566 int cachesize = 0;
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000567 int maxkeypage = 0;
568 int minkeypage = 0;
569 int btflags = 0;
570 unsigned int psize = 0;
571 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000572
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000573 if (!PyArg_ParseTuple(args, "s|siiiiiii",
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000574 &file, &flag, &mode,
575 &btflags, &cachesize, &maxkeypage, &minkeypage,
576 &psize, &lorder))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000577 return NULL;
578 if (flag != NULL) {
579 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
580 if (flag[0] == 'r')
581 flags = O_RDONLY;
582 else if (flag[0] == 'w')
583 flags = O_RDWR;
584 else if (flag[0] == 'c')
585 flags = O_RDWR|O_CREAT;
586 else if (flag[0] == 'n')
587 flags = O_RDWR|O_CREAT|O_TRUNC;
588 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000589 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000590 "Flag should begin with 'r', 'w', 'c' or 'n'");
591 return NULL;
592 }
593 if (flag[1] == 'l') {
594#if defined(O_EXLOCK) && defined(O_SHLOCK)
595 if (flag[0] == 'r')
596 flags |= O_SHLOCK;
597 else
598 flags |= O_EXLOCK;
599#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000600 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000601 return NULL;
602#endif
603 }
604 }
605 return newdbbtobject(file, flags, mode,
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000606 btflags, cachesize, maxkeypage, minkeypage,
607 psize, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000608}
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000609
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000610static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000611bsdrnopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000612 PyObject *self;
613 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000614{
615 char *file;
616 char *flag = NULL;
617 int flags = O_RDONLY;
618 int mode = 0666;
619 int cachesize = 0;
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000620 int rnflags = 0;
621 unsigned int psize = 0;
622 int lorder = 0;
623 size_t reclen = 0;
624 char *bval = "";
625 char *bfname = NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000626
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000627 if (!PyArg_ParseTuple(args, "s|siiiiiiss",
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000628 &file, &flag, &mode,
629 &rnflags, &cachesize, &psize, &lorder,
630 &reclen, &bval, &bfname))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000631 return NULL;
632 if (flag != NULL) {
633 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
634 if (flag[0] == 'r')
635 flags = O_RDONLY;
636 else if (flag[0] == 'w')
637 flags = O_RDWR;
638 else if (flag[0] == 'c')
639 flags = O_RDWR|O_CREAT;
640 else if (flag[0] == 'n')
641 flags = O_RDWR|O_CREAT|O_TRUNC;
642 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000643 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000644 "Flag should begin with 'r', 'w', 'c' or 'n'");
645 return NULL;
646 }
647 if (flag[1] == 'l') {
648#if defined(O_EXLOCK) && defined(O_SHLOCK)
649 if (flag[0] == 'r')
650 flags |= O_SHLOCK;
651 else
652 flags |= O_EXLOCK;
653#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000654 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000655 return NULL;
656#endif
657 }
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000658 else if (flag[1] != '\0') {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000659 PyErr_SetString(BsddbError,
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000660 "Flag char 2 should be 'l' or absent");
661 return NULL;
662 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000663 }
664 return newdbrnobject(file, flags, mode,
665 rnflags, cachesize, psize, lorder, bval[0], bfname);
666}
667
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000668static PyMethodDef bsddbmodule_methods[] = {
669 {"hashopen", (PyCFunction)bsdhashopen, 1},
670 {"btopen", (PyCFunction)bsdbtopen, 1},
671 {"rnopen", (PyCFunction)bsdrnopen, 1},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000672 {0, 0},
673};
674
675void
676initbsddb() {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000677 PyObject *m, *d;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000678
Guido van Rossum622f5771996-09-11 23:18:43 +0000679 Bsddbtype.ob_type = &PyType_Type;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000680 m = Py_InitModule("bsddb", bsddbmodule_methods);
681 d = PyModule_GetDict(m);
682 BsddbError = PyString_FromString("bsddb.error");
683 if (BsddbError == NULL || PyDict_SetItemString(d, "error", BsddbError))
684 Py_FatalError("can't define bsddb.error");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000685}