Ditched '_find_SET()', since it was a no-value-added wrapper around
[python/dscho.git] / Modules / bsddbmodule.c
blob514159faed0dce67fddde13f6268b83c19d1d2eb
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* Berkeley DB interface.
33 Author: Michael McLay
34 Hacked: Guido van Rossum
35 Btree and Recno additions plus sequence methods: David Ely
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
42 The windows port of the Berkeley DB code is hard to find on the web:
43 www.nightmare.com/software.html
46 #include "Python.h"
47 #ifdef WITH_THREAD
48 #include "pythread.h"
49 #endif
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #include <fcntl.h>
54 #include <db.h>
55 /* Please don't include internal header files of the Berkeley db package
56 (it messes up the info required in the Setup file) */
58 typedef struct {
59 PyObject_HEAD
60 DB *di_bsddb;
61 int di_size; /* -1 means recompute */
62 #ifdef WITH_THREAD
63 PyThread_type_lock di_lock;
64 #endif
65 } bsddbobject;
67 staticforward PyTypeObject Bsddbtype;
69 #define is_bsddbobject(v) ((v)->ob_type == &Bsddbtype)
70 #define check_bsddbobject_open(v) if ((v)->di_bsddb == NULL) \
71 { PyErr_SetString(BsddbError, "BSDDB object has already been closed"); \
72 return NULL; }
74 static PyObject *BsddbError;
76 static PyObject *
77 newdbhashobject(file, flags, mode,
78 bsize, ffactor, nelem, cachesize, hash, lorder)
79 char *file;
80 int flags;
81 int mode;
82 int bsize;
83 int ffactor;
84 int nelem;
85 int cachesize;
86 int hash; /* XXX ignored */
87 int lorder;
89 bsddbobject *dp;
90 HASHINFO info;
92 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
93 return NULL;
95 info.bsize = bsize;
96 info.ffactor = ffactor;
97 info.nelem = nelem;
98 info.cachesize = cachesize;
99 info.hash = NULL; /* XXX should derive from hash argument */
100 info.lorder = lorder;
102 #ifdef O_BINARY
103 flags |= O_BINARY;
104 #endif
105 Py_BEGIN_ALLOW_THREADS
106 dp->di_bsddb = dbopen(file, flags, mode, DB_HASH, &info);
107 Py_END_ALLOW_THREADS
108 if (dp->di_bsddb == NULL) {
109 PyErr_SetFromErrno(BsddbError);
110 #ifdef WITH_THREAD
111 dp->di_lock = NULL;
112 #endif
113 Py_DECREF(dp);
114 return NULL;
117 dp->di_size = -1;
118 #ifdef WITH_THREAD
119 dp->di_lock = PyThread_allocate_lock();
120 if (dp->di_lock == NULL) {
121 PyErr_SetString(BsddbError, "can't allocate lock");
122 Py_DECREF(dp);
123 return NULL;
125 #endif
127 return (PyObject *)dp;
130 static PyObject *
131 newdbbtobject(file, flags, mode,
132 btflags, cachesize, maxkeypage, minkeypage, psize, lorder)
133 char *file;
134 int flags;
135 int mode;
136 int btflags;
137 int cachesize;
138 int maxkeypage;
139 int minkeypage;
140 int psize;
141 int lorder;
143 bsddbobject *dp;
144 BTREEINFO info;
146 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
147 return NULL;
149 info.flags = btflags;
150 info.cachesize = cachesize;
151 info.maxkeypage = maxkeypage;
152 info.minkeypage = minkeypage;
153 info.psize = psize;
154 info.lorder = lorder;
155 info.compare = 0; /* Use default comparison functions, for now..*/
156 info.prefix = 0;
158 #ifdef O_BINARY
159 flags |= O_BINARY;
160 #endif
161 Py_BEGIN_ALLOW_THREADS
162 dp->di_bsddb = dbopen(file, flags, mode, DB_BTREE, &info);
163 Py_END_ALLOW_THREADS
164 if (dp->di_bsddb == NULL) {
165 PyErr_SetFromErrno(BsddbError);
166 #ifdef WITH_THREAD
167 dp->di_lock = NULL;
168 #endif
169 Py_DECREF(dp);
170 return NULL;
173 dp->di_size = -1;
174 #ifdef WITH_THREAD
175 dp->di_lock = PyThread_allocate_lock();
176 if (dp->di_lock == NULL) {
177 PyErr_SetString(BsddbError, "can't allocate lock");
178 Py_DECREF(dp);
179 return NULL;
181 #endif
183 return (PyObject *)dp;
186 static PyObject *
187 newdbrnobject(file, flags, mode,
188 rnflags, cachesize, psize, lorder, reclen, bval, bfname)
189 char *file;
190 int flags;
191 int mode;
192 int rnflags;
193 int cachesize;
194 int psize;
195 int lorder;
196 size_t reclen;
197 u_char bval;
198 char *bfname;
200 bsddbobject *dp;
201 RECNOINFO info;
203 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
204 return NULL;
206 info.flags = rnflags;
207 info.cachesize = cachesize;
208 info.psize = psize;
209 info.lorder = lorder;
210 info.reclen = reclen;
211 info.bval = bval;
212 info.bfname = bfname;
214 #ifdef O_BINARY
215 flags |= O_BINARY;
216 #endif
217 Py_BEGIN_ALLOW_THREADS
218 dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info);
219 Py_END_ALLOW_THREADS
220 if (dp->di_bsddb == NULL) {
221 PyErr_SetFromErrno(BsddbError);
222 #ifdef WITH_THREAD
223 dp->di_lock = NULL;
224 #endif
225 Py_DECREF(dp);
226 return NULL;
229 dp->di_size = -1;
230 #ifdef WITH_THREAD
231 dp->di_lock = PyThread_allocate_lock();
232 if (dp->di_lock == NULL) {
233 PyErr_SetString(BsddbError, "can't allocate lock");
234 Py_DECREF(dp);
235 return NULL;
237 #endif
239 return (PyObject *)dp;
242 static void
243 bsddb_dealloc(dp)
244 bsddbobject *dp;
246 #ifdef WITH_THREAD
247 if (dp->di_lock) {
248 PyThread_acquire_lock(dp->di_lock, 0);
249 PyThread_release_lock(dp->di_lock);
250 PyThread_free_lock(dp->di_lock);
251 dp->di_lock = NULL;
253 #endif
254 if (dp->di_bsddb != NULL) {
255 int status;
256 Py_BEGIN_ALLOW_THREADS
257 status = (dp->di_bsddb->close)(dp->di_bsddb);
258 Py_END_ALLOW_THREADS
259 if (status != 0)
260 fprintf(stderr,
261 "Python bsddb: close errno %d in dealloc\n",
262 errno);
264 PyMem_DEL(dp);
267 #ifdef WITH_THREAD
268 #define BSDDB_BGN_SAVE(_dp) Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(_dp->di_lock,1);
269 #define BSDDB_END_SAVE(_dp) PyThread_release_lock(_dp->di_lock); Py_END_ALLOW_THREADS
270 #else
271 #define BSDDB_BGN_SAVE(_dp) Py_BEGIN_ALLOW_THREADS
272 #define BSDDB_END_SAVE(_dp) Py_END_ALLOW_THREADS
273 #endif
275 static int
276 bsddb_length(dp)
277 bsddbobject *dp;
279 if (dp->di_bsddb == NULL) {
280 PyErr_SetString(BsddbError, "BSDDB object has already been closed");
281 return -1;
283 if (dp->di_size < 0) {
284 DBT krec, drec;
285 int status;
286 int size = 0;
287 BSDDB_BGN_SAVE(dp)
288 for (status = (dp->di_bsddb->seq)(dp->di_bsddb,
289 &krec, &drec,R_FIRST);
290 status == 0;
291 status = (dp->di_bsddb->seq)(dp->di_bsddb,
292 &krec, &drec, R_NEXT))
293 size++;
294 BSDDB_END_SAVE(dp)
295 if (status < 0) {
296 PyErr_SetFromErrno(BsddbError);
297 return -1;
299 dp->di_size = size;
301 return dp->di_size;
304 static PyObject *
305 bsddb_subscript(dp, key)
306 bsddbobject *dp;
307 PyObject *key;
309 int status;
310 DBT krec, drec;
311 char *data,buf[4096];
312 int size;
313 PyObject *result;
315 if (!PyArg_Parse(key, "s#", &data, &size))
316 return NULL;
317 check_bsddbobject_open(dp);
319 krec.data = data;
320 krec.size = size;
322 BSDDB_BGN_SAVE(dp)
323 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
324 if (status == 0) {
325 if (drec.size > sizeof(buf)) data = malloc(drec.size);
326 else data = buf;
327 memcpy(data,drec.data,drec.size);
329 BSDDB_END_SAVE(dp)
330 if (status != 0) {
331 if (status < 0)
332 PyErr_SetFromErrno(BsddbError);
333 else
334 PyErr_SetObject(PyExc_KeyError, key);
335 return NULL;
338 result = PyString_FromStringAndSize(data, (int)drec.size);
339 if (data != buf) free(data);
340 return result;
343 static int
344 bsddb_ass_sub(dp, key, value)
345 bsddbobject *dp;
346 PyObject *key, *value;
348 int status;
349 DBT krec, drec;
350 char *data;
351 int size;
353 if (!PyArg_Parse(key, "s#", &data, &size)) {
354 PyErr_SetString(PyExc_TypeError,
355 "bsddb key type must be string");
356 return -1;
358 if (dp->di_bsddb == NULL) {
359 PyErr_SetString(BsddbError, "BSDDB object has already been closed");
360 return -1;
362 krec.data = data;
363 krec.size = size;
364 dp->di_size = -1;
365 if (value == NULL) {
366 BSDDB_BGN_SAVE(dp)
367 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
368 BSDDB_END_SAVE(dp)
370 else {
371 if (!PyArg_Parse(value, "s#", &data, &size)) {
372 PyErr_SetString(PyExc_TypeError,
373 "bsddb value type must be string");
374 return -1;
376 drec.data = data;
377 drec.size = size;
378 #if 0
379 /* For RECNO, put fails with 'No space left on device'
380 after a few short records are added?? Looks fine
381 to this point... linked with 1.85 on Solaris Intel
382 Roger E. Masse 1/16/97
384 printf("before put data: '%s', size: %d\n",
385 drec.data, drec.size);
386 printf("before put key= '%s', size= %d\n",
387 krec.data, krec.size);
388 #endif
389 BSDDB_BGN_SAVE(dp)
390 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
391 BSDDB_END_SAVE(dp)
393 if (status != 0) {
394 if (status < 0)
395 PyErr_SetFromErrno(BsddbError);
396 else
397 PyErr_SetObject(PyExc_KeyError, key);
398 return -1;
400 return 0;
403 static PyMappingMethods bsddb_as_mapping = {
404 (inquiry)bsddb_length, /*mp_length*/
405 (binaryfunc)bsddb_subscript, /*mp_subscript*/
406 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
409 static PyObject *
410 bsddb_close(dp, args)
411 bsddbobject *dp;
412 PyObject *args;
414 if (!PyArg_NoArgs(args))
415 return NULL;
416 if (dp->di_bsddb != NULL) {
417 int status;
418 BSDDB_BGN_SAVE(dp)
419 status = (dp->di_bsddb->close)(dp->di_bsddb);
420 BSDDB_END_SAVE(dp)
421 if (status != 0) {
422 dp->di_bsddb = NULL;
423 PyErr_SetFromErrno(BsddbError);
424 return NULL;
427 dp->di_bsddb = NULL;
428 Py_INCREF(Py_None);
429 return Py_None;
432 static PyObject *
433 bsddb_keys(dp, args)
434 bsddbobject *dp;
435 PyObject *args;
437 PyObject *list, *item;
438 DBT krec, drec;
439 char *data=NULL,buf[4096];
440 int status;
441 int err;
443 if (!PyArg_NoArgs(args))
444 return NULL;
445 check_bsddbobject_open(dp);
446 list = PyList_New(0);
447 if (list == NULL)
448 return NULL;
449 BSDDB_BGN_SAVE(dp)
450 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
451 if (status == 0) {
452 if (krec.size > sizeof(buf)) data = malloc(krec.size);
453 else data = buf;
454 memcpy(data,krec.data,krec.size);
456 BSDDB_END_SAVE(dp)
457 while (status == 0) {
458 item = PyString_FromStringAndSize(data, (int)krec.size);
459 if (data != buf) free(data);
460 if (item == NULL) {
461 Py_DECREF(list);
462 return NULL;
464 err = PyList_Append(list, item);
465 Py_DECREF(item);
466 if (err != 0) {
467 Py_DECREF(list);
468 return NULL;
470 BSDDB_BGN_SAVE(dp)
471 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT);
472 if (status == 0) {
473 if (krec.size > sizeof(buf)) data = malloc(krec.size);
474 else data = buf;
475 memcpy(data,krec.data,krec.size);
477 BSDDB_END_SAVE(dp)
479 if (status < 0) {
480 PyErr_SetFromErrno(BsddbError);
481 Py_DECREF(list);
482 return NULL;
484 if (dp->di_size < 0)
485 dp->di_size = PyList_Size(list); /* We just did the work */
486 return list;
489 static PyObject *
490 bsddb_has_key(dp, args)
491 bsddbobject *dp;
492 PyObject *args;
494 DBT krec, drec;
495 int status;
496 char *data;
497 int size;
499 if (!PyArg_Parse(args, "s#", &data, &size))
500 return NULL;
501 check_bsddbobject_open(dp);
502 krec.data = data;
503 krec.size = size;
505 BSDDB_BGN_SAVE(dp)
506 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
507 BSDDB_END_SAVE(dp)
508 if (status < 0) {
509 PyErr_SetFromErrno(BsddbError);
510 return NULL;
513 return PyInt_FromLong(status == 0);
516 static PyObject *
517 bsddb_set_location(dp, key)
518 bsddbobject *dp;
519 PyObject *key;
521 int status;
522 DBT krec, drec;
523 char *data,buf[4096];
524 int size;
525 PyObject *result;
527 if (!PyArg_Parse(key, "s#", &data, &size))
528 return NULL;
529 check_bsddbobject_open(dp);
530 krec.data = data;
531 krec.size = size;
533 BSDDB_BGN_SAVE(dp)
534 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
535 if (status == 0) {
536 if (drec.size > sizeof(buf)) data = malloc(drec.size);
537 else data = buf;
538 memcpy(data,drec.data,drec.size);
540 BSDDB_END_SAVE(dp)
541 if (status != 0) {
542 if (status < 0)
543 PyErr_SetFromErrno(BsddbError);
544 else
545 PyErr_SetObject(PyExc_KeyError, key);
546 return NULL;
549 result = Py_BuildValue("s#s#", krec.data, krec.size, data, drec.size);
550 if (data != buf) free(data);
551 return result;
554 static PyObject *
555 bsddb_seq(dp, args, sequence_request)
556 bsddbobject *dp;
557 PyObject *args;
558 int sequence_request;
560 int status;
561 DBT krec, drec;
562 char *kdata=NULL,kbuf[4096];
563 char *ddata=NULL,dbuf[4096];
564 PyObject *result;
566 if (!PyArg_NoArgs(args))
567 return NULL;
569 check_bsddbobject_open(dp);
570 krec.data = 0;
571 krec.size = 0;
573 BSDDB_BGN_SAVE(dp)
574 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec,
575 &drec, sequence_request);
576 if (status == 0) {
577 if (krec.size > sizeof(kbuf)) kdata = malloc(krec.size);
578 else kdata = kbuf;
579 memcpy(kdata,krec.data,krec.size);
580 if (drec.size > sizeof(dbuf)) ddata = malloc(drec.size);
581 else ddata = dbuf;
582 memcpy(ddata,drec.data,drec.size);
584 BSDDB_END_SAVE(dp)
585 if (status != 0) {
586 if (status < 0)
587 PyErr_SetFromErrno(BsddbError);
588 else
589 PyErr_SetObject(PyExc_KeyError, args);
590 return NULL;
593 result = Py_BuildValue("s#s#", kdata, krec.size, ddata, drec.size);
594 if (kdata != kbuf) free(kdata);
595 if (ddata != dbuf) free(ddata);
596 return result;
599 static PyObject *
600 bsddb_next(dp, key)
601 bsddbobject *dp;
602 PyObject *key;
604 return bsddb_seq(dp, key, R_NEXT);
606 static PyObject *
607 bsddb_previous(dp, key)
608 bsddbobject *dp;
609 PyObject *key;
611 return bsddb_seq(dp, key, R_PREV);
613 static PyObject *
614 bsddb_first(dp, key)
615 bsddbobject *dp;
616 PyObject *key;
618 return bsddb_seq(dp, key, R_FIRST);
620 static PyObject *
621 bsddb_last(dp, key)
622 bsddbobject *dp;
623 PyObject *key;
625 return bsddb_seq(dp, key, R_LAST);
627 static PyObject *
628 bsddb_sync(dp, args)
629 bsddbobject *dp;
630 PyObject *args;
632 int status;
634 if (!PyArg_NoArgs(args))
635 return NULL;
636 check_bsddbobject_open(dp);
637 BSDDB_BGN_SAVE(dp)
638 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
639 BSDDB_END_SAVE(dp)
640 if (status != 0) {
641 PyErr_SetFromErrno(BsddbError);
642 return NULL;
644 return PyInt_FromLong(status = 0);
646 static PyMethodDef bsddb_methods[] = {
647 {"close", (PyCFunction)bsddb_close},
648 {"keys", (PyCFunction)bsddb_keys},
649 {"has_key", (PyCFunction)bsddb_has_key},
650 {"set_location", (PyCFunction)bsddb_set_location},
651 {"next", (PyCFunction)bsddb_next},
652 {"previous", (PyCFunction)bsddb_previous},
653 {"first", (PyCFunction)bsddb_first},
654 {"last", (PyCFunction)bsddb_last},
655 {"sync", (PyCFunction)bsddb_sync},
656 {NULL, NULL} /* sentinel */
659 static PyObject *
660 bsddb_getattr(dp, name)
661 PyObject *dp;
662 char *name;
664 return Py_FindMethod(bsddb_methods, dp, name);
667 static PyTypeObject Bsddbtype = {
668 PyObject_HEAD_INIT(NULL)
670 "bsddb",
671 sizeof(bsddbobject),
673 (destructor)bsddb_dealloc, /*tp_dealloc*/
674 0, /*tp_print*/
675 (getattrfunc)bsddb_getattr, /*tp_getattr*/
676 0, /*tp_setattr*/
677 0, /*tp_compare*/
678 0, /*tp_repr*/
679 0, /*tp_as_number*/
680 0, /*tp_as_sequence*/
681 &bsddb_as_mapping, /*tp_as_mapping*/
684 static PyObject *
685 bsdhashopen(self, args)
686 PyObject *self;
687 PyObject *args;
689 char *file;
690 char *flag = NULL;
691 int flags = O_RDONLY;
692 int mode = 0666;
693 int bsize = 0;
694 int ffactor = 0;
695 int nelem = 0;
696 int cachesize = 0;
697 int hash = 0; /* XXX currently ignored */
698 int lorder = 0;
700 if (!PyArg_ParseTuple(args, "s|siiiiiii",
701 &file, &flag, &mode,
702 &bsize, &ffactor, &nelem, &cachesize,
703 &hash, &lorder))
704 return NULL;
705 if (flag != NULL) {
706 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
707 if (flag[0] == 'r')
708 flags = O_RDONLY;
709 else if (flag[0] == 'w')
710 flags = O_RDWR;
711 else if (flag[0] == 'c')
712 flags = O_RDWR|O_CREAT;
713 else if (flag[0] == 'n')
714 flags = O_RDWR|O_CREAT|O_TRUNC;
715 else {
716 PyErr_SetString(BsddbError,
717 "Flag should begin with 'r', 'w', 'c' or 'n'");
718 return NULL;
720 if (flag[1] == 'l') {
721 #if defined(O_EXLOCK) && defined(O_SHLOCK)
722 if (flag[0] == 'r')
723 flags |= O_SHLOCK;
724 else
725 flags |= O_EXLOCK;
726 #else
727 PyErr_SetString(BsddbError,
728 "locking not supported on this platform");
729 return NULL;
730 #endif
733 return newdbhashobject(file, flags, mode,
734 bsize, ffactor, nelem, cachesize, hash, lorder);
737 static PyObject *
738 bsdbtopen(self, args)
739 PyObject *self;
740 PyObject *args;
742 char *file;
743 char *flag = NULL;
744 int flags = O_RDONLY;
745 int mode = 0666;
746 int cachesize = 0;
747 int maxkeypage = 0;
748 int minkeypage = 0;
749 int btflags = 0;
750 unsigned int psize = 0;
751 int lorder = 0;
753 if (!PyArg_ParseTuple(args, "s|siiiiiii",
754 &file, &flag, &mode,
755 &btflags, &cachesize, &maxkeypage, &minkeypage,
756 &psize, &lorder))
757 return NULL;
758 if (flag != NULL) {
759 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
760 if (flag[0] == 'r')
761 flags = O_RDONLY;
762 else if (flag[0] == 'w')
763 flags = O_RDWR;
764 else if (flag[0] == 'c')
765 flags = O_RDWR|O_CREAT;
766 else if (flag[0] == 'n')
767 flags = O_RDWR|O_CREAT|O_TRUNC;
768 else {
769 PyErr_SetString(BsddbError,
770 "Flag should begin with 'r', 'w', 'c' or 'n'");
771 return NULL;
773 if (flag[1] == 'l') {
774 #if defined(O_EXLOCK) && defined(O_SHLOCK)
775 if (flag[0] == 'r')
776 flags |= O_SHLOCK;
777 else
778 flags |= O_EXLOCK;
779 #else
780 PyErr_SetString(BsddbError,
781 "locking not supported on this platform");
782 return NULL;
783 #endif
786 return newdbbtobject(file, flags, mode,
787 btflags, cachesize, maxkeypage, minkeypage,
788 psize, lorder);
791 static PyObject *
792 bsdrnopen(self, args)
793 PyObject *self;
794 PyObject *args;
796 char *file;
797 char *flag = NULL;
798 int flags = O_RDONLY;
799 int mode = 0666;
800 int cachesize = 0;
801 int rnflags = 0;
802 unsigned int psize = 0;
803 int lorder = 0;
804 size_t reclen = 0;
805 char *bval = "";
806 char *bfname = NULL;
808 if (!PyArg_ParseTuple(args, "s|siiiiiiss",
809 &file, &flag, &mode,
810 &rnflags, &cachesize, &psize, &lorder,
811 &reclen, &bval, &bfname))
812 return NULL;
814 # if 0
815 printf("file: %s\n", file);
816 printf("flag: %s\n", flag);
817 printf("mode: %d\n", mode);
818 printf("rnflags: 0x%x\n", rnflags);
819 printf("cachesize: %d\n", cachesize);
820 printf("psize: %d\n", psize);
821 printf("lorder: %d\n", 0);
822 printf("reclen: %d\n", reclen);
823 printf("bval: %c\n", bval[0]);
824 printf("bfname %s\n", bfname);
825 #endif
827 if (flag != NULL) {
828 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
829 if (flag[0] == 'r')
830 flags = O_RDONLY;
831 else if (flag[0] == 'w')
832 flags = O_RDWR;
833 else if (flag[0] == 'c')
834 flags = O_RDWR|O_CREAT;
835 else if (flag[0] == 'n')
836 flags = O_RDWR|O_CREAT|O_TRUNC;
837 else {
838 PyErr_SetString(BsddbError,
839 "Flag should begin with 'r', 'w', 'c' or 'n'");
840 return NULL;
842 if (flag[1] == 'l') {
843 #if defined(O_EXLOCK) && defined(O_SHLOCK)
844 if (flag[0] == 'r')
845 flags |= O_SHLOCK;
846 else
847 flags |= O_EXLOCK;
848 #else
849 PyErr_SetString(BsddbError,
850 "locking not supported on this platform");
851 return NULL;
852 #endif
854 else if (flag[1] != '\0') {
855 PyErr_SetString(BsddbError,
856 "Flag char 2 should be 'l' or absent");
857 return NULL;
860 return newdbrnobject(file, flags, mode, rnflags, cachesize,
861 psize, lorder, reclen, bval[0], bfname);
864 static PyMethodDef bsddbmodule_methods[] = {
865 {"hashopen", (PyCFunction)bsdhashopen, 1},
866 {"btopen", (PyCFunction)bsdbtopen, 1},
867 {"rnopen", (PyCFunction)bsdrnopen, 1},
868 {0, 0},
871 DL_EXPORT(void)
872 initbsddb() {
873 PyObject *m, *d;
875 Bsddbtype.ob_type = &PyType_Type;
876 m = Py_InitModule("bsddb", bsddbmodule_methods);
877 d = PyModule_GetDict(m);
878 BsddbError = PyErr_NewException("bsddb.error", NULL, NULL);
879 if (BsddbError != NULL)
880 PyDict_SetItemString(d, "error", BsddbError);