blob: 01b11160d50a2539ee47fa2db60225f5cec0c9c7 [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,
Guido van Rossum81b24c01996-12-05 23:30:16 +0000196 "Python bsddb: close errno %d in dealloc\n", errno);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000197 }
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 Rossum1100dca1995-08-30 23:43:03 +0000228 DBT krec, drec;
229 char *data;
230 int size;
231
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000232 if (!PyArg_Parse(key, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000233 return NULL;
234 krec.data = data;
235 krec.size = size;
236
237 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
238 if (status != 0) {
239 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000240 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000241 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000242 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000243 return NULL;
244 }
245
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000246 return PyString_FromStringAndSize((char *)drec.data, (int)drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000247}
248
249static int
250bsddb_ass_sub(dp, key, value)
251 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000252 PyObject *key, *value;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000253{
254 int status;
255 DBT krec, drec;
256 char *data;
257 int size;
258
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000259 if (!PyArg_Parse(key, "s#", &data, &size)) {
260 PyErr_SetString(PyExc_TypeError, "bsddb key type must be string");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000261 return -1;
262 }
263 krec.data = data;
264 krec.size = size;
265 dp->di_size = -1;
266 if (value == NULL) {
267 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
268 }
269 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000270 if (!PyArg_Parse(value, "s#", &data, &size)) {
271 PyErr_SetString(PyExc_TypeError, "bsddb value type must be string");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000272 return -1;
273 }
274 drec.data = data;
275 drec.size = size;
276 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
277 }
278 if (status != 0) {
279 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000280 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000281 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000282 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000283 return -1;
284 }
285 return 0;
286}
287
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000288static PyMappingMethods bsddb_as_mapping = {
Guido van Rossum1100dca1995-08-30 23:43:03 +0000289 (inquiry)bsddb_length, /*mp_length*/
290 (binaryfunc)bsddb_subscript, /*mp_subscript*/
291 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
292};
293
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000294static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000295bsddb_close(dp, args)
296 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000297 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000298{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000299 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000300 return NULL;
301 if (dp->di_bsddb != NULL) {
302 if ((dp->di_bsddb->close)(dp->di_bsddb) != 0) {
303 dp->di_bsddb = NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000304 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000305 return NULL;
306 }
307 }
308 dp->di_bsddb = NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000309 Py_INCREF(Py_None);
310 return Py_None;
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_keys(dp, args)
315 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000316 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000317{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000318 PyObject *list, *item;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000319 DBT krec, drec;
320 int status;
321 int err;
322
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000323 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000324 return NULL;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000325 list = PyList_New(0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000326 if (list == NULL)
327 return NULL;
328 for (status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
329 status == 0;
330 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT)) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000331 item = PyString_FromStringAndSize((char *)krec.data, (int)krec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000332 if (item == NULL) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000333 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000334 return NULL;
335 }
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000336 err = PyList_Append(list, item);
337 Py_DECREF(item);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000338 if (err != 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000339 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000340 return NULL;
341 }
342 }
343 if (status < 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000344 PyErr_SetFromErrno(BsddbError);
345 Py_DECREF(list);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000346 return NULL;
347 }
348 if (dp->di_size < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000349 dp->di_size = PyList_Size(list); /* We just did the work for this... */
Guido van Rossum1100dca1995-08-30 23:43:03 +0000350 return list;
351}
352
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000353static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000354bsddb_has_key(dp, args)
355 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000356 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000357{
358 DBT krec, drec;
359 int status;
360 char *data;
361 int size;
362
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000363 if (!PyArg_Parse(args, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000364 return NULL;
365 krec.data = data;
366 krec.size = size;
367
368 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
369 if (status < 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000370 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000371 return NULL;
372 }
373
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000374 return PyInt_FromLong(status == 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000375}
376
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000377static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000378bsddb_set_location(dp, key)
379 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000380 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000381{
382 int status;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000383 DBT krec, drec;
384 char *data;
385 int size;
386
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000387 if (!PyArg_Parse(key, "s#", &data, &size))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000388 return NULL;
389 krec.data = data;
390 krec.size = size;
391
392 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
393 if (status != 0) {
394 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000395 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000396 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000397 PyErr_SetObject(PyExc_KeyError, key);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000398 return NULL;
399 }
400
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000401 return Py_BuildValue("s#s#", krec.data, krec.size, drec.data, drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000402}
403
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000404static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000405bsddb_seq(dp, args, sequence_request)
406 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000407 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000408 int sequence_request;
409{
410 int status;
411 DBT krec, drec;
412
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000413 if (!PyArg_NoArgs(args))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000414 return NULL;
415
416 krec.data = 0;
417 krec.size = 0;
418
419 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, sequence_request);
420 if (status != 0) {
421 if (status < 0)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000422 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000423 else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000424 PyErr_SetObject(PyExc_KeyError, args);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000425 return NULL;
426 }
427
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000428 return Py_BuildValue("s#s#", krec.data, krec.size, drec.data, drec.size);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000429}
430
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000431static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000432bsddb_next(dp, key)
433 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000434 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000435{
436 return bsddb_seq(dp, key, R_NEXT);
437}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000438static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000439bsddb_previous(dp, key)
440 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000441 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000442{
443 return bsddb_seq(dp, key, R_PREV);
444}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000445static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000446bsddb_first(dp, key)
447 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000448 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000449{
450 return bsddb_seq(dp, key, R_FIRST);
451}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000452static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000453bsddb_last(dp, key)
454 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000455 PyObject *key;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000456{
457 return bsddb_seq(dp, key, R_LAST);
458}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000459static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000460bsddb_sync(dp, args)
461 bsddbobject *dp;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000462 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000463{
464 int status;
465
466 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
467 if (status != 0) {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000468 PyErr_SetFromErrno(BsddbError);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000469 return NULL;
470 }
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000471 return PyInt_FromLong(status = 0);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000472}
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000473static PyMethodDef bsddb_methods[] = {
474 {"close", (PyCFunction)bsddb_close},
475 {"keys", (PyCFunction)bsddb_keys},
476 {"has_key", (PyCFunction)bsddb_has_key},
477 {"set_location", (PyCFunction)bsddb_set_location},
478 {"next", (PyCFunction)bsddb_next},
479 {"previous", (PyCFunction)bsddb_previous},
480 {"first", (PyCFunction)bsddb_first},
481 {"last", (PyCFunction)bsddb_last},
482 {"sync", (PyCFunction)bsddb_sync},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000483 {NULL, NULL} /* sentinel */
484};
485
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000486static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000487bsddb_getattr(dp, name)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000488 PyObject *dp;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000489 char *name;
490{
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000491 return Py_FindMethod(bsddb_methods, dp, name);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000492}
493
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000494static PyTypeObject Bsddbtype = {
Guido van Rossum622f5771996-09-11 23:18:43 +0000495 PyObject_HEAD_INIT(NULL)
Guido van Rossum1100dca1995-08-30 23:43:03 +0000496 0,
497 "bsddb",
498 sizeof(bsddbobject),
499 0,
500 (destructor)bsddb_dealloc, /*tp_dealloc*/
501 0, /*tp_print*/
502 (getattrfunc)bsddb_getattr, /*tp_getattr*/
503 0, /*tp_setattr*/
504 0, /*tp_compare*/
505 0, /*tp_repr*/
506 0, /*tp_as_number*/
507 0, /*tp_as_sequence*/
508 &bsddb_as_mapping, /*tp_as_mapping*/
509};
510
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000511static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000512bsdhashopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000513 PyObject *self;
514 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000515{
516 char *file;
517 char *flag = NULL;
518 int flags = O_RDONLY;
519 int mode = 0666;
520 int bsize = 0;
521 int ffactor = 0;
522 int nelem = 0;
523 int cachesize = 0;
524 int hash = 0; /* XXX currently ignored */
525 int lorder = 0;
526
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000527 if (!PyArg_ParseTuple(args, "s|siiiiiii",
Guido van Rossum1100dca1995-08-30 23:43:03 +0000528 &file, &flag, &mode,
529 &bsize, &ffactor, &nelem, &cachesize, &hash, &lorder))
530 return NULL;
531 if (flag != NULL) {
532 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
533 if (flag[0] == 'r')
534 flags = O_RDONLY;
535 else if (flag[0] == 'w')
536 flags = O_RDWR;
537 else if (flag[0] == 'c')
538 flags = O_RDWR|O_CREAT;
539 else if (flag[0] == 'n')
540 flags = O_RDWR|O_CREAT|O_TRUNC;
541 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000542 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000543 "Flag should begin with 'r', 'w', 'c' or 'n'");
544 return NULL;
545 }
546 if (flag[1] == 'l') {
547#if defined(O_EXLOCK) && defined(O_SHLOCK)
548 if (flag[0] == 'r')
549 flags |= O_SHLOCK;
550 else
551 flags |= O_EXLOCK;
552#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000553 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000554 return NULL;
555#endif
556 }
557 }
558 return newdbhashobject(file, flags, mode,
559 bsize, ffactor, nelem, cachesize, hash, lorder);
560}
561
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000562static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000563bsdbtopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000564 PyObject *self;
565 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000566{
567 char *file;
568 char *flag = NULL;
569 int flags = O_RDONLY;
570 int mode = 0666;
571 int cachesize = 0;
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000572 int maxkeypage = 0;
573 int minkeypage = 0;
574 int btflags = 0;
575 unsigned int psize = 0;
576 int lorder = 0;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000577
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000578 if (!PyArg_ParseTuple(args, "s|siiiiiii",
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000579 &file, &flag, &mode,
580 &btflags, &cachesize, &maxkeypage, &minkeypage,
581 &psize, &lorder))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000582 return NULL;
583 if (flag != NULL) {
584 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
585 if (flag[0] == 'r')
586 flags = O_RDONLY;
587 else if (flag[0] == 'w')
588 flags = O_RDWR;
589 else if (flag[0] == 'c')
590 flags = O_RDWR|O_CREAT;
591 else if (flag[0] == 'n')
592 flags = O_RDWR|O_CREAT|O_TRUNC;
593 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000594 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000595 "Flag should begin with 'r', 'w', 'c' or 'n'");
596 return NULL;
597 }
598 if (flag[1] == 'l') {
599#if defined(O_EXLOCK) && defined(O_SHLOCK)
600 if (flag[0] == 'r')
601 flags |= O_SHLOCK;
602 else
603 flags |= O_EXLOCK;
604#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000605 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000606 return NULL;
607#endif
608 }
609 }
610 return newdbbtobject(file, flags, mode,
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000611 btflags, cachesize, maxkeypage, minkeypage,
612 psize, lorder);
Guido van Rossum1100dca1995-08-30 23:43:03 +0000613}
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000614
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000615static PyObject *
Guido van Rossum1100dca1995-08-30 23:43:03 +0000616bsdrnopen(self, args)
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000617 PyObject *self;
618 PyObject *args;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000619{
620 char *file;
621 char *flag = NULL;
622 int flags = O_RDONLY;
623 int mode = 0666;
624 int cachesize = 0;
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000625 int rnflags = 0;
626 unsigned int psize = 0;
627 int lorder = 0;
628 size_t reclen = 0;
629 char *bval = "";
630 char *bfname = NULL;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000631
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000632 if (!PyArg_ParseTuple(args, "s|siiiiiiss",
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000633 &file, &flag, &mode,
634 &rnflags, &cachesize, &psize, &lorder,
635 &reclen, &bval, &bfname))
Guido van Rossum1100dca1995-08-30 23:43:03 +0000636 return NULL;
637 if (flag != NULL) {
638 /* XXX need a way to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
639 if (flag[0] == 'r')
640 flags = O_RDONLY;
641 else if (flag[0] == 'w')
642 flags = O_RDWR;
643 else if (flag[0] == 'c')
644 flags = O_RDWR|O_CREAT;
645 else if (flag[0] == 'n')
646 flags = O_RDWR|O_CREAT|O_TRUNC;
647 else {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000648 PyErr_SetString(BsddbError,
Guido van Rossum1100dca1995-08-30 23:43:03 +0000649 "Flag should begin with 'r', 'w', 'c' or 'n'");
650 return NULL;
651 }
652 if (flag[1] == 'l') {
653#if defined(O_EXLOCK) && defined(O_SHLOCK)
654 if (flag[0] == 'r')
655 flags |= O_SHLOCK;
656 else
657 flags |= O_EXLOCK;
658#else
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000659 PyErr_SetString(BsddbError, "locking not supported on this platform");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000660 return NULL;
661#endif
662 }
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000663 else if (flag[1] != '\0') {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000664 PyErr_SetString(BsddbError,
Guido van Rossumdd96ca71996-05-23 22:57:54 +0000665 "Flag char 2 should be 'l' or absent");
666 return NULL;
667 }
Guido van Rossum1100dca1995-08-30 23:43:03 +0000668 }
669 return newdbrnobject(file, flags, mode,
670 rnflags, cachesize, psize, lorder, bval[0], bfname);
671}
672
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000673static PyMethodDef bsddbmodule_methods[] = {
674 {"hashopen", (PyCFunction)bsdhashopen, 1},
675 {"btopen", (PyCFunction)bsdbtopen, 1},
676 {"rnopen", (PyCFunction)bsdrnopen, 1},
Guido van Rossum1100dca1995-08-30 23:43:03 +0000677 {0, 0},
678};
679
680void
681initbsddb() {
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000682 PyObject *m, *d;
Guido van Rossum1100dca1995-08-30 23:43:03 +0000683
Guido van Rossum622f5771996-09-11 23:18:43 +0000684 Bsddbtype.ob_type = &PyType_Type;
Guido van Rossumdfe8ad91996-07-24 00:51:20 +0000685 m = Py_InitModule("bsddb", bsddbmodule_methods);
686 d = PyModule_GetDict(m);
687 BsddbError = PyString_FromString("bsddb.error");
688 if (BsddbError == NULL || PyDict_SetItemString(d, "error", BsddbError))
689 Py_FatalError("can't define bsddb.error");
Guido van Rossum1100dca1995-08-30 23:43:03 +0000690}