Class around PixMap objects that allows more python-like access. By Joe Strout.
[python/dscho.git] / Modules / bsddbmodule.c
blobef20624281477a62f14979ac1bacd1f576039df3
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
43 #include "Python.h"
44 #ifdef WITH_THREAD
45 #include "pythread.h"
46 #endif
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <fcntl.h>
51 #include <db.h>
52 /* Please don't include internal header files of the Berkeley db package
53 (it messes up the info required in the Setup file) */
55 typedef struct {
56 PyObject_HEAD
57 DB *di_bsddb;
58 int di_size; /* -1 means recompute */
59 #ifdef WITH_THREAD
60 PyThread_type_lock di_lock;
61 #endif
62 } bsddbobject;
64 staticforward PyTypeObject Bsddbtype;
66 #define is_bsddbobject(v) ((v)->ob_type == &Bsddbtype)
67 #define check_bsddbobject_open(v) if ((v)->di_bsddb == NULL) \
68 { PyErr_SetString(BsddbError, "BSDDB object has already been closed"); \
69 return NULL; }
71 static PyObject *BsddbError;
73 static PyObject *
74 newdbhashobject(file, flags, mode,
75 bsize, ffactor, nelem, cachesize, hash, lorder)
76 char *file;
77 int flags;
78 int mode;
79 int bsize;
80 int ffactor;
81 int nelem;
82 int cachesize;
83 int hash; /* XXX ignored */
84 int lorder;
86 bsddbobject *dp;
87 HASHINFO info;
89 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
90 return NULL;
92 info.bsize = bsize;
93 info.ffactor = ffactor;
94 info.nelem = nelem;
95 info.cachesize = cachesize;
96 info.hash = NULL; /* XXX should derive from hash argument */
97 info.lorder = lorder;
99 #ifdef O_BINARY
100 flags |= O_BINARY;
101 #endif
102 Py_BEGIN_ALLOW_THREADS
103 dp->di_bsddb = dbopen(file, flags, mode, DB_HASH, &info);
104 Py_END_ALLOW_THREADS
105 if (dp->di_bsddb == NULL) {
106 PyErr_SetFromErrno(BsddbError);
107 #ifdef WITH_THREAD
108 dp->di_lock = NULL;
109 #endif
110 Py_DECREF(dp);
111 return NULL;
114 dp->di_size = -1;
115 #ifdef WITH_THREAD
116 dp->di_lock = PyThread_allocate_lock();
117 if (dp->di_lock == NULL) {
118 PyErr_SetString(BsddbError, "can't allocate lock");
119 Py_DECREF(dp);
120 return NULL;
122 #endif
124 return (PyObject *)dp;
127 static PyObject *
128 newdbbtobject(file, flags, mode,
129 btflags, cachesize, maxkeypage, minkeypage, psize, lorder)
130 char *file;
131 int flags;
132 int mode;
133 int btflags;
134 int cachesize;
135 int maxkeypage;
136 int minkeypage;
137 int psize;
138 int lorder;
140 bsddbobject *dp;
141 BTREEINFO info;
143 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
144 return NULL;
146 info.flags = btflags;
147 info.cachesize = cachesize;
148 info.maxkeypage = maxkeypage;
149 info.minkeypage = minkeypage;
150 info.psize = psize;
151 info.lorder = lorder;
152 info.compare = 0; /* Use default comparison functions, for now..*/
153 info.prefix = 0;
155 #ifdef O_BINARY
156 flags |= O_BINARY;
157 #endif
158 Py_BEGIN_ALLOW_THREADS
159 dp->di_bsddb = dbopen(file, flags, mode, DB_BTREE, &info);
160 Py_END_ALLOW_THREADS
161 if (dp->di_bsddb == NULL) {
162 PyErr_SetFromErrno(BsddbError);
163 #ifdef WITH_THREAD
164 dp->di_lock = NULL;
165 #endif
166 Py_DECREF(dp);
167 return NULL;
170 dp->di_size = -1;
171 #ifdef WITH_THREAD
172 dp->di_lock = PyThread_allocate_lock();
173 if (dp->di_lock == NULL) {
174 PyErr_SetString(BsddbError, "can't allocate lock");
175 Py_DECREF(dp);
176 return NULL;
178 #endif
180 return (PyObject *)dp;
183 static PyObject *
184 newdbrnobject(file, flags, mode,
185 rnflags, cachesize, psize, lorder, reclen, bval, bfname)
186 char *file;
187 int flags;
188 int mode;
189 int rnflags;
190 int cachesize;
191 int psize;
192 int lorder;
193 size_t reclen;
194 u_char bval;
195 char *bfname;
197 bsddbobject *dp;
198 RECNOINFO info;
200 if ((dp = PyObject_NEW(bsddbobject, &Bsddbtype)) == NULL)
201 return NULL;
203 info.flags = rnflags;
204 info.cachesize = cachesize;
205 info.psize = psize;
206 info.lorder = lorder;
207 info.reclen = reclen;
208 info.bval = bval;
209 info.bfname = bfname;
211 #ifdef O_BINARY
212 flags |= O_BINARY;
213 #endif
214 Py_BEGIN_ALLOW_THREADS
215 dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info);
216 Py_END_ALLOW_THREADS
217 if (dp->di_bsddb == NULL) {
218 PyErr_SetFromErrno(BsddbError);
219 #ifdef WITH_THREAD
220 dp->di_lock = NULL;
221 #endif
222 Py_DECREF(dp);
223 return NULL;
226 dp->di_size = -1;
227 #ifdef WITH_THREAD
228 dp->di_lock = PyThread_allocate_lock();
229 if (dp->di_lock == NULL) {
230 PyErr_SetString(BsddbError, "can't allocate lock");
231 Py_DECREF(dp);
232 return NULL;
234 #endif
236 return (PyObject *)dp;
239 static void
240 bsddb_dealloc(dp)
241 bsddbobject *dp;
243 #ifdef WITH_THREAD
244 if (dp->di_lock) {
245 PyThread_acquire_lock(dp->di_lock, 0);
246 PyThread_release_lock(dp->di_lock);
247 PyThread_free_lock(dp->di_lock);
248 dp->di_lock = NULL;
250 #endif
251 if (dp->di_bsddb != NULL) {
252 int status;
253 Py_BEGIN_ALLOW_THREADS
254 status = (dp->di_bsddb->close)(dp->di_bsddb);
255 Py_END_ALLOW_THREADS
256 if (status != 0)
257 fprintf(stderr,
258 "Python bsddb: close errno %d in dealloc\n",
259 errno);
261 PyMem_DEL(dp);
264 #ifdef WITH_THREAD
265 #define BSDDB_BGN_SAVE(_dp) Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(_dp->di_lock,1);
266 #define BSDDB_END_SAVE(_dp) PyThread_release_lock(_dp->di_lock); Py_END_ALLOW_THREADS
267 #else
268 #define BSDDB_BGN_SAVE(_dp) Py_BEGIN_ALLOW_THREADS
269 #define BSDDB_END_SAVE(_dp) Py_END_ALLOW_THREADS
270 #endif
272 static int
273 bsddb_length(dp)
274 bsddbobject *dp;
276 if (dp->di_bsddb == NULL) {
277 PyErr_SetString(BsddbError, "BSDDB object has already been closed");
278 return -1;
280 if (dp->di_size < 0) {
281 DBT krec, drec;
282 int status;
283 int size = 0;
284 BSDDB_BGN_SAVE(dp)
285 for (status = (dp->di_bsddb->seq)(dp->di_bsddb,
286 &krec, &drec,R_FIRST);
287 status == 0;
288 status = (dp->di_bsddb->seq)(dp->di_bsddb,
289 &krec, &drec, R_NEXT))
290 size++;
291 BSDDB_END_SAVE(dp)
292 if (status < 0) {
293 PyErr_SetFromErrno(BsddbError);
294 return -1;
296 dp->di_size = size;
298 return dp->di_size;
301 static PyObject *
302 bsddb_subscript(dp, key)
303 bsddbobject *dp;
304 PyObject *key;
306 int status;
307 DBT krec, drec;
308 char *data,buf[4096];
309 int size;
310 PyObject *result;
312 if (!PyArg_Parse(key, "s#", &data, &size))
313 return NULL;
314 check_bsddbobject_open(dp);
316 krec.data = data;
317 krec.size = size;
319 BSDDB_BGN_SAVE(dp)
320 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
321 if (status == 0) {
322 if (drec.size > sizeof(buf)) data = malloc(drec.size);
323 else data = buf;
324 memcpy(data,drec.data,drec.size);
326 BSDDB_END_SAVE(dp)
327 if (status != 0) {
328 if (status < 0)
329 PyErr_SetFromErrno(BsddbError);
330 else
331 PyErr_SetObject(PyExc_KeyError, key);
332 return NULL;
335 result = PyString_FromStringAndSize(data, (int)drec.size);
336 if (data != buf) free(data);
337 return result;
340 static int
341 bsddb_ass_sub(dp, key, value)
342 bsddbobject *dp;
343 PyObject *key, *value;
345 int status;
346 DBT krec, drec;
347 char *data;
348 int size;
350 if (!PyArg_Parse(key, "s#", &data, &size)) {
351 PyErr_SetString(PyExc_TypeError,
352 "bsddb key type must be string");
353 return -1;
355 if (dp->di_bsddb == NULL) {
356 PyErr_SetString(BsddbError, "BSDDB object has already been closed");
357 return -1;
359 krec.data = data;
360 krec.size = size;
361 dp->di_size = -1;
362 if (value == NULL) {
363 BSDDB_BGN_SAVE(dp)
364 status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
365 BSDDB_END_SAVE(dp)
367 else {
368 if (!PyArg_Parse(value, "s#", &data, &size)) {
369 PyErr_SetString(PyExc_TypeError,
370 "bsddb value type must be string");
371 return -1;
373 drec.data = data;
374 drec.size = size;
375 #if 0
376 /* For RECNO, put fails with 'No space left on device'
377 after a few short records are added?? Looks fine
378 to this point... linked with 1.85 on Solaris Intel
379 Roger E. Masse 1/16/97
381 printf("before put data: '%s', size: %d\n",
382 drec.data, drec.size);
383 printf("before put key= '%s', size= %d\n",
384 krec.data, krec.size);
385 #endif
386 BSDDB_BGN_SAVE(dp)
387 status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
388 BSDDB_END_SAVE(dp)
390 if (status != 0) {
391 if (status < 0)
392 PyErr_SetFromErrno(BsddbError);
393 else
394 PyErr_SetObject(PyExc_KeyError, key);
395 return -1;
397 return 0;
400 static PyMappingMethods bsddb_as_mapping = {
401 (inquiry)bsddb_length, /*mp_length*/
402 (binaryfunc)bsddb_subscript, /*mp_subscript*/
403 (objobjargproc)bsddb_ass_sub, /*mp_ass_subscript*/
406 static PyObject *
407 bsddb_close(dp, args)
408 bsddbobject *dp;
409 PyObject *args;
411 if (!PyArg_NoArgs(args))
412 return NULL;
413 if (dp->di_bsddb != NULL) {
414 int status;
415 BSDDB_BGN_SAVE(dp)
416 status = (dp->di_bsddb->close)(dp->di_bsddb);
417 BSDDB_END_SAVE(dp)
418 if (status != 0) {
419 dp->di_bsddb = NULL;
420 PyErr_SetFromErrno(BsddbError);
421 return NULL;
424 dp->di_bsddb = NULL;
425 Py_INCREF(Py_None);
426 return Py_None;
429 static PyObject *
430 bsddb_keys(dp, args)
431 bsddbobject *dp;
432 PyObject *args;
434 PyObject *list, *item;
435 DBT krec, drec;
436 char *data=NULL,buf[4096];
437 int status;
438 int err;
440 if (!PyArg_NoArgs(args))
441 return NULL;
442 check_bsddbobject_open(dp);
443 list = PyList_New(0);
444 if (list == NULL)
445 return NULL;
446 BSDDB_BGN_SAVE(dp)
447 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
448 if (status == 0) {
449 if (krec.size > sizeof(buf)) data = malloc(krec.size);
450 else data = buf;
451 memcpy(data,krec.data,krec.size);
453 BSDDB_END_SAVE(dp)
454 while (status == 0) {
455 item = PyString_FromStringAndSize(data, (int)krec.size);
456 if (data != buf) free(data);
457 if (item == NULL) {
458 Py_DECREF(list);
459 return NULL;
461 err = PyList_Append(list, item);
462 Py_DECREF(item);
463 if (err != 0) {
464 Py_DECREF(list);
465 return NULL;
467 BSDDB_BGN_SAVE(dp)
468 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT);
469 if (status == 0) {
470 if (krec.size > sizeof(buf)) data = malloc(krec.size);
471 else data = buf;
472 memcpy(data,krec.data,krec.size);
474 BSDDB_END_SAVE(dp)
476 if (status < 0) {
477 PyErr_SetFromErrno(BsddbError);
478 Py_DECREF(list);
479 return NULL;
481 if (dp->di_size < 0)
482 dp->di_size = PyList_Size(list); /* We just did the work */
483 return list;
486 static PyObject *
487 bsddb_has_key(dp, args)
488 bsddbobject *dp;
489 PyObject *args;
491 DBT krec, drec;
492 int status;
493 char *data;
494 int size;
496 if (!PyArg_Parse(args, "s#", &data, &size))
497 return NULL;
498 check_bsddbobject_open(dp);
499 krec.data = data;
500 krec.size = size;
502 BSDDB_BGN_SAVE(dp)
503 status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
504 BSDDB_END_SAVE(dp)
505 if (status < 0) {
506 PyErr_SetFromErrno(BsddbError);
507 return NULL;
510 return PyInt_FromLong(status == 0);
513 static PyObject *
514 bsddb_set_location(dp, key)
515 bsddbobject *dp;
516 PyObject *key;
518 int status;
519 DBT krec, drec;
520 char *data,buf[4096];
521 int size;
522 PyObject *result;
524 if (!PyArg_Parse(key, "s#", &data, &size))
525 return NULL;
526 check_bsddbobject_open(dp);
527 krec.data = data;
528 krec.size = size;
530 BSDDB_BGN_SAVE(dp)
531 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
532 if (status == 0) {
533 if (drec.size > sizeof(buf)) data = malloc(drec.size);
534 else data = buf;
535 memcpy(data,drec.data,drec.size);
537 BSDDB_END_SAVE(dp)
538 if (status != 0) {
539 if (status < 0)
540 PyErr_SetFromErrno(BsddbError);
541 else
542 PyErr_SetObject(PyExc_KeyError, key);
543 return NULL;
546 result = Py_BuildValue("s#s#", krec.data, krec.size, data, drec.size);
547 if (data != buf) free(data);
548 return result;
551 static PyObject *
552 bsddb_seq(dp, args, sequence_request)
553 bsddbobject *dp;
554 PyObject *args;
555 int sequence_request;
557 int status;
558 DBT krec, drec;
559 char *kdata=NULL,kbuf[4096];
560 char *ddata=NULL,dbuf[4096];
561 PyObject *result;
563 if (!PyArg_NoArgs(args))
564 return NULL;
566 check_bsddbobject_open(dp);
567 krec.data = 0;
568 krec.size = 0;
570 BSDDB_BGN_SAVE(dp)
571 status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec,
572 &drec, sequence_request);
573 if (status == 0) {
574 if (krec.size > sizeof(kbuf)) kdata = malloc(krec.size);
575 else kdata = kbuf;
576 memcpy(kdata,krec.data,krec.size);
577 if (drec.size > sizeof(dbuf)) ddata = malloc(drec.size);
578 else ddata = dbuf;
579 memcpy(ddata,drec.data,drec.size);
581 BSDDB_END_SAVE(dp)
582 if (status != 0) {
583 if (status < 0)
584 PyErr_SetFromErrno(BsddbError);
585 else
586 PyErr_SetObject(PyExc_KeyError, args);
587 return NULL;
590 result = Py_BuildValue("s#s#", kdata, krec.size, ddata, drec.size);
591 if (kdata != kbuf) free(kdata);
592 if (ddata != dbuf) free(ddata);
593 return result;
596 static PyObject *
597 bsddb_next(dp, key)
598 bsddbobject *dp;
599 PyObject *key;
601 return bsddb_seq(dp, key, R_NEXT);
603 static PyObject *
604 bsddb_previous(dp, key)
605 bsddbobject *dp;
606 PyObject *key;
608 return bsddb_seq(dp, key, R_PREV);
610 static PyObject *
611 bsddb_first(dp, key)
612 bsddbobject *dp;
613 PyObject *key;
615 return bsddb_seq(dp, key, R_FIRST);
617 static PyObject *
618 bsddb_last(dp, key)
619 bsddbobject *dp;
620 PyObject *key;
622 return bsddb_seq(dp, key, R_LAST);
624 static PyObject *
625 bsddb_sync(dp, args)
626 bsddbobject *dp;
627 PyObject *args;
629 int status;
631 if (!PyArg_NoArgs(args))
632 return NULL;
633 check_bsddbobject_open(dp);
634 BSDDB_BGN_SAVE(dp)
635 status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
636 BSDDB_END_SAVE(dp)
637 if (status != 0) {
638 PyErr_SetFromErrno(BsddbError);
639 return NULL;
641 return PyInt_FromLong(status = 0);
643 static PyMethodDef bsddb_methods[] = {
644 {"close", (PyCFunction)bsddb_close},
645 {"keys", (PyCFunction)bsddb_keys},
646 {"has_key", (PyCFunction)bsddb_has_key},
647 {"set_location", (PyCFunction)bsddb_set_location},
648 {"next", (PyCFunction)bsddb_next},
649 {"previous", (PyCFunction)bsddb_previous},
650 {"first", (PyCFunction)bsddb_first},
651 {"last", (PyCFunction)bsddb_last},
652 {"sync", (PyCFunction)bsddb_sync},
653 {NULL, NULL} /* sentinel */
656 static PyObject *
657 bsddb_getattr(dp, name)
658 PyObject *dp;
659 char *name;
661 return Py_FindMethod(bsddb_methods, dp, name);
664 static PyTypeObject Bsddbtype = {
665 PyObject_HEAD_INIT(NULL)
667 "bsddb",
668 sizeof(bsddbobject),
670 (destructor)bsddb_dealloc, /*tp_dealloc*/
671 0, /*tp_print*/
672 (getattrfunc)bsddb_getattr, /*tp_getattr*/
673 0, /*tp_setattr*/
674 0, /*tp_compare*/
675 0, /*tp_repr*/
676 0, /*tp_as_number*/
677 0, /*tp_as_sequence*/
678 &bsddb_as_mapping, /*tp_as_mapping*/
681 static PyObject *
682 bsdhashopen(self, args)
683 PyObject *self;
684 PyObject *args;
686 char *file;
687 char *flag = NULL;
688 int flags = O_RDONLY;
689 int mode = 0666;
690 int bsize = 0;
691 int ffactor = 0;
692 int nelem = 0;
693 int cachesize = 0;
694 int hash = 0; /* XXX currently ignored */
695 int lorder = 0;
697 if (!PyArg_ParseTuple(args, "s|siiiiiii",
698 &file, &flag, &mode,
699 &bsize, &ffactor, &nelem, &cachesize,
700 &hash, &lorder))
701 return NULL;
702 if (flag != NULL) {
703 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
704 if (flag[0] == 'r')
705 flags = O_RDONLY;
706 else if (flag[0] == 'w')
707 flags = O_RDWR;
708 else if (flag[0] == 'c')
709 flags = O_RDWR|O_CREAT;
710 else if (flag[0] == 'n')
711 flags = O_RDWR|O_CREAT|O_TRUNC;
712 else {
713 PyErr_SetString(BsddbError,
714 "Flag should begin with 'r', 'w', 'c' or 'n'");
715 return NULL;
717 if (flag[1] == 'l') {
718 #if defined(O_EXLOCK) && defined(O_SHLOCK)
719 if (flag[0] == 'r')
720 flags |= O_SHLOCK;
721 else
722 flags |= O_EXLOCK;
723 #else
724 PyErr_SetString(BsddbError,
725 "locking not supported on this platform");
726 return NULL;
727 #endif
730 return newdbhashobject(file, flags, mode,
731 bsize, ffactor, nelem, cachesize, hash, lorder);
734 static PyObject *
735 bsdbtopen(self, args)
736 PyObject *self;
737 PyObject *args;
739 char *file;
740 char *flag = NULL;
741 int flags = O_RDONLY;
742 int mode = 0666;
743 int cachesize = 0;
744 int maxkeypage = 0;
745 int minkeypage = 0;
746 int btflags = 0;
747 unsigned int psize = 0;
748 int lorder = 0;
750 if (!PyArg_ParseTuple(args, "s|siiiiiii",
751 &file, &flag, &mode,
752 &btflags, &cachesize, &maxkeypage, &minkeypage,
753 &psize, &lorder))
754 return NULL;
755 if (flag != NULL) {
756 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
757 if (flag[0] == 'r')
758 flags = O_RDONLY;
759 else if (flag[0] == 'w')
760 flags = O_RDWR;
761 else if (flag[0] == 'c')
762 flags = O_RDWR|O_CREAT;
763 else if (flag[0] == 'n')
764 flags = O_RDWR|O_CREAT|O_TRUNC;
765 else {
766 PyErr_SetString(BsddbError,
767 "Flag should begin with 'r', 'w', 'c' or 'n'");
768 return NULL;
770 if (flag[1] == 'l') {
771 #if defined(O_EXLOCK) && defined(O_SHLOCK)
772 if (flag[0] == 'r')
773 flags |= O_SHLOCK;
774 else
775 flags |= O_EXLOCK;
776 #else
777 PyErr_SetString(BsddbError,
778 "locking not supported on this platform");
779 return NULL;
780 #endif
783 return newdbbtobject(file, flags, mode,
784 btflags, cachesize, maxkeypage, minkeypage,
785 psize, lorder);
788 static PyObject *
789 bsdrnopen(self, args)
790 PyObject *self;
791 PyObject *args;
793 char *file;
794 char *flag = NULL;
795 int flags = O_RDONLY;
796 int mode = 0666;
797 int cachesize = 0;
798 int rnflags = 0;
799 unsigned int psize = 0;
800 int lorder = 0;
801 size_t reclen = 0;
802 char *bval = "";
803 char *bfname = NULL;
805 if (!PyArg_ParseTuple(args, "s|siiiiiiss",
806 &file, &flag, &mode,
807 &rnflags, &cachesize, &psize, &lorder,
808 &reclen, &bval, &bfname))
809 return NULL;
811 # if 0
812 printf("file: %s\n", file);
813 printf("flag: %s\n", flag);
814 printf("mode: %d\n", mode);
815 printf("rnflags: 0x%x\n", rnflags);
816 printf("cachesize: %d\n", cachesize);
817 printf("psize: %d\n", psize);
818 printf("lorder: %d\n", 0);
819 printf("reclen: %d\n", reclen);
820 printf("bval: %c\n", bval[0]);
821 printf("bfname %s\n", bfname);
822 #endif
824 if (flag != NULL) {
825 /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
826 if (flag[0] == 'r')
827 flags = O_RDONLY;
828 else if (flag[0] == 'w')
829 flags = O_RDWR;
830 else if (flag[0] == 'c')
831 flags = O_RDWR|O_CREAT;
832 else if (flag[0] == 'n')
833 flags = O_RDWR|O_CREAT|O_TRUNC;
834 else {
835 PyErr_SetString(BsddbError,
836 "Flag should begin with 'r', 'w', 'c' or 'n'");
837 return NULL;
839 if (flag[1] == 'l') {
840 #if defined(O_EXLOCK) && defined(O_SHLOCK)
841 if (flag[0] == 'r')
842 flags |= O_SHLOCK;
843 else
844 flags |= O_EXLOCK;
845 #else
846 PyErr_SetString(BsddbError,
847 "locking not supported on this platform");
848 return NULL;
849 #endif
851 else if (flag[1] != '\0') {
852 PyErr_SetString(BsddbError,
853 "Flag char 2 should be 'l' or absent");
854 return NULL;
857 return newdbrnobject(file, flags, mode, rnflags, cachesize,
858 psize, lorder, reclen, bval[0], bfname);
861 static PyMethodDef bsddbmodule_methods[] = {
862 {"hashopen", (PyCFunction)bsdhashopen, 1},
863 {"btopen", (PyCFunction)bsdbtopen, 1},
864 {"rnopen", (PyCFunction)bsdrnopen, 1},
865 {0, 0},
868 DL_EXPORT(void)
869 initbsddb() {
870 PyObject *m, *d;
872 Bsddbtype.ob_type = &PyType_Type;
873 m = Py_InitModule("bsddb", bsddbmodule_methods);
874 d = PyModule_GetDict(m);
875 BsddbError = PyErr_NewException("bsddb.error", NULL, NULL);
876 if (BsddbError != NULL)
877 PyDict_SetItemString(d, "error", BsddbError);