1 /*
2 LibRCC - interface to BerkleyDB
3
4 Copyright (C) 2005-2008 Suren A. Chilingaryan <csa@dside.dyndns.org>
5
6 This library is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License version 2.1 or later
8 as published by the Free Software Foundation.
9
10 This library is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 for more details.
14
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "../config.h"
25
26 #include "internal.h"
27 #include "rcchome.h"
28 #include "rccdb4.h"
29
30 #define DATABASE "autolearn.db"
31
rccDb4CreateContext(const char * dbpath,rcc_db4_flags flags)32 db4_context rccDb4CreateContext(const char *dbpath, rcc_db4_flags flags) {
33 db4_context ctx;
34
35 if (!dbpath) return NULL;
36
37 ctx = (db4_context)malloc(sizeof(db4_context_s));
38 if (!ctx) return NULL;
39
40 memset(ctx, 0, sizeof(db4_context_s));
41 ctx->dbpath = strdup(dbpath);
42 ctx->flags = flags;
43
44 if (!ctx->dbpath) {
45 free(ctx);
46 return NULL;
47 }
48
49 return ctx;
50 }
51
rccDb4InitContext(db4_context ctx,const char * dbpath,rcc_db4_flags flags)52 static int rccDb4InitContext(db4_context ctx, const char *dbpath, rcc_db4_flags flags) {
53 #ifdef HAVE_DB_H
54 int err;
55
56 # ifdef DB_VERSION_MISMATCH
57 char stmp[160];
58 # endif /* DB_VERSION_MISMATCH */
59
60 if (ctx->initialized) {
61 if ((ctx->dbe)&&(ctx->db)) return 0;
62 return -1;
63 }
64
65 err = rccLock();
66 if (err) return -1;
67
68 if (ctx->initialized) {
69 if ((ctx->dbe)&&(ctx->db)) return 0;
70 return -1;
71 }
72
73 ctx->initialized = 1;
74 rccUnLock();
75
76 DB_ENV *dbe;
77 DB *db;
78
79 err = db_env_create(&dbe, 0);
80 if (err) return -1;
81
82 # if defined(DB_LOG_AUTOREMOVE)
83 dbe->set_flags(dbe, DB_LOG_AUTOREMOVE, 1);
84 dbe->set_lg_max(dbe, 131072);
85 # elif defined(DB_LOG_AUTO_REMOVE)
86 // Starting from berkeleydb 4.7 API has changed
87 dbe->log_set_config(dbe, DB_LOG_AUTO_REMOVE, 1);
88 dbe->set_lg_max(dbe, 131072);
89 # endif /* DB_LOG_AUTOREMOVE */
90
91 err = rccLock();
92 if (err) {
93 dbe->close(dbe, 0);
94 return -1;
95 }
96
97 err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL|DB_THREAD, 00644);
98 if (err) {
99 err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|DB_INIT_TXN|DB_USE_ENVIRON|DB_PRIVATE|DB_RECOVER|DB_THREAD, 0);
100 dbe->close(dbe, 0);
101
102 if (err) {
103 err = db_env_create(&dbe, 0);
104 if (err) {
105 rccUnLock();
106 return -1;
107 }
108 dbe->remove(dbe, dbpath, 0);
109 }
110
111 if (strlen(dbpath)<128) {
112 sprintf(stmp, "%s/log.0000000001", dbpath);
113 remove(stmp);
114 }
115
116 err = db_env_create(&dbe, 0);
117 if (err) {
118 rccUnLock();
119 return -1;
120 }
121
122 err = dbe->open(dbe, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL|DB_THREAD, 00644);
123 }
124 rccUnLock();
125
126 if (err) {
127 // fprintf(stderr, "BerkelyDB initialization failed: %i (%s)\n", err, db_strerror(err));
128 dbe->close(dbe, 0);
129 return -1;
130 }
131
132 err = db_create(&db, dbe, 0);
133 if (err) {
134 dbe->close(dbe, 0);
135 return -1;
136 }
137
138
139 err = db->open(db, NULL, DATABASE, NULL, DB_BTREE, DB_CREATE|DB_THREAD, 0);
140 if (err) {
141 db->close(db, 0);
142 dbe->close(dbe, 0);
143 return -1;
144 }
145 #endif /* HAVE_DB_H */
146
147 #ifdef HAVE_DB_H
148 ctx->db = db;
149 ctx->dbe = dbe;
150 #endif /* HAVE_DB_H */
151
152 return 0;
153 }
154
rccDb4FreeContext(db4_context ctx)155 void rccDb4FreeContext(db4_context ctx) {
156 if (ctx) {
157 #ifdef HAVE_DB_H
158 if (ctx->db) ctx->db->close(ctx->db, 0);
159 if (ctx->dbe) ctx->dbe->close(ctx->dbe, 0);
160 #endif /* HAVE_DB_H */
161 if (ctx->dbpath) free(ctx->dbpath);
162 free(ctx);
163 }
164 }
165
166 #ifdef HAVE_DB_H
rccDb4Strip(DBT * key)167 static void rccDb4Strip(DBT *key) {
168 size_t size;
169 char *str;
170
171 str = (char*)key->data;
172 size = key->size;
173
174 while ((size > 0)&&((*str==' ')||(*str=='\n')||(*str==0))) {
175 str++;
176 size--;
177 }
178 while ((size > 0)&&((str[size-1]==' ')||(str[size-1]=='\n')||(str[size-1]==0))) {
179 size--;
180 }
181
182 key->size = size;
183 key->data = str;
184 }
185 #endif /* HAVE_DB_H */
186
rccDb4SetKey(db4_context ctx,const char * orig,size_t olen,const char * string)187 int rccDb4SetKey(db4_context ctx, const char *orig, size_t olen, const char *string) {
188 #ifdef HAVE_DB_H
189 DBT key, data;
190
191 if ((!ctx)||(!orig)||(!string)) return -1;
192 if (rccDb4InitContext(ctx, ctx->dbpath, ctx->flags)) return -1;
193
194 memset(&key, 0, sizeof(key));
195 memset(&data, 0, sizeof(data));
196
197 key.data = (char*)orig;
198 key.size = olen?olen:strlen(orig); /* No ending zero */
199 data.data = (char*)string;
200 data.size = strlen(string)+1;
201
202 rccDb4Strip(&key);
203 if (key.size < RCC_MIN_DB4_CHARS) return -1;
204
205 if (!ctx->db->put(ctx->db, NULL, &key, &data, 0)) return 0;
206 #endif /* HAVE_DB_H */
207
208 return 1;
209 }
210
rccDb4GetKey(db4_context ctx,const char * orig,size_t olen)211 char *rccDb4GetKey(db4_context ctx, const char *orig, size_t olen) {
212 #ifdef HAVE_DB_H
213 DBT key, data;
214
215 if ((!ctx)||(!orig)) return NULL;
216 if (rccDb4InitContext(ctx, ctx->dbpath, ctx->flags)) return NULL;
217
218 memset(&key, 0, sizeof(key));
219 memset(&data, 0, sizeof(data));
220
221 key.data = (char*)orig;
222 key.size = olen?olen:strlen(orig); /* No ending zero */
223
224 data.flags = DB_DBT_REALLOC;
225
226 rccDb4Strip(&key);
227 if (key.size < RCC_MIN_DB4_CHARS) return NULL;
228
229 if (!ctx->db->get(ctx->db, NULL, &key, &data, 0)) return data.data;
230 #endif /* HAVE_DB_H */
231
232 return NULL;
233 }
234