14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#---------------------------------------------------------------------- 24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA 34adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# and Andrew Kuchling. All rights reserved. 44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Redistribution and use in source and binary forms, with or without 64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# modification, are permitted provided that the following conditions are 74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# met: 84adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# o Redistributions of source code must retain the above copyright 104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# notice, this list of conditions, and the disclaimer that follows. 114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# o Redistributions in binary form must reproduce the above copyright 134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# notice, this list of conditions, and the following disclaimer in 144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# the documentation and/or other materials provided with the 154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# distribution. 164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# o Neither the name of Digital Creations nor the names of its 184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# contributors may be used to endorse or promote products derived 194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# from this software without specific prior written permission. 204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS 224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL 254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# DAMAGE. 334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#---------------------------------------------------------------------- 344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao"""Support for Berkeley DB 4.3 through 5.3 with a simple interface. 374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 384adfde8bc82dd39f59e0445588c3e599ada477dJosh GaoFor the full featured object oriented interface use the bsddb.db module 394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoinstead. It mirrors the Oracle Berkeley DB C API. 404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao""" 414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport sys 434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoabsolute_import = (sys.version_info[0] >= 3) 444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoif (sys.version_info >= (2, 6)) and (sys.version_info < (3, 0)) : 464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao import warnings 474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if sys.py3kwarning and (__name__ != 'bsddb3') : 484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao warnings.warnpy3k("in 3.x, the bsddb module has been removed; " 494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "please use the pybsddb project instead", 504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao DeprecationWarning, 2) 514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao warnings.filterwarnings("ignore", ".*CObject.*", DeprecationWarning, 524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao "bsddb.__init__") 534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaotry: 554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if __name__ == 'bsddb3': 564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # import _pybsddb binary as it should be the more recent version from 574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # a standalone pybsddb addon package than the version included with 584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # python as bsddb._bsddb. 594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if absolute_import : 604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Because this syntaxis is not valid before Python 2.5 614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao exec("from . import _pybsddb") 624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else : 634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao import _pybsddb 644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _bsddb = _pybsddb 654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao from bsddb3.dbutils import DeadlockWrap as _DeadlockWrap 664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao import _bsddb 684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao from bsddb.dbutils import DeadlockWrap as _DeadlockWrap 694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoexcept ImportError: 704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Remove ourselves from sys.modules 714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao import sys 724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao del sys.modules[__name__] 734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise 744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# bsddb3 calls it db, but provide _db for backwards compatibility 764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodb = _db = _bsddb 774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao__version__ = db.__version__ 784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoerror = db.DBError # So bsddb.error will mean something... 804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#---------------------------------------------------------------------- 824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport sys, os 844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom weakref import ref 864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoif sys.version_info < (2, 6) : 884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao import UserDict 894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao MutableMapping = UserDict.DictMixin 904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoelse : 914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao import collections 924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao MutableMapping = collections.MutableMapping 934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass _iter_mixin(MutableMapping): 954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def _make_iter_cursor(self): 964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao cur = _DeadlockWrap(self.db.cursor) 974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao key = id(cur) 984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._cursor_refs[key] = ref(cur, self._gen_cref_cleaner(key)) 994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return cur 1004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def _gen_cref_cleaner(self, key): 1024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # use generate the function for the weakref callback here 1034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # to ensure that we do not hold a strict reference to cur 1044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # in the callback. 1054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return lambda ref: self._cursor_refs.pop(key, None) 1064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __iter__(self): 1084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._kill_iteration = False 1094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._in_iter += 1 1104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao cur = self._make_iter_cursor() 1134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # FIXME-20031102-greg: race condition. cursor could 1154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # be closed by another thread before this call. 1164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # since we're only returning keys, we call the cursor 1184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # methods with flags=0, dlen=0, dofs=0 1194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao key = _DeadlockWrap(cur.first, 0,0,0)[0] 1204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao yield key 1214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao next = getattr(cur, "next") 1234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao while 1: 1244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao key = _DeadlockWrap(next, 0,0,0)[0] 1264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao yield key 1274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except _bsddb.DBCursorClosedError: 1284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self._kill_iteration: 1294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise RuntimeError('Database changed size ' 1304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'during iteration.') 1314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao cur = self._make_iter_cursor() 1324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # FIXME-20031101-greg: race condition. cursor could 1334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # be closed by another thread before this call. 1344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _DeadlockWrap(cur.set, key,0,0,0) 1354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao next = getattr(cur, "next") 1364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except _bsddb.DBNotFoundError: 1374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 1384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except _bsddb.DBCursorClosedError: 1394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # the database was modified during iteration. abort. 1404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 1414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# When Python 2.4 not supported in bsddb3, we can change this to "finally" 1424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except : 1434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._in_iter -= 1 1444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise 1454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._in_iter -= 1 1474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def iteritems(self): 1494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if not self.db: 1504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 1514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._kill_iteration = False 1524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._in_iter += 1 1534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao cur = self._make_iter_cursor() 1564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # FIXME-20031102-greg: race condition. cursor could 1584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # be closed by another thread before this call. 1594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao kv = _DeadlockWrap(cur.first) 1614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao key = kv[0] 1624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao yield kv 1634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao next = getattr(cur, "next") 1654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao while 1: 1664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao kv = _DeadlockWrap(next) 1684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao key = kv[0] 1694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao yield kv 1704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except _bsddb.DBCursorClosedError: 1714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self._kill_iteration: 1724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise RuntimeError('Database changed size ' 1734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'during iteration.') 1744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao cur = self._make_iter_cursor() 1754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # FIXME-20031101-greg: race condition. cursor could 1764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # be closed by another thread before this call. 1774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _DeadlockWrap(cur.set, key,0,0,0) 1784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao next = getattr(cur, "next") 1794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except _bsddb.DBNotFoundError: 1804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 1814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except _bsddb.DBCursorClosedError: 1824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # the database was modified during iteration. abort. 1834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 1844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# When Python 2.4 not supported in bsddb3, we can change this to "finally" 1854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except : 1864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._in_iter -= 1 1874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise 1884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._in_iter -= 1 1904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass _DBWithCursor(_iter_mixin): 1934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """ 1944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao A simple wrapper around DB that makes it look like the bsddbobject in 1954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao the old module. It uses a cursor as needed to provide DB traversal. 1964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """ 1974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, db): 1984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.db = db 1994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.db.set_get_returns_none(0) 2004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # FIXME-20031101-greg: I believe there is still the potential 2024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # for deadlocks in a multithreaded environment if someone 2034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # attempts to use the any of the cursor interfaces in one 2044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # thread while doing a put or delete in another thread. The 2054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # reason is that _checkCursor and _closeCursors are not atomic 2064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # operations. Doing our own locking around self.dbc, 2074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # self.saved_dbc_key and self._cursor_refs could prevent this. 2084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # TODO: A test case demonstrating the problem needs to be written. 2094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # self.dbc is a DBCursor object used to implement the 2114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # first/next/previous/last/set_location methods. 2124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.dbc = None 2134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.saved_dbc_key = None 2144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # a collection of all DBCursor objects currently allocated 2164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # by the _iter_mixin interface. 2174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._cursor_refs = {} 2184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._in_iter = 0 2194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._kill_iteration = False 2204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __del__(self): 2224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.close() 2234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def _checkCursor(self): 2254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self.dbc is None: 2264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.dbc = _DeadlockWrap(self.db.cursor) 2274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self.saved_dbc_key is not None: 2284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _DeadlockWrap(self.dbc.set, self.saved_dbc_key) 2294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.saved_dbc_key = None 2304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # This method is needed for all non-cursor DB calls to avoid 2324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Berkeley DB deadlocks (due to being opened with DB_INIT_LOCK 2334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # and DB_THREAD to be thread safe) when intermixing database 2344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # operations that use the cursor internally with those that don't. 2354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def _closeCursors(self, save=1): 2364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self.dbc: 2374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao c = self.dbc 2384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.dbc = None 2394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if save: 2404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 2414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.saved_dbc_key = _DeadlockWrap(c.current, 0,0,0)[0] 2424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except db.DBError: 2434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 2444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _DeadlockWrap(c.close) 2454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao del c 2464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for cref in self._cursor_refs.values(): 2474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao c = cref() 2484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if c is not None: 2494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _DeadlockWrap(c.close) 2504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def _checkOpen(self): 2524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self.db is None: 2534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise error, "BSDDB object has already been closed" 2544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def isOpen(self): 2564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self.db is not None 2574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __len__(self): 2594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 2604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return _DeadlockWrap(lambda: len(self.db)) # len(self.db) 2614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if sys.version_info >= (2, 6) : 2634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __repr__(self) : 2644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self.isOpen() : 2654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return repr(dict(_DeadlockWrap(self.db.items))) 2664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return repr(dict()) 2674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __getitem__(self, key): 2694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 2704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return _DeadlockWrap(lambda: self.db[key]) # self.db[key] 2714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __setitem__(self, key, value): 2734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 2744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._closeCursors() 2754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self._in_iter and key not in self: 2764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._kill_iteration = True 2774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def wrapF(): 2784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.db[key] = value 2794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _DeadlockWrap(wrapF) # self.db[key] = value 2804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __delitem__(self, key): 2824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 2834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._closeCursors() 2844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self._in_iter and key in self: 2854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._kill_iteration = True 2864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def wrapF(): 2874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao del self.db[key] 2884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _DeadlockWrap(wrapF) # del self.db[key] 2894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def close(self): 2914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._closeCursors(save=0) 2924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self.dbc is not None: 2934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _DeadlockWrap(self.dbc.close) 2944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao v = 0 2954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self.db is not None: 2964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao v = _DeadlockWrap(self.db.close) 2974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.dbc = None 2984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.db = None 2994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return v 3004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def keys(self): 3024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 3034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return _DeadlockWrap(self.db.keys) 3044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def has_key(self, key): 3064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 3074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return _DeadlockWrap(self.db.has_key, key) 3084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_location(self, key): 3104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 3114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkCursor() 3124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return _DeadlockWrap(self.dbc.set_range, key) 3134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def next(self): # Renamed by "2to3" 3154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 3164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkCursor() 3174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao rv = _DeadlockWrap(getattr(self.dbc, "next")) 3184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return rv 3194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if sys.version_info[0] >= 3 : # For "2to3" conversion 3214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao next = __next__ 3224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def previous(self): 3244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 3254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkCursor() 3264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao rv = _DeadlockWrap(self.dbc.prev) 3274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return rv 3284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def first(self): 3304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 3314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # fix 1725856: don't needlessly try to restore our cursor position 3324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.saved_dbc_key = None 3334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkCursor() 3344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao rv = _DeadlockWrap(self.dbc.first) 3354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return rv 3364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def last(self): 3384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 3394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # fix 1725856: don't needlessly try to restore our cursor position 3404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.saved_dbc_key = None 3414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkCursor() 3424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao rv = _DeadlockWrap(self.dbc.last) 3434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return rv 3444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def sync(self): 3464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self._checkOpen() 3474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return _DeadlockWrap(self.db.sync) 3484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#---------------------------------------------------------------------- 3514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Compatibility object factory functions 3524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef hashopen(file, flag='c', mode=0666, pgsize=None, ffactor=None, nelem=None, 3544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao cachesize=None, lorder=None, hflags=0): 3554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao flags = _checkflag(flag, file) 3574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao e = _openDBEnv(cachesize) 3584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao d = db.DB(e) 3594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao d.set_flags(hflags) 3604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if pgsize is not None: d.set_pagesize(pgsize) 3614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if lorder is not None: d.set_lorder(lorder) 3624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if ffactor is not None: d.set_h_ffactor(ffactor) 3634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if nelem is not None: d.set_h_nelem(nelem) 3644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao d.open(file, db.DB_HASH, flags, mode) 3654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return _DBWithCursor(d) 3664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#---------------------------------------------------------------------- 3684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef btopen(file, flag='c', mode=0666, 3704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao btflags=0, cachesize=None, maxkeypage=None, minkeypage=None, 3714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pgsize=None, lorder=None): 3724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao flags = _checkflag(flag, file) 3744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao e = _openDBEnv(cachesize) 3754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao d = db.DB(e) 3764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if pgsize is not None: d.set_pagesize(pgsize) 3774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if lorder is not None: d.set_lorder(lorder) 3784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao d.set_flags(btflags) 3794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if minkeypage is not None: d.set_bt_minkey(minkeypage) 3804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if maxkeypage is not None: d.set_bt_maxkey(maxkeypage) 3814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao d.open(file, db.DB_BTREE, flags, mode) 3824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return _DBWithCursor(d) 3834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#---------------------------------------------------------------------- 3854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef rnopen(file, flag='c', mode=0666, 3884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao rnflags=0, cachesize=None, pgsize=None, lorder=None, 3894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao rlen=None, delim=None, source=None, pad=None): 3904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao flags = _checkflag(flag, file) 3924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao e = _openDBEnv(cachesize) 3934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao d = db.DB(e) 3944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if pgsize is not None: d.set_pagesize(pgsize) 3954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if lorder is not None: d.set_lorder(lorder) 3964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao d.set_flags(rnflags) 3974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if delim is not None: d.set_re_delim(delim) 3984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if rlen is not None: d.set_re_len(rlen) 3994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if source is not None: d.set_re_source(source) 4004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if pad is not None: d.set_re_pad(pad) 4014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao d.open(file, db.DB_RECNO, flags, mode) 4024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return _DBWithCursor(d) 4034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 4044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#---------------------------------------------------------------------- 4054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 4064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef _openDBEnv(cachesize): 4074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao e = db.DBEnv() 4084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if cachesize is not None: 4094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if cachesize >= 20480: 4104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao e.set_cachesize(0, cachesize) 4114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 4124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise error, "cachesize must be >= 20480" 4134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao e.set_lk_detect(db.DB_LOCK_DEFAULT) 4144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao e.open('.', db.DB_PRIVATE | db.DB_CREATE | db.DB_THREAD | db.DB_INIT_LOCK | db.DB_INIT_MPOOL) 4154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return e 4164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 4174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef _checkflag(flag, file): 4184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if flag == 'r': 4194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao flags = db.DB_RDONLY 4204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif flag == 'rw': 4214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao flags = 0 4224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif flag == 'w': 4234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao flags = db.DB_CREATE 4244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif flag == 'c': 4254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao flags = db.DB_CREATE 4264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif flag == 'n': 4274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao flags = db.DB_CREATE 4284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao #flags = db.DB_CREATE | db.DB_TRUNCATE 4294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # we used db.DB_TRUNCATE flag for this before but Berkeley DB 4304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # 4.2.52 changed to disallowed truncate with txn environments. 4314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if file is not None and os.path.isfile(file): 4324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao os.unlink(file) 4334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 4344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise error, "flags should be one of 'r', 'w', 'c' or 'n'" 4354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return flags | db.DB_THREAD 4364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 4374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#---------------------------------------------------------------------- 4384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 4394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 4404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# This is a silly little hack that allows apps to continue to use the 4414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# DB_THREAD flag even on systems without threads without freaking out 4424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Berkeley DB. 4434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# 4444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# This assumes that if Python was built with thread support then 4454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# Berkeley DB was too. 4464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 4474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaotry: 4484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # 2to3 automatically changes "import thread" to "import _thread" 4494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao import thread as T 4504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao del T 4514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 4524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoexcept ImportError: 4534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao db.DB_THREAD = 0 4544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 4554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao#---------------------------------------------------------------------- 456