blob: 1ec6adc195f22e38a5d1b7abfc3f4febc162e73a [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001#----------------------------------------------------------------------
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
Barry Warsaw9a0d7792002-12-30 20:53:52 +000036"""Support for BerkeleyDB 3.1 through 4.1.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000037"""
38
Martin v. Löwis65730a42002-11-24 08:26:01 +000039try:
40 import _bsddb
41except ImportError:
42 # Remove ourselves from sys.modules
43 import sys
44 del sys.modules[__name__]
45 raise
Tim Peters0eadaac2003-04-24 16:02:54 +000046
Barry Warsawf71de3e2003-01-28 17:20:44 +000047# bsddb3 calls it db, but provide _db for backwards compatibility
48db = _db = _bsddb
49__version__ = db.__version__
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000050
Barry Warsawf71de3e2003-01-28 17:20:44 +000051error = db.DBError # So bsddb.error will mean something...
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000052
53#----------------------------------------------------------------------
54
55
56class _DBWithCursor:
57 """
58 A simple wrapper around DB that makes it look like the bsddbobject in
59 the old module. It uses a cursor as needed to provide DB traversal.
60 """
61 def __init__(self, db):
62 self.db = db
63 self.dbc = None
64 self.db.set_get_returns_none(0)
65
66 def __del__(self):
67 self.close()
68
69 def _checkCursor(self):
70 if self.dbc is None:
71 self.dbc = self.db.cursor()
72
73 def _checkOpen(self):
74 if self.db is None:
75 raise error, "BSDDB object has already been closed"
76
77 def isOpen(self):
78 return self.db is not None
79
80 def __len__(self):
81 self._checkOpen()
82 return len(self.db)
83
84 def __getitem__(self, key):
85 self._checkOpen()
86 return self.db[key]
87
88 def __setitem__(self, key, value):
89 self._checkOpen()
90 self.db[key] = value
91
92 def __delitem__(self, key):
93 self._checkOpen()
94 del self.db[key]
95
96 def close(self):
97 if self.dbc is not None:
98 self.dbc.close()
99 v = 0
100 if self.db is not None:
101 v = self.db.close()
102 self.dbc = None
103 self.db = None
104 return v
105
106 def keys(self):
107 self._checkOpen()
108 return self.db.keys()
109
110 def has_key(self, key):
111 self._checkOpen()
112 return self.db.has_key(key)
113
114 def set_location(self, key):
115 self._checkOpen()
116 self._checkCursor()
117 return self.dbc.set(key)
118
119 def next(self):
120 self._checkOpen()
121 self._checkCursor()
122 rv = self.dbc.next()
123 return rv
124
125 def previous(self):
126 self._checkOpen()
127 self._checkCursor()
128 rv = self.dbc.prev()
129 return rv
130
131 def first(self):
132 self._checkOpen()
133 self._checkCursor()
134 rv = self.dbc.first()
135 return rv
136
137 def last(self):
138 self._checkOpen()
139 self._checkCursor()
140 rv = self.dbc.last()
141 return rv
142
143 def sync(self):
144 self._checkOpen()
145 return self.db.sync()
146
147
148#----------------------------------------------------------------------
149# Compatibility object factory functions
150
151def hashopen(file, flag='c', mode=0666, pgsize=None, ffactor=None, nelem=None,
152 cachesize=None, lorder=None, hflags=0):
153
154 flags = _checkflag(flag)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000155 d = db.DB()
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000156 d.set_flags(hflags)
157 if cachesize is not None: d.set_cachesize(0, cachesize)
158 if pgsize is not None: d.set_pagesize(pgsize)
159 if lorder is not None: d.set_lorder(lorder)
160 if ffactor is not None: d.set_h_ffactor(ffactor)
161 if nelem is not None: d.set_h_nelem(nelem)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000162 d.open(file, db.DB_HASH, flags, mode)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000163 return _DBWithCursor(d)
164
165#----------------------------------------------------------------------
166
167def btopen(file, flag='c', mode=0666,
168 btflags=0, cachesize=None, maxkeypage=None, minkeypage=None,
169 pgsize=None, lorder=None):
170
171 flags = _checkflag(flag)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000172 d = db.DB()
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000173 if cachesize is not None: d.set_cachesize(0, cachesize)
174 if pgsize is not None: d.set_pagesize(pgsize)
175 if lorder is not None: d.set_lorder(lorder)
176 d.set_flags(btflags)
177 if minkeypage is not None: d.set_bt_minkey(minkeypage)
178 if maxkeypage is not None: d.set_bt_maxkey(maxkeypage)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000179 d.open(file, db.DB_BTREE, flags, mode)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000180 return _DBWithCursor(d)
181
182#----------------------------------------------------------------------
183
184
185def rnopen(file, flag='c', mode=0666,
186 rnflags=0, cachesize=None, pgsize=None, lorder=None,
187 rlen=None, delim=None, source=None, pad=None):
188
189 flags = _checkflag(flag)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000190 d = db.DB()
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000191 if cachesize is not None: d.set_cachesize(0, cachesize)
192 if pgsize is not None: d.set_pagesize(pgsize)
193 if lorder is not None: d.set_lorder(lorder)
194 d.set_flags(rnflags)
195 if delim is not None: d.set_re_delim(delim)
196 if rlen is not None: d.set_re_len(rlen)
197 if source is not None: d.set_re_source(source)
198 if pad is not None: d.set_re_pad(pad)
Barry Warsawf71de3e2003-01-28 17:20:44 +0000199 d.open(file, db.DB_RECNO, flags, mode)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000200 return _DBWithCursor(d)
201
202#----------------------------------------------------------------------
203
204
205def _checkflag(flag):
206 if flag == 'r':
Barry Warsawf71de3e2003-01-28 17:20:44 +0000207 flags = db.DB_RDONLY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000208 elif flag == 'rw':
209 flags = 0
210 elif flag == 'w':
Barry Warsawf71de3e2003-01-28 17:20:44 +0000211 flags = db.DB_CREATE
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000212 elif flag == 'c':
Barry Warsawf71de3e2003-01-28 17:20:44 +0000213 flags = db.DB_CREATE
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000214 elif flag == 'n':
Barry Warsawf71de3e2003-01-28 17:20:44 +0000215 flags = db.DB_CREATE | db.DB_TRUNCATE
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000216 else:
217 raise error, "flags should be one of 'r', 'w', 'c' or 'n'"
Barry Warsawf71de3e2003-01-28 17:20:44 +0000218 return flags | db.DB_THREAD
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000219
220#----------------------------------------------------------------------
221
222
223# This is a silly little hack that allows apps to continue to use the
224# DB_THREAD flag even on systems without threads without freaking out
225# BerkeleyDB.
226#
227# This assumes that if Python was built with thread support then
228# BerkeleyDB was too.
229
230try:
231 import thread
232 del thread
233except ImportError:
Barry Warsawf71de3e2003-01-28 17:20:44 +0000234 db.DB_THREAD = 0
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000235
236
237#----------------------------------------------------------------------