OpenSync  0.22
opensync_db_bdb.c
1 /*
2  * libopensync - A synchronization framework
3  * Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  */
20 
21 #include <opensync.h>
22 #include "opensync_internals.h"
23 
24 void osync_db_errcall_fcn(const char *errpfx, char *msg)
25 {
26  osync_debug("OSGRP", 3, "BDB error %s: %s", errpfx, msg);
27 }
28 
29 DB_ENV *osync_db_setup(char *configdir, FILE *errfp)
30 {
31  DB_ENV *dbenv;
32  int ret;
33 
34  if ((ret = db_env_create(&dbenv, 0)) != 0) {
35  fprintf(errfp, "opensync: %s\n", db_strerror(ret));
36  return (NULL);
37  }
38  dbenv->set_errfile(dbenv, errfp);
39  dbenv->set_errpfx(dbenv, "opensync");
40 
41  if ((ret = dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, 1)) != 0) {
42  dbenv->err(dbenv, ret, "set_verbose: db");
43  goto err;
44  }
45 
46  dbenv->set_errcall(dbenv, osync_db_errcall_fcn);
47 
48  /*if ((ret = dbenv->set_cachesize(dbenv, 0, 5 * 1024 * 1024, 0)) != 0) {
49  dbenv->err(dbenv, ret, "set_cachesize");
50  goto err;
51  }*/
52 
53  if ((ret = dbenv->set_data_dir(dbenv, "db")) != 0) {
54  dbenv->err(dbenv, ret, "set_data_dir: db");
55  goto err;
56  }
57 
58  if ((ret = dbenv->set_flags(dbenv, DB_LOG_AUTOREMOVE, 1)) != 0) {
59  dbenv->err(dbenv, ret, "set_flags: db");
60  goto err;
61  }
62 
63  if ((ret = dbenv->open(dbenv, configdir, DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_RECOVER | DB_PRIVATE | DB_INIT_LOCK, 0)) != 0) {
64  dbenv->err(dbenv, ret, "environment open: %s", configdir);
65  goto err;
66  }
67 
68  return (dbenv);
69 
70  err:
71  (void)dbenv->close(dbenv, 0);
72  return (NULL);
73 }
74 
75 void osync_db_tear_down(DB_ENV *dbenv)
76 {
77  dbenv->close(dbenv, 0);
78 }
79 
80 DB *osync_db_open(char *filename, char *dbname, int type, DB_ENV *dbenv)
81 {
82  int ret = 0;
83  DB *dbp = NULL;
84  if ((ret = db_create(&dbp, NULL, 0)) != 0) {
85  printf("db_create: %s\n", db_strerror(ret));
86  return NULL;
87  }
88 
89  //Verify
90  //FIXME
91  if ((ret = dbp->verify(dbp, g_strdup(filename), NULL, NULL, 0)) != 0) {
92  if (ret != 2) { //ENOENT FIXME
93  printf("%i verify failed for db %s: %s\n", ret, filename, db_strerror(ret));
94  return NULL;
95  }
96  }
97  dbp = NULL;
98 
99  if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
100  printf("db_create: %s\n", db_strerror(ret));
101  return NULL;
102  }
103 
104  if ((ret = dbp->set_flags(dbp, DB_RECNUM)) != 0) {
105  dbp->err(dbp, ret, "set_flags: DB_RECNUM");
106  return NULL;
107  }
108 
109  //FIXME g_strdup
110  if ((ret = dbp->open(dbp, NULL, g_strdup(filename), g_strdup(dbname), type, DB_CREATE, 0664)) != 0) {
111  printf("opening db %s", filename);
112  return NULL;
113  }
114  return dbp;
115 }
116 
117 int stubcallback(DB *dbp, const DBT *dbt1, const DBT *dbt2, DBT *dbt3)
118 {
119  printf("Stubcallback called\n");
120  return DB_DONOTINDEX;
121 }
122 
123 void osync_db_sync(DB *dbp)
124 {
125  dbp->sync(dbp, 0);
126 }
127 
128 DB *osync_db_open_secondary(DB *firstdb, char *filename, char *dbname, int (*callback)(DB *, const DBT *, const DBT *, DBT *), DB_ENV *dbenv)
129 {
130  DB *sdbp = NULL;
131  int ret;
132  int (*secfunc)(DB *, const DBT *, const DBT *, DBT *);
133 
134  if ((ret = db_create(&sdbp, dbenv, 0)) != 0) {
135  printf("sec_db_create: %s\n", db_strerror(ret));
136  return NULL;
137  }
138  if ((ret = sdbp->set_flags(sdbp, DB_DUP | DB_DUPSORT)) != 0) {
139  printf("sec_db_set_flag: %s\n", db_strerror(ret));
140  return NULL;
141  }
142  if ((ret = sdbp->open(sdbp, NULL, filename, dbname, DB_BTREE, DB_CREATE, 0600)) != 0) {
143  printf("sec_db_open: %s\n", db_strerror(ret));
144  return NULL;
145  }
146 
147  if (!callback) {
148  secfunc = stubcallback;
149  } else {
150  secfunc = callback;
151  }
152  if ((ret = firstdb->associate(firstdb, NULL, sdbp, secfunc, 0)) != 0) {
153  printf("sec_db_associate: %s\n", db_strerror(ret));
154  return NULL;
155  }
156  return sdbp;
157 }
158 
159 osync_bool osync_db_put_dbt(DB *dbp, DBT *key, DBT *data)
160 {
161  int ret;
162  if ((ret = dbp->put(dbp, NULL, key, data, 0)) != 0) {
163  dbp->err(dbp, ret, "DB->put");
164  return FALSE;
165  }
166  dbp->sync(dbp, 0);
167  return TRUE;
168 }
169 
170 osync_bool osync_db_put(DB *dbp, void *key, int keysize, void *data, int datasize)
171 {
172  DBT keydbt, datadbt;
173  memset(&keydbt, 0, sizeof(keydbt));
174  memset(&datadbt, 0, sizeof(datadbt));
175 
176  keydbt.data = key;
177  keydbt.size = keysize;
178  datadbt.data = data;
179  datadbt.size = datasize;
180 
181  return osync_db_put_dbt(dbp, &keydbt, &datadbt);
182 }
183 
184 osync_bool osync_db_del_dbt(DB *dbp, DBT *key)
185 {
186  int ret;
187 
188  if ((ret = dbp->del(dbp, NULL, key, 0)) != 0) {
189  dbp->err(dbp, ret, "DB->del");
190  return FALSE;
191  }
192  dbp->sync(dbp, 0);
193  return TRUE;
194 }
195 
196 osync_bool osync_db_del(DB *dbp, void *key, int keysize)
197 {
198  DBT keydbt;
199  memset(&keydbt, 0, sizeof(keydbt));
200 
201  keydbt.data = key;
202  keydbt.size = keysize;
203  return osync_db_del_dbt(dbp, &keydbt);
204 }
205 
206 void osync_db_close(DB *dbp)
207 {
208  dbp->close(dbp, 0);
209 }
210 
211 DBC *osync_db_cursor_new(DB *dbp)
212 {
213  DBC *dbcp;
214  int ret;
215 
216  if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
217  dbp->err(dbp, ret, "DB->cursor");
218  return NULL;
219  }
220  return dbcp;
221 }
222 
223 osync_bool osync_db_cursor_next_sec(DBC *dbcp, void **pkey, void **skey, void **data)
224 {
225  DBT pkeydbt, skeydbt, datadbt;
226  int ret;
227 
228  memset(&pkeydbt, 0, sizeof(pkeydbt));
229  memset(&skeydbt, 0, sizeof(skeydbt));
230  memset(&datadbt, 0, sizeof(datadbt));
231 
232  if ((ret = dbcp->c_pget(dbcp, &skeydbt, &pkeydbt, &datadbt, DB_NEXT)) == 0) {
233  *pkey = g_malloc0(pkeydbt.size);
234  memcpy(*pkey, pkeydbt.data, pkeydbt.size);
235  *skey = g_malloc0(skeydbt.size);
236  memcpy(*skey, skeydbt.data, skeydbt.size);
237  *data = g_malloc0(datadbt.size);
238  memcpy(*data, datadbt.data, datadbt.size);
239  return TRUE;
240  } else {
241  return FALSE;
242  }
243 }
244 osync_bool osync_db_cursor_next(DBC *dbcp, void **key, void **data)
245 {
246  DBT keydbt, datadbt;
247  int ret;
248 
249  memset(&keydbt, 0, sizeof(keydbt));
250  memset(&datadbt, 0, sizeof(datadbt));
251 
252  if ((ret = dbcp->c_get(dbcp, &keydbt, &datadbt, DB_NEXT)) == 0) {
253  *key = g_malloc0(keydbt.size);
254  memcpy(*key, keydbt.data, keydbt.size);
255  *data = g_malloc0(datadbt.size);
256  memcpy(*data, datadbt.data, datadbt.size);
257  return TRUE;
258  } else {
259  return FALSE;
260  }
261 }
262 
263 osync_bool osync_db_get(DB *dbp, void *key, int keysize, void **target)
264 {
265  DBT keydbt, datadbt;
266  int ret;
267  memset(&keydbt, 0, sizeof(keydbt));
268  memset(&datadbt, 0, sizeof(datadbt));
269 
270  keydbt.data = key;
271  keydbt.size = keysize;
272 
273  if ((ret = dbp->get(dbp, NULL, &keydbt, &datadbt, 0)) == 0) {
274  *target = g_malloc0(datadbt.size);
275  memcpy(*target, datadbt.data, datadbt.size);
276  return TRUE;
277  } else {
278  if (ret != DB_NOTFOUND) {
279  dbp->err(dbp, ret, "DB->get");
280  }
281  return FALSE;
282  }
283 }
284 
285 void osync_db_empty(DB *db)
286 {
287  u_int32_t deleted = 0;
288  db->truncate(db, NULL, &deleted, DB_AUTO_COMMIT);
289 }
290 
291 void osync_db_cursor_close(DBC *dbcp)
292 {
293  dbcp->c_close(dbcp);
294 }