|
Lines 67-81
Link Here
|
| 67 |
#include <sys/types.h> |
67 |
#include <sys/types.h> |
| 68 |
#include <sys/file.h> |
68 |
#include <sys/file.h> |
| 69 |
#include <sys/stat.h> |
69 |
#include <sys/stat.h> |
| 70 |
#include <db.h> |
70 |
#include <lmdb.h> |
| 71 |
#include <stdbool.h> |
71 |
#include <stdbool.h> |
| 72 |
#include <assert.h> |
72 |
#include <assert.h> |
|
|
73 |
#include <stdint.h> |
| 73 |
|
74 |
|
| 74 |
#include <univention/debug.h> |
75 |
#include <univention/debug.h> |
| 75 |
#include <univention/config.h> |
76 |
#include <univention/config.h> |
| 76 |
|
77 |
|
| 77 |
#include "common.h" |
78 |
#include "common.h" |
| 78 |
#include "cache.h" |
79 |
#include "cache.h" |
|
|
80 |
#include "cache_dn.h" |
| 79 |
#include "cache_lowlevel.h" |
81 |
#include "cache_lowlevel.h" |
| 80 |
#include "cache_entry.h" |
82 |
#include "cache_entry.h" |
| 81 |
#include "network.h" |
83 |
#include "network.h" |
|
Lines 83-100
Link Here
|
| 83 |
#include "filter.h" |
85 |
#include "filter.h" |
| 84 |
#include "utils.h" |
86 |
#include "utils.h" |
| 85 |
|
87 |
|
| 86 |
#define MASTER_KEY "__master__" |
88 |
// #define MASTER_KEY "__master__" |
| 87 |
#define MASTER_KEY_SIZE (sizeof MASTER_KEY) |
89 |
static size_t MASTER_KEY=0; |
|
|
90 |
#define MASTER_KEY_SIZE (sizeof(DNID)) |
| 88 |
|
91 |
|
| 89 |
char *cache_dir = "/var/lib/univention-directory-listener"; |
92 |
char *cache_dir = "/var/lib/univention-directory-listener"; |
| 90 |
char *ldap_dir = "/var/lib/univention-ldap"; |
93 |
char *ldap_dir = "/var/lib/univention-ldap"; |
| 91 |
|
94 |
|
| 92 |
CacheMasterEntry cache_master_entry; |
95 |
CacheMasterEntry cache_master_entry; |
| 93 |
|
96 |
|
| 94 |
DB *dbp; |
97 |
MDB_env *env; |
| 95 |
#ifdef WITH_DB42 |
98 |
MDB_dbi id2dn; |
| 96 |
DB_ENV *dbenvp; |
99 |
MDB_dbi id2entry; |
| 97 |
#endif |
100 |
int mdb_readonly = 0; |
| 98 |
static FILE *lock_fp=NULL; |
101 |
static FILE *lock_fp=NULL; |
| 99 |
|
102 |
|
| 100 |
static struct filter cache_filter; |
103 |
static struct filter cache_filter; |
|
Lines 110-126
static void setup_cache_filter(void) {
Link Here
|
| 110 |
} |
113 |
} |
| 111 |
} |
114 |
} |
| 112 |
|
115 |
|
| 113 |
#ifdef WITH_DB42 |
116 |
/* |
| 114 |
static void cache_panic_call(DB_ENV *dbenvp, int errval) |
117 |
int mdb_message_func(const char *msg, void *ctx) { |
| 115 |
{ |
118 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_INFO, |
| 116 |
exit(1); |
119 |
"%s\n", msg); |
|
|
120 |
return MDB_SUCCESS; |
| 117 |
} |
121 |
} |
| 118 |
#endif |
122 |
*/ |
| 119 |
|
123 |
|
| 120 |
static void cache_error_message(const char *errpfx, char *msg) |
124 |
void cache_error_message(int rv, char *msg) |
| 121 |
{ |
125 |
{ |
| 122 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
126 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 123 |
"database error: %s", msg); |
127 |
"%s: failed: %s (%d)\n", |
|
|
128 |
msg, mdb_strerror(rv), rv); |
| 124 |
} |
129 |
} |
| 125 |
|
130 |
|
| 126 |
int cache_lock(void) |
131 |
int cache_lock(void) |
|
Lines 130-136
int cache_lock(void)
Link Here
|
| 130 |
|
135 |
|
| 131 |
assert(!lock_fp); |
136 |
assert(!lock_fp); |
| 132 |
|
137 |
|
| 133 |
rv = snprintf(lock_file, PATH_MAX, "%s/cache.db.lock", cache_dir); |
138 |
rv = snprintf(lock_file, PATH_MAX, "%s/cache.lock", cache_dir); |
| 134 |
if (rv < 0 || rv >= PATH_MAX) |
139 |
if (rv < 0 || rv >= PATH_MAX) |
| 135 |
abort(); |
140 |
abort(); |
| 136 |
|
141 |
|
|
Lines 152-217
int cache_lock(void)
Link Here
|
| 152 |
return fd; |
157 |
return fd; |
| 153 |
} |
158 |
} |
| 154 |
|
159 |
|
| 155 |
int cache_init(void) |
160 |
int cache_init(int mdb_flags) |
| 156 |
{ |
161 |
{ |
| 157 |
int rv; |
162 |
int rv; |
| 158 |
char file[PATH_MAX]; |
163 |
char mdb_dir[PATH_MAX]; |
|
|
164 |
MDB_txn *cache_init_txn; |
| 165 |
int mdb_dbi_flags = MDB_INTEGERKEY; |
| 166 |
|
| 167 |
if ((mdb_flags & MDB_RDONLY) != 0) { |
| 168 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_INFO, |
| 169 |
"cache_init: MDB_RDONLY"); |
| 170 |
mdb_readonly = MDB_RDONLY; |
| 171 |
} else { |
| 172 |
mdb_dbi_flags |= MDB_CREATE; |
| 173 |
} |
| 159 |
|
174 |
|
| 160 |
snprintf(file, PATH_MAX, "%s/cache.db", cache_dir); |
175 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
|
|
176 |
"cache_init: start"); |
| 161 |
|
177 |
|
| 162 |
#ifdef WITH_DB42 |
178 |
snprintf(mdb_dir, PATH_MAX, "%s/cache", cache_dir); |
| 163 |
if ((rv = db_env_create(&dbenvp, 0)) != 0) { |
179 |
|
|
|
180 |
rv = mdb_env_create(&env); |
| 181 |
if (rv != MDB_SUCCESS) { |
| 164 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
182 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 165 |
"creating database environment failed"); |
183 |
"cache_init: creating environment handle failed"); |
|
|
184 |
cache_error_message(rv, "cache_init: mdb_env_create"); |
| 166 |
return rv; |
185 |
return rv; |
| 167 |
} |
186 |
} |
| 168 |
dbenvp->set_errcall(dbenvp, cache_error_message); |
187 |
|
| 169 |
dbenvp->set_paniccall(dbenvp, cache_panic_call); |
188 |
rv = mdb_env_set_mapsize(env, 1992294400); |
| 170 |
if ((rv = dbenvp->open(dbenvp, cache_dir, DB_CREATE | DB_INIT_MPOOL | |
189 |
if (rv != MDB_SUCCESS) { |
| 171 |
/*DB_INIT_LOCK | */DB_INIT_LOG | DB_INIT_TXN | |
|
|
| 172 |
DB_RECOVER, 0600)) != 0) { |
| 173 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
190 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 174 |
"opening database environment failed"); |
191 |
"cache_init: setting mdb mapsize failed"); |
| 175 |
dbenvp->err(dbenvp, rv, "%s", "environment"); |
192 |
cache_error_message(rv, "cache_init: mdb_env_set_mapsize"); |
| 176 |
return rv; |
193 |
return rv; |
| 177 |
} |
194 |
} |
| 178 |
if ((rv = db_create(&dbp, dbenvp, 0)) != 0) { |
195 |
|
|
|
196 |
rv = mdb_env_set_maxdbs(env, 2); |
| 197 |
if (rv != MDB_SUCCESS) { |
| 179 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
198 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 180 |
"creating database handle failed"); |
199 |
"cache_init: setting mdb maxdbs failed"); |
|
|
200 |
cache_error_message(rv, "cache_init: mdb_env_set_maxdbs"); |
| 181 |
return rv; |
201 |
return rv; |
| 182 |
} |
202 |
} |
| 183 |
if ((rv = dbp->open(dbp, NULL, "cache.db", NULL, DB_BTREE, |
203 |
|
| 184 |
DB_CREATE | DB_CHKSUM | DB_AUTO_COMMIT, |
204 |
rv = mdb_env_open(env, mdb_dir, 0, 0600); |
| 185 |
0600)) != 0) { |
205 |
if (rv != MDB_SUCCESS) { |
| 186 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
206 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 187 |
"opening database failed"); |
207 |
"cache_init: opening database failed"); |
| 188 |
dbp->err(dbp, rv, "open"); |
208 |
cache_error_message(rv, "cache_init: mdb_env_open"); |
| 189 |
// FIXME: free dbp |
|
|
| 190 |
return rv; |
209 |
return rv; |
| 191 |
} |
210 |
} |
| 192 |
#else |
211 |
|
| 193 |
if ((rv = db_create(&dbp, NULL, 0)) != 0) { |
212 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 194 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
213 |
"cache_init: Transaction begin"); |
| 195 |
"creating database handle failed"); |
214 |
|
|
|
215 |
rv = mdb_txn_begin(env, NULL, mdb_readonly, &cache_init_txn); |
| 216 |
if (rv != MDB_SUCCESS) { |
| 217 |
cache_error_message(rv, "cache_init: mdb_txn_begin"); |
| 218 |
mdb_env_close(env); |
| 196 |
return rv; |
219 |
return rv; |
| 197 |
} |
220 |
} |
| 198 |
if ((rv = dbp->open(dbp, file, NULL, DB_BTREE, DB_CREATE, 0600)) != 0) { |
221 |
|
| 199 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
222 |
rv = dntree_init(&id2dn, cache_init_txn, mdb_flags); |
| 200 |
"opening database failed"); |
223 |
if (rv != MDB_SUCCESS) { |
| 201 |
dbp->err(dbp, rv, "open"); |
224 |
cache_error_message(rv, "dntree_init: mdb_open"); |
| 202 |
// FIXME: free dbp |
225 |
mdb_txn_abort(cache_init_txn); |
|
|
226 |
mdb_env_close(env); |
| 203 |
return rv; |
227 |
return rv; |
| 204 |
} |
228 |
} |
| 205 |
dbp->set_errcall(dbp, cache_error_message); |
|
|
| 206 |
#endif |
| 207 |
setup_cache_filter(); |
| 208 |
return 0; |
| 209 |
} |
| 210 |
|
229 |
|
| 211 |
void cache_sync(void) { |
230 |
rv = mdb_dbi_open(cache_init_txn, "id2entry", mdb_dbi_flags, &id2entry); |
| 212 |
if (!INIT_ONLY && dbp) { |
231 |
if (rv != MDB_SUCCESS) { |
| 213 |
dbp->sync(dbp, 0); |
232 |
cache_error_message(rv, "cache_init: mdb_open"); |
|
|
233 |
mdb_txn_abort(cache_init_txn); |
| 234 |
mdb_dbi_close(env, id2dn); |
| 235 |
mdb_env_close(env); |
| 236 |
return rv; |
| 214 |
} |
237 |
} |
|
|
238 |
|
| 239 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 240 |
"cache_init: Transaction commit"); |
| 241 |
|
| 242 |
rv = mdb_txn_commit(cache_init_txn); |
| 243 |
if (rv != MDB_SUCCESS) { |
| 244 |
cache_error_message(rv, "cache_init: mdb_txn_commit"); |
| 245 |
mdb_dbi_close(env, id2dn); |
| 246 |
mdb_dbi_close(env, id2entry); |
| 247 |
mdb_env_close(env); |
| 248 |
return rv; |
| 249 |
} |
| 250 |
|
| 251 |
setup_cache_filter(); |
| 252 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 253 |
"cache_init: end"); |
| 254 |
return 0; |
| 215 |
} |
255 |
} |
| 216 |
|
256 |
|
| 217 |
int cache_set_schema_id(const NotifierID value) |
257 |
int cache_set_schema_id(const NotifierID value) |
|
Lines 219-225
int cache_set_schema_id(const NotifierID value)
Link Here
|
| 219 |
int rv, fd, len; |
259 |
int rv, fd, len; |
| 220 |
char file[PATH_MAX], buf[15]; |
260 |
char file[PATH_MAX], buf[15]; |
| 221 |
|
261 |
|
| 222 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_WARN, "Set Schema ID to %ld", value); |
262 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_WARN, |
|
|
263 |
"Set Schema ID to %ld", value); |
| 223 |
len = snprintf(buf, sizeof buf, "%ld", value); |
264 |
len = snprintf(buf, sizeof buf, "%ld", value); |
| 224 |
if (len < 0 || len >= sizeof buf) |
265 |
if (len < 0 || len >= sizeof buf) |
| 225 |
return len; |
266 |
return len; |
|
Lines 299-381
int cache_get_int(char *key, NotifierID *value, const long def)
Link Here
|
| 299 |
|
340 |
|
| 300 |
int cache_get_master_entry(CacheMasterEntry *master_entry) |
341 |
int cache_get_master_entry(CacheMasterEntry *master_entry) |
| 301 |
{ |
342 |
{ |
| 302 |
DBT key, data; |
343 |
int rv; |
| 303 |
int rv; |
344 |
MDB_txn *read_txn; |
|
|
345 |
MDB_val key, data; |
| 346 |
|
| 347 |
memset(&key, 0, sizeof(MDB_val)); |
| 348 |
memset(&data, 0, sizeof(MDB_val)); |
| 304 |
|
349 |
|
| 305 |
memset(&key, 0, sizeof(DBT)); |
350 |
key.mv_data=&MASTER_KEY; |
| 306 |
memset(&data, 0, sizeof(DBT)); |
351 |
key.mv_size=MASTER_KEY_SIZE; |
| 307 |
|
352 |
|
| 308 |
key.data=MASTER_KEY; |
353 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 309 |
key.size=MASTER_KEY_SIZE; |
354 |
"cache_get_master_entry: Transaction begin"); |
| 310 |
data.flags = DB_DBT_REALLOC; |
|
|
| 311 |
|
355 |
|
| 312 |
if ((rv=dbp->get(dbp, NULL, &key, &data, 0)) == DB_NOTFOUND) |
356 |
rv = mdb_txn_begin(env, NULL, MDB_RDONLY, &read_txn); |
|
|
357 |
if (rv != MDB_SUCCESS) { |
| 358 |
cache_error_message(rv, "cache_get_master_entry: mdb_txn_begin"); |
| 313 |
return rv; |
359 |
return rv; |
| 314 |
else if (rv != 0) { |
360 |
} |
|
|
361 |
|
| 362 |
rv = mdb_get(read_txn, id2entry, &key, &data); |
| 363 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 364 |
"cache_get_master_entry: got data"); |
| 365 |
if (rv == MDB_NOTFOUND) { |
| 366 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 367 |
"cache_get_master_entry: Transaction abort"); |
| 368 |
mdb_txn_abort(read_txn); |
| 369 |
return rv; |
| 370 |
} else if (rv != MDB_SUCCESS) { |
| 315 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
371 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 316 |
"reading master entry from database failed"); |
372 |
"cache_get_master_entry: reading master entry from database failed"); |
| 317 |
dbp->err(dbp, rv, "get"); |
373 |
cache_error_message(rv, "cache_get_master_entry: mdb_get"); |
|
|
374 |
mdb_txn_abort(read_txn); |
| 318 |
return rv; |
375 |
return rv; |
| 319 |
} |
376 |
} |
| 320 |
|
377 |
|
| 321 |
if (data.size != sizeof(CacheMasterEntry)) { |
378 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
|
|
379 |
"cache_get_master_entry: Transaction abort"); |
| 380 |
mdb_txn_abort(read_txn); |
| 381 |
|
| 382 |
if (data.mv_size != sizeof(CacheMasterEntry)) { |
| 322 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
383 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 323 |
"master entry has unexpected length"); |
384 |
"cache_get_master_entry: master entry has unexpected length"); |
| 324 |
return 1; |
385 |
return 1; |
| 325 |
} |
386 |
} |
| 326 |
|
387 |
|
| 327 |
memcpy(master_entry, data.data, sizeof(CacheMasterEntry)); |
388 |
memcpy(master_entry, data.mv_data, sizeof(CacheMasterEntry)); |
| 328 |
free(data.data); |
|
|
| 329 |
|
389 |
|
| 330 |
return 0; |
390 |
return MDB_SUCCESS; |
| 331 |
} |
391 |
} |
| 332 |
|
392 |
|
| 333 |
int cache_update_master_entry(CacheMasterEntry *master_entry, DB_TXN *dbtxnp) |
393 |
/* The dbtxnp argument is only used when WITH_DB42 is defined - useless? */ |
|
|
394 |
int cache_update_master_entry(CacheMasterEntry *master_entry, MDB_txn *dbtxnp) |
| 334 |
{ |
395 |
{ |
| 335 |
DBT key, data; |
396 |
int rv; |
| 336 |
int rv; |
397 |
MDB_txn *write_txn = dbtxnp; |
| 337 |
int flags; |
398 |
MDB_val key, data; |
| 338 |
|
|
|
| 339 |
memset(&key, 0, sizeof(DBT)); |
| 340 |
memset(&data, 0, sizeof(DBT)); |
| 341 |
|
399 |
|
| 342 |
key.data=MASTER_KEY; |
400 |
memset(&key, 0, sizeof(MDB_val)); |
| 343 |
key.size=MASTER_KEY_SIZE; |
401 |
memset(&data, 0, sizeof(MDB_val)); |
| 344 |
|
402 |
|
| 345 |
data.data=(void*)master_entry; |
403 |
key.mv_data=&MASTER_KEY; |
| 346 |
data.size=sizeof(CacheMasterEntry); |
404 |
key.mv_size=MASTER_KEY_SIZE; |
| 347 |
|
405 |
|
| 348 |
#ifdef WITH_DB42 |
406 |
data.mv_data=(void*)master_entry; |
| 349 |
if (dbtxnp == NULL) |
407 |
data.mv_size=sizeof(CacheMasterEntry); |
| 350 |
flags = DB_AUTO_COMMIT; |
|
|
| 351 |
else |
| 352 |
#endif |
| 353 |
flags = 0; |
| 354 |
|
408 |
|
| 355 |
if ((rv=dbp->put(dbp, dbtxnp, &key, &data, flags)) != 0) { |
409 |
if (!dbtxnp) { |
|
|
410 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 411 |
"cache_update_master_entry: Transaction begin"); |
| 412 |
} |
| 413 |
if (!dbtxnp |
| 414 |
&& (rv = mdb_txn_begin(env, NULL, 0, &write_txn)) != MDB_SUCCESS) { |
| 415 |
cache_error_message(rv, "cache_update_master_entry: mdb_txn_begin"); |
| 416 |
return rv; |
| 417 |
} |
| 418 |
rv = mdb_put(write_txn, id2entry, &key, &data, 0); |
| 419 |
if (rv != MDB_SUCCESS) { |
| 356 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
420 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 357 |
"storing master entry in database failed"); |
421 |
"cache_update_master_entry: storing master entry in database failed"); |
| 358 |
dbp->err(dbp, rv, "put"); |
422 |
cache_error_message(rv, "cache_update_master_entry: mdb_put"); |
|
|
423 |
mdb_txn_abort(write_txn); |
| 424 |
return rv; |
| 425 |
} |
| 426 |
if (!dbtxnp) { |
| 427 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 428 |
"cache_update_master_entry: Transaction commit"); |
| 429 |
} |
| 430 |
if (!dbtxnp |
| 431 |
&& (rv = mdb_txn_commit(write_txn)) != MDB_SUCCESS) { |
| 432 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 433 |
"cache_update_master_entry: storing master entry in database failed"); |
| 434 |
cache_error_message(rv, "cache_update_master_entry: mdb_txn_commit"); |
| 359 |
return rv; |
435 |
return rv; |
| 360 |
} |
436 |
} |
| 361 |
|
437 |
|
| 362 |
cache_sync(); |
438 |
return MDB_SUCCESS; |
| 363 |
|
|
|
| 364 |
return 0; |
| 365 |
} |
439 |
} |
| 366 |
|
440 |
|
| 367 |
DB_TXN* cache_new_transaction(NotifierID id, char *dn) |
441 |
MDB_txn *cache_new_transaction(NotifierID id, char *dn) |
| 368 |
{ |
442 |
{ |
| 369 |
#ifdef WITH_DB42 |
443 |
#ifdef WITH_DB42 |
| 370 |
DB_TXN *dbtxnp; |
444 |
int rv; |
|
|
445 |
MDB_txn *write_txn; |
| 371 |
CacheMasterEntry master_entry; |
446 |
CacheMasterEntry master_entry; |
| 372 |
NotifierID *old_id; |
447 |
NotifierID *old_id; |
| 373 |
|
448 |
|
| 374 |
dbenvp->txn_begin(dbenvp, NULL, &dbtxnp, 0); |
449 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
|
|
450 |
"cache_new_transaction: Transaction begin"); |
| 451 |
rv = mdb_txn_begin(env, NULL, 0, &write_txn); |
| 452 |
if (rv != MDB_SUCCESS) { |
| 453 |
cache_error_message(rv, "cache_new_transaction: mdb_txn_begin"); |
| 454 |
return NULL; |
| 455 |
} |
| 375 |
|
456 |
|
| 376 |
if (id != 0) { |
457 |
if (id != 0) { |
| 377 |
if (cache_get_master_entry(&master_entry) != 0) { |
458 |
rv = cache_get_master_entry(&master_entry); |
| 378 |
dbtxnp->abort(dbtxnp); |
459 |
if (rv != MDB_SUCCESS) { |
|
|
460 |
mdb_txn_abort(write_txn); |
| 379 |
return NULL; |
461 |
return NULL; |
| 380 |
} |
462 |
} |
| 381 |
|
463 |
|
|
Lines 386-467
DB_TXN* cache_new_transaction(NotifierID id, char *dn)
Link Here
|
| 386 |
|
468 |
|
| 387 |
if (*old_id >= id) { |
469 |
if (*old_id >= id) { |
| 388 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
470 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 389 |
"New ID (%ld) is not greater than old" |
471 |
"New ID (%ld) is not greater than old" |
| 390 |
" ID (%ld): %s", id, *old_id, dn); |
472 |
" ID (%ld): %s", id, *old_id, dn); |
| 391 |
dbtxnp->abort(dbtxnp); |
473 |
mdb_txn_abort(write_txn); |
| 392 |
return NULL; |
474 |
return NULL; |
| 393 |
} else |
475 |
} else |
| 394 |
*old_id = id; |
476 |
*old_id = id; |
| 395 |
|
477 |
|
| 396 |
if (cache_update_master_entry(&master_entry, dbtxnp) != 0) { |
478 |
rv = cache_update_master_entry(&master_entry, write_txn); |
| 397 |
dbtxnp->abort(dbtxnp); |
479 |
if (rv != MDB_SUCCESS) { |
|
|
480 |
mdb_txn_abort(write_txn); |
| 398 |
return NULL; |
481 |
return NULL; |
| 399 |
} |
482 |
} |
| 400 |
} |
483 |
} |
| 401 |
|
484 |
|
| 402 |
return dbtxnp; |
485 |
return write_txn; |
| 403 |
#else |
486 |
#else |
| 404 |
return NULL; |
487 |
return NULL; |
| 405 |
#endif |
488 |
#endif |
| 406 |
} |
489 |
} |
| 407 |
|
490 |
|
| 408 |
|
|
|
| 409 |
/* XXX: The NotifierID is passed for future use. Once the journal is |
491 |
/* XXX: The NotifierID is passed for future use. Once the journal is |
| 410 |
implemented, entries other than the most recent one can be returned. |
492 |
implemented, entries other than the most recent one can be returned. |
| 411 |
At the moment, the id parameters for cache_update_entry, and |
493 |
At the moment, the id parameters for cache_update_entry, and |
| 412 |
cache_delete_entry do nothing (at least if WITH_DB42 is undefined) */ |
494 |
cache_delete_entry do nothing (at least if WITH_DB42 is undefined) */ |
| 413 |
inline int cache_update_entry(NotifierID id, char *dn, CacheEntry *entry) |
495 |
static inline int cache_update_entry_in_transaction(NotifierID id, char *dn, CacheEntry *entry, MDB_cursor **id2dn_cursor_pp) |
| 414 |
{ |
496 |
{ |
| 415 |
DBT key, data; |
497 |
int rv; |
| 416 |
DB_TXN *dbtxnp; |
498 |
DNID dnid; |
| 417 |
int rv = 0; |
499 |
MDB_txn *write_txn; |
|
|
500 |
MDB_val key, data; |
| 501 |
u_int32_t tmp_size = 0; |
| 502 |
|
| 503 |
memset(&data, 0, sizeof(MDB_val)); |
| 504 |
rv = unparse_entry(&data.mv_data, &tmp_size, entry); |
| 505 |
data.mv_size = tmp_size; |
| 506 |
if (rv != 0) { |
| 507 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 508 |
"cache_update_entry: unparsing entry failed"); |
| 509 |
return rv; |
| 510 |
} |
| 418 |
|
511 |
|
| 419 |
memset(&key, 0, sizeof(DBT)); |
512 |
signals_block(); |
| 420 |
memset(&data, 0, sizeof(DBT)); |
513 |
|
|
|
514 |
rv = dntree_get_id4dn(*id2dn_cursor_pp, dn, &dnid, true); |
| 515 |
if (rv != MDB_SUCCESS) { |
| 516 |
signals_unblock(); |
| 517 |
return rv; |
| 518 |
} |
| 519 |
|
| 520 |
key.mv_data = &dnid; |
| 521 |
key.mv_size = sizeof(DNID); |
| 421 |
|
522 |
|
| 422 |
if ((rv=unparse_entry(&data.data, &data.size, entry)) != 0) { |
523 |
write_txn = mdb_cursor_txn(*id2dn_cursor_pp); |
|
|
524 |
rv = mdb_put(write_txn, id2entry, &key, &data, 0); |
| 525 |
if (rv != MDB_SUCCESS) { |
| 423 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
526 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 424 |
"unparsing entry failed"); |
527 |
"cache_update_entry: storing entry in database failed: %s", dn); |
|
|
528 |
cache_error_message(rv, "cache_update_entry: mdb_put"); |
| 529 |
signals_unblock(); |
| 425 |
return rv; |
530 |
return rv; |
| 426 |
} |
531 |
} |
|
|
532 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 533 |
"put %zu bytes for %s", data.mv_size, dn); |
| 427 |
|
534 |
|
|
|
535 |
signals_unblock(); |
| 536 |
|
| 537 |
return rv; |
| 538 |
} |
| 539 |
|
| 540 |
inline int cache_update_entry(NotifierID id, char *dn, CacheEntry *entry) |
| 541 |
{ |
| 542 |
int rv; |
| 543 |
MDB_txn *write_txn; |
| 544 |
MDB_cursor *id2dn_write_cursor_p; |
| 428 |
|
545 |
|
| 429 |
signals_block(); |
|
|
| 430 |
#ifdef WITH_DB42 |
546 |
#ifdef WITH_DB42 |
| 431 |
dbtxnp = cache_new_transaction(id, dn); |
547 |
write_txn = cache_new_transaction(id, dn); |
| 432 |
if (dbtxnp == NULL) { |
548 |
if (write_txn == NULL) { |
| 433 |
signals_unblock(); |
|
|
| 434 |
free(data.data); |
| 435 |
return 1; |
549 |
return 1; |
| 436 |
} |
550 |
} |
| 437 |
#else |
551 |
#else |
| 438 |
dbtxnp = NULL; |
552 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
|
|
553 |
"cache_update_entry: Transaction begin"); |
| 554 |
rv = mdb_txn_begin(env, NULL, 0, &write_txn); |
| 555 |
if (rv != MDB_SUCCESS) { |
| 556 |
cache_error_message(rv, "cache_update_entry: mdb_txn_begin"); |
| 557 |
return rv; |
| 558 |
} |
| 439 |
#endif |
559 |
#endif |
| 440 |
|
560 |
|
| 441 |
key.data=dn; |
561 |
rv = mdb_cursor_open(write_txn, id2dn, &id2dn_write_cursor_p); |
| 442 |
key.size=strlen(dn)+1; |
562 |
if (rv != MDB_SUCCESS) { |
| 443 |
|
563 |
cache_error_message(rv, "cache_update_entry: mdb_cursor_open"); |
| 444 |
if ((rv=dbp->put(dbp, dbtxnp, &key, &data, 0)) != 0) { |
|
|
| 445 |
signals_unblock(); |
| 446 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 447 |
"storing entry in database failed: %s", dn); |
| 448 |
dbp->err(dbp, rv, "put"); |
| 449 |
#ifdef WITH_DB42 |
| 450 |
dbtxnp->abort(dbtxnp); |
| 451 |
#endif |
| 452 |
free(data.data); |
| 453 |
return rv; |
564 |
return rv; |
| 454 |
} |
565 |
} |
| 455 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "put %d bytes for %s", data.size, dn); |
|
|
| 456 |
|
566 |
|
|
|
567 |
rv = cache_update_entry_in_transaction(id, dn, entry, &id2dn_write_cursor_p); |
| 457 |
|
568 |
|
| 458 |
#ifdef WITH_DB42 |
569 |
mdb_cursor_close(id2dn_write_cursor_p); |
| 459 |
dbtxnp->commit(dbtxnp, 0); |
570 |
|
| 460 |
#endif |
571 |
if (rv != MDB_SUCCESS) { |
| 461 |
cache_sync(); |
572 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 462 |
signals_unblock(); |
573 |
"cache_update_entry: Transaction abort"); |
|
|
574 |
mdb_txn_abort(write_txn); |
| 575 |
return rv; |
| 576 |
} |
| 577 |
|
| 578 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 579 |
"cache_update_entry: Transaction commit"); |
| 580 |
rv = mdb_txn_commit(write_txn); |
| 581 |
if (rv != MDB_SUCCESS) { |
| 582 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 583 |
"cache_update_entry: storing updated entry in database failed"); |
| 584 |
cache_error_message(rv, "cache_update_entry: mdb_txn_commit"); |
| 585 |
return rv; |
| 586 |
} |
| 463 |
|
587 |
|
| 464 |
free(data.data); |
|
|
| 465 |
return rv; |
588 |
return rv; |
| 466 |
} |
589 |
} |
| 467 |
|
590 |
|
|
Lines 482-521
int cache_update_entry_lower(NotifierID id, char *dn, CacheEntry *entry)
Link Here
|
| 482 |
return rv; |
605 |
return rv; |
| 483 |
} |
606 |
} |
| 484 |
|
607 |
|
| 485 |
int cache_delete_entry(NotifierID id, char *dn) |
608 |
static inline int cache_delete_entry_in_transaction(NotifierID id, char *dn, MDB_cursor **id2dn_cursor_pp) |
| 486 |
{ |
609 |
{ |
| 487 |
DB_TXN *dbtxnp; |
610 |
int rv; |
| 488 |
DBT key; |
611 |
DNID dnid; |
| 489 |
int rv; |
612 |
MDB_txn *write_txn; |
|
|
613 |
MDB_val key; |
| 614 |
|
| 615 |
signals_block(); |
| 490 |
|
616 |
|
| 491 |
memset(&key, 0, sizeof(DBT)); |
617 |
rv = dntree_get_id4dn(*id2dn_cursor_pp, dn, &dnid, false); |
|
|
618 |
if (rv != MDB_SUCCESS) { |
| 619 |
signals_unblock(); |
| 620 |
return rv; |
| 621 |
} |
| 492 |
|
622 |
|
| 493 |
key.data=dn; |
623 |
key.mv_data = &dnid; |
| 494 |
key.size=strlen(dn)+1; |
624 |
key.mv_size = sizeof(DNID); |
| 495 |
|
625 |
|
| 496 |
signals_block(); |
626 |
write_txn = mdb_cursor_txn(*id2dn_cursor_pp); |
| 497 |
#ifdef WITH_DB42 |
627 |
rv = mdb_del(write_txn, id2entry, &key, 0); |
| 498 |
dbtxnp = cache_new_transaction(id, dn); |
628 |
if (rv != MDB_SUCCESS && rv != MDB_NOTFOUND) { |
| 499 |
if (dbtxnp == NULL) { |
629 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
|
|
630 |
"cache_delete_entry: removing from database failed: %s", dn); |
| 631 |
cache_error_message(rv, "cache_delete_entry: mdb_del"); |
| 500 |
signals_unblock(); |
632 |
signals_unblock(); |
| 501 |
return 1; |
633 |
return rv; |
| 502 |
} |
634 |
} |
| 503 |
#else |
|
|
| 504 |
dbtxnp = NULL; |
| 505 |
#endif |
| 506 |
|
635 |
|
| 507 |
if ((rv=dbp->del(dbp, dbtxnp, &key, 0)) != 0 && rv != DB_NOTFOUND) { |
636 |
rv = dntree_del_id(*id2dn_cursor_pp, dnid); |
|
|
637 |
if (rv != MDB_SUCCESS) { |
| 508 |
signals_unblock(); |
638 |
signals_unblock(); |
| 509 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
639 |
return rv; |
| 510 |
"removing from database failed: %s", dn); |
|
|
| 511 |
dbp->err(dbp, rv, "del"); |
| 512 |
} |
640 |
} |
| 513 |
|
641 |
|
|
|
642 |
signals_unblock(); |
| 643 |
|
| 644 |
return rv; |
| 645 |
} |
| 646 |
|
| 647 |
int cache_delete_entry(NotifierID id, char *dn) |
| 648 |
{ |
| 649 |
int rv; |
| 650 |
MDB_txn *write_txn; |
| 651 |
MDB_cursor *id2dn_write_cursor_p; |
| 652 |
|
| 514 |
#ifdef WITH_DB42 |
653 |
#ifdef WITH_DB42 |
| 515 |
dbtxnp->commit(dbtxnp, 0); |
654 |
write_txn = cache_new_transaction(id, dn); |
|
|
655 |
if (write_txn == NULL) { |
| 656 |
return 1; |
| 657 |
} |
| 658 |
#else |
| 659 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 660 |
"cache_delete_entry: Transaction begin"); |
| 661 |
rv = mdb_txn_begin(env, NULL, 0, &write_txn); |
| 662 |
if (rv != MDB_SUCCESS) { |
| 663 |
cache_error_message(rv, "cache_delete_entry: mdb_txn_begin"); |
| 664 |
return rv; |
| 665 |
} |
| 516 |
#endif |
666 |
#endif |
| 517 |
cache_sync(); |
667 |
|
| 518 |
signals_unblock(); |
668 |
rv = mdb_cursor_open(write_txn, id2dn, &id2dn_write_cursor_p); |
|
|
669 |
if (rv != MDB_SUCCESS) { |
| 670 |
cache_error_message(rv, "cache_delete_entry: mdb_cursor_open"); |
| 671 |
return rv; |
| 672 |
} |
| 673 |
|
| 674 |
rv = cache_delete_entry_in_transaction(id, dn, &id2dn_write_cursor_p); |
| 675 |
|
| 676 |
mdb_cursor_close(id2dn_write_cursor_p); |
| 677 |
|
| 678 |
if (rv != MDB_SUCCESS) { |
| 679 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 680 |
"cache_update_entry: Transaction abort"); |
| 681 |
mdb_txn_abort(write_txn); |
| 682 |
return rv; |
| 683 |
} |
| 684 |
|
| 685 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 686 |
"cache_delete_entry: Transaction commit"); |
| 687 |
rv = mdb_txn_commit(write_txn); |
| 688 |
if (rv != MDB_SUCCESS) { |
| 689 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 690 |
"cache_delete_entry: storing entry removal from database failed"); |
| 691 |
cache_error_message(rv, "cache_delete_entry: mdb_txn_commit"); |
| 692 |
} |
| 519 |
|
693 |
|
| 520 |
return rv; |
694 |
return rv; |
| 521 |
} |
695 |
} |
|
Lines 528-534
int cache_delete_entry_lower_upper(NotifierID id, char *dn)
Link Here
|
| 528 |
|
702 |
|
| 529 |
// convert to a lowercase dn |
703 |
// convert to a lowercase dn |
| 530 |
lower_dn = lower_utf8(dn); |
704 |
lower_dn = lower_utf8(dn); |
| 531 |
rv=cache_delete_entry(id, lower_dn); |
705 |
rv = cache_delete_entry(id, lower_dn); |
| 532 |
if (strcmp(dn, lower_dn) != 0) { |
706 |
if (strcmp(dn, lower_dn) != 0) { |
| 533 |
mixedcase = true; |
707 |
mixedcase = true; |
| 534 |
// try again with original dn |
708 |
// try again with original dn |
|
Lines 536-595
int cache_delete_entry_lower_upper(NotifierID id, char *dn)
Link Here
|
| 536 |
} |
710 |
} |
| 537 |
|
711 |
|
| 538 |
free(lower_dn); |
712 |
free(lower_dn); |
| 539 |
if ( mixedcase ) { |
713 |
if (mixedcase) { |
| 540 |
return rv?rv2:rv; // if rv was bad (!=0) return rv2, otherwise return rv |
714 |
return rv?rv2:rv; // if rv was bad (!=0) return rv2, otherwise return rv |
| 541 |
} else { |
715 |
} else { |
| 542 |
return rv; |
716 |
return rv; |
| 543 |
} |
717 |
} |
| 544 |
} |
718 |
} |
| 545 |
|
719 |
|
| 546 |
int cache_update_or_deleteifunused_entry(NotifierID id, char *dn, CacheEntry *entry) |
720 |
int cache_update_or_deleteifunused_entry(NotifierID id, char *dn, CacheEntry *entry, MDB_cursor **id2dn_cursor_pp) |
| 547 |
{ |
721 |
{ |
| 548 |
if (entry->module_count == 0) |
722 |
if (entry->module_count == 0) |
| 549 |
return cache_delete_entry(id, dn); |
723 |
return cache_delete_entry_in_transaction(id, dn, id2dn_cursor_pp); |
| 550 |
else |
724 |
else |
| 551 |
return cache_update_entry(id, dn, entry); |
725 |
return cache_update_entry_in_transaction(id, dn, entry, id2dn_cursor_pp); |
| 552 |
} |
726 |
} |
| 553 |
|
727 |
|
| 554 |
int cache_get_entry(char *dn, CacheEntry *entry) |
728 |
int cache_get_entry(char *dn, CacheEntry *entry) |
| 555 |
{ |
729 |
{ |
| 556 |
DBT key, data; |
730 |
int rv; |
| 557 |
int rv = 0; |
731 |
DNID dnid; |
| 558 |
|
732 |
MDB_txn *read_txn; |
| 559 |
memset(&key, 0, sizeof(DBT)); |
733 |
MDB_cursor *id2dn_read_cursor_p; |
| 560 |
memset(&data, 0, sizeof(DBT)); |
734 |
MDB_val key, data; |
|
|
735 |
|
| 736 |
memset(&key, 0, sizeof(MDB_val)); |
| 737 |
memset(&data, 0, sizeof(MDB_val)); |
| 561 |
memset(entry, 0, sizeof(CacheEntry)); |
738 |
memset(entry, 0, sizeof(CacheEntry)); |
| 562 |
|
739 |
|
| 563 |
key.data=dn; |
740 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 564 |
key.size=strlen(dn)+1; |
741 |
"cache_get_entry: Transaction begin"); |
| 565 |
data.flags = DB_DBT_REALLOC; |
|
|
| 566 |
|
742 |
|
| 567 |
signals_block(); |
743 |
rv = mdb_txn_begin(env, NULL, MDB_RDONLY, &read_txn); |
| 568 |
rv=dbp->get(dbp, NULL, &key, &data, 0); |
744 |
if (rv != MDB_SUCCESS) { |
| 569 |
signals_unblock(); |
745 |
cache_error_message(rv, "cache_get_entry: mdb_txn_begin"); |
|
|
746 |
return rv; |
| 747 |
} |
| 570 |
|
748 |
|
| 571 |
if (rv != 0 && rv != DB_NOTFOUND) { |
749 |
rv = mdb_cursor_open(read_txn, id2dn, &id2dn_read_cursor_p); |
| 572 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
750 |
if (rv != MDB_SUCCESS) { |
| 573 |
"reading %s from database failed", dn); |
751 |
cache_error_message(rv, "cache_get_entry: mdb_cursor_open"); |
| 574 |
dbp->err(dbp, rv, "get"); |
752 |
mdb_txn_abort(read_txn); |
| 575 |
return rv; |
753 |
return rv; |
| 576 |
} else if (rv == DB_NOTFOUND) { |
754 |
} |
| 577 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "no cache entry found for %s", |
755 |
|
| 578 |
dn); |
756 |
rv = dntree_get_id4dn(id2dn_read_cursor_p, dn, &dnid, false); |
|
|
757 |
mdb_cursor_close(id2dn_read_cursor_p); |
| 758 |
if (rv == MDB_NOTFOUND) { |
| 759 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 760 |
"cache_get_entry: Transaction abort"); |
| 761 |
mdb_txn_abort(read_txn); |
| 579 |
return rv; |
762 |
return rv; |
| 580 |
} |
763 |
} |
| 581 |
|
764 |
|
| 582 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "got %d bytes for %s", |
765 |
key.mv_data = &dnid; |
| 583 |
data.size, dn); |
766 |
key.mv_size = sizeof(DNID); |
|
|
767 |
|
| 768 |
// signals_block(); // TODO: Is this really required? |
| 769 |
rv = mdb_get(read_txn, id2entry, &key, &data); |
| 770 |
// signals_unblock(); |
| 771 |
|
| 772 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 773 |
"cache_get_entry: Transaction abort"); |
| 774 |
mdb_txn_abort(read_txn); |
| 584 |
|
775 |
|
| 585 |
if ((rv=parse_entry(data.data, data.size, entry)) != 0) { |
776 |
if (rv == MDB_SUCCESS) { |
|
|
777 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_INFO, |
| 778 |
"got %zu bytes for %s", data.mv_size, dn); |
| 779 |
} else if (rv == MDB_NOTFOUND) { |
| 780 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_INFO, |
| 781 |
"cache_get_entry: no cache entry found for %s", dn); |
| 782 |
return rv; |
| 783 |
} else { |
| 784 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 785 |
"reading %s from database failed", dn); |
| 786 |
cache_error_message(rv, "cache_get_entry: mdb_get"); |
| 787 |
return rv; |
| 788 |
} |
| 789 |
|
| 790 |
assert(data.mv_size <= UINT32_MAX); |
| 791 |
rv = parse_entry(data.mv_data, data.mv_size, entry); |
| 792 |
if (rv != 0) { |
| 586 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
793 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 587 |
"parsing entry failed"); |
794 |
"cache_get_entry: parsing entry failed"); |
| 588 |
free(data.data); |
|
|
| 589 |
exit(1); |
795 |
exit(1); |
| 590 |
} |
796 |
} |
| 591 |
|
797 |
|
| 592 |
free(data.data); |
|
|
| 593 |
return rv; |
798 |
return rv; |
| 594 |
} |
799 |
} |
| 595 |
|
800 |
|
|
Lines 606-612
int cache_get_entry_lower_upper(char *dn, CacheEntry *entry)
Link Here
|
| 606 |
} |
811 |
} |
| 607 |
|
812 |
|
| 608 |
rv = cache_get_entry(lower_dn, entry); |
813 |
rv = cache_get_entry(lower_dn, entry); |
| 609 |
if (rv == DB_NOTFOUND && mixedcase ) { |
814 |
if (rv == MDB_NOTFOUND && mixedcase ) { |
| 610 |
// try again with original dn |
815 |
// try again with original dn |
| 611 |
rv = cache_get_entry(dn, entry); |
816 |
rv = cache_get_entry(dn, entry); |
| 612 |
} |
817 |
} |
|
Lines 615-722
int cache_get_entry_lower_upper(char *dn, CacheEntry *entry)
Link Here
|
| 615 |
return rv; |
820 |
return rv; |
| 616 |
} |
821 |
} |
| 617 |
|
822 |
|
| 618 |
int cache_first_entry(DBC **cur, char **dn, CacheEntry *entry) |
823 |
int cache_first_entry(MDB_cursor **id2entry_read_cursor_pp, MDB_cursor **id2dn_read_cursor_pp, char **dn, CacheEntry *entry) |
| 619 |
{ |
824 |
{ |
|
|
825 |
MDB_txn *read_txn; |
| 620 |
int rv; |
826 |
int rv; |
| 621 |
|
827 |
|
| 622 |
if ((rv=dbp->cursor(dbp, NULL, cur, 0)) != 0) { |
828 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 623 |
dbp->err(dbp, rv, "cursor"); |
829 |
"cache_first_entry: Transaction begin"); |
|
|
830 |
|
| 831 |
rv = mdb_txn_begin(env, NULL, mdb_readonly, &read_txn); |
| 832 |
if (rv != MDB_SUCCESS) { |
| 833 |
cache_error_message(rv, "cache_first_entry: mdb_txn_begin"); |
| 834 |
return rv; |
| 835 |
} |
| 836 |
|
| 837 |
rv = mdb_cursor_open(read_txn, id2entry, id2entry_read_cursor_pp); |
| 838 |
if (rv != MDB_SUCCESS) { |
| 839 |
cache_error_message(rv, "cache_first_entry: mdb_cursor_open"); |
| 840 |
mdb_txn_abort(read_txn); |
| 624 |
return rv; |
841 |
return rv; |
| 625 |
} |
842 |
} |
| 626 |
|
843 |
|
| 627 |
return cache_next_entry(cur, dn, entry); |
844 |
rv = mdb_cursor_open(read_txn, id2dn, id2dn_read_cursor_pp); |
|
|
845 |
if (rv != MDB_SUCCESS) { |
| 846 |
cache_error_message(rv, "cache_first_entry: mdb_cursor_open"); |
| 847 |
mdb_txn_abort(read_txn); |
| 848 |
return rv; |
| 849 |
} |
| 850 |
|
| 851 |
/* |
| 852 |
// mdb_reader_list(env, &mdb_message_func, NULL); |
| 853 |
MDB_envinfo stat; |
| 854 |
MDB_env *env = mdb_txn_env(read_txn); |
| 855 |
mdb_env_info(env, &stat); |
| 856 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "LAST COMMITTED TXN: %zu", stat.me_last_txnid); |
| 857 |
*/ |
| 858 |
|
| 859 |
return cache_next_entry(id2entry_read_cursor_pp, id2dn_read_cursor_pp, dn, entry); |
| 628 |
} |
860 |
} |
| 629 |
|
861 |
|
| 630 |
int cache_print_entries(char *dn) |
862 |
int cache_print_entries(char *dn) |
| 631 |
{ |
863 |
{ |
| 632 |
DBT key, data; |
864 |
int rv; |
| 633 |
DBC *cur; |
865 |
DNID dnid; |
| 634 |
memset(&key, 0, sizeof(DBT)); |
866 |
MDB_txn *read_txn; |
| 635 |
memset(&data, 0, sizeof(DBT)); |
867 |
MDB_cursor *id2dn_read_cursor_p; |
| 636 |
key.data = strdup(dn); |
868 |
MDB_cursor *id2entry_read_cursor_p; |
| 637 |
key.size = strlen(dn)+1; |
869 |
MDB_val key, data; |
| 638 |
key.flags = DB_DBT_REALLOC; |
870 |
|
| 639 |
data.flags = DB_DBT_REALLOC; |
871 |
memset(&key, 0, sizeof(MDB_val)); |
| 640 |
|
872 |
memset(&data, 0, sizeof(MDB_val)); |
| 641 |
dbp->cursor(dbp, NULL, &cur, 0); |
873 |
|
| 642 |
cur->c_get(cur, &key, &data, DB_FIRST); |
874 |
rv = mdb_txn_begin(env, NULL, MDB_RDONLY, &read_txn); |
| 643 |
do { |
875 |
if (rv != MDB_SUCCESS) { |
| 644 |
printf("%s\n", (char*)key.data); |
876 |
cache_error_message(rv, "cache_print_entries: mdb_txn_begin"); |
| 645 |
} while (cur->c_get(cur, &key, &data, DB_NEXT) == 0); |
877 |
return rv; |
|
|
878 |
} |
| 646 |
|
879 |
|
| 647 |
cur->c_close(cur); |
880 |
rv = mdb_cursor_open(read_txn, id2dn, &id2dn_read_cursor_p); |
| 648 |
free(key.data); |
881 |
if (rv != MDB_SUCCESS) { |
| 649 |
free(data.data); |
882 |
cache_error_message(rv, "cache_print_entries: mdb_cursor_open"); |
| 650 |
return 0; |
883 |
mdb_txn_abort(read_txn); |
|
|
884 |
return rv; |
| 885 |
} |
| 886 |
|
| 887 |
// rv = cache_dntree_get_id(id2dn_read_cursor_p, dn, &dnid, false); |
| 888 |
rv = dntree_get_id4dn(id2dn_read_cursor_p, dn, &dnid, false); |
| 889 |
mdb_cursor_close(id2dn_read_cursor_p); |
| 890 |
if (rv == MDB_NOTFOUND) { |
| 891 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 892 |
"cache_print_entries: Transaction abort"); |
| 893 |
mdb_txn_abort(read_txn); |
| 894 |
return rv; |
| 895 |
} |
| 896 |
|
| 897 |
key.mv_data = &dnid; |
| 898 |
key.mv_size = sizeof(DNID); |
| 899 |
|
| 900 |
rv = mdb_cursor_open(read_txn, id2entry, &id2entry_read_cursor_p); |
| 901 |
if (rv != MDB_SUCCESS) { |
| 902 |
cache_error_message(rv, "cache_print_entries: mdb_cursor_open"); |
| 903 |
mdb_txn_abort(read_txn); |
| 904 |
return rv; |
| 905 |
} |
| 906 |
rv = mdb_cursor_get(id2entry_read_cursor_p, &key, &data, MDB_FIRST); |
| 907 |
do { |
| 908 |
if (rv != MDB_SUCCESS) { |
| 909 |
cache_error_message(rv, "cache_print_entries: mdb_cursor_get"); |
| 910 |
mdb_txn_abort(read_txn); |
| 911 |
return rv; |
| 912 |
} |
| 913 |
printf("%s\n", dn); |
| 914 |
printf("%s\n", (char*)data.mv_data); //TODO: Is that what we want? |
| 915 |
} while ((rv = mdb_cursor_get(id2entry_read_cursor_p, &key, &data, MDB_NEXT))); |
| 916 |
|
| 917 |
mdb_cursor_close(id2entry_read_cursor_p); |
| 918 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 919 |
"cache_print_entries: Transaction abort"); |
| 920 |
mdb_txn_abort(read_txn); |
| 921 |
return MDB_SUCCESS; |
| 651 |
} |
922 |
} |
| 652 |
|
923 |
|
| 653 |
int cache_next_entry(DBC **cur, char **dn, CacheEntry *entry) |
924 |
int cache_next_entry(MDB_cursor **id2entry_read_cursor_pp, MDB_cursor **id2dn_read_cursor_pp, char **dn, CacheEntry *entry) |
| 654 |
{ |
925 |
{ |
| 655 |
DBT key, data; |
926 |
MDB_val key, data; |
|
|
927 |
DNID dnid; |
| 656 |
int rv; |
928 |
int rv; |
| 657 |
|
929 |
|
| 658 |
memset(&key, 0, sizeof(DBT)); |
930 |
memset(&key, 0, sizeof(MDB_val)); |
| 659 |
key.flags = DB_DBT_REALLOC; |
931 |
memset(&data, 0, sizeof(MDB_val)); |
| 660 |
memset(&data, 0, sizeof(DBT)); |
|
|
| 661 |
data.flags = DB_DBT_REALLOC; |
| 662 |
|
932 |
|
| 663 |
if ((rv=(*cur)->c_get(*cur, &key, &data, DB_NEXT)) == DB_NOTFOUND) { |
933 |
/* Get the next entry data */ |
|
|
934 |
rv = mdb_cursor_get(*id2entry_read_cursor_pp, &key, &data, MDB_NEXT); |
| 935 |
if (rv == MDB_NOTFOUND) { |
| 664 |
return rv; |
936 |
return rv; |
| 665 |
} else if (rv != 0) { |
937 |
} else if (rv != MDB_SUCCESS) { |
| 666 |
dbp->err(dbp, rv, "c_get"); |
938 |
cache_error_message(rv, "cache_next_entry: mdb_cursor_get"); |
| 667 |
return rv; |
939 |
return rv; |
| 668 |
} |
940 |
} |
| 669 |
|
941 |
|
| 670 |
/* skip master entry */ |
942 |
// skip root node |
| 671 |
if (strcmp(key.data, MASTER_KEY) == 0) { |
943 |
dnid = * (DNID *) key.mv_data; |
| 672 |
free(key.data); |
944 |
if (dnid == MASTER_KEY) { |
| 673 |
free(data.data); |
945 |
return cache_next_entry(id2entry_read_cursor_pp, id2dn_read_cursor_pp, dn, entry); |
| 674 |
return cache_next_entry(cur, dn, entry); |
|
|
| 675 |
} |
946 |
} |
| 676 |
|
947 |
|
| 677 |
if (*dn) |
948 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 678 |
free(*dn); |
949 |
"got %zu bytes", data.mv_size); |
| 679 |
*dn = strdup(key.data); |
|
|
| 680 |
|
| 681 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "got %d bytes", data.size); |
| 682 |
|
950 |
|
| 683 |
if ((rv=parse_entry(data.data, data.size, entry)) != 0) { |
951 |
assert(data.mv_size <= UINT32_MAX); |
|
|
952 |
rv = parse_entry(data.mv_data, (u_int32_t) data.mv_size, entry); |
| 953 |
if (rv != 0) { |
| 684 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
954 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 685 |
"parsing entry failed: %s", *dn); |
955 |
"cache_next_entry: parsing entry failed: %s", *dn); |
| 686 |
printf("%d\n", data.size); |
956 |
printf("%zu\n", data.mv_size); |
| 687 |
free(key.data); |
|
|
| 688 |
free(data.data); |
| 689 |
return rv; |
957 |
return rv; |
| 690 |
} |
958 |
} |
| 691 |
|
959 |
|
| 692 |
free(key.data); |
960 |
/* Get the corresponding dn */ |
| 693 |
free(data.data); |
961 |
if (*dn) { |
|
|
962 |
free(*dn); |
| 963 |
*dn = NULL; |
| 964 |
} |
| 965 |
|
| 966 |
rv = dntree_lookup_dn4id(*id2dn_read_cursor_pp, dnid, dn); |
| 967 |
|
| 968 |
if (rv != MDB_SUCCESS) { |
| 969 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 970 |
"cache_next_entry: DB corruption, DN entry for id %d not found", |
| 971 |
*(int*)key.mv_data); |
| 972 |
cache_error_message(rv, "cache_next_entry: mdb_get"); |
| 973 |
return rv; |
| 974 |
} |
| 694 |
|
975 |
|
| 695 |
return 0; |
976 |
return 0; |
| 696 |
} |
977 |
} |
| 697 |
|
978 |
|
| 698 |
int cache_free_cursor(DBC *cur) |
979 |
int cache_free_cursor(MDB_cursor *id2entry_read_cursor_pp, MDB_cursor *id2dn_read_cursor_pp) |
| 699 |
{ |
980 |
{ |
| 700 |
return cur->c_close(cur); |
981 |
int rv = 0; |
|
|
982 |
MDB_txn *read_txn; |
| 983 |
|
| 984 |
/* |
| 985 |
// mdb_reader_list(env, &mdb_message_func, NULL); |
| 986 |
MDB_envinfo stat; |
| 987 |
MDB_env *env = mdb_txn_env(read_txn); |
| 988 |
mdb_env_info(env, &stat); |
| 989 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "LAST COMMITTED TXN: %zu", stat.me_last_txnid); |
| 990 |
*/ |
| 991 |
|
| 992 |
read_txn = mdb_cursor_txn(id2entry_read_cursor_pp); |
| 993 |
mdb_cursor_close(id2entry_read_cursor_pp); |
| 994 |
mdb_cursor_close(id2dn_read_cursor_pp); |
| 995 |
|
| 996 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, |
| 997 |
"cache_free_cursor: Transaction commit"); |
| 998 |
rv = mdb_txn_commit(read_txn); |
| 999 |
if (rv != MDB_SUCCESS) { |
| 1000 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 1001 |
"cache_free_cursor: Transation commit failed"); |
| 1002 |
cache_error_message(rv, "cache_free_cursor: mdb_txn_commit"); |
| 1003 |
} |
| 1004 |
return rv; |
| 701 |
} |
1005 |
} |
| 702 |
|
1006 |
|
| 703 |
int cache_close(void) |
1007 |
void cache_close(void) |
| 704 |
{ |
1008 |
{ |
| 705 |
int rv = 0; |
1009 |
mdb_close(env, id2dn); |
|
|
1010 |
mdb_close(env, id2entry); |
| 1011 |
mdb_env_close(env); |
| 706 |
|
1012 |
|
| 707 |
if (dbp && (rv = dbp->close(dbp, 0)) != 0) { |
|
|
| 708 |
dbp->err(dbp, rv, "close"); |
| 709 |
} |
| 710 |
dbp = NULL; |
| 711 |
#ifdef WITH_DB42 |
| 712 |
if ((rv = dbenvp->close(dbenvp, 0)) != 0) { |
| 713 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
| 714 |
"closing database environment failed"); |
| 715 |
} |
| 716 |
#endif |
| 717 |
if (lock_fp != NULL) { |
1013 |
if (lock_fp != NULL) { |
| 718 |
fclose(lock_fp); |
1014 |
fclose(lock_fp); |
| 719 |
lock_fp = NULL; |
1015 |
lock_fp = NULL; |
| 720 |
} |
1016 |
} |
| 721 |
return rv; |
|
|
| 722 |
} |
1017 |
} |