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