|
1 /*---------------------------------------------------------------------- |
|
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA |
|
3 and Andrew Kuchling. All rights reserved. |
|
4 |
|
5 Redistribution and use in source and binary forms, with or without |
|
6 modification, are permitted provided that the following conditions are |
|
7 met: |
|
8 |
|
9 o Redistributions of source code must retain the above copyright |
|
10 notice, this list of conditions, and the disclaimer that follows. |
|
11 |
|
12 o Redistributions in binary form must reproduce the above copyright |
|
13 notice, this list of conditions, and the following disclaimer in |
|
14 the documentation and/or other materials provided with the |
|
15 distribution. |
|
16 |
|
17 o Neither the name of Digital Creations nor the names of its |
|
18 contributors may be used to endorse or promote products derived |
|
19 from this software without specific prior written permission. |
|
20 |
|
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS |
|
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
|
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
|
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL |
|
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
|
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
|
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
|
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
|
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
|
32 DAMAGE. |
|
33 ------------------------------------------------------------------------*/ |
|
34 |
|
35 |
|
36 /* |
|
37 * Handwritten code to wrap version 3.x of the Berkeley DB library, |
|
38 * written to replace a SWIG-generated file. It has since been updated |
|
39 * to compile with Berkeley DB versions 3.2 through 4.2. |
|
40 * |
|
41 * This module was started by Andrew Kuchling to remove the dependency |
|
42 * on SWIG in a package by Gregory P. Smith who based his work on a |
|
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped |
|
44 * Berkeley DB 2.7.x. |
|
45 * |
|
46 * Development of this module then returned full circle back to Robin Dunn |
|
47 * who worked on behalf of Digital Creations to complete the wrapping of |
|
48 * the DB 3.x API and to build a solid unit test suite. Robin has |
|
49 * since gone onto other projects (wxPython). |
|
50 * |
|
51 * Gregory P. Smith <greg@krypto.org> was once again the maintainer. |
|
52 * |
|
53 * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>. |
|
54 * Jesus Cea licenses this code to PSF under a Contributor Agreement. |
|
55 * |
|
56 * Use the pybsddb-users@lists.sf.net mailing list for all questions. |
|
57 * Things can change faster than the header of this file is updated. This |
|
58 * file is shared with the PyBSDDB project at SourceForge: |
|
59 * |
|
60 * http://pybsddb.sf.net |
|
61 * |
|
62 * This file should remain backward compatible with Python 2.1, but see PEP |
|
63 * 291 for the most current backward compatibility requirements: |
|
64 * |
|
65 * http://www.python.org/peps/pep-0291.html |
|
66 * |
|
67 * This module contains 6 types: |
|
68 * |
|
69 * DB (Database) |
|
70 * DBCursor (Database Cursor) |
|
71 * DBEnv (database environment) |
|
72 * DBTxn (An explicit database transaction) |
|
73 * DBLock (A lock handle) |
|
74 * DBSequence (Sequence) |
|
75 * |
|
76 */ |
|
77 |
|
78 /* --------------------------------------------------------------------- */ |
|
79 |
|
80 /* |
|
81 * Portions of this module, associated unit tests and build scripts are the |
|
82 * result of a contract with The Written Word (http://thewrittenword.com/) |
|
83 * Many thanks go out to them for causing me to raise the bar on quality and |
|
84 * functionality, resulting in a better bsddb3 package for all of us to use. |
|
85 * |
|
86 * --Robin |
|
87 */ |
|
88 |
|
89 /* --------------------------------------------------------------------- */ |
|
90 |
|
91 #include <stddef.h> /* for offsetof() */ |
|
92 #include <Python.h> |
|
93 |
|
94 #define COMPILING_BSDDB_C |
|
95 #include "bsddb.h" |
|
96 #undef COMPILING_BSDDB_C |
|
97 |
|
98 static char *rcs_id = "$Id: _bsddb.c 66568 2008-09-23 18:54:08Z jesus.cea $"; |
|
99 |
|
100 /* --------------------------------------------------------------------- */ |
|
101 /* Various macro definitions */ |
|
102 |
|
103 #if (PY_VERSION_HEX < 0x02050000) |
|
104 typedef int Py_ssize_t; |
|
105 #endif |
|
106 |
|
107 #if (PY_VERSION_HEX < 0x02060000) /* really: before python trunk r63675 */ |
|
108 /* This code now uses PyBytes* API function names instead of PyString*. |
|
109 * These #defines map to their equivalent on earlier python versions. */ |
|
110 #define PyBytes_FromStringAndSize PyString_FromStringAndSize |
|
111 #define PyBytes_FromString PyString_FromString |
|
112 #define PyBytes_AsStringAndSize PyString_AsStringAndSize |
|
113 #define PyBytes_Check PyString_Check |
|
114 #define PyBytes_GET_SIZE PyString_GET_SIZE |
|
115 #define PyBytes_AS_STRING PyString_AS_STRING |
|
116 #endif |
|
117 |
|
118 #if (PY_VERSION_HEX >= 0x03000000) |
|
119 #define NUMBER_Check PyLong_Check |
|
120 #define NUMBER_AsLong PyLong_AsLong |
|
121 #define NUMBER_FromLong PyLong_FromLong |
|
122 #else |
|
123 #define NUMBER_Check PyInt_Check |
|
124 #define NUMBER_AsLong PyInt_AsLong |
|
125 #define NUMBER_FromLong PyInt_FromLong |
|
126 #endif |
|
127 |
|
128 #ifdef WITH_THREAD |
|
129 |
|
130 /* These are for when calling Python --> C */ |
|
131 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS; |
|
132 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS; |
|
133 |
|
134 /* For 2.3, use the PyGILState_ calls */ |
|
135 #if (PY_VERSION_HEX >= 0x02030000) |
|
136 #define MYDB_USE_GILSTATE |
|
137 #endif |
|
138 |
|
139 /* and these are for calling C --> Python */ |
|
140 #if defined(MYDB_USE_GILSTATE) |
|
141 #define MYDB_BEGIN_BLOCK_THREADS \ |
|
142 PyGILState_STATE __savestate = PyGILState_Ensure(); |
|
143 #define MYDB_END_BLOCK_THREADS \ |
|
144 PyGILState_Release(__savestate); |
|
145 #else /* MYDB_USE_GILSTATE */ |
|
146 /* Pre GILState API - do it the long old way */ |
|
147 static PyInterpreterState* _db_interpreterState = NULL; |
|
148 #define MYDB_BEGIN_BLOCK_THREADS { \ |
|
149 PyThreadState* prevState; \ |
|
150 PyThreadState* newState; \ |
|
151 PyEval_AcquireLock(); \ |
|
152 newState = PyThreadState_New(_db_interpreterState); \ |
|
153 prevState = PyThreadState_Swap(newState); |
|
154 |
|
155 #define MYDB_END_BLOCK_THREADS \ |
|
156 newState = PyThreadState_Swap(prevState); \ |
|
157 PyThreadState_Clear(newState); \ |
|
158 PyEval_ReleaseLock(); \ |
|
159 PyThreadState_Delete(newState); \ |
|
160 } |
|
161 #endif /* MYDB_USE_GILSTATE */ |
|
162 |
|
163 #else |
|
164 /* Compiled without threads - avoid all this cruft */ |
|
165 #define MYDB_BEGIN_ALLOW_THREADS |
|
166 #define MYDB_END_ALLOW_THREADS |
|
167 #define MYDB_BEGIN_BLOCK_THREADS |
|
168 #define MYDB_END_BLOCK_THREADS |
|
169 |
|
170 #endif |
|
171 |
|
172 /* Should DB_INCOMPLETE be turned into a warning or an exception? */ |
|
173 #define INCOMPLETE_IS_WARNING 1 |
|
174 |
|
175 /* --------------------------------------------------------------------- */ |
|
176 /* Exceptions */ |
|
177 |
|
178 static PyObject* DBError; /* Base class, all others derive from this */ |
|
179 static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */ |
|
180 static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */ |
|
181 static PyObject* DBKeyExistError; /* DB_KEYEXIST */ |
|
182 static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */ |
|
183 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */ |
|
184 static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */ |
|
185 static PyObject* DBOldVersionError; /* DB_OLD_VERSION */ |
|
186 static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */ |
|
187 static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */ |
|
188 static PyObject* DBNoServerError; /* DB_NOSERVER */ |
|
189 static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */ |
|
190 static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */ |
|
191 static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */ |
|
192 static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */ |
|
193 |
|
194 #if !INCOMPLETE_IS_WARNING |
|
195 static PyObject* DBIncompleteError; /* DB_INCOMPLETE */ |
|
196 #endif |
|
197 |
|
198 static PyObject* DBInvalidArgError; /* EINVAL */ |
|
199 static PyObject* DBAccessError; /* EACCES */ |
|
200 static PyObject* DBNoSpaceError; /* ENOSPC */ |
|
201 static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */ |
|
202 static PyObject* DBAgainError; /* EAGAIN */ |
|
203 static PyObject* DBBusyError; /* EBUSY */ |
|
204 static PyObject* DBFileExistsError; /* EEXIST */ |
|
205 static PyObject* DBNoSuchFileError; /* ENOENT */ |
|
206 static PyObject* DBPermissionsError; /* EPERM */ |
|
207 |
|
208 #if (DBVER >= 42) |
|
209 static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */ |
|
210 #endif |
|
211 |
|
212 static PyObject* DBRepUnavailError; /* DB_REP_UNAVAIL */ |
|
213 |
|
214 #if (DBVER < 43) |
|
215 #define DB_BUFFER_SMALL ENOMEM |
|
216 #endif |
|
217 |
|
218 |
|
219 /* --------------------------------------------------------------------- */ |
|
220 /* Structure definitions */ |
|
221 |
|
222 #if PYTHON_API_VERSION < 1010 |
|
223 #error "Python 2.1 or later required" |
|
224 #endif |
|
225 |
|
226 |
|
227 /* Defaults for moduleFlags in DBEnvObject and DBObject. */ |
|
228 #define DEFAULT_GET_RETURNS_NONE 1 |
|
229 #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */ |
|
230 |
|
231 |
|
232 /* See comment in Python 2.6 "object.h" */ |
|
233 #ifndef staticforward |
|
234 #define staticforward static |
|
235 #endif |
|
236 #ifndef statichere |
|
237 #define statichere static |
|
238 #endif |
|
239 |
|
240 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, |
|
241 DBLock_Type; |
|
242 #if (DBVER >= 43) |
|
243 staticforward PyTypeObject DBSequence_Type; |
|
244 #endif |
|
245 |
|
246 #ifndef Py_TYPE |
|
247 /* for compatibility with Python 2.5 and earlier */ |
|
248 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) |
|
249 #endif |
|
250 |
|
251 #define DBObject_Check(v) (Py_TYPE(v) == &DB_Type) |
|
252 #define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type) |
|
253 #define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type) |
|
254 #define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type) |
|
255 #define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type) |
|
256 #if (DBVER >= 43) |
|
257 #define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type) |
|
258 #endif |
|
259 |
|
260 #if (DBVER < 46) |
|
261 #define _DBC_close(dbc) dbc->c_close(dbc) |
|
262 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b) |
|
263 #define _DBC_del(dbc,a) dbc->c_del(dbc,a) |
|
264 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b) |
|
265 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c) |
|
266 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d) |
|
267 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c) |
|
268 #else |
|
269 #define _DBC_close(dbc) dbc->close(dbc) |
|
270 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b) |
|
271 #define _DBC_del(dbc,a) dbc->del(dbc,a) |
|
272 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b) |
|
273 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c) |
|
274 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d) |
|
275 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c) |
|
276 #endif |
|
277 |
|
278 |
|
279 /* --------------------------------------------------------------------- */ |
|
280 /* Utility macros and functions */ |
|
281 |
|
282 #define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \ |
|
283 { \ |
|
284 object->sibling_next=backlink; \ |
|
285 object->sibling_prev_p=&(backlink); \ |
|
286 backlink=object; \ |
|
287 if (object->sibling_next) { \ |
|
288 object->sibling_next->sibling_prev_p=&(object->sibling_next); \ |
|
289 } \ |
|
290 } |
|
291 |
|
292 #define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \ |
|
293 { \ |
|
294 if (object->sibling_next) { \ |
|
295 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \ |
|
296 } \ |
|
297 *(object->sibling_prev_p)=object->sibling_next; \ |
|
298 } |
|
299 |
|
300 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \ |
|
301 { \ |
|
302 if (object->sibling_next) { \ |
|
303 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \ |
|
304 } \ |
|
305 if (object->sibling_prev_p) { \ |
|
306 *(object->sibling_prev_p)=object->sibling_next; \ |
|
307 } \ |
|
308 } |
|
309 |
|
310 #define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \ |
|
311 { \ |
|
312 object->sibling_next_txn=backlink; \ |
|
313 object->sibling_prev_p_txn=&(backlink); \ |
|
314 backlink=object; \ |
|
315 if (object->sibling_next_txn) { \ |
|
316 object->sibling_next_txn->sibling_prev_p_txn= \ |
|
317 &(object->sibling_next_txn); \ |
|
318 } \ |
|
319 } |
|
320 |
|
321 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \ |
|
322 { \ |
|
323 if (object->sibling_next_txn) { \ |
|
324 object->sibling_next_txn->sibling_prev_p_txn= \ |
|
325 object->sibling_prev_p_txn; \ |
|
326 } \ |
|
327 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \ |
|
328 } |
|
329 |
|
330 |
|
331 #define RETURN_IF_ERR() \ |
|
332 if (makeDBError(err)) { \ |
|
333 return NULL; \ |
|
334 } |
|
335 |
|
336 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None; |
|
337 |
|
338 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \ |
|
339 if ((nonNull) == NULL) { \ |
|
340 PyObject *errTuple = NULL; \ |
|
341 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \ |
|
342 if (errTuple) { \ |
|
343 PyErr_SetObject((pyErrObj), errTuple); \ |
|
344 Py_DECREF(errTuple); \ |
|
345 } \ |
|
346 return NULL; \ |
|
347 } |
|
348 |
|
349 #define CHECK_DB_NOT_CLOSED(dbobj) \ |
|
350 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB) |
|
351 |
|
352 #define CHECK_ENV_NOT_CLOSED(env) \ |
|
353 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv) |
|
354 |
|
355 #define CHECK_CURSOR_NOT_CLOSED(curs) \ |
|
356 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor) |
|
357 |
|
358 #if (DBVER >= 43) |
|
359 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \ |
|
360 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence) |
|
361 #endif |
|
362 |
|
363 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \ |
|
364 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag)))) |
|
365 |
|
366 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt))) |
|
367 |
|
368 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \ |
|
369 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; } |
|
370 |
|
371 |
|
372 static int makeDBError(int err); |
|
373 |
|
374 |
|
375 /* Return the access method type of the DBObject */ |
|
376 static int _DB_get_type(DBObject* self) |
|
377 { |
|
378 DBTYPE type; |
|
379 int err; |
|
380 |
|
381 err = self->db->get_type(self->db, &type); |
|
382 if (makeDBError(err)) { |
|
383 return -1; |
|
384 } |
|
385 return type; |
|
386 } |
|
387 |
|
388 |
|
389 /* Create a DBT structure (containing key and data values) from Python |
|
390 strings. Returns 1 on success, 0 on an error. */ |
|
391 static int make_dbt(PyObject* obj, DBT* dbt) |
|
392 { |
|
393 CLEAR_DBT(*dbt); |
|
394 if (obj == Py_None) { |
|
395 /* no need to do anything, the structure has already been zeroed */ |
|
396 } |
|
397 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) { |
|
398 PyErr_SetString(PyExc_TypeError, |
|
399 #if (PY_VERSION_HEX < 0x03000000) |
|
400 "Data values must be of type string or None."); |
|
401 #else |
|
402 "Data values must be of type bytes or None."); |
|
403 #endif |
|
404 return 0; |
|
405 } |
|
406 return 1; |
|
407 } |
|
408 |
|
409 |
|
410 /* Recno and Queue DBs can have integer keys. This function figures out |
|
411 what's been given, verifies that it's allowed, and then makes the DBT. |
|
412 |
|
413 Caller MUST call FREE_DBT(key) when done. */ |
|
414 static int |
|
415 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags) |
|
416 { |
|
417 db_recno_t recno; |
|
418 int type; |
|
419 |
|
420 CLEAR_DBT(*key); |
|
421 if (keyobj == Py_None) { |
|
422 type = _DB_get_type(self); |
|
423 if (type == -1) |
|
424 return 0; |
|
425 if (type == DB_RECNO || type == DB_QUEUE) { |
|
426 PyErr_SetString( |
|
427 PyExc_TypeError, |
|
428 "None keys not allowed for Recno and Queue DB's"); |
|
429 return 0; |
|
430 } |
|
431 /* no need to do anything, the structure has already been zeroed */ |
|
432 } |
|
433 |
|
434 else if (PyBytes_Check(keyobj)) { |
|
435 /* verify access method type */ |
|
436 type = _DB_get_type(self); |
|
437 if (type == -1) |
|
438 return 0; |
|
439 if (type == DB_RECNO || type == DB_QUEUE) { |
|
440 PyErr_SetString( |
|
441 PyExc_TypeError, |
|
442 #if (PY_VERSION_HEX < 0x03000000) |
|
443 "String keys not allowed for Recno and Queue DB's"); |
|
444 #else |
|
445 "Bytes keys not allowed for Recno and Queue DB's"); |
|
446 #endif |
|
447 return 0; |
|
448 } |
|
449 |
|
450 /* |
|
451 * NOTE(gps): I don't like doing a data copy here, it seems |
|
452 * wasteful. But without a clean way to tell FREE_DBT if it |
|
453 * should free key->data or not we have to. Other places in |
|
454 * the code check for DB_THREAD and forceably set DBT_MALLOC |
|
455 * when we otherwise would leave flags 0 to indicate that. |
|
456 */ |
|
457 key->data = malloc(PyBytes_GET_SIZE(keyobj)); |
|
458 if (key->data == NULL) { |
|
459 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed"); |
|
460 return 0; |
|
461 } |
|
462 memcpy(key->data, PyBytes_AS_STRING(keyobj), |
|
463 PyBytes_GET_SIZE(keyobj)); |
|
464 key->flags = DB_DBT_REALLOC; |
|
465 key->size = PyBytes_GET_SIZE(keyobj); |
|
466 } |
|
467 |
|
468 else if (NUMBER_Check(keyobj)) { |
|
469 /* verify access method type */ |
|
470 type = _DB_get_type(self); |
|
471 if (type == -1) |
|
472 return 0; |
|
473 if (type == DB_BTREE && pflags != NULL) { |
|
474 /* if BTREE then an Integer key is allowed with the |
|
475 * DB_SET_RECNO flag */ |
|
476 *pflags |= DB_SET_RECNO; |
|
477 } |
|
478 else if (type != DB_RECNO && type != DB_QUEUE) { |
|
479 PyErr_SetString( |
|
480 PyExc_TypeError, |
|
481 "Integer keys only allowed for Recno and Queue DB's"); |
|
482 return 0; |
|
483 } |
|
484 |
|
485 /* Make a key out of the requested recno, use allocated space so DB |
|
486 * will be able to realloc room for the real key if needed. */ |
|
487 recno = NUMBER_AsLong(keyobj); |
|
488 key->data = malloc(sizeof(db_recno_t)); |
|
489 if (key->data == NULL) { |
|
490 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed"); |
|
491 return 0; |
|
492 } |
|
493 key->ulen = key->size = sizeof(db_recno_t); |
|
494 memcpy(key->data, &recno, sizeof(db_recno_t)); |
|
495 key->flags = DB_DBT_REALLOC; |
|
496 } |
|
497 else { |
|
498 PyErr_Format(PyExc_TypeError, |
|
499 #if (PY_VERSION_HEX < 0x03000000) |
|
500 "String or Integer object expected for key, %s found", |
|
501 #else |
|
502 "Bytes or Integer object expected for key, %s found", |
|
503 #endif |
|
504 Py_TYPE(keyobj)->tp_name); |
|
505 return 0; |
|
506 } |
|
507 |
|
508 return 1; |
|
509 } |
|
510 |
|
511 |
|
512 /* Add partial record access to an existing DBT data struct. |
|
513 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set |
|
514 and the data storage/retrieval will be done using dlen and doff. */ |
|
515 static int add_partial_dbt(DBT* d, int dlen, int doff) { |
|
516 /* if neither were set we do nothing (-1 is the default value) */ |
|
517 if ((dlen == -1) && (doff == -1)) { |
|
518 return 1; |
|
519 } |
|
520 |
|
521 if ((dlen < 0) || (doff < 0)) { |
|
522 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0"); |
|
523 return 0; |
|
524 } |
|
525 |
|
526 d->flags = d->flags | DB_DBT_PARTIAL; |
|
527 d->dlen = (unsigned int) dlen; |
|
528 d->doff = (unsigned int) doff; |
|
529 return 1; |
|
530 } |
|
531 |
|
532 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */ |
|
533 /* TODO: make this use the native libc strlcpy() when available (BSD) */ |
|
534 unsigned int our_strlcpy(char* dest, const char* src, unsigned int n) |
|
535 { |
|
536 unsigned int srclen, copylen; |
|
537 |
|
538 srclen = strlen(src); |
|
539 if (n <= 0) |
|
540 return srclen; |
|
541 copylen = (srclen > n-1) ? n-1 : srclen; |
|
542 /* populate dest[0] thru dest[copylen-1] */ |
|
543 memcpy(dest, src, copylen); |
|
544 /* guarantee null termination */ |
|
545 dest[copylen] = 0; |
|
546 |
|
547 return srclen; |
|
548 } |
|
549 |
|
550 /* Callback used to save away more information about errors from the DB |
|
551 * library. */ |
|
552 static char _db_errmsg[1024]; |
|
553 #if (DBVER <= 42) |
|
554 static void _db_errorCallback(const char* prefix, char* msg) |
|
555 #else |
|
556 static void _db_errorCallback(const DB_ENV *db_env, |
|
557 const char* prefix, const char* msg) |
|
558 #endif |
|
559 { |
|
560 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg)); |
|
561 } |
|
562 |
|
563 |
|
564 /* |
|
565 ** We need these functions because some results |
|
566 ** are undefined if pointer is NULL. Some other |
|
567 ** give None instead of "". |
|
568 ** |
|
569 ** This functions are static and will be |
|
570 ** -I hope- inlined. |
|
571 */ |
|
572 static const char *DummyString = "This string is a simple placeholder"; |
|
573 static PyObject *Build_PyString(const char *p,int s) |
|
574 { |
|
575 if (!p) { |
|
576 p=DummyString; |
|
577 assert(s==0); |
|
578 } |
|
579 return PyBytes_FromStringAndSize(p,s); |
|
580 } |
|
581 |
|
582 static PyObject *BuildValue_S(const void *p,int s) |
|
583 { |
|
584 if (!p) { |
|
585 p=DummyString; |
|
586 assert(s==0); |
|
587 } |
|
588 return PyBytes_FromStringAndSize(p, s); |
|
589 } |
|
590 |
|
591 static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2) |
|
592 { |
|
593 PyObject *a, *b, *r; |
|
594 |
|
595 if (!p1) { |
|
596 p1=DummyString; |
|
597 assert(s1==0); |
|
598 } |
|
599 if (!p2) { |
|
600 p2=DummyString; |
|
601 assert(s2==0); |
|
602 } |
|
603 |
|
604 if (!(a = PyBytes_FromStringAndSize(p1, s1))) { |
|
605 return NULL; |
|
606 } |
|
607 if (!(b = PyBytes_FromStringAndSize(p2, s2))) { |
|
608 Py_DECREF(a); |
|
609 return NULL; |
|
610 } |
|
611 |
|
612 #if (PY_VERSION_HEX >= 0x02040000) |
|
613 r = PyTuple_Pack(2, a, b) ; |
|
614 #else |
|
615 r = Py_BuildValue("OO", a, b); |
|
616 #endif |
|
617 Py_DECREF(a); |
|
618 Py_DECREF(b); |
|
619 return r; |
|
620 } |
|
621 |
|
622 static PyObject *BuildValue_IS(int i,const void *p,int s) |
|
623 { |
|
624 PyObject *a, *r; |
|
625 |
|
626 if (!p) { |
|
627 p=DummyString; |
|
628 assert(s==0); |
|
629 } |
|
630 |
|
631 if (!(a = PyBytes_FromStringAndSize(p, s))) { |
|
632 return NULL; |
|
633 } |
|
634 |
|
635 r = Py_BuildValue("iO", i, a); |
|
636 Py_DECREF(a); |
|
637 return r; |
|
638 } |
|
639 |
|
640 static PyObject *BuildValue_LS(long l,const void *p,int s) |
|
641 { |
|
642 PyObject *a, *r; |
|
643 |
|
644 if (!p) { |
|
645 p=DummyString; |
|
646 assert(s==0); |
|
647 } |
|
648 |
|
649 if (!(a = PyBytes_FromStringAndSize(p, s))) { |
|
650 return NULL; |
|
651 } |
|
652 |
|
653 r = Py_BuildValue("lO", l, a); |
|
654 Py_DECREF(a); |
|
655 return r; |
|
656 } |
|
657 |
|
658 |
|
659 |
|
660 /* make a nice exception object to raise for errors. */ |
|
661 static int makeDBError(int err) |
|
662 { |
|
663 char errTxt[2048]; /* really big, just in case... */ |
|
664 PyObject *errObj = NULL; |
|
665 PyObject *errTuple = NULL; |
|
666 int exceptionRaised = 0; |
|
667 unsigned int bytes_left; |
|
668 |
|
669 switch (err) { |
|
670 case 0: /* successful, no error */ break; |
|
671 |
|
672 #if (DBVER < 41) |
|
673 case DB_INCOMPLETE: |
|
674 #if INCOMPLETE_IS_WARNING |
|
675 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt)); |
|
676 /* Ensure that bytes_left never goes negative */ |
|
677 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) { |
|
678 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1; |
|
679 assert(bytes_left >= 0); |
|
680 strcat(errTxt, " -- "); |
|
681 strncat(errTxt, _db_errmsg, bytes_left); |
|
682 } |
|
683 _db_errmsg[0] = 0; |
|
684 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt); |
|
685 |
|
686 #else /* do an exception instead */ |
|
687 errObj = DBIncompleteError; |
|
688 #endif |
|
689 break; |
|
690 #endif /* DBVER < 41 */ |
|
691 |
|
692 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break; |
|
693 case DB_KEYEXIST: errObj = DBKeyExistError; break; |
|
694 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break; |
|
695 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break; |
|
696 case DB_NOTFOUND: errObj = DBNotFoundError; break; |
|
697 case DB_OLD_VERSION: errObj = DBOldVersionError; break; |
|
698 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break; |
|
699 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break; |
|
700 case DB_NOSERVER: errObj = DBNoServerError; break; |
|
701 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break; |
|
702 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break; |
|
703 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break; |
|
704 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break; |
|
705 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break; |
|
706 |
|
707 #if (DBVER >= 43) |
|
708 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */ |
|
709 case ENOMEM: errObj = PyExc_MemoryError; break; |
|
710 #endif |
|
711 case EINVAL: errObj = DBInvalidArgError; break; |
|
712 case EACCES: errObj = DBAccessError; break; |
|
713 case ENOSPC: errObj = DBNoSpaceError; break; |
|
714 case EAGAIN: errObj = DBAgainError; break; |
|
715 case EBUSY : errObj = DBBusyError; break; |
|
716 case EEXIST: errObj = DBFileExistsError; break; |
|
717 case ENOENT: errObj = DBNoSuchFileError; break; |
|
718 case EPERM : errObj = DBPermissionsError; break; |
|
719 |
|
720 #if (DBVER >= 42) |
|
721 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break; |
|
722 #endif |
|
723 |
|
724 case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break; |
|
725 |
|
726 default: errObj = DBError; break; |
|
727 } |
|
728 |
|
729 if (errObj != NULL) { |
|
730 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt)); |
|
731 /* Ensure that bytes_left never goes negative */ |
|
732 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) { |
|
733 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1; |
|
734 assert(bytes_left >= 0); |
|
735 strcat(errTxt, " -- "); |
|
736 strncat(errTxt, _db_errmsg, bytes_left); |
|
737 } |
|
738 _db_errmsg[0] = 0; |
|
739 |
|
740 errTuple = Py_BuildValue("(is)", err, errTxt); |
|
741 if (errTuple == NULL) { |
|
742 Py_DECREF(errObj); |
|
743 return !0; |
|
744 } |
|
745 PyErr_SetObject(errObj, errTuple); |
|
746 Py_DECREF(errTuple); |
|
747 } |
|
748 |
|
749 return ((errObj != NULL) || exceptionRaised); |
|
750 } |
|
751 |
|
752 |
|
753 |
|
754 /* set a type exception */ |
|
755 static void makeTypeError(char* expected, PyObject* found) |
|
756 { |
|
757 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.", |
|
758 expected, Py_TYPE(found)->tp_name); |
|
759 } |
|
760 |
|
761 |
|
762 /* verify that an obj is either None or a DBTxn, and set the txn pointer */ |
|
763 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn) |
|
764 { |
|
765 if (txnobj == Py_None || txnobj == NULL) { |
|
766 *txn = NULL; |
|
767 return 1; |
|
768 } |
|
769 if (DBTxnObject_Check(txnobj)) { |
|
770 *txn = ((DBTxnObject*)txnobj)->txn; |
|
771 return 1; |
|
772 } |
|
773 else |
|
774 makeTypeError("DBTxn", txnobj); |
|
775 return 0; |
|
776 } |
|
777 |
|
778 |
|
779 /* Delete a key from a database |
|
780 Returns 0 on success, -1 on an error. */ |
|
781 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags) |
|
782 { |
|
783 int err; |
|
784 |
|
785 MYDB_BEGIN_ALLOW_THREADS; |
|
786 err = self->db->del(self->db, txn, key, 0); |
|
787 MYDB_END_ALLOW_THREADS; |
|
788 if (makeDBError(err)) { |
|
789 return -1; |
|
790 } |
|
791 self->haveStat = 0; |
|
792 return 0; |
|
793 } |
|
794 |
|
795 |
|
796 /* Store a key into a database |
|
797 Returns 0 on success, -1 on an error. */ |
|
798 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags) |
|
799 { |
|
800 int err; |
|
801 |
|
802 MYDB_BEGIN_ALLOW_THREADS; |
|
803 err = self->db->put(self->db, txn, key, data, flags); |
|
804 MYDB_END_ALLOW_THREADS; |
|
805 if (makeDBError(err)) { |
|
806 return -1; |
|
807 } |
|
808 self->haveStat = 0; |
|
809 return 0; |
|
810 } |
|
811 |
|
812 /* Get a key/data pair from a cursor */ |
|
813 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags, |
|
814 PyObject *args, PyObject *kwargs, char *format) |
|
815 { |
|
816 int err; |
|
817 PyObject* retval = NULL; |
|
818 DBT key, data; |
|
819 int dlen = -1; |
|
820 int doff = -1; |
|
821 int flags = 0; |
|
822 static char* kwnames[] = { "flags", "dlen", "doff", NULL }; |
|
823 |
|
824 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames, |
|
825 &flags, &dlen, &doff)) |
|
826 return NULL; |
|
827 |
|
828 CHECK_CURSOR_NOT_CLOSED(self); |
|
829 |
|
830 flags |= extra_flags; |
|
831 CLEAR_DBT(key); |
|
832 CLEAR_DBT(data); |
|
833 if (!add_partial_dbt(&data, dlen, doff)) |
|
834 return NULL; |
|
835 |
|
836 MYDB_BEGIN_ALLOW_THREADS; |
|
837 err = _DBC_get(self->dbc, &key, &data, flags); |
|
838 MYDB_END_ALLOW_THREADS; |
|
839 |
|
840 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) |
|
841 && self->mydb->moduleFlags.getReturnsNone) { |
|
842 Py_INCREF(Py_None); |
|
843 retval = Py_None; |
|
844 } |
|
845 else if (makeDBError(err)) { |
|
846 retval = NULL; |
|
847 } |
|
848 else { /* otherwise, success! */ |
|
849 |
|
850 /* if Recno or Queue, return the key as an Int */ |
|
851 switch (_DB_get_type(self->mydb)) { |
|
852 case -1: |
|
853 retval = NULL; |
|
854 break; |
|
855 |
|
856 case DB_RECNO: |
|
857 case DB_QUEUE: |
|
858 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); |
|
859 break; |
|
860 case DB_HASH: |
|
861 case DB_BTREE: |
|
862 default: |
|
863 retval = BuildValue_SS(key.data, key.size, data.data, data.size); |
|
864 break; |
|
865 } |
|
866 } |
|
867 return retval; |
|
868 } |
|
869 |
|
870 |
|
871 /* add an integer to a dictionary using the given name as a key */ |
|
872 static void _addIntToDict(PyObject* dict, char *name, int value) |
|
873 { |
|
874 PyObject* v = NUMBER_FromLong((long) value); |
|
875 if (!v || PyDict_SetItemString(dict, name, v)) |
|
876 PyErr_Clear(); |
|
877 |
|
878 Py_XDECREF(v); |
|
879 } |
|
880 |
|
881 /* The same, when the value is a time_t */ |
|
882 static void _addTimeTToDict(PyObject* dict, char *name, time_t value) |
|
883 { |
|
884 PyObject* v; |
|
885 /* if the value fits in regular int, use that. */ |
|
886 #ifdef PY_LONG_LONG |
|
887 if (sizeof(time_t) > sizeof(long)) |
|
888 v = PyLong_FromLongLong((PY_LONG_LONG) value); |
|
889 else |
|
890 #endif |
|
891 v = NUMBER_FromLong((long) value); |
|
892 if (!v || PyDict_SetItemString(dict, name, v)) |
|
893 PyErr_Clear(); |
|
894 |
|
895 Py_XDECREF(v); |
|
896 } |
|
897 |
|
898 #if (DBVER >= 43) |
|
899 /* add an db_seq_t to a dictionary using the given name as a key */ |
|
900 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value) |
|
901 { |
|
902 PyObject* v = PyLong_FromLongLong(value); |
|
903 if (!v || PyDict_SetItemString(dict, name, v)) |
|
904 PyErr_Clear(); |
|
905 |
|
906 Py_XDECREF(v); |
|
907 } |
|
908 #endif |
|
909 |
|
910 static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value) |
|
911 { |
|
912 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset); |
|
913 if (!v || PyDict_SetItemString(dict, name, v)) |
|
914 PyErr_Clear(); |
|
915 |
|
916 Py_XDECREF(v); |
|
917 } |
|
918 |
|
919 /* --------------------------------------------------------------------- */ |
|
920 /* Allocators and deallocators */ |
|
921 |
|
922 static DBObject* |
|
923 newDBObject(DBEnvObject* arg, int flags) |
|
924 { |
|
925 DBObject* self; |
|
926 DB_ENV* db_env = NULL; |
|
927 int err; |
|
928 |
|
929 self = PyObject_New(DBObject, &DB_Type); |
|
930 if (self == NULL) |
|
931 return NULL; |
|
932 |
|
933 self->haveStat = 0; |
|
934 self->flags = 0; |
|
935 self->setflags = 0; |
|
936 self->myenvobj = NULL; |
|
937 self->db = NULL; |
|
938 self->children_cursors = NULL; |
|
939 #if (DBVER >=43) |
|
940 self->children_sequences = NULL; |
|
941 #endif |
|
942 self->associateCallback = NULL; |
|
943 self->btCompareCallback = NULL; |
|
944 self->primaryDBType = 0; |
|
945 Py_INCREF(Py_None); |
|
946 self->private_obj = Py_None; |
|
947 self->in_weakreflist = NULL; |
|
948 |
|
949 /* keep a reference to our python DBEnv object */ |
|
950 if (arg) { |
|
951 Py_INCREF(arg); |
|
952 self->myenvobj = arg; |
|
953 db_env = arg->db_env; |
|
954 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self); |
|
955 } else { |
|
956 self->sibling_prev_p=NULL; |
|
957 self->sibling_next=NULL; |
|
958 } |
|
959 self->txn=NULL; |
|
960 self->sibling_prev_p_txn=NULL; |
|
961 self->sibling_next_txn=NULL; |
|
962 |
|
963 if (self->myenvobj) |
|
964 self->moduleFlags = self->myenvobj->moduleFlags; |
|
965 else |
|
966 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE; |
|
967 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE; |
|
968 |
|
969 MYDB_BEGIN_ALLOW_THREADS; |
|
970 err = db_create(&self->db, db_env, flags); |
|
971 if (self->db != NULL) { |
|
972 self->db->set_errcall(self->db, _db_errorCallback); |
|
973 self->db->app_private = (void*)self; |
|
974 } |
|
975 MYDB_END_ALLOW_THREADS; |
|
976 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs |
|
977 * list so that a DBEnv can refuse to close without aborting any open |
|
978 * DBTxns and closing any open DBs first. */ |
|
979 if (makeDBError(err)) { |
|
980 if (self->myenvobj) { |
|
981 Py_DECREF(self->myenvobj); |
|
982 self->myenvobj = NULL; |
|
983 } |
|
984 Py_DECREF(self); |
|
985 self = NULL; |
|
986 } |
|
987 return self; |
|
988 } |
|
989 |
|
990 |
|
991 /* Forward declaration */ |
|
992 static PyObject *DB_close_internal(DBObject* self, int flags, int do_not_close); |
|
993 |
|
994 static void |
|
995 DB_dealloc(DBObject* self) |
|
996 { |
|
997 PyObject *dummy; |
|
998 |
|
999 if (self->db != NULL) { |
|
1000 dummy=DB_close_internal(self, 0, 0); |
|
1001 /* |
|
1002 ** Raising exceptions while doing |
|
1003 ** garbage collection is a fatal error. |
|
1004 */ |
|
1005 if (dummy) |
|
1006 Py_DECREF(dummy); |
|
1007 else |
|
1008 PyErr_Clear(); |
|
1009 } |
|
1010 if (self->in_weakreflist != NULL) { |
|
1011 PyObject_ClearWeakRefs((PyObject *) self); |
|
1012 } |
|
1013 if (self->myenvobj) { |
|
1014 Py_DECREF(self->myenvobj); |
|
1015 self->myenvobj = NULL; |
|
1016 } |
|
1017 if (self->associateCallback != NULL) { |
|
1018 Py_DECREF(self->associateCallback); |
|
1019 self->associateCallback = NULL; |
|
1020 } |
|
1021 if (self->btCompareCallback != NULL) { |
|
1022 Py_DECREF(self->btCompareCallback); |
|
1023 self->btCompareCallback = NULL; |
|
1024 } |
|
1025 Py_DECREF(self->private_obj); |
|
1026 PyObject_Del(self); |
|
1027 } |
|
1028 |
|
1029 static DBCursorObject* |
|
1030 newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db) |
|
1031 { |
|
1032 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type); |
|
1033 if (self == NULL) |
|
1034 return NULL; |
|
1035 |
|
1036 self->dbc = dbc; |
|
1037 self->mydb = db; |
|
1038 |
|
1039 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self); |
|
1040 if (txn && ((PyObject *)txn!=Py_None)) { |
|
1041 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self); |
|
1042 self->txn=txn; |
|
1043 } else { |
|
1044 self->txn=NULL; |
|
1045 } |
|
1046 |
|
1047 self->in_weakreflist = NULL; |
|
1048 Py_INCREF(self->mydb); |
|
1049 return self; |
|
1050 } |
|
1051 |
|
1052 |
|
1053 /* Forward declaration */ |
|
1054 static PyObject *DBC_close_internal(DBCursorObject* self); |
|
1055 |
|
1056 static void |
|
1057 DBCursor_dealloc(DBCursorObject* self) |
|
1058 { |
|
1059 PyObject *dummy; |
|
1060 |
|
1061 if (self->dbc != NULL) { |
|
1062 dummy=DBC_close_internal(self); |
|
1063 /* |
|
1064 ** Raising exceptions while doing |
|
1065 ** garbage collection is a fatal error. |
|
1066 */ |
|
1067 if (dummy) |
|
1068 Py_DECREF(dummy); |
|
1069 else |
|
1070 PyErr_Clear(); |
|
1071 } |
|
1072 if (self->in_weakreflist != NULL) { |
|
1073 PyObject_ClearWeakRefs((PyObject *) self); |
|
1074 } |
|
1075 Py_DECREF(self->mydb); |
|
1076 PyObject_Del(self); |
|
1077 } |
|
1078 |
|
1079 |
|
1080 static DBEnvObject* |
|
1081 newDBEnvObject(int flags) |
|
1082 { |
|
1083 int err; |
|
1084 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type); |
|
1085 if (self == NULL) |
|
1086 return NULL; |
|
1087 |
|
1088 self->db_env = NULL; |
|
1089 self->closed = 1; |
|
1090 self->flags = flags; |
|
1091 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE; |
|
1092 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE; |
|
1093 self->children_dbs = NULL; |
|
1094 self->children_txns = NULL; |
|
1095 Py_INCREF(Py_None); |
|
1096 self->private_obj = Py_None; |
|
1097 Py_INCREF(Py_None); |
|
1098 self->rep_transport = Py_None; |
|
1099 self->in_weakreflist = NULL; |
|
1100 self->event_notifyCallback = NULL; |
|
1101 |
|
1102 MYDB_BEGIN_ALLOW_THREADS; |
|
1103 err = db_env_create(&self->db_env, flags); |
|
1104 MYDB_END_ALLOW_THREADS; |
|
1105 if (makeDBError(err)) { |
|
1106 Py_DECREF(self); |
|
1107 self = NULL; |
|
1108 } |
|
1109 else { |
|
1110 self->db_env->set_errcall(self->db_env, _db_errorCallback); |
|
1111 self->db_env->app_private = self; |
|
1112 } |
|
1113 return self; |
|
1114 } |
|
1115 |
|
1116 /* Forward declaration */ |
|
1117 static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags); |
|
1118 |
|
1119 static void |
|
1120 DBEnv_dealloc(DBEnvObject* self) |
|
1121 { |
|
1122 PyObject *dummy; |
|
1123 |
|
1124 if (self->db_env) { |
|
1125 dummy=DBEnv_close_internal(self, 0); |
|
1126 /* |
|
1127 ** Raising exceptions while doing |
|
1128 ** garbage collection is a fatal error. |
|
1129 */ |
|
1130 if (dummy) |
|
1131 Py_DECREF(dummy); |
|
1132 else |
|
1133 PyErr_Clear(); |
|
1134 } |
|
1135 |
|
1136 Py_XDECREF(self->event_notifyCallback); |
|
1137 self->event_notifyCallback = NULL; |
|
1138 |
|
1139 if (self->in_weakreflist != NULL) { |
|
1140 PyObject_ClearWeakRefs((PyObject *) self); |
|
1141 } |
|
1142 Py_DECREF(self->private_obj); |
|
1143 Py_DECREF(self->rep_transport); |
|
1144 PyObject_Del(self); |
|
1145 } |
|
1146 |
|
1147 |
|
1148 static DBTxnObject* |
|
1149 newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags) |
|
1150 { |
|
1151 int err; |
|
1152 DB_TXN *parent_txn = NULL; |
|
1153 |
|
1154 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type); |
|
1155 if (self == NULL) |
|
1156 return NULL; |
|
1157 |
|
1158 self->in_weakreflist = NULL; |
|
1159 self->children_txns = NULL; |
|
1160 self->children_dbs = NULL; |
|
1161 self->children_cursors = NULL; |
|
1162 self->children_sequences = NULL; |
|
1163 self->flag_prepare = 0; |
|
1164 self->parent_txn = NULL; |
|
1165 self->env = NULL; |
|
1166 |
|
1167 if (parent && ((PyObject *)parent!=Py_None)) { |
|
1168 parent_txn = parent->txn; |
|
1169 } |
|
1170 |
|
1171 if (txn) { |
|
1172 self->txn = txn; |
|
1173 } else { |
|
1174 MYDB_BEGIN_ALLOW_THREADS; |
|
1175 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags); |
|
1176 MYDB_END_ALLOW_THREADS; |
|
1177 |
|
1178 if (makeDBError(err)) { |
|
1179 Py_DECREF(self); |
|
1180 return NULL; |
|
1181 } |
|
1182 } |
|
1183 |
|
1184 /* Can't use 'parent' because could be 'parent==Py_None' */ |
|
1185 if (parent_txn) { |
|
1186 self->parent_txn = parent; |
|
1187 Py_INCREF(parent); |
|
1188 self->env = NULL; |
|
1189 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self); |
|
1190 } else { |
|
1191 self->parent_txn = NULL; |
|
1192 Py_INCREF(myenv); |
|
1193 self->env = myenv; |
|
1194 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self); |
|
1195 } |
|
1196 |
|
1197 return self; |
|
1198 } |
|
1199 |
|
1200 /* Forward declaration */ |
|
1201 static PyObject * |
|
1202 DBTxn_abort_discard_internal(DBTxnObject* self, int discard); |
|
1203 |
|
1204 static void |
|
1205 DBTxn_dealloc(DBTxnObject* self) |
|
1206 { |
|
1207 PyObject *dummy; |
|
1208 |
|
1209 if (self->txn) { |
|
1210 int flag_prepare = self->flag_prepare; |
|
1211 |
|
1212 dummy=DBTxn_abort_discard_internal(self,0); |
|
1213 /* |
|
1214 ** Raising exceptions while doing |
|
1215 ** garbage collection is a fatal error. |
|
1216 */ |
|
1217 if (dummy) |
|
1218 Py_DECREF(dummy); |
|
1219 else |
|
1220 PyErr_Clear(); |
|
1221 |
|
1222 if (!flag_prepare) { |
|
1223 PyErr_Warn(PyExc_RuntimeWarning, |
|
1224 "DBTxn aborted in destructor. No prior commit() or abort()."); |
|
1225 } |
|
1226 } |
|
1227 |
|
1228 if (self->in_weakreflist != NULL) { |
|
1229 PyObject_ClearWeakRefs((PyObject *) self); |
|
1230 } |
|
1231 |
|
1232 if (self->env) { |
|
1233 Py_DECREF(self->env); |
|
1234 } else { |
|
1235 Py_DECREF(self->parent_txn); |
|
1236 } |
|
1237 PyObject_Del(self); |
|
1238 } |
|
1239 |
|
1240 |
|
1241 static DBLockObject* |
|
1242 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj, |
|
1243 db_lockmode_t lock_mode, int flags) |
|
1244 { |
|
1245 int err; |
|
1246 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type); |
|
1247 if (self == NULL) |
|
1248 return NULL; |
|
1249 self->in_weakreflist = NULL; |
|
1250 |
|
1251 MYDB_BEGIN_ALLOW_THREADS; |
|
1252 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode, |
|
1253 &self->lock); |
|
1254 MYDB_END_ALLOW_THREADS; |
|
1255 if (makeDBError(err)) { |
|
1256 Py_DECREF(self); |
|
1257 self = NULL; |
|
1258 } |
|
1259 |
|
1260 return self; |
|
1261 } |
|
1262 |
|
1263 |
|
1264 static void |
|
1265 DBLock_dealloc(DBLockObject* self) |
|
1266 { |
|
1267 if (self->in_weakreflist != NULL) { |
|
1268 PyObject_ClearWeakRefs((PyObject *) self); |
|
1269 } |
|
1270 /* TODO: is this lock held? should we release it? */ |
|
1271 |
|
1272 PyObject_Del(self); |
|
1273 } |
|
1274 |
|
1275 |
|
1276 #if (DBVER >= 43) |
|
1277 static DBSequenceObject* |
|
1278 newDBSequenceObject(DBObject* mydb, int flags) |
|
1279 { |
|
1280 int err; |
|
1281 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type); |
|
1282 if (self == NULL) |
|
1283 return NULL; |
|
1284 Py_INCREF(mydb); |
|
1285 self->mydb = mydb; |
|
1286 |
|
1287 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self); |
|
1288 self->txn = NULL; |
|
1289 |
|
1290 self->in_weakreflist = NULL; |
|
1291 |
|
1292 MYDB_BEGIN_ALLOW_THREADS; |
|
1293 err = db_sequence_create(&self->sequence, self->mydb->db, flags); |
|
1294 MYDB_END_ALLOW_THREADS; |
|
1295 if (makeDBError(err)) { |
|
1296 Py_DECREF(self); |
|
1297 self = NULL; |
|
1298 } |
|
1299 |
|
1300 return self; |
|
1301 } |
|
1302 |
|
1303 /* Forward declaration */ |
|
1304 static PyObject |
|
1305 *DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close); |
|
1306 |
|
1307 static void |
|
1308 DBSequence_dealloc(DBSequenceObject* self) |
|
1309 { |
|
1310 PyObject *dummy; |
|
1311 |
|
1312 if (self->sequence != NULL) { |
|
1313 dummy=DBSequence_close_internal(self,0,0); |
|
1314 /* |
|
1315 ** Raising exceptions while doing |
|
1316 ** garbage collection is a fatal error. |
|
1317 */ |
|
1318 if (dummy) |
|
1319 Py_DECREF(dummy); |
|
1320 else |
|
1321 PyErr_Clear(); |
|
1322 } |
|
1323 |
|
1324 if (self->in_weakreflist != NULL) { |
|
1325 PyObject_ClearWeakRefs((PyObject *) self); |
|
1326 } |
|
1327 |
|
1328 Py_DECREF(self->mydb); |
|
1329 PyObject_Del(self); |
|
1330 } |
|
1331 #endif |
|
1332 |
|
1333 /* --------------------------------------------------------------------- */ |
|
1334 /* DB methods */ |
|
1335 |
|
1336 static PyObject* |
|
1337 DB_append(DBObject* self, PyObject* args, PyObject* kwargs) |
|
1338 { |
|
1339 PyObject* txnobj = NULL; |
|
1340 PyObject* dataobj; |
|
1341 db_recno_t recno; |
|
1342 DBT key, data; |
|
1343 DB_TXN *txn = NULL; |
|
1344 static char* kwnames[] = { "data", "txn", NULL }; |
|
1345 |
|
1346 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames, |
|
1347 &dataobj, &txnobj)) |
|
1348 return NULL; |
|
1349 |
|
1350 CHECK_DB_NOT_CLOSED(self); |
|
1351 |
|
1352 /* make a dummy key out of a recno */ |
|
1353 recno = 0; |
|
1354 CLEAR_DBT(key); |
|
1355 key.data = &recno; |
|
1356 key.size = sizeof(recno); |
|
1357 key.ulen = key.size; |
|
1358 key.flags = DB_DBT_USERMEM; |
|
1359 |
|
1360 if (!make_dbt(dataobj, &data)) return NULL; |
|
1361 if (!checkTxnObj(txnobj, &txn)) return NULL; |
|
1362 |
|
1363 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) |
|
1364 return NULL; |
|
1365 |
|
1366 return NUMBER_FromLong(recno); |
|
1367 } |
|
1368 |
|
1369 |
|
1370 static int |
|
1371 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData, |
|
1372 DBT* secKey) |
|
1373 { |
|
1374 int retval = DB_DONOTINDEX; |
|
1375 DBObject* secondaryDB = (DBObject*)db->app_private; |
|
1376 PyObject* callback = secondaryDB->associateCallback; |
|
1377 int type = secondaryDB->primaryDBType; |
|
1378 PyObject* args; |
|
1379 PyObject* result = NULL; |
|
1380 |
|
1381 |
|
1382 if (callback != NULL) { |
|
1383 MYDB_BEGIN_BLOCK_THREADS; |
|
1384 |
|
1385 if (type == DB_RECNO || type == DB_QUEUE) |
|
1386 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size); |
|
1387 else |
|
1388 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size); |
|
1389 if (args != NULL) { |
|
1390 result = PyEval_CallObject(callback, args); |
|
1391 } |
|
1392 if (args == NULL || result == NULL) { |
|
1393 PyErr_Print(); |
|
1394 } |
|
1395 else if (result == Py_None) { |
|
1396 retval = DB_DONOTINDEX; |
|
1397 } |
|
1398 else if (NUMBER_Check(result)) { |
|
1399 retval = NUMBER_AsLong(result); |
|
1400 } |
|
1401 else if (PyBytes_Check(result)) { |
|
1402 char* data; |
|
1403 Py_ssize_t size; |
|
1404 |
|
1405 CLEAR_DBT(*secKey); |
|
1406 PyBytes_AsStringAndSize(result, &data, &size); |
|
1407 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */ |
|
1408 secKey->data = malloc(size); /* TODO, check this */ |
|
1409 if (secKey->data) { |
|
1410 memcpy(secKey->data, data, size); |
|
1411 secKey->size = size; |
|
1412 retval = 0; |
|
1413 } |
|
1414 else { |
|
1415 PyErr_SetString(PyExc_MemoryError, |
|
1416 "malloc failed in _db_associateCallback"); |
|
1417 PyErr_Print(); |
|
1418 } |
|
1419 } |
|
1420 else { |
|
1421 PyErr_SetString( |
|
1422 PyExc_TypeError, |
|
1423 "DB associate callback should return DB_DONOTINDEX or string."); |
|
1424 PyErr_Print(); |
|
1425 } |
|
1426 |
|
1427 Py_XDECREF(args); |
|
1428 Py_XDECREF(result); |
|
1429 |
|
1430 MYDB_END_BLOCK_THREADS; |
|
1431 } |
|
1432 return retval; |
|
1433 } |
|
1434 |
|
1435 |
|
1436 static PyObject* |
|
1437 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs) |
|
1438 { |
|
1439 int err, flags=0; |
|
1440 DBObject* secondaryDB; |
|
1441 PyObject* callback; |
|
1442 #if (DBVER >= 41) |
|
1443 PyObject *txnobj = NULL; |
|
1444 DB_TXN *txn = NULL; |
|
1445 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", |
|
1446 NULL}; |
|
1447 #else |
|
1448 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL}; |
|
1449 #endif |
|
1450 |
|
1451 #if (DBVER >= 41) |
|
1452 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames, |
|
1453 &secondaryDB, &callback, &flags, |
|
1454 &txnobj)) { |
|
1455 #else |
|
1456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames, |
|
1457 &secondaryDB, &callback, &flags)) { |
|
1458 #endif |
|
1459 return NULL; |
|
1460 } |
|
1461 |
|
1462 #if (DBVER >= 41) |
|
1463 if (!checkTxnObj(txnobj, &txn)) return NULL; |
|
1464 #endif |
|
1465 |
|
1466 CHECK_DB_NOT_CLOSED(self); |
|
1467 if (!DBObject_Check(secondaryDB)) { |
|
1468 makeTypeError("DB", (PyObject*)secondaryDB); |
|
1469 return NULL; |
|
1470 } |
|
1471 CHECK_DB_NOT_CLOSED(secondaryDB); |
|
1472 if (callback == Py_None) { |
|
1473 callback = NULL; |
|
1474 } |
|
1475 else if (!PyCallable_Check(callback)) { |
|
1476 makeTypeError("Callable", callback); |
|
1477 return NULL; |
|
1478 } |
|
1479 |
|
1480 /* Save a reference to the callback in the secondary DB. */ |
|
1481 Py_XDECREF(secondaryDB->associateCallback); |
|
1482 Py_XINCREF(callback); |
|
1483 secondaryDB->associateCallback = callback; |
|
1484 secondaryDB->primaryDBType = _DB_get_type(self); |
|
1485 |
|
1486 /* PyEval_InitThreads is called here due to a quirk in python 1.5 |
|
1487 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>: |
|
1488 * The global interepreter lock is not initialized until the first |
|
1489 * thread is created using thread.start_new_thread() or fork() is |
|
1490 * called. that would cause the ALLOW_THREADS here to segfault due |
|
1491 * to a null pointer reference if no threads or child processes |
|
1492 * have been created. This works around that and is a no-op if |
|
1493 * threads have already been initialized. |
|
1494 * (see pybsddb-users mailing list post on 2002-08-07) |
|
1495 */ |
|
1496 #ifdef WITH_THREAD |
|
1497 PyEval_InitThreads(); |
|
1498 #endif |
|
1499 MYDB_BEGIN_ALLOW_THREADS; |
|
1500 #if (DBVER >= 41) |
|
1501 err = self->db->associate(self->db, |
|
1502 txn, |
|
1503 secondaryDB->db, |
|
1504 _db_associateCallback, |
|
1505 flags); |
|
1506 #else |
|
1507 err = self->db->associate(self->db, |
|
1508 secondaryDB->db, |
|
1509 _db_associateCallback, |
|
1510 flags); |
|
1511 #endif |
|
1512 MYDB_END_ALLOW_THREADS; |
|
1513 |
|
1514 if (err) { |
|
1515 Py_XDECREF(secondaryDB->associateCallback); |
|
1516 secondaryDB->associateCallback = NULL; |
|
1517 secondaryDB->primaryDBType = 0; |
|
1518 } |
|
1519 |
|
1520 RETURN_IF_ERR(); |
|
1521 RETURN_NONE(); |
|
1522 } |
|
1523 |
|
1524 |
|
1525 static PyObject* |
|
1526 DB_close_internal(DBObject* self, int flags, int do_not_close) |
|
1527 { |
|
1528 PyObject *dummy; |
|
1529 int err = 0; |
|
1530 |
|
1531 if (self->db != NULL) { |
|
1532 /* Can be NULL if db is not in an environment */ |
|
1533 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self); |
|
1534 |
|
1535 if (self->txn) { |
|
1536 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self); |
|
1537 self->txn=NULL; |
|
1538 } |
|
1539 |
|
1540 while(self->children_cursors) { |
|
1541 dummy=DBC_close_internal(self->children_cursors); |
|
1542 Py_XDECREF(dummy); |
|
1543 } |
|
1544 |
|
1545 #if (DBVER >= 43) |
|
1546 while(self->children_sequences) { |
|
1547 dummy=DBSequence_close_internal(self->children_sequences,0,0); |
|
1548 Py_XDECREF(dummy); |
|
1549 } |
|
1550 #endif |
|
1551 |
|
1552 /* |
|
1553 ** "do_not_close" is used to dispose all related objects in the |
|
1554 ** tree, without actually releasing the "root" object. |
|
1555 ** This is done, for example, because function calls like |
|
1556 ** "DB.verify()" implicitly close the underlying handle. So |
|
1557 ** the handle doesn't need to be closed, but related objects |
|
1558 ** must be cleaned up. |
|
1559 */ |
|
1560 if (!do_not_close) { |
|
1561 MYDB_BEGIN_ALLOW_THREADS; |
|
1562 err = self->db->close(self->db, flags); |
|
1563 MYDB_END_ALLOW_THREADS; |
|
1564 self->db = NULL; |
|
1565 } |
|
1566 RETURN_IF_ERR(); |
|
1567 } |
|
1568 RETURN_NONE(); |
|
1569 } |
|
1570 |
|
1571 static PyObject* |
|
1572 DB_close(DBObject* self, PyObject* args) |
|
1573 { |
|
1574 int flags=0; |
|
1575 if (!PyArg_ParseTuple(args,"|i:close", &flags)) |
|
1576 return NULL; |
|
1577 return DB_close_internal(self, flags, 0); |
|
1578 } |
|
1579 |
|
1580 |
|
1581 static PyObject* |
|
1582 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag) |
|
1583 { |
|
1584 int err, flags=0, type; |
|
1585 PyObject* txnobj = NULL; |
|
1586 PyObject* retval = NULL; |
|
1587 DBT key, data; |
|
1588 DB_TXN *txn = NULL; |
|
1589 static char* kwnames[] = { "txn", "flags", NULL }; |
|
1590 |
|
1591 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames, |
|
1592 &txnobj, &flags)) |
|
1593 return NULL; |
|
1594 |
|
1595 CHECK_DB_NOT_CLOSED(self); |
|
1596 type = _DB_get_type(self); |
|
1597 if (type == -1) |
|
1598 return NULL; |
|
1599 if (type != DB_QUEUE) { |
|
1600 PyErr_SetString(PyExc_TypeError, |
|
1601 "Consume methods only allowed for Queue DB's"); |
|
1602 return NULL; |
|
1603 } |
|
1604 if (!checkTxnObj(txnobj, &txn)) |
|
1605 return NULL; |
|
1606 |
|
1607 CLEAR_DBT(key); |
|
1608 CLEAR_DBT(data); |
|
1609 if (CHECK_DBFLAG(self, DB_THREAD)) { |
|
1610 /* Tell Berkeley DB to malloc the return value (thread safe) */ |
|
1611 data.flags = DB_DBT_MALLOC; |
|
1612 key.flags = DB_DBT_MALLOC; |
|
1613 } |
|
1614 |
|
1615 MYDB_BEGIN_ALLOW_THREADS; |
|
1616 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag); |
|
1617 MYDB_END_ALLOW_THREADS; |
|
1618 |
|
1619 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) |
|
1620 && self->moduleFlags.getReturnsNone) { |
|
1621 err = 0; |
|
1622 Py_INCREF(Py_None); |
|
1623 retval = Py_None; |
|
1624 } |
|
1625 else if (!err) { |
|
1626 retval = BuildValue_SS(key.data, key.size, data.data, data.size); |
|
1627 FREE_DBT(key); |
|
1628 FREE_DBT(data); |
|
1629 } |
|
1630 |
|
1631 RETURN_IF_ERR(); |
|
1632 return retval; |
|
1633 } |
|
1634 |
|
1635 static PyObject* |
|
1636 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag) |
|
1637 { |
|
1638 return _DB_consume(self, args, kwargs, DB_CONSUME); |
|
1639 } |
|
1640 |
|
1641 static PyObject* |
|
1642 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs, |
|
1643 int consume_flag) |
|
1644 { |
|
1645 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT); |
|
1646 } |
|
1647 |
|
1648 |
|
1649 static PyObject* |
|
1650 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs) |
|
1651 { |
|
1652 int err, flags=0; |
|
1653 DBC* dbc; |
|
1654 PyObject* txnobj = NULL; |
|
1655 DB_TXN *txn = NULL; |
|
1656 static char* kwnames[] = { "txn", "flags", NULL }; |
|
1657 |
|
1658 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames, |
|
1659 &txnobj, &flags)) |
|
1660 return NULL; |
|
1661 CHECK_DB_NOT_CLOSED(self); |
|
1662 if (!checkTxnObj(txnobj, &txn)) |
|
1663 return NULL; |
|
1664 |
|
1665 MYDB_BEGIN_ALLOW_THREADS; |
|
1666 err = self->db->cursor(self->db, txn, &dbc, flags); |
|
1667 MYDB_END_ALLOW_THREADS; |
|
1668 RETURN_IF_ERR(); |
|
1669 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self); |
|
1670 } |
|
1671 |
|
1672 |
|
1673 static PyObject* |
|
1674 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs) |
|
1675 { |
|
1676 PyObject* txnobj = NULL; |
|
1677 int flags = 0; |
|
1678 PyObject* keyobj; |
|
1679 DBT key; |
|
1680 DB_TXN *txn = NULL; |
|
1681 static char* kwnames[] = { "key", "txn", "flags", NULL }; |
|
1682 |
|
1683 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames, |
|
1684 &keyobj, &txnobj, &flags)) |
|
1685 return NULL; |
|
1686 CHECK_DB_NOT_CLOSED(self); |
|
1687 if (!make_key_dbt(self, keyobj, &key, NULL)) |
|
1688 return NULL; |
|
1689 if (!checkTxnObj(txnobj, &txn)) { |
|
1690 FREE_DBT(key); |
|
1691 return NULL; |
|
1692 } |
|
1693 |
|
1694 if (-1 == _DB_delete(self, txn, &key, 0)) { |
|
1695 FREE_DBT(key); |
|
1696 return NULL; |
|
1697 } |
|
1698 |
|
1699 FREE_DBT(key); |
|
1700 RETURN_NONE(); |
|
1701 } |
|
1702 |
|
1703 |
|
1704 static PyObject* |
|
1705 DB_fd(DBObject* self) |
|
1706 { |
|
1707 int err, the_fd; |
|
1708 |
|
1709 CHECK_DB_NOT_CLOSED(self); |
|
1710 |
|
1711 MYDB_BEGIN_ALLOW_THREADS; |
|
1712 err = self->db->fd(self->db, &the_fd); |
|
1713 MYDB_END_ALLOW_THREADS; |
|
1714 RETURN_IF_ERR(); |
|
1715 return NUMBER_FromLong(the_fd); |
|
1716 } |
|
1717 |
|
1718 |
|
1719 static PyObject* |
|
1720 DB_get(DBObject* self, PyObject* args, PyObject* kwargs) |
|
1721 { |
|
1722 int err, flags=0; |
|
1723 PyObject* txnobj = NULL; |
|
1724 PyObject* keyobj; |
|
1725 PyObject* dfltobj = NULL; |
|
1726 PyObject* retval = NULL; |
|
1727 int dlen = -1; |
|
1728 int doff = -1; |
|
1729 DBT key, data; |
|
1730 DB_TXN *txn = NULL; |
|
1731 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen", |
|
1732 "doff", NULL}; |
|
1733 |
|
1734 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames, |
|
1735 &keyobj, &dfltobj, &txnobj, &flags, &dlen, |
|
1736 &doff)) |
|
1737 return NULL; |
|
1738 |
|
1739 CHECK_DB_NOT_CLOSED(self); |
|
1740 if (!make_key_dbt(self, keyobj, &key, &flags)) |
|
1741 return NULL; |
|
1742 if (!checkTxnObj(txnobj, &txn)) { |
|
1743 FREE_DBT(key); |
|
1744 return NULL; |
|
1745 } |
|
1746 |
|
1747 CLEAR_DBT(data); |
|
1748 if (CHECK_DBFLAG(self, DB_THREAD)) { |
|
1749 /* Tell Berkeley DB to malloc the return value (thread safe) */ |
|
1750 data.flags = DB_DBT_MALLOC; |
|
1751 } |
|
1752 if (!add_partial_dbt(&data, dlen, doff)) { |
|
1753 FREE_DBT(key); |
|
1754 return NULL; |
|
1755 } |
|
1756 |
|
1757 MYDB_BEGIN_ALLOW_THREADS; |
|
1758 err = self->db->get(self->db, txn, &key, &data, flags); |
|
1759 MYDB_END_ALLOW_THREADS; |
|
1760 |
|
1761 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) { |
|
1762 err = 0; |
|
1763 Py_INCREF(dfltobj); |
|
1764 retval = dfltobj; |
|
1765 } |
|
1766 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) |
|
1767 && self->moduleFlags.getReturnsNone) { |
|
1768 err = 0; |
|
1769 Py_INCREF(Py_None); |
|
1770 retval = Py_None; |
|
1771 } |
|
1772 else if (!err) { |
|
1773 if (flags & DB_SET_RECNO) /* return both key and data */ |
|
1774 retval = BuildValue_SS(key.data, key.size, data.data, data.size); |
|
1775 else /* return just the data */ |
|
1776 retval = Build_PyString(data.data, data.size); |
|
1777 FREE_DBT(data); |
|
1778 } |
|
1779 FREE_DBT(key); |
|
1780 |
|
1781 RETURN_IF_ERR(); |
|
1782 return retval; |
|
1783 } |
|
1784 |
|
1785 static PyObject* |
|
1786 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs) |
|
1787 { |
|
1788 int err, flags=0; |
|
1789 PyObject* txnobj = NULL; |
|
1790 PyObject* keyobj; |
|
1791 PyObject* dfltobj = NULL; |
|
1792 PyObject* retval = NULL; |
|
1793 int dlen = -1; |
|
1794 int doff = -1; |
|
1795 DBT key, pkey, data; |
|
1796 DB_TXN *txn = NULL; |
|
1797 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen", |
|
1798 "doff", NULL}; |
|
1799 |
|
1800 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames, |
|
1801 &keyobj, &dfltobj, &txnobj, &flags, &dlen, |
|
1802 &doff)) |
|
1803 return NULL; |
|
1804 |
|
1805 CHECK_DB_NOT_CLOSED(self); |
|
1806 if (!make_key_dbt(self, keyobj, &key, &flags)) |
|
1807 return NULL; |
|
1808 if (!checkTxnObj(txnobj, &txn)) { |
|
1809 FREE_DBT(key); |
|
1810 return NULL; |
|
1811 } |
|
1812 |
|
1813 CLEAR_DBT(data); |
|
1814 if (CHECK_DBFLAG(self, DB_THREAD)) { |
|
1815 /* Tell Berkeley DB to malloc the return value (thread safe) */ |
|
1816 data.flags = DB_DBT_MALLOC; |
|
1817 } |
|
1818 if (!add_partial_dbt(&data, dlen, doff)) { |
|
1819 FREE_DBT(key); |
|
1820 return NULL; |
|
1821 } |
|
1822 |
|
1823 CLEAR_DBT(pkey); |
|
1824 pkey.flags = DB_DBT_MALLOC; |
|
1825 |
|
1826 MYDB_BEGIN_ALLOW_THREADS; |
|
1827 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags); |
|
1828 MYDB_END_ALLOW_THREADS; |
|
1829 |
|
1830 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) { |
|
1831 err = 0; |
|
1832 Py_INCREF(dfltobj); |
|
1833 retval = dfltobj; |
|
1834 } |
|
1835 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) |
|
1836 && self->moduleFlags.getReturnsNone) { |
|
1837 err = 0; |
|
1838 Py_INCREF(Py_None); |
|
1839 retval = Py_None; |
|
1840 } |
|
1841 else if (!err) { |
|
1842 PyObject *pkeyObj; |
|
1843 PyObject *dataObj; |
|
1844 dataObj = Build_PyString(data.data, data.size); |
|
1845 |
|
1846 if (self->primaryDBType == DB_RECNO || |
|
1847 self->primaryDBType == DB_QUEUE) |
|
1848 pkeyObj = NUMBER_FromLong(*(int *)pkey.data); |
|
1849 else |
|
1850 pkeyObj = Build_PyString(pkey.data, pkey.size); |
|
1851 |
|
1852 if (flags & DB_SET_RECNO) /* return key , pkey and data */ |
|
1853 { |
|
1854 PyObject *keyObj; |
|
1855 int type = _DB_get_type(self); |
|
1856 if (type == DB_RECNO || type == DB_QUEUE) |
|
1857 keyObj = NUMBER_FromLong(*(int *)key.data); |
|
1858 else |
|
1859 keyObj = Build_PyString(key.data, key.size); |
|
1860 #if (PY_VERSION_HEX >= 0x02040000) |
|
1861 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj); |
|
1862 #else |
|
1863 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj); |
|
1864 #endif |
|
1865 Py_DECREF(keyObj); |
|
1866 } |
|
1867 else /* return just the pkey and data */ |
|
1868 { |
|
1869 #if (PY_VERSION_HEX >= 0x02040000) |
|
1870 retval = PyTuple_Pack(2, pkeyObj, dataObj); |
|
1871 #else |
|
1872 retval = Py_BuildValue("OO", pkeyObj, dataObj); |
|
1873 #endif |
|
1874 } |
|
1875 Py_DECREF(dataObj); |
|
1876 Py_DECREF(pkeyObj); |
|
1877 FREE_DBT(pkey); |
|
1878 FREE_DBT(data); |
|
1879 } |
|
1880 FREE_DBT(key); |
|
1881 |
|
1882 RETURN_IF_ERR(); |
|
1883 return retval; |
|
1884 } |
|
1885 |
|
1886 |
|
1887 /* Return size of entry */ |
|
1888 static PyObject* |
|
1889 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs) |
|
1890 { |
|
1891 int err, flags=0; |
|
1892 PyObject* txnobj = NULL; |
|
1893 PyObject* keyobj; |
|
1894 PyObject* retval = NULL; |
|
1895 DBT key, data; |
|
1896 DB_TXN *txn = NULL; |
|
1897 static char* kwnames[] = { "key", "txn", NULL }; |
|
1898 |
|
1899 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames, |
|
1900 &keyobj, &txnobj)) |
|
1901 return NULL; |
|
1902 CHECK_DB_NOT_CLOSED(self); |
|
1903 if (!make_key_dbt(self, keyobj, &key, &flags)) |
|
1904 return NULL; |
|
1905 if (!checkTxnObj(txnobj, &txn)) { |
|
1906 FREE_DBT(key); |
|
1907 return NULL; |
|
1908 } |
|
1909 CLEAR_DBT(data); |
|
1910 |
|
1911 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and |
|
1912 thus getting the record size. */ |
|
1913 data.flags = DB_DBT_USERMEM; |
|
1914 data.ulen = 0; |
|
1915 MYDB_BEGIN_ALLOW_THREADS; |
|
1916 err = self->db->get(self->db, txn, &key, &data, flags); |
|
1917 MYDB_END_ALLOW_THREADS; |
|
1918 if (err == DB_BUFFER_SMALL) { |
|
1919 retval = NUMBER_FromLong((long)data.size); |
|
1920 err = 0; |
|
1921 } |
|
1922 |
|
1923 FREE_DBT(key); |
|
1924 FREE_DBT(data); |
|
1925 RETURN_IF_ERR(); |
|
1926 return retval; |
|
1927 } |
|
1928 |
|
1929 |
|
1930 static PyObject* |
|
1931 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs) |
|
1932 { |
|
1933 int err, flags=0; |
|
1934 PyObject* txnobj = NULL; |
|
1935 PyObject* keyobj; |
|
1936 PyObject* dataobj; |
|
1937 PyObject* retval = NULL; |
|
1938 DBT key, data; |
|
1939 void *orig_data; |
|
1940 DB_TXN *txn = NULL; |
|
1941 static char* kwnames[] = { "key", "data", "txn", "flags", NULL }; |
|
1942 |
|
1943 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames, |
|
1944 &keyobj, &dataobj, &txnobj, &flags)) |
|
1945 return NULL; |
|
1946 |
|
1947 CHECK_DB_NOT_CLOSED(self); |
|
1948 if (!make_key_dbt(self, keyobj, &key, NULL)) |
|
1949 return NULL; |
|
1950 if ( !make_dbt(dataobj, &data) || |
|
1951 !checkTxnObj(txnobj, &txn) ) |
|
1952 { |
|
1953 FREE_DBT(key); |
|
1954 return NULL; |
|
1955 } |
|
1956 |
|
1957 flags |= DB_GET_BOTH; |
|
1958 orig_data = data.data; |
|
1959 |
|
1960 if (CHECK_DBFLAG(self, DB_THREAD)) { |
|
1961 /* Tell Berkeley DB to malloc the return value (thread safe) */ |
|
1962 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */ |
|
1963 data.flags = DB_DBT_MALLOC; |
|
1964 } |
|
1965 |
|
1966 MYDB_BEGIN_ALLOW_THREADS; |
|
1967 err = self->db->get(self->db, txn, &key, &data, flags); |
|
1968 MYDB_END_ALLOW_THREADS; |
|
1969 |
|
1970 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) |
|
1971 && self->moduleFlags.getReturnsNone) { |
|
1972 err = 0; |
|
1973 Py_INCREF(Py_None); |
|
1974 retval = Py_None; |
|
1975 } |
|
1976 else if (!err) { |
|
1977 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */ |
|
1978 retval = Build_PyString(data.data, data.size); |
|
1979 |
|
1980 /* Even though the flags require DB_DBT_MALLOC, data is not always |
|
1981 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */ |
|
1982 if (data.data != orig_data) |
|
1983 FREE_DBT(data); |
|
1984 } |
|
1985 |
|
1986 FREE_DBT(key); |
|
1987 RETURN_IF_ERR(); |
|
1988 return retval; |
|
1989 } |
|
1990 |
|
1991 |
|
1992 static PyObject* |
|
1993 DB_get_byteswapped(DBObject* self) |
|
1994 { |
|
1995 int err = 0; |
|
1996 int retval = -1; |
|
1997 |
|
1998 CHECK_DB_NOT_CLOSED(self); |
|
1999 |
|
2000 MYDB_BEGIN_ALLOW_THREADS; |
|
2001 err = self->db->get_byteswapped(self->db, &retval); |
|
2002 MYDB_END_ALLOW_THREADS; |
|
2003 RETURN_IF_ERR(); |
|
2004 return NUMBER_FromLong(retval); |
|
2005 } |
|
2006 |
|
2007 |
|
2008 static PyObject* |
|
2009 DB_get_type(DBObject* self) |
|
2010 { |
|
2011 int type; |
|
2012 |
|
2013 CHECK_DB_NOT_CLOSED(self); |
|
2014 |
|
2015 type = _DB_get_type(self); |
|
2016 if (type == -1) |
|
2017 return NULL; |
|
2018 return NUMBER_FromLong(type); |
|
2019 } |
|
2020 |
|
2021 |
|
2022 static PyObject* |
|
2023 DB_join(DBObject* self, PyObject* args) |
|
2024 { |
|
2025 int err, flags=0; |
|
2026 int length, x; |
|
2027 PyObject* cursorsObj; |
|
2028 DBC** cursors; |
|
2029 DBC* dbc; |
|
2030 |
|
2031 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags)) |
|
2032 return NULL; |
|
2033 |
|
2034 CHECK_DB_NOT_CLOSED(self); |
|
2035 |
|
2036 if (!PySequence_Check(cursorsObj)) { |
|
2037 PyErr_SetString(PyExc_TypeError, |
|
2038 "Sequence of DBCursor objects expected"); |
|
2039 return NULL; |
|
2040 } |
|
2041 |
|
2042 length = PyObject_Length(cursorsObj); |
|
2043 cursors = malloc((length+1) * sizeof(DBC*)); |
|
2044 if (!cursors) { |
|
2045 PyErr_NoMemory(); |
|
2046 return NULL; |
|
2047 } |
|
2048 |
|
2049 cursors[length] = NULL; |
|
2050 for (x=0; x<length; x++) { |
|
2051 PyObject* item = PySequence_GetItem(cursorsObj, x); |
|
2052 if (item == NULL) { |
|
2053 free(cursors); |
|
2054 return NULL; |
|
2055 } |
|
2056 if (!DBCursorObject_Check(item)) { |
|
2057 PyErr_SetString(PyExc_TypeError, |
|
2058 "Sequence of DBCursor objects expected"); |
|
2059 free(cursors); |
|
2060 return NULL; |
|
2061 } |
|
2062 cursors[x] = ((DBCursorObject*)item)->dbc; |
|
2063 Py_DECREF(item); |
|
2064 } |
|
2065 |
|
2066 MYDB_BEGIN_ALLOW_THREADS; |
|
2067 err = self->db->join(self->db, cursors, &dbc, flags); |
|
2068 MYDB_END_ALLOW_THREADS; |
|
2069 free(cursors); |
|
2070 RETURN_IF_ERR(); |
|
2071 |
|
2072 /* FIXME: this is a buggy interface. The returned cursor |
|
2073 contains internal references to the passed in cursors |
|
2074 but does not hold python references to them or prevent |
|
2075 them from being closed prematurely. This can cause |
|
2076 python to crash when things are done in the wrong order. */ |
|
2077 return (PyObject*) newDBCursorObject(dbc, NULL, self); |
|
2078 } |
|
2079 |
|
2080 |
|
2081 static PyObject* |
|
2082 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs) |
|
2083 { |
|
2084 int err, flags=0; |
|
2085 PyObject* txnobj = NULL; |
|
2086 PyObject* keyobj; |
|
2087 DBT key; |
|
2088 DB_TXN *txn = NULL; |
|
2089 DB_KEY_RANGE range; |
|
2090 static char* kwnames[] = { "key", "txn", "flags", NULL }; |
|
2091 |
|
2092 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames, |
|
2093 &keyobj, &txnobj, &flags)) |
|
2094 return NULL; |
|
2095 CHECK_DB_NOT_CLOSED(self); |
|
2096 if (!make_dbt(keyobj, &key)) |
|
2097 /* BTree only, don't need to allow for an int key */ |
|
2098 return NULL; |
|
2099 if (!checkTxnObj(txnobj, &txn)) |
|
2100 return NULL; |
|
2101 |
|
2102 MYDB_BEGIN_ALLOW_THREADS; |
|
2103 err = self->db->key_range(self->db, txn, &key, &range, flags); |
|
2104 MYDB_END_ALLOW_THREADS; |
|
2105 |
|
2106 RETURN_IF_ERR(); |
|
2107 return Py_BuildValue("ddd", range.less, range.equal, range.greater); |
|
2108 } |
|
2109 |
|
2110 |
|
2111 static PyObject* |
|
2112 DB_open(DBObject* self, PyObject* args, PyObject* kwargs) |
|
2113 { |
|
2114 int err, type = DB_UNKNOWN, flags=0, mode=0660; |
|
2115 char* filename = NULL; |
|
2116 char* dbname = NULL; |
|
2117 #if (DBVER >= 41) |
|
2118 PyObject *txnobj = NULL; |
|
2119 DB_TXN *txn = NULL; |
|
2120 /* with dbname */ |
|
2121 static char* kwnames[] = { |
|
2122 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL}; |
|
2123 /* without dbname */ |
|
2124 static char* kwnames_basic[] = { |
|
2125 "filename", "dbtype", "flags", "mode", "txn", NULL}; |
|
2126 #else |
|
2127 /* with dbname */ |
|
2128 static char* kwnames[] = { |
|
2129 "filename", "dbname", "dbtype", "flags", "mode", NULL}; |
|
2130 /* without dbname */ |
|
2131 static char* kwnames_basic[] = { |
|
2132 "filename", "dbtype", "flags", "mode", NULL}; |
|
2133 #endif |
|
2134 |
|
2135 #if (DBVER >= 41) |
|
2136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames, |
|
2137 &filename, &dbname, &type, &flags, &mode, |
|
2138 &txnobj)) |
|
2139 #else |
|
2140 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames, |
|
2141 &filename, &dbname, &type, &flags, |
|
2142 &mode)) |
|
2143 #endif |
|
2144 { |
|
2145 PyErr_Clear(); |
|
2146 type = DB_UNKNOWN; flags = 0; mode = 0660; |
|
2147 filename = NULL; dbname = NULL; |
|
2148 #if (DBVER >= 41) |
|
2149 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open", |
|
2150 kwnames_basic, |
|
2151 &filename, &type, &flags, &mode, |
|
2152 &txnobj)) |
|
2153 return NULL; |
|
2154 #else |
|
2155 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open", |
|
2156 kwnames_basic, |
|
2157 &filename, &type, &flags, &mode)) |
|
2158 return NULL; |
|
2159 #endif |
|
2160 } |
|
2161 |
|
2162 #if (DBVER >= 41) |
|
2163 if (!checkTxnObj(txnobj, &txn)) return NULL; |
|
2164 #endif |
|
2165 |
|
2166 if (NULL == self->db) { |
|
2167 PyObject *t = Py_BuildValue("(is)", 0, |
|
2168 "Cannot call open() twice for DB object"); |
|
2169 if (t) { |
|
2170 PyErr_SetObject(DBError, t); |
|
2171 Py_DECREF(t); |
|
2172 } |
|
2173 return NULL; |
|
2174 } |
|
2175 |
|
2176 #if (DBVER >= 41) |
|
2177 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */ |
|
2178 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self); |
|
2179 self->txn=(DBTxnObject *)txnobj; |
|
2180 } else { |
|
2181 self->txn=NULL; |
|
2182 } |
|
2183 #else |
|
2184 self->txn=NULL; |
|
2185 #endif |
|
2186 |
|
2187 MYDB_BEGIN_ALLOW_THREADS; |
|
2188 #if (DBVER >= 41) |
|
2189 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode); |
|
2190 #else |
|
2191 err = self->db->open(self->db, filename, dbname, type, flags, mode); |
|
2192 #endif |
|
2193 MYDB_END_ALLOW_THREADS; |
|
2194 if (makeDBError(err)) { |
|
2195 PyObject *dummy; |
|
2196 |
|
2197 dummy=DB_close_internal(self, 0, 0); |
|
2198 Py_XDECREF(dummy); |
|
2199 return NULL; |
|
2200 } |
|
2201 |
|
2202 #if (DBVER >= 42) |
|
2203 self->db->get_flags(self->db, &self->setflags); |
|
2204 #endif |
|
2205 |
|
2206 self->flags = flags; |
|
2207 |
|
2208 RETURN_NONE(); |
|
2209 } |
|
2210 |
|
2211 |
|
2212 static PyObject* |
|
2213 DB_put(DBObject* self, PyObject* args, PyObject* kwargs) |
|
2214 { |
|
2215 int flags=0; |
|
2216 PyObject* txnobj = NULL; |
|
2217 int dlen = -1; |
|
2218 int doff = -1; |
|
2219 PyObject* keyobj, *dataobj, *retval; |
|
2220 DBT key, data; |
|
2221 DB_TXN *txn = NULL; |
|
2222 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen", |
|
2223 "doff", NULL }; |
|
2224 |
|
2225 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames, |
|
2226 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff)) |
|
2227 return NULL; |
|
2228 |
|
2229 CHECK_DB_NOT_CLOSED(self); |
|
2230 if (!make_key_dbt(self, keyobj, &key, NULL)) |
|
2231 return NULL; |
|
2232 if ( !make_dbt(dataobj, &data) || |
|
2233 !add_partial_dbt(&data, dlen, doff) || |
|
2234 !checkTxnObj(txnobj, &txn) ) |
|
2235 { |
|
2236 FREE_DBT(key); |
|
2237 return NULL; |
|
2238 } |
|
2239 |
|
2240 if (-1 == _DB_put(self, txn, &key, &data, flags)) { |
|
2241 FREE_DBT(key); |
|
2242 return NULL; |
|
2243 } |
|
2244 |
|
2245 if (flags & DB_APPEND) |
|
2246 retval = NUMBER_FromLong(*((db_recno_t*)key.data)); |
|
2247 else { |
|
2248 retval = Py_None; |
|
2249 Py_INCREF(retval); |
|
2250 } |
|
2251 FREE_DBT(key); |
|
2252 return retval; |
|
2253 } |
|
2254 |
|
2255 |
|
2256 |
|
2257 static PyObject* |
|
2258 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs) |
|
2259 { |
|
2260 char* filename; |
|
2261 char* database = NULL; |
|
2262 int err, flags=0; |
|
2263 static char* kwnames[] = { "filename", "dbname", "flags", NULL}; |
|
2264 |
|
2265 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames, |
|
2266 &filename, &database, &flags)) |
|
2267 return NULL; |
|
2268 CHECK_DB_NOT_CLOSED(self); |
|
2269 |
|
2270 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self); |
|
2271 |
|
2272 MYDB_BEGIN_ALLOW_THREADS; |
|
2273 err = self->db->remove(self->db, filename, database, flags); |
|
2274 MYDB_END_ALLOW_THREADS; |
|
2275 |
|
2276 self->db = NULL; |
|
2277 RETURN_IF_ERR(); |
|
2278 RETURN_NONE(); |
|
2279 } |
|
2280 |
|
2281 |
|
2282 |
|
2283 static PyObject* |
|
2284 DB_rename(DBObject* self, PyObject* args) |
|
2285 { |
|
2286 char* filename; |
|
2287 char* database; |
|
2288 char* newname; |
|
2289 int err, flags=0; |
|
2290 |
|
2291 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname, |
|
2292 &flags)) |
|
2293 return NULL; |
|
2294 CHECK_DB_NOT_CLOSED(self); |
|
2295 |
|
2296 MYDB_BEGIN_ALLOW_THREADS; |
|
2297 err = self->db->rename(self->db, filename, database, newname, flags); |
|
2298 MYDB_END_ALLOW_THREADS; |
|
2299 RETURN_IF_ERR(); |
|
2300 RETURN_NONE(); |
|
2301 } |
|
2302 |
|
2303 |
|
2304 static PyObject* |
|
2305 DB_get_private(DBObject* self) |
|
2306 { |
|
2307 /* We can give out the private field even if db is closed */ |
|
2308 Py_INCREF(self->private_obj); |
|
2309 return self->private_obj; |
|
2310 } |
|
2311 |
|
2312 static PyObject* |
|
2313 DB_set_private(DBObject* self, PyObject* private_obj) |
|
2314 { |
|
2315 /* We can set the private field even if db is closed */ |
|
2316 Py_DECREF(self->private_obj); |
|
2317 Py_INCREF(private_obj); |
|
2318 self->private_obj = private_obj; |
|
2319 RETURN_NONE(); |
|
2320 } |
|
2321 |
|
2322 |
|
2323 static PyObject* |
|
2324 DB_set_bt_minkey(DBObject* self, PyObject* args) |
|
2325 { |
|
2326 int err, minkey; |
|
2327 |
|
2328 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey )) |
|
2329 return NULL; |
|
2330 CHECK_DB_NOT_CLOSED(self); |
|
2331 |
|
2332 MYDB_BEGIN_ALLOW_THREADS; |
|
2333 err = self->db->set_bt_minkey(self->db, minkey); |
|
2334 MYDB_END_ALLOW_THREADS; |
|
2335 RETURN_IF_ERR(); |
|
2336 RETURN_NONE(); |
|
2337 } |
|
2338 |
|
2339 static int |
|
2340 _default_cmp(const DBT *leftKey, |
|
2341 const DBT *rightKey) |
|
2342 { |
|
2343 int res; |
|
2344 int lsize = leftKey->size, rsize = rightKey->size; |
|
2345 |
|
2346 res = memcmp(leftKey->data, rightKey->data, |
|
2347 lsize < rsize ? lsize : rsize); |
|
2348 |
|
2349 if (res == 0) { |
|
2350 if (lsize < rsize) { |
|
2351 res = -1; |
|
2352 } |
|
2353 else if (lsize > rsize) { |
|
2354 res = 1; |
|
2355 } |
|
2356 } |
|
2357 return res; |
|
2358 } |
|
2359 |
|
2360 static int |
|
2361 _db_compareCallback(DB* db, |
|
2362 const DBT *leftKey, |
|
2363 const DBT *rightKey) |
|
2364 { |
|
2365 int res = 0; |
|
2366 PyObject *args; |
|
2367 PyObject *result = NULL; |
|
2368 DBObject *self = (DBObject *)db->app_private; |
|
2369 |
|
2370 if (self == NULL || self->btCompareCallback == NULL) { |
|
2371 MYDB_BEGIN_BLOCK_THREADS; |
|
2372 PyErr_SetString(PyExc_TypeError, |
|
2373 (self == 0 |
|
2374 ? "DB_bt_compare db is NULL." |
|
2375 : "DB_bt_compare callback is NULL.")); |
|
2376 /* we're in a callback within the DB code, we can't raise */ |
|
2377 PyErr_Print(); |
|
2378 res = _default_cmp(leftKey, rightKey); |
|
2379 MYDB_END_BLOCK_THREADS; |
|
2380 } else { |
|
2381 MYDB_BEGIN_BLOCK_THREADS; |
|
2382 |
|
2383 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size); |
|
2384 if (args != NULL) { |
|
2385 /* XXX(twouters) I highly doubt this INCREF is correct */ |
|
2386 Py_INCREF(self); |
|
2387 result = PyEval_CallObject(self->btCompareCallback, args); |
|
2388 } |
|
2389 if (args == NULL || result == NULL) { |
|
2390 /* we're in a callback within the DB code, we can't raise */ |
|
2391 PyErr_Print(); |
|
2392 res = _default_cmp(leftKey, rightKey); |
|
2393 } else if (NUMBER_Check(result)) { |
|
2394 res = NUMBER_AsLong(result); |
|
2395 } else { |
|
2396 PyErr_SetString(PyExc_TypeError, |
|
2397 "DB_bt_compare callback MUST return an int."); |
|
2398 /* we're in a callback within the DB code, we can't raise */ |
|
2399 PyErr_Print(); |
|
2400 res = _default_cmp(leftKey, rightKey); |
|
2401 } |
|
2402 |
|
2403 Py_XDECREF(args); |
|
2404 Py_XDECREF(result); |
|
2405 |
|
2406 MYDB_END_BLOCK_THREADS; |
|
2407 } |
|
2408 return res; |
|
2409 } |
|
2410 |
|
2411 static PyObject* |
|
2412 DB_set_bt_compare(DBObject* self, PyObject* comparator) |
|
2413 { |
|
2414 int err; |
|
2415 PyObject *tuple, *result; |
|
2416 |
|
2417 CHECK_DB_NOT_CLOSED(self); |
|
2418 |
|
2419 if (!PyCallable_Check(comparator)) { |
|
2420 makeTypeError("Callable", comparator); |
|
2421 return NULL; |
|
2422 } |
|
2423 |
|
2424 /* |
|
2425 * Perform a test call of the comparator function with two empty |
|
2426 * string objects here. verify that it returns an int (0). |
|
2427 * err if not. |
|
2428 */ |
|
2429 tuple = Py_BuildValue("(ss)", "", ""); |
|
2430 result = PyEval_CallObject(comparator, tuple); |
|
2431 Py_DECREF(tuple); |
|
2432 if (result == NULL) |
|
2433 return NULL; |
|
2434 if (!NUMBER_Check(result)) { |
|
2435 PyErr_SetString(PyExc_TypeError, |
|
2436 "callback MUST return an int"); |
|
2437 return NULL; |
|
2438 } else if (NUMBER_AsLong(result) != 0) { |
|
2439 PyErr_SetString(PyExc_TypeError, |
|
2440 "callback failed to return 0 on two empty strings"); |
|
2441 return NULL; |
|
2442 } |
|
2443 Py_DECREF(result); |
|
2444 |
|
2445 /* We don't accept multiple set_bt_compare operations, in order to |
|
2446 * simplify the code. This would have no real use, as one cannot |
|
2447 * change the function once the db is opened anyway */ |
|
2448 if (self->btCompareCallback != NULL) { |
|
2449 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once"); |
|
2450 return NULL; |
|
2451 } |
|
2452 |
|
2453 Py_INCREF(comparator); |
|
2454 self->btCompareCallback = comparator; |
|
2455 |
|
2456 /* This is to workaround a problem with un-initialized threads (see |
|
2457 comment in DB_associate) */ |
|
2458 #ifdef WITH_THREAD |
|
2459 PyEval_InitThreads(); |
|
2460 #endif |
|
2461 |
|
2462 err = self->db->set_bt_compare(self->db, _db_compareCallback); |
|
2463 |
|
2464 if (err) { |
|
2465 /* restore the old state in case of error */ |
|
2466 Py_DECREF(comparator); |
|
2467 self->btCompareCallback = NULL; |
|
2468 } |
|
2469 |
|
2470 RETURN_IF_ERR(); |
|
2471 RETURN_NONE(); |
|
2472 } |
|
2473 |
|
2474 |
|
2475 static PyObject* |
|
2476 DB_set_cachesize(DBObject* self, PyObject* args) |
|
2477 { |
|
2478 int err; |
|
2479 int gbytes = 0, bytes = 0, ncache = 0; |
|
2480 |
|
2481 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize", |
|
2482 &gbytes,&bytes,&ncache)) |
|
2483 return NULL; |
|
2484 CHECK_DB_NOT_CLOSED(self); |
|
2485 |
|
2486 MYDB_BEGIN_ALLOW_THREADS; |
|
2487 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache); |
|
2488 MYDB_END_ALLOW_THREADS; |
|
2489 RETURN_IF_ERR(); |
|
2490 RETURN_NONE(); |
|
2491 } |
|
2492 |
|
2493 |
|
2494 static PyObject* |
|
2495 DB_set_flags(DBObject* self, PyObject* args) |
|
2496 { |
|
2497 int err, flags; |
|
2498 |
|
2499 if (!PyArg_ParseTuple(args,"i:set_flags", &flags)) |
|
2500 return NULL; |
|
2501 CHECK_DB_NOT_CLOSED(self); |
|
2502 |
|
2503 MYDB_BEGIN_ALLOW_THREADS; |
|
2504 err = self->db->set_flags(self->db, flags); |
|
2505 MYDB_END_ALLOW_THREADS; |
|
2506 RETURN_IF_ERR(); |
|
2507 |
|
2508 self->setflags |= flags; |
|
2509 RETURN_NONE(); |
|
2510 } |
|
2511 |
|
2512 |
|
2513 static PyObject* |
|
2514 DB_set_h_ffactor(DBObject* self, PyObject* args) |
|
2515 { |
|
2516 int err, ffactor; |
|
2517 |
|
2518 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor)) |
|
2519 return NULL; |
|
2520 CHECK_DB_NOT_CLOSED(self); |
|
2521 |
|
2522 MYDB_BEGIN_ALLOW_THREADS; |
|
2523 err = self->db->set_h_ffactor(self->db, ffactor); |
|
2524 MYDB_END_ALLOW_THREADS; |
|
2525 RETURN_IF_ERR(); |
|
2526 RETURN_NONE(); |
|
2527 } |
|
2528 |
|
2529 |
|
2530 static PyObject* |
|
2531 DB_set_h_nelem(DBObject* self, PyObject* args) |
|
2532 { |
|
2533 int err, nelem; |
|
2534 |
|
2535 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem)) |
|
2536 return NULL; |
|
2537 CHECK_DB_NOT_CLOSED(self); |
|
2538 |
|
2539 MYDB_BEGIN_ALLOW_THREADS; |
|
2540 err = self->db->set_h_nelem(self->db, nelem); |
|
2541 MYDB_END_ALLOW_THREADS; |
|
2542 RETURN_IF_ERR(); |
|
2543 RETURN_NONE(); |
|
2544 } |
|
2545 |
|
2546 |
|
2547 static PyObject* |
|
2548 DB_set_lorder(DBObject* self, PyObject* args) |
|
2549 { |
|
2550 int err, lorder; |
|
2551 |
|
2552 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder)) |
|
2553 return NULL; |
|
2554 CHECK_DB_NOT_CLOSED(self); |
|
2555 |
|
2556 MYDB_BEGIN_ALLOW_THREADS; |
|
2557 err = self->db->set_lorder(self->db, lorder); |
|
2558 MYDB_END_ALLOW_THREADS; |
|
2559 RETURN_IF_ERR(); |
|
2560 RETURN_NONE(); |
|
2561 } |
|
2562 |
|
2563 |
|
2564 static PyObject* |
|
2565 DB_set_pagesize(DBObject* self, PyObject* args) |
|
2566 { |
|
2567 int err, pagesize; |
|
2568 |
|
2569 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize)) |
|
2570 return NULL; |
|
2571 CHECK_DB_NOT_CLOSED(self); |
|
2572 |
|
2573 MYDB_BEGIN_ALLOW_THREADS; |
|
2574 err = self->db->set_pagesize(self->db, pagesize); |
|
2575 MYDB_END_ALLOW_THREADS; |
|
2576 RETURN_IF_ERR(); |
|
2577 RETURN_NONE(); |
|
2578 } |
|
2579 |
|
2580 |
|
2581 static PyObject* |
|
2582 DB_set_re_delim(DBObject* self, PyObject* args) |
|
2583 { |
|
2584 int err; |
|
2585 char delim; |
|
2586 |
|
2587 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) { |
|
2588 PyErr_Clear(); |
|
2589 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim)) |
|
2590 return NULL; |
|
2591 } |
|
2592 |
|
2593 CHECK_DB_NOT_CLOSED(self); |
|
2594 |
|
2595 MYDB_BEGIN_ALLOW_THREADS; |
|
2596 err = self->db->set_re_delim(self->db, delim); |
|
2597 MYDB_END_ALLOW_THREADS; |
|
2598 RETURN_IF_ERR(); |
|
2599 RETURN_NONE(); |
|
2600 } |
|
2601 |
|
2602 static PyObject* |
|
2603 DB_set_re_len(DBObject* self, PyObject* args) |
|
2604 { |
|
2605 int err, len; |
|
2606 |
|
2607 if (!PyArg_ParseTuple(args,"i:set_re_len", &len)) |
|
2608 return NULL; |
|
2609 CHECK_DB_NOT_CLOSED(self); |
|
2610 |
|
2611 MYDB_BEGIN_ALLOW_THREADS; |
|
2612 err = self->db->set_re_len(self->db, len); |
|
2613 MYDB_END_ALLOW_THREADS; |
|
2614 RETURN_IF_ERR(); |
|
2615 RETURN_NONE(); |
|
2616 } |
|
2617 |
|
2618 |
|
2619 static PyObject* |
|
2620 DB_set_re_pad(DBObject* self, PyObject* args) |
|
2621 { |
|
2622 int err; |
|
2623 char pad; |
|
2624 |
|
2625 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) { |
|
2626 PyErr_Clear(); |
|
2627 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad)) |
|
2628 return NULL; |
|
2629 } |
|
2630 CHECK_DB_NOT_CLOSED(self); |
|
2631 |
|
2632 MYDB_BEGIN_ALLOW_THREADS; |
|
2633 err = self->db->set_re_pad(self->db, pad); |
|
2634 MYDB_END_ALLOW_THREADS; |
|
2635 RETURN_IF_ERR(); |
|
2636 RETURN_NONE(); |
|
2637 } |
|
2638 |
|
2639 |
|
2640 static PyObject* |
|
2641 DB_set_re_source(DBObject* self, PyObject* args) |
|
2642 { |
|
2643 int err; |
|
2644 char *re_source; |
|
2645 |
|
2646 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source)) |
|
2647 return NULL; |
|
2648 CHECK_DB_NOT_CLOSED(self); |
|
2649 |
|
2650 MYDB_BEGIN_ALLOW_THREADS; |
|
2651 err = self->db->set_re_source(self->db, re_source); |
|
2652 MYDB_END_ALLOW_THREADS; |
|
2653 RETURN_IF_ERR(); |
|
2654 RETURN_NONE(); |
|
2655 } |
|
2656 |
|
2657 |
|
2658 static PyObject* |
|
2659 DB_set_q_extentsize(DBObject* self, PyObject* args) |
|
2660 { |
|
2661 int err; |
|
2662 int extentsize; |
|
2663 |
|
2664 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize)) |
|
2665 return NULL; |
|
2666 CHECK_DB_NOT_CLOSED(self); |
|
2667 |
|
2668 MYDB_BEGIN_ALLOW_THREADS; |
|
2669 err = self->db->set_q_extentsize(self->db, extentsize); |
|
2670 MYDB_END_ALLOW_THREADS; |
|
2671 RETURN_IF_ERR(); |
|
2672 RETURN_NONE(); |
|
2673 } |
|
2674 |
|
2675 static PyObject* |
|
2676 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs) |
|
2677 { |
|
2678 int err, flags = 0, type; |
|
2679 void* sp; |
|
2680 PyObject* d; |
|
2681 #if (DBVER >= 43) |
|
2682 PyObject* txnobj = NULL; |
|
2683 DB_TXN *txn = NULL; |
|
2684 static char* kwnames[] = { "flags", "txn", NULL }; |
|
2685 #else |
|
2686 static char* kwnames[] = { "flags", NULL }; |
|
2687 #endif |
|
2688 |
|
2689 #if (DBVER >= 43) |
|
2690 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames, |
|
2691 &flags, &txnobj)) |
|
2692 return NULL; |
|
2693 if (!checkTxnObj(txnobj, &txn)) |
|
2694 return NULL; |
|
2695 #else |
|
2696 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags)) |
|
2697 return NULL; |
|
2698 #endif |
|
2699 CHECK_DB_NOT_CLOSED(self); |
|
2700 |
|
2701 MYDB_BEGIN_ALLOW_THREADS; |
|
2702 #if (DBVER >= 43) |
|
2703 err = self->db->stat(self->db, txn, &sp, flags); |
|
2704 #else |
|
2705 err = self->db->stat(self->db, &sp, flags); |
|
2706 #endif |
|
2707 MYDB_END_ALLOW_THREADS; |
|
2708 RETURN_IF_ERR(); |
|
2709 |
|
2710 self->haveStat = 1; |
|
2711 |
|
2712 /* Turn the stat structure into a dictionary */ |
|
2713 type = _DB_get_type(self); |
|
2714 if ((type == -1) || ((d = PyDict_New()) == NULL)) { |
|
2715 free(sp); |
|
2716 return NULL; |
|
2717 } |
|
2718 |
|
2719 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name) |
|
2720 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name) |
|
2721 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name) |
|
2722 |
|
2723 switch (type) { |
|
2724 case DB_HASH: |
|
2725 MAKE_HASH_ENTRY(magic); |
|
2726 MAKE_HASH_ENTRY(version); |
|
2727 MAKE_HASH_ENTRY(nkeys); |
|
2728 MAKE_HASH_ENTRY(ndata); |
|
2729 #if (DBVER >= 46) |
|
2730 MAKE_HASH_ENTRY(pagecnt); |
|
2731 #endif |
|
2732 MAKE_HASH_ENTRY(pagesize); |
|
2733 #if (DBVER < 41) |
|
2734 MAKE_HASH_ENTRY(nelem); |
|
2735 #endif |
|
2736 MAKE_HASH_ENTRY(ffactor); |
|
2737 MAKE_HASH_ENTRY(buckets); |
|
2738 MAKE_HASH_ENTRY(free); |
|
2739 MAKE_HASH_ENTRY(bfree); |
|
2740 MAKE_HASH_ENTRY(bigpages); |
|
2741 MAKE_HASH_ENTRY(big_bfree); |
|
2742 MAKE_HASH_ENTRY(overflows); |
|
2743 MAKE_HASH_ENTRY(ovfl_free); |
|
2744 MAKE_HASH_ENTRY(dup); |
|
2745 MAKE_HASH_ENTRY(dup_free); |
|
2746 break; |
|
2747 |
|
2748 case DB_BTREE: |
|
2749 case DB_RECNO: |
|
2750 MAKE_BT_ENTRY(magic); |
|
2751 MAKE_BT_ENTRY(version); |
|
2752 MAKE_BT_ENTRY(nkeys); |
|
2753 MAKE_BT_ENTRY(ndata); |
|
2754 #if (DBVER >= 46) |
|
2755 MAKE_BT_ENTRY(pagecnt); |
|
2756 #endif |
|
2757 MAKE_BT_ENTRY(pagesize); |
|
2758 MAKE_BT_ENTRY(minkey); |
|
2759 MAKE_BT_ENTRY(re_len); |
|
2760 MAKE_BT_ENTRY(re_pad); |
|
2761 MAKE_BT_ENTRY(levels); |
|
2762 MAKE_BT_ENTRY(int_pg); |
|
2763 MAKE_BT_ENTRY(leaf_pg); |
|
2764 MAKE_BT_ENTRY(dup_pg); |
|
2765 MAKE_BT_ENTRY(over_pg); |
|
2766 #if (DBVER >= 43) |
|
2767 MAKE_BT_ENTRY(empty_pg); |
|
2768 #endif |
|
2769 MAKE_BT_ENTRY(free); |
|
2770 MAKE_BT_ENTRY(int_pgfree); |
|
2771 MAKE_BT_ENTRY(leaf_pgfree); |
|
2772 MAKE_BT_ENTRY(dup_pgfree); |
|
2773 MAKE_BT_ENTRY(over_pgfree); |
|
2774 break; |
|
2775 |
|
2776 case DB_QUEUE: |
|
2777 MAKE_QUEUE_ENTRY(magic); |
|
2778 MAKE_QUEUE_ENTRY(version); |
|
2779 MAKE_QUEUE_ENTRY(nkeys); |
|
2780 MAKE_QUEUE_ENTRY(ndata); |
|
2781 MAKE_QUEUE_ENTRY(pagesize); |
|
2782 #if (DBVER >= 41) |
|
2783 MAKE_QUEUE_ENTRY(extentsize); |
|
2784 #endif |
|
2785 MAKE_QUEUE_ENTRY(pages); |
|
2786 MAKE_QUEUE_ENTRY(re_len); |
|
2787 MAKE_QUEUE_ENTRY(re_pad); |
|
2788 MAKE_QUEUE_ENTRY(pgfree); |
|
2789 #if (DBVER == 31) |
|
2790 MAKE_QUEUE_ENTRY(start); |
|
2791 #endif |
|
2792 MAKE_QUEUE_ENTRY(first_recno); |
|
2793 MAKE_QUEUE_ENTRY(cur_recno); |
|
2794 break; |
|
2795 |
|
2796 default: |
|
2797 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat"); |
|
2798 Py_DECREF(d); |
|
2799 d = NULL; |
|
2800 } |
|
2801 |
|
2802 #undef MAKE_HASH_ENTRY |
|
2803 #undef MAKE_BT_ENTRY |
|
2804 #undef MAKE_QUEUE_ENTRY |
|
2805 |
|
2806 free(sp); |
|
2807 return d; |
|
2808 } |
|
2809 |
|
2810 static PyObject* |
|
2811 DB_sync(DBObject* self, PyObject* args) |
|
2812 { |
|
2813 int err; |
|
2814 int flags = 0; |
|
2815 |
|
2816 if (!PyArg_ParseTuple(args,"|i:sync", &flags )) |
|
2817 return NULL; |
|
2818 CHECK_DB_NOT_CLOSED(self); |
|
2819 |
|
2820 MYDB_BEGIN_ALLOW_THREADS; |
|
2821 err = self->db->sync(self->db, flags); |
|
2822 MYDB_END_ALLOW_THREADS; |
|
2823 RETURN_IF_ERR(); |
|
2824 RETURN_NONE(); |
|
2825 } |
|
2826 |
|
2827 |
|
2828 static PyObject* |
|
2829 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs) |
|
2830 { |
|
2831 int err, flags=0; |
|
2832 u_int32_t count=0; |
|
2833 PyObject* txnobj = NULL; |
|
2834 DB_TXN *txn = NULL; |
|
2835 static char* kwnames[] = { "txn", "flags", NULL }; |
|
2836 |
|
2837 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames, |
|
2838 &txnobj, &flags)) |
|
2839 return NULL; |
|
2840 CHECK_DB_NOT_CLOSED(self); |
|
2841 if (!checkTxnObj(txnobj, &txn)) |
|
2842 return NULL; |
|
2843 |
|
2844 MYDB_BEGIN_ALLOW_THREADS; |
|
2845 err = self->db->truncate(self->db, txn, &count, flags); |
|
2846 MYDB_END_ALLOW_THREADS; |
|
2847 RETURN_IF_ERR(); |
|
2848 return NUMBER_FromLong(count); |
|
2849 } |
|
2850 |
|
2851 |
|
2852 static PyObject* |
|
2853 DB_upgrade(DBObject* self, PyObject* args) |
|
2854 { |
|
2855 int err, flags=0; |
|
2856 char *filename; |
|
2857 |
|
2858 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags)) |
|
2859 return NULL; |
|
2860 CHECK_DB_NOT_CLOSED(self); |
|
2861 |
|
2862 MYDB_BEGIN_ALLOW_THREADS; |
|
2863 err = self->db->upgrade(self->db, filename, flags); |
|
2864 MYDB_END_ALLOW_THREADS; |
|
2865 RETURN_IF_ERR(); |
|
2866 RETURN_NONE(); |
|
2867 } |
|
2868 |
|
2869 |
|
2870 static PyObject* |
|
2871 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs) |
|
2872 { |
|
2873 int err, flags=0; |
|
2874 char* fileName; |
|
2875 char* dbName=NULL; |
|
2876 char* outFileName=NULL; |
|
2877 FILE* outFile=NULL; |
|
2878 static char* kwnames[] = { "filename", "dbname", "outfile", "flags", |
|
2879 NULL }; |
|
2880 |
|
2881 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames, |
|
2882 &fileName, &dbName, &outFileName, &flags)) |
|
2883 return NULL; |
|
2884 |
|
2885 CHECK_DB_NOT_CLOSED(self); |
|
2886 if (outFileName) |
|
2887 outFile = fopen(outFileName, "w"); |
|
2888 /* XXX(nnorwitz): it should probably be an exception if outFile |
|
2889 can't be opened. */ |
|
2890 |
|
2891 { /* DB.verify acts as a DB handle destructor (like close) */ |
|
2892 PyObject *error; |
|
2893 |
|
2894 error=DB_close_internal(self, 0, 1); |
|
2895 if (error ) { |
|
2896 return error; |
|
2897 } |
|
2898 } |
|
2899 |
|
2900 MYDB_BEGIN_ALLOW_THREADS; |
|
2901 err = self->db->verify(self->db, fileName, dbName, outFile, flags); |
|
2902 MYDB_END_ALLOW_THREADS; |
|
2903 |
|
2904 self->db = NULL; /* Implicit close; related objects already released */ |
|
2905 |
|
2906 if (outFile) |
|
2907 fclose(outFile); |
|
2908 |
|
2909 RETURN_IF_ERR(); |
|
2910 RETURN_NONE(); |
|
2911 } |
|
2912 |
|
2913 |
|
2914 static PyObject* |
|
2915 DB_set_get_returns_none(DBObject* self, PyObject* args) |
|
2916 { |
|
2917 int flags=0; |
|
2918 int oldValue=0; |
|
2919 |
|
2920 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags)) |
|
2921 return NULL; |
|
2922 CHECK_DB_NOT_CLOSED(self); |
|
2923 |
|
2924 if (self->moduleFlags.getReturnsNone) |
|
2925 ++oldValue; |
|
2926 if (self->moduleFlags.cursorSetReturnsNone) |
|
2927 ++oldValue; |
|
2928 self->moduleFlags.getReturnsNone = (flags >= 1); |
|
2929 self->moduleFlags.cursorSetReturnsNone = (flags >= 2); |
|
2930 return NUMBER_FromLong(oldValue); |
|
2931 } |
|
2932 |
|
2933 #if (DBVER >= 41) |
|
2934 static PyObject* |
|
2935 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs) |
|
2936 { |
|
2937 int err; |
|
2938 u_int32_t flags=0; |
|
2939 char *passwd = NULL; |
|
2940 static char* kwnames[] = { "passwd", "flags", NULL }; |
|
2941 |
|
2942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames, |
|
2943 &passwd, &flags)) { |
|
2944 return NULL; |
|
2945 } |
|
2946 |
|
2947 MYDB_BEGIN_ALLOW_THREADS; |
|
2948 err = self->db->set_encrypt(self->db, passwd, flags); |
|
2949 MYDB_END_ALLOW_THREADS; |
|
2950 |
|
2951 RETURN_IF_ERR(); |
|
2952 RETURN_NONE(); |
|
2953 } |
|
2954 #endif /* DBVER >= 41 */ |
|
2955 |
|
2956 |
|
2957 /*-------------------------------------------------------------- */ |
|
2958 /* Mapping and Dictionary-like access routines */ |
|
2959 |
|
2960 Py_ssize_t DB_length(PyObject* _self) |
|
2961 { |
|
2962 int err; |
|
2963 Py_ssize_t size = 0; |
|
2964 int flags = 0; |
|
2965 void* sp; |
|
2966 DBObject* self = (DBObject*)_self; |
|
2967 |
|
2968 if (self->db == NULL) { |
|
2969 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed"); |
|
2970 if (t) { |
|
2971 PyErr_SetObject(DBError, t); |
|
2972 Py_DECREF(t); |
|
2973 } |
|
2974 return -1; |
|
2975 } |
|
2976 |
|
2977 if (self->haveStat) { /* Has the stat function been called recently? If |
|
2978 so, we can use the cached value. */ |
|
2979 flags = DB_FAST_STAT; |
|
2980 } |
|
2981 |
|
2982 MYDB_BEGIN_ALLOW_THREADS; |
|
2983 redo_stat_for_length: |
|
2984 #if (DBVER >= 43) |
|
2985 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags); |
|
2986 #else |
|
2987 err = self->db->stat(self->db, &sp, flags); |
|
2988 #endif |
|
2989 |
|
2990 /* All the stat structures have matching fields upto the ndata field, |
|
2991 so we can use any of them for the type cast */ |
|
2992 size = ((DB_BTREE_STAT*)sp)->bt_ndata; |
|
2993 |
|
2994 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached. |
|
2995 * redo a full stat to make sure. |
|
2996 * Fixes SF python bug 1493322, pybsddb bug 1184012 |
|
2997 */ |
|
2998 if (size == 0 && (flags & DB_FAST_STAT)) { |
|
2999 flags = 0; |
|
3000 if (!err) |
|
3001 free(sp); |
|
3002 goto redo_stat_for_length; |
|
3003 } |
|
3004 |
|
3005 MYDB_END_ALLOW_THREADS; |
|
3006 |
|
3007 if (err) |
|
3008 return -1; |
|
3009 |
|
3010 self->haveStat = 1; |
|
3011 |
|
3012 free(sp); |
|
3013 return size; |
|
3014 } |
|
3015 |
|
3016 |
|
3017 PyObject* DB_subscript(DBObject* self, PyObject* keyobj) |
|
3018 { |
|
3019 int err; |
|
3020 PyObject* retval; |
|
3021 DBT key; |
|
3022 DBT data; |
|
3023 |
|
3024 CHECK_DB_NOT_CLOSED(self); |
|
3025 if (!make_key_dbt(self, keyobj, &key, NULL)) |
|
3026 return NULL; |
|
3027 |
|
3028 CLEAR_DBT(data); |
|
3029 if (CHECK_DBFLAG(self, DB_THREAD)) { |
|
3030 /* Tell Berkeley DB to malloc the return value (thread safe) */ |
|
3031 data.flags = DB_DBT_MALLOC; |
|
3032 } |
|
3033 MYDB_BEGIN_ALLOW_THREADS; |
|
3034 err = self->db->get(self->db, NULL, &key, &data, 0); |
|
3035 MYDB_END_ALLOW_THREADS; |
|
3036 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) { |
|
3037 PyErr_SetObject(PyExc_KeyError, keyobj); |
|
3038 retval = NULL; |
|
3039 } |
|
3040 else if (makeDBError(err)) { |
|
3041 retval = NULL; |
|
3042 } |
|
3043 else { |
|
3044 retval = Build_PyString(data.data, data.size); |
|
3045 FREE_DBT(data); |
|
3046 } |
|
3047 |
|
3048 FREE_DBT(key); |
|
3049 return retval; |
|
3050 } |
|
3051 |
|
3052 |
|
3053 static int |
|
3054 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj) |
|
3055 { |
|
3056 DBT key, data; |
|
3057 int retval; |
|
3058 int flags = 0; |
|
3059 |
|
3060 if (self->db == NULL) { |
|
3061 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed"); |
|
3062 if (t) { |
|
3063 PyErr_SetObject(DBError, t); |
|
3064 Py_DECREF(t); |
|
3065 } |
|
3066 return -1; |
|
3067 } |
|
3068 |
|
3069 if (!make_key_dbt(self, keyobj, &key, NULL)) |
|
3070 return -1; |
|
3071 |
|
3072 if (dataobj != NULL) { |
|
3073 if (!make_dbt(dataobj, &data)) |
|
3074 retval = -1; |
|
3075 else { |
|
3076 if (self->setflags & (DB_DUP|DB_DUPSORT)) |
|
3077 /* dictionaries shouldn't have duplicate keys */ |
|
3078 flags = DB_NOOVERWRITE; |
|
3079 retval = _DB_put(self, NULL, &key, &data, flags); |
|
3080 |
|
3081 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) { |
|
3082 /* try deleting any old record that matches and then PUT it |
|
3083 * again... */ |
|
3084 _DB_delete(self, NULL, &key, 0); |
|
3085 PyErr_Clear(); |
|
3086 retval = _DB_put(self, NULL, &key, &data, flags); |
|
3087 } |
|
3088 } |
|
3089 } |
|
3090 else { |
|
3091 /* dataobj == NULL, so delete the key */ |
|
3092 retval = _DB_delete(self, NULL, &key, 0); |
|
3093 } |
|
3094 FREE_DBT(key); |
|
3095 return retval; |
|
3096 } |
|
3097 |
|
3098 |
|
3099 static PyObject* |
|
3100 DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs) |
|
3101 { |
|
3102 int err; |
|
3103 PyObject* keyobj; |
|
3104 DBT key, data; |
|
3105 PyObject* txnobj = NULL; |
|
3106 DB_TXN *txn = NULL; |
|
3107 static char* kwnames[] = {"key","txn", NULL}; |
|
3108 |
|
3109 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames, |
|
3110 &keyobj, &txnobj)) |
|
3111 return NULL; |
|
3112 |
|
3113 CHECK_DB_NOT_CLOSED(self); |
|
3114 if (!make_key_dbt(self, keyobj, &key, NULL)) |
|
3115 return NULL; |
|
3116 if (!checkTxnObj(txnobj, &txn)) { |
|
3117 FREE_DBT(key); |
|
3118 return NULL; |
|
3119 } |
|
3120 |
|
3121 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because |
|
3122 it has a record but can't allocate a buffer for the data. This saves |
|
3123 having to deal with data we won't be using. |
|
3124 */ |
|
3125 CLEAR_DBT(data); |
|
3126 data.flags = DB_DBT_USERMEM; |
|
3127 |
|
3128 MYDB_BEGIN_ALLOW_THREADS; |
|
3129 err = self->db->get(self->db, txn, &key, &data, 0); |
|
3130 MYDB_END_ALLOW_THREADS; |
|
3131 FREE_DBT(key); |
|
3132 |
|
3133 if (err == DB_BUFFER_SMALL || err == 0) { |
|
3134 return NUMBER_FromLong(1); |
|
3135 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) { |
|
3136 return NUMBER_FromLong(0); |
|
3137 } |
|
3138 |
|
3139 makeDBError(err); |
|
3140 return NULL; |
|
3141 } |
|
3142 |
|
3143 |
|
3144 #define _KEYS_LIST 1 |
|
3145 #define _VALUES_LIST 2 |
|
3146 #define _ITEMS_LIST 3 |
|
3147 |
|
3148 static PyObject* |
|
3149 _DB_make_list(DBObject* self, DB_TXN* txn, int type) |
|
3150 { |
|
3151 int err, dbtype; |
|
3152 DBT key; |
|
3153 DBT data; |
|
3154 DBC *cursor; |
|
3155 PyObject* list; |
|
3156 PyObject* item = NULL; |
|
3157 |
|
3158 CHECK_DB_NOT_CLOSED(self); |
|
3159 CLEAR_DBT(key); |
|
3160 CLEAR_DBT(data); |
|
3161 |
|
3162 dbtype = _DB_get_type(self); |
|
3163 if (dbtype == -1) |
|
3164 return NULL; |
|
3165 |
|
3166 list = PyList_New(0); |
|
3167 if (list == NULL) |
|
3168 return NULL; |
|
3169 |
|
3170 /* get a cursor */ |
|
3171 MYDB_BEGIN_ALLOW_THREADS; |
|
3172 err = self->db->cursor(self->db, txn, &cursor, 0); |
|
3173 MYDB_END_ALLOW_THREADS; |
|
3174 if (makeDBError(err)) { |
|
3175 Py_DECREF(list); |
|
3176 return NULL; |
|
3177 } |
|
3178 |
|
3179 while (1) { /* use the cursor to traverse the DB, collecting items */ |
|
3180 MYDB_BEGIN_ALLOW_THREADS; |
|
3181 err = _DBC_get(cursor, &key, &data, DB_NEXT); |
|
3182 MYDB_END_ALLOW_THREADS; |
|
3183 |
|
3184 if (err) { |
|
3185 /* for any error, break out of the loop */ |
|
3186 break; |
|
3187 } |
|
3188 |
|
3189 switch (type) { |
|
3190 case _KEYS_LIST: |
|
3191 switch(dbtype) { |
|
3192 case DB_BTREE: |
|
3193 case DB_HASH: |
|
3194 default: |
|
3195 item = Build_PyString(key.data, key.size); |
|
3196 break; |
|
3197 case DB_RECNO: |
|
3198 case DB_QUEUE: |
|
3199 item = NUMBER_FromLong(*((db_recno_t*)key.data)); |
|
3200 break; |
|
3201 } |
|
3202 break; |
|
3203 |
|
3204 case _VALUES_LIST: |
|
3205 item = Build_PyString(data.data, data.size); |
|
3206 break; |
|
3207 |
|
3208 case _ITEMS_LIST: |
|
3209 switch(dbtype) { |
|
3210 case DB_BTREE: |
|
3211 case DB_HASH: |
|
3212 default: |
|
3213 item = BuildValue_SS(key.data, key.size, data.data, data.size); |
|
3214 break; |
|
3215 case DB_RECNO: |
|
3216 case DB_QUEUE: |
|
3217 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); |
|
3218 break; |
|
3219 } |
|
3220 break; |
|
3221 default: |
|
3222 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type); |
|
3223 item = NULL; |
|
3224 break; |
|
3225 } |
|
3226 if (item == NULL) { |
|
3227 Py_DECREF(list); |
|
3228 list = NULL; |
|
3229 goto done; |
|
3230 } |
|
3231 if (PyList_Append(list, item)) { |
|
3232 Py_DECREF(list); |
|
3233 Py_DECREF(item); |
|
3234 list = NULL; |
|
3235 goto done; |
|
3236 } |
|
3237 Py_DECREF(item); |
|
3238 } |
|
3239 |
|
3240 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */ |
|
3241 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) { |
|
3242 Py_DECREF(list); |
|
3243 list = NULL; |
|
3244 } |
|
3245 |
|
3246 done: |
|
3247 MYDB_BEGIN_ALLOW_THREADS; |
|
3248 _DBC_close(cursor); |
|
3249 MYDB_END_ALLOW_THREADS; |
|
3250 return list; |
|
3251 } |
|
3252 |
|
3253 |
|
3254 static PyObject* |
|
3255 DB_keys(DBObject* self, PyObject* args) |
|
3256 { |
|
3257 PyObject* txnobj = NULL; |
|
3258 DB_TXN *txn = NULL; |
|
3259 |
|
3260 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj)) |
|
3261 return NULL; |
|
3262 if (!checkTxnObj(txnobj, &txn)) |
|
3263 return NULL; |
|
3264 return _DB_make_list(self, txn, _KEYS_LIST); |
|
3265 } |
|
3266 |
|
3267 |
|
3268 static PyObject* |
|
3269 DB_items(DBObject* self, PyObject* args) |
|
3270 { |
|
3271 PyObject* txnobj = NULL; |
|
3272 DB_TXN *txn = NULL; |
|
3273 |
|
3274 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj)) |
|
3275 return NULL; |
|
3276 if (!checkTxnObj(txnobj, &txn)) |
|
3277 return NULL; |
|
3278 return _DB_make_list(self, txn, _ITEMS_LIST); |
|
3279 } |
|
3280 |
|
3281 |
|
3282 static PyObject* |
|
3283 DB_values(DBObject* self, PyObject* args) |
|
3284 { |
|
3285 PyObject* txnobj = NULL; |
|
3286 DB_TXN *txn = NULL; |
|
3287 |
|
3288 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj)) |
|
3289 return NULL; |
|
3290 if (!checkTxnObj(txnobj, &txn)) |
|
3291 return NULL; |
|
3292 return _DB_make_list(self, txn, _VALUES_LIST); |
|
3293 } |
|
3294 |
|
3295 /* --------------------------------------------------------------------- */ |
|
3296 /* DBCursor methods */ |
|
3297 |
|
3298 |
|
3299 static PyObject* |
|
3300 DBC_close_internal(DBCursorObject* self) |
|
3301 { |
|
3302 int err = 0; |
|
3303 |
|
3304 if (self->dbc != NULL) { |
|
3305 EXTRACT_FROM_DOUBLE_LINKED_LIST(self); |
|
3306 if (self->txn) { |
|
3307 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self); |
|
3308 self->txn=NULL; |
|
3309 } |
|
3310 |
|
3311 MYDB_BEGIN_ALLOW_THREADS; |
|
3312 err = _DBC_close(self->dbc); |
|
3313 MYDB_END_ALLOW_THREADS; |
|
3314 self->dbc = NULL; |
|
3315 } |
|
3316 RETURN_IF_ERR(); |
|
3317 RETURN_NONE(); |
|
3318 } |
|
3319 |
|
3320 static PyObject* |
|
3321 DBC_close(DBCursorObject* self) |
|
3322 { |
|
3323 return DBC_close_internal(self); |
|
3324 } |
|
3325 |
|
3326 |
|
3327 static PyObject* |
|
3328 DBC_count(DBCursorObject* self, PyObject* args) |
|
3329 { |
|
3330 int err = 0; |
|
3331 db_recno_t count; |
|
3332 int flags = 0; |
|
3333 |
|
3334 if (!PyArg_ParseTuple(args, "|i:count", &flags)) |
|
3335 return NULL; |
|
3336 |
|
3337 CHECK_CURSOR_NOT_CLOSED(self); |
|
3338 |
|
3339 MYDB_BEGIN_ALLOW_THREADS; |
|
3340 err = _DBC_count(self->dbc, &count, flags); |
|
3341 MYDB_END_ALLOW_THREADS; |
|
3342 RETURN_IF_ERR(); |
|
3343 |
|
3344 return NUMBER_FromLong(count); |
|
3345 } |
|
3346 |
|
3347 |
|
3348 static PyObject* |
|
3349 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3350 { |
|
3351 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current"); |
|
3352 } |
|
3353 |
|
3354 |
|
3355 static PyObject* |
|
3356 DBC_delete(DBCursorObject* self, PyObject* args) |
|
3357 { |
|
3358 int err, flags=0; |
|
3359 |
|
3360 if (!PyArg_ParseTuple(args, "|i:delete", &flags)) |
|
3361 return NULL; |
|
3362 |
|
3363 CHECK_CURSOR_NOT_CLOSED(self); |
|
3364 |
|
3365 MYDB_BEGIN_ALLOW_THREADS; |
|
3366 err = _DBC_del(self->dbc, flags); |
|
3367 MYDB_END_ALLOW_THREADS; |
|
3368 RETURN_IF_ERR(); |
|
3369 |
|
3370 self->mydb->haveStat = 0; |
|
3371 RETURN_NONE(); |
|
3372 } |
|
3373 |
|
3374 |
|
3375 static PyObject* |
|
3376 DBC_dup(DBCursorObject* self, PyObject* args) |
|
3377 { |
|
3378 int err, flags =0; |
|
3379 DBC* dbc = NULL; |
|
3380 |
|
3381 if (!PyArg_ParseTuple(args, "|i:dup", &flags)) |
|
3382 return NULL; |
|
3383 |
|
3384 CHECK_CURSOR_NOT_CLOSED(self); |
|
3385 |
|
3386 MYDB_BEGIN_ALLOW_THREADS; |
|
3387 err = _DBC_dup(self->dbc, &dbc, flags); |
|
3388 MYDB_END_ALLOW_THREADS; |
|
3389 RETURN_IF_ERR(); |
|
3390 |
|
3391 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb); |
|
3392 } |
|
3393 |
|
3394 static PyObject* |
|
3395 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs) |
|
3396 { |
|
3397 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first"); |
|
3398 } |
|
3399 |
|
3400 |
|
3401 static PyObject* |
|
3402 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3403 { |
|
3404 int err, flags=0; |
|
3405 PyObject* keyobj = NULL; |
|
3406 PyObject* dataobj = NULL; |
|
3407 PyObject* retval = NULL; |
|
3408 int dlen = -1; |
|
3409 int doff = -1; |
|
3410 DBT key, data; |
|
3411 static char* kwnames[] = { "key","data", "flags", "dlen", "doff", |
|
3412 NULL }; |
|
3413 |
|
3414 CLEAR_DBT(key); |
|
3415 CLEAR_DBT(data); |
|
3416 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2], |
|
3417 &flags, &dlen, &doff)) |
|
3418 { |
|
3419 PyErr_Clear(); |
|
3420 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get", |
|
3421 &kwnames[1], |
|
3422 &keyobj, &flags, &dlen, &doff)) |
|
3423 { |
|
3424 PyErr_Clear(); |
|
3425 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get", |
|
3426 kwnames, &keyobj, &dataobj, |
|
3427 &flags, &dlen, &doff)) |
|
3428 { |
|
3429 return NULL; |
|
3430 } |
|
3431 } |
|
3432 } |
|
3433 |
|
3434 CHECK_CURSOR_NOT_CLOSED(self); |
|
3435 |
|
3436 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL)) |
|
3437 return NULL; |
|
3438 if ( (dataobj && !make_dbt(dataobj, &data)) || |
|
3439 (!add_partial_dbt(&data, dlen, doff)) ) |
|
3440 { |
|
3441 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3442 return NULL; |
|
3443 } |
|
3444 |
|
3445 MYDB_BEGIN_ALLOW_THREADS; |
|
3446 err = _DBC_get(self->dbc, &key, &data, flags); |
|
3447 MYDB_END_ALLOW_THREADS; |
|
3448 |
|
3449 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) |
|
3450 && self->mydb->moduleFlags.getReturnsNone) { |
|
3451 Py_INCREF(Py_None); |
|
3452 retval = Py_None; |
|
3453 } |
|
3454 else if (makeDBError(err)) { |
|
3455 retval = NULL; |
|
3456 } |
|
3457 else { |
|
3458 switch (_DB_get_type(self->mydb)) { |
|
3459 case -1: |
|
3460 retval = NULL; |
|
3461 break; |
|
3462 case DB_BTREE: |
|
3463 case DB_HASH: |
|
3464 default: |
|
3465 retval = BuildValue_SS(key.data, key.size, data.data, data.size); |
|
3466 break; |
|
3467 case DB_RECNO: |
|
3468 case DB_QUEUE: |
|
3469 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); |
|
3470 break; |
|
3471 } |
|
3472 } |
|
3473 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3474 return retval; |
|
3475 } |
|
3476 |
|
3477 static PyObject* |
|
3478 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3479 { |
|
3480 int err, flags=0; |
|
3481 PyObject* keyobj = NULL; |
|
3482 PyObject* dataobj = NULL; |
|
3483 PyObject* retval = NULL; |
|
3484 int dlen = -1; |
|
3485 int doff = -1; |
|
3486 DBT key, pkey, data; |
|
3487 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL }; |
|
3488 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL }; |
|
3489 |
|
3490 CLEAR_DBT(key); |
|
3491 CLEAR_DBT(data); |
|
3492 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2], |
|
3493 &flags, &dlen, &doff)) |
|
3494 { |
|
3495 PyErr_Clear(); |
|
3496 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget", |
|
3497 kwnames_keyOnly, |
|
3498 &keyobj, &flags, &dlen, &doff)) |
|
3499 { |
|
3500 PyErr_Clear(); |
|
3501 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget", |
|
3502 kwnames, &keyobj, &dataobj, |
|
3503 &flags, &dlen, &doff)) |
|
3504 { |
|
3505 return NULL; |
|
3506 } |
|
3507 } |
|
3508 } |
|
3509 |
|
3510 CHECK_CURSOR_NOT_CLOSED(self); |
|
3511 |
|
3512 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL)) |
|
3513 return NULL; |
|
3514 if ( (dataobj && !make_dbt(dataobj, &data)) || |
|
3515 (!add_partial_dbt(&data, dlen, doff)) ) { |
|
3516 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3517 return NULL; |
|
3518 } |
|
3519 |
|
3520 CLEAR_DBT(pkey); |
|
3521 pkey.flags = DB_DBT_MALLOC; |
|
3522 |
|
3523 MYDB_BEGIN_ALLOW_THREADS; |
|
3524 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags); |
|
3525 MYDB_END_ALLOW_THREADS; |
|
3526 |
|
3527 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) |
|
3528 && self->mydb->moduleFlags.getReturnsNone) { |
|
3529 Py_INCREF(Py_None); |
|
3530 retval = Py_None; |
|
3531 } |
|
3532 else if (makeDBError(err)) { |
|
3533 retval = NULL; |
|
3534 } |
|
3535 else { |
|
3536 PyObject *pkeyObj; |
|
3537 PyObject *dataObj; |
|
3538 dataObj = Build_PyString(data.data, data.size); |
|
3539 |
|
3540 if (self->mydb->primaryDBType == DB_RECNO || |
|
3541 self->mydb->primaryDBType == DB_QUEUE) |
|
3542 pkeyObj = NUMBER_FromLong(*(int *)pkey.data); |
|
3543 else |
|
3544 pkeyObj = Build_PyString(pkey.data, pkey.size); |
|
3545 |
|
3546 if (key.data && key.size) /* return key, pkey and data */ |
|
3547 { |
|
3548 PyObject *keyObj; |
|
3549 int type = _DB_get_type(self->mydb); |
|
3550 if (type == DB_RECNO || type == DB_QUEUE) |
|
3551 keyObj = NUMBER_FromLong(*(int *)key.data); |
|
3552 else |
|
3553 keyObj = Build_PyString(key.data, key.size); |
|
3554 #if (PY_VERSION_HEX >= 0x02040000) |
|
3555 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj); |
|
3556 #else |
|
3557 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj); |
|
3558 #endif |
|
3559 Py_DECREF(keyObj); |
|
3560 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3561 } |
|
3562 else /* return just the pkey and data */ |
|
3563 { |
|
3564 #if (PY_VERSION_HEX >= 0x02040000) |
|
3565 retval = PyTuple_Pack(2, pkeyObj, dataObj); |
|
3566 #else |
|
3567 retval = Py_BuildValue("OO", pkeyObj, dataObj); |
|
3568 #endif |
|
3569 } |
|
3570 Py_DECREF(dataObj); |
|
3571 Py_DECREF(pkeyObj); |
|
3572 FREE_DBT(pkey); |
|
3573 } |
|
3574 /* the only time REALLOC should be set is if we used an integer |
|
3575 * key that make_key_dbt malloc'd for us. always free these. */ |
|
3576 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */ |
|
3577 FREE_DBT(key); |
|
3578 } |
|
3579 return retval; |
|
3580 } |
|
3581 |
|
3582 |
|
3583 static PyObject* |
|
3584 DBC_get_recno(DBCursorObject* self) |
|
3585 { |
|
3586 int err; |
|
3587 db_recno_t recno; |
|
3588 DBT key; |
|
3589 DBT data; |
|
3590 |
|
3591 CHECK_CURSOR_NOT_CLOSED(self); |
|
3592 |
|
3593 CLEAR_DBT(key); |
|
3594 CLEAR_DBT(data); |
|
3595 |
|
3596 MYDB_BEGIN_ALLOW_THREADS; |
|
3597 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO); |
|
3598 MYDB_END_ALLOW_THREADS; |
|
3599 RETURN_IF_ERR(); |
|
3600 |
|
3601 recno = *((db_recno_t*)data.data); |
|
3602 return NUMBER_FromLong(recno); |
|
3603 } |
|
3604 |
|
3605 |
|
3606 static PyObject* |
|
3607 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3608 { |
|
3609 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last"); |
|
3610 } |
|
3611 |
|
3612 |
|
3613 static PyObject* |
|
3614 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3615 { |
|
3616 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next"); |
|
3617 } |
|
3618 |
|
3619 |
|
3620 static PyObject* |
|
3621 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3622 { |
|
3623 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev"); |
|
3624 } |
|
3625 |
|
3626 |
|
3627 static PyObject* |
|
3628 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs) |
|
3629 { |
|
3630 int err, flags = 0; |
|
3631 PyObject* keyobj, *dataobj; |
|
3632 DBT key, data; |
|
3633 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", |
|
3634 NULL }; |
|
3635 int dlen = -1; |
|
3636 int doff = -1; |
|
3637 |
|
3638 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames, |
|
3639 &keyobj, &dataobj, &flags, &dlen, &doff)) |
|
3640 return NULL; |
|
3641 |
|
3642 CHECK_CURSOR_NOT_CLOSED(self); |
|
3643 |
|
3644 if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) |
|
3645 return NULL; |
|
3646 if (!make_dbt(dataobj, &data) || |
|
3647 !add_partial_dbt(&data, dlen, doff) ) |
|
3648 { |
|
3649 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3650 return NULL; |
|
3651 } |
|
3652 |
|
3653 MYDB_BEGIN_ALLOW_THREADS; |
|
3654 err = _DBC_put(self->dbc, &key, &data, flags); |
|
3655 MYDB_END_ALLOW_THREADS; |
|
3656 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3657 RETURN_IF_ERR(); |
|
3658 self->mydb->haveStat = 0; |
|
3659 RETURN_NONE(); |
|
3660 } |
|
3661 |
|
3662 |
|
3663 static PyObject* |
|
3664 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3665 { |
|
3666 int err, flags = 0; |
|
3667 DBT key, data; |
|
3668 PyObject* retval, *keyobj; |
|
3669 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; |
|
3670 int dlen = -1; |
|
3671 int doff = -1; |
|
3672 |
|
3673 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames, |
|
3674 &keyobj, &flags, &dlen, &doff)) |
|
3675 return NULL; |
|
3676 |
|
3677 CHECK_CURSOR_NOT_CLOSED(self); |
|
3678 |
|
3679 if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) |
|
3680 return NULL; |
|
3681 |
|
3682 CLEAR_DBT(data); |
|
3683 if (!add_partial_dbt(&data, dlen, doff)) { |
|
3684 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3685 return NULL; |
|
3686 } |
|
3687 |
|
3688 MYDB_BEGIN_ALLOW_THREADS; |
|
3689 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET); |
|
3690 MYDB_END_ALLOW_THREADS; |
|
3691 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) |
|
3692 && self->mydb->moduleFlags.cursorSetReturnsNone) { |
|
3693 Py_INCREF(Py_None); |
|
3694 retval = Py_None; |
|
3695 } |
|
3696 else if (makeDBError(err)) { |
|
3697 retval = NULL; |
|
3698 } |
|
3699 else { |
|
3700 switch (_DB_get_type(self->mydb)) { |
|
3701 case -1: |
|
3702 retval = NULL; |
|
3703 break; |
|
3704 case DB_BTREE: |
|
3705 case DB_HASH: |
|
3706 default: |
|
3707 retval = BuildValue_SS(key.data, key.size, data.data, data.size); |
|
3708 break; |
|
3709 case DB_RECNO: |
|
3710 case DB_QUEUE: |
|
3711 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); |
|
3712 break; |
|
3713 } |
|
3714 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3715 } |
|
3716 /* the only time REALLOC should be set is if we used an integer |
|
3717 * key that make_key_dbt malloc'd for us. always free these. */ |
|
3718 if (key.flags & DB_DBT_REALLOC) { |
|
3719 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3720 } |
|
3721 |
|
3722 return retval; |
|
3723 } |
|
3724 |
|
3725 |
|
3726 static PyObject* |
|
3727 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs) |
|
3728 { |
|
3729 int err, flags = 0; |
|
3730 DBT key, data; |
|
3731 PyObject* retval, *keyobj; |
|
3732 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; |
|
3733 int dlen = -1; |
|
3734 int doff = -1; |
|
3735 |
|
3736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames, |
|
3737 &keyobj, &flags, &dlen, &doff)) |
|
3738 return NULL; |
|
3739 |
|
3740 CHECK_CURSOR_NOT_CLOSED(self); |
|
3741 |
|
3742 if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) |
|
3743 return NULL; |
|
3744 |
|
3745 CLEAR_DBT(data); |
|
3746 if (!add_partial_dbt(&data, dlen, doff)) { |
|
3747 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3748 return NULL; |
|
3749 } |
|
3750 MYDB_BEGIN_ALLOW_THREADS; |
|
3751 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE); |
|
3752 MYDB_END_ALLOW_THREADS; |
|
3753 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) |
|
3754 && self->mydb->moduleFlags.cursorSetReturnsNone) { |
|
3755 Py_INCREF(Py_None); |
|
3756 retval = Py_None; |
|
3757 } |
|
3758 else if (makeDBError(err)) { |
|
3759 retval = NULL; |
|
3760 } |
|
3761 else { |
|
3762 switch (_DB_get_type(self->mydb)) { |
|
3763 case -1: |
|
3764 retval = NULL; |
|
3765 break; |
|
3766 case DB_BTREE: |
|
3767 case DB_HASH: |
|
3768 default: |
|
3769 retval = BuildValue_SS(key.data, key.size, data.data, data.size); |
|
3770 break; |
|
3771 case DB_RECNO: |
|
3772 case DB_QUEUE: |
|
3773 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); |
|
3774 break; |
|
3775 } |
|
3776 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3777 } |
|
3778 /* the only time REALLOC should be set is if we used an integer |
|
3779 * key that make_key_dbt malloc'd for us. always free these. */ |
|
3780 if (key.flags & DB_DBT_REALLOC) { |
|
3781 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3782 } |
|
3783 |
|
3784 return retval; |
|
3785 } |
|
3786 |
|
3787 static PyObject* |
|
3788 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj, |
|
3789 int flags, unsigned int returnsNone) |
|
3790 { |
|
3791 int err; |
|
3792 DBT key, data; |
|
3793 PyObject* retval; |
|
3794 |
|
3795 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */ |
|
3796 if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) |
|
3797 return NULL; |
|
3798 if (!make_dbt(dataobj, &data)) { |
|
3799 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3800 return NULL; |
|
3801 } |
|
3802 |
|
3803 MYDB_BEGIN_ALLOW_THREADS; |
|
3804 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH); |
|
3805 MYDB_END_ALLOW_THREADS; |
|
3806 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) { |
|
3807 Py_INCREF(Py_None); |
|
3808 retval = Py_None; |
|
3809 } |
|
3810 else if (makeDBError(err)) { |
|
3811 retval = NULL; |
|
3812 } |
|
3813 else { |
|
3814 switch (_DB_get_type(self->mydb)) { |
|
3815 case -1: |
|
3816 retval = NULL; |
|
3817 break; |
|
3818 case DB_BTREE: |
|
3819 case DB_HASH: |
|
3820 default: |
|
3821 retval = BuildValue_SS(key.data, key.size, data.data, data.size); |
|
3822 break; |
|
3823 case DB_RECNO: |
|
3824 case DB_QUEUE: |
|
3825 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); |
|
3826 break; |
|
3827 } |
|
3828 } |
|
3829 |
|
3830 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ |
|
3831 return retval; |
|
3832 } |
|
3833 |
|
3834 static PyObject* |
|
3835 DBC_get_both(DBCursorObject* self, PyObject* args) |
|
3836 { |
|
3837 int flags=0; |
|
3838 PyObject *keyobj, *dataobj; |
|
3839 |
|
3840 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags)) |
|
3841 return NULL; |
|
3842 |
|
3843 /* if the cursor is closed, self->mydb may be invalid */ |
|
3844 CHECK_CURSOR_NOT_CLOSED(self); |
|
3845 |
|
3846 return _DBC_get_set_both(self, keyobj, dataobj, flags, |
|
3847 self->mydb->moduleFlags.getReturnsNone); |
|
3848 } |
|
3849 |
|
3850 /* Return size of entry */ |
|
3851 static PyObject* |
|
3852 DBC_get_current_size(DBCursorObject* self) |
|
3853 { |
|
3854 int err, flags=DB_CURRENT; |
|
3855 PyObject* retval = NULL; |
|
3856 DBT key, data; |
|
3857 |
|
3858 CHECK_CURSOR_NOT_CLOSED(self); |
|
3859 CLEAR_DBT(key); |
|
3860 CLEAR_DBT(data); |
|
3861 |
|
3862 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus |
|
3863 getting the record size. */ |
|
3864 data.flags = DB_DBT_USERMEM; |
|
3865 data.ulen = 0; |
|
3866 MYDB_BEGIN_ALLOW_THREADS; |
|
3867 err = _DBC_get(self->dbc, &key, &data, flags); |
|
3868 MYDB_END_ALLOW_THREADS; |
|
3869 if (err == DB_BUFFER_SMALL || !err) { |
|
3870 /* DB_BUFFER_SMALL means positive size, !err means zero length value */ |
|
3871 retval = NUMBER_FromLong((long)data.size); |
|
3872 err = 0; |
|
3873 } |
|
3874 |
|
3875 RETURN_IF_ERR(); |
|
3876 return retval; |
|
3877 } |
|
3878 |
|
3879 static PyObject* |
|
3880 DBC_set_both(DBCursorObject* self, PyObject* args) |
|
3881 { |
|
3882 int flags=0; |
|
3883 PyObject *keyobj, *dataobj; |
|
3884 |
|
3885 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags)) |
|
3886 return NULL; |
|
3887 |
|
3888 /* if the cursor is closed, self->mydb may be invalid */ |
|
3889 CHECK_CURSOR_NOT_CLOSED(self); |
|
3890 |
|
3891 return _DBC_get_set_both(self, keyobj, dataobj, flags, |
|
3892 self->mydb->moduleFlags.cursorSetReturnsNone); |
|
3893 } |
|
3894 |
|
3895 |
|
3896 static PyObject* |
|
3897 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3898 { |
|
3899 int err, irecno, flags=0; |
|
3900 db_recno_t recno; |
|
3901 DBT key, data; |
|
3902 PyObject* retval; |
|
3903 int dlen = -1; |
|
3904 int doff = -1; |
|
3905 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL }; |
|
3906 |
|
3907 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames, |
|
3908 &irecno, &flags, &dlen, &doff)) |
|
3909 return NULL; |
|
3910 |
|
3911 CHECK_CURSOR_NOT_CLOSED(self); |
|
3912 |
|
3913 CLEAR_DBT(key); |
|
3914 recno = (db_recno_t) irecno; |
|
3915 /* use allocated space so DB will be able to realloc room for the real |
|
3916 * key */ |
|
3917 key.data = malloc(sizeof(db_recno_t)); |
|
3918 if (key.data == NULL) { |
|
3919 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed"); |
|
3920 return NULL; |
|
3921 } |
|
3922 key.size = sizeof(db_recno_t); |
|
3923 key.ulen = key.size; |
|
3924 memcpy(key.data, &recno, sizeof(db_recno_t)); |
|
3925 key.flags = DB_DBT_REALLOC; |
|
3926 |
|
3927 CLEAR_DBT(data); |
|
3928 if (!add_partial_dbt(&data, dlen, doff)) { |
|
3929 FREE_DBT(key); |
|
3930 return NULL; |
|
3931 } |
|
3932 |
|
3933 MYDB_BEGIN_ALLOW_THREADS; |
|
3934 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO); |
|
3935 MYDB_END_ALLOW_THREADS; |
|
3936 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) |
|
3937 && self->mydb->moduleFlags.cursorSetReturnsNone) { |
|
3938 Py_INCREF(Py_None); |
|
3939 retval = Py_None; |
|
3940 } |
|
3941 else if (makeDBError(err)) { |
|
3942 retval = NULL; |
|
3943 } |
|
3944 else { /* Can only be used for BTrees, so no need to return int key */ |
|
3945 retval = BuildValue_SS(key.data, key.size, data.data, data.size); |
|
3946 } |
|
3947 FREE_DBT(key); |
|
3948 |
|
3949 return retval; |
|
3950 } |
|
3951 |
|
3952 |
|
3953 static PyObject* |
|
3954 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3955 { |
|
3956 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume"); |
|
3957 } |
|
3958 |
|
3959 |
|
3960 static PyObject* |
|
3961 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3962 { |
|
3963 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup"); |
|
3964 } |
|
3965 |
|
3966 |
|
3967 static PyObject* |
|
3968 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3969 { |
|
3970 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup"); |
|
3971 } |
|
3972 |
|
3973 |
|
3974 static PyObject* |
|
3975 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs) |
|
3976 { |
|
3977 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup"); |
|
3978 } |
|
3979 |
|
3980 |
|
3981 static PyObject* |
|
3982 DBC_join_item(DBCursorObject* self, PyObject* args) |
|
3983 { |
|
3984 int err, flags=0; |
|
3985 DBT key, data; |
|
3986 PyObject* retval; |
|
3987 |
|
3988 if (!PyArg_ParseTuple(args, "|i:join_item", &flags)) |
|
3989 return NULL; |
|
3990 |
|
3991 CHECK_CURSOR_NOT_CLOSED(self); |
|
3992 |
|
3993 CLEAR_DBT(key); |
|
3994 CLEAR_DBT(data); |
|
3995 |
|
3996 MYDB_BEGIN_ALLOW_THREADS; |
|
3997 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM); |
|
3998 MYDB_END_ALLOW_THREADS; |
|
3999 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) |
|
4000 && self->mydb->moduleFlags.getReturnsNone) { |
|
4001 Py_INCREF(Py_None); |
|
4002 retval = Py_None; |
|
4003 } |
|
4004 else if (makeDBError(err)) { |
|
4005 retval = NULL; |
|
4006 } |
|
4007 else { |
|
4008 retval = BuildValue_S(key.data, key.size); |
|
4009 } |
|
4010 |
|
4011 return retval; |
|
4012 } |
|
4013 |
|
4014 |
|
4015 |
|
4016 /* --------------------------------------------------------------------- */ |
|
4017 /* DBEnv methods */ |
|
4018 |
|
4019 |
|
4020 static PyObject* |
|
4021 DBEnv_close_internal(DBEnvObject* self, int flags) |
|
4022 { |
|
4023 PyObject *dummy; |
|
4024 int err; |
|
4025 |
|
4026 if (!self->closed) { /* Don't close more than once */ |
|
4027 while(self->children_txns) { |
|
4028 dummy=DBTxn_abort_discard_internal(self->children_txns,0); |
|
4029 Py_XDECREF(dummy); |
|
4030 } |
|
4031 while(self->children_dbs) { |
|
4032 dummy=DB_close_internal(self->children_dbs, 0, 0); |
|
4033 Py_XDECREF(dummy); |
|
4034 } |
|
4035 } |
|
4036 |
|
4037 self->closed = 1; |
|
4038 if (self->db_env) { |
|
4039 MYDB_BEGIN_ALLOW_THREADS; |
|
4040 err = self->db_env->close(self->db_env, flags); |
|
4041 MYDB_END_ALLOW_THREADS; |
|
4042 /* after calling DBEnv->close, regardless of error, this DBEnv |
|
4043 * may not be accessed again (Berkeley DB docs). */ |
|
4044 self->db_env = NULL; |
|
4045 RETURN_IF_ERR(); |
|
4046 } |
|
4047 RETURN_NONE(); |
|
4048 } |
|
4049 |
|
4050 static PyObject* |
|
4051 DBEnv_close(DBEnvObject* self, PyObject* args) |
|
4052 { |
|
4053 int flags = 0; |
|
4054 |
|
4055 if (!PyArg_ParseTuple(args, "|i:close", &flags)) |
|
4056 return NULL; |
|
4057 return DBEnv_close_internal(self, flags); |
|
4058 } |
|
4059 |
|
4060 |
|
4061 static PyObject* |
|
4062 DBEnv_open(DBEnvObject* self, PyObject* args) |
|
4063 { |
|
4064 int err, flags=0, mode=0660; |
|
4065 char *db_home; |
|
4066 |
|
4067 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode)) |
|
4068 return NULL; |
|
4069 |
|
4070 CHECK_ENV_NOT_CLOSED(self); |
|
4071 |
|
4072 MYDB_BEGIN_ALLOW_THREADS; |
|
4073 err = self->db_env->open(self->db_env, db_home, flags, mode); |
|
4074 MYDB_END_ALLOW_THREADS; |
|
4075 RETURN_IF_ERR(); |
|
4076 self->closed = 0; |
|
4077 self->flags = flags; |
|
4078 RETURN_NONE(); |
|
4079 } |
|
4080 |
|
4081 |
|
4082 static PyObject* |
|
4083 DBEnv_remove(DBEnvObject* self, PyObject* args) |
|
4084 { |
|
4085 int err, flags=0; |
|
4086 char *db_home; |
|
4087 |
|
4088 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags)) |
|
4089 return NULL; |
|
4090 CHECK_ENV_NOT_CLOSED(self); |
|
4091 MYDB_BEGIN_ALLOW_THREADS; |
|
4092 err = self->db_env->remove(self->db_env, db_home, flags); |
|
4093 MYDB_END_ALLOW_THREADS; |
|
4094 RETURN_IF_ERR(); |
|
4095 RETURN_NONE(); |
|
4096 } |
|
4097 |
|
4098 #if (DBVER >= 41) |
|
4099 static PyObject* |
|
4100 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs) |
|
4101 { |
|
4102 int err; |
|
4103 u_int32_t flags=0; |
|
4104 char *file = NULL; |
|
4105 char *database = NULL; |
|
4106 PyObject *txnobj = NULL; |
|
4107 DB_TXN *txn = NULL; |
|
4108 static char* kwnames[] = { "file", "database", "txn", "flags", |
|
4109 NULL }; |
|
4110 |
|
4111 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames, |
|
4112 &file, &database, &txnobj, &flags)) { |
|
4113 return NULL; |
|
4114 } |
|
4115 if (!checkTxnObj(txnobj, &txn)) { |
|
4116 return NULL; |
|
4117 } |
|
4118 CHECK_ENV_NOT_CLOSED(self); |
|
4119 MYDB_BEGIN_ALLOW_THREADS; |
|
4120 err = self->db_env->dbremove(self->db_env, txn, file, database, flags); |
|
4121 MYDB_END_ALLOW_THREADS; |
|
4122 RETURN_IF_ERR(); |
|
4123 RETURN_NONE(); |
|
4124 } |
|
4125 |
|
4126 static PyObject* |
|
4127 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs) |
|
4128 { |
|
4129 int err; |
|
4130 u_int32_t flags=0; |
|
4131 char *file = NULL; |
|
4132 char *database = NULL; |
|
4133 char *newname = NULL; |
|
4134 PyObject *txnobj = NULL; |
|
4135 DB_TXN *txn = NULL; |
|
4136 static char* kwnames[] = { "file", "database", "newname", "txn", |
|
4137 "flags", NULL }; |
|
4138 |
|
4139 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames, |
|
4140 &file, &database, &newname, &txnobj, &flags)) { |
|
4141 return NULL; |
|
4142 } |
|
4143 if (!checkTxnObj(txnobj, &txn)) { |
|
4144 return NULL; |
|
4145 } |
|
4146 CHECK_ENV_NOT_CLOSED(self); |
|
4147 MYDB_BEGIN_ALLOW_THREADS; |
|
4148 err = self->db_env->dbrename(self->db_env, txn, file, database, newname, |
|
4149 flags); |
|
4150 MYDB_END_ALLOW_THREADS; |
|
4151 RETURN_IF_ERR(); |
|
4152 RETURN_NONE(); |
|
4153 } |
|
4154 |
|
4155 static PyObject* |
|
4156 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs) |
|
4157 { |
|
4158 int err; |
|
4159 u_int32_t flags=0; |
|
4160 char *passwd = NULL; |
|
4161 static char* kwnames[] = { "passwd", "flags", NULL }; |
|
4162 |
|
4163 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames, |
|
4164 &passwd, &flags)) { |
|
4165 return NULL; |
|
4166 } |
|
4167 |
|
4168 MYDB_BEGIN_ALLOW_THREADS; |
|
4169 err = self->db_env->set_encrypt(self->db_env, passwd, flags); |
|
4170 MYDB_END_ALLOW_THREADS; |
|
4171 |
|
4172 RETURN_IF_ERR(); |
|
4173 RETURN_NONE(); |
|
4174 } |
|
4175 #endif /* DBVER >= 41 */ |
|
4176 |
|
4177 static PyObject* |
|
4178 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs) |
|
4179 { |
|
4180 int err; |
|
4181 u_int32_t flags=0; |
|
4182 u_int32_t timeout = 0; |
|
4183 static char* kwnames[] = { "timeout", "flags", NULL }; |
|
4184 |
|
4185 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames, |
|
4186 &timeout, &flags)) { |
|
4187 return NULL; |
|
4188 } |
|
4189 |
|
4190 MYDB_BEGIN_ALLOW_THREADS; |
|
4191 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags); |
|
4192 MYDB_END_ALLOW_THREADS; |
|
4193 |
|
4194 RETURN_IF_ERR(); |
|
4195 RETURN_NONE(); |
|
4196 } |
|
4197 |
|
4198 static PyObject* |
|
4199 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args) |
|
4200 { |
|
4201 int err; |
|
4202 long shm_key = 0; |
|
4203 |
|
4204 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key)) |
|
4205 return NULL; |
|
4206 CHECK_ENV_NOT_CLOSED(self); |
|
4207 |
|
4208 err = self->db_env->set_shm_key(self->db_env, shm_key); |
|
4209 RETURN_IF_ERR(); |
|
4210 RETURN_NONE(); |
|
4211 } |
|
4212 |
|
4213 static PyObject* |
|
4214 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args) |
|
4215 { |
|
4216 int err, gbytes=0, bytes=0, ncache=0; |
|
4217 |
|
4218 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize", |
|
4219 &gbytes, &bytes, &ncache)) |
|
4220 return NULL; |
|
4221 CHECK_ENV_NOT_CLOSED(self); |
|
4222 |
|
4223 MYDB_BEGIN_ALLOW_THREADS; |
|
4224 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache); |
|
4225 MYDB_END_ALLOW_THREADS; |
|
4226 RETURN_IF_ERR(); |
|
4227 RETURN_NONE(); |
|
4228 } |
|
4229 |
|
4230 |
|
4231 static PyObject* |
|
4232 DBEnv_set_flags(DBEnvObject* self, PyObject* args) |
|
4233 { |
|
4234 int err, flags=0, onoff=0; |
|
4235 |
|
4236 if (!PyArg_ParseTuple(args, "ii:set_flags", |
|
4237 &flags, &onoff)) |
|
4238 return NULL; |
|
4239 CHECK_ENV_NOT_CLOSED(self); |
|
4240 |
|
4241 MYDB_BEGIN_ALLOW_THREADS; |
|
4242 err = self->db_env->set_flags(self->db_env, flags, onoff); |
|
4243 MYDB_END_ALLOW_THREADS; |
|
4244 RETURN_IF_ERR(); |
|
4245 RETURN_NONE(); |
|
4246 } |
|
4247 |
|
4248 |
|
4249 #if (DBVER >= 47) |
|
4250 static PyObject* |
|
4251 DBEnv_log_set_config(DBEnvObject* self, PyObject* args) |
|
4252 { |
|
4253 int err, flags, onoff; |
|
4254 |
|
4255 if (!PyArg_ParseTuple(args, "ii:log_set_config", |
|
4256 &flags, &onoff)) |
|
4257 return NULL; |
|
4258 CHECK_ENV_NOT_CLOSED(self); |
|
4259 |
|
4260 MYDB_BEGIN_ALLOW_THREADS; |
|
4261 err = self->db_env->log_set_config(self->db_env, flags, onoff); |
|
4262 MYDB_END_ALLOW_THREADS; |
|
4263 RETURN_IF_ERR(); |
|
4264 RETURN_NONE(); |
|
4265 } |
|
4266 #endif /* DBVER >= 47 */ |
|
4267 |
|
4268 |
|
4269 static PyObject* |
|
4270 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args) |
|
4271 { |
|
4272 int err; |
|
4273 char *dir; |
|
4274 |
|
4275 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir)) |
|
4276 return NULL; |
|
4277 CHECK_ENV_NOT_CLOSED(self); |
|
4278 |
|
4279 MYDB_BEGIN_ALLOW_THREADS; |
|
4280 err = self->db_env->set_data_dir(self->db_env, dir); |
|
4281 MYDB_END_ALLOW_THREADS; |
|
4282 RETURN_IF_ERR(); |
|
4283 RETURN_NONE(); |
|
4284 } |
|
4285 |
|
4286 |
|
4287 static PyObject* |
|
4288 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args) |
|
4289 { |
|
4290 int err, lg_bsize; |
|
4291 |
|
4292 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize)) |
|
4293 return NULL; |
|
4294 CHECK_ENV_NOT_CLOSED(self); |
|
4295 |
|
4296 MYDB_BEGIN_ALLOW_THREADS; |
|
4297 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize); |
|
4298 MYDB_END_ALLOW_THREADS; |
|
4299 RETURN_IF_ERR(); |
|
4300 RETURN_NONE(); |
|
4301 } |
|
4302 |
|
4303 |
|
4304 static PyObject* |
|
4305 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args) |
|
4306 { |
|
4307 int err; |
|
4308 char *dir; |
|
4309 |
|
4310 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir)) |
|
4311 return NULL; |
|
4312 CHECK_ENV_NOT_CLOSED(self); |
|
4313 |
|
4314 MYDB_BEGIN_ALLOW_THREADS; |
|
4315 err = self->db_env->set_lg_dir(self->db_env, dir); |
|
4316 MYDB_END_ALLOW_THREADS; |
|
4317 RETURN_IF_ERR(); |
|
4318 RETURN_NONE(); |
|
4319 } |
|
4320 |
|
4321 static PyObject* |
|
4322 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args) |
|
4323 { |
|
4324 int err, lg_max; |
|
4325 |
|
4326 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max)) |
|
4327 return NULL; |
|
4328 CHECK_ENV_NOT_CLOSED(self); |
|
4329 |
|
4330 MYDB_BEGIN_ALLOW_THREADS; |
|
4331 err = self->db_env->set_lg_max(self->db_env, lg_max); |
|
4332 MYDB_END_ALLOW_THREADS; |
|
4333 RETURN_IF_ERR(); |
|
4334 RETURN_NONE(); |
|
4335 } |
|
4336 |
|
4337 #if (DBVER >= 42) |
|
4338 static PyObject* |
|
4339 DBEnv_get_lg_max(DBEnvObject* self) |
|
4340 { |
|
4341 int err; |
|
4342 u_int32_t lg_max; |
|
4343 |
|
4344 CHECK_ENV_NOT_CLOSED(self); |
|
4345 |
|
4346 MYDB_BEGIN_ALLOW_THREADS; |
|
4347 err = self->db_env->get_lg_max(self->db_env, &lg_max); |
|
4348 MYDB_END_ALLOW_THREADS; |
|
4349 RETURN_IF_ERR(); |
|
4350 return NUMBER_FromLong(lg_max); |
|
4351 } |
|
4352 #endif |
|
4353 |
|
4354 |
|
4355 static PyObject* |
|
4356 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args) |
|
4357 { |
|
4358 int err, lg_max; |
|
4359 |
|
4360 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max)) |
|
4361 return NULL; |
|
4362 CHECK_ENV_NOT_CLOSED(self); |
|
4363 |
|
4364 MYDB_BEGIN_ALLOW_THREADS; |
|
4365 err = self->db_env->set_lg_regionmax(self->db_env, lg_max); |
|
4366 MYDB_END_ALLOW_THREADS; |
|
4367 RETURN_IF_ERR(); |
|
4368 RETURN_NONE(); |
|
4369 } |
|
4370 |
|
4371 |
|
4372 static PyObject* |
|
4373 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args) |
|
4374 { |
|
4375 int err, lk_detect; |
|
4376 |
|
4377 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect)) |
|
4378 return NULL; |
|
4379 CHECK_ENV_NOT_CLOSED(self); |
|
4380 |
|
4381 MYDB_BEGIN_ALLOW_THREADS; |
|
4382 err = self->db_env->set_lk_detect(self->db_env, lk_detect); |
|
4383 MYDB_END_ALLOW_THREADS; |
|
4384 RETURN_IF_ERR(); |
|
4385 RETURN_NONE(); |
|
4386 } |
|
4387 |
|
4388 |
|
4389 #if (DBVER < 45) |
|
4390 static PyObject* |
|
4391 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args) |
|
4392 { |
|
4393 int err, max; |
|
4394 |
|
4395 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max)) |
|
4396 return NULL; |
|
4397 CHECK_ENV_NOT_CLOSED(self); |
|
4398 |
|
4399 MYDB_BEGIN_ALLOW_THREADS; |
|
4400 err = self->db_env->set_lk_max(self->db_env, max); |
|
4401 MYDB_END_ALLOW_THREADS; |
|
4402 RETURN_IF_ERR(); |
|
4403 RETURN_NONE(); |
|
4404 } |
|
4405 #endif |
|
4406 |
|
4407 |
|
4408 |
|
4409 static PyObject* |
|
4410 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args) |
|
4411 { |
|
4412 int err, max; |
|
4413 |
|
4414 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max)) |
|
4415 return NULL; |
|
4416 CHECK_ENV_NOT_CLOSED(self); |
|
4417 |
|
4418 MYDB_BEGIN_ALLOW_THREADS; |
|
4419 err = self->db_env->set_lk_max_locks(self->db_env, max); |
|
4420 MYDB_END_ALLOW_THREADS; |
|
4421 RETURN_IF_ERR(); |
|
4422 RETURN_NONE(); |
|
4423 } |
|
4424 |
|
4425 |
|
4426 static PyObject* |
|
4427 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args) |
|
4428 { |
|
4429 int err, max; |
|
4430 |
|
4431 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max)) |
|
4432 return NULL; |
|
4433 CHECK_ENV_NOT_CLOSED(self); |
|
4434 |
|
4435 MYDB_BEGIN_ALLOW_THREADS; |
|
4436 err = self->db_env->set_lk_max_lockers(self->db_env, max); |
|
4437 MYDB_END_ALLOW_THREADS; |
|
4438 RETURN_IF_ERR(); |
|
4439 RETURN_NONE(); |
|
4440 } |
|
4441 |
|
4442 |
|
4443 static PyObject* |
|
4444 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args) |
|
4445 { |
|
4446 int err, max; |
|
4447 |
|
4448 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max)) |
|
4449 return NULL; |
|
4450 CHECK_ENV_NOT_CLOSED(self); |
|
4451 |
|
4452 MYDB_BEGIN_ALLOW_THREADS; |
|
4453 err = self->db_env->set_lk_max_objects(self->db_env, max); |
|
4454 MYDB_END_ALLOW_THREADS; |
|
4455 RETURN_IF_ERR(); |
|
4456 RETURN_NONE(); |
|
4457 } |
|
4458 |
|
4459 |
|
4460 static PyObject* |
|
4461 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args) |
|
4462 { |
|
4463 int err, mp_mmapsize; |
|
4464 |
|
4465 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize)) |
|
4466 return NULL; |
|
4467 CHECK_ENV_NOT_CLOSED(self); |
|
4468 |
|
4469 MYDB_BEGIN_ALLOW_THREADS; |
|
4470 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize); |
|
4471 MYDB_END_ALLOW_THREADS; |
|
4472 RETURN_IF_ERR(); |
|
4473 RETURN_NONE(); |
|
4474 } |
|
4475 |
|
4476 |
|
4477 static PyObject* |
|
4478 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args) |
|
4479 { |
|
4480 int err; |
|
4481 char *dir; |
|
4482 |
|
4483 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir)) |
|
4484 return NULL; |
|
4485 CHECK_ENV_NOT_CLOSED(self); |
|
4486 |
|
4487 MYDB_BEGIN_ALLOW_THREADS; |
|
4488 err = self->db_env->set_tmp_dir(self->db_env, dir); |
|
4489 MYDB_END_ALLOW_THREADS; |
|
4490 RETURN_IF_ERR(); |
|
4491 RETURN_NONE(); |
|
4492 } |
|
4493 |
|
4494 |
|
4495 static PyObject* |
|
4496 DBEnv_txn_recover(DBEnvObject* self) |
|
4497 { |
|
4498 int flags = DB_FIRST; |
|
4499 int err, i; |
|
4500 PyObject *list, *tuple, *gid; |
|
4501 DBTxnObject *txn; |
|
4502 #define PREPLIST_LEN 16 |
|
4503 DB_PREPLIST preplist[PREPLIST_LEN]; |
|
4504 long retp; |
|
4505 |
|
4506 CHECK_ENV_NOT_CLOSED(self); |
|
4507 |
|
4508 list=PyList_New(0); |
|
4509 if (!list) |
|
4510 return NULL; |
|
4511 while (!0) { |
|
4512 MYDB_BEGIN_ALLOW_THREADS |
|
4513 err=self->db_env->txn_recover(self->db_env, |
|
4514 preplist, PREPLIST_LEN, &retp, flags); |
|
4515 #undef PREPLIST_LEN |
|
4516 MYDB_END_ALLOW_THREADS |
|
4517 if (err) { |
|
4518 Py_DECREF(list); |
|
4519 RETURN_IF_ERR(); |
|
4520 } |
|
4521 if (!retp) break; |
|
4522 flags=DB_NEXT; /* Prepare for next loop pass */ |
|
4523 for (i=0; i<retp; i++) { |
|
4524 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid), |
|
4525 DB_XIDDATASIZE); |
|
4526 if (!gid) { |
|
4527 Py_DECREF(list); |
|
4528 return NULL; |
|
4529 } |
|
4530 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags); |
|
4531 if (!txn) { |
|
4532 Py_DECREF(list); |
|
4533 Py_DECREF(gid); |
|
4534 return NULL; |
|
4535 } |
|
4536 txn->flag_prepare=1; /* Recover state */ |
|
4537 tuple=PyTuple_New(2); |
|
4538 if (!tuple) { |
|
4539 Py_DECREF(list); |
|
4540 Py_DECREF(gid); |
|
4541 Py_DECREF(txn); |
|
4542 return NULL; |
|
4543 } |
|
4544 if (PyTuple_SetItem(tuple, 0, gid)) { |
|
4545 Py_DECREF(list); |
|
4546 Py_DECREF(gid); |
|
4547 Py_DECREF(txn); |
|
4548 Py_DECREF(tuple); |
|
4549 return NULL; |
|
4550 } |
|
4551 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) { |
|
4552 Py_DECREF(list); |
|
4553 Py_DECREF(txn); |
|
4554 Py_DECREF(tuple); /* This delete the "gid" also */ |
|
4555 return NULL; |
|
4556 } |
|
4557 if (PyList_Append(list, tuple)) { |
|
4558 Py_DECREF(list); |
|
4559 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */ |
|
4560 return NULL; |
|
4561 } |
|
4562 Py_DECREF(tuple); |
|
4563 } |
|
4564 } |
|
4565 return list; |
|
4566 } |
|
4567 |
|
4568 static PyObject* |
|
4569 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs) |
|
4570 { |
|
4571 int flags = 0; |
|
4572 PyObject* txnobj = NULL; |
|
4573 DB_TXN *txn = NULL; |
|
4574 static char* kwnames[] = { "parent", "flags", NULL }; |
|
4575 |
|
4576 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames, |
|
4577 &txnobj, &flags)) |
|
4578 return NULL; |
|
4579 |
|
4580 if (!checkTxnObj(txnobj, &txn)) |
|
4581 return NULL; |
|
4582 CHECK_ENV_NOT_CLOSED(self); |
|
4583 |
|
4584 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags); |
|
4585 } |
|
4586 |
|
4587 |
|
4588 static PyObject* |
|
4589 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args) |
|
4590 { |
|
4591 int err, kbyte=0, min=0, flags=0; |
|
4592 |
|
4593 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags)) |
|
4594 return NULL; |
|
4595 CHECK_ENV_NOT_CLOSED(self); |
|
4596 |
|
4597 MYDB_BEGIN_ALLOW_THREADS; |
|
4598 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags); |
|
4599 MYDB_END_ALLOW_THREADS; |
|
4600 RETURN_IF_ERR(); |
|
4601 RETURN_NONE(); |
|
4602 } |
|
4603 |
|
4604 |
|
4605 static PyObject* |
|
4606 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args) |
|
4607 { |
|
4608 int err, max; |
|
4609 |
|
4610 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max)) |
|
4611 return NULL; |
|
4612 CHECK_ENV_NOT_CLOSED(self); |
|
4613 |
|
4614 err = self->db_env->set_tx_max(self->db_env, max); |
|
4615 RETURN_IF_ERR(); |
|
4616 RETURN_NONE(); |
|
4617 } |
|
4618 |
|
4619 |
|
4620 static PyObject* |
|
4621 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args) |
|
4622 { |
|
4623 int err; |
|
4624 long stamp; |
|
4625 time_t timestamp; |
|
4626 |
|
4627 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp)) |
|
4628 return NULL; |
|
4629 CHECK_ENV_NOT_CLOSED(self); |
|
4630 timestamp = (time_t)stamp; |
|
4631 err = self->db_env->set_tx_timestamp(self->db_env, ×tamp); |
|
4632 RETURN_IF_ERR(); |
|
4633 RETURN_NONE(); |
|
4634 } |
|
4635 |
|
4636 |
|
4637 static PyObject* |
|
4638 DBEnv_lock_detect(DBEnvObject* self, PyObject* args) |
|
4639 { |
|
4640 int err, atype, flags=0; |
|
4641 int aborted = 0; |
|
4642 |
|
4643 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags)) |
|
4644 return NULL; |
|
4645 CHECK_ENV_NOT_CLOSED(self); |
|
4646 |
|
4647 MYDB_BEGIN_ALLOW_THREADS; |
|
4648 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted); |
|
4649 MYDB_END_ALLOW_THREADS; |
|
4650 RETURN_IF_ERR(); |
|
4651 return NUMBER_FromLong(aborted); |
|
4652 } |
|
4653 |
|
4654 |
|
4655 static PyObject* |
|
4656 DBEnv_lock_get(DBEnvObject* self, PyObject* args) |
|
4657 { |
|
4658 int flags=0; |
|
4659 int locker, lock_mode; |
|
4660 DBT obj; |
|
4661 PyObject* objobj; |
|
4662 |
|
4663 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags)) |
|
4664 return NULL; |
|
4665 |
|
4666 |
|
4667 if (!make_dbt(objobj, &obj)) |
|
4668 return NULL; |
|
4669 |
|
4670 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags); |
|
4671 } |
|
4672 |
|
4673 |
|
4674 static PyObject* |
|
4675 DBEnv_lock_id(DBEnvObject* self) |
|
4676 { |
|
4677 int err; |
|
4678 u_int32_t theID; |
|
4679 |
|
4680 CHECK_ENV_NOT_CLOSED(self); |
|
4681 MYDB_BEGIN_ALLOW_THREADS; |
|
4682 err = self->db_env->lock_id(self->db_env, &theID); |
|
4683 MYDB_END_ALLOW_THREADS; |
|
4684 RETURN_IF_ERR(); |
|
4685 |
|
4686 return NUMBER_FromLong((long)theID); |
|
4687 } |
|
4688 |
|
4689 static PyObject* |
|
4690 DBEnv_lock_id_free(DBEnvObject* self, PyObject* args) |
|
4691 { |
|
4692 int err; |
|
4693 u_int32_t theID; |
|
4694 |
|
4695 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID)) |
|
4696 return NULL; |
|
4697 |
|
4698 CHECK_ENV_NOT_CLOSED(self); |
|
4699 MYDB_BEGIN_ALLOW_THREADS; |
|
4700 err = self->db_env->lock_id_free(self->db_env, theID); |
|
4701 MYDB_END_ALLOW_THREADS; |
|
4702 RETURN_IF_ERR(); |
|
4703 RETURN_NONE(); |
|
4704 } |
|
4705 |
|
4706 static PyObject* |
|
4707 DBEnv_lock_put(DBEnvObject* self, PyObject* args) |
|
4708 { |
|
4709 int err; |
|
4710 DBLockObject* dblockobj; |
|
4711 |
|
4712 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj)) |
|
4713 return NULL; |
|
4714 |
|
4715 CHECK_ENV_NOT_CLOSED(self); |
|
4716 MYDB_BEGIN_ALLOW_THREADS; |
|
4717 err = self->db_env->lock_put(self->db_env, &dblockobj->lock); |
|
4718 MYDB_END_ALLOW_THREADS; |
|
4719 RETURN_IF_ERR(); |
|
4720 RETURN_NONE(); |
|
4721 } |
|
4722 |
|
4723 #if (DBVER >= 44) |
|
4724 static PyObject* |
|
4725 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs) |
|
4726 { |
|
4727 int err; |
|
4728 char *file; |
|
4729 u_int32_t flags = 0; |
|
4730 static char* kwnames[] = { "file", "flags", NULL}; |
|
4731 |
|
4732 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames, |
|
4733 &file, &flags)) |
|
4734 return NULL; |
|
4735 CHECK_ENV_NOT_CLOSED(self); |
|
4736 |
|
4737 MYDB_BEGIN_ALLOW_THREADS; |
|
4738 err = self->db_env->lsn_reset(self->db_env, file, flags); |
|
4739 MYDB_END_ALLOW_THREADS; |
|
4740 RETURN_IF_ERR(); |
|
4741 RETURN_NONE(); |
|
4742 } |
|
4743 #endif /* DBVER >= 4.4 */ |
|
4744 |
|
4745 static PyObject* |
|
4746 DBEnv_log_stat(DBEnvObject* self, PyObject* args) |
|
4747 { |
|
4748 int err; |
|
4749 DB_LOG_STAT* statp = NULL; |
|
4750 PyObject* d = NULL; |
|
4751 u_int32_t flags = 0; |
|
4752 |
|
4753 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags)) |
|
4754 return NULL; |
|
4755 CHECK_ENV_NOT_CLOSED(self); |
|
4756 |
|
4757 MYDB_BEGIN_ALLOW_THREADS; |
|
4758 err = self->db_env->log_stat(self->db_env, &statp, flags); |
|
4759 MYDB_END_ALLOW_THREADS; |
|
4760 RETURN_IF_ERR(); |
|
4761 |
|
4762 /* Turn the stat structure into a dictionary */ |
|
4763 d = PyDict_New(); |
|
4764 if (d == NULL) { |
|
4765 if (statp) |
|
4766 free(statp); |
|
4767 return NULL; |
|
4768 } |
|
4769 |
|
4770 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name) |
|
4771 |
|
4772 MAKE_ENTRY(magic); |
|
4773 MAKE_ENTRY(version); |
|
4774 MAKE_ENTRY(mode); |
|
4775 MAKE_ENTRY(lg_bsize); |
|
4776 #if (DBVER >= 44) |
|
4777 MAKE_ENTRY(lg_size); |
|
4778 MAKE_ENTRY(record); |
|
4779 #endif |
|
4780 #if (DBVER < 41) |
|
4781 MAKE_ENTRY(lg_max); |
|
4782 #endif |
|
4783 MAKE_ENTRY(w_mbytes); |
|
4784 MAKE_ENTRY(w_bytes); |
|
4785 MAKE_ENTRY(wc_mbytes); |
|
4786 MAKE_ENTRY(wc_bytes); |
|
4787 MAKE_ENTRY(wcount); |
|
4788 MAKE_ENTRY(wcount_fill); |
|
4789 #if (DBVER >= 44) |
|
4790 MAKE_ENTRY(rcount); |
|
4791 #endif |
|
4792 MAKE_ENTRY(scount); |
|
4793 MAKE_ENTRY(cur_file); |
|
4794 MAKE_ENTRY(cur_offset); |
|
4795 MAKE_ENTRY(disk_file); |
|
4796 MAKE_ENTRY(disk_offset); |
|
4797 MAKE_ENTRY(maxcommitperflush); |
|
4798 MAKE_ENTRY(mincommitperflush); |
|
4799 MAKE_ENTRY(regsize); |
|
4800 MAKE_ENTRY(region_wait); |
|
4801 MAKE_ENTRY(region_nowait); |
|
4802 |
|
4803 #undef MAKE_ENTRY |
|
4804 free(statp); |
|
4805 return d; |
|
4806 } /* DBEnv_log_stat */ |
|
4807 |
|
4808 |
|
4809 static PyObject* |
|
4810 DBEnv_lock_stat(DBEnvObject* self, PyObject* args) |
|
4811 { |
|
4812 int err; |
|
4813 DB_LOCK_STAT* sp; |
|
4814 PyObject* d = NULL; |
|
4815 u_int32_t flags = 0; |
|
4816 |
|
4817 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags)) |
|
4818 return NULL; |
|
4819 CHECK_ENV_NOT_CLOSED(self); |
|
4820 |
|
4821 MYDB_BEGIN_ALLOW_THREADS; |
|
4822 err = self->db_env->lock_stat(self->db_env, &sp, flags); |
|
4823 MYDB_END_ALLOW_THREADS; |
|
4824 RETURN_IF_ERR(); |
|
4825 |
|
4826 /* Turn the stat structure into a dictionary */ |
|
4827 d = PyDict_New(); |
|
4828 if (d == NULL) { |
|
4829 free(sp); |
|
4830 return NULL; |
|
4831 } |
|
4832 |
|
4833 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) |
|
4834 |
|
4835 #if (DBVER < 41) |
|
4836 MAKE_ENTRY(lastid); |
|
4837 #endif |
|
4838 #if (DBVER >=41) |
|
4839 MAKE_ENTRY(id); |
|
4840 MAKE_ENTRY(cur_maxid); |
|
4841 #endif |
|
4842 MAKE_ENTRY(nmodes); |
|
4843 MAKE_ENTRY(maxlocks); |
|
4844 MAKE_ENTRY(maxlockers); |
|
4845 MAKE_ENTRY(maxobjects); |
|
4846 MAKE_ENTRY(nlocks); |
|
4847 MAKE_ENTRY(maxnlocks); |
|
4848 MAKE_ENTRY(nlockers); |
|
4849 MAKE_ENTRY(maxnlockers); |
|
4850 MAKE_ENTRY(nobjects); |
|
4851 MAKE_ENTRY(maxnobjects); |
|
4852 MAKE_ENTRY(nrequests); |
|
4853 MAKE_ENTRY(nreleases); |
|
4854 #if (DBVER >= 44) |
|
4855 MAKE_ENTRY(nupgrade); |
|
4856 MAKE_ENTRY(ndowngrade); |
|
4857 #endif |
|
4858 #if (DBVER < 44) |
|
4859 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */ |
|
4860 MAKE_ENTRY(nconflicts); |
|
4861 #else |
|
4862 MAKE_ENTRY(lock_nowait); |
|
4863 MAKE_ENTRY(lock_wait); |
|
4864 #endif |
|
4865 MAKE_ENTRY(ndeadlocks); |
|
4866 #if (DBVER >= 41) |
|
4867 MAKE_ENTRY(locktimeout); |
|
4868 MAKE_ENTRY(txntimeout); |
|
4869 #endif |
|
4870 MAKE_ENTRY(nlocktimeouts); |
|
4871 MAKE_ENTRY(ntxntimeouts); |
|
4872 #if (DBVER >= 46) |
|
4873 MAKE_ENTRY(objs_wait); |
|
4874 MAKE_ENTRY(objs_nowait); |
|
4875 MAKE_ENTRY(lockers_wait); |
|
4876 MAKE_ENTRY(lockers_nowait); |
|
4877 #if (DBVER >= 47) |
|
4878 MAKE_ENTRY(lock_wait); |
|
4879 MAKE_ENTRY(lock_nowait); |
|
4880 #else |
|
4881 MAKE_ENTRY(locks_wait); |
|
4882 MAKE_ENTRY(locks_nowait); |
|
4883 #endif |
|
4884 MAKE_ENTRY(hash_len); |
|
4885 #endif |
|
4886 MAKE_ENTRY(regsize); |
|
4887 MAKE_ENTRY(region_wait); |
|
4888 MAKE_ENTRY(region_nowait); |
|
4889 |
|
4890 #undef MAKE_ENTRY |
|
4891 free(sp); |
|
4892 return d; |
|
4893 } |
|
4894 |
|
4895 static PyObject* |
|
4896 DBEnv_log_flush(DBEnvObject* self) |
|
4897 { |
|
4898 int err; |
|
4899 |
|
4900 CHECK_ENV_NOT_CLOSED(self); |
|
4901 |
|
4902 MYDB_BEGIN_ALLOW_THREADS |
|
4903 err = self->db_env->log_flush(self->db_env, NULL); |
|
4904 MYDB_END_ALLOW_THREADS |
|
4905 |
|
4906 RETURN_IF_ERR(); |
|
4907 RETURN_NONE(); |
|
4908 } |
|
4909 |
|
4910 static PyObject* |
|
4911 DBEnv_log_archive(DBEnvObject* self, PyObject* args) |
|
4912 { |
|
4913 int flags=0; |
|
4914 int err; |
|
4915 char **log_list = NULL; |
|
4916 PyObject* list; |
|
4917 PyObject* item = NULL; |
|
4918 |
|
4919 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags)) |
|
4920 return NULL; |
|
4921 |
|
4922 CHECK_ENV_NOT_CLOSED(self); |
|
4923 MYDB_BEGIN_ALLOW_THREADS; |
|
4924 err = self->db_env->log_archive(self->db_env, &log_list, flags); |
|
4925 MYDB_END_ALLOW_THREADS; |
|
4926 RETURN_IF_ERR(); |
|
4927 |
|
4928 list = PyList_New(0); |
|
4929 if (list == NULL) { |
|
4930 if (log_list) |
|
4931 free(log_list); |
|
4932 return NULL; |
|
4933 } |
|
4934 |
|
4935 if (log_list) { |
|
4936 char **log_list_start; |
|
4937 for (log_list_start = log_list; *log_list != NULL; ++log_list) { |
|
4938 item = PyBytes_FromString (*log_list); |
|
4939 if (item == NULL) { |
|
4940 Py_DECREF(list); |
|
4941 list = NULL; |
|
4942 break; |
|
4943 } |
|
4944 if (PyList_Append(list, item)) { |
|
4945 Py_DECREF(list); |
|
4946 list = NULL; |
|
4947 Py_DECREF(item); |
|
4948 break; |
|
4949 } |
|
4950 Py_DECREF(item); |
|
4951 } |
|
4952 free(log_list_start); |
|
4953 } |
|
4954 return list; |
|
4955 } |
|
4956 |
|
4957 |
|
4958 static PyObject* |
|
4959 DBEnv_txn_stat(DBEnvObject* self, PyObject* args) |
|
4960 { |
|
4961 int err; |
|
4962 DB_TXN_STAT* sp; |
|
4963 PyObject* d = NULL; |
|
4964 u_int32_t flags=0; |
|
4965 |
|
4966 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags)) |
|
4967 return NULL; |
|
4968 CHECK_ENV_NOT_CLOSED(self); |
|
4969 |
|
4970 MYDB_BEGIN_ALLOW_THREADS; |
|
4971 err = self->db_env->txn_stat(self->db_env, &sp, flags); |
|
4972 MYDB_END_ALLOW_THREADS; |
|
4973 RETURN_IF_ERR(); |
|
4974 |
|
4975 /* Turn the stat structure into a dictionary */ |
|
4976 d = PyDict_New(); |
|
4977 if (d == NULL) { |
|
4978 free(sp); |
|
4979 return NULL; |
|
4980 } |
|
4981 |
|
4982 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) |
|
4983 #define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name) |
|
4984 #define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name) |
|
4985 |
|
4986 MAKE_DB_LSN_ENTRY(last_ckp); |
|
4987 MAKE_TIME_T_ENTRY(time_ckp); |
|
4988 MAKE_ENTRY(last_txnid); |
|
4989 MAKE_ENTRY(maxtxns); |
|
4990 MAKE_ENTRY(nactive); |
|
4991 MAKE_ENTRY(maxnactive); |
|
4992 #if (DBVER >= 45) |
|
4993 MAKE_ENTRY(nsnapshot); |
|
4994 MAKE_ENTRY(maxnsnapshot); |
|
4995 #endif |
|
4996 MAKE_ENTRY(nbegins); |
|
4997 MAKE_ENTRY(naborts); |
|
4998 MAKE_ENTRY(ncommits); |
|
4999 MAKE_ENTRY(nrestores); |
|
5000 MAKE_ENTRY(regsize); |
|
5001 MAKE_ENTRY(region_wait); |
|
5002 MAKE_ENTRY(region_nowait); |
|
5003 |
|
5004 #undef MAKE_DB_LSN_ENTRY |
|
5005 #undef MAKE_ENTRY |
|
5006 #undef MAKE_TIME_T_ENTRY |
|
5007 free(sp); |
|
5008 return d; |
|
5009 } |
|
5010 |
|
5011 |
|
5012 static PyObject* |
|
5013 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args) |
|
5014 { |
|
5015 int flags=0; |
|
5016 int oldValue=0; |
|
5017 |
|
5018 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags)) |
|
5019 return NULL; |
|
5020 CHECK_ENV_NOT_CLOSED(self); |
|
5021 |
|
5022 if (self->moduleFlags.getReturnsNone) |
|
5023 ++oldValue; |
|
5024 if (self->moduleFlags.cursorSetReturnsNone) |
|
5025 ++oldValue; |
|
5026 self->moduleFlags.getReturnsNone = (flags >= 1); |
|
5027 self->moduleFlags.cursorSetReturnsNone = (flags >= 2); |
|
5028 return NUMBER_FromLong(oldValue); |
|
5029 } |
|
5030 |
|
5031 static PyObject* |
|
5032 DBEnv_get_private(DBEnvObject* self) |
|
5033 { |
|
5034 /* We can give out the private field even if dbenv is closed */ |
|
5035 Py_INCREF(self->private_obj); |
|
5036 return self->private_obj; |
|
5037 } |
|
5038 |
|
5039 static PyObject* |
|
5040 DBEnv_set_private(DBEnvObject* self, PyObject* private_obj) |
|
5041 { |
|
5042 /* We can set the private field even if dbenv is closed */ |
|
5043 Py_DECREF(self->private_obj); |
|
5044 Py_INCREF(private_obj); |
|
5045 self->private_obj = private_obj; |
|
5046 RETURN_NONE(); |
|
5047 } |
|
5048 |
|
5049 |
|
5050 static PyObject* |
|
5051 DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs) |
|
5052 { |
|
5053 int err; |
|
5054 char *host; |
|
5055 long cl_timeout=0, sv_timeout=0; |
|
5056 |
|
5057 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL}; |
|
5058 |
|
5059 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames, |
|
5060 &host, &cl_timeout, &sv_timeout)) |
|
5061 return NULL; |
|
5062 CHECK_ENV_NOT_CLOSED(self); |
|
5063 |
|
5064 MYDB_BEGIN_ALLOW_THREADS; |
|
5065 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout, |
|
5066 sv_timeout, 0); |
|
5067 MYDB_END_ALLOW_THREADS; |
|
5068 RETURN_IF_ERR(); |
|
5069 RETURN_NONE(); |
|
5070 } |
|
5071 |
|
5072 static PyObject* |
|
5073 DBEnv_set_verbose(DBEnvObject* self, PyObject* args) |
|
5074 { |
|
5075 int err; |
|
5076 int which, onoff; |
|
5077 |
|
5078 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) { |
|
5079 return NULL; |
|
5080 } |
|
5081 CHECK_ENV_NOT_CLOSED(self); |
|
5082 MYDB_BEGIN_ALLOW_THREADS; |
|
5083 err = self->db_env->set_verbose(self->db_env, which, onoff); |
|
5084 MYDB_END_ALLOW_THREADS; |
|
5085 RETURN_IF_ERR(); |
|
5086 RETURN_NONE(); |
|
5087 } |
|
5088 |
|
5089 #if (DBVER >= 42) |
|
5090 static PyObject* |
|
5091 DBEnv_get_verbose(DBEnvObject* self, PyObject* args) |
|
5092 { |
|
5093 int err; |
|
5094 int which; |
|
5095 int verbose; |
|
5096 |
|
5097 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) { |
|
5098 return NULL; |
|
5099 } |
|
5100 CHECK_ENV_NOT_CLOSED(self); |
|
5101 MYDB_BEGIN_ALLOW_THREADS; |
|
5102 err = self->db_env->get_verbose(self->db_env, which, &verbose); |
|
5103 MYDB_END_ALLOW_THREADS; |
|
5104 RETURN_IF_ERR(); |
|
5105 return PyBool_FromLong(verbose); |
|
5106 } |
|
5107 #endif |
|
5108 |
|
5109 #if (DBVER >= 45) |
|
5110 static void |
|
5111 _dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info) |
|
5112 { |
|
5113 DBEnvObject *dbenv; |
|
5114 PyObject* callback; |
|
5115 PyObject* args; |
|
5116 PyObject* result = NULL; |
|
5117 |
|
5118 MYDB_BEGIN_BLOCK_THREADS; |
|
5119 dbenv = (DBEnvObject *)db_env->app_private; |
|
5120 callback = dbenv->event_notifyCallback; |
|
5121 if (callback) { |
|
5122 if (event == DB_EVENT_REP_NEWMASTER) { |
|
5123 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info)); |
|
5124 } else { |
|
5125 args = Py_BuildValue("(OiO)", dbenv, event, Py_None); |
|
5126 } |
|
5127 if (args) { |
|
5128 result = PyEval_CallObject(callback, args); |
|
5129 } |
|
5130 if ((!args) || (!result)) { |
|
5131 PyErr_Print(); |
|
5132 } |
|
5133 Py_XDECREF(args); |
|
5134 Py_XDECREF(result); |
|
5135 } |
|
5136 MYDB_END_BLOCK_THREADS; |
|
5137 } |
|
5138 #endif |
|
5139 |
|
5140 #if (DBVER >= 45) |
|
5141 static PyObject* |
|
5142 DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc) |
|
5143 { |
|
5144 int err; |
|
5145 |
|
5146 CHECK_ENV_NOT_CLOSED(self); |
|
5147 |
|
5148 if (!PyCallable_Check(notifyFunc)) { |
|
5149 makeTypeError("Callable", notifyFunc); |
|
5150 return NULL; |
|
5151 } |
|
5152 |
|
5153 Py_XDECREF(self->event_notifyCallback); |
|
5154 Py_INCREF(notifyFunc); |
|
5155 self->event_notifyCallback = notifyFunc; |
|
5156 |
|
5157 /* This is to workaround a problem with un-initialized threads (see |
|
5158 comment in DB_associate) */ |
|
5159 #ifdef WITH_THREAD |
|
5160 PyEval_InitThreads(); |
|
5161 #endif |
|
5162 |
|
5163 MYDB_BEGIN_ALLOW_THREADS; |
|
5164 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback); |
|
5165 MYDB_END_ALLOW_THREADS; |
|
5166 |
|
5167 if (err) { |
|
5168 Py_DECREF(notifyFunc); |
|
5169 self->event_notifyCallback = NULL; |
|
5170 } |
|
5171 |
|
5172 RETURN_IF_ERR(); |
|
5173 RETURN_NONE(); |
|
5174 } |
|
5175 #endif |
|
5176 |
|
5177 |
|
5178 /* --------------------------------------------------------------------- */ |
|
5179 /* REPLICATION METHODS: Base Replication */ |
|
5180 |
|
5181 |
|
5182 static PyObject* |
|
5183 DBEnv_rep_process_message(DBEnvObject* self, PyObject* args) |
|
5184 { |
|
5185 int err; |
|
5186 PyObject *control_py, *rec_py; |
|
5187 DBT control, rec; |
|
5188 int envid; |
|
5189 #if (DBVER >= 42) |
|
5190 DB_LSN lsn; |
|
5191 #endif |
|
5192 |
|
5193 if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py, |
|
5194 &rec_py, &envid)) |
|
5195 return NULL; |
|
5196 CHECK_ENV_NOT_CLOSED(self); |
|
5197 |
|
5198 if (!make_dbt(control_py, &control)) |
|
5199 return NULL; |
|
5200 if (!make_dbt(rec_py, &rec)) |
|
5201 return NULL; |
|
5202 |
|
5203 MYDB_BEGIN_ALLOW_THREADS; |
|
5204 #if (DBVER >= 46) |
|
5205 err = self->db_env->rep_process_message(self->db_env, &control, &rec, |
|
5206 envid, &lsn); |
|
5207 #else |
|
5208 #if (DBVER >= 42) |
|
5209 err = self->db_env->rep_process_message(self->db_env, &control, &rec, |
|
5210 &envid, &lsn); |
|
5211 #else |
|
5212 err = self->db_env->rep_process_message(self->db_env, &control, &rec, |
|
5213 &envid); |
|
5214 #endif |
|
5215 #endif |
|
5216 MYDB_END_ALLOW_THREADS; |
|
5217 switch (err) { |
|
5218 case DB_REP_NEWMASTER : |
|
5219 return Py_BuildValue("(iO)", envid, Py_None); |
|
5220 break; |
|
5221 |
|
5222 case DB_REP_DUPMASTER : |
|
5223 case DB_REP_HOLDELECTION : |
|
5224 #if (DBVER >= 44) |
|
5225 case DB_REP_IGNORE : |
|
5226 case DB_REP_JOIN_FAILURE : |
|
5227 #endif |
|
5228 return Py_BuildValue("(iO)", err, Py_None); |
|
5229 break; |
|
5230 case DB_REP_NEWSITE : |
|
5231 { |
|
5232 PyObject *tmp, *r; |
|
5233 |
|
5234 if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) { |
|
5235 return NULL; |
|
5236 } |
|
5237 |
|
5238 r = Py_BuildValue("(iO)", err, tmp); |
|
5239 Py_DECREF(tmp); |
|
5240 return r; |
|
5241 break; |
|
5242 } |
|
5243 #if (DBVER >= 42) |
|
5244 case DB_REP_NOTPERM : |
|
5245 case DB_REP_ISPERM : |
|
5246 return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset); |
|
5247 break; |
|
5248 #endif |
|
5249 } |
|
5250 RETURN_IF_ERR(); |
|
5251 return Py_BuildValue("(OO)", Py_None, Py_None); |
|
5252 } |
|
5253 |
|
5254 static int |
|
5255 _DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec, |
|
5256 const DB_LSN *lsn, int envid, u_int32_t flags) |
|
5257 { |
|
5258 DBEnvObject *dbenv; |
|
5259 PyObject* rep_transport; |
|
5260 PyObject* args; |
|
5261 PyObject *a, *b; |
|
5262 PyObject* result = NULL; |
|
5263 int ret=0; |
|
5264 |
|
5265 MYDB_BEGIN_BLOCK_THREADS; |
|
5266 dbenv = (DBEnvObject *)db_env->app_private; |
|
5267 rep_transport = dbenv->rep_transport; |
|
5268 |
|
5269 /* |
|
5270 ** The errors in 'a' or 'b' are detected in "Py_BuildValue". |
|
5271 */ |
|
5272 a = PyBytes_FromStringAndSize(control->data, control->size); |
|
5273 b = PyBytes_FromStringAndSize(rec->data, rec->size); |
|
5274 |
|
5275 args = Py_BuildValue( |
|
5276 #if (PY_VERSION_HEX >= 0x02040000) |
|
5277 "(OOO(ll)iI)", |
|
5278 #else |
|
5279 "(OOO(ll)ii)", |
|
5280 #endif |
|
5281 dbenv, |
|
5282 a, b, |
|
5283 lsn->file, lsn->offset, envid, flags); |
|
5284 if (args) { |
|
5285 result = PyEval_CallObject(rep_transport, args); |
|
5286 } |
|
5287 |
|
5288 if ((!args) || (!result)) { |
|
5289 PyErr_Print(); |
|
5290 ret = -1; |
|
5291 } |
|
5292 Py_XDECREF(a); |
|
5293 Py_XDECREF(b); |
|
5294 Py_XDECREF(args); |
|
5295 Py_XDECREF(result); |
|
5296 MYDB_END_BLOCK_THREADS; |
|
5297 return ret; |
|
5298 } |
|
5299 |
|
5300 #if (DBVER <= 41) |
|
5301 static int |
|
5302 _DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec, |
|
5303 int envid, u_int32_t flags) |
|
5304 { |
|
5305 DB_LSN lsn; |
|
5306 |
|
5307 lsn.file = -1; /* Dummy values */ |
|
5308 lsn.offset = -1; |
|
5309 return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid, |
|
5310 flags); |
|
5311 } |
|
5312 #endif |
|
5313 |
|
5314 static PyObject* |
|
5315 DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args) |
|
5316 { |
|
5317 int err; |
|
5318 int envid; |
|
5319 PyObject *rep_transport; |
|
5320 |
|
5321 if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport)) |
|
5322 return NULL; |
|
5323 CHECK_ENV_NOT_CLOSED(self); |
|
5324 if (!PyCallable_Check(rep_transport)) { |
|
5325 makeTypeError("Callable", rep_transport); |
|
5326 return NULL; |
|
5327 } |
|
5328 |
|
5329 MYDB_BEGIN_ALLOW_THREADS; |
|
5330 #if (DBVER >=45) |
|
5331 err = self->db_env->rep_set_transport(self->db_env, envid, |
|
5332 &_DBEnv_rep_transportCallback); |
|
5333 #else |
|
5334 #if (DBVER >= 42) |
|
5335 err = self->db_env->set_rep_transport(self->db_env, envid, |
|
5336 &_DBEnv_rep_transportCallback); |
|
5337 #else |
|
5338 err = self->db_env->set_rep_transport(self->db_env, envid, |
|
5339 &_DBEnv_rep_transportCallbackOLD); |
|
5340 #endif |
|
5341 #endif |
|
5342 MYDB_END_ALLOW_THREADS; |
|
5343 RETURN_IF_ERR(); |
|
5344 |
|
5345 Py_DECREF(self->rep_transport); |
|
5346 Py_INCREF(rep_transport); |
|
5347 self->rep_transport = rep_transport; |
|
5348 RETURN_NONE(); |
|
5349 } |
|
5350 |
|
5351 #if (DBVER >= 47) |
|
5352 static PyObject* |
|
5353 DBEnv_rep_set_request(DBEnvObject* self, PyObject* args) |
|
5354 { |
|
5355 int err; |
|
5356 unsigned int minimum, maximum; |
|
5357 |
|
5358 if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum)) |
|
5359 return NULL; |
|
5360 CHECK_ENV_NOT_CLOSED(self); |
|
5361 |
|
5362 MYDB_BEGIN_ALLOW_THREADS; |
|
5363 err = self->db_env->rep_set_request(self->db_env, minimum, maximum); |
|
5364 MYDB_END_ALLOW_THREADS; |
|
5365 RETURN_IF_ERR(); |
|
5366 RETURN_NONE(); |
|
5367 } |
|
5368 |
|
5369 static PyObject* |
|
5370 DBEnv_rep_get_request(DBEnvObject* self) |
|
5371 { |
|
5372 int err; |
|
5373 u_int32_t minimum, maximum; |
|
5374 |
|
5375 CHECK_ENV_NOT_CLOSED(self); |
|
5376 MYDB_BEGIN_ALLOW_THREADS; |
|
5377 err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum); |
|
5378 MYDB_END_ALLOW_THREADS; |
|
5379 RETURN_IF_ERR(); |
|
5380 #if (PY_VERSION_HEX >= 0x02040000) |
|
5381 return Py_BuildValue("II", minimum, maximum); |
|
5382 #else |
|
5383 return Py_BuildValue("ii", minimum, maximum); |
|
5384 #endif |
|
5385 } |
|
5386 #endif |
|
5387 |
|
5388 #if (DBVER >= 45) |
|
5389 static PyObject* |
|
5390 DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args) |
|
5391 { |
|
5392 int err; |
|
5393 int limit; |
|
5394 |
|
5395 if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit)) |
|
5396 return NULL; |
|
5397 CHECK_ENV_NOT_CLOSED(self); |
|
5398 |
|
5399 MYDB_BEGIN_ALLOW_THREADS; |
|
5400 err = self->db_env->rep_set_limit(self->db_env, 0, limit); |
|
5401 MYDB_END_ALLOW_THREADS; |
|
5402 RETURN_IF_ERR(); |
|
5403 RETURN_NONE(); |
|
5404 } |
|
5405 |
|
5406 static PyObject* |
|
5407 DBEnv_rep_get_limit(DBEnvObject* self) |
|
5408 { |
|
5409 int err; |
|
5410 u_int32_t gbytes, bytes; |
|
5411 |
|
5412 CHECK_ENV_NOT_CLOSED(self); |
|
5413 MYDB_BEGIN_ALLOW_THREADS; |
|
5414 err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes); |
|
5415 MYDB_END_ALLOW_THREADS; |
|
5416 RETURN_IF_ERR(); |
|
5417 return NUMBER_FromLong(bytes); |
|
5418 } |
|
5419 #endif |
|
5420 |
|
5421 #if (DBVER >= 44) |
|
5422 static PyObject* |
|
5423 DBEnv_rep_set_config(DBEnvObject* self, PyObject* args) |
|
5424 { |
|
5425 int err; |
|
5426 int which; |
|
5427 int onoff; |
|
5428 |
|
5429 if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff)) |
|
5430 return NULL; |
|
5431 CHECK_ENV_NOT_CLOSED(self); |
|
5432 |
|
5433 MYDB_BEGIN_ALLOW_THREADS; |
|
5434 err = self->db_env->rep_set_config(self->db_env, which, onoff); |
|
5435 MYDB_END_ALLOW_THREADS; |
|
5436 RETURN_IF_ERR(); |
|
5437 RETURN_NONE(); |
|
5438 } |
|
5439 |
|
5440 static PyObject* |
|
5441 DBEnv_rep_get_config(DBEnvObject* self, PyObject* args) |
|
5442 { |
|
5443 int err; |
|
5444 int which; |
|
5445 int onoff; |
|
5446 |
|
5447 if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) { |
|
5448 return NULL; |
|
5449 } |
|
5450 CHECK_ENV_NOT_CLOSED(self); |
|
5451 MYDB_BEGIN_ALLOW_THREADS; |
|
5452 err = self->db_env->rep_get_config(self->db_env, which, &onoff); |
|
5453 MYDB_END_ALLOW_THREADS; |
|
5454 RETURN_IF_ERR(); |
|
5455 return PyBool_FromLong(onoff); |
|
5456 } |
|
5457 #endif |
|
5458 |
|
5459 #if (DBVER >= 46) |
|
5460 static PyObject* |
|
5461 DBEnv_rep_elect(DBEnvObject* self, PyObject* args) |
|
5462 { |
|
5463 int err; |
|
5464 u_int32_t nsites, nvotes; |
|
5465 |
|
5466 if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) { |
|
5467 return NULL; |
|
5468 } |
|
5469 CHECK_ENV_NOT_CLOSED(self); |
|
5470 MYDB_BEGIN_ALLOW_THREADS; |
|
5471 err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0); |
|
5472 MYDB_END_ALLOW_THREADS; |
|
5473 RETURN_IF_ERR(); |
|
5474 RETURN_NONE(); |
|
5475 } |
|
5476 #endif |
|
5477 |
|
5478 static PyObject* |
|
5479 DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs) |
|
5480 { |
|
5481 int err; |
|
5482 PyObject *cdata_py = Py_None; |
|
5483 DBT cdata; |
|
5484 int flags; |
|
5485 static char* kwnames[] = {"flags","cdata", NULL}; |
|
5486 |
|
5487 if (!PyArg_ParseTupleAndKeywords(args, kwargs, |
|
5488 "i|O:rep_start", kwnames, &flags, &cdata_py)) |
|
5489 { |
|
5490 return NULL; |
|
5491 } |
|
5492 CHECK_ENV_NOT_CLOSED(self); |
|
5493 |
|
5494 if (!make_dbt(cdata_py, &cdata)) |
|
5495 return NULL; |
|
5496 |
|
5497 MYDB_BEGIN_ALLOW_THREADS; |
|
5498 err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL, |
|
5499 flags); |
|
5500 MYDB_END_ALLOW_THREADS; |
|
5501 RETURN_IF_ERR(); |
|
5502 RETURN_NONE(); |
|
5503 } |
|
5504 |
|
5505 #if (DBVER >= 44) |
|
5506 static PyObject* |
|
5507 DBEnv_rep_sync(DBEnvObject* self) |
|
5508 { |
|
5509 int err; |
|
5510 |
|
5511 CHECK_ENV_NOT_CLOSED(self); |
|
5512 MYDB_BEGIN_ALLOW_THREADS; |
|
5513 err = self->db_env->rep_sync(self->db_env, 0); |
|
5514 MYDB_END_ALLOW_THREADS; |
|
5515 RETURN_IF_ERR(); |
|
5516 RETURN_NONE(); |
|
5517 } |
|
5518 #endif |
|
5519 |
|
5520 |
|
5521 #if (DBVER >= 45) |
|
5522 static PyObject* |
|
5523 DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args) |
|
5524 { |
|
5525 int err; |
|
5526 int nsites; |
|
5527 |
|
5528 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) { |
|
5529 return NULL; |
|
5530 } |
|
5531 CHECK_ENV_NOT_CLOSED(self); |
|
5532 MYDB_BEGIN_ALLOW_THREADS; |
|
5533 err = self->db_env->rep_set_nsites(self->db_env, nsites); |
|
5534 MYDB_END_ALLOW_THREADS; |
|
5535 RETURN_IF_ERR(); |
|
5536 RETURN_NONE(); |
|
5537 } |
|
5538 |
|
5539 static PyObject* |
|
5540 DBEnv_rep_get_nsites(DBEnvObject* self) |
|
5541 { |
|
5542 int err; |
|
5543 #if (DBVER >= 47) |
|
5544 u_int32_t nsites; |
|
5545 #else |
|
5546 int nsites; |
|
5547 #endif |
|
5548 |
|
5549 CHECK_ENV_NOT_CLOSED(self); |
|
5550 MYDB_BEGIN_ALLOW_THREADS; |
|
5551 err = self->db_env->rep_get_nsites(self->db_env, &nsites); |
|
5552 MYDB_END_ALLOW_THREADS; |
|
5553 RETURN_IF_ERR(); |
|
5554 return NUMBER_FromLong(nsites); |
|
5555 } |
|
5556 |
|
5557 static PyObject* |
|
5558 DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args) |
|
5559 { |
|
5560 int err; |
|
5561 int priority; |
|
5562 |
|
5563 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) { |
|
5564 return NULL; |
|
5565 } |
|
5566 CHECK_ENV_NOT_CLOSED(self); |
|
5567 MYDB_BEGIN_ALLOW_THREADS; |
|
5568 err = self->db_env->rep_set_priority(self->db_env, priority); |
|
5569 MYDB_END_ALLOW_THREADS; |
|
5570 RETURN_IF_ERR(); |
|
5571 RETURN_NONE(); |
|
5572 } |
|
5573 |
|
5574 static PyObject* |
|
5575 DBEnv_rep_get_priority(DBEnvObject* self) |
|
5576 { |
|
5577 int err; |
|
5578 #if (DBVER >= 47) |
|
5579 u_int32_t priority; |
|
5580 #else |
|
5581 int priority; |
|
5582 #endif |
|
5583 |
|
5584 CHECK_ENV_NOT_CLOSED(self); |
|
5585 MYDB_BEGIN_ALLOW_THREADS; |
|
5586 err = self->db_env->rep_get_priority(self->db_env, &priority); |
|
5587 MYDB_END_ALLOW_THREADS; |
|
5588 RETURN_IF_ERR(); |
|
5589 return NUMBER_FromLong(priority); |
|
5590 } |
|
5591 |
|
5592 static PyObject* |
|
5593 DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args) |
|
5594 { |
|
5595 int err; |
|
5596 int which, timeout; |
|
5597 |
|
5598 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) { |
|
5599 return NULL; |
|
5600 } |
|
5601 CHECK_ENV_NOT_CLOSED(self); |
|
5602 MYDB_BEGIN_ALLOW_THREADS; |
|
5603 err = self->db_env->rep_set_timeout(self->db_env, which, timeout); |
|
5604 MYDB_END_ALLOW_THREADS; |
|
5605 RETURN_IF_ERR(); |
|
5606 RETURN_NONE(); |
|
5607 } |
|
5608 |
|
5609 static PyObject* |
|
5610 DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args) |
|
5611 { |
|
5612 int err; |
|
5613 int which; |
|
5614 u_int32_t timeout; |
|
5615 |
|
5616 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) { |
|
5617 return NULL; |
|
5618 } |
|
5619 CHECK_ENV_NOT_CLOSED(self); |
|
5620 MYDB_BEGIN_ALLOW_THREADS; |
|
5621 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout); |
|
5622 MYDB_END_ALLOW_THREADS; |
|
5623 RETURN_IF_ERR(); |
|
5624 return NUMBER_FromLong(timeout); |
|
5625 } |
|
5626 #endif |
|
5627 |
|
5628 /* --------------------------------------------------------------------- */ |
|
5629 /* REPLICATION METHODS: Replication Manager */ |
|
5630 |
|
5631 #if (DBVER >= 45) |
|
5632 static PyObject* |
|
5633 DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject* |
|
5634 kwargs) |
|
5635 { |
|
5636 int err; |
|
5637 int nthreads, flags; |
|
5638 static char* kwnames[] = {"nthreads","flags", NULL}; |
|
5639 |
|
5640 if (!PyArg_ParseTupleAndKeywords(args, kwargs, |
|
5641 "ii:repmgr_start", kwnames, &nthreads, &flags)) |
|
5642 { |
|
5643 return NULL; |
|
5644 } |
|
5645 CHECK_ENV_NOT_CLOSED(self); |
|
5646 MYDB_BEGIN_ALLOW_THREADS; |
|
5647 err = self->db_env->repmgr_start(self->db_env, nthreads, flags); |
|
5648 MYDB_END_ALLOW_THREADS; |
|
5649 RETURN_IF_ERR(); |
|
5650 RETURN_NONE(); |
|
5651 } |
|
5652 |
|
5653 static PyObject* |
|
5654 DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject* |
|
5655 kwargs) |
|
5656 { |
|
5657 int err; |
|
5658 char *host; |
|
5659 int port; |
|
5660 int flags = 0; |
|
5661 static char* kwnames[] = {"host", "port", "flags", NULL}; |
|
5662 |
|
5663 if (!PyArg_ParseTupleAndKeywords(args, kwargs, |
|
5664 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags)) |
|
5665 { |
|
5666 return NULL; |
|
5667 } |
|
5668 CHECK_ENV_NOT_CLOSED(self); |
|
5669 MYDB_BEGIN_ALLOW_THREADS; |
|
5670 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags); |
|
5671 MYDB_END_ALLOW_THREADS; |
|
5672 RETURN_IF_ERR(); |
|
5673 RETURN_NONE(); |
|
5674 } |
|
5675 |
|
5676 static PyObject* |
|
5677 DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject* |
|
5678 kwargs) |
|
5679 { |
|
5680 int err; |
|
5681 char *host; |
|
5682 int port; |
|
5683 int flags = 0; |
|
5684 int eidp; |
|
5685 static char* kwnames[] = {"host", "port", "flags", NULL}; |
|
5686 |
|
5687 if (!PyArg_ParseTupleAndKeywords(args, kwargs, |
|
5688 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags)) |
|
5689 { |
|
5690 return NULL; |
|
5691 } |
|
5692 CHECK_ENV_NOT_CLOSED(self); |
|
5693 MYDB_BEGIN_ALLOW_THREADS; |
|
5694 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags); |
|
5695 MYDB_END_ALLOW_THREADS; |
|
5696 RETURN_IF_ERR(); |
|
5697 return NUMBER_FromLong(eidp); |
|
5698 } |
|
5699 |
|
5700 static PyObject* |
|
5701 DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args) |
|
5702 { |
|
5703 int err; |
|
5704 int ack_policy; |
|
5705 |
|
5706 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy)) |
|
5707 { |
|
5708 return NULL; |
|
5709 } |
|
5710 CHECK_ENV_NOT_CLOSED(self); |
|
5711 MYDB_BEGIN_ALLOW_THREADS; |
|
5712 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy); |
|
5713 MYDB_END_ALLOW_THREADS; |
|
5714 RETURN_IF_ERR(); |
|
5715 RETURN_NONE(); |
|
5716 } |
|
5717 |
|
5718 static PyObject* |
|
5719 DBEnv_repmgr_get_ack_policy(DBEnvObject* self) |
|
5720 { |
|
5721 int err; |
|
5722 int ack_policy; |
|
5723 |
|
5724 CHECK_ENV_NOT_CLOSED(self); |
|
5725 MYDB_BEGIN_ALLOW_THREADS; |
|
5726 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy); |
|
5727 MYDB_END_ALLOW_THREADS; |
|
5728 RETURN_IF_ERR(); |
|
5729 return NUMBER_FromLong(ack_policy); |
|
5730 } |
|
5731 |
|
5732 static PyObject* |
|
5733 DBEnv_repmgr_site_list(DBEnvObject* self) |
|
5734 { |
|
5735 int err; |
|
5736 unsigned int countp; |
|
5737 DB_REPMGR_SITE *listp; |
|
5738 PyObject *stats, *key, *tuple; |
|
5739 |
|
5740 CHECK_ENV_NOT_CLOSED(self); |
|
5741 MYDB_BEGIN_ALLOW_THREADS; |
|
5742 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp); |
|
5743 MYDB_END_ALLOW_THREADS; |
|
5744 RETURN_IF_ERR(); |
|
5745 |
|
5746 stats=PyDict_New(); |
|
5747 if (stats == NULL) { |
|
5748 free(listp); |
|
5749 return NULL; |
|
5750 } |
|
5751 |
|
5752 for(;countp--;) { |
|
5753 key=NUMBER_FromLong(listp[countp].eid); |
|
5754 if(!key) { |
|
5755 Py_DECREF(stats); |
|
5756 free(listp); |
|
5757 return NULL; |
|
5758 } |
|
5759 #if (PY_VERSION_HEX >= 0x02040000) |
|
5760 tuple=Py_BuildValue("(sII)", listp[countp].host, |
|
5761 listp[countp].port, listp[countp].status); |
|
5762 #else |
|
5763 tuple=Py_BuildValue("(sii)", listp[countp].host, |
|
5764 listp[countp].port, listp[countp].status); |
|
5765 #endif |
|
5766 if(!tuple) { |
|
5767 Py_DECREF(key); |
|
5768 Py_DECREF(stats); |
|
5769 free(listp); |
|
5770 return NULL; |
|
5771 } |
|
5772 if(PyDict_SetItem(stats, key, tuple)) { |
|
5773 Py_DECREF(key); |
|
5774 Py_DECREF(tuple); |
|
5775 Py_DECREF(stats); |
|
5776 free(listp); |
|
5777 return NULL; |
|
5778 } |
|
5779 } |
|
5780 free(listp); |
|
5781 return stats; |
|
5782 } |
|
5783 #endif |
|
5784 |
|
5785 #if (DBVER >= 46) |
|
5786 static PyObject* |
|
5787 DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs) |
|
5788 { |
|
5789 int err; |
|
5790 int flags=0; |
|
5791 static char* kwnames[] = { "flags", NULL }; |
|
5792 |
|
5793 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print", |
|
5794 kwnames, &flags)) |
|
5795 { |
|
5796 return NULL; |
|
5797 } |
|
5798 CHECK_ENV_NOT_CLOSED(self); |
|
5799 MYDB_BEGIN_ALLOW_THREADS; |
|
5800 err = self->db_env->repmgr_stat_print(self->db_env, flags); |
|
5801 MYDB_END_ALLOW_THREADS; |
|
5802 RETURN_IF_ERR(); |
|
5803 RETURN_NONE(); |
|
5804 } |
|
5805 |
|
5806 static PyObject* |
|
5807 DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs) |
|
5808 { |
|
5809 int err; |
|
5810 int flags=0; |
|
5811 DB_REPMGR_STAT *statp; |
|
5812 PyObject *stats; |
|
5813 static char* kwnames[] = { "flags", NULL }; |
|
5814 |
|
5815 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat", |
|
5816 kwnames, &flags)) |
|
5817 { |
|
5818 return NULL; |
|
5819 } |
|
5820 CHECK_ENV_NOT_CLOSED(self); |
|
5821 MYDB_BEGIN_ALLOW_THREADS; |
|
5822 err = self->db_env->repmgr_stat(self->db_env, &statp, flags); |
|
5823 MYDB_END_ALLOW_THREADS; |
|
5824 RETURN_IF_ERR(); |
|
5825 |
|
5826 stats=PyDict_New(); |
|
5827 if (stats == NULL) { |
|
5828 free(statp); |
|
5829 return NULL; |
|
5830 } |
|
5831 |
|
5832 #define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name) |
|
5833 |
|
5834 MAKE_ENTRY(perm_failed); |
|
5835 MAKE_ENTRY(msgs_queued); |
|
5836 MAKE_ENTRY(msgs_dropped); |
|
5837 MAKE_ENTRY(connection_drop); |
|
5838 MAKE_ENTRY(connect_fail); |
|
5839 |
|
5840 #undef MAKE_ENTRY |
|
5841 |
|
5842 free(statp); |
|
5843 return stats; |
|
5844 } |
|
5845 #endif |
|
5846 |
|
5847 |
|
5848 /* --------------------------------------------------------------------- */ |
|
5849 /* DBTxn methods */ |
|
5850 |
|
5851 |
|
5852 static void _close_transaction_cursors(DBTxnObject* txn) |
|
5853 { |
|
5854 PyObject *dummy; |
|
5855 |
|
5856 while(txn->children_cursors) { |
|
5857 PyErr_Warn(PyExc_RuntimeWarning, |
|
5858 "Must close cursors before resolving a transaction."); |
|
5859 dummy=DBC_close_internal(txn->children_cursors); |
|
5860 Py_XDECREF(dummy); |
|
5861 } |
|
5862 } |
|
5863 |
|
5864 static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn) |
|
5865 { |
|
5866 DBObject *db; |
|
5867 #if (DBVER >= 43) |
|
5868 DBSequenceObject *dbs; |
|
5869 #endif |
|
5870 |
|
5871 while (txn->children_dbs) { |
|
5872 db=txn->children_dbs; |
|
5873 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db); |
|
5874 if (txn->parent_txn) { |
|
5875 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db); |
|
5876 db->txn=txn->parent_txn; |
|
5877 } else { |
|
5878 /* The db is already linked to its environment, |
|
5879 ** so nothing to do. |
|
5880 */ |
|
5881 db->txn=NULL; |
|
5882 } |
|
5883 } |
|
5884 |
|
5885 #if (DBVER >= 43) |
|
5886 while (txn->children_sequences) { |
|
5887 dbs=txn->children_sequences; |
|
5888 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs); |
|
5889 if (txn->parent_txn) { |
|
5890 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs); |
|
5891 dbs->txn=txn->parent_txn; |
|
5892 } else { |
|
5893 /* The sequence is already linked to its |
|
5894 ** parent db. Nothing to do. |
|
5895 */ |
|
5896 dbs->txn=NULL; |
|
5897 } |
|
5898 } |
|
5899 #endif |
|
5900 } |
|
5901 |
|
5902 |
|
5903 static PyObject* |
|
5904 DBTxn_commit(DBTxnObject* self, PyObject* args) |
|
5905 { |
|
5906 int flags=0, err; |
|
5907 DB_TXN *txn; |
|
5908 |
|
5909 if (!PyArg_ParseTuple(args, "|i:commit", &flags)) |
|
5910 return NULL; |
|
5911 |
|
5912 _close_transaction_cursors(self); |
|
5913 |
|
5914 if (!self->txn) { |
|
5915 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " |
|
5916 "after txn_commit, txn_abort " |
|
5917 "or txn_discard"); |
|
5918 if (t) { |
|
5919 PyErr_SetObject(DBError, t); |
|
5920 Py_DECREF(t); |
|
5921 } |
|
5922 return NULL; |
|
5923 } |
|
5924 self->flag_prepare=0; |
|
5925 txn = self->txn; |
|
5926 self->txn = NULL; /* this DB_TXN is no longer valid after this call */ |
|
5927 |
|
5928 EXTRACT_FROM_DOUBLE_LINKED_LIST(self); |
|
5929 |
|
5930 MYDB_BEGIN_ALLOW_THREADS; |
|
5931 err = txn->commit(txn, flags); |
|
5932 MYDB_END_ALLOW_THREADS; |
|
5933 |
|
5934 _promote_transaction_dbs_and_sequences(self); |
|
5935 |
|
5936 RETURN_IF_ERR(); |
|
5937 RETURN_NONE(); |
|
5938 } |
|
5939 |
|
5940 static PyObject* |
|
5941 DBTxn_prepare(DBTxnObject* self, PyObject* args) |
|
5942 { |
|
5943 int err; |
|
5944 char* gid=NULL; |
|
5945 int gid_size=0; |
|
5946 |
|
5947 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size)) |
|
5948 return NULL; |
|
5949 |
|
5950 if (gid_size != DB_XIDDATASIZE) { |
|
5951 PyErr_SetString(PyExc_TypeError, |
|
5952 "gid must be DB_XIDDATASIZE bytes long"); |
|
5953 return NULL; |
|
5954 } |
|
5955 |
|
5956 if (!self->txn) { |
|
5957 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used " |
|
5958 "after txn_commit, txn_abort " |
|
5959 "or txn_discard"); |
|
5960 if (t) { |
|
5961 PyErr_SetObject(DBError, t); |
|
5962 Py_DECREF(t); |
|
5963 } |
|
5964 return NULL; |
|
5965 } |
|
5966 self->flag_prepare=1; /* Prepare state */ |
|
5967 MYDB_BEGIN_ALLOW_THREADS; |
|
5968 err = self->txn->prepare(self->txn, (u_int8_t*)gid); |
|
5969 MYDB_END_ALLOW_THREADS; |
|
5970 RETURN_IF_ERR(); |
|
5971 RETURN_NONE(); |
|
5972 } |
|
5973 |
|
5974 |
|
5975 static PyObject* |
|
5976 DBTxn_abort_discard_internal(DBTxnObject* self, int discard) |
|
5977 { |
|
5978 PyObject *dummy; |
|
5979 int err=0; |
|
5980 DB_TXN *txn; |
|
5981 |
|
5982 if (!self->txn) { |
|
5983 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " |
|
5984 "after txn_commit, txn_abort " |
|
5985 "or txn_discard"); |
|
5986 if (t) { |
|
5987 PyErr_SetObject(DBError, t); |
|
5988 Py_DECREF(t); |
|
5989 } |
|
5990 return NULL; |
|
5991 } |
|
5992 txn = self->txn; |
|
5993 self->txn = NULL; /* this DB_TXN is no longer valid after this call */ |
|
5994 |
|
5995 _close_transaction_cursors(self); |
|
5996 #if (DBVER >= 43) |
|
5997 while (self->children_sequences) { |
|
5998 dummy=DBSequence_close_internal(self->children_sequences,0,0); |
|
5999 Py_XDECREF(dummy); |
|
6000 } |
|
6001 #endif |
|
6002 while (self->children_dbs) { |
|
6003 dummy=DB_close_internal(self->children_dbs, 0, 0); |
|
6004 Py_XDECREF(dummy); |
|
6005 } |
|
6006 |
|
6007 EXTRACT_FROM_DOUBLE_LINKED_LIST(self); |
|
6008 |
|
6009 MYDB_BEGIN_ALLOW_THREADS; |
|
6010 if (discard) { |
|
6011 assert(!self->flag_prepare); |
|
6012 err = txn->discard(txn,0); |
|
6013 } else { |
|
6014 /* |
|
6015 ** If the transaction is in the "prepare" or "recover" state, |
|
6016 ** we better do not implicitly abort it. |
|
6017 */ |
|
6018 if (!self->flag_prepare) { |
|
6019 err = txn->abort(txn); |
|
6020 } |
|
6021 } |
|
6022 MYDB_END_ALLOW_THREADS; |
|
6023 RETURN_IF_ERR(); |
|
6024 RETURN_NONE(); |
|
6025 } |
|
6026 |
|
6027 static PyObject* |
|
6028 DBTxn_abort(DBTxnObject* self) |
|
6029 { |
|
6030 self->flag_prepare=0; |
|
6031 _close_transaction_cursors(self); |
|
6032 |
|
6033 return DBTxn_abort_discard_internal(self,0); |
|
6034 } |
|
6035 |
|
6036 static PyObject* |
|
6037 DBTxn_discard(DBTxnObject* self) |
|
6038 { |
|
6039 self->flag_prepare=0; |
|
6040 _close_transaction_cursors(self); |
|
6041 |
|
6042 return DBTxn_abort_discard_internal(self,1); |
|
6043 } |
|
6044 |
|
6045 |
|
6046 static PyObject* |
|
6047 DBTxn_id(DBTxnObject* self) |
|
6048 { |
|
6049 int id; |
|
6050 |
|
6051 if (!self->txn) { |
|
6052 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " |
|
6053 "after txn_commit, txn_abort " |
|
6054 "or txn_discard"); |
|
6055 if (t) { |
|
6056 PyErr_SetObject(DBError, t); |
|
6057 Py_DECREF(t); |
|
6058 } |
|
6059 return NULL; |
|
6060 } |
|
6061 MYDB_BEGIN_ALLOW_THREADS; |
|
6062 id = self->txn->id(self->txn); |
|
6063 MYDB_END_ALLOW_THREADS; |
|
6064 return NUMBER_FromLong(id); |
|
6065 } |
|
6066 |
|
6067 #if (DBVER >= 43) |
|
6068 /* --------------------------------------------------------------------- */ |
|
6069 /* DBSequence methods */ |
|
6070 |
|
6071 |
|
6072 static PyObject* |
|
6073 DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close) |
|
6074 { |
|
6075 int err=0; |
|
6076 |
|
6077 if (self->sequence!=NULL) { |
|
6078 EXTRACT_FROM_DOUBLE_LINKED_LIST(self); |
|
6079 if (self->txn) { |
|
6080 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self); |
|
6081 self->txn=NULL; |
|
6082 } |
|
6083 |
|
6084 /* |
|
6085 ** "do_not_close" is used to dispose all related objects in the |
|
6086 ** tree, without actually releasing the "root" object. |
|
6087 ** This is done, for example, because function calls like |
|
6088 ** "DBSequence.remove()" implicitly close the underlying handle. So |
|
6089 ** the handle doesn't need to be closed, but related objects |
|
6090 ** must be cleaned up. |
|
6091 */ |
|
6092 if (!do_not_close) { |
|
6093 MYDB_BEGIN_ALLOW_THREADS |
|
6094 err = self->sequence->close(self->sequence, flags); |
|
6095 MYDB_END_ALLOW_THREADS |
|
6096 } |
|
6097 self->sequence = NULL; |
|
6098 |
|
6099 RETURN_IF_ERR(); |
|
6100 } |
|
6101 |
|
6102 RETURN_NONE(); |
|
6103 } |
|
6104 |
|
6105 static PyObject* |
|
6106 DBSequence_close(DBSequenceObject* self, PyObject* args) |
|
6107 { |
|
6108 int flags=0; |
|
6109 if (!PyArg_ParseTuple(args,"|i:close", &flags)) |
|
6110 return NULL; |
|
6111 |
|
6112 return DBSequence_close_internal(self,flags,0); |
|
6113 } |
|
6114 |
|
6115 static PyObject* |
|
6116 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs) |
|
6117 { |
|
6118 int err, flags = 0; |
|
6119 int delta = 1; |
|
6120 db_seq_t value; |
|
6121 PyObject *txnobj = NULL; |
|
6122 DB_TXN *txn = NULL; |
|
6123 static char* kwnames[] = {"delta", "txn", "flags", NULL }; |
|
6124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags)) |
|
6125 return NULL; |
|
6126 CHECK_SEQUENCE_NOT_CLOSED(self) |
|
6127 |
|
6128 if (!checkTxnObj(txnobj, &txn)) |
|
6129 return NULL; |
|
6130 |
|
6131 MYDB_BEGIN_ALLOW_THREADS |
|
6132 err = self->sequence->get(self->sequence, txn, delta, &value, flags); |
|
6133 MYDB_END_ALLOW_THREADS |
|
6134 |
|
6135 RETURN_IF_ERR(); |
|
6136 return PyLong_FromLongLong(value); |
|
6137 } |
|
6138 |
|
6139 static PyObject* |
|
6140 DBSequence_get_dbp(DBSequenceObject* self) |
|
6141 { |
|
6142 CHECK_SEQUENCE_NOT_CLOSED(self) |
|
6143 Py_INCREF(self->mydb); |
|
6144 return (PyObject* )self->mydb; |
|
6145 } |
|
6146 |
|
6147 static PyObject* |
|
6148 DBSequence_get_key(DBSequenceObject* self) |
|
6149 { |
|
6150 int err; |
|
6151 DBT key; |
|
6152 PyObject *retval = NULL; |
|
6153 |
|
6154 key.flags = DB_DBT_MALLOC; |
|
6155 CHECK_SEQUENCE_NOT_CLOSED(self) |
|
6156 MYDB_BEGIN_ALLOW_THREADS |
|
6157 err = self->sequence->get_key(self->sequence, &key); |
|
6158 MYDB_END_ALLOW_THREADS |
|
6159 |
|
6160 if (!err) |
|
6161 retval = Build_PyString(key.data, key.size); |
|
6162 |
|
6163 FREE_DBT(key); |
|
6164 RETURN_IF_ERR(); |
|
6165 |
|
6166 return retval; |
|
6167 } |
|
6168 |
|
6169 static PyObject* |
|
6170 DBSequence_init_value(DBSequenceObject* self, PyObject* args) |
|
6171 { |
|
6172 int err; |
|
6173 PY_LONG_LONG value; |
|
6174 db_seq_t value2; |
|
6175 if (!PyArg_ParseTuple(args,"L:init_value", &value)) |
|
6176 return NULL; |
|
6177 CHECK_SEQUENCE_NOT_CLOSED(self) |
|
6178 |
|
6179 value2=value; /* If truncation, compiler should show a warning */ |
|
6180 MYDB_BEGIN_ALLOW_THREADS |
|
6181 err = self->sequence->initial_value(self->sequence, value2); |
|
6182 MYDB_END_ALLOW_THREADS |
|
6183 |
|
6184 RETURN_IF_ERR(); |
|
6185 |
|
6186 RETURN_NONE(); |
|
6187 } |
|
6188 |
|
6189 static PyObject* |
|
6190 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs) |
|
6191 { |
|
6192 int err, flags = 0; |
|
6193 PyObject* keyobj; |
|
6194 PyObject *txnobj = NULL; |
|
6195 DB_TXN *txn = NULL; |
|
6196 DBT key; |
|
6197 |
|
6198 static char* kwnames[] = {"key", "txn", "flags", NULL }; |
|
6199 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags)) |
|
6200 return NULL; |
|
6201 |
|
6202 if (!checkTxnObj(txnobj, &txn)) |
|
6203 return NULL; |
|
6204 |
|
6205 if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) |
|
6206 return NULL; |
|
6207 |
|
6208 MYDB_BEGIN_ALLOW_THREADS |
|
6209 err = self->sequence->open(self->sequence, txn, &key, flags); |
|
6210 MYDB_END_ALLOW_THREADS |
|
6211 |
|
6212 FREE_DBT(key); |
|
6213 RETURN_IF_ERR(); |
|
6214 |
|
6215 if (txn) { |
|
6216 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self); |
|
6217 self->txn=(DBTxnObject *)txnobj; |
|
6218 } |
|
6219 |
|
6220 RETURN_NONE(); |
|
6221 } |
|
6222 |
|
6223 static PyObject* |
|
6224 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs) |
|
6225 { |
|
6226 PyObject *dummy; |
|
6227 int err, flags = 0; |
|
6228 PyObject *txnobj = NULL; |
|
6229 DB_TXN *txn = NULL; |
|
6230 |
|
6231 static char* kwnames[] = {"txn", "flags", NULL }; |
|
6232 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags)) |
|
6233 return NULL; |
|
6234 |
|
6235 if (!checkTxnObj(txnobj, &txn)) |
|
6236 return NULL; |
|
6237 |
|
6238 CHECK_SEQUENCE_NOT_CLOSED(self) |
|
6239 |
|
6240 MYDB_BEGIN_ALLOW_THREADS |
|
6241 err = self->sequence->remove(self->sequence, txn, flags); |
|
6242 MYDB_END_ALLOW_THREADS |
|
6243 |
|
6244 dummy=DBSequence_close_internal(self,flags,1); |
|
6245 Py_XDECREF(dummy); |
|
6246 |
|
6247 RETURN_IF_ERR(); |
|
6248 RETURN_NONE(); |
|
6249 } |
|
6250 |
|
6251 static PyObject* |
|
6252 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args) |
|
6253 { |
|
6254 int err, size; |
|
6255 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size)) |
|
6256 return NULL; |
|
6257 CHECK_SEQUENCE_NOT_CLOSED(self) |
|
6258 |
|
6259 MYDB_BEGIN_ALLOW_THREADS |
|
6260 err = self->sequence->set_cachesize(self->sequence, size); |
|
6261 MYDB_END_ALLOW_THREADS |
|
6262 |
|
6263 RETURN_IF_ERR(); |
|
6264 RETURN_NONE(); |
|
6265 } |
|
6266 |
|
6267 static PyObject* |
|
6268 DBSequence_get_cachesize(DBSequenceObject* self) |
|
6269 { |
|
6270 int err, size; |
|
6271 |
|
6272 CHECK_SEQUENCE_NOT_CLOSED(self) |
|
6273 |
|
6274 MYDB_BEGIN_ALLOW_THREADS |
|
6275 err = self->sequence->get_cachesize(self->sequence, &size); |
|
6276 MYDB_END_ALLOW_THREADS |
|
6277 |
|
6278 RETURN_IF_ERR(); |
|
6279 return NUMBER_FromLong(size); |
|
6280 } |
|
6281 |
|
6282 static PyObject* |
|
6283 DBSequence_set_flags(DBSequenceObject* self, PyObject* args) |
|
6284 { |
|
6285 int err, flags = 0; |
|
6286 if (!PyArg_ParseTuple(args,"i:set_flags", &flags)) |
|
6287 return NULL; |
|
6288 CHECK_SEQUENCE_NOT_CLOSED(self) |
|
6289 |
|
6290 MYDB_BEGIN_ALLOW_THREADS |
|
6291 err = self->sequence->set_flags(self->sequence, flags); |
|
6292 MYDB_END_ALLOW_THREADS |
|
6293 |
|
6294 RETURN_IF_ERR(); |
|
6295 RETURN_NONE(); |
|
6296 } |
|
6297 |
|
6298 static PyObject* |
|
6299 DBSequence_get_flags(DBSequenceObject* self) |
|
6300 { |
|
6301 unsigned int flags; |
|
6302 int err; |
|
6303 |
|
6304 CHECK_SEQUENCE_NOT_CLOSED(self) |
|
6305 |
|
6306 MYDB_BEGIN_ALLOW_THREADS |
|
6307 err = self->sequence->get_flags(self->sequence, &flags); |
|
6308 MYDB_END_ALLOW_THREADS |
|
6309 |
|
6310 RETURN_IF_ERR(); |
|
6311 return NUMBER_FromLong((int)flags); |
|
6312 } |
|
6313 |
|
6314 static PyObject* |
|
6315 DBSequence_set_range(DBSequenceObject* self, PyObject* args) |
|
6316 { |
|
6317 int err; |
|
6318 PY_LONG_LONG min, max; |
|
6319 db_seq_t min2, max2; |
|
6320 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max)) |
|
6321 return NULL; |
|
6322 CHECK_SEQUENCE_NOT_CLOSED(self) |
|
6323 |
|
6324 min2=min; /* If truncation, compiler should show a warning */ |
|
6325 max2=max; |
|
6326 MYDB_BEGIN_ALLOW_THREADS |
|
6327 err = self->sequence->set_range(self->sequence, min2, max2); |
|
6328 MYDB_END_ALLOW_THREADS |
|
6329 |
|
6330 RETURN_IF_ERR(); |
|
6331 RETURN_NONE(); |
|
6332 } |
|
6333 |
|
6334 static PyObject* |
|
6335 DBSequence_get_range(DBSequenceObject* self) |
|
6336 { |
|
6337 int err; |
|
6338 PY_LONG_LONG min, max; |
|
6339 db_seq_t min2, max2; |
|
6340 |
|
6341 CHECK_SEQUENCE_NOT_CLOSED(self) |
|
6342 |
|
6343 MYDB_BEGIN_ALLOW_THREADS |
|
6344 err = self->sequence->get_range(self->sequence, &min2, &max2); |
|
6345 MYDB_END_ALLOW_THREADS |
|
6346 |
|
6347 RETURN_IF_ERR(); |
|
6348 min=min2; /* If truncation, compiler should show a warning */ |
|
6349 max=max2; |
|
6350 return Py_BuildValue("(LL)", min, max); |
|
6351 } |
|
6352 |
|
6353 static PyObject* |
|
6354 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs) |
|
6355 { |
|
6356 int err, flags = 0; |
|
6357 DB_SEQUENCE_STAT* sp = NULL; |
|
6358 PyObject* dict_stat; |
|
6359 static char* kwnames[] = {"flags", NULL }; |
|
6360 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags)) |
|
6361 return NULL; |
|
6362 CHECK_SEQUENCE_NOT_CLOSED(self); |
|
6363 |
|
6364 MYDB_BEGIN_ALLOW_THREADS; |
|
6365 err = self->sequence->stat(self->sequence, &sp, flags); |
|
6366 MYDB_END_ALLOW_THREADS; |
|
6367 RETURN_IF_ERR(); |
|
6368 |
|
6369 if ((dict_stat = PyDict_New()) == NULL) { |
|
6370 free(sp); |
|
6371 return NULL; |
|
6372 } |
|
6373 |
|
6374 |
|
6375 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name) |
|
6376 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name) |
|
6377 |
|
6378 MAKE_INT_ENTRY(wait); |
|
6379 MAKE_INT_ENTRY(nowait); |
|
6380 MAKE_LONG_LONG_ENTRY(current); |
|
6381 MAKE_LONG_LONG_ENTRY(value); |
|
6382 MAKE_LONG_LONG_ENTRY(last_value); |
|
6383 MAKE_LONG_LONG_ENTRY(min); |
|
6384 MAKE_LONG_LONG_ENTRY(max); |
|
6385 MAKE_INT_ENTRY(cache_size); |
|
6386 MAKE_INT_ENTRY(flags); |
|
6387 |
|
6388 #undef MAKE_INT_ENTRY |
|
6389 #undef MAKE_LONG_LONG_ENTRY |
|
6390 |
|
6391 free(sp); |
|
6392 return dict_stat; |
|
6393 } |
|
6394 #endif |
|
6395 |
|
6396 |
|
6397 /* --------------------------------------------------------------------- */ |
|
6398 /* Method definition tables and type objects */ |
|
6399 |
|
6400 static PyMethodDef DB_methods[] = { |
|
6401 {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS}, |
|
6402 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS}, |
|
6403 {"close", (PyCFunction)DB_close, METH_VARARGS}, |
|
6404 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS}, |
|
6405 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS}, |
|
6406 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS}, |
|
6407 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS}, |
|
6408 {"fd", (PyCFunction)DB_fd, METH_NOARGS}, |
|
6409 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS}, |
|
6410 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS}, |
|
6411 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS}, |
|
6412 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS}, |
|
6413 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS}, |
|
6414 {"get_type", (PyCFunction)DB_get_type, METH_NOARGS}, |
|
6415 {"join", (PyCFunction)DB_join, METH_VARARGS}, |
|
6416 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS}, |
|
6417 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS}, |
|
6418 {"items", (PyCFunction)DB_items, METH_VARARGS}, |
|
6419 {"keys", (PyCFunction)DB_keys, METH_VARARGS}, |
|
6420 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS}, |
|
6421 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS}, |
|
6422 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS}, |
|
6423 {"rename", (PyCFunction)DB_rename, METH_VARARGS}, |
|
6424 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS}, |
|
6425 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O}, |
|
6426 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS}, |
|
6427 #if (DBVER >= 41) |
|
6428 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS}, |
|
6429 #endif |
|
6430 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS}, |
|
6431 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS}, |
|
6432 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS}, |
|
6433 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS}, |
|
6434 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS}, |
|
6435 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS}, |
|
6436 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS}, |
|
6437 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS}, |
|
6438 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS}, |
|
6439 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS}, |
|
6440 {"set_private", (PyCFunction)DB_set_private, METH_O}, |
|
6441 {"get_private", (PyCFunction)DB_get_private, METH_NOARGS}, |
|
6442 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS}, |
|
6443 {"sync", (PyCFunction)DB_sync, METH_VARARGS}, |
|
6444 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS}, |
|
6445 {"type", (PyCFunction)DB_get_type, METH_NOARGS}, |
|
6446 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS}, |
|
6447 {"values", (PyCFunction)DB_values, METH_VARARGS}, |
|
6448 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS}, |
|
6449 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS}, |
|
6450 {NULL, NULL} /* sentinel */ |
|
6451 }; |
|
6452 |
|
6453 |
|
6454 static PyMappingMethods DB_mapping = { |
|
6455 DB_length, /*mp_length*/ |
|
6456 (binaryfunc)DB_subscript, /*mp_subscript*/ |
|
6457 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/ |
|
6458 }; |
|
6459 |
|
6460 |
|
6461 static PyMethodDef DBCursor_methods[] = { |
|
6462 {"close", (PyCFunction)DBC_close, METH_NOARGS}, |
|
6463 {"count", (PyCFunction)DBC_count, METH_VARARGS}, |
|
6464 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS}, |
|
6465 {"delete", (PyCFunction)DBC_delete, METH_VARARGS}, |
|
6466 {"dup", (PyCFunction)DBC_dup, METH_VARARGS}, |
|
6467 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS}, |
|
6468 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS}, |
|
6469 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS}, |
|
6470 {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS}, |
|
6471 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS}, |
|
6472 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS}, |
|
6473 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS}, |
|
6474 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS}, |
|
6475 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS}, |
|
6476 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS}, |
|
6477 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS}, |
|
6478 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS}, |
|
6479 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS}, |
|
6480 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS}, |
|
6481 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS}, |
|
6482 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS}, |
|
6483 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS}, |
|
6484 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS}, |
|
6485 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS}, |
|
6486 {NULL, NULL} /* sentinel */ |
|
6487 }; |
|
6488 |
|
6489 |
|
6490 static PyMethodDef DBEnv_methods[] = { |
|
6491 {"close", (PyCFunction)DBEnv_close, METH_VARARGS}, |
|
6492 {"open", (PyCFunction)DBEnv_open, METH_VARARGS}, |
|
6493 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS}, |
|
6494 #if (DBVER >= 41) |
|
6495 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS}, |
|
6496 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS}, |
|
6497 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS}, |
|
6498 #endif |
|
6499 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS}, |
|
6500 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS}, |
|
6501 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS}, |
|
6502 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS}, |
|
6503 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS}, |
|
6504 #if (DBVER >= 47) |
|
6505 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS}, |
|
6506 #endif |
|
6507 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS}, |
|
6508 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS}, |
|
6509 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS}, |
|
6510 #if (DBVER >= 42) |
|
6511 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS}, |
|
6512 #endif |
|
6513 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS}, |
|
6514 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS}, |
|
6515 #if (DBVER < 45) |
|
6516 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS}, |
|
6517 #endif |
|
6518 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS}, |
|
6519 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS}, |
|
6520 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS}, |
|
6521 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS}, |
|
6522 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS}, |
|
6523 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS}, |
|
6524 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS}, |
|
6525 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS}, |
|
6526 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS}, |
|
6527 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS}, |
|
6528 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS}, |
|
6529 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS}, |
|
6530 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS}, |
|
6531 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS}, |
|
6532 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS}, |
|
6533 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS}, |
|
6534 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS}, |
|
6535 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS}, |
|
6536 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS}, |
|
6537 #if (DBVER >= 44) |
|
6538 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS}, |
|
6539 #endif |
|
6540 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS}, |
|
6541 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS}, |
|
6542 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server, |
|
6543 METH_VARARGS||METH_KEYWORDS}, |
|
6544 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS}, |
|
6545 #if (DBVER >= 42) |
|
6546 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS}, |
|
6547 #endif |
|
6548 {"set_private", (PyCFunction)DBEnv_set_private, METH_O}, |
|
6549 {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS}, |
|
6550 {"rep_start", (PyCFunction)DBEnv_rep_start, |
|
6551 METH_VARARGS|METH_KEYWORDS}, |
|
6552 {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS}, |
|
6553 {"rep_process_message", (PyCFunction)DBEnv_rep_process_message, |
|
6554 METH_VARARGS}, |
|
6555 #if (DBVER >= 46) |
|
6556 {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS}, |
|
6557 #endif |
|
6558 #if (DBVER >= 44) |
|
6559 {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS}, |
|
6560 {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS}, |
|
6561 {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS}, |
|
6562 #endif |
|
6563 #if (DBVER >= 45) |
|
6564 {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS}, |
|
6565 {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS}, |
|
6566 #endif |
|
6567 #if (DBVER >= 47) |
|
6568 {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS}, |
|
6569 {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS}, |
|
6570 #endif |
|
6571 #if (DBVER >= 45) |
|
6572 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O}, |
|
6573 #endif |
|
6574 #if (DBVER >= 45) |
|
6575 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS}, |
|
6576 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS}, |
|
6577 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS}, |
|
6578 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS}, |
|
6579 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS}, |
|
6580 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS}, |
|
6581 #endif |
|
6582 #if (DBVER >= 45) |
|
6583 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start, |
|
6584 METH_VARARGS|METH_KEYWORDS}, |
|
6585 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site, |
|
6586 METH_VARARGS|METH_KEYWORDS}, |
|
6587 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site, |
|
6588 METH_VARARGS|METH_KEYWORDS}, |
|
6589 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy, |
|
6590 METH_VARARGS}, |
|
6591 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy, |
|
6592 METH_NOARGS}, |
|
6593 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list, |
|
6594 METH_NOARGS}, |
|
6595 #endif |
|
6596 #if (DBVER >= 46) |
|
6597 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat, |
|
6598 METH_VARARGS|METH_KEYWORDS}, |
|
6599 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print, |
|
6600 METH_VARARGS|METH_KEYWORDS}, |
|
6601 #endif |
|
6602 {NULL, NULL} /* sentinel */ |
|
6603 }; |
|
6604 |
|
6605 |
|
6606 static PyMethodDef DBTxn_methods[] = { |
|
6607 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS}, |
|
6608 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS}, |
|
6609 {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS}, |
|
6610 {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS}, |
|
6611 {"id", (PyCFunction)DBTxn_id, METH_NOARGS}, |
|
6612 {NULL, NULL} /* sentinel */ |
|
6613 }; |
|
6614 |
|
6615 |
|
6616 #if (DBVER >= 43) |
|
6617 static PyMethodDef DBSequence_methods[] = { |
|
6618 {"close", (PyCFunction)DBSequence_close, METH_VARARGS}, |
|
6619 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS}, |
|
6620 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS}, |
|
6621 {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS}, |
|
6622 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS}, |
|
6623 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS}, |
|
6624 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS}, |
|
6625 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS}, |
|
6626 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS}, |
|
6627 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS}, |
|
6628 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS}, |
|
6629 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS}, |
|
6630 {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS}, |
|
6631 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS}, |
|
6632 {NULL, NULL} /* sentinel */ |
|
6633 }; |
|
6634 #endif |
|
6635 |
|
6636 |
|
6637 static PyObject* |
|
6638 DBEnv_db_home_get(DBEnvObject* self) |
|
6639 { |
|
6640 const char *home = NULL; |
|
6641 |
|
6642 CHECK_ENV_NOT_CLOSED(self); |
|
6643 |
|
6644 #if (DBVER >= 42) |
|
6645 self->db_env->get_home(self->db_env, &home); |
|
6646 #else |
|
6647 home=self->db_env->db_home; |
|
6648 #endif |
|
6649 |
|
6650 if (home == NULL) { |
|
6651 RETURN_NONE(); |
|
6652 } |
|
6653 return PyBytes_FromString(home); |
|
6654 } |
|
6655 |
|
6656 static PyGetSetDef DBEnv_getsets[] = { |
|
6657 {"db_home", (getter)DBEnv_db_home_get, NULL,}, |
|
6658 {NULL} |
|
6659 }; |
|
6660 |
|
6661 |
|
6662 statichere PyTypeObject DB_Type = { |
|
6663 #if (PY_VERSION_HEX < 0x03000000) |
|
6664 PyObject_HEAD_INIT(NULL) |
|
6665 0, /*ob_size*/ |
|
6666 #else |
|
6667 PyVarObject_HEAD_INIT(NULL, 0) |
|
6668 #endif |
|
6669 "DB", /*tp_name*/ |
|
6670 sizeof(DBObject), /*tp_basicsize*/ |
|
6671 0, /*tp_itemsize*/ |
|
6672 /* methods */ |
|
6673 (destructor)DB_dealloc, /*tp_dealloc*/ |
|
6674 0, /*tp_print*/ |
|
6675 0, /*tp_getattr*/ |
|
6676 0, /*tp_setattr*/ |
|
6677 0, /*tp_compare*/ |
|
6678 0, /*tp_repr*/ |
|
6679 0, /*tp_as_number*/ |
|
6680 0, /*tp_as_sequence*/ |
|
6681 &DB_mapping,/*tp_as_mapping*/ |
|
6682 0, /*tp_hash*/ |
|
6683 0, /* tp_call */ |
|
6684 0, /* tp_str */ |
|
6685 0, /* tp_getattro */ |
|
6686 0, /* tp_setattro */ |
|
6687 0, /* tp_as_buffer */ |
|
6688 #if (PY_VERSION_HEX < 0x03000000) |
|
6689 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ |
|
6690 #else |
|
6691 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
6692 #endif |
|
6693 0, /* tp_doc */ |
|
6694 0, /* tp_traverse */ |
|
6695 0, /* tp_clear */ |
|
6696 0, /* tp_richcompare */ |
|
6697 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */ |
|
6698 0, /*tp_iter*/ |
|
6699 0, /*tp_iternext*/ |
|
6700 DB_methods, /*tp_methods*/ |
|
6701 0, /*tp_members*/ |
|
6702 }; |
|
6703 |
|
6704 |
|
6705 statichere PyTypeObject DBCursor_Type = { |
|
6706 #if (PY_VERSION_HEX < 0x03000000) |
|
6707 PyObject_HEAD_INIT(NULL) |
|
6708 0, /*ob_size*/ |
|
6709 #else |
|
6710 PyVarObject_HEAD_INIT(NULL, 0) |
|
6711 #endif |
|
6712 "DBCursor", /*tp_name*/ |
|
6713 sizeof(DBCursorObject), /*tp_basicsize*/ |
|
6714 0, /*tp_itemsize*/ |
|
6715 /* methods */ |
|
6716 (destructor)DBCursor_dealloc,/*tp_dealloc*/ |
|
6717 0, /*tp_print*/ |
|
6718 0, /*tp_getattr*/ |
|
6719 0, /*tp_setattr*/ |
|
6720 0, /*tp_compare*/ |
|
6721 0, /*tp_repr*/ |
|
6722 0, /*tp_as_number*/ |
|
6723 0, /*tp_as_sequence*/ |
|
6724 0, /*tp_as_mapping*/ |
|
6725 0, /*tp_hash*/ |
|
6726 0, /*tp_call*/ |
|
6727 0, /*tp_str*/ |
|
6728 0, /*tp_getattro*/ |
|
6729 0, /*tp_setattro*/ |
|
6730 0, /*tp_as_buffer*/ |
|
6731 #if (PY_VERSION_HEX < 0x03000000) |
|
6732 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ |
|
6733 #else |
|
6734 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
6735 #endif |
|
6736 0, /* tp_doc */ |
|
6737 0, /* tp_traverse */ |
|
6738 0, /* tp_clear */ |
|
6739 0, /* tp_richcompare */ |
|
6740 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */ |
|
6741 0, /*tp_iter*/ |
|
6742 0, /*tp_iternext*/ |
|
6743 DBCursor_methods, /*tp_methods*/ |
|
6744 0, /*tp_members*/ |
|
6745 }; |
|
6746 |
|
6747 |
|
6748 statichere PyTypeObject DBEnv_Type = { |
|
6749 #if (PY_VERSION_HEX < 0x03000000) |
|
6750 PyObject_HEAD_INIT(NULL) |
|
6751 0, /*ob_size*/ |
|
6752 #else |
|
6753 PyVarObject_HEAD_INIT(NULL, 0) |
|
6754 #endif |
|
6755 "DBEnv", /*tp_name*/ |
|
6756 sizeof(DBEnvObject), /*tp_basicsize*/ |
|
6757 0, /*tp_itemsize*/ |
|
6758 /* methods */ |
|
6759 (destructor)DBEnv_dealloc, /*tp_dealloc*/ |
|
6760 0, /*tp_print*/ |
|
6761 0, /*tp_getattr*/ |
|
6762 0, /*tp_setattr*/ |
|
6763 0, /*tp_compare*/ |
|
6764 0, /*tp_repr*/ |
|
6765 0, /*tp_as_number*/ |
|
6766 0, /*tp_as_sequence*/ |
|
6767 0, /*tp_as_mapping*/ |
|
6768 0, /*tp_hash*/ |
|
6769 0, /* tp_call */ |
|
6770 0, /* tp_str */ |
|
6771 0, /* tp_getattro */ |
|
6772 0, /* tp_setattro */ |
|
6773 0, /* tp_as_buffer */ |
|
6774 #if (PY_VERSION_HEX < 0x03000000) |
|
6775 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ |
|
6776 #else |
|
6777 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
6778 #endif |
|
6779 0, /* tp_doc */ |
|
6780 0, /* tp_traverse */ |
|
6781 0, /* tp_clear */ |
|
6782 0, /* tp_richcompare */ |
|
6783 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */ |
|
6784 0, /* tp_iter */ |
|
6785 0, /* tp_iternext */ |
|
6786 DBEnv_methods, /* tp_methods */ |
|
6787 0, /* tp_members */ |
|
6788 DBEnv_getsets, /* tp_getsets */ |
|
6789 }; |
|
6790 |
|
6791 statichere PyTypeObject DBTxn_Type = { |
|
6792 #if (PY_VERSION_HEX < 0x03000000) |
|
6793 PyObject_HEAD_INIT(NULL) |
|
6794 0, /*ob_size*/ |
|
6795 #else |
|
6796 PyVarObject_HEAD_INIT(NULL, 0) |
|
6797 #endif |
|
6798 "DBTxn", /*tp_name*/ |
|
6799 sizeof(DBTxnObject), /*tp_basicsize*/ |
|
6800 0, /*tp_itemsize*/ |
|
6801 /* methods */ |
|
6802 (destructor)DBTxn_dealloc, /*tp_dealloc*/ |
|
6803 0, /*tp_print*/ |
|
6804 0, /*tp_getattr*/ |
|
6805 0, /*tp_setattr*/ |
|
6806 0, /*tp_compare*/ |
|
6807 0, /*tp_repr*/ |
|
6808 0, /*tp_as_number*/ |
|
6809 0, /*tp_as_sequence*/ |
|
6810 0, /*tp_as_mapping*/ |
|
6811 0, /*tp_hash*/ |
|
6812 0, /* tp_call */ |
|
6813 0, /* tp_str */ |
|
6814 0, /* tp_getattro */ |
|
6815 0, /* tp_setattro */ |
|
6816 0, /* tp_as_buffer */ |
|
6817 #if (PY_VERSION_HEX < 0x03000000) |
|
6818 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ |
|
6819 #else |
|
6820 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
6821 #endif |
|
6822 0, /* tp_doc */ |
|
6823 0, /* tp_traverse */ |
|
6824 0, /* tp_clear */ |
|
6825 0, /* tp_richcompare */ |
|
6826 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */ |
|
6827 0, /*tp_iter*/ |
|
6828 0, /*tp_iternext*/ |
|
6829 DBTxn_methods, /*tp_methods*/ |
|
6830 0, /*tp_members*/ |
|
6831 }; |
|
6832 |
|
6833 |
|
6834 statichere PyTypeObject DBLock_Type = { |
|
6835 #if (PY_VERSION_HEX < 0x03000000) |
|
6836 PyObject_HEAD_INIT(NULL) |
|
6837 0, /*ob_size*/ |
|
6838 #else |
|
6839 PyVarObject_HEAD_INIT(NULL, 0) |
|
6840 #endif |
|
6841 "DBLock", /*tp_name*/ |
|
6842 sizeof(DBLockObject), /*tp_basicsize*/ |
|
6843 0, /*tp_itemsize*/ |
|
6844 /* methods */ |
|
6845 (destructor)DBLock_dealloc, /*tp_dealloc*/ |
|
6846 0, /*tp_print*/ |
|
6847 0, /*tp_getattr*/ |
|
6848 0, /*tp_setattr*/ |
|
6849 0, /*tp_compare*/ |
|
6850 0, /*tp_repr*/ |
|
6851 0, /*tp_as_number*/ |
|
6852 0, /*tp_as_sequence*/ |
|
6853 0, /*tp_as_mapping*/ |
|
6854 0, /*tp_hash*/ |
|
6855 0, /* tp_call */ |
|
6856 0, /* tp_str */ |
|
6857 0, /* tp_getattro */ |
|
6858 0, /* tp_setattro */ |
|
6859 0, /* tp_as_buffer */ |
|
6860 #if (PY_VERSION_HEX < 0x03000000) |
|
6861 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ |
|
6862 #else |
|
6863 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
6864 #endif |
|
6865 0, /* tp_doc */ |
|
6866 0, /* tp_traverse */ |
|
6867 0, /* tp_clear */ |
|
6868 0, /* tp_richcompare */ |
|
6869 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */ |
|
6870 }; |
|
6871 |
|
6872 #if (DBVER >= 43) |
|
6873 statichere PyTypeObject DBSequence_Type = { |
|
6874 #if (PY_VERSION_HEX < 0x03000000) |
|
6875 PyObject_HEAD_INIT(NULL) |
|
6876 0, /*ob_size*/ |
|
6877 #else |
|
6878 PyVarObject_HEAD_INIT(NULL, 0) |
|
6879 #endif |
|
6880 "DBSequence", /*tp_name*/ |
|
6881 sizeof(DBSequenceObject), /*tp_basicsize*/ |
|
6882 0, /*tp_itemsize*/ |
|
6883 /* methods */ |
|
6884 (destructor)DBSequence_dealloc, /*tp_dealloc*/ |
|
6885 0, /*tp_print*/ |
|
6886 0, /*tp_getattr*/ |
|
6887 0, /*tp_setattr*/ |
|
6888 0, /*tp_compare*/ |
|
6889 0, /*tp_repr*/ |
|
6890 0, /*tp_as_number*/ |
|
6891 0, /*tp_as_sequence*/ |
|
6892 0, /*tp_as_mapping*/ |
|
6893 0, /*tp_hash*/ |
|
6894 0, /* tp_call */ |
|
6895 0, /* tp_str */ |
|
6896 0, /* tp_getattro */ |
|
6897 0, /* tp_setattro */ |
|
6898 0, /* tp_as_buffer */ |
|
6899 #if (PY_VERSION_HEX < 0x03000000) |
|
6900 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ |
|
6901 #else |
|
6902 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
6903 #endif |
|
6904 0, /* tp_doc */ |
|
6905 0, /* tp_traverse */ |
|
6906 0, /* tp_clear */ |
|
6907 0, /* tp_richcompare */ |
|
6908 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */ |
|
6909 0, /*tp_iter*/ |
|
6910 0, /*tp_iternext*/ |
|
6911 DBSequence_methods, /*tp_methods*/ |
|
6912 0, /*tp_members*/ |
|
6913 }; |
|
6914 #endif |
|
6915 |
|
6916 /* --------------------------------------------------------------------- */ |
|
6917 /* Module-level functions */ |
|
6918 |
|
6919 static PyObject* |
|
6920 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs) |
|
6921 { |
|
6922 PyObject* dbenvobj = NULL; |
|
6923 int flags = 0; |
|
6924 static char* kwnames[] = { "dbEnv", "flags", NULL}; |
|
6925 |
|
6926 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames, |
|
6927 &dbenvobj, &flags)) |
|
6928 return NULL; |
|
6929 if (dbenvobj == Py_None) |
|
6930 dbenvobj = NULL; |
|
6931 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) { |
|
6932 makeTypeError("DBEnv", dbenvobj); |
|
6933 return NULL; |
|
6934 } |
|
6935 |
|
6936 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags); |
|
6937 } |
|
6938 |
|
6939 |
|
6940 static PyObject* |
|
6941 DBEnv_construct(PyObject* self, PyObject* args) |
|
6942 { |
|
6943 int flags = 0; |
|
6944 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL; |
|
6945 return (PyObject* )newDBEnvObject(flags); |
|
6946 } |
|
6947 |
|
6948 #if (DBVER >= 43) |
|
6949 static PyObject* |
|
6950 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs) |
|
6951 { |
|
6952 PyObject* dbobj; |
|
6953 int flags = 0; |
|
6954 static char* kwnames[] = { "db", "flags", NULL}; |
|
6955 |
|
6956 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags)) |
|
6957 return NULL; |
|
6958 if (!DBObject_Check(dbobj)) { |
|
6959 makeTypeError("DB", dbobj); |
|
6960 return NULL; |
|
6961 } |
|
6962 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags); |
|
6963 } |
|
6964 #endif |
|
6965 |
|
6966 static char bsddb_version_doc[] = |
|
6967 "Returns a tuple of major, minor, and patch release numbers of the\n\ |
|
6968 underlying DB library."; |
|
6969 |
|
6970 static PyObject* |
|
6971 bsddb_version(PyObject* self) |
|
6972 { |
|
6973 int major, minor, patch; |
|
6974 |
|
6975 db_version(&major, &minor, &patch); |
|
6976 return Py_BuildValue("(iii)", major, minor, patch); |
|
6977 } |
|
6978 |
|
6979 |
|
6980 /* List of functions defined in the module */ |
|
6981 static PyMethodDef bsddb_methods[] = { |
|
6982 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS }, |
|
6983 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS}, |
|
6984 #if (DBVER >= 43) |
|
6985 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS }, |
|
6986 #endif |
|
6987 {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc}, |
|
6988 {NULL, NULL} /* sentinel */ |
|
6989 }; |
|
6990 |
|
6991 |
|
6992 /* API structure */ |
|
6993 static BSDDB_api bsddb_api; |
|
6994 |
|
6995 |
|
6996 /* --------------------------------------------------------------------- */ |
|
6997 /* Module initialization */ |
|
6998 |
|
6999 |
|
7000 /* Convenience routine to export an integer value. |
|
7001 * Errors are silently ignored, for better or for worse... |
|
7002 */ |
|
7003 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME) |
|
7004 |
|
7005 #define MODULE_NAME_MAX_LEN 11 |
|
7006 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb"; |
|
7007 |
|
7008 #if (PY_VERSION_HEX >= 0x03000000) |
|
7009 static struct PyModuleDef bsddbmodule = { |
|
7010 PyModuleDef_HEAD_INIT, |
|
7011 _bsddbModuleName, /* Name of module */ |
|
7012 NULL, /* module documentation, may be NULL */ |
|
7013 -1, /* size of per-interpreter state of the module, |
|
7014 or -1 if the module keeps state in global variables. */ |
|
7015 bsddb_methods, |
|
7016 NULL, /* Reload */ |
|
7017 NULL, /* Traverse */ |
|
7018 NULL, /* Clear */ |
|
7019 NULL /* Free */ |
|
7020 }; |
|
7021 #endif |
|
7022 |
|
7023 |
|
7024 #if (PY_VERSION_HEX < 0x03000000) |
|
7025 DL_EXPORT(void) init_bsddb(void) |
|
7026 #else |
|
7027 PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */ |
|
7028 #endif |
|
7029 { |
|
7030 PyObject* m; |
|
7031 PyObject* d; |
|
7032 PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION ); |
|
7033 PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING ); |
|
7034 PyObject* cvsid_s = PyBytes_FromString( rcs_id ); |
|
7035 PyObject* py_api; |
|
7036 |
|
7037 /* Initialize object types */ |
|
7038 if ((PyType_Ready(&DB_Type) < 0) |
|
7039 || (PyType_Ready(&DBCursor_Type) < 0) |
|
7040 || (PyType_Ready(&DBEnv_Type) < 0) |
|
7041 || (PyType_Ready(&DBTxn_Type) < 0) |
|
7042 || (PyType_Ready(&DBLock_Type) < 0) |
|
7043 #if (DBVER >= 43) |
|
7044 || (PyType_Ready(&DBSequence_Type) < 0) |
|
7045 #endif |
|
7046 ) { |
|
7047 #if (PY_VERSION_HEX < 0x03000000) |
|
7048 return; |
|
7049 #else |
|
7050 return NULL; |
|
7051 #endif |
|
7052 } |
|
7053 |
|
7054 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE) |
|
7055 /* Save the current interpreter, so callbacks can do the right thing. */ |
|
7056 _db_interpreterState = PyThreadState_GET()->interp; |
|
7057 #endif |
|
7058 |
|
7059 /* Create the module and add the functions */ |
|
7060 #if (PY_VERSION_HEX < 0x03000000) |
|
7061 m = Py_InitModule(_bsddbModuleName, bsddb_methods); |
|
7062 #else |
|
7063 m=PyModule_Create(&bsddbmodule); |
|
7064 #endif |
|
7065 if (m == NULL) { |
|
7066 #if (PY_VERSION_HEX < 0x03000000) |
|
7067 return; |
|
7068 #else |
|
7069 return NULL; |
|
7070 #endif |
|
7071 } |
|
7072 |
|
7073 /* Add some symbolic constants to the module */ |
|
7074 d = PyModule_GetDict(m); |
|
7075 PyDict_SetItemString(d, "__version__", pybsddb_version_s); |
|
7076 PyDict_SetItemString(d, "cvsid", cvsid_s); |
|
7077 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s); |
|
7078 Py_DECREF(pybsddb_version_s); |
|
7079 pybsddb_version_s = NULL; |
|
7080 Py_DECREF(cvsid_s); |
|
7081 cvsid_s = NULL; |
|
7082 Py_DECREF(db_version_s); |
|
7083 db_version_s = NULL; |
|
7084 |
|
7085 ADD_INT(d, DB_VERSION_MAJOR); |
|
7086 ADD_INT(d, DB_VERSION_MINOR); |
|
7087 ADD_INT(d, DB_VERSION_PATCH); |
|
7088 |
|
7089 ADD_INT(d, DB_MAX_PAGES); |
|
7090 ADD_INT(d, DB_MAX_RECORDS); |
|
7091 |
|
7092 #if (DBVER >= 42) |
|
7093 ADD_INT(d, DB_RPCCLIENT); |
|
7094 #else |
|
7095 ADD_INT(d, DB_CLIENT); |
|
7096 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */ |
|
7097 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT); |
|
7098 #endif |
|
7099 ADD_INT(d, DB_XA_CREATE); |
|
7100 |
|
7101 ADD_INT(d, DB_CREATE); |
|
7102 ADD_INT(d, DB_NOMMAP); |
|
7103 ADD_INT(d, DB_THREAD); |
|
7104 #if (DBVER >= 45) |
|
7105 ADD_INT(d, DB_MULTIVERSION); |
|
7106 #endif |
|
7107 |
|
7108 ADD_INT(d, DB_FORCE); |
|
7109 ADD_INT(d, DB_INIT_CDB); |
|
7110 ADD_INT(d, DB_INIT_LOCK); |
|
7111 ADD_INT(d, DB_INIT_LOG); |
|
7112 ADD_INT(d, DB_INIT_MPOOL); |
|
7113 ADD_INT(d, DB_INIT_TXN); |
|
7114 ADD_INT(d, DB_JOINENV); |
|
7115 |
|
7116 ADD_INT(d, DB_XIDDATASIZE); |
|
7117 |
|
7118 ADD_INT(d, DB_RECOVER); |
|
7119 ADD_INT(d, DB_RECOVER_FATAL); |
|
7120 ADD_INT(d, DB_TXN_NOSYNC); |
|
7121 ADD_INT(d, DB_USE_ENVIRON); |
|
7122 ADD_INT(d, DB_USE_ENVIRON_ROOT); |
|
7123 |
|
7124 ADD_INT(d, DB_LOCKDOWN); |
|
7125 ADD_INT(d, DB_PRIVATE); |
|
7126 ADD_INT(d, DB_SYSTEM_MEM); |
|
7127 |
|
7128 ADD_INT(d, DB_TXN_SYNC); |
|
7129 ADD_INT(d, DB_TXN_NOWAIT); |
|
7130 |
|
7131 ADD_INT(d, DB_EXCL); |
|
7132 ADD_INT(d, DB_FCNTL_LOCKING); |
|
7133 ADD_INT(d, DB_ODDFILESIZE); |
|
7134 ADD_INT(d, DB_RDWRMASTER); |
|
7135 ADD_INT(d, DB_RDONLY); |
|
7136 ADD_INT(d, DB_TRUNCATE); |
|
7137 ADD_INT(d, DB_EXTENT); |
|
7138 ADD_INT(d, DB_CDB_ALLDB); |
|
7139 ADD_INT(d, DB_VERIFY); |
|
7140 ADD_INT(d, DB_UPGRADE); |
|
7141 |
|
7142 ADD_INT(d, DB_AGGRESSIVE); |
|
7143 ADD_INT(d, DB_NOORDERCHK); |
|
7144 ADD_INT(d, DB_ORDERCHKONLY); |
|
7145 ADD_INT(d, DB_PR_PAGE); |
|
7146 |
|
7147 ADD_INT(d, DB_PR_RECOVERYTEST); |
|
7148 ADD_INT(d, DB_SALVAGE); |
|
7149 |
|
7150 ADD_INT(d, DB_LOCK_NORUN); |
|
7151 ADD_INT(d, DB_LOCK_DEFAULT); |
|
7152 ADD_INT(d, DB_LOCK_OLDEST); |
|
7153 ADD_INT(d, DB_LOCK_RANDOM); |
|
7154 ADD_INT(d, DB_LOCK_YOUNGEST); |
|
7155 ADD_INT(d, DB_LOCK_MAXLOCKS); |
|
7156 ADD_INT(d, DB_LOCK_MINLOCKS); |
|
7157 ADD_INT(d, DB_LOCK_MINWRITE); |
|
7158 |
|
7159 ADD_INT(d, DB_LOCK_EXPIRE); |
|
7160 #if (DBVER >= 43) |
|
7161 ADD_INT(d, DB_LOCK_MAXWRITE); |
|
7162 #endif |
|
7163 |
|
7164 _addIntToDict(d, "DB_LOCK_CONFLICT", 0); |
|
7165 |
|
7166 ADD_INT(d, DB_LOCK_DUMP); |
|
7167 ADD_INT(d, DB_LOCK_GET); |
|
7168 ADD_INT(d, DB_LOCK_INHERIT); |
|
7169 ADD_INT(d, DB_LOCK_PUT); |
|
7170 ADD_INT(d, DB_LOCK_PUT_ALL); |
|
7171 ADD_INT(d, DB_LOCK_PUT_OBJ); |
|
7172 |
|
7173 ADD_INT(d, DB_LOCK_NG); |
|
7174 ADD_INT(d, DB_LOCK_READ); |
|
7175 ADD_INT(d, DB_LOCK_WRITE); |
|
7176 ADD_INT(d, DB_LOCK_NOWAIT); |
|
7177 ADD_INT(d, DB_LOCK_WAIT); |
|
7178 ADD_INT(d, DB_LOCK_IWRITE); |
|
7179 ADD_INT(d, DB_LOCK_IREAD); |
|
7180 ADD_INT(d, DB_LOCK_IWR); |
|
7181 #if (DBVER < 44) |
|
7182 ADD_INT(d, DB_LOCK_DIRTY); |
|
7183 #else |
|
7184 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */ |
|
7185 #endif |
|
7186 ADD_INT(d, DB_LOCK_WWRITE); |
|
7187 |
|
7188 ADD_INT(d, DB_LOCK_RECORD); |
|
7189 ADD_INT(d, DB_LOCK_UPGRADE); |
|
7190 ADD_INT(d, DB_LOCK_SWITCH); |
|
7191 ADD_INT(d, DB_LOCK_UPGRADE_WRITE); |
|
7192 |
|
7193 ADD_INT(d, DB_LOCK_NOWAIT); |
|
7194 ADD_INT(d, DB_LOCK_RECORD); |
|
7195 ADD_INT(d, DB_LOCK_UPGRADE); |
|
7196 |
|
7197 ADD_INT(d, DB_LSTAT_ABORTED); |
|
7198 #if (DBVER < 43) |
|
7199 ADD_INT(d, DB_LSTAT_ERR); |
|
7200 #endif |
|
7201 ADD_INT(d, DB_LSTAT_FREE); |
|
7202 ADD_INT(d, DB_LSTAT_HELD); |
|
7203 |
|
7204 ADD_INT(d, DB_LSTAT_PENDING); |
|
7205 ADD_INT(d, DB_LSTAT_WAITING); |
|
7206 |
|
7207 ADD_INT(d, DB_ARCH_ABS); |
|
7208 ADD_INT(d, DB_ARCH_DATA); |
|
7209 ADD_INT(d, DB_ARCH_LOG); |
|
7210 #if (DBVER >= 42) |
|
7211 ADD_INT(d, DB_ARCH_REMOVE); |
|
7212 #endif |
|
7213 |
|
7214 ADD_INT(d, DB_BTREE); |
|
7215 ADD_INT(d, DB_HASH); |
|
7216 ADD_INT(d, DB_RECNO); |
|
7217 ADD_INT(d, DB_QUEUE); |
|
7218 ADD_INT(d, DB_UNKNOWN); |
|
7219 |
|
7220 ADD_INT(d, DB_DUP); |
|
7221 ADD_INT(d, DB_DUPSORT); |
|
7222 ADD_INT(d, DB_RECNUM); |
|
7223 ADD_INT(d, DB_RENUMBER); |
|
7224 ADD_INT(d, DB_REVSPLITOFF); |
|
7225 ADD_INT(d, DB_SNAPSHOT); |
|
7226 |
|
7227 ADD_INT(d, DB_JOIN_NOSORT); |
|
7228 |
|
7229 ADD_INT(d, DB_AFTER); |
|
7230 ADD_INT(d, DB_APPEND); |
|
7231 ADD_INT(d, DB_BEFORE); |
|
7232 #if (DBVER < 45) |
|
7233 ADD_INT(d, DB_CACHED_COUNTS); |
|
7234 #endif |
|
7235 |
|
7236 #if (DBVER >= 41) |
|
7237 _addIntToDict(d, "DB_CHECKPOINT", 0); |
|
7238 #else |
|
7239 ADD_INT(d, DB_CHECKPOINT); |
|
7240 ADD_INT(d, DB_CURLSN); |
|
7241 #endif |
|
7242 #if (DBVER <= 41) |
|
7243 ADD_INT(d, DB_COMMIT); |
|
7244 #endif |
|
7245 ADD_INT(d, DB_CONSUME); |
|
7246 ADD_INT(d, DB_CONSUME_WAIT); |
|
7247 ADD_INT(d, DB_CURRENT); |
|
7248 ADD_INT(d, DB_FAST_STAT); |
|
7249 ADD_INT(d, DB_FIRST); |
|
7250 ADD_INT(d, DB_FLUSH); |
|
7251 ADD_INT(d, DB_GET_BOTH); |
|
7252 ADD_INT(d, DB_GET_RECNO); |
|
7253 ADD_INT(d, DB_JOIN_ITEM); |
|
7254 ADD_INT(d, DB_KEYFIRST); |
|
7255 ADD_INT(d, DB_KEYLAST); |
|
7256 ADD_INT(d, DB_LAST); |
|
7257 ADD_INT(d, DB_NEXT); |
|
7258 ADD_INT(d, DB_NEXT_DUP); |
|
7259 ADD_INT(d, DB_NEXT_NODUP); |
|
7260 ADD_INT(d, DB_NODUPDATA); |
|
7261 ADD_INT(d, DB_NOOVERWRITE); |
|
7262 ADD_INT(d, DB_NOSYNC); |
|
7263 ADD_INT(d, DB_POSITION); |
|
7264 ADD_INT(d, DB_PREV); |
|
7265 ADD_INT(d, DB_PREV_NODUP); |
|
7266 #if (DBVER < 45) |
|
7267 ADD_INT(d, DB_RECORDCOUNT); |
|
7268 #endif |
|
7269 ADD_INT(d, DB_SET); |
|
7270 ADD_INT(d, DB_SET_RANGE); |
|
7271 ADD_INT(d, DB_SET_RECNO); |
|
7272 ADD_INT(d, DB_WRITECURSOR); |
|
7273 |
|
7274 ADD_INT(d, DB_OPFLAGS_MASK); |
|
7275 ADD_INT(d, DB_RMW); |
|
7276 ADD_INT(d, DB_DIRTY_READ); |
|
7277 ADD_INT(d, DB_MULTIPLE); |
|
7278 ADD_INT(d, DB_MULTIPLE_KEY); |
|
7279 |
|
7280 #if (DBVER >= 44) |
|
7281 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */ |
|
7282 ADD_INT(d, DB_READ_COMMITTED); |
|
7283 #endif |
|
7284 |
|
7285 ADD_INT(d, DB_DONOTINDEX); |
|
7286 |
|
7287 #if (DBVER >= 41) |
|
7288 _addIntToDict(d, "DB_INCOMPLETE", 0); |
|
7289 #else |
|
7290 ADD_INT(d, DB_INCOMPLETE); |
|
7291 #endif |
|
7292 ADD_INT(d, DB_KEYEMPTY); |
|
7293 ADD_INT(d, DB_KEYEXIST); |
|
7294 ADD_INT(d, DB_LOCK_DEADLOCK); |
|
7295 ADD_INT(d, DB_LOCK_NOTGRANTED); |
|
7296 ADD_INT(d, DB_NOSERVER); |
|
7297 ADD_INT(d, DB_NOSERVER_HOME); |
|
7298 ADD_INT(d, DB_NOSERVER_ID); |
|
7299 ADD_INT(d, DB_NOTFOUND); |
|
7300 ADD_INT(d, DB_OLD_VERSION); |
|
7301 ADD_INT(d, DB_RUNRECOVERY); |
|
7302 ADD_INT(d, DB_VERIFY_BAD); |
|
7303 ADD_INT(d, DB_PAGE_NOTFOUND); |
|
7304 ADD_INT(d, DB_SECONDARY_BAD); |
|
7305 ADD_INT(d, DB_STAT_CLEAR); |
|
7306 ADD_INT(d, DB_REGION_INIT); |
|
7307 ADD_INT(d, DB_NOLOCKING); |
|
7308 ADD_INT(d, DB_YIELDCPU); |
|
7309 ADD_INT(d, DB_PANIC_ENVIRONMENT); |
|
7310 ADD_INT(d, DB_NOPANIC); |
|
7311 |
|
7312 #if (DBVER >= 41) |
|
7313 ADD_INT(d, DB_OVERWRITE); |
|
7314 #endif |
|
7315 |
|
7316 #ifdef DB_REGISTER |
|
7317 ADD_INT(d, DB_REGISTER); |
|
7318 #endif |
|
7319 |
|
7320 #if (DBVER >= 42) |
|
7321 ADD_INT(d, DB_TIME_NOTGRANTED); |
|
7322 ADD_INT(d, DB_TXN_NOT_DURABLE); |
|
7323 ADD_INT(d, DB_TXN_WRITE_NOSYNC); |
|
7324 ADD_INT(d, DB_DIRECT_DB); |
|
7325 ADD_INT(d, DB_INIT_REP); |
|
7326 ADD_INT(d, DB_ENCRYPT); |
|
7327 ADD_INT(d, DB_CHKSUM); |
|
7328 #endif |
|
7329 |
|
7330 #if (DBVER >= 42) && (DBVER < 47) |
|
7331 ADD_INT(d, DB_LOG_AUTOREMOVE); |
|
7332 ADD_INT(d, DB_DIRECT_LOG); |
|
7333 #endif |
|
7334 |
|
7335 #if (DBVER >= 47) |
|
7336 ADD_INT(d, DB_LOG_DIRECT); |
|
7337 ADD_INT(d, DB_LOG_DSYNC); |
|
7338 ADD_INT(d, DB_LOG_IN_MEMORY); |
|
7339 ADD_INT(d, DB_LOG_AUTO_REMOVE); |
|
7340 ADD_INT(d, DB_LOG_ZERO); |
|
7341 #endif |
|
7342 |
|
7343 #if (DBVER >= 44) |
|
7344 ADD_INT(d, DB_DSYNC_DB); |
|
7345 #endif |
|
7346 |
|
7347 #if (DBVER >= 45) |
|
7348 ADD_INT(d, DB_TXN_SNAPSHOT); |
|
7349 #endif |
|
7350 |
|
7351 ADD_INT(d, DB_VERB_DEADLOCK); |
|
7352 #if (DBVER >= 46) |
|
7353 ADD_INT(d, DB_VERB_FILEOPS); |
|
7354 ADD_INT(d, DB_VERB_FILEOPS_ALL); |
|
7355 #endif |
|
7356 ADD_INT(d, DB_VERB_RECOVERY); |
|
7357 #if (DBVER >= 44) |
|
7358 ADD_INT(d, DB_VERB_REGISTER); |
|
7359 #endif |
|
7360 ADD_INT(d, DB_VERB_REPLICATION); |
|
7361 ADD_INT(d, DB_VERB_WAITSFOR); |
|
7362 |
|
7363 #if (DBVER >= 45) |
|
7364 ADD_INT(d, DB_EVENT_PANIC); |
|
7365 ADD_INT(d, DB_EVENT_REP_CLIENT); |
|
7366 #if (DBVER >= 46) |
|
7367 ADD_INT(d, DB_EVENT_REP_ELECTED); |
|
7368 #endif |
|
7369 ADD_INT(d, DB_EVENT_REP_MASTER); |
|
7370 ADD_INT(d, DB_EVENT_REP_NEWMASTER); |
|
7371 #if (DBVER >= 46) |
|
7372 ADD_INT(d, DB_EVENT_REP_PERM_FAILED); |
|
7373 #endif |
|
7374 ADD_INT(d, DB_EVENT_REP_STARTUPDONE); |
|
7375 ADD_INT(d, DB_EVENT_WRITE_FAILED); |
|
7376 #endif |
|
7377 |
|
7378 ADD_INT(d, DB_REP_DUPMASTER); |
|
7379 ADD_INT(d, DB_REP_HOLDELECTION); |
|
7380 #if (DBVER >= 44) |
|
7381 ADD_INT(d, DB_REP_IGNORE); |
|
7382 ADD_INT(d, DB_REP_JOIN_FAILURE); |
|
7383 #endif |
|
7384 #if (DBVER >= 42) |
|
7385 ADD_INT(d, DB_REP_ISPERM); |
|
7386 ADD_INT(d, DB_REP_NOTPERM); |
|
7387 #endif |
|
7388 ADD_INT(d, DB_REP_NEWSITE); |
|
7389 |
|
7390 ADD_INT(d, DB_REP_MASTER); |
|
7391 ADD_INT(d, DB_REP_CLIENT); |
|
7392 #if (DBVER >= 45) |
|
7393 ADD_INT(d, DB_REP_ELECTION); |
|
7394 |
|
7395 ADD_INT(d, DB_REP_ACK_TIMEOUT); |
|
7396 ADD_INT(d, DB_REP_CONNECTION_RETRY); |
|
7397 ADD_INT(d, DB_REP_ELECTION_TIMEOUT); |
|
7398 ADD_INT(d, DB_REP_ELECTION_RETRY); |
|
7399 #endif |
|
7400 #if (DBVER >= 46) |
|
7401 ADD_INT(d, DB_REP_CHECKPOINT_DELAY); |
|
7402 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT); |
|
7403 #endif |
|
7404 |
|
7405 #if (DBVER >= 45) |
|
7406 ADD_INT(d, DB_REPMGR_PEER); |
|
7407 ADD_INT(d, DB_REPMGR_ACKS_ALL); |
|
7408 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS); |
|
7409 ADD_INT(d, DB_REPMGR_ACKS_NONE); |
|
7410 ADD_INT(d, DB_REPMGR_ACKS_ONE); |
|
7411 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER); |
|
7412 ADD_INT(d, DB_REPMGR_ACKS_QUORUM); |
|
7413 ADD_INT(d, DB_REPMGR_CONNECTED); |
|
7414 ADD_INT(d, DB_REPMGR_DISCONNECTED); |
|
7415 ADD_INT(d, DB_STAT_CLEAR); |
|
7416 ADD_INT(d, DB_STAT_ALL); |
|
7417 #endif |
|
7418 |
|
7419 #if (DBVER >= 43) |
|
7420 ADD_INT(d, DB_BUFFER_SMALL); |
|
7421 ADD_INT(d, DB_SEQ_DEC); |
|
7422 ADD_INT(d, DB_SEQ_INC); |
|
7423 ADD_INT(d, DB_SEQ_WRAP); |
|
7424 #endif |
|
7425 |
|
7426 #if (DBVER >= 43) && (DBVER < 47) |
|
7427 ADD_INT(d, DB_LOG_INMEMORY); |
|
7428 ADD_INT(d, DB_DSYNC_LOG); |
|
7429 #endif |
|
7430 |
|
7431 #if (DBVER >= 41) |
|
7432 ADD_INT(d, DB_ENCRYPT_AES); |
|
7433 ADD_INT(d, DB_AUTO_COMMIT); |
|
7434 #else |
|
7435 /* allow Berkeley DB 4.1 aware apps to run on older versions */ |
|
7436 _addIntToDict(d, "DB_AUTO_COMMIT", 0); |
|
7437 #endif |
|
7438 |
|
7439 ADD_INT(d, EINVAL); |
|
7440 ADD_INT(d, EACCES); |
|
7441 ADD_INT(d, ENOSPC); |
|
7442 ADD_INT(d, ENOMEM); |
|
7443 ADD_INT(d, EAGAIN); |
|
7444 ADD_INT(d, EBUSY); |
|
7445 ADD_INT(d, EEXIST); |
|
7446 ADD_INT(d, ENOENT); |
|
7447 ADD_INT(d, EPERM); |
|
7448 |
|
7449 ADD_INT(d, DB_SET_LOCK_TIMEOUT); |
|
7450 ADD_INT(d, DB_SET_TXN_TIMEOUT); |
|
7451 |
|
7452 /* The exception name must be correct for pickled exception * |
|
7453 * objects to unpickle properly. */ |
|
7454 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */ |
|
7455 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db." |
|
7456 #else |
|
7457 #define PYBSDDB_EXCEPTION_BASE "bsddb.db." |
|
7458 #endif |
|
7459 |
|
7460 /* All the rest of the exceptions derive only from DBError */ |
|
7461 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \ |
|
7462 PyDict_SetItemString(d, #name, name) |
|
7463 |
|
7464 /* The base exception class is DBError */ |
|
7465 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */ |
|
7466 MAKE_EX(DBError); |
|
7467 |
|
7468 #if (PY_VERSION_HEX < 0x03000000) |
|
7469 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive |
|
7470 * from both DBError and KeyError, since the API only supports |
|
7471 * using one base class. */ |
|
7472 PyDict_SetItemString(d, "KeyError", PyExc_KeyError); |
|
7473 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n" |
|
7474 "class DBKeyEmptyError(DBError, KeyError): pass", |
|
7475 Py_file_input, d, d); |
|
7476 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError"); |
|
7477 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError"); |
|
7478 PyDict_DelItemString(d, "KeyError"); |
|
7479 #else |
|
7480 /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to |
|
7481 ** derive from several classes. We use this new API only for Python 3.0, |
|
7482 ** though. |
|
7483 */ |
|
7484 { |
|
7485 PyObject* bases; |
|
7486 |
|
7487 bases = PyTuple_Pack(2, DBError, PyExc_KeyError); |
|
7488 |
|
7489 #define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \ |
|
7490 PyDict_SetItemString(d, #name, name) |
|
7491 MAKE_EX2(DBNotFoundError); |
|
7492 MAKE_EX2(DBKeyEmptyError); |
|
7493 |
|
7494 #undef MAKE_EX2 |
|
7495 |
|
7496 Py_XDECREF(bases); |
|
7497 } |
|
7498 #endif |
|
7499 |
|
7500 |
|
7501 #if !INCOMPLETE_IS_WARNING |
|
7502 MAKE_EX(DBIncompleteError); |
|
7503 #endif |
|
7504 MAKE_EX(DBCursorClosedError); |
|
7505 MAKE_EX(DBKeyEmptyError); |
|
7506 MAKE_EX(DBKeyExistError); |
|
7507 MAKE_EX(DBLockDeadlockError); |
|
7508 MAKE_EX(DBLockNotGrantedError); |
|
7509 MAKE_EX(DBOldVersionError); |
|
7510 MAKE_EX(DBRunRecoveryError); |
|
7511 MAKE_EX(DBVerifyBadError); |
|
7512 MAKE_EX(DBNoServerError); |
|
7513 MAKE_EX(DBNoServerHomeError); |
|
7514 MAKE_EX(DBNoServerIDError); |
|
7515 MAKE_EX(DBPageNotFoundError); |
|
7516 MAKE_EX(DBSecondaryBadError); |
|
7517 |
|
7518 MAKE_EX(DBInvalidArgError); |
|
7519 MAKE_EX(DBAccessError); |
|
7520 MAKE_EX(DBNoSpaceError); |
|
7521 MAKE_EX(DBNoMemoryError); |
|
7522 MAKE_EX(DBAgainError); |
|
7523 MAKE_EX(DBBusyError); |
|
7524 MAKE_EX(DBFileExistsError); |
|
7525 MAKE_EX(DBNoSuchFileError); |
|
7526 MAKE_EX(DBPermissionsError); |
|
7527 |
|
7528 #if (DBVER >= 42) |
|
7529 MAKE_EX(DBRepHandleDeadError); |
|
7530 #endif |
|
7531 |
|
7532 MAKE_EX(DBRepUnavailError); |
|
7533 |
|
7534 #undef MAKE_EX |
|
7535 |
|
7536 /* Initiliase the C API structure and add it to the module */ |
|
7537 bsddb_api.db_type = &DB_Type; |
|
7538 bsddb_api.dbcursor_type = &DBCursor_Type; |
|
7539 bsddb_api.dbenv_type = &DBEnv_Type; |
|
7540 bsddb_api.dbtxn_type = &DBTxn_Type; |
|
7541 bsddb_api.dblock_type = &DBLock_Type; |
|
7542 #if (DBVER >= 43) |
|
7543 bsddb_api.dbsequence_type = &DBSequence_Type; |
|
7544 #endif |
|
7545 bsddb_api.makeDBError = makeDBError; |
|
7546 |
|
7547 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL); |
|
7548 PyDict_SetItemString(d, "api", py_api); |
|
7549 Py_DECREF(py_api); |
|
7550 |
|
7551 /* Check for errors */ |
|
7552 if (PyErr_Occurred()) { |
|
7553 PyErr_Print(); |
|
7554 Py_FatalError("can't initialize module _bsddb/_pybsddb"); |
|
7555 Py_DECREF(m); |
|
7556 m = NULL; |
|
7557 } |
|
7558 #if (PY_VERSION_HEX < 0x03000000) |
|
7559 return; |
|
7560 #else |
|
7561 return m; |
|
7562 #endif |
|
7563 } |
|
7564 |
|
7565 /* allow this module to be named _pybsddb so that it can be installed |
|
7566 * and imported on top of python >= 2.3 that includes its own older |
|
7567 * copy of the library named _bsddb without importing the old version. */ |
|
7568 #if (PY_VERSION_HEX < 0x03000000) |
|
7569 DL_EXPORT(void) init_pybsddb(void) |
|
7570 #else |
|
7571 PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */ |
|
7572 #endif |
|
7573 { |
|
7574 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN); |
|
7575 #if (PY_VERSION_HEX < 0x03000000) |
|
7576 init_bsddb(); |
|
7577 #else |
|
7578 return PyInit__bsddb(); /* Note the two underscores */ |
|
7579 #endif |
|
7580 } |
|
7581 |