blob: c4155acb3987d901e5c739c559dc1ea836c635b8 [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 {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000053 PyObject_HEAD
Guido van Rossum1100dca1995-08-30 23:43:03 +000054 DB *di_bsddb;
55 int di_size; /* -1 means recompute */
56} 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)
67 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;
76{
77 bsddbobject *dp;
78 HASHINFO info;
79
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000080 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
Guido van Rossum1100dca1995-08-30 23:43:03 +000081 return NULL;
82
83 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;
89
Guido van Rossum6beb4791996-09-11 23:22:25 +000090#ifdef O_BINARY
91 flags |= O_BINARY;
92#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +000093 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_HASH, &info)) == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +000094 PyErr_SetFromErrno(BsddbError);
95 Py_DECREF(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +000096 return NULL;
97 }
98
99 dp->di_size = -1;
100
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000101 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000102}
103
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000104static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000105newdbbtobject(file, flags, mode,
106 btflags, cachesize, maxkeypage, minkeypage, psize, lorder)
107 char *file;
108 int flags;
109 int mode;
110 int btflags;
111 int cachesize;
112 int maxkeypage;
113 int minkeypage;
114 int psize;
115 int lorder;
116{
117 bsddbobject *dp;
118 BTREEINFO info;
119
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000120 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000121 return NULL;
122
123 info.flags = btflags;
124 info.cachesize = cachesize;
125 info.maxkeypage = maxkeypage;
126 info.minkeypage = minkeypage;
127 info.psize = psize;
128 info.lorder = lorder;
Guido van Rossum6beb4791996-09-11 23:22:25 +0000129 info.compare = 0; /* Use default comparison functions, for now..*/
Guido van Rossum1100dca1995-08-30 23:43:03 +0000130 info.prefix = 0;
131
Guido van Rossum6beb4791996-09-11 23:22:25 +0000132#ifdef O_BINARY
133 flags |= O_BINARY;
134#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +0000135 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_BTREE, &info)) == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000136 PyErr_SetFromErrno(BsddbError);
137 Py_DECREF(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000138 return NULL;
139 }
140
141 dp->di_size = -1;
142
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000143 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000144}
145
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000146static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000147newdbrnobject(file, flags, mode,
148 rnflags, cachesize, psize, lorder, reclen, bval, bfname)
149 char *file;
150 int flags;
151 int mode;
152 int rnflags;
153 int cachesize;
154 int psize;
155 int lorder;
156 size_t reclen;
157 u_char bval;
158 char *bfname;
159{
160 bsddbobject *dp;
161 RECNOINFO info;
162
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000163 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000164 return NULL;
165
166 info.flags = rnflags;
167 info.cachesize = cachesize;
168 info.psize = psize;
169 info.lorder = lorder;
170 info.reclen = reclen;
171 info.bval = bval;
172 info.bfname = bfname;
173
Guido van Rossum6beb4791996-09-11 23:22:25 +0000174#ifdef O_BINARY
175 flags |= O_BINARY;
176#endif
Guido van Rossum1100dca1995-08-30 23:43:03 +0000177 if ((dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info)) == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000178 PyErr_SetFromErrno(BsddbError);
179 Py_DECREF(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000180 return NULL;
181 }
182
183 dp->di_size = -1;
184
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000185 return (PyObject *)dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000186}
187
188
189static void
190bsddb_dealloc(dp)
191 bsddbobject *dp;
192{
193 if (dp->di_bsddb != NULL) {
194 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0)
195 fprintf(stderr,
196 "Python bsddb: close errno %s in dealloc\n", errno);
197 }
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000198 PyMem_DEL(dp);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000199}
200
201static int
202bsddb_length(dp)
203 bsddbobject *dp;
204{
205 if (dp->di_size < 0) {
206 DBT krec, drec;
207 int status;
208 int size = 0;
209 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec,R_FIRST);
210 status == 0;
211 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT))
212 size++;
213 if (status < 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000214 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000215 return -1;
216 }
217 dp->di_size = size;
218 }
219 return dp->di_size;
220}
221
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000222static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000223bsddb_subscript(dp, key)
224 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000225 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000226{
227 int status;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000228 PyObject *v;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000229 DBT krec, drec;
230 char *data;
231 int size;
232
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000233 if (!PyArg_Parse(key, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000234 return NULL;
235 krec.data = data;
236 krec.size = size;
237
238 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
239 if (status != 0) {
240 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000241 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000242 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000243 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000244 return NULL;
245 }
246
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000247 return PyString_FromStringAndSize((char *)drec.data, (int)drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000248}
249
250static int
251bsddb_ass_sub(dp, key, value)
252 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000253 PyObject *key, *value;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000254{
255 int status;
256 DBT krec, drec;
257 char *data;
258 int size;
259
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000260 if (!PyArg_Parse(key, "s#", &data, &size)) {
261 PyErr_SetString(PyExc_TypeError, "bsddb key type must be string");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000262 return -1;
263 }
264 krec.data = data;
265 krec.size = size;
266 dp->di_size = -1;
267 if (value == NULL) {
268 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
269 }
270 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000271 if (!PyArg_Parse(value, "s#", &data, &size)) {
272 PyErr_SetString(PyExc_TypeError, "bsddb value type must be string");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000273 return -1;
274 }
275 drec.data = data;
276 drec.size = size;
277 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
278 }
279 if (status != 0) {
280 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000281 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000282 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000283 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000284 return -1;
285 }
286 return 0;
287}
288
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000289static PyMappingMethods bsddb_as_mapping = {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000290 (inquiry)bsddb_length, /*mp_length*/
291 (binaryfunc)bsddb_subscript, /*mp_subscript*/
292 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
293};
294
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000295static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000296bsddb_close(dp, args)
297 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000298 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000299{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000300 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000301 return NULL;
302 if (dp->di_bsddb != NULL) {
303 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0) {
304 dp->di_bsddb = NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000305 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000306 return NULL;
307 }
308 }
309 dp->di_bsddb = NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000310 Py_INCREF(Py_None);
311 return Py_None;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000312}
313
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000314static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000315bsddb_keys(dp, args)
316 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000317 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000318{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000319 PyObject *list, *item;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000320 DBT krec, drec;
321 int status;
322 int err;
323
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000324 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000325 return NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000326 list = PyList_New(0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000327 if (list == NULL)
328 return NULL;
329 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
330 status == 0;
331 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT)) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000332 item = PyString_FromStringAndSize((char *)krec.data, (int)krec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000333 if (item == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000334 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000335 return NULL;
336 }
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000337 err = PyList_Append(list, item);
338 Py_DECREF(item);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000339 if (err != 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000340 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000341 return NULL;
342 }
343 }
344 if (status < 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000345 PyErr_SetFromErrno(BsddbError);
346 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000347 return NULL;
348 }
349 if (dp->di_size < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000350 dp->di_size = PyList_Size(list); /* We just did the work for this... */
Guido van Rossum1100dca1995-08-30 23:43:03 +0000351 return list;
352}
353
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000354static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000355bsddb_has_key(dp, args)
356 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000357 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000358{
359 DBT krec, drec;
360 int status;
361 char *data;
362 int size;
363
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000364 if (!PyArg_Parse(args, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000365 return NULL;
366 krec.data = data;
367 krec.size = size;
368
369 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
370 if (status < 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000371 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000372 return NULL;
373 }
374
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000375 return PyInt_FromLong(status == 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000376}
377
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000378static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000379bsddb_set_location(dp, key)
380 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000381 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000382{
383 int status;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000384 PyObject *v;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000385 DBT krec, drec;
386 char *data;
387 int size;
388
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000389 if (!PyArg_Parse(key, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000390 return NULL;
391 krec.data = data;
392 krec.size = size;
393
394 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
395 if (status != 0) {
396 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000397 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000398 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000399 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000400 return NULL;
401 }
402
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000403 return Py_BuildValue("s#s#", krec.data, krec.size, drec.data, drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000404}
405
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000406static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000407bsddb_seq(dp, args, sequence_request)
408 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000409 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000410 int sequence_request;
411{
412 int status;
413 DBT krec, drec;
414
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000415 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000416 return NULL;
417
418 krec.data = 0;
419 krec.size = 0;
420
421 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, sequence_request);
422 if (status != 0) {
423 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000424 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000425 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000426 PyErr_SetObject(PyExc_KeyError, args);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000427 return NULL;
428 }
429
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000430 return Py_BuildValue("s#s#", krec.data, krec.size, drec.data, drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000431}
432
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000433static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000434bsddb_next(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_NEXT);
439}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000440static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000441bsddb_previous(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_PREV);
446}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000447static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000448bsddb_first(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_FIRST);
453}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000454static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000455bsddb_last(dp, key)
456 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000457 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000458{
459 return bsddb_seq(dp, key, R_LAST);
460}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000461static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000462bsddb_sync(dp, args)
463 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000464 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000465{
466 int status;
467
468 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
469 if (status != 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000470 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000471 return NULL;
472 }
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000473 return PyInt_FromLong(status = 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000474}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000475static PyMethodDef bsddb_methods[] = {
476 {"close", (PyCFunction)bsddb_close},
477 {"keys", (PyCFunction)bsddb_keys},
478 {"has_key", (PyCFunction)bsddb_has_key},
479 {"set_location", (PyCFunction)bsddb_set_location},
480 {"next", (PyCFunction)bsddb_next},
481 {"previous", (PyCFunction)bsddb_previous},
482 {"first", (PyCFunction)bsddb_first},
483 {"last", (PyCFunction)bsddb_last},
484 {"sync", (PyCFunction)bsddb_sync},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000485 {NULL, NULL} /* sentinel */
486};
487
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000488static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000489bsddb_getattr(dp, name)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000490 PyObject *dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000491 char *name;
492{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000493 return Py_FindMethod(bsddb_methods, dp, name);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000494}
495
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000496static PyTypeObject Bsddbtype = {
Guido van Rossum622f5771996-09-11 23:18:43 +0000497 PyObject_HEAD_INIT(NULL)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000498 0,
499 "bsddb",
500 sizeof(bsddbobject),
501 0,
502 (destructor)bsddb_dealloc, /*tp_dealloc*/
503 0, /*tp_print*/
504 (getattrfunc)bsddb_getattr, /*tp_getattr*/
505 0, /*tp_setattr*/
506 0, /*tp_compare*/
507 0, /*tp_repr*/
508 0, /*tp_as_number*/
509 0, /*tp_as_sequence*/
510 &bsddb_as_mapping, /*tp_as_mapping*/
511};
512
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000513static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000514bsdhashopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000515 PyObject *self;
516 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000517{
518 char *file;
519 char *flag = NULL;
520 int flags = O_RDONLY;
521 int mode = 0666;
522 int bsize = 0;
523 int ffactor = 0;
524 int nelem = 0;
525 int cachesize = 0;
526 int hash = 0; /* XXX currently ignored */
527 int lorder = 0;
528
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000529 if (!PyArg_ParseTuple(args, "s|siiiiiii",
Guido van Rossum1100dca1995-08-30 23:43:03 +0000530 &file, &flag, &mode,
531 &bsize, &ffactor, &nelem, &cachesize, &hash, &lorder))
532 return NULL;
533 if (flag != NULL) {
534 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
535 if (flag[0] == 'r')
536 flags = O_RDONLY;
537 else if (flag[0] == 'w')
538 flags = O_RDWR;
539 else if (flag[0] == 'c')
540 flags = O_RDWR|O_CREAT;
541 else if (flag[0] == 'n')
542 flags = O_RDWR|O_CREAT|O_TRUNC;
543 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000544 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000545 "Flag should begin with 'r', 'w', 'c' or 'n'");
546 return NULL;
547 }
548 if (flag[1] == 'l') {
549#if defined(O_EXLOCK) && defined(O_SHLOCK)
550 if (flag[0] == 'r')
551 flags |= O_SHLOCK;
552 else
553 flags |= O_EXLOCK;
554#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000555 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000556 return NULL;
557#endif
558 }
559 }
560 return newdbhashobject(file, flags, mode,
561 bsize, ffactor, nelem, cachesize, hash, lorder);
562}
563
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000564static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000565bsdbtopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000566 PyObject *self;
567 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000568{
569 char *file;
570 char *flag = NULL;
571 int flags = O_RDONLY;
572 int mode = 0666;
573 int cachesize = 0;
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000574 int maxkeypage = 0;
575 int minkeypage = 0;
576 int btflags = 0;
577 unsigned int psize = 0;
578 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000579
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000580 if (!PyArg_ParseTuple(args, "s|siiiiiii",
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000581 &file, &flag, &mode,
582 &btflags, &cachesize, &maxkeypage, &minkeypage,
583 &psize, &lorder))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000584 return NULL;
585 if (flag != NULL) {
586 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
587 if (flag[0] == 'r')
588 flags = O_RDONLY;
589 else if (flag[0] == 'w')
590 flags = O_RDWR;
591 else if (flag[0] == 'c')
592 flags = O_RDWR|O_CREAT;
593 else if (flag[0] == 'n')
594 flags = O_RDWR|O_CREAT|O_TRUNC;
595 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000596 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000597 "Flag should begin with 'r', 'w', 'c' or 'n'");
598 return NULL;
599 }
600 if (flag[1] == 'l') {
601#if defined(O_EXLOCK) && defined(O_SHLOCK)
602 if (flag[0] == 'r')
603 flags |= O_SHLOCK;
604 else
605 flags |= O_EXLOCK;
606#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000607 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000608 return NULL;
609#endif
610 }
611 }
612 return newdbbtobject(file, flags, mode,
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000613 btflags, cachesize, maxkeypage, minkeypage,
614 psize, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000615}
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000616
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000617static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000618bsdrnopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000619 PyObject *self;
620 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000621{
622 char *file;
623 char *flag = NULL;
624 int flags = O_RDONLY;
625 int mode = 0666;
626 int cachesize = 0;
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000627 int rnflags = 0;
628 unsigned int psize = 0;
629 int lorder = 0;
630 size_t reclen = 0;
631 char *bval = "";
632 char *bfname = NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000633
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000634 if (!PyArg_ParseTuple(args, "s|siiiiiiss",
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000635 &file, &flag, &mode,
636 &rnflags, &cachesize, &psize, &lorder,
637 &reclen, &bval, &bfname))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000638 return NULL;
639 if (flag != NULL) {
640 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
641 if (flag[0] == 'r')
642 flags = O_RDONLY;
643 else if (flag[0] == 'w')
644 flags = O_RDWR;
645 else if (flag[0] == 'c')
646 flags = O_RDWR|O_CREAT;
647 else if (flag[0] == 'n')
648 flags = O_RDWR|O_CREAT|O_TRUNC;
649 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000650 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000651 "Flag should begin with 'r', 'w', 'c' or 'n'");
652 return NULL;
653 }
654 if (flag[1] == 'l') {
655#if defined(O_EXLOCK) && defined(O_SHLOCK)
656 if (flag[0] == 'r')
657 flags |= O_SHLOCK;
658 else
659 flags |= O_EXLOCK;
660#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000661 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000662 return NULL;
663#endif
664 }
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000665 else if (flag[1] != '\0') {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000666 PyErr_SetString(BsddbError,
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000667 "Flag char 2 should be 'l' or absent");
668 return NULL;
669 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000670 }
671 return newdbrnobject(file, flags, mode,
672 rnflags, cachesize, psize, lorder, bval[0], bfname);
673}
674
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000675static PyMethodDef bsddbmodule_methods[] = {
676 {"hashopen", (PyCFunction)bsdhashopen, 1},
677 {"btopen", (PyCFunction)bsdbtopen, 1},
678 {"rnopen", (PyCFunction)bsdrnopen, 1},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000679 {0, 0},
680};
681
682void
683initbsddb() {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000684 PyObject *m, *d;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000685
Guido van Rossum622f5771996-09-11 23:18:43 +0000686 Bsddbtype.ob_type = &PyType_Type;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000687 m = Py_InitModule("bsddb", bsddbmodule_methods);
688 d = PyModule_GetDict(m);
689 BsddbError = PyString_FromString("bsddb.error");
690 if (BsddbError == NULL || PyDict_SetItemString(d, "error", BsddbError))
691 Py_FatalError("can't define bsddb.error");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000692}