blob: 203180f8349165316b2662965a271989f4623996 [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
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum1100dca1995-08-30 23:43:03 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum1100dca1995-08-30 23:43:03 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum1100dca1995-08-30 23:43:03 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum1100dca1995-08-30 23:43:03 +000029
30******************************************************************/
31
32/* Berkeley DB interface.
33 Author: Michael McLay
34 Hacked: Guido van Rossum
35 Btree and Recno additions plus sequence methods: David Ely
36
37 XXX To do:
38 - provide interface to the B-tree and record libraries too
39 - provide a way to access the various hash functions
40 - support more open flags
41 */
42
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000043#include "Python.h"
Guido van Rossum1100dca1995-08-30 23:43:03 +000044
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <fcntl.h>
48#include <db.h>
49/* Please don't include internal header files of the Berkeley db package
50 (it messes up the info required in the Setup file) */
51
52typedef struct {
Roger E. Massed9240d11997-01-16 22:05:33 +000053 PyObject_HEAD
54 DB *di_bsddb;
55 int di_size; /* -1 means recompute */
Guido van Rossum1100dca1995-08-30 23:43:03 +000056} bsddbobject;
57
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000058staticforward PyTypeObject Bsddbtype;
Guido van Rossum1100dca1995-08-30 23:43:03 +000059
60#define is_bsddbobject(v) ((v)->ob_type == &Bsddbtype)
61
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000062static PyObject *BsddbError;
Guido van Rossum1100dca1995-08-30 23:43:03 +000063
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000064static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +000065newdbhashobject(file, flags, mode,
66 bsize, ffactor, nelem, cachesize, hash, lorder)
Roger E. Massed9240d11997-01-16 22:05:33 +000067 char *file;
68 int flags;
69 int mode;
70 int bsize;
71 int ffactor;
72 int nelem;
73 int cachesize;
74 int hash; /* XXX ignored */
75 int lorder;
Guido van Rossum1100dca1995-08-30 23:43:03 +000076{
Roger E. Massed9240d11997-01-16 22:05:33 +000077 bsddbobject *dp;
78 HASHINFO info;
Guido van Rossum1100dca1995-08-30 23:43:03 +000079
Roger E. Massed9240d11997-01-16 22:05:33 +000080 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
81 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +000082
Roger E. Massed9240d11997-01-16 22:05:33 +000083 info.bsize = bsize;
84 info.ffactor = ffactor;
85 info.nelem = nelem;
86 info.cachesize = cachesize;
87 info.hash = NULL; /* XXX should derive from hash argument */
88 info.lorder = lorder;
Guido van Rossum1100dca1995-08-30 23:43:03 +000089
Guido van Rossum6beb4791996-09-11 23:22:25 +000090#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +000091 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +000092#endif
Roger E. Massed9240d11997-01-16 22:05:33 +000093 if ((dp->di_bsddb = dbopen(file, flags,
94 mode, DB_HASH, &info)) == NULL) {
95 PyErr_SetFromErrno(BsddbError);
96 Py_DECREF(dp);
97 return NULL;
98 }
Guido van Rossum1100dca1995-08-30 23:43:03 +000099
Roger E. Massed9240d11997-01-16 22:05:33 +0000100 dp->di_size = -1;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000101
Roger E. Massed9240d11997-01-16 22:05:33 +0000102 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000103}
104
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000105static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000106newdbbtobject(file, flags, mode,
Roger E. Massed9240d11997-01-16 22:05:33 +0000107 btflags, cachesize, maxkeypage, minkeypage, psize, lorder)
108 char *file;
109 int flags;
110 int mode;
111 int btflags;
112 int cachesize;
113 int maxkeypage;
114 int minkeypage;
115 int psize;
116 int lorder;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000117{
Roger E. Massed9240d11997-01-16 22:05:33 +0000118 bsddbobject *dp;
119 BTREEINFO info;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000120
Roger E. Massed9240d11997-01-16 22:05:33 +0000121 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
122 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000123
Roger E. Massed9240d11997-01-16 22:05:33 +0000124 info.flags = btflags;
125 info.cachesize = cachesize;
126 info.maxkeypage = maxkeypage;
127 info.minkeypage = minkeypage;
128 info.psize = psize;
129 info.lorder = lorder;
130 info.compare = 0; /* Use default comparison functions, for now..*/
131 info.prefix = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000132
Guido van Rossum6beb4791996-09-11 23:22:25 +0000133#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +0000134 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +0000135#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000136 if ((dp->di_bsddb = dbopen(file, flags,
137 mode, DB_BTREE, &info)) == NULL) {
138 PyErr_SetFromErrno(BsddbError);
139 Py_DECREF(dp);
140 return NULL;
141 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000142
Roger E. Massed9240d11997-01-16 22:05:33 +0000143 dp->di_size = -1;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000144
Roger E. Massed9240d11997-01-16 22:05:33 +0000145 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000146}
147
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000148static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000149newdbrnobject(file, flags, mode,
Roger E. Massed9240d11997-01-16 22:05:33 +0000150 rnflags, cachesize, psize, lorder, reclen, bval, bfname)
151 char *file;
152 int flags;
153 int mode;
154 int rnflags;
155 int cachesize;
156 int psize;
157 int lorder;
158 size_t reclen;
159 u_char bval;
160 char *bfname;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000161{
Roger E. Massed9240d11997-01-16 22:05:33 +0000162 bsddbobject *dp;
163 RECNOINFO info;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000164
Roger E. Massed9240d11997-01-16 22:05:33 +0000165 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
166 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000167
Roger E. Massed9240d11997-01-16 22:05:33 +0000168 info.flags = rnflags;
169 info.cachesize = cachesize;
170 info.psize = psize;
171 info.lorder = lorder;
172 info.reclen = reclen;
173 info.bval = bval;
174 info.bfname = bfname;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000175
Guido van Rossum6beb4791996-09-11 23:22:25 +0000176#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +0000177 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +0000178#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000179 if ((dp->di_bsddb = dbopen(file, flags, mode,
180 DB_RECNO, &info)) == NULL) {
181 PyErr_SetFromErrno(BsddbError);
182 Py_DECREF(dp);
183 return NULL;
184 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000185
Roger E. Massed9240d11997-01-16 22:05:33 +0000186 dp->di_size = -1;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000187
Roger E. Massed9240d11997-01-16 22:05:33 +0000188 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000189}
190
191
192static void
193bsddb_dealloc(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000194 bsddbobject *dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000195{
Roger E. Massed9240d11997-01-16 22:05:33 +0000196 if (dp->di_bsddb != NULL) {
197 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0)
198 fprintf(stderr,
199 "Python bsddb: close errno %d in dealloc\n",
200 errno);
201 }
202 PyMem_DEL(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000203}
204
205static int
206bsddb_length(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000207 bsddbobject *dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000208{
Roger E. Massed9240d11997-01-16 22:05:33 +0000209 if (dp->di_size < 0) {
210 DBT krec, drec;
211 int status;
212 int size = 0;
213 for (status = (dp->di_bsddb->seq)(dp->di_bsddb,
214 &krec, &drec,R_FIRST);
215 status == 0;
216 status = (dp->di_bsddb->seq)(dp->di_bsddb,
217 &krec, &drec, R_NEXT))
218 size++;
219 if (status < 0) {
220 PyErr_SetFromErrno(BsddbError);
221 return -1;
222 }
223 dp->di_size = size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000224 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000225 return dp->di_size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000226}
227
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000228static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000229bsddb_subscript(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000230 bsddbobject *dp;
231 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000232{
Roger E. Massed9240d11997-01-16 22:05:33 +0000233 int status;
234 DBT krec, drec;
235 char *data;
236 int size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000237
Roger E. Massed9240d11997-01-16 22:05:33 +0000238 if (!PyArg_Parse(key, "s#", &data, &size))
239 return NULL;
240 krec.data = data;
241 krec.size = size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000242
Roger E. Massed9240d11997-01-16 22:05:33 +0000243 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
244 if (status != 0) {
245 if (status < 0)
246 PyErr_SetFromErrno(BsddbError);
247 else
248 PyErr_SetObject(PyExc_KeyError, key);
249 return NULL;
250 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000251
Roger E. Massed9240d11997-01-16 22:05:33 +0000252 return PyString_FromStringAndSize((char *)drec.data, (int)drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000253}
254
255static int
256bsddb_ass_sub(dp, key, value)
Roger E. Massed9240d11997-01-16 22:05:33 +0000257 bsddbobject *dp;
258 PyObject *key, *value;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000259{
Roger E. Massed9240d11997-01-16 22:05:33 +0000260 int status;
261 DBT krec, drec;
262 char *data;
263 int size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000264
Roger E. Massed9240d11997-01-16 22:05:33 +0000265 if (!PyArg_Parse(key, "s#", &data, &size)) {
266 PyErr_SetString(PyExc_TypeError,
267 "bsddb key type must be string");
268 return -1;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000269 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000270 krec.data = data;
271 krec.size = size;
272 dp->di_size = -1;
273 if (value == NULL) {
274 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
275 }
276 else {
277 if (!PyArg_Parse(value, "s#", &data, &size)) {
278 PyErr_SetString(PyExc_TypeError,
279 "bsddb value type must be string");
280 return -1;
281 }
282 drec.data = data;
283 drec.size = size;
284#if 0
285 /* For RECNO, put fails with 'No space left on device'
286 after a few short records are added?? Looks fine
287 to this point... linked with 1.85 on Solaris Intel
288 Roger E. Masse 1/16/97
289 */
290 printf("before put data: '%s', size: %d\n",
291 drec.data, drec.size);
292 printf("before put key= '%s', size= %d\n",
293 krec.data, krec.size);
294#endif
295 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
296 }
297 if (status != 0) {
298 if (status < 0)
299 PyErr_SetFromErrno(BsddbError);
300 else
301 PyErr_SetObject(PyExc_KeyError, key);
302 return -1;
303 }
304 return 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000305}
306
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000307static PyMappingMethods bsddb_as_mapping = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000308 (inquiry)bsddb_length, /*mp_length*/
309 (binaryfunc)bsddb_subscript, /*mp_subscript*/
310 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000311};
312
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000313static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000314bsddb_close(dp, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000315 bsddbobject *dp;
316 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000317{
Roger E. Massed9240d11997-01-16 22:05:33 +0000318 if (!PyArg_NoArgs(args))
319 return NULL;
320 if (dp->di_bsddb != NULL) {
321 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0) {
322 dp->di_bsddb = NULL;
323 PyErr_SetFromErrno(BsddbError);
324 return NULL;
325 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000326 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000327 dp->di_bsddb = NULL;
328 Py_INCREF(Py_None);
329 return Py_None;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000330}
331
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000332static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000333bsddb_keys(dp, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000334 bsddbobject *dp;
335 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000336{
Roger E. Massed9240d11997-01-16 22:05:33 +0000337 PyObject *list, *item;
338 DBT krec, drec;
339 int status;
340 int err;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000341
Roger E. Massed9240d11997-01-16 22:05:33 +0000342 if (!PyArg_NoArgs(args))
343 return NULL;
344 list = PyList_New(0);
345 if (list == NULL)
346 return NULL;
347 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
348 status == 0;
349 status = (dp->di_bsddb->seq)(dp->di_bsddb,
350 &krec, &drec, R_NEXT)) {
351 item = PyString_FromStringAndSize((char *)krec.data,
352 (int)krec.size);
353 if (item == NULL) {
354 Py_DECREF(list);
355 return NULL;
356 }
357 err = PyList_Append(list, item);
358 Py_DECREF(item);
359 if (err != 0) {
360 Py_DECREF(list);
361 return NULL;
362 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000363 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000364 if (status < 0) {
365 PyErr_SetFromErrno(BsddbError);
366 Py_DECREF(list);
367 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000368 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000369 if (dp->di_size < 0)
370 dp->di_size = PyList_Size(list); /* We just did the work */
371 return list;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000372}
373
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000374static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000375bsddb_has_key(dp, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000376 bsddbobject *dp;
377 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000378{
Roger E. Massed9240d11997-01-16 22:05:33 +0000379 DBT krec, drec;
380 int status;
381 char *data;
382 int size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000383
Roger E. Massed9240d11997-01-16 22:05:33 +0000384 if (!PyArg_Parse(args, "s#", &data, &size))
385 return NULL;
386 krec.data = data;
387 krec.size = size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000388
Roger E. Massed9240d11997-01-16 22:05:33 +0000389 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
390 if (status < 0) {
391 PyErr_SetFromErrno(BsddbError);
392 return NULL;
393 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000394
Roger E. Massed9240d11997-01-16 22:05:33 +0000395 return PyInt_FromLong(status == 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000396}
397
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000398static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000399bsddb_set_location(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000400 bsddbobject *dp;
401 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000402{
Roger E. Massed9240d11997-01-16 22:05:33 +0000403 int status;
404 DBT krec, drec;
405 char *data;
406 int size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000407
Roger E. Massed9240d11997-01-16 22:05:33 +0000408 if (!PyArg_Parse(key, "s#", &data, &size))
409 return NULL;
410 krec.data = data;
411 krec.size = size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000412
Roger E. Massed9240d11997-01-16 22:05:33 +0000413 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
414 if (status != 0) {
415 if (status < 0)
416 PyErr_SetFromErrno(BsddbError);
417 else
418 PyErr_SetObject(PyExc_KeyError, key);
419 return NULL;
420 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000421
Roger E. Massed9240d11997-01-16 22:05:33 +0000422 return Py_BuildValue("s#s#", krec.data, krec.size,
423 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_seq(dp, args, sequence_request)
Roger E. Massed9240d11997-01-16 22:05:33 +0000428 bsddbobject *dp;
429 PyObject *args;
430 int sequence_request;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000431{
Roger E. Massed9240d11997-01-16 22:05:33 +0000432 int status;
433 DBT krec, drec;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000434
Roger E. Massed9240d11997-01-16 22:05:33 +0000435 if (!PyArg_NoArgs(args))
436 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000437
Roger E. Massed9240d11997-01-16 22:05:33 +0000438 krec.data = 0;
439 krec.size = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000440
Roger E. Massed9240d11997-01-16 22:05:33 +0000441 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec,
442 &drec, sequence_request);
443 if (status != 0) {
444 if (status < 0)
445 PyErr_SetFromErrno(BsddbError);
446 else
447 PyErr_SetObject(PyExc_KeyError, args);
448 return NULL;
449 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000450
Roger E. Massed9240d11997-01-16 22:05:33 +0000451 return Py_BuildValue("s#s#", krec.data, krec.size,
452 drec.data, drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000453}
454
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000455static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000456bsddb_next(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000457 bsddbobject *dp;
458 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000459{
Roger E. Massed9240d11997-01-16 22:05:33 +0000460 return bsddb_seq(dp, key, R_NEXT);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000461}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000462static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000463bsddb_previous(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000464 bsddbobject *dp;
465 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000466{
Roger E. Massed9240d11997-01-16 22:05:33 +0000467 return bsddb_seq(dp, key, R_PREV);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000468}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000469static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000470bsddb_first(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000471 bsddbobject *dp;
472 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000473{
Roger E. Massed9240d11997-01-16 22:05:33 +0000474 return bsddb_seq(dp, key, R_FIRST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000475}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000476static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000477bsddb_last(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000478 bsddbobject *dp;
479 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000480{
Roger E. Massed9240d11997-01-16 22:05:33 +0000481 return bsddb_seq(dp, key, R_LAST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000482}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000483static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000484bsddb_sync(dp, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000485 bsddbobject *dp;
486 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000487{
Roger E. Massed9240d11997-01-16 22:05:33 +0000488 int status;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000489
Roger E. Massed9240d11997-01-16 22:05:33 +0000490 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
491 if (status != 0) {
492 PyErr_SetFromErrno(BsddbError);
493 return NULL;
494 }
495 return PyInt_FromLong(status = 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000496}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000497static PyMethodDef bsddb_methods[] = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000498 {"close", (PyCFunction)bsddb_close},
499 {"keys", (PyCFunction)bsddb_keys},
500 {"has_key", (PyCFunction)bsddb_has_key},
501 {"set_location", (PyCFunction)bsddb_set_location},
502 {"next", (PyCFunction)bsddb_next},
503 {"previous", (PyCFunction)bsddb_previous},
504 {"first", (PyCFunction)bsddb_first},
505 {"last", (PyCFunction)bsddb_last},
506 {"sync", (PyCFunction)bsddb_sync},
507 {NULL, NULL} /* sentinel */
Guido van Rossum1100dca1995-08-30 23:43:03 +0000508};
509
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000510static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000511bsddb_getattr(dp, name)
Roger E. Massed9240d11997-01-16 22:05:33 +0000512 PyObject *dp;
513 char *name;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000514{
Roger E. Massed9240d11997-01-16 22:05:33 +0000515 return Py_FindMethod(bsddb_methods, dp, name);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000516}
517
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000518static PyTypeObject Bsddbtype = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000519 PyObject_HEAD_INIT(NULL)
520 0,
521 "bsddb",
522 sizeof(bsddbobject),
523 0,
524 (destructor)bsddb_dealloc, /*tp_dealloc*/
525 0, /*tp_print*/
526 (getattrfunc)bsddb_getattr, /*tp_getattr*/
527 0, /*tp_setattr*/
528 0, /*tp_compare*/
529 0, /*tp_repr*/
530 0, /*tp_as_number*/
531 0, /*tp_as_sequence*/
532 &bsddb_as_mapping, /*tp_as_mapping*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000533};
534
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000535static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000536bsdhashopen(self, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000537 PyObject *self;
538 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000539{
Roger E. Massed9240d11997-01-16 22:05:33 +0000540 char *file;
541 char *flag = NULL;
542 int flags = O_RDONLY;
543 int mode = 0666;
544 int bsize = 0;
545 int ffactor = 0;
546 int nelem = 0;
547 int cachesize = 0;
548 int hash = 0; /* XXX currently ignored */
549 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000550
Roger E. Massed9240d11997-01-16 22:05:33 +0000551 if (!PyArg_ParseTuple(args, "s|siiiiiii",
552 &file, &flag, &mode,
553 &bsize, &ffactor, &nelem, &cachesize,
554 &hash, &lorder))
555 return NULL;
556 if (flag != NULL) {
557 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
558 if (flag[0] == 'r')
559 flags = O_RDONLY;
560 else if (flag[0] == 'w')
561 flags = O_RDWR;
562 else if (flag[0] == 'c')
563 flags = O_RDWR|O_CREAT;
564 else if (flag[0] == 'n')
565 flags = O_RDWR|O_CREAT|O_TRUNC;
566 else {
567 PyErr_SetString(BsddbError,
568 "Flag should begin with 'r', 'w', 'c' or 'n'");
569 return NULL;
570 }
571 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000572#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000573 if (flag[0] == 'r')
574 flags |= O_SHLOCK;
575 else
576 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000577#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000578 PyErr_SetString(BsddbError,
579 "locking not supported on this platform");
580 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000581#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000582 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000583 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000584 return newdbhashobject(file, flags, mode,
585 bsize, ffactor, nelem, cachesize, hash, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000586}
587
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000588static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000589bsdbtopen(self, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000590 PyObject *self;
591 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000592{
Roger E. Massed9240d11997-01-16 22:05:33 +0000593 char *file;
594 char *flag = NULL;
595 int flags = O_RDONLY;
596 int mode = 0666;
597 int cachesize = 0;
598 int maxkeypage = 0;
599 int minkeypage = 0;
600 int btflags = 0;
601 unsigned int psize = 0;
602 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000603
Roger E. Massed9240d11997-01-16 22:05:33 +0000604 if (!PyArg_ParseTuple(args, "s|siiiiiii",
605 &file, &flag, &mode,
606 &btflags, &cachesize, &maxkeypage, &minkeypage,
607 &psize, &lorder))
608 return NULL;
609 if (flag != NULL) {
610 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
611 if (flag[0] == 'r')
612 flags = O_RDONLY;
613 else if (flag[0] == 'w')
614 flags = O_RDWR;
615 else if (flag[0] == 'c')
616 flags = O_RDWR|O_CREAT;
617 else if (flag[0] == 'n')
618 flags = O_RDWR|O_CREAT|O_TRUNC;
619 else {
620 PyErr_SetString(BsddbError,
621 "Flag should begin with 'r', 'w', 'c' or 'n'");
622 return NULL;
623 }
624 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000625#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000626 if (flag[0] == 'r')
627 flags |= O_SHLOCK;
628 else
629 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000630#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000631 PyErr_SetString(BsddbError,
632 "locking not supported on this platform");
633 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000634#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000635 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000636 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000637 return newdbbtobject(file, flags, mode,
638 btflags, cachesize, maxkeypage, minkeypage,
639 psize, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000640}
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000641
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000642static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000643bsdrnopen(self, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000644 PyObject *self;
645 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000646{
Roger E. Massed9240d11997-01-16 22:05:33 +0000647 char *file;
648 char *flag = NULL;
649 int flags = O_RDONLY;
650 int mode = 0666;
651 int cachesize = 0;
652 int rnflags = 0;
653 unsigned int psize = 0;
654 int lorder = 0;
655 size_t reclen = 0;
656 char *bval = "";
657 char *bfname = NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000658
Roger E. Massed9240d11997-01-16 22:05:33 +0000659 if (!PyArg_ParseTuple(args, "s|siiiiiiss",
660 &file, &flag, &mode,
661 &rnflags, &cachesize, &psize, &lorder,
662 &reclen, &bval, &bfname))
663 return NULL;
664
665# if 0
666 printf("file: %s\n", file);
667 printf("flag: %s\n", flag);
668 printf("mode: %d\n", mode);
669 printf("rnflags: 0x%x\n", rnflags);
670 printf("cachesize: %d\n", cachesize);
671 printf("psize: %d\n", psize);
672 printf("lorder: %d\n", 0);
673 printf("reclen: %d\n", reclen);
674 printf("bval: %c\n", bval[0]);
675 printf("bfname %s\n", bfname);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000676#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000677
678 if (flag != NULL) {
679 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
680 if (flag[0] == 'r')
681 flags = O_RDONLY;
682 else if (flag[0] == 'w')
683 flags = O_RDWR;
684 else if (flag[0] == 'c')
685 flags = O_RDWR|O_CREAT;
686 else if (flag[0] == 'n')
687 flags = O_RDWR|O_CREAT|O_TRUNC;
688 else {
689 PyErr_SetString(BsddbError,
690 "Flag should begin with 'r', 'w', 'c' or 'n'");
691 return NULL;
692 }
693 if (flag[1] == 'l') {
694#if defined(O_EXLOCK) && defined(O_SHLOCK)
695 if (flag[0] == 'r')
696 flags |= O_SHLOCK;
697 else
698 flags |= O_EXLOCK;
699#else
700 PyErr_SetString(BsddbError,
701 "locking not supported on this platform");
702 return NULL;
703#endif
704 }
705 else if (flag[1] != '\0') {
706 PyErr_SetString(BsddbError,
707 "Flag char 2 should be 'l' or absent");
708 return NULL;
709 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000710 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000711 return newdbrnobject(file, flags, mode, rnflags, cachesize,
712 psize, lorder, reclen, bval[0], bfname);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000713}
714
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000715static PyMethodDef bsddbmodule_methods[] = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000716 {"hashopen", (PyCFunction)bsdhashopen, 1},
717 {"btopen", (PyCFunction)bsdbtopen, 1},
718 {"rnopen", (PyCFunction)bsdrnopen, 1},
719 {0, 0},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000720};
721
722void
723initbsddb() {
Roger E. Massed9240d11997-01-16 22:05:33 +0000724 PyObject *m, *d;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000725
Roger E. Massed9240d11997-01-16 22:05:33 +0000726 Bsddbtype.ob_type = &PyType_Type;
727 m = Py_InitModule("bsddb", bsddbmodule_methods);
728 d = PyModule_GetDict(m);
729 BsddbError = PyString_FromString("bsddb.error");
730 if (BsddbError == NULL || PyDict_SetItemString(d, "error", BsddbError))
731 Py_FatalError("can't define bsddb.error");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000732}