home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Modules / bsddbmodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-25  |  17.8 KB  |  793 lines

  1.  
  2. /* Berkeley DB interface.
  3.    Author: Michael McLay
  4.    Hacked: Guido van Rossum
  5.    Btree and Recno additions plus sequence methods: David Ely
  6.  
  7.    XXX To do:
  8.    - provide interface to the B-tree and record libraries too
  9.    - provide a way to access the various hash functions
  10.    - support more open flags
  11.  
  12.    The windows port of the Berkeley DB code is hard to find on the web:
  13.    www.nightmare.com/software.html
  14. */
  15.  
  16. #include "Python.h"
  17. #ifdef WITH_THREAD
  18. #include "pythread.h"
  19. #endif
  20.  
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <fcntl.h>
  24. #ifdef HAVE_DB_185_H
  25. #include <db_185.h>
  26. #else
  27. #include <db.h>
  28. #endif
  29. /* Please don't include internal header files of the Berkeley db package
  30.    (it messes up the info required in the Setup file) */
  31.  
  32. typedef struct {
  33.     PyObject_HEAD
  34.     DB *di_bsddb;
  35.     int di_size;    /* -1 means recompute */
  36. #ifdef WITH_THREAD
  37.     PyThread_type_lock di_lock;
  38. #endif
  39. } bsddbobject;
  40.  
  41. staticforward PyTypeObject Bsddbtype;
  42.  
  43. #define is_bsddbobject(v) ((v)->ob_type == &Bsddbtype)
  44. #define check_bsddbobject_open(v) if ((v)->di_bsddb == NULL) \
  45.                { PyErr_SetString(BsddbError, "BSDDB object has already been closed"); \
  46.                  return NULL; }
  47.  
  48. static PyObject *BsddbError;
  49.  
  50. static PyObject *
  51. newdbhashobject(char *file, int flags, int mode,
  52.         int bsize, int ffactor, int nelem, int cachesize, int hash, int lorder)
  53. {
  54.     bsddbobject *dp;
  55.     HASHINFO info;
  56.  
  57.     if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
  58.         return NULL;
  59.  
  60.     info.bsize = bsize;
  61.     info.ffactor = ffactor;
  62.     info.nelem = nelem;
  63.     info.cachesize = cachesize;
  64.     info.hash = NULL; /* XXX should derive from hash argument */
  65.     info.lorder = lorder;
  66.  
  67. #ifdef O_BINARY
  68.     flags |= O_BINARY;
  69. #endif
  70.     Py_BEGIN_ALLOW_THREADS
  71.     dp->di_bsddb = dbopen(file, flags, mode, DB_HASH, &info);
  72.     Py_END_ALLOW_THREADS
  73.     if (dp->di_bsddb == NULL) {
  74.         PyErr_SetFromErrno(BsddbError);
  75. #ifdef WITH_THREAD
  76.         dp->di_lock = NULL;
  77. #endif
  78.         Py_DECREF(dp);
  79.         return NULL;
  80.     }
  81.  
  82.     dp->di_size = -1;
  83. #ifdef WITH_THREAD
  84.     dp->di_lock = PyThread_allocate_lock();
  85.     if (dp->di_lock == NULL) {
  86.         PyErr_SetString(BsddbError, "can't allocate lock");
  87.         Py_DECREF(dp);
  88.         return NULL;
  89.     }
  90. #endif
  91.  
  92.     return (PyObject *)dp;
  93. }
  94.  
  95. static PyObject *
  96. newdbbtobject(char *file, int flags, int mode,
  97.           int btflags, int cachesize, int maxkeypage, int minkeypage, int psize, int lorder)
  98. {
  99.     bsddbobject *dp;
  100.     BTREEINFO info;
  101.  
  102.     if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
  103.         return NULL;
  104.  
  105.     info.flags = btflags;
  106.     info.cachesize = cachesize;
  107.     info.maxkeypage = maxkeypage;
  108.     info.minkeypage = minkeypage;
  109.     info.psize = psize;
  110.     info.lorder = lorder;
  111.     info.compare = 0; /* Use default comparison functions, for now..*/
  112.     info.prefix = 0;
  113.  
  114. #ifdef O_BINARY
  115.     flags |= O_BINARY;
  116. #endif
  117.     Py_BEGIN_ALLOW_THREADS
  118.     dp->di_bsddb = dbopen(file, flags, mode, DB_BTREE, &info);
  119.     Py_END_ALLOW_THREADS
  120.     if (dp->di_bsddb == NULL) {
  121.         PyErr_SetFromErrno(BsddbError);
  122. #ifdef WITH_THREAD
  123.         dp->di_lock = NULL;
  124. #endif
  125.         Py_DECREF(dp);
  126.         return NULL;
  127.     }
  128.  
  129.     dp->di_size = -1;
  130. #ifdef WITH_THREAD
  131.     dp->di_lock = PyThread_allocate_lock();
  132.     if (dp->di_lock == NULL) {
  133.         PyErr_SetString(BsddbError, "can't allocate lock");
  134.         Py_DECREF(dp);
  135.         return NULL;
  136.     }
  137. #endif
  138.  
  139.     return (PyObject *)dp;
  140. }
  141.  
  142. static PyObject *
  143. newdbrnobject(char *file, int flags, int mode,
  144.           int rnflags, int cachesize, int psize, int lorder, size_t reclen, u_char bval, char *bfname)
  145. {
  146.     bsddbobject *dp;
  147.     RECNOINFO info;
  148.  
  149.     if ((dp = PyObject_New(bsddbobject, &Bsddbtype)) == NULL)
  150.         return NULL;
  151.  
  152.     info.flags = rnflags;
  153.     info.cachesize = cachesize;
  154.     info.psize = psize;
  155.     info.lorder = lorder;
  156.     info.reclen = reclen;
  157.     info.bval = bval;
  158.     info.bfname = bfname;
  159.  
  160. #ifdef O_BINARY
  161.     flags |= O_BINARY;
  162. #endif
  163.     Py_BEGIN_ALLOW_THREADS
  164.     dp->di_bsddb = dbopen(file, flags, mode, DB_RECNO, &info);
  165.     Py_END_ALLOW_THREADS
  166.     if (dp->di_bsddb == NULL) {
  167.         PyErr_SetFromErrno(BsddbError);
  168. #ifdef WITH_THREAD
  169.         dp->di_lock = NULL;
  170. #endif
  171.         Py_DECREF(dp);
  172.         return NULL;
  173.     }
  174.  
  175.     dp->di_size = -1;
  176. #ifdef WITH_THREAD
  177.     dp->di_lock = PyThread_allocate_lock();
  178.     if (dp->di_lock == NULL) {
  179.         PyErr_SetString(BsddbError, "can't allocate lock");
  180.         Py_DECREF(dp);
  181.         return NULL;
  182.     }
  183. #endif
  184.  
  185.     return (PyObject *)dp;
  186. }
  187.  
  188. static void
  189. bsddb_dealloc(bsddbobject *dp)
  190. {
  191. #ifdef WITH_THREAD
  192.     if (dp->di_lock) {
  193.         PyThread_acquire_lock(dp->di_lock, 0);
  194.         PyThread_release_lock(dp->di_lock);
  195.         PyThread_free_lock(dp->di_lock);
  196.         dp->di_lock = NULL;
  197.     }
  198. #endif
  199.     if (dp->di_bsddb != NULL) {
  200.         int status;
  201.         Py_BEGIN_ALLOW_THREADS
  202.         status = (dp->di_bsddb->close)(dp->di_bsddb);
  203.         Py_END_ALLOW_THREADS
  204.         if (status != 0)
  205.             fprintf(stderr,
  206.                 "Python bsddb: close errno %d in dealloc\n",
  207.                 errno);
  208.     }
  209.     PyObject_Del(dp);
  210. }
  211.  
  212. #ifdef WITH_THREAD
  213. #define BSDDB_BGN_SAVE(_dp) Py_BEGIN_ALLOW_THREADS PyThread_acquire_lock(_dp->di_lock,1);
  214. #define BSDDB_END_SAVE(_dp) PyThread_release_lock(_dp->di_lock); Py_END_ALLOW_THREADS
  215. #else
  216. #define BSDDB_BGN_SAVE(_dp) Py_BEGIN_ALLOW_THREADS 
  217. #define BSDDB_END_SAVE(_dp) Py_END_ALLOW_THREADS
  218. #endif
  219.  
  220. static int
  221. bsddb_length(bsddbobject *dp)
  222. {
  223.         if (dp->di_bsddb == NULL) {
  224.                  PyErr_SetString(BsddbError, "BSDDB object has already been closed"); 
  225.                  return -1; 
  226.         }
  227.     if (dp->di_size < 0) {
  228.         DBT krec, drec;
  229.         int status;
  230.         int size = 0;
  231.         BSDDB_BGN_SAVE(dp)
  232.         for (status = (dp->di_bsddb->seq)(dp->di_bsddb,
  233.                           &krec, &drec,R_FIRST);
  234.              status == 0;
  235.              status = (dp->di_bsddb->seq)(dp->di_bsddb,
  236.                           &krec, &drec, R_NEXT))
  237.             size++;
  238.         BSDDB_END_SAVE(dp)
  239.         if (status < 0) {
  240.             PyErr_SetFromErrno(BsddbError);
  241.             return -1;
  242.         }
  243.         dp->di_size = size;
  244.     }
  245.     return dp->di_size;
  246. }
  247.  
  248. static PyObject *
  249. bsddb_subscript(bsddbobject *dp, PyObject *key)
  250. {
  251.     int status;
  252.     DBT krec, drec;
  253.     char *data,buf[4096];
  254.     int size;
  255.     PyObject *result;
  256.  
  257.     if (!PyArg_Parse(key, "s#", &data, &size))
  258.         return NULL;
  259.         check_bsddbobject_open(dp);
  260.     
  261.     krec.data = data;
  262.     krec.size = size;
  263.  
  264.     BSDDB_BGN_SAVE(dp)
  265.     status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
  266.     if (status == 0) {
  267.         if (drec.size > sizeof(buf)) data = malloc(drec.size);
  268.         else data = buf;
  269.         memcpy(data,drec.data,drec.size);
  270.     }
  271.     BSDDB_END_SAVE(dp)
  272.     if (status != 0) {
  273.         if (status < 0)
  274.             PyErr_SetFromErrno(BsddbError);
  275.         else
  276.             PyErr_SetObject(PyExc_KeyError, key);
  277.         return NULL;
  278.     }
  279.  
  280.     result = PyString_FromStringAndSize(data, (int)drec.size);
  281.     if (data != buf) free(data);
  282.     return result;
  283. }
  284.  
  285. static int
  286. bsddb_ass_sub(bsddbobject *dp, PyObject *key, PyObject *value)
  287. {
  288.     int status;
  289.     DBT krec, drec;
  290.     char *data;
  291.     int size;
  292.  
  293.     if (!PyArg_Parse(key, "s#", &data, &size)) {
  294.         PyErr_SetString(PyExc_TypeError,
  295.                 "bsddb key type must be string");
  296.         return -1;
  297.     }
  298.         if (dp->di_bsddb == NULL) {
  299.                  PyErr_SetString(BsddbError, "BSDDB object has already been closed"); 
  300.                  return -1; 
  301.         }
  302.     krec.data = data;
  303.     krec.size = size;
  304.     dp->di_size = -1;
  305.     if (value == NULL) {
  306.         BSDDB_BGN_SAVE(dp)
  307.         status = (dp->di_bsddb->del)(dp->di_bsddb, &krec, 0);
  308.         BSDDB_END_SAVE(dp)
  309.     }
  310.     else {
  311.         if (!PyArg_Parse(value, "s#", &data, &size)) {
  312.             PyErr_SetString(PyExc_TypeError,
  313.                     "bsddb value type must be string");
  314.             return -1;
  315.         }
  316.         drec.data = data;
  317.         drec.size = size;
  318. #if 0
  319.         /* For RECNO, put fails with 'No space left on device'
  320.            after a few short records are added??  Looks fine
  321.            to this point... linked with 1.85 on Solaris Intel
  322.            Roger E. Masse 1/16/97
  323.          */
  324.         printf("before put data: '%s', size: %d\n",
  325.                drec.data, drec.size);
  326.         printf("before put key= '%s', size= %d\n",
  327.                krec.data, krec.size);
  328. #endif
  329.         BSDDB_BGN_SAVE(dp)
  330.         status = (dp->di_bsddb->put)(dp->di_bsddb, &krec, &drec, 0);
  331.         BSDDB_END_SAVE(dp)
  332.     }
  333.     if (status != 0) {
  334.         if (status < 0)
  335.             PyErr_SetFromErrno(BsddbError);
  336.         else
  337.             PyErr_SetObject(PyExc_KeyError, key);
  338.         return -1;
  339.     }
  340.     return 0;
  341. }
  342.  
  343. static PyMappingMethods bsddb_as_mapping = {
  344.     (inquiry)bsddb_length,        /*mp_length*/
  345.     (binaryfunc)bsddb_subscript,    /*mp_subscript*/
  346.     (objobjargproc)bsddb_ass_sub,    /*mp_ass_subscript*/
  347. };
  348.  
  349. static PyObject *
  350. bsddb_close(bsddbobject *dp, PyObject *args)
  351. {
  352.     if (!PyArg_NoArgs(args))
  353.         return NULL;
  354.     if (dp->di_bsddb != NULL) {
  355.         int status;
  356.         BSDDB_BGN_SAVE(dp)
  357.         status = (dp->di_bsddb->close)(dp->di_bsddb);
  358.         BSDDB_END_SAVE(dp)
  359.         if (status != 0) {
  360.             dp->di_bsddb = NULL;
  361.             PyErr_SetFromErrno(BsddbError);
  362.             return NULL;
  363.         }
  364.     }
  365.     dp->di_bsddb = NULL;
  366.     Py_INCREF(Py_None);
  367.     return Py_None;
  368. }
  369.  
  370. static PyObject *
  371. bsddb_keys(bsddbobject *dp, PyObject *args)
  372. {
  373.     PyObject *list, *item;
  374.     DBT krec, drec;
  375.     char *data=NULL,buf[4096];
  376.     int status;
  377.     int err;
  378.  
  379.     if (!PyArg_NoArgs(args))
  380.         return NULL;
  381.     check_bsddbobject_open(dp);
  382.     list = PyList_New(0);
  383.     if (list == NULL)
  384.         return NULL;
  385.     BSDDB_BGN_SAVE(dp)
  386.     status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_FIRST);
  387.     if (status == 0) {
  388.         if (krec.size > sizeof(buf)) data = malloc(krec.size);
  389.         else data = buf;
  390.         memcpy(data,krec.data,krec.size);
  391.     }
  392.     BSDDB_END_SAVE(dp)
  393.     while (status == 0) {
  394.         item = PyString_FromStringAndSize(data, (int)krec.size);
  395.         if (data != buf) free(data);
  396.         if (item == NULL) {
  397.             Py_DECREF(list);
  398.             return NULL;
  399.         }
  400.         err = PyList_Append(list, item);
  401.         Py_DECREF(item);
  402.         if (err != 0) {
  403.             Py_DECREF(list);
  404.             return NULL;
  405.         }
  406.         BSDDB_BGN_SAVE(dp)
  407.         status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_NEXT);
  408.         if (status == 0) {
  409.             if (krec.size > sizeof(buf)) data = malloc(krec.size);
  410.             else data = buf;
  411.             memcpy(data,krec.data,krec.size);
  412.         }
  413.         BSDDB_END_SAVE(dp)
  414.     }
  415.     if (status < 0) {
  416.         PyErr_SetFromErrno(BsddbError);
  417.         Py_DECREF(list);
  418.         return NULL;
  419.     }
  420.     if (dp->di_size < 0)
  421.         dp->di_size = PyList_Size(list); /* We just did the work */
  422.     return list;
  423. }
  424.  
  425. static PyObject *
  426. bsddb_has_key(bsddbobject *dp, PyObject *args)
  427. {
  428.     DBT krec, drec;
  429.     int status;
  430.     char *data;
  431.     int size;
  432.  
  433.     if (!PyArg_Parse(args, "s#", &data, &size))
  434.         return NULL;
  435.     check_bsddbobject_open(dp);
  436.     krec.data = data;
  437.     krec.size = size;
  438.  
  439.     BSDDB_BGN_SAVE(dp)
  440.     status = (dp->di_bsddb->get)(dp->di_bsddb, &krec, &drec, 0);
  441.     BSDDB_END_SAVE(dp)
  442.     if (status < 0) {
  443.         PyErr_SetFromErrno(BsddbError);
  444.         return NULL;
  445.     }
  446.  
  447.     return PyInt_FromLong(status == 0);
  448. }
  449.  
  450. static PyObject *
  451. bsddb_set_location(bsddbobject *dp, PyObject *key)
  452. {
  453.     int status;
  454.     DBT krec, drec;
  455.     char *data,buf[4096];
  456.     int size;
  457.     PyObject *result;
  458.  
  459.     if (!PyArg_Parse(key, "s#", &data, &size))
  460.         return NULL;
  461.     check_bsddbobject_open(dp);
  462.     krec.data = data;
  463.     krec.size = size;
  464.  
  465.     BSDDB_BGN_SAVE(dp)
  466.     status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec, &drec, R_CURSOR);
  467.     if (status == 0) {
  468.         if (drec.size > sizeof(buf)) data = malloc(drec.size);
  469.         else data = buf;
  470.         memcpy(data,drec.data,drec.size);
  471.     }
  472.     BSDDB_END_SAVE(dp)
  473.     if (status != 0) {
  474.         if (status < 0)
  475.             PyErr_SetFromErrno(BsddbError);
  476.         else
  477.             PyErr_SetObject(PyExc_KeyError, key);
  478.         return NULL;
  479.     }
  480.  
  481.     result = Py_BuildValue("s#s#", krec.data, krec.size, data, drec.size);
  482.     if (data != buf) free(data);
  483.     return result;
  484. }
  485.  
  486. static PyObject *
  487. bsddb_seq(bsddbobject *dp, PyObject *args, int sequence_request)
  488. {
  489.     int status;
  490.     DBT krec, drec;
  491.     char *kdata=NULL,kbuf[4096];
  492.     char *ddata=NULL,dbuf[4096];
  493.     PyObject *result;
  494.  
  495.     if (!PyArg_NoArgs(args))
  496.         return NULL;
  497.  
  498.     check_bsddbobject_open(dp);
  499.     krec.data = 0;
  500.     krec.size = 0;
  501.  
  502.     BSDDB_BGN_SAVE(dp)
  503.     status = (dp->di_bsddb->seq)(dp->di_bsddb, &krec,
  504.                      &drec, sequence_request);
  505.     if (status == 0) {
  506.         if (krec.size > sizeof(kbuf)) kdata = malloc(krec.size);
  507.         else kdata = kbuf;
  508.         memcpy(kdata,krec.data,krec.size);
  509.         if (drec.size > sizeof(dbuf)) ddata = malloc(drec.size);
  510.         else ddata = dbuf;
  511.         memcpy(ddata,drec.data,drec.size);
  512.     }
  513.     BSDDB_END_SAVE(dp)
  514.     if (status != 0) {
  515.         if (status < 0)
  516.             PyErr_SetFromErrno(BsddbError);
  517.         else
  518.             PyErr_SetObject(PyExc_KeyError, args);
  519.         return NULL;
  520.     }
  521.  
  522.     result = Py_BuildValue("s#s#", kdata, krec.size, ddata, drec.size);
  523.     if (kdata != kbuf) free(kdata);
  524.     if (ddata != dbuf) free(ddata);
  525.     return result;
  526. }
  527.  
  528. static PyObject *
  529. bsddb_next(bsddbobject *dp, PyObject *key)
  530. {
  531.     return bsddb_seq(dp, key, R_NEXT);
  532. }
  533. static PyObject *
  534. bsddb_previous(bsddbobject *dp, PyObject *key)
  535. {
  536.     return bsddb_seq(dp, key, R_PREV);
  537. }
  538. static PyObject *
  539. bsddb_first(bsddbobject *dp, PyObject *key)
  540. {
  541.     return bsddb_seq(dp, key, R_FIRST);
  542. }
  543. static PyObject *
  544. bsddb_last(bsddbobject *dp, PyObject *key)
  545. {
  546.     return bsddb_seq(dp, key, R_LAST);
  547. }
  548. static PyObject *
  549. bsddb_sync(bsddbobject *dp, PyObject *args)
  550. {
  551.     int status;
  552.  
  553.     if (!PyArg_NoArgs(args))
  554.         return NULL;
  555.     check_bsddbobject_open(dp);
  556.     BSDDB_BGN_SAVE(dp)
  557.     status = (dp->di_bsddb->sync)(dp->di_bsddb, 0);
  558.     BSDDB_END_SAVE(dp)
  559.     if (status != 0) {
  560.         PyErr_SetFromErrno(BsddbError);
  561.         return NULL;
  562.     }
  563.     return PyInt_FromLong(status = 0);
  564. }
  565. static PyMethodDef bsddb_methods[] = {
  566.     {"close",        (PyCFunction)bsddb_close},
  567.     {"keys",        (PyCFunction)bsddb_keys},
  568.     {"has_key",        (PyCFunction)bsddb_has_key},
  569.     {"set_location",    (PyCFunction)bsddb_set_location},
  570.     {"next",        (PyCFunction)bsddb_next},
  571.     {"previous",    (PyCFunction)bsddb_previous},
  572.     {"first",        (PyCFunction)bsddb_first},
  573.     {"last",        (PyCFunction)bsddb_last},
  574.     {"sync",        (PyCFunction)bsddb_sync},
  575.     {NULL,               NULL}        /* sentinel */
  576. };
  577.  
  578. static PyObject *
  579. bsddb_getattr(PyObject *dp, char *name)
  580. {
  581.     return Py_FindMethod(bsddb_methods, dp, name);
  582. }
  583.  
  584. static PyTypeObject Bsddbtype = {
  585.     PyObject_HEAD_INIT(NULL)
  586.     0,
  587.     "bsddb",
  588.     sizeof(bsddbobject),
  589.     0,
  590.     (destructor)bsddb_dealloc, /*tp_dealloc*/
  591.     0,            /*tp_print*/
  592.     (getattrfunc)bsddb_getattr, /*tp_getattr*/
  593.     0,            /*tp_setattr*/
  594.     0,            /*tp_compare*/
  595.     0,            /*tp_repr*/
  596.     0,            /*tp_as_number*/
  597.     0,            /*tp_as_sequence*/
  598.     &bsddb_as_mapping,    /*tp_as_mapping*/
  599. };
  600.  
  601. static PyObject *
  602. bsdhashopen(PyObject *self, PyObject *args)
  603. {
  604.     char *file;
  605.     char *flag = NULL;
  606.     int flags = O_RDONLY;
  607.     int mode = 0666;
  608.     int bsize = 0;
  609.     int ffactor = 0;
  610.     int nelem = 0;
  611.     int cachesize = 0;
  612.     int hash = 0; /* XXX currently ignored */
  613.     int lorder = 0;
  614.  
  615.     if (!PyArg_ParseTuple(args, "s|siiiiiii:hashopen",
  616.                   &file, &flag, &mode,
  617.                   &bsize, &ffactor, &nelem, &cachesize,
  618.                   &hash, &lorder))
  619.         return NULL;
  620.     if (flag != NULL) {
  621.         /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
  622.         if (flag[0] == 'r')
  623.             flags = O_RDONLY;
  624.         else if (flag[0] == 'w')
  625.             flags = O_RDWR;
  626.         else if (flag[0] == 'c')
  627.             flags = O_RDWR|O_CREAT;
  628.         else if (flag[0] == 'n')
  629.             flags = O_RDWR|O_CREAT|O_TRUNC;
  630.         else {
  631.             PyErr_SetString(BsddbError,
  632.                 "Flag should begin with 'r', 'w', 'c' or 'n'");
  633.             return NULL;
  634.         }
  635.         if (flag[1] == 'l') {
  636. #if defined(O_EXLOCK) && defined(O_SHLOCK)
  637.             if (flag[0] == 'r')
  638.                 flags |= O_SHLOCK;
  639.             else
  640.                 flags |= O_EXLOCK;
  641. #else
  642.             PyErr_SetString(BsddbError,
  643.                      "locking not supported on this platform");
  644.             return NULL;
  645. #endif
  646.         }
  647.     }
  648.     return newdbhashobject(file, flags, mode,
  649.                    bsize, ffactor, nelem, cachesize, hash, lorder);
  650. }
  651.  
  652. static PyObject *
  653. bsdbtopen(PyObject *self, PyObject *args)
  654. {
  655.     char *file;
  656.     char *flag = NULL;
  657.     int flags = O_RDONLY;
  658.     int mode = 0666;
  659.     int cachesize = 0;
  660.     int maxkeypage = 0;
  661.     int minkeypage = 0;
  662.     int btflags = 0;
  663.     unsigned int psize = 0;
  664.     int lorder = 0;
  665.  
  666.     if (!PyArg_ParseTuple(args, "s|siiiiiii:btopen",
  667.                   &file, &flag, &mode,
  668.                   &btflags, &cachesize, &maxkeypage, &minkeypage,
  669.                   &psize, &lorder))
  670.         return NULL;
  671.     if (flag != NULL) {
  672.         /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
  673.         if (flag[0] == 'r')
  674.             flags = O_RDONLY;
  675.         else if (flag[0] == 'w')
  676.             flags = O_RDWR;
  677.         else if (flag[0] == 'c')
  678.             flags = O_RDWR|O_CREAT;
  679.         else if (flag[0] == 'n')
  680.             flags = O_RDWR|O_CREAT|O_TRUNC;
  681.         else {
  682.             PyErr_SetString(BsddbError,
  683.                    "Flag should begin with 'r', 'w', 'c' or 'n'");
  684.             return NULL;
  685.         }
  686.         if (flag[1] == 'l') {
  687. #if defined(O_EXLOCK) && defined(O_SHLOCK)
  688.             if (flag[0] == 'r')
  689.                 flags |= O_SHLOCK;
  690.             else
  691.                 flags |= O_EXLOCK;
  692. #else
  693.             PyErr_SetString(BsddbError,
  694.                     "locking not supported on this platform");
  695.             return NULL;
  696. #endif
  697.         }
  698.     }
  699.     return newdbbtobject(file, flags, mode,
  700.                  btflags, cachesize, maxkeypage, minkeypage,
  701.                  psize, lorder);
  702. }
  703.  
  704. static PyObject *
  705. bsdrnopen(PyObject *self, PyObject *args)
  706. {
  707.     char *file;
  708.     char *flag = NULL;
  709.     int flags = O_RDONLY;
  710.     int mode = 0666;
  711.     int cachesize = 0;
  712.     int rnflags = 0;
  713.     unsigned int psize = 0;
  714.     int lorder = 0;
  715.     size_t reclen = 0;
  716.     char  *bval = "";
  717.     char *bfname = NULL;
  718.  
  719.     if (!PyArg_ParseTuple(args, "s|siiiiiiss:rnopen",
  720.                   &file, &flag, &mode,
  721.                   &rnflags, &cachesize, &psize, &lorder,
  722.                   &reclen, &bval, &bfname))
  723.         return NULL;
  724.  
  725. # if 0
  726.     printf("file: %s\n", file);
  727.     printf("flag: %s\n", flag);
  728.     printf("mode: %d\n", mode);
  729.     printf("rnflags: 0x%x\n", rnflags);
  730.     printf("cachesize: %d\n", cachesize);
  731.     printf("psize: %d\n", psize);
  732.     printf("lorder: %d\n", 0);
  733.     printf("reclen: %d\n", reclen);
  734.     printf("bval: %c\n", bval[0]);
  735.     printf("bfname %s\n", bfname);
  736. #endif
  737.     
  738.     if (flag != NULL) {
  739.         /* XXX need to pass O_EXCL, O_EXLOCK, O_NONBLOCK, O_SHLOCK */
  740.         if (flag[0] == 'r')
  741.             flags = O_RDONLY;
  742.         else if (flag[0] == 'w')
  743.             flags = O_RDWR;
  744.         else if (flag[0] == 'c')
  745.             flags = O_RDWR|O_CREAT;
  746.         else if (flag[0] == 'n')
  747.             flags = O_RDWR|O_CREAT|O_TRUNC;
  748.         else {
  749.             PyErr_SetString(BsddbError,
  750.                    "Flag should begin with 'r', 'w', 'c' or 'n'");
  751.             return NULL;
  752.         }
  753.         if (flag[1] == 'l') {
  754. #if defined(O_EXLOCK) && defined(O_SHLOCK)
  755.             if (flag[0] == 'r')
  756.                 flags |= O_SHLOCK;
  757.             else
  758.                 flags |= O_EXLOCK;
  759. #else
  760.             PyErr_SetString(BsddbError,
  761.                     "locking not supported on this platform");
  762.             return NULL;
  763. #endif
  764.         }
  765.         else if (flag[1] != '\0') {
  766.             PyErr_SetString(BsddbError,
  767.                        "Flag char 2 should be 'l' or absent");
  768.             return NULL;
  769.         }
  770.     }
  771.     return newdbrnobject(file, flags, mode, rnflags, cachesize,
  772.                  psize, lorder, reclen, bval[0], bfname);
  773. }
  774.  
  775. static PyMethodDef bsddbmodule_methods[] = {
  776.     {"hashopen",    (PyCFunction)bsdhashopen, 1},
  777.     {"btopen",    (PyCFunction)bsdbtopen, 1},
  778.     {"rnopen",    (PyCFunction)bsdrnopen, 1},
  779.     {0,        0},
  780. };
  781.  
  782. DL_EXPORT(void)
  783. initbsddb(void) {
  784.     PyObject *m, *d;
  785.  
  786.     Bsddbtype.ob_type = &PyType_Type;
  787.     m = Py_InitModule("bsddb", bsddbmodule_methods);
  788.     d = PyModule_GetDict(m);
  789.     BsddbError = PyErr_NewException("bsddb.error", NULL, NULL);
  790.     if (BsddbError != NULL)
  791.         PyDict_SetItemString(d, "error", BsddbError);
  792. }
  793.