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