Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <db.hxx>
31 : :
32 : : #include <rtl/alloc.h>
33 : : #include <rtl/instance.hxx>
34 : : #include <cstring>
35 : : #include <errno.h>
36 : :
37 : : namespace berkeleydbproxy {
38 : :
39 : : //----------------------------------------------------------------------------
40 : : namespace db_internal
41 : : {
42 : : static void raise_error(int dberr, const char * where);
43 : :
44 : 7648 : static inline int check_error(int dberr, const char * where)
45 : : {
46 [ - + ]: 7648 : if (dberr) raise_error(dberr,where);
47 : 7648 : return dberr;
48 : : }
49 : : }
50 : :
51 : : //----------------------------------------------------------------------------
52 : :
53 : 0 : char *DbEnv::strerror(int error)
54 : : {
55 : 0 : return (db_strerror(error));
56 : : }
57 : :
58 : : namespace
59 : : {
60 : : class theDbEnvMutex
61 : : : public rtl::Static<osl::Mutex, theDbEnvMutex> {};
62 : :
63 : : class SharedDbEnv : private boost::noncopyable
64 : : {
65 : : public:
66 : : static DB_ENV* getInstance();
67 : : static void releaseInstance();
68 : : private:
69 : : SharedDbEnv();
70 : : ~SharedDbEnv();
71 : : static DB_ENV* pSharedEnv;
72 : : static int nSharedEnv;
73 : : };
74 : :
75 : : DB_ENV* SharedDbEnv::pSharedEnv = NULL;
76 : : int SharedDbEnv::nSharedEnv = 0;
77 : :
78 : 380 : DB_ENV* SharedDbEnv::getInstance()
79 : : {
80 [ + - ][ + - ]: 380 : ::osl::MutexGuard aGuard(theDbEnvMutex::get());
81 [ + + ]: 380 : if (pSharedEnv == NULL)
82 : : {
83 [ + - ]: 124 : db_env_create(&pSharedEnv, 0);
84 : : // xxx todo: DB_THREAD currently not used
85 [ + - ]: 124 : pSharedEnv->open(pSharedEnv, NULL, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE /*| DB_THREAD*/, 0);
86 : : }
87 : 380 : ++nSharedEnv;
88 [ + - ]: 380 : return pSharedEnv;
89 : : }
90 : :
91 : 380 : void SharedDbEnv::releaseInstance()
92 : : {
93 [ + - ][ + - ]: 380 : ::osl::MutexGuard aGuard(theDbEnvMutex::get());
94 : 380 : --nSharedEnv;
95 [ + + ]: 380 : if (0 == nSharedEnv)
96 : : {
97 [ + - ]: 124 : pSharedEnv->close(pSharedEnv, 0);
98 : 124 : pSharedEnv = NULL;
99 [ + - ]: 380 : }
100 : 380 : }
101 : : }
102 : :
103 : : //----------------------------------------------------------------------------
104 : :
105 : 380 : Db::Db(u_int32_t flags)
106 : 380 : : m_pDBP(0)
107 : : {
108 [ + - ]: 380 : DB_ENV *pSharedDbEnv = SharedDbEnv::getInstance();
109 [ + - ][ + - ]: 380 : db_internal::check_error( db_create(&m_pDBP, pSharedDbEnv, flags),"Db::Db" );
110 : 380 : }
111 : :
112 : :
113 : 380 : Db::~Db()
114 : : {
115 : 380 : if (m_pDBP)
116 : : {
117 : : // should not happen
118 : : // TODO: add assert
119 : : }
120 : :
121 : 380 : }
122 : :
123 : :
124 : 380 : int Db::close(u_int32_t flags)
125 : : {
126 : 380 : int error = m_pDBP->close(m_pDBP,flags);
127 : 380 : m_pDBP = 0;
128 : 380 : SharedDbEnv::releaseInstance();
129 : 380 : return db_internal::check_error(error,"Db::close");
130 : : }
131 : :
132 : 380 : int Db::open(DB_TXN *txnid,
133 : : const char *file,
134 : : const char *database,
135 : : DBTYPE type,
136 : : u_int32_t flags,
137 : : int mode)
138 : : {
139 : 380 : int err = m_pDBP->open(m_pDBP,txnid,file,database,type,flags,mode);
140 : 380 : return db_internal::check_error( err,"Db::open" );
141 : : }
142 : :
143 : :
144 : 70 : int Db::get(DB_TXN *txnid, Dbt *key, Dbt *data, u_int32_t flags)
145 : : {
146 : 70 : int err = m_pDBP->get(m_pDBP,txnid,key,data,flags);
147 : :
148 : : // these are non-exceptional outcomes
149 [ + - ][ + + ]: 70 : if (err != DB_NOTFOUND && err != DB_KEYEMPTY)
150 : 14 : db_internal::check_error( err,"Db::get" );
151 : :
152 : 70 : return err;
153 : : }
154 : :
155 : 502 : int Db::put(DB_TXN* txnid, Dbt *key, Dbt *data, u_int32_t flags)
156 : : {
157 : 502 : int err = m_pDBP->put(m_pDBP,txnid,key,data,flags);
158 : :
159 [ + - ]: 502 : if (err != DB_KEYEXIST) // this is a non-exceptional outcome
160 : 502 : db_internal::check_error( err,"Db::put" );
161 : 502 : return err;
162 : : }
163 : :
164 : 1570 : int Db::cursor(DB_TXN *txnid, Dbc **cursorp, u_int32_t flags)
165 : : {
166 : 1570 : DBC * dbc = 0;
167 [ + - ]: 1570 : int error = m_pDBP->cursor(m_pDBP,txnid,&dbc,flags);
168 : :
169 [ + - ][ + - ]: 1570 : if (!db_internal::check_error(error,"Db::cursor"))
170 [ + - ]: 1570 : *cursorp = new Dbc(dbc);
171 : :
172 : 1570 : return error;
173 : : }
174 : :
175 : :
176 : : #define DB_INCOMPLETE (-30999)/* Sync didn't finish. */
177 : :
178 : 508 : int Db::sync(u_int32_t flags)
179 : : {
180 : : int err;
181 : 508 : DB *db = m_pDBP;
182 : :
183 [ - + ]: 508 : if (!db) {
184 : 0 : db_internal::check_error(EINVAL,"Db::sync");
185 : 0 : return (EINVAL);
186 : : }
187 [ - + ][ # # ]: 508 : if ((err = db->sync(db, flags)) != 0 && err != DB_INCOMPLETE) {
[ - + ]
188 : 0 : db_internal::check_error(err, "Db::sync");
189 : 0 : return (err);
190 : : }
191 : 508 : return (err);
192 : : }
193 : :
194 : 6 : int Db::del(Dbt *key, u_int32_t flags)
195 : : {
196 : 6 : DB *db = m_pDBP;
197 : : int err;
198 : :
199 [ - + ]: 6 : if ((err = db->del(db, 0, key, flags)) != 0) {
200 : : // DB_NOTFOUND is a "normal" return, so should not be
201 : : // thrown as an error
202 [ # # ]: 0 : if (err != DB_NOTFOUND) {
203 : 0 : db_internal::check_error(err, "Db::del");
204 : 0 : return (err);
205 : : }
206 : : }
207 : 6 : return (err);
208 : : }
209 : :
210 : : //----------------------------------------------------------------------------
211 : :
212 : 1570 : Dbc::Dbc(DBC * dbc)
213 : 1570 : : m_pDBC(dbc)
214 : : {
215 : 1570 : }
216 : :
217 : 1570 : Dbc::~Dbc()
218 : : {
219 : 1570 : }
220 : :
221 : 1570 : int Dbc::close()
222 : : {
223 : 1570 : int err = m_pDBC->c_close(m_pDBC);
224 [ + - ]: 1570 : delete this;
225 : 1570 : return db_internal::check_error( err,"Dbcursor::close" );
226 : : }
227 : :
228 : 4422 : int Dbc::get(Dbt *key, Dbt *data, u_int32_t flags)
229 : : {
230 : 4422 : int err = m_pDBC->c_get(m_pDBC,key,data,flags);
231 : :
232 : : // these are non-exceptional outcomes
233 [ + - ][ + + ]: 4422 : if (err != DB_NOTFOUND && err != DB_KEYEMPTY)
234 : 2852 : db_internal::check_error( err, "Dbcursor::get" );
235 : :
236 : 4422 : return err;
237 : : }
238 : :
239 : : //----------------------------------------------------------------------------
240 : :
241 : 8914 : Dbt::Dbt()
242 : : {
243 : : using namespace std;
244 : 8914 : DBT * thispod = this;
245 : 8914 : memset(thispod, 0, sizeof *thispod);
246 : 8914 : }
247 : :
248 : :
249 : 1080 : Dbt::Dbt(void *data_arg, u_int32_t size_arg)
250 : : {
251 : : using namespace std;
252 : 1080 : DBT * thispod = this;
253 : 1080 : memset(thispod, 0, sizeof *thispod);
254 : 1080 : this->set_data(data_arg);
255 : 1080 : this->set_size(size_arg);
256 : 1080 : }
257 : :
258 : 0 : Dbt::Dbt(const Dbt & other)
259 : : {
260 : : using namespace std;
261 : 0 : const DBT *otherpod = &other;
262 : 0 : DBT *thispod = this;
263 : 0 : memcpy(thispod, otherpod, sizeof *thispod);
264 : 0 : }
265 : :
266 : 0 : Dbt& Dbt::operator = (const Dbt & other)
267 : : {
268 [ # # ]: 0 : if (this != &other)
269 : : {
270 : : using namespace std;
271 : 0 : const DBT *otherpod = &other;
272 : 0 : DBT *thispod = this;
273 : 0 : memcpy(thispod, otherpod, sizeof *thispod);
274 : : }
275 : 0 : return *this;
276 : : }
277 : :
278 : 9994 : Dbt::~Dbt()
279 : : {
280 : 9994 : }
281 : :
282 : 5718 : void * Dbt::get_data() const
283 : : {
284 : 5718 : return this->data;
285 : : }
286 : :
287 : 1080 : void Dbt::set_data(void *value)
288 : : {
289 : 1080 : this->data = value;
290 : 1080 : }
291 : :
292 : 5718 : u_int32_t Dbt::get_size() const
293 : : {
294 : 5718 : return this->size;
295 : : }
296 : :
297 : 1080 : void Dbt::set_size(u_int32_t value)
298 : : {
299 : 1080 : this->size = value;
300 : 1080 : }
301 : :
302 : : //----------------------------------------------------------------------------
303 : 0 : void db_internal::raise_error(int dberr, const char * where)
304 : : {
305 [ # # ]: 0 : if (!where) where = "<unknown>";
306 : :
307 [ # # ]: 0 : const char * dberrmsg = db_strerror(dberr);
308 [ # # ][ # # ]: 0 : if (!dberrmsg || !*dberrmsg) dberrmsg = "<unknown DB error>";
309 : :
310 : 0 : rtl::OString msg = where;
311 : 0 : msg += ": ";
312 : 0 : msg += dberrmsg;
313 : :
314 : 0 : throw DbException(msg);
315 : : }
316 : :
317 : : //----------------------------------------------------------------------------
318 : : } // namespace ecomp
319 : :
320 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|