PyXR

c:\python24\lib \ bsddb

Subpackages:

Modules

Init code



0001 #----------------------------------------------------------------------
0002 #  Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
0003 #  and Andrew Kuchling. All rights reserved.
0004 #
0005 #  Redistribution and use in source and binary forms, with or without
0006 #  modification, are permitted provided that the following conditions are
0007 #  met:
0008 #
0009 #    o Redistributions of source code must retain the above copyright
0010 #      notice, this list of conditions, and the disclaimer that follows.
0011 #
0012 #    o Redistributions in binary form must reproduce the above copyright
0013 #      notice, this list of conditions, and the following disclaimer in
0014 #      the documentation and/or other materials provided with the
0015 #      distribution.
0016 #
0017 #    o Neither the name of Digital Creations nor the names of its
0018 #      contributors may be used to endorse or promote products derived
0019 #      from this software without specific prior written permission.
0020 #
0021 #  THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
0022 #  IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
0023 #  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
0024 #  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL
0025 #  CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
0026 #  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
0027 #  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
0028 #  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0029 #  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
0030 #  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
0031 #  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
0032 #  DAMAGE.
0033 #----------------------------------------------------------------------
0034 
0035 
0036 """Support for BerkeleyDB 3.2 through 4.2.
0037 """
0038 
0039 try:
0040     if __name__ == 'bsddb3':
0041         # import _pybsddb binary as it should be the more recent version from
0042         # a standalone pybsddb addon package than the version included with
0043         # python as bsddb._bsddb.
0044         import _pybsddb
0045         _bsddb = _pybsddb
0046     else:
0047         import _bsddb
0048 except ImportError:
0049     # Remove ourselves from sys.modules
0050     import sys
0051     del sys.modules[__name__]
0052     raise
0053 
0054 # bsddb3 calls it db, but provide _db for backwards compatibility
0055 db = _db = _bsddb
0056 __version__ = db.__version__
0057 
0058 error = db.DBError  # So bsddb.error will mean something...
0059 
0060 #----------------------------------------------------------------------
0061 
0062 import sys, os
0063 
0064 # for backwards compatibility with python versions older than 2.3, the
0065 # iterator interface is dynamically defined and added using a mixin
0066 # class.  old python can't tokenize it due to the yield keyword.
0067 if sys.version >= '2.3':
0068     exec """
0069 import UserDict
0070 from weakref import ref
0071 class _iter_mixin(UserDict.DictMixin):
0072     def _make_iter_cursor(self):
0073         cur = self.db.cursor()
0074         key = id(cur)
0075         self._cursor_refs[key] = ref(cur, self._gen_cref_cleaner(key))
0076         return cur
0077 
0078     def _gen_cref_cleaner(self, key):
0079         # use generate the function for the weakref callback here
0080         # to ensure that we do not hold a strict reference to cur
0081         # in the callback.
0082         return lambda ref: self._cursor_refs.pop(key, None)
0083 
0084     def __iter__(self):
0085         try:
0086             cur = self._make_iter_cursor()
0087 
0088             # FIXME-20031102-greg: race condition.  cursor could
0089             # be closed by another thread before this call.
0090 
0091             # since we're only returning keys, we call the cursor
0092             # methods with flags=0, dlen=0, dofs=0
0093             key = cur.first(0,0,0)[0]
0094             yield key
0095 
0096             next = cur.next
0097             while 1:
0098                 try:
0099                     key = next(0,0,0)[0]
0100                     yield key
0101                 except _bsddb.DBCursorClosedError:
0102                     cur = self._make_iter_cursor()
0103                     # FIXME-20031101-greg: race condition.  cursor could
0104                     # be closed by another thread before this call.
0105                     cur.set(key,0,0,0)
0106                     next = cur.next
0107         except _bsddb.DBNotFoundError:
0108             return
0109         except _bsddb.DBCursorClosedError:
0110             # the database was modified during iteration.  abort.
0111             return
0112 
0113     def iteritems(self):
0114         try:
0115             cur = self._make_iter_cursor()
0116 
0117             # FIXME-20031102-greg: race condition.  cursor could
0118             # be closed by another thread before this call.
0119 
0120             kv = cur.first()
0121             key = kv[0]
0122             yield kv
0123 
0124             next = cur.next
0125             while 1:
0126                 try:
0127                     kv = next()
0128                     key = kv[0]
0129                     yield kv
0130                 except _bsddb.DBCursorClosedError:
0131                     cur = self._make_iter_cursor()
0132                     # FIXME-20031101-greg: race condition.  cursor could
0133                     # be closed by another thread before this call.
0134                     cur.set(key,0,0,0)
0135                     next = cur.next
0136         except _bsddb.DBNotFoundError:
0137             return
0138         except _bsddb.DBCursorClosedError:
0139             # the database was modified during iteration.  abort.
0140             return
0141 """
0142 else:
0143     class _iter_mixin: pass
0144 
0145 
0146 class _DBWithCursor(_iter_mixin):
0147     """
0148     A simple wrapper around DB that makes it look like the bsddbobject in
0149     the old module.  It uses a cursor as needed to provide DB traversal.
0150     """
0151     def __init__(self, db):
0152         self.db = db
0153         self.db.set_get_returns_none(0)
0154 
0155         # FIXME-20031101-greg: I believe there is still the potential
0156         # for deadlocks in a multithreaded environment if someone
0157         # attempts to use the any of the cursor interfaces in one
0158         # thread while doing a put or delete in another thread.  The
0159         # reason is that _checkCursor and _closeCursors are not atomic
0160         # operations.  Doing our own locking around self.dbc,
0161         # self.saved_dbc_key and self._cursor_refs could prevent this.
0162         # TODO: A test case demonstrating the problem needs to be written.
0163 
0164         # self.dbc is a DBCursor object used to implement the
0165         # first/next/previous/last/set_location methods.
0166         self.dbc = None
0167         self.saved_dbc_key = None
0168 
0169         # a collection of all DBCursor objects currently allocated
0170         # by the _iter_mixin interface.
0171         self._cursor_refs = {}
0172 
0173     def __del__(self):
0174         self.close()
0175 
0176     def _checkCursor(self):
0177         if self.dbc is None:
0178             self.dbc = self.db.cursor()
0179             if self.saved_dbc_key is not None:
0180                 self.dbc.set(self.saved_dbc_key)
0181                 self.saved_dbc_key = None
0182 
0183     # This method is needed for all non-cursor DB calls to avoid
0184     # BerkeleyDB deadlocks (due to being opened with DB_INIT_LOCK
0185     # and DB_THREAD to be thread safe) when intermixing database
0186     # operations that use the cursor internally with those that don't.
0187     def _closeCursors(self, save=1):
0188         if self.dbc:
0189             c = self.dbc
0190             self.dbc = None
0191             if save:
0192                 self.saved_dbc_key = c.current(0,0,0)[0]
0193             c.close()
0194             del c
0195         for cref in self._cursor_refs.values():
0196             c = cref()
0197             if c is not None:
0198                 c.close()
0199 
0200     def _checkOpen(self):
0201         if self.db is None:
0202             raise error, "BSDDB object has already been closed"
0203 
0204     def isOpen(self):
0205         return self.db is not None
0206 
0207     def __len__(self):
0208         self._checkOpen()
0209         return len(self.db)
0210 
0211     def __getitem__(self, key):
0212         self._checkOpen()
0213         return self.db[key]
0214 
0215     def __setitem__(self, key, value):
0216         self._checkOpen()
0217         self._closeCursors()
0218         self.db[key] = value
0219 
0220     def __delitem__(self, key):
0221         self._checkOpen()
0222         self._closeCursors()
0223         del self.db[key]
0224 
0225     def close(self):
0226         self._closeCursors(save=0)
0227         if self.dbc is not None:
0228             self.dbc.close()
0229         v = 0
0230         if self.db is not None:
0231             v = self.db.close()
0232         self.dbc = None
0233         self.db = None
0234         return v
0235 
0236     def keys(self):
0237         self._checkOpen()
0238         return self.db.keys()
0239 
0240     def has_key(self, key):
0241         self._checkOpen()
0242         return self.db.has_key(key)
0243 
0244     def set_location(self, key):
0245         self._checkOpen()
0246         self._checkCursor()
0247         return self.dbc.set_range(key)
0248 
0249     def next(self):
0250         self._checkOpen()
0251         self._checkCursor()
0252         rv = self.dbc.next()
0253         return rv
0254 
0255     def previous(self):
0256         self._checkOpen()
0257         self._checkCursor()
0258         rv = self.dbc.prev()
0259         return rv
0260 
0261     def first(self):
0262         self._checkOpen()
0263         self._checkCursor()
0264         rv = self.dbc.first()
0265         return rv
0266 
0267     def last(self):
0268         self._checkOpen()
0269         self._checkCursor()
0270         rv = self.dbc.last()
0271         return rv
0272 
0273     def sync(self):
0274         self._checkOpen()
0275         return self.db.sync()
0276 
0277 
0278 #----------------------------------------------------------------------
0279 # Compatibility object factory functions
0280 
0281 def hashopen(file, flag='c', mode=0666, pgsize=None, ffactor=None, nelem=None,
0282             cachesize=None, lorder=None, hflags=0):
0283 
0284     flags = _checkflag(flag, file)
0285     e = _openDBEnv()
0286     d = db.DB(e)
0287     d.set_flags(hflags)
0288     if cachesize is not None: d.set_cachesize(0, cachesize)
0289     if pgsize is not None:    d.set_pagesize(pgsize)
0290     if lorder is not None:    d.set_lorder(lorder)
0291     if ffactor is not None:   d.set_h_ffactor(ffactor)
0292     if nelem is not None:     d.set_h_nelem(nelem)
0293     d.open(file, db.DB_HASH, flags, mode)
0294     return _DBWithCursor(d)
0295 
0296 #----------------------------------------------------------------------
0297 
0298 def btopen(file, flag='c', mode=0666,
0299             btflags=0, cachesize=None, maxkeypage=None, minkeypage=None,
0300             pgsize=None, lorder=None):
0301 
0302     flags = _checkflag(flag, file)
0303     e = _openDBEnv()
0304     d = db.DB(e)
0305     if cachesize is not None: d.set_cachesize(0, cachesize)
0306     if pgsize is not None: d.set_pagesize(pgsize)
0307     if lorder is not None: d.set_lorder(lorder)
0308     d.set_flags(btflags)
0309     if minkeypage is not None: d.set_bt_minkey(minkeypage)
0310     if maxkeypage is not None: d.set_bt_maxkey(maxkeypage)
0311     d.open(file, db.DB_BTREE, flags, mode)
0312     return _DBWithCursor(d)
0313 
0314 #----------------------------------------------------------------------
0315 
0316 
0317 def rnopen(file, flag='c', mode=0666,
0318             rnflags=0, cachesize=None, pgsize=None, lorder=None,
0319             rlen=None, delim=None, source=None, pad=None):
0320 
0321     flags = _checkflag(flag, file)
0322     e = _openDBEnv()
0323     d = db.DB(e)
0324     if cachesize is not None: d.set_cachesize(0, cachesize)
0325     if pgsize is not None: d.set_pagesize(pgsize)
0326     if lorder is not None: d.set_lorder(lorder)
0327     d.set_flags(rnflags)
0328     if delim is not None: d.set_re_delim(delim)
0329     if rlen is not None: d.set_re_len(rlen)
0330     if source is not None: d.set_re_source(source)
0331     if pad is not None: d.set_re_pad(pad)
0332     d.open(file, db.DB_RECNO, flags, mode)
0333     return _DBWithCursor(d)
0334 
0335 #----------------------------------------------------------------------
0336 
0337 def _openDBEnv():
0338     e = db.DBEnv()
0339     e.open('.', db.DB_PRIVATE | db.DB_CREATE | db.DB_THREAD | db.DB_INIT_LOCK | db.DB_INIT_MPOOL)
0340     return e
0341 
0342 def _checkflag(flag, file):
0343     if flag == 'r':
0344         flags = db.DB_RDONLY
0345     elif flag == 'rw':
0346         flags = 0
0347     elif flag == 'w':
0348         flags =  db.DB_CREATE
0349     elif flag == 'c':
0350         flags =  db.DB_CREATE
0351     elif flag == 'n':
0352         flags = db.DB_CREATE
0353         #flags = db.DB_CREATE | db.DB_TRUNCATE
0354         # we used db.DB_TRUNCATE flag for this before but BerkeleyDB
0355         # 4.2.52 changed to disallowed truncate with txn environments.
0356         if os.path.isfile(file):
0357             os.unlink(file)
0358     else:
0359         raise error, "flags should be one of 'r', 'w', 'c' or 'n'"
0360     return flags | db.DB_THREAD
0361 
0362 #----------------------------------------------------------------------
0363 
0364 
0365 # This is a silly little hack that allows apps to continue to use the
0366 # DB_THREAD flag even on systems without threads without freaking out
0367 # BerkeleyDB.
0368 #
0369 # This assumes that if Python was built with thread support then
0370 # BerkeleyDB was too.
0371 
0372 try:
0373     import thread
0374     del thread
0375 except ImportError:
0376     db.DB_THREAD = 0
0377 
0378 
0379 #----------------------------------------------------------------------
0380 

Generated by PyXR 0.9.4
SourceForge.net Logo