| 1 | n/a | #---------------------------------------------------------------------- |
|---|
| 2 | n/a | # Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA |
|---|
| 3 | n/a | # and Andrew Kuchling. All rights reserved. |
|---|
| 4 | n/a | # |
|---|
| 5 | n/a | # Redistribution and use in source and binary forms, with or without |
|---|
| 6 | n/a | # modification, are permitted provided that the following conditions are |
|---|
| 7 | n/a | # met: |
|---|
| 8 | n/a | # |
|---|
| 9 | n/a | # o Redistributions of source code must retain the above copyright |
|---|
| 10 | n/a | # notice, this list of conditions, and the disclaimer that follows. |
|---|
| 11 | n/a | # |
|---|
| 12 | n/a | # o Redistributions in binary form must reproduce the above copyright |
|---|
| 13 | n/a | # notice, this list of conditions, and the following disclaimer in |
|---|
| 14 | n/a | # the documentation and/or other materials provided with the |
|---|
| 15 | n/a | # distribution. |
|---|
| 16 | n/a | # |
|---|
| 17 | n/a | # o Neither the name of Digital Creations nor the names of its |
|---|
| 18 | n/a | # contributors may be used to endorse or promote products derived |
|---|
| 19 | n/a | # from this software without specific prior written permission. |
|---|
| 20 | n/a | # |
|---|
| 21 | n/a | # THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS |
|---|
| 22 | n/a | # IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
|---|
| 23 | n/a | # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
|---|
| 24 | n/a | # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL |
|---|
| 25 | n/a | # CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
|---|
| 26 | n/a | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|---|
| 27 | n/a | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
|---|
| 28 | n/a | # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|---|
| 29 | n/a | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
|---|
| 30 | n/a | # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
|---|
| 31 | n/a | # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
|---|
| 32 | n/a | # DAMAGE. |
|---|
| 33 | n/a | #---------------------------------------------------------------------- |
|---|
| 34 | n/a | |
|---|
| 35 | n/a | |
|---|
| 36 | n/a | """Support for Berkeley DB 4.1 through 4.8 with a simple interface. |
|---|
| 37 | n/a | |
|---|
| 38 | n/a | For the full featured object oriented interface use the bsddb.db module |
|---|
| 39 | n/a | instead. It mirrors the Oracle Berkeley DB C API. |
|---|
| 40 | 1 | """ |
|---|
| 41 | n/a | |
|---|
| 42 | 1 | import sys |
|---|
| 43 | 1 | absolute_import = (sys.version_info[0] >= 3) |
|---|
| 44 | n/a | |
|---|
| 45 | 1 | if (sys.version_info >= (2, 6)) and (sys.version_info < (3, 0)) : |
|---|
| 46 | 1 | import warnings |
|---|
| 47 | 1 | if sys.py3kwarning and (__name__ != 'bsddb3') : |
|---|
| 48 | 0 | warnings.warnpy3k("in 3.x, the bsddb module has been removed; " |
|---|
| 49 | n/a | "please use the pybsddb project instead", |
|---|
| 50 | 0 | DeprecationWarning, 2) |
|---|
| 51 | 1 | warnings.filterwarnings("ignore", ".*CObject.*", DeprecationWarning, |
|---|
| 52 | 1 | "bsddb.__init__") |
|---|
| 53 | n/a | |
|---|
| 54 | 1 | try: |
|---|
| 55 | 1 | if __name__ == 'bsddb3': |
|---|
| 56 | n/a | # import _pybsddb binary as it should be the more recent version from |
|---|
| 57 | n/a | # a standalone pybsddb addon package than the version included with |
|---|
| 58 | n/a | # python as bsddb._bsddb. |
|---|
| 59 | 0 | if absolute_import : |
|---|
| 60 | n/a | # Because this syntaxis is not valid before Python 2.5 |
|---|
| 61 | 0 | exec("from . import _pybsddb") |
|---|
| 62 | n/a | else : |
|---|
| 63 | 0 | import _pybsddb |
|---|
| 64 | 0 | _bsddb = _pybsddb |
|---|
| 65 | 0 | from bsddb3.dbutils import DeadlockWrap as _DeadlockWrap |
|---|
| 66 | n/a | else: |
|---|
| 67 | 1 | import _bsddb |
|---|
| 68 | 1 | from bsddb.dbutils import DeadlockWrap as _DeadlockWrap |
|---|
| 69 | 0 | except ImportError: |
|---|
| 70 | n/a | # Remove ourselves from sys.modules |
|---|
| 71 | 0 | import sys |
|---|
| 72 | 0 | del sys.modules[__name__] |
|---|
| 73 | 0 | raise |
|---|
| 74 | n/a | |
|---|
| 75 | n/a | # bsddb3 calls it db, but provide _db for backwards compatibility |
|---|
| 76 | 1 | db = _db = _bsddb |
|---|
| 77 | 1 | __version__ = db.__version__ |
|---|
| 78 | n/a | |
|---|
| 79 | 1 | error = db.DBError # So bsddb.error will mean something... |
|---|
| 80 | n/a | |
|---|
| 81 | n/a | #---------------------------------------------------------------------- |
|---|
| 82 | n/a | |
|---|
| 83 | 1 | import sys, os |
|---|
| 84 | n/a | |
|---|
| 85 | 1 | from weakref import ref |
|---|
| 86 | n/a | |
|---|
| 87 | 1 | if sys.version_info < (2, 6) : |
|---|
| 88 | 0 | import UserDict |
|---|
| 89 | 0 | MutableMapping = UserDict.DictMixin |
|---|
| 90 | n/a | else : |
|---|
| 91 | 1 | import collections |
|---|
| 92 | 1 | MutableMapping = collections.MutableMapping |
|---|
| 93 | n/a | |
|---|
| 94 | 2 | class _iter_mixin(MutableMapping): |
|---|
| 95 | 1 | def _make_iter_cursor(self): |
|---|
| 96 | 283 | cur = _DeadlockWrap(self.db.cursor) |
|---|
| 97 | 283 | key = id(cur) |
|---|
| 98 | 283 | self._cursor_refs[key] = ref(cur, self._gen_cref_cleaner(key)) |
|---|
| 99 | 283 | return cur |
|---|
| 100 | n/a | |
|---|
| 101 | 1 | def _gen_cref_cleaner(self, key): |
|---|
| 102 | n/a | # use generate the function for the weakref callback here |
|---|
| 103 | n/a | # to ensure that we do not hold a strict reference to cur |
|---|
| 104 | n/a | # in the callback. |
|---|
| 105 | 561 | return lambda ref: self._cursor_refs.pop(key, None) |
|---|
| 106 | n/a | |
|---|
| 107 | 1 | def __iter__(self): |
|---|
| 108 | 153 | self._kill_iteration = False |
|---|
| 109 | 153 | self._in_iter += 1 |
|---|
| 110 | 153 | try: |
|---|
| 111 | 153 | try: |
|---|
| 112 | 153 | cur = self._make_iter_cursor() |
|---|
| 113 | n/a | |
|---|
| 114 | n/a | # FIXME-20031102-greg: race condition. cursor could |
|---|
| 115 | n/a | # be closed by another thread before this call. |
|---|
| 116 | n/a | |
|---|
| 117 | n/a | # since we're only returning keys, we call the cursor |
|---|
| 118 | n/a | # methods with flags=0, dlen=0, dofs=0 |
|---|
| 119 | 153 | key = _DeadlockWrap(cur.first, 0,0,0)[0] |
|---|
| 120 | 138 | yield key |
|---|
| 121 | n/a | |
|---|
| 122 | 103 | next = getattr(cur, "next") |
|---|
| 123 | 103 | while 1: |
|---|
| 124 | 648 | try: |
|---|
| 125 | 648 | key = _DeadlockWrap(next, 0,0,0)[0] |
|---|
| 126 | 485 | yield key |
|---|
| 127 | 163 | except _bsddb.DBCursorClosedError: |
|---|
| 128 | 65 | if self._kill_iteration: |
|---|
| 129 | 5 | raise RuntimeError('Database changed size ' |
|---|
| 130 | n/a | 'during iteration.') |
|---|
| 131 | 60 | cur = self._make_iter_cursor() |
|---|
| 132 | n/a | # FIXME-20031101-greg: race condition. cursor could |
|---|
| 133 | n/a | # be closed by another thread before this call. |
|---|
| 134 | 60 | _DeadlockWrap(cur.set, key,0,0,0) |
|---|
| 135 | 60 | next = getattr(cur, "next") |
|---|
| 136 | 153 | except _bsddb.DBNotFoundError: |
|---|
| 137 | 113 | pass |
|---|
| 138 | 40 | except _bsddb.DBCursorClosedError: |
|---|
| 139 | n/a | # the database was modified during iteration. abort. |
|---|
| 140 | 0 | pass |
|---|
| 141 | n/a | # When Python 2.3 not supported in bsddb3, we can change this to "finally" |
|---|
| 142 | 40 | except : |
|---|
| 143 | 40 | self._in_iter -= 1 |
|---|
| 144 | 40 | raise |
|---|
| 145 | n/a | |
|---|
| 146 | 113 | self._in_iter -= 1 |
|---|
| 147 | n/a | |
|---|
| 148 | 1 | def iteritems(self): |
|---|
| 149 | 35 | if not self.db: |
|---|
| 150 | 0 | return |
|---|
| 151 | 35 | self._kill_iteration = False |
|---|
| 152 | 35 | self._in_iter += 1 |
|---|
| 153 | 35 | try: |
|---|
| 154 | 35 | try: |
|---|
| 155 | 35 | cur = self._make_iter_cursor() |
|---|
| 156 | n/a | |
|---|
| 157 | n/a | # FIXME-20031102-greg: race condition. cursor could |
|---|
| 158 | n/a | # be closed by another thread before this call. |
|---|
| 159 | n/a | |
|---|
| 160 | 35 | kv = _DeadlockWrap(cur.first) |
|---|
| 161 | 35 | key = kv[0] |
|---|
| 162 | 35 | yield kv |
|---|
| 163 | n/a | |
|---|
| 164 | 30 | next = getattr(cur, "next") |
|---|
| 165 | 30 | while 1: |
|---|
| 166 | 190 | try: |
|---|
| 167 | 190 | kv = _DeadlockWrap(next) |
|---|
| 168 | 125 | key = kv[0] |
|---|
| 169 | 125 | yield kv |
|---|
| 170 | 65 | except _bsddb.DBCursorClosedError: |
|---|
| 171 | 40 | if self._kill_iteration: |
|---|
| 172 | 5 | raise RuntimeError('Database changed size ' |
|---|
| 173 | n/a | 'during iteration.') |
|---|
| 174 | 35 | cur = self._make_iter_cursor() |
|---|
| 175 | n/a | # FIXME-20031101-greg: race condition. cursor could |
|---|
| 176 | n/a | # be closed by another thread before this call. |
|---|
| 177 | 35 | _DeadlockWrap(cur.set, key,0,0,0) |
|---|
| 178 | 35 | next = getattr(cur, "next") |
|---|
| 179 | 30 | except _bsddb.DBNotFoundError: |
|---|
| 180 | 25 | pass |
|---|
| 181 | 5 | except _bsddb.DBCursorClosedError: |
|---|
| 182 | n/a | # the database was modified during iteration. abort. |
|---|
| 183 | 0 | pass |
|---|
| 184 | n/a | # When Python 2.3 not supported in bsddb3, we can change this to "finally" |
|---|
| 185 | 5 | except : |
|---|
| 186 | 5 | self._in_iter -= 1 |
|---|
| 187 | 5 | raise |
|---|
| 188 | n/a | |
|---|
| 189 | 25 | self._in_iter -= 1 |
|---|
| 190 | n/a | |
|---|
| 191 | n/a | |
|---|
| 192 | 2 | class _DBWithCursor(_iter_mixin): |
|---|
| 193 | n/a | """ |
|---|
| 194 | n/a | A simple wrapper around DB that makes it look like the bsddbobject in |
|---|
| 195 | n/a | the old module. It uses a cursor as needed to provide DB traversal. |
|---|
| 196 | 1 | """ |
|---|
| 197 | 1 | def __init__(self, db): |
|---|
| 198 | 217 | self.db = db |
|---|
| 199 | 217 | self.db.set_get_returns_none(0) |
|---|
| 200 | n/a | |
|---|
| 201 | n/a | # FIXME-20031101-greg: I believe there is still the potential |
|---|
| 202 | n/a | # for deadlocks in a multithreaded environment if someone |
|---|
| 203 | n/a | # attempts to use the any of the cursor interfaces in one |
|---|
| 204 | n/a | # thread while doing a put or delete in another thread. The |
|---|
| 205 | n/a | # reason is that _checkCursor and _closeCursors are not atomic |
|---|
| 206 | n/a | # operations. Doing our own locking around self.dbc, |
|---|
| 207 | n/a | # self.saved_dbc_key and self._cursor_refs could prevent this. |
|---|
| 208 | n/a | # TODO: A test case demonstrating the problem needs to be written. |
|---|
| 209 | n/a | |
|---|
| 210 | n/a | # self.dbc is a DBCursor object used to implement the |
|---|
| 211 | n/a | # first/next/previous/last/set_location methods. |
|---|
| 212 | 217 | self.dbc = None |
|---|
| 213 | 217 | self.saved_dbc_key = None |
|---|
| 214 | n/a | |
|---|
| 215 | n/a | # a collection of all DBCursor objects currently allocated |
|---|
| 216 | n/a | # by the _iter_mixin interface. |
|---|
| 217 | 217 | self._cursor_refs = {} |
|---|
| 218 | 217 | self._in_iter = 0 |
|---|
| 219 | 217 | self._kill_iteration = False |
|---|
| 220 | n/a | |
|---|
| 221 | 1 | def __del__(self): |
|---|
| 222 | 216 | self.close() |
|---|
| 223 | n/a | |
|---|
| 224 | 1 | def _checkCursor(self): |
|---|
| 225 | 152 | if self.dbc is None: |
|---|
| 226 | 88 | self.dbc = _DeadlockWrap(self.db.cursor) |
|---|
| 227 | 88 | if self.saved_dbc_key is not None: |
|---|
| 228 | 0 | _DeadlockWrap(self.dbc.set, self.saved_dbc_key) |
|---|
| 229 | 0 | self.saved_dbc_key = None |
|---|
| 230 | n/a | |
|---|
| 231 | n/a | # This method is needed for all non-cursor DB calls to avoid |
|---|
| 232 | n/a | # Berkeley DB deadlocks (due to being opened with DB_INIT_LOCK |
|---|
| 233 | n/a | # and DB_THREAD to be thread safe) when intermixing database |
|---|
| 234 | n/a | # operations that use the cursor internally with those that don't. |
|---|
| 235 | 1 | def _closeCursors(self, save=1): |
|---|
| 236 | 1534 | if self.dbc: |
|---|
| 237 | 88 | c = self.dbc |
|---|
| 238 | 88 | self.dbc = None |
|---|
| 239 | 88 | if save: |
|---|
| 240 | 70 | try: |
|---|
| 241 | 70 | self.saved_dbc_key = _DeadlockWrap(c.current, 0,0,0)[0] |
|---|
| 242 | 0 | except db.DBError: |
|---|
| 243 | 0 | pass |
|---|
| 244 | 88 | _DeadlockWrap(c.close) |
|---|
| 245 | 88 | del c |
|---|
| 246 | 1639 | for cref in self._cursor_refs.values(): |
|---|
| 247 | 105 | c = cref() |
|---|
| 248 | 105 | if c is not None: |
|---|
| 249 | 105 | _DeadlockWrap(c.close) |
|---|
| 250 | n/a | |
|---|
| 251 | 1 | def _checkOpen(self): |
|---|
| 252 | 2521 | if self.db is None: |
|---|
| 253 | 0 | raise error, "BSDDB object has already been closed" |
|---|
| 254 | n/a | |
|---|
| 255 | 1 | def isOpen(self): |
|---|
| 256 | 0 | return self.db is not None |
|---|
| 257 | n/a | |
|---|
| 258 | 1 | def __len__(self): |
|---|
| 259 | 67 | self._checkOpen() |
|---|
| 260 | 134 | return _DeadlockWrap(lambda: len(self.db)) # len(self.db) |
|---|
| 261 | n/a | |
|---|
| 262 | 1 | if sys.version_info >= (2, 6) : |
|---|
| 263 | 1 | def __repr__(self) : |
|---|
| 264 | 0 | if self.isOpen() : |
|---|
| 265 | 0 | return repr(dict(_DeadlockWrap(self.db.items))) |
|---|
| 266 | 0 | return repr(dict()) |
|---|
| 267 | n/a | |
|---|
| 268 | 1 | def __getitem__(self, key): |
|---|
| 269 | 833 | self._checkOpen() |
|---|
| 270 | 1666 | return _DeadlockWrap(lambda: self.db[key]) # self.db[key] |
|---|
| 271 | n/a | |
|---|
| 272 | 1 | def __setitem__(self, key, value): |
|---|
| 273 | 975 | self._checkOpen() |
|---|
| 274 | 975 | self._closeCursors() |
|---|
| 275 | 975 | if self._in_iter and key not in self: |
|---|
| 276 | 5 | self._kill_iteration = True |
|---|
| 277 | 975 | def wrapF(): |
|---|
| 278 | 975 | self.db[key] = value |
|---|
| 279 | 975 | _DeadlockWrap(wrapF) # self.db[key] = value |
|---|
| 280 | n/a | |
|---|
| 281 | 1 | def __delitem__(self, key): |
|---|
| 282 | 126 | self._checkOpen() |
|---|
| 283 | 126 | self._closeCursors() |
|---|
| 284 | 126 | if self._in_iter and key in self: |
|---|
| 285 | 5 | self._kill_iteration = True |
|---|
| 286 | 126 | def wrapF(): |
|---|
| 287 | 126 | del self.db[key] |
|---|
| 288 | 126 | _DeadlockWrap(wrapF) # del self.db[key] |
|---|
| 289 | n/a | |
|---|
| 290 | 1 | def close(self): |
|---|
| 291 | 433 | self._closeCursors(save=0) |
|---|
| 292 | 433 | if self.dbc is not None: |
|---|
| 293 | 0 | _DeadlockWrap(self.dbc.close) |
|---|
| 294 | 433 | v = 0 |
|---|
| 295 | 433 | if self.db is not None: |
|---|
| 296 | 217 | v = _DeadlockWrap(self.db.close) |
|---|
| 297 | 433 | self.dbc = None |
|---|
| 298 | 433 | self.db = None |
|---|
| 299 | 433 | return v |
|---|
| 300 | n/a | |
|---|
| 301 | 1 | def keys(self): |
|---|
| 302 | 127 | self._checkOpen() |
|---|
| 303 | 127 | return _DeadlockWrap(self.db.keys) |
|---|
| 304 | n/a | |
|---|
| 305 | 1 | def has_key(self, key): |
|---|
| 306 | 35 | self._checkOpen() |
|---|
| 307 | 35 | return _DeadlockWrap(self.db.has_key, key) |
|---|
| 308 | n/a | |
|---|
| 309 | 1 | def set_location(self, key): |
|---|
| 310 | 5 | self._checkOpen() |
|---|
| 311 | 5 | self._checkCursor() |
|---|
| 312 | 5 | return _DeadlockWrap(self.dbc.set_range, key) |
|---|
| 313 | n/a | |
|---|
| 314 | 1 | def next(self): # Renamed by "2to3" |
|---|
| 315 | 33 | self._checkOpen() |
|---|
| 316 | 33 | self._checkCursor() |
|---|
| 317 | 33 | rv = _DeadlockWrap(getattr(self.dbc, "next")) |
|---|
| 318 | 33 | return rv |
|---|
| 319 | n/a | |
|---|
| 320 | 1 | if sys.version_info[0] >= 3 : # For "2to3" conversion |
|---|
| 321 | 0 | next = __next__ |
|---|
| 322 | n/a | |
|---|
| 323 | 1 | def previous(self): |
|---|
| 324 | 28 | self._checkOpen() |
|---|
| 325 | 28 | self._checkCursor() |
|---|
| 326 | 28 | rv = _DeadlockWrap(self.dbc.prev) |
|---|
| 327 | 28 | return rv |
|---|
| 328 | n/a | |
|---|
| 329 | 1 | def first(self): |
|---|
| 330 | 48 | self._checkOpen() |
|---|
| 331 | n/a | # fix 1725856: don't needlessly try to restore our cursor position |
|---|
| 332 | 48 | self.saved_dbc_key = None |
|---|
| 333 | 48 | self._checkCursor() |
|---|
| 334 | 48 | rv = _DeadlockWrap(self.dbc.first) |
|---|
| 335 | 48 | return rv |
|---|
| 336 | n/a | |
|---|
| 337 | 1 | def last(self): |
|---|
| 338 | 38 | self._checkOpen() |
|---|
| 339 | n/a | # fix 1725856: don't needlessly try to restore our cursor position |
|---|
| 340 | 38 | self.saved_dbc_key = None |
|---|
| 341 | 38 | self._checkCursor() |
|---|
| 342 | 38 | rv = _DeadlockWrap(self.dbc.last) |
|---|
| 343 | 38 | return rv |
|---|
| 344 | n/a | |
|---|
| 345 | 1 | def sync(self): |
|---|
| 346 | 206 | self._checkOpen() |
|---|
| 347 | 206 | return _DeadlockWrap(self.db.sync) |
|---|
| 348 | n/a | |
|---|
| 349 | n/a | |
|---|
| 350 | n/a | #---------------------------------------------------------------------- |
|---|
| 351 | n/a | # Compatibility object factory functions |
|---|
| 352 | n/a | |
|---|
| 353 | 1 | def hashopen(file, flag='c', mode=0666, pgsize=None, ffactor=None, nelem=None, |
|---|
| 354 | 1 | cachesize=None, lorder=None, hflags=0): |
|---|
| 355 | n/a | |
|---|
| 356 | 141 | flags = _checkflag(flag, file) |
|---|
| 357 | 141 | e = _openDBEnv(cachesize) |
|---|
| 358 | 141 | d = db.DB(e) |
|---|
| 359 | 141 | d.set_flags(hflags) |
|---|
| 360 | 141 | if pgsize is not None: d.set_pagesize(pgsize) |
|---|
| 361 | 141 | if lorder is not None: d.set_lorder(lorder) |
|---|
| 362 | 141 | if ffactor is not None: d.set_h_ffactor(ffactor) |
|---|
| 363 | 141 | if nelem is not None: d.set_h_nelem(nelem) |
|---|
| 364 | 141 | d.open(file, db.DB_HASH, flags, mode) |
|---|
| 365 | 141 | return _DBWithCursor(d) |
|---|
| 366 | n/a | |
|---|
| 367 | n/a | #---------------------------------------------------------------------- |
|---|
| 368 | n/a | |
|---|
| 369 | 1 | def btopen(file, flag='c', mode=0666, |
|---|
| 370 | 1 | btflags=0, cachesize=None, maxkeypage=None, minkeypage=None, |
|---|
| 371 | 1 | pgsize=None, lorder=None): |
|---|
| 372 | n/a | |
|---|
| 373 | 76 | flags = _checkflag(flag, file) |
|---|
| 374 | 76 | e = _openDBEnv(cachesize) |
|---|
| 375 | 76 | d = db.DB(e) |
|---|
| 376 | 76 | if pgsize is not None: d.set_pagesize(pgsize) |
|---|
| 377 | 76 | if lorder is not None: d.set_lorder(lorder) |
|---|
| 378 | 76 | d.set_flags(btflags) |
|---|
| 379 | 76 | if minkeypage is not None: d.set_bt_minkey(minkeypage) |
|---|
| 380 | 76 | if maxkeypage is not None: d.set_bt_maxkey(maxkeypage) |
|---|
| 381 | 76 | d.open(file, db.DB_BTREE, flags, mode) |
|---|
| 382 | 76 | return _DBWithCursor(d) |
|---|
| 383 | n/a | |
|---|
| 384 | n/a | #---------------------------------------------------------------------- |
|---|
| 385 | n/a | |
|---|
| 386 | n/a | |
|---|
| 387 | 1 | def rnopen(file, flag='c', mode=0666, |
|---|
| 388 | 1 | rnflags=0, cachesize=None, pgsize=None, lorder=None, |
|---|
| 389 | 1 | rlen=None, delim=None, source=None, pad=None): |
|---|
| 390 | n/a | |
|---|
| 391 | 0 | flags = _checkflag(flag, file) |
|---|
| 392 | 0 | e = _openDBEnv(cachesize) |
|---|
| 393 | 0 | d = db.DB(e) |
|---|
| 394 | 0 | if pgsize is not None: d.set_pagesize(pgsize) |
|---|
| 395 | 0 | if lorder is not None: d.set_lorder(lorder) |
|---|
| 396 | 0 | d.set_flags(rnflags) |
|---|
| 397 | 0 | if delim is not None: d.set_re_delim(delim) |
|---|
| 398 | 0 | if rlen is not None: d.set_re_len(rlen) |
|---|
| 399 | 0 | if source is not None: d.set_re_source(source) |
|---|
| 400 | 0 | if pad is not None: d.set_re_pad(pad) |
|---|
| 401 | 0 | d.open(file, db.DB_RECNO, flags, mode) |
|---|
| 402 | 0 | return _DBWithCursor(d) |
|---|
| 403 | n/a | |
|---|
| 404 | n/a | #---------------------------------------------------------------------- |
|---|
| 405 | n/a | |
|---|
| 406 | 1 | def _openDBEnv(cachesize): |
|---|
| 407 | 217 | e = db.DBEnv() |
|---|
| 408 | 217 | if cachesize is not None: |
|---|
| 409 | 125 | if cachesize >= 20480: |
|---|
| 410 | 125 | e.set_cachesize(0, cachesize) |
|---|
| 411 | n/a | else: |
|---|
| 412 | 0 | raise error, "cachesize must be >= 20480" |
|---|
| 413 | 217 | e.set_lk_detect(db.DB_LOCK_DEFAULT) |
|---|
| 414 | 217 | e.open('.', db.DB_PRIVATE | db.DB_CREATE | db.DB_THREAD | db.DB_INIT_LOCK | db.DB_INIT_MPOOL) |
|---|
| 415 | 217 | return e |
|---|
| 416 | n/a | |
|---|
| 417 | 1 | def _checkflag(flag, file): |
|---|
| 418 | 217 | if flag == 'r': |
|---|
| 419 | 2 | flags = db.DB_RDONLY |
|---|
| 420 | 215 | elif flag == 'rw': |
|---|
| 421 | 0 | flags = 0 |
|---|
| 422 | 215 | elif flag == 'w': |
|---|
| 423 | 3 | flags = db.DB_CREATE |
|---|
| 424 | 212 | elif flag == 'c': |
|---|
| 425 | 184 | flags = db.DB_CREATE |
|---|
| 426 | 28 | elif flag == 'n': |
|---|
| 427 | 28 | flags = db.DB_CREATE |
|---|
| 428 | n/a | #flags = db.DB_CREATE | db.DB_TRUNCATE |
|---|
| 429 | n/a | # we used db.DB_TRUNCATE flag for this before but Berkeley DB |
|---|
| 430 | n/a | # 4.2.52 changed to disallowed truncate with txn environments. |
|---|
| 431 | 28 | if file is not None and os.path.isfile(file): |
|---|
| 432 | 0 | os.unlink(file) |
|---|
| 433 | n/a | else: |
|---|
| 434 | 0 | raise error, "flags should be one of 'r', 'w', 'c' or 'n'" |
|---|
| 435 | 217 | return flags | db.DB_THREAD |
|---|
| 436 | n/a | |
|---|
| 437 | n/a | #---------------------------------------------------------------------- |
|---|
| 438 | n/a | |
|---|
| 439 | n/a | |
|---|
| 440 | n/a | # This is a silly little hack that allows apps to continue to use the |
|---|
| 441 | n/a | # DB_THREAD flag even on systems without threads without freaking out |
|---|
| 442 | n/a | # Berkeley DB. |
|---|
| 443 | n/a | # |
|---|
| 444 | n/a | # This assumes that if Python was built with thread support then |
|---|
| 445 | n/a | # Berkeley DB was too. |
|---|
| 446 | n/a | |
|---|
| 447 | 1 | try: |
|---|
| 448 | n/a | # 2to3 automatically changes "import thread" to "import _thread" |
|---|
| 449 | 1 | import thread as T |
|---|
| 450 | 1 | del T |
|---|
| 451 | n/a | |
|---|
| 452 | 0 | except ImportError: |
|---|
| 453 | 0 | db.DB_THREAD = 0 |
|---|
| 454 | n/a | |
|---|
| 455 | n/a | #---------------------------------------------------------------------- |
|---|