blob: 0c9915a062959d7b68e3a55e56654961d39ad177 [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)
Guido van Rossum77eecfa1997-07-17 22:56:01 +000061#define check_bsddbobject_open(v) if ((v)->di_bsddb == NULL) \
62 { PyErr_SetString(BsddbError, "BSDDB object has already been closed"); \
63 return NULL; }
Guido van Rossum1100dca1995-08-30 23:43:03 +000064
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000065static PyObject *BsddbError;
Guido van Rossum1100dca1995-08-30 23:43:03 +000066
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000067static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +000068newdbhashobject(file, flags, mode,
69 bsize, ffactor, nelem, cachesize, hash, lorder)
Roger E. Massed9240d11997-01-16 22:05:33 +000070 char *file;
71 int flags;
72 int mode;
73 int bsize;
74 int ffactor;
75 int nelem;
76 int cachesize;
77 int hash; /* XXX ignored */
78 int lorder;
Guido van Rossum1100dca1995-08-30 23:43:03 +000079{
Roger E. Massed9240d11997-01-16 22:05:33 +000080 bsddbobject *dp;
81 HASHINFO info;
Guido van Rossum1100dca1995-08-30 23:43:03 +000082
Roger E. Massed9240d11997-01-16 22:05:33 +000083 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
84 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +000085
Roger E. Massed9240d11997-01-16 22:05:33 +000086 info.bsize = bsize;
87 info.ffactor = ffactor;
88 info.nelem = nelem;
89 info.cachesize = cachesize;
90 info.hash = NULL; /* XXX should derive from hash argument */
91 info.lorder = lorder;
Guido van Rossum1100dca1995-08-30 23:43:03 +000092
Guido van Rossum6beb4791996-09-11 23:22:25 +000093#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +000094 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +000095#endif
Roger E. Massed9240d11997-01-16 22:05:33 +000096 if ((dp->di_bsddb = dbopen(file, flags,
97 mode, DB_HASH, &info)) == NULL) {
98 PyErr_SetFromErrno(BsddbError);
99 Py_DECREF(dp);
100 return NULL;
101 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000102
Roger E. Massed9240d11997-01-16 22:05:33 +0000103 dp->di_size = -1;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000104
Roger E. Massed9240d11997-01-16 22:05:33 +0000105 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000106}
107
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000108static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000109newdbbtobject(file, flags, mode,
Roger E. Massed9240d11997-01-16 22:05:33 +0000110 btflags, cachesize, maxkeypage, minkeypage, psize, lorder)
111 char *file;
112 int flags;
113 int mode;
114 int btflags;
115 int cachesize;
116 int maxkeypage;
117 int minkeypage;
118 int psize;
119 int lorder;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000120{
Roger E. Massed9240d11997-01-16 22:05:33 +0000121 bsddbobject *dp;
122 BTREEINFO info;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000123
Roger E. Massed9240d11997-01-16 22:05:33 +0000124 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
125 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000126
Roger E. Massed9240d11997-01-16 22:05:33 +0000127 info.flags = btflags;
128 info.cachesize = cachesize;
129 info.maxkeypage = maxkeypage;
130 info.minkeypage = minkeypage;
131 info.psize = psize;
132 info.lorder = lorder;
133 info.compare = 0; /* Use default comparison functions, for now..*/
134 info.prefix = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000135
Guido van Rossum6beb4791996-09-11 23:22:25 +0000136#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +0000137 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +0000138#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000139 if ((dp->di_bsddb = dbopen(file, flags,
140 mode, DB_BTREE, &info)) == NULL) {
141 PyErr_SetFromErrno(BsddbError);
142 Py_DECREF(dp);
143 return NULL;
144 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000145
Roger E. Massed9240d11997-01-16 22:05:33 +0000146 dp->di_size = -1;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000147
Roger E. Massed9240d11997-01-16 22:05:33 +0000148 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000149}
150
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000151static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000152newdbrnobject(file, flags, mode,
Roger E. Massed9240d11997-01-16 22:05:33 +0000153 rnflags, cachesize, psize, lorder, reclen, bval, bfname)
154 char *file;
155 int flags;
156 int mode;
157 int rnflags;
158 int cachesize;
159 int psize;
160 int lorder;
161 size_t reclen;
162 u_char bval;
163 char *bfname;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000164{
Roger E. Massed9240d11997-01-16 22:05:33 +0000165 bsddbobject *dp;
166 RECNOINFO info;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000167
Roger E. Massed9240d11997-01-16 22:05:33 +0000168 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
169 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000170
Roger E. Massed9240d11997-01-16 22:05:33 +0000171 info.flags = rnflags;
172 info.cachesize = cachesize;
173 info.psize = psize;
174 info.lorder = lorder;
175 info.reclen = reclen;
176 info.bval = bval;
177 info.bfname = bfname;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000178
Guido van Rossum6beb4791996-09-11 23:22:25 +0000179#ifdef O_BINARY
Roger E. Massed9240d11997-01-16 22:05:33 +0000180 flags |= O_BINARY;
Guido van Rossum6beb4791996-09-11 23:22:25 +0000181#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000182 if ((dp->di_bsddb = dbopen(file, flags, mode,
183 DB_RECNO, &info)) == NULL) {
184 PyErr_SetFromErrno(BsddbError);
185 Py_DECREF(dp);
186 return NULL;
187 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000188
Roger E. Massed9240d11997-01-16 22:05:33 +0000189 dp->di_size = -1;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000190
Roger E. Massed9240d11997-01-16 22:05:33 +0000191 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000192}
193
194
195static void
196bsddb_dealloc(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000197 bsddbobject *dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000198{
Roger E. Massed9240d11997-01-16 22:05:33 +0000199 if (dp->di_bsddb != NULL) {
200 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0)
201 fprintf(stderr,
202 "Python bsddb: close errno %d in dealloc\n",
203 errno);
204 }
205 PyMem_DEL(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000206}
207
208static int
209bsddb_length(dp)
Roger E. Massed9240d11997-01-16 22:05:33 +0000210 bsddbobject *dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000211{
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000212 if (dp->di_bsddb == NULL) {
213 PyErr_SetString(BsddbError, "BSDDB object has already been closed");
214 return -1;
215 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000216 if (dp->di_size < 0) {
217 DBT krec, drec;
218 int status;
219 int size = 0;
220 for (status = (dp->di_bsddb->seq)(dp->di_bsddb,
221 &krec, &drec,R_FIRST);
222 status == 0;
223 status = (dp->di_bsddb->seq)(dp->di_bsddb,
224 &krec, &drec, R_NEXT))
225 size++;
226 if (status < 0) {
227 PyErr_SetFromErrno(BsddbError);
228 return -1;
229 }
230 dp->di_size = size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000231 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000232 return dp->di_size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000233}
234
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000235static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000236bsddb_subscript(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000237 bsddbobject *dp;
238 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000239{
Roger E. Massed9240d11997-01-16 22:05:33 +0000240 int status;
241 DBT krec, drec;
242 char *data;
243 int size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000244
Roger E. Massed9240d11997-01-16 22:05:33 +0000245 if (!PyArg_Parse(key, "s#", &data, &size))
246 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000247 check_bsddbobject_open(dp);
248
Roger E. Massed9240d11997-01-16 22:05:33 +0000249 krec.data = data;
250 krec.size = size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000251
Roger E. Massed9240d11997-01-16 22:05:33 +0000252 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
253 if (status != 0) {
254 if (status < 0)
255 PyErr_SetFromErrno(BsddbError);
256 else
257 PyErr_SetObject(PyExc_KeyError, key);
258 return NULL;
259 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000260
Roger E. Massed9240d11997-01-16 22:05:33 +0000261 return PyString_FromStringAndSize((char *)drec.data, (int)drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000262}
263
264static int
265bsddb_ass_sub(dp, key, value)
Roger E. Massed9240d11997-01-16 22:05:33 +0000266 bsddbobject *dp;
267 PyObject *key, *value;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000268{
Roger E. Massed9240d11997-01-16 22:05:33 +0000269 int status;
270 DBT krec, drec;
271 char *data;
272 int size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000273
Roger E. Massed9240d11997-01-16 22:05:33 +0000274 if (!PyArg_Parse(key, "s#", &data, &size)) {
275 PyErr_SetString(PyExc_TypeError,
276 "bsddb key type must be string");
277 return -1;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000278 }
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000279 if (dp->di_bsddb == NULL) {
280 PyErr_SetString(BsddbError, "BSDDB object has already been closed");
281 return -1;
282 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000283 krec.data = data;
284 krec.size = size;
285 dp->di_size = -1;
286 if (value == NULL) {
287 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
288 }
289 else {
290 if (!PyArg_Parse(value, "s#", &data, &size)) {
291 PyErr_SetString(PyExc_TypeError,
292 "bsddb value type must be string");
293 return -1;
294 }
295 drec.data = data;
296 drec.size = size;
297#if 0
298 /* For RECNO, put fails with 'No space left on device'
299 after a few short records are added?? Looks fine
300 to this point... linked with 1.85 on Solaris Intel
301 Roger E. Masse 1/16/97
302 */
303 printf("before put data: '%s', size: %d\n",
304 drec.data, drec.size);
305 printf("before put key= '%s', size= %d\n",
306 krec.data, krec.size);
307#endif
308 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
309 }
310 if (status != 0) {
311 if (status < 0)
312 PyErr_SetFromErrno(BsddbError);
313 else
314 PyErr_SetObject(PyExc_KeyError, key);
315 return -1;
316 }
317 return 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000318}
319
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000320static PyMappingMethods bsddb_as_mapping = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000321 (inquiry)bsddb_length, /*mp_length*/
322 (binaryfunc)bsddb_subscript, /*mp_subscript*/
323 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000324};
325
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000326static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000327bsddb_close(dp, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000328 bsddbobject *dp;
329 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000330{
Roger E. Massed9240d11997-01-16 22:05:33 +0000331 if (!PyArg_NoArgs(args))
332 return NULL;
333 if (dp->di_bsddb != NULL) {
334 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0) {
335 dp->di_bsddb = NULL;
336 PyErr_SetFromErrno(BsddbError);
337 return NULL;
338 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000339 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000340 dp->di_bsddb = NULL;
341 Py_INCREF(Py_None);
342 return Py_None;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000343}
344
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000345static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000346bsddb_keys(dp, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000347 bsddbobject *dp;
348 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000349{
Roger E. Massed9240d11997-01-16 22:05:33 +0000350 PyObject *list, *item;
351 DBT krec, drec;
352 int status;
353 int err;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000354
Roger E. Massed9240d11997-01-16 22:05:33 +0000355 if (!PyArg_NoArgs(args))
356 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000357 check_bsddbobject_open(dp);
Roger E. Massed9240d11997-01-16 22:05:33 +0000358 list = PyList_New(0);
359 if (list == NULL)
360 return NULL;
361 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
362 status == 0;
363 status = (dp->di_bsddb->seq)(dp->di_bsddb,
364 &krec, &drec, R_NEXT)) {
365 item = PyString_FromStringAndSize((char *)krec.data,
366 (int)krec.size);
367 if (item == NULL) {
368 Py_DECREF(list);
369 return NULL;
370 }
371 err = PyList_Append(list, item);
372 Py_DECREF(item);
373 if (err != 0) {
374 Py_DECREF(list);
375 return NULL;
376 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000377 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000378 if (status < 0) {
379 PyErr_SetFromErrno(BsddbError);
380 Py_DECREF(list);
381 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000382 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000383 if (dp->di_size < 0)
384 dp->di_size = PyList_Size(list); /* We just did the work */
385 return list;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000386}
387
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000388static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000389bsddb_has_key(dp, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000390 bsddbobject *dp;
391 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000392{
Roger E. Massed9240d11997-01-16 22:05:33 +0000393 DBT krec, drec;
394 int status;
395 char *data;
396 int size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000397
Roger E. Massed9240d11997-01-16 22:05:33 +0000398 if (!PyArg_Parse(args, "s#", &data, &size))
399 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000400 check_bsddbobject_open(dp);
Roger E. Massed9240d11997-01-16 22:05:33 +0000401 krec.data = data;
402 krec.size = size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000403
Roger E. Massed9240d11997-01-16 22:05:33 +0000404 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
405 if (status < 0) {
406 PyErr_SetFromErrno(BsddbError);
407 return NULL;
408 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000409
Roger E. Massed9240d11997-01-16 22:05:33 +0000410 return PyInt_FromLong(status == 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000411}
412
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000413static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000414bsddb_set_location(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000415 bsddbobject *dp;
416 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000417{
Roger E. Massed9240d11997-01-16 22:05:33 +0000418 int status;
419 DBT krec, drec;
420 char *data;
421 int size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000422
Roger E. Massed9240d11997-01-16 22:05:33 +0000423 if (!PyArg_Parse(key, "s#", &data, &size))
424 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000425 check_bsddbobject_open(dp);
Roger E. Massed9240d11997-01-16 22:05:33 +0000426 krec.data = data;
427 krec.size = size;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000428
Roger E. Massed9240d11997-01-16 22:05:33 +0000429 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
430 if (status != 0) {
431 if (status < 0)
432 PyErr_SetFromErrno(BsddbError);
433 else
434 PyErr_SetObject(PyExc_KeyError, key);
435 return NULL;
436 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000437
Roger E. Massed9240d11997-01-16 22:05:33 +0000438 return Py_BuildValue("s#s#", krec.data, krec.size,
439 drec.data, drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000440}
441
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000442static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000443bsddb_seq(dp, args, sequence_request)
Roger E. Massed9240d11997-01-16 22:05:33 +0000444 bsddbobject *dp;
445 PyObject *args;
446 int sequence_request;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000447{
Roger E. Massed9240d11997-01-16 22:05:33 +0000448 int status;
449 DBT krec, drec;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000450
Roger E. Massed9240d11997-01-16 22:05:33 +0000451 if (!PyArg_NoArgs(args))
452 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000453
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000454 check_bsddbobject_open(dp);
Roger E. Massed9240d11997-01-16 22:05:33 +0000455 krec.data = 0;
456 krec.size = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000457
Roger E. Massed9240d11997-01-16 22:05:33 +0000458 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec,
459 &drec, sequence_request);
460 if (status != 0) {
461 if (status < 0)
462 PyErr_SetFromErrno(BsddbError);
463 else
464 PyErr_SetObject(PyExc_KeyError, args);
465 return NULL;
466 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000467
Roger E. Massed9240d11997-01-16 22:05:33 +0000468 return Py_BuildValue("s#s#", krec.data, krec.size,
469 drec.data, drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000470}
471
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000472static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000473bsddb_next(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000474 bsddbobject *dp;
475 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000476{
Roger E. Massed9240d11997-01-16 22:05:33 +0000477 return bsddb_seq(dp, key, R_NEXT);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000478}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000479static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000480bsddb_previous(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000481 bsddbobject *dp;
482 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000483{
Roger E. Massed9240d11997-01-16 22:05:33 +0000484 return bsddb_seq(dp, key, R_PREV);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000485}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000486static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000487bsddb_first(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000488 bsddbobject *dp;
489 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000490{
Roger E. Massed9240d11997-01-16 22:05:33 +0000491 return bsddb_seq(dp, key, R_FIRST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000492}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000493static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000494bsddb_last(dp, key)
Roger E. Massed9240d11997-01-16 22:05:33 +0000495 bsddbobject *dp;
496 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000497{
Roger E. Massed9240d11997-01-16 22:05:33 +0000498 return bsddb_seq(dp, key, R_LAST);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000499}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000500static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000501bsddb_sync(dp, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000502 bsddbobject *dp;
503 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000504{
Roger E. Massed9240d11997-01-16 22:05:33 +0000505 int status;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000506
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000507 if (!PyArg_NoArgs(args))
508 return NULL;
509 check_bsddbobject_open(dp);
Roger E. Massed9240d11997-01-16 22:05:33 +0000510 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
511 if (status != 0) {
512 PyErr_SetFromErrno(BsddbError);
513 return NULL;
514 }
515 return PyInt_FromLong(status = 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000516}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000517static PyMethodDef bsddb_methods[] = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000518 {"close", (PyCFunction)bsddb_close},
519 {"keys", (PyCFunction)bsddb_keys},
520 {"has_key", (PyCFunction)bsddb_has_key},
521 {"set_location", (PyCFunction)bsddb_set_location},
522 {"next", (PyCFunction)bsddb_next},
523 {"previous", (PyCFunction)bsddb_previous},
524 {"first", (PyCFunction)bsddb_first},
525 {"last", (PyCFunction)bsddb_last},
526 {"sync", (PyCFunction)bsddb_sync},
527 {NULL, NULL} /* sentinel */
Guido van Rossum1100dca1995-08-30 23:43:03 +0000528};
529
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000530static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000531bsddb_getattr(dp, name)
Roger E. Massed9240d11997-01-16 22:05:33 +0000532 PyObject *dp;
533 char *name;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000534{
Roger E. Massed9240d11997-01-16 22:05:33 +0000535 return Py_FindMethod(bsddb_methods, dp, name);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000536}
537
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000538static PyTypeObject Bsddbtype = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000539 PyObject_HEAD_INIT(NULL)
540 0,
541 "bsddb",
542 sizeof(bsddbobject),
543 0,
544 (destructor)bsddb_dealloc, /*tp_dealloc*/
545 0, /*tp_print*/
546 (getattrfunc)bsddb_getattr, /*tp_getattr*/
547 0, /*tp_setattr*/
548 0, /*tp_compare*/
549 0, /*tp_repr*/
550 0, /*tp_as_number*/
551 0, /*tp_as_sequence*/
552 &bsddb_as_mapping, /*tp_as_mapping*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000553};
554
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000555static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000556bsdhashopen(self, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000557 PyObject *self;
558 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000559{
Roger E. Massed9240d11997-01-16 22:05:33 +0000560 char *file;
561 char *flag = NULL;
562 int flags = O_RDONLY;
563 int mode = 0666;
564 int bsize = 0;
565 int ffactor = 0;
566 int nelem = 0;
567 int cachesize = 0;
568 int hash = 0; /* XXX currently ignored */
569 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000570
Roger E. Massed9240d11997-01-16 22:05:33 +0000571 if (!PyArg_ParseTuple(args, "s|siiiiiii",
572 &file, &flag, &mode,
573 &bsize, &ffactor, &nelem, &cachesize,
574 &hash, &lorder))
575 return NULL;
576 if (flag != NULL) {
577 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
578 if (flag[0] == 'r')
579 flags = O_RDONLY;
580 else if (flag[0] == 'w')
581 flags = O_RDWR;
582 else if (flag[0] == 'c')
583 flags = O_RDWR|O_CREAT;
584 else if (flag[0] == 'n')
585 flags = O_RDWR|O_CREAT|O_TRUNC;
586 else {
587 PyErr_SetString(BsddbError,
588 "Flag should begin with 'r', 'w', 'c' or 'n'");
589 return NULL;
590 }
591 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000592#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000593 if (flag[0] == 'r')
594 flags |= O_SHLOCK;
595 else
596 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000597#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000598 PyErr_SetString(BsddbError,
599 "locking not supported on this platform");
600 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000601#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000602 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000603 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000604 return newdbhashobject(file, flags, mode,
605 bsize, ffactor, nelem, cachesize, hash, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000606}
607
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000608static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000609bsdbtopen(self, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000610 PyObject *self;
611 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000612{
Roger E. Massed9240d11997-01-16 22:05:33 +0000613 char *file;
614 char *flag = NULL;
615 int flags = O_RDONLY;
616 int mode = 0666;
617 int cachesize = 0;
618 int maxkeypage = 0;
619 int minkeypage = 0;
620 int btflags = 0;
621 unsigned int psize = 0;
622 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000623
Roger E. Massed9240d11997-01-16 22:05:33 +0000624 if (!PyArg_ParseTuple(args, "s|siiiiiii",
625 &file, &flag, &mode,
626 &btflags, &cachesize, &maxkeypage, &minkeypage,
627 &psize, &lorder))
628 return NULL;
629 if (flag != NULL) {
630 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
631 if (flag[0] == 'r')
632 flags = O_RDONLY;
633 else if (flag[0] == 'w')
634 flags = O_RDWR;
635 else if (flag[0] == 'c')
636 flags = O_RDWR|O_CREAT;
637 else if (flag[0] == 'n')
638 flags = O_RDWR|O_CREAT|O_TRUNC;
639 else {
640 PyErr_SetString(BsddbError,
641 "Flag should begin with 'r', 'w', 'c' or 'n'");
642 return NULL;
643 }
644 if (flag[1] == 'l') {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000645#if defined(O_EXLOCK) && defined(O_SHLOCK)
Roger E. Massed9240d11997-01-16 22:05:33 +0000646 if (flag[0] == 'r')
647 flags |= O_SHLOCK;
648 else
649 flags |= O_EXLOCK;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000650#else
Roger E. Massed9240d11997-01-16 22:05:33 +0000651 PyErr_SetString(BsddbError,
652 "locking not supported on this platform");
653 return NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000654#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000655 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000656 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000657 return newdbbtobject(file, flags, mode,
658 btflags, cachesize, maxkeypage, minkeypage,
659 psize, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000660}
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000661
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000662static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000663bsdrnopen(self, args)
Roger E. Massed9240d11997-01-16 22:05:33 +0000664 PyObject *self;
665 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000666{
Roger E. Massed9240d11997-01-16 22:05:33 +0000667 char *file;
668 char *flag = NULL;
669 int flags = O_RDONLY;
670 int mode = 0666;
671 int cachesize = 0;
672 int rnflags = 0;
673 unsigned int psize = 0;
674 int lorder = 0;
675 size_t reclen = 0;
676 char *bval = "";
677 char *bfname = NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000678
Roger E. Massed9240d11997-01-16 22:05:33 +0000679 if (!PyArg_ParseTuple(args, "s|siiiiiiss",
680 &file, &flag, &mode,
681 &rnflags, &cachesize, &psize, &lorder,
682 &reclen, &bval, &bfname))
683 return NULL;
684
685# if 0
686 printf("file: %s\n", file);
687 printf("flag: %s\n", flag);
688 printf("mode: %d\n", mode);
689 printf("rnflags: 0x%x\n", rnflags);
690 printf("cachesize: %d\n", cachesize);
691 printf("psize: %d\n", psize);
692 printf("lorder: %d\n", 0);
693 printf("reclen: %d\n", reclen);
694 printf("bval: %c\n", bval[0]);
695 printf("bfname %s\n", bfname);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000696#endif
Roger E. Massed9240d11997-01-16 22:05:33 +0000697
698 if (flag != NULL) {
699 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
700 if (flag[0] == 'r')
701 flags = O_RDONLY;
702 else if (flag[0] == 'w')
703 flags = O_RDWR;
704 else if (flag[0] == 'c')
705 flags = O_RDWR|O_CREAT;
706 else if (flag[0] == 'n')
707 flags = O_RDWR|O_CREAT|O_TRUNC;
708 else {
709 PyErr_SetString(BsddbError,
710 "Flag should begin with 'r', 'w', 'c' or 'n'");
711 return NULL;
712 }
713 if (flag[1] == 'l') {
714#if defined(O_EXLOCK) && defined(O_SHLOCK)
715 if (flag[0] == 'r')
716 flags |= O_SHLOCK;
717 else
718 flags |= O_EXLOCK;
719#else
720 PyErr_SetString(BsddbError,
721 "locking not supported on this platform");
722 return NULL;
723#endif
724 }
725 else if (flag[1] != '\0') {
726 PyErr_SetString(BsddbError,
727 "Flag char 2 should be 'l' or absent");
728 return NULL;
729 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000730 }
Roger E. Massed9240d11997-01-16 22:05:33 +0000731 return newdbrnobject(file, flags, mode, rnflags, cachesize,
732 psize, lorder, reclen, bval[0], bfname);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000733}
734
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000735static PyMethodDef bsddbmodule_methods[] = {
Roger E. Massed9240d11997-01-16 22:05:33 +0000736 {"hashopen", (PyCFunction)bsdhashopen, 1},
737 {"btopen", (PyCFunction)bsdbtopen, 1},
738 {"rnopen", (PyCFunction)bsdrnopen, 1},
739 {0, 0},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000740};
741
742void
743initbsddb() {
Roger E. Massed9240d11997-01-16 22:05:33 +0000744 PyObject *m, *d;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000745
Roger E. Massed9240d11997-01-16 22:05:33 +0000746 Bsddbtype.ob_type = &PyType_Type;
747 m = Py_InitModule("bsddb", bsddbmodule_methods);
748 d = PyModule_GetDict(m);
749 BsddbError = PyString_FromString("bsddb.error");
750 if (BsddbError == NULL || PyDict_SetItemString(d, "error", BsddbError))
751 Py_FatalError("can't define bsddb.error");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000752}