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