|
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 |
|
73 |
|
|
91 |
|
91 |
|
92 |
CacheMasterEntry cache_master_entry; |
92 |
CacheMasterEntry cache_master_entry; |
93 |
|
93 |
|
94 |
DB *dbp; |
94 |
MDB_env *env; |
95 |
#ifdef WITH_DB42 |
95 |
MDB_dbi dbi; |
96 |
DB_ENV *dbenvp; |
|
|
97 |
#endif |
98 |
static FILE *lock_fp=NULL; |
96 |
static FILE *lock_fp=NULL; |
99 |
|
97 |
|
100 |
static struct filter cache_filter; |
98 |
static struct filter cache_filter; |
|
110 |
} |
108 |
} |
111 |
} |
109 |
} |
112 |
|
110 |
|
113 |
#ifdef WITH_DB42 |
111 |
static void cache_error_message(int rv, char *msg) |
114 |
static void cache_panic_call(DB_ENV *dbenvp, int errval) |
|
|
115 |
{ |
112 |
{ |
116 |
exit(1); |
113 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
|
|
114 |
"database error: %s: %s (%d)\n", |
115 |
msg, mdb_strerror(rv), rv); |
117 |
} |
116 |
} |
118 |
#endif |
|
|
119 |
|
117 |
|
120 |
static void cache_error_message(const char *errpfx, char *msg) |
118 |
int mdb_message_func(const char *msg, void *ctx) { |
121 |
{ |
119 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_INFO, |
122 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
120 |
"%s\n", msg); |
123 |
"database error: %s", msg); |
121 |
return 0; |
124 |
} |
122 |
} |
125 |
|
123 |
|
126 |
int cache_lock(void) |
124 |
int cache_lock(void) |
|
130 |
|
128 |
|
131 |
assert(!lock_fp); |
129 |
assert(!lock_fp); |
132 |
|
130 |
|
133 |
rv = snprintf(lock_file, PATH_MAX, "%s/cache.db.lock", cache_dir); |
131 |
rv = snprintf(lock_file, PATH_MAX, "%s/cache.lock", cache_dir); |
134 |
if (rv < 0 || rv >= PATH_MAX) |
132 |
if (rv < 0 || rv >= PATH_MAX) |
135 |
abort(); |
133 |
abort(); |
136 |
|
134 |
|
|
155 |
int cache_init(void) |
153 |
int cache_init(void) |
156 |
{ |
154 |
{ |
157 |
int rv; |
155 |
int rv; |
158 |
char file[PATH_MAX]; |
156 |
char mdb_dir[PATH_MAX]; |
|
|
157 |
MDB_txn *txn; |
159 |
|
158 |
|
160 |
snprintf(file, PATH_MAX, "%s/cache.db", cache_dir); |
159 |
snprintf(mdb_dir, PATH_MAX, "%s/cache", cache_dir); |
161 |
|
160 |
|
162 |
#ifdef WITH_DB42 |
161 |
if ((rv = mdb_env_create(&env)) != 0) { |
163 |
if ((rv = db_env_create(&dbenvp, 0)) != 0) { |
|
|
164 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
162 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
165 |
"creating database environment failed"); |
163 |
"creating environment handle failed"); |
|
|
164 |
cache_error_message(rv, "mdb_env_create"); |
166 |
return rv; |
165 |
return rv; |
167 |
} |
166 |
} |
168 |
dbenvp->set_errcall(dbenvp, cache_error_message); |
167 |
if ((rv = mdb_env_set_mapsize(env, 1992294400)) != 0) { |
169 |
dbenvp->set_paniccall(dbenvp, cache_panic_call); |
|
|
170 |
if ((rv = dbenvp->open(dbenvp, cache_dir, DB_CREATE | DB_INIT_MPOOL | |
171 |
/*DB_INIT_LOCK | */DB_INIT_LOG | DB_INIT_TXN | |
172 |
DB_RECOVER, 0600)) != 0) { |
173 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
168 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
174 |
"opening database environment failed"); |
169 |
"setting mdb mapsize failed"); |
175 |
dbenvp->err(dbenvp, rv, "%s", "environment"); |
170 |
cache_error_message(rv, "mdb_env_set_mapsize"); |
176 |
return rv; |
171 |
return rv; |
177 |
} |
172 |
} |
178 |
if ((rv = db_create(&dbp, dbenvp, 0)) != 0) { |
173 |
if ((rv = mdb_env_open(env, mdb_dir, MDB_NORDAHEAD, 0600)) != 0) { |
179 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
174 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
180 |
"creating database handle failed"); |
175 |
"opening database failed"); |
|
|
176 |
cache_error_message(rv, "mdb_env_open"); |
181 |
return rv; |
177 |
return rv; |
182 |
} |
178 |
} |
183 |
if ((rv = dbp->open(dbp, NULL, "cache.db", NULL, DB_BTREE, |
179 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction begin (cache_init)"); |
184 |
DB_CREATE | DB_CHKSUM | DB_AUTO_COMMIT, |
180 |
if ((rv = mdb_txn_begin(env, NULL, 0, &txn)) != 0) { |
185 |
0600)) != 0) { |
181 |
cache_error_message(rv, "mdb_txn_begin"); |
186 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
182 |
mdb_env_close(env); |
187 |
"opening database failed"); |
|
|
188 |
dbp->err(dbp, rv, "open"); |
189 |
// FIXME: free dbp |
190 |
return rv; |
183 |
return rv; |
191 |
} |
184 |
} |
192 |
#else |
185 |
if ((rv = mdb_open(txn, NULL, 0, &dbi)) != 0) { |
193 |
if ((rv = db_create(&dbp, NULL, 0)) != 0) { |
186 |
cache_error_message(rv, "mdb_open"); |
194 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
187 |
mdb_txn_abort(txn); |
195 |
"creating database handle failed"); |
188 |
mdb_env_close(env); |
196 |
return rv; |
189 |
return rv; |
197 |
} |
190 |
} |
198 |
if ((rv = dbp->open(dbp, file, NULL, DB_BTREE, DB_CREATE, 0600)) != 0) { |
191 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction commit (cache_init)"); |
199 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
192 |
if ((rv = mdb_txn_commit(txn)) != 0) { |
200 |
"opening database failed"); |
193 |
cache_error_message(rv, "mdb_txn_commit"); |
201 |
dbp->err(dbp, rv, "open"); |
194 |
mdb_dbi_close(env, dbi); |
202 |
// FIXME: free dbp |
195 |
mdb_env_close(env); |
203 |
return rv; |
196 |
return rv; |
204 |
} |
197 |
} |
205 |
dbp->set_errcall(dbp, cache_error_message); |
198 |
|
206 |
#endif |
|
|
207 |
setup_cache_filter(); |
199 |
setup_cache_filter(); |
208 |
return 0; |
200 |
return 0; |
209 |
} |
201 |
} |
210 |
|
202 |
|
211 |
void cache_sync(void) { |
|
|
212 |
if (!INIT_ONLY && dbp) { |
213 |
dbp->sync(dbp, 0); |
214 |
} |
215 |
} |
216 |
|
217 |
int cache_set_schema_id(const NotifierID value) |
203 |
int cache_set_schema_id(const NotifierID value) |
218 |
{ |
204 |
{ |
219 |
int rv, fd, len; |
205 |
int rv, fd, len; |
|
297 |
|
283 |
|
298 |
int cache_get_master_entry(CacheMasterEntry *master_entry) |
284 |
int cache_get_master_entry(CacheMasterEntry *master_entry) |
299 |
{ |
285 |
{ |
300 |
DBT key, data; |
286 |
MDB_txn *txn; |
|
|
287 |
MDB_val key, data; |
301 |
int rv; |
288 |
int rv; |
302 |
|
289 |
|
303 |
memset(&key, 0, sizeof(DBT)); |
290 |
memset(&key, 0, sizeof(MDB_val)); |
304 |
memset(&data, 0, sizeof(DBT)); |
291 |
memset(&data, 0, sizeof(MDB_val)); |
305 |
|
292 |
|
306 |
key.data=MASTER_KEY; |
293 |
key.mv_data=MASTER_KEY; |
307 |
key.size=MASTER_KEY_SIZE; |
294 |
key.mv_size=MASTER_KEY_SIZE; |
308 |
data.flags = DB_DBT_REALLOC; |
|
|
309 |
|
295 |
|
310 |
if ((rv=dbp->get(dbp, NULL, &key, &data, 0)) == DB_NOTFOUND) |
296 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction begin (cache_get_master_entry)"); |
|
|
297 |
if ((rv = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)) != 0) { |
298 |
cache_error_message(rv, "mdb_txn_begin"); |
311 |
return rv; |
299 |
return rv; |
|
|
300 |
} |
301 |
if ((rv = mdb_get(txn, dbi, &key, &data)) == MDB_NOTFOUND) { |
302 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction abort (cache_get_master_entry)"); |
303 |
mdb_txn_abort(txn); |
304 |
return rv; |
305 |
} |
312 |
else if (rv != 0) { |
306 |
else if (rv != 0) { |
313 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
307 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
314 |
"reading master entry from database failed"); |
308 |
"reading master entry from database failed"); |
315 |
dbp->err(dbp, rv, "get"); |
309 |
cache_error_message(rv, "mdb_get"); |
|
|
310 |
mdb_txn_abort(txn); |
316 |
return rv; |
311 |
return rv; |
317 |
} |
312 |
} |
|
|
313 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction abort (cache_get_master_entry)"); |
314 |
mdb_txn_abort(txn); |
318 |
|
315 |
|
319 |
if (data.size != sizeof(CacheMasterEntry)) { |
316 |
if (data.mv_size != sizeof(CacheMasterEntry)) { |
320 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
317 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
321 |
"master entry has unexpected length"); |
318 |
"master entry has unexpected length"); |
322 |
return 1; |
319 |
return 1; |
323 |
} |
320 |
} |
324 |
|
321 |
|
325 |
memcpy(master_entry, data.data, sizeof(CacheMasterEntry)); |
322 |
memcpy(master_entry, data.mv_data, sizeof(CacheMasterEntry)); |
326 |
free(data.data); |
|
|
327 |
|
323 |
|
328 |
return 0; |
324 |
return 0; |
329 |
} |
325 |
} |
330 |
|
326 |
|
331 |
int cache_update_master_entry(CacheMasterEntry *master_entry, DB_TXN *dbtxnp) |
327 |
/* The dbtxnp argument is only used when WITH_DB42 is defined - useless? */ |
|
|
328 |
int cache_update_master_entry(CacheMasterEntry *master_entry, MDB_txn *dbtxnp) |
332 |
{ |
329 |
{ |
333 |
DBT key, data; |
330 |
MDB_txn *txn = dbtxnp; |
|
|
331 |
MDB_val key, data; |
334 |
int rv; |
332 |
int rv; |
335 |
int flags; |
333 |
int flags; |
336 |
|
334 |
|
337 |
memset(&key, 0, sizeof(DBT)); |
335 |
memset(&key, 0, sizeof(MDB_val)); |
338 |
memset(&data, 0, sizeof(DBT)); |
336 |
memset(&data, 0, sizeof(MDB_val)); |
339 |
|
337 |
|
340 |
key.data=MASTER_KEY; |
338 |
key.mv_data=MASTER_KEY; |
341 |
key.size=MASTER_KEY_SIZE; |
339 |
key.mv_size=MASTER_KEY_SIZE; |
342 |
|
340 |
|
343 |
data.data=(void*)master_entry; |
341 |
data.mv_data=(void*)master_entry; |
344 |
data.size=sizeof(CacheMasterEntry); |
342 |
data.mv_size=sizeof(CacheMasterEntry); |
345 |
|
343 |
|
346 |
#ifdef WITH_DB42 |
344 |
flags = 0; |
347 |
if (dbtxnp == NULL) |
|
|
348 |
flags = DB_AUTO_COMMIT; |
349 |
else |
350 |
#endif |
351 |
flags = 0; |
352 |
|
345 |
|
353 |
if ((rv=dbp->put(dbp, dbtxnp, &key, &data, flags)) != 0) { |
346 |
if (!dbtxnp) { |
|
|
347 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction begin (cache_update_master_entry)"); |
348 |
} |
349 |
if (!dbtxnp && (rv = mdb_txn_begin(env, NULL, 0, &txn)) != 0) { |
350 |
cache_error_message(rv, "mdb_txn_begin"); |
351 |
return rv; |
352 |
} |
353 |
if ((rv = mdb_put(txn, dbi, &key, &data, flags)) != 0) { |
354 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
354 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
355 |
"storing master entry in database failed"); |
355 |
"storing master entry in database failed"); |
356 |
dbp->err(dbp, rv, "put"); |
356 |
cache_error_message(rv, "mdb_put"); |
|
|
357 |
mdb_txn_abort(txn); |
357 |
return rv; |
358 |
return rv; |
358 |
} |
359 |
} |
|
|
360 |
if (!dbtxnp) { |
361 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction commit (cache_update_master_entry)"); |
362 |
} |
363 |
if (!dbtxnp && (rv = mdb_txn_commit(txn)) != 0) { |
364 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
365 |
"storing master entry in database failed"); |
366 |
cache_error_message(rv, "mdb_txn_commit"); |
367 |
return rv; |
368 |
} |
359 |
|
369 |
|
360 |
cache_sync(); |
|
|
361 |
|
362 |
return 0; |
370 |
return 0; |
363 |
} |
371 |
} |
364 |
|
372 |
|
365 |
DB_TXN* cache_new_transaction(NotifierID id, char *dn) |
373 |
MDB_txn *cache_new_transaction(NotifierID id, char *dn) |
366 |
{ |
374 |
{ |
367 |
#ifdef WITH_DB42 |
375 |
#ifdef WITH_DB42 |
368 |
DB_TXN *dbtxnp; |
376 |
int rv; |
|
|
377 |
MDB_txn *txn; |
369 |
CacheMasterEntry master_entry; |
378 |
CacheMasterEntry master_entry; |
370 |
NotifierID *old_id; |
379 |
NotifierID *old_id; |
371 |
|
380 |
|
372 |
dbenvp->txn_begin(dbenvp, NULL, &dbtxnp, 0); |
381 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction begin (cache_new_transaction)"); |
|
|
382 |
if ((rv = mdb_txn_begin(env, NULL, 0, &txn)) != 0) { |
383 |
cache_error_message(rv, "mdb_txn_begin"); |
384 |
return NULL; |
385 |
} |
373 |
|
386 |
|
374 |
if (id != 0) { |
387 |
if (id != 0) { |
375 |
if (cache_get_master_entry(&master_entry) != 0) { |
388 |
if (cache_get_master_entry(&master_entry) != 0) { |
376 |
dbtxnp->abort(dbtxnp); |
389 |
mdb_txn_abort(txn); |
377 |
return NULL; |
390 |
return NULL; |
378 |
} |
391 |
} |
379 |
|
392 |
|
|
386 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
399 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
387 |
"New ID (%ld) is not greater than old" |
400 |
"New ID (%ld) is not greater than old" |
388 |
" ID (%ld): %s", id, *old_id, dn); |
401 |
" ID (%ld): %s", id, *old_id, dn); |
389 |
dbtxnp->abort(dbtxnp); |
402 |
mdb_txn_abort(txn); |
390 |
return NULL; |
403 |
return NULL; |
391 |
} else |
404 |
} else |
392 |
*old_id = id; |
405 |
*old_id = id; |
393 |
|
406 |
|
394 |
if (cache_update_master_entry(&master_entry, dbtxnp) != 0) { |
407 |
if (cache_update_master_entry(&master_entry, txn) != 0) { |
395 |
dbtxnp->abort(dbtxnp); |
408 |
mdb_txn_abort(txn); |
396 |
return NULL; |
409 |
return NULL; |
397 |
} |
410 |
} |
398 |
} |
411 |
} |
399 |
|
412 |
|
400 |
return dbtxnp; |
413 |
return txn; |
401 |
#else |
414 |
#else |
402 |
return NULL; |
415 |
return NULL; |
403 |
#endif |
416 |
#endif |
|
410 |
cache_delete_entry do nothing (at least if WITH_DB42 is undefined) */ |
423 |
cache_delete_entry do nothing (at least if WITH_DB42 is undefined) */ |
411 |
inline int cache_update_entry(NotifierID id, char *dn, CacheEntry *entry) |
424 |
inline int cache_update_entry(NotifierID id, char *dn, CacheEntry *entry) |
412 |
{ |
425 |
{ |
413 |
DBT key, data; |
426 |
MDB_txn *txn; |
414 |
DB_TXN *dbtxnp; |
427 |
MDB_val key, data; |
415 |
int rv = 0; |
428 |
int rv = 0; |
416 |
|
429 |
|
417 |
memset(&key, 0, sizeof(DBT)); |
430 |
memset(&key, 0, sizeof(MDB_val)); |
418 |
memset(&data, 0, sizeof(DBT)); |
431 |
memset(&data, 0, sizeof(MDB_val)); |
419 |
|
432 |
|
420 |
if ((rv=unparse_entry(&data.data, &data.size, entry)) != 0) { |
433 |
if ((rv=unparse_entry(&data.mv_data, &data.mv_size, entry)) != 0) { |
421 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
434 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
422 |
"unparsing entry failed"); |
435 |
"unparsing entry failed"); |
423 |
return rv; |
436 |
return rv; |
|
426 |
|
439 |
|
427 |
signals_block(); |
440 |
signals_block(); |
428 |
#ifdef WITH_DB42 |
441 |
#ifdef WITH_DB42 |
429 |
dbtxnp = cache_new_transaction(id, dn); |
442 |
txn = cache_new_transaction(id, dn); |
430 |
if (dbtxnp == NULL) { |
443 |
if (txn == NULL) { |
431 |
signals_unblock(); |
444 |
signals_unblock(); |
432 |
free(data.data); |
|
|
433 |
return 1; |
445 |
return 1; |
434 |
} |
446 |
} |
435 |
#else |
447 |
#else |
436 |
dbtxnp = NULL; |
448 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction begin (cache_update_entry)"); |
|
|
449 |
if ((rv = mdb_txn_begin(env, NULL, 0, &txn)) != 0) { |
450 |
cache_error_message(rv, "mdb_txn_begin"); |
451 |
signals_unblock(); |
452 |
return rv; |
453 |
} |
437 |
#endif |
454 |
#endif |
438 |
|
455 |
|
439 |
key.data=dn; |
456 |
key.mv_data=dn; |
440 |
key.size=strlen(dn)+1; |
457 |
key.mv_size=strlen(dn)+1; |
441 |
|
458 |
|
442 |
if ((rv=dbp->put(dbp, dbtxnp, &key, &data, 0)) != 0) { |
459 |
if ((rv = mdb_put(txn, dbi, &key, &data, 0)) != 0) { |
443 |
signals_unblock(); |
460 |
signals_unblock(); |
444 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
461 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
445 |
"storing entry in database failed: %s", dn); |
462 |
"storing entry in database failed: %s", dn); |
446 |
dbp->err(dbp, rv, "put"); |
463 |
cache_error_message(rv, "mdb_put"); |
447 |
#ifdef WITH_DB42 |
464 |
mdb_txn_abort(txn); |
448 |
dbtxnp->abort(dbtxnp); |
|
|
449 |
#endif |
450 |
free(data.data); |
451 |
return rv; |
465 |
return rv; |
452 |
} |
466 |
} |
453 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "put %d bytes for %s", data.size, dn); |
467 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "put %zu bytes for %s", data.mv_size, dn); |
454 |
|
468 |
|
455 |
|
469 |
|
456 |
#ifdef WITH_DB42 |
470 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction commit (cache_update_entry)"); |
457 |
dbtxnp->commit(dbtxnp, 0); |
471 |
if ((rv = mdb_txn_commit(txn)) != 0) { |
458 |
#endif |
472 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
459 |
cache_sync(); |
473 |
"storing updated entry in database failed"); |
|
|
474 |
cache_error_message(rv, "mdb_txn_commit"); |
475 |
return rv; |
476 |
} |
477 |
|
460 |
signals_unblock(); |
478 |
signals_unblock(); |
461 |
|
479 |
|
462 |
free(data.data); |
|
|
463 |
return rv; |
480 |
return rv; |
464 |
} |
481 |
} |
465 |
|
482 |
|
|
482 |
|
499 |
|
483 |
int cache_delete_entry(NotifierID id, char *dn) |
500 |
int cache_delete_entry(NotifierID id, char *dn) |
484 |
{ |
501 |
{ |
485 |
DB_TXN *dbtxnp; |
502 |
MDB_txn *txn; |
486 |
DBT key; |
503 |
MDB_val key; |
487 |
int rv; |
504 |
int rv; |
488 |
|
505 |
|
489 |
memset(&key, 0, sizeof(DBT)); |
506 |
memset(&key, 0, sizeof(MDB_val)); |
490 |
|
507 |
|
491 |
key.data=dn; |
508 |
key.mv_data=dn; |
492 |
key.size=strlen(dn)+1; |
509 |
key.mv_size=strlen(dn)+1; |
493 |
|
510 |
|
494 |
signals_block(); |
511 |
signals_block(); |
495 |
#ifdef WITH_DB42 |
512 |
#ifdef WITH_DB42 |
496 |
dbtxnp = cache_new_transaction(id, dn); |
513 |
txn = cache_new_transaction(id, dn); |
497 |
if (dbtxnp == NULL) { |
514 |
if (txn == NULL) { |
498 |
signals_unblock(); |
515 |
signals_unblock(); |
499 |
return 1; |
516 |
return 1; |
500 |
} |
517 |
} |
501 |
#else |
518 |
#else |
502 |
dbtxnp = NULL; |
519 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction begin (cache_delete_entry)"); |
|
|
520 |
if ((rv = mdb_txn_begin(env, NULL, 0, &txn)) != 0) { |
521 |
cache_error_message(rv, "mdb_txn_begin"); |
522 |
return rv; |
523 |
} |
503 |
#endif |
524 |
#endif |
504 |
|
525 |
|
505 |
if ((rv=dbp->del(dbp, dbtxnp, &key, 0)) != 0 && rv != DB_NOTFOUND) { |
526 |
if ((rv = mdb_del(txn, dbi, &key, 0)) != 0 && rv != MDB_NOTFOUND) { |
506 |
signals_unblock(); |
527 |
signals_unblock(); |
507 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
528 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
508 |
"removing from database failed: %s", dn); |
529 |
"removing from database failed: %s", dn); |
509 |
dbp->err(dbp, rv, "del"); |
530 |
cache_error_message(rv, "mdb_del"); |
|
|
531 |
mdb_txn_abort(txn); |
532 |
return rv; |
510 |
} |
533 |
} |
511 |
|
534 |
|
512 |
#ifdef WITH_DB42 |
535 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction commit (cache_delete_entry)"); |
513 |
dbtxnp->commit(dbtxnp, 0); |
536 |
if ((rv = mdb_txn_commit(txn)) != 0) { |
514 |
#endif |
537 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
515 |
cache_sync(); |
538 |
"storing entry removal from database failed"); |
|
|
539 |
cache_error_message(rv, "mdb_txn_commit"); |
540 |
return rv; |
541 |
} |
516 |
signals_unblock(); |
542 |
signals_unblock(); |
517 |
|
543 |
|
518 |
return rv; |
544 |
return rv; |
|
551 |
|
577 |
|
552 |
int cache_get_entry(char *dn, CacheEntry *entry) |
578 |
int cache_get_entry(char *dn, CacheEntry *entry) |
553 |
{ |
579 |
{ |
554 |
DBT key, data; |
580 |
MDB_txn *txn; |
|
|
581 |
MDB_val key, data; |
555 |
int rv = 0; |
582 |
int rv = 0; |
556 |
|
583 |
|
557 |
memset(&key, 0, sizeof(DBT)); |
584 |
memset(&key, 0, sizeof(MDB_val)); |
558 |
memset(&data, 0, sizeof(DBT)); |
585 |
memset(&data, 0, sizeof(MDB_val)); |
559 |
memset(entry, 0, sizeof(CacheEntry)); |
586 |
memset(entry, 0, sizeof(CacheEntry)); |
560 |
|
587 |
|
561 |
key.data=dn; |
588 |
key.mv_data=dn; |
562 |
key.size=strlen(dn)+1; |
589 |
key.mv_size=strlen(dn)+1; |
563 |
data.flags = DB_DBT_REALLOC; |
|
|
564 |
|
590 |
|
|
|
591 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction begin (cache_get_entry)"); |
592 |
if ((rv = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)) != 0) { |
593 |
cache_error_message(rv, "mdb_txn_begin"); |
594 |
return rv; |
595 |
} |
565 |
signals_block(); |
596 |
signals_block(); |
566 |
rv=dbp->get(dbp, NULL, &key, &data, 0); |
597 |
rv = mdb_get(txn, dbi, &key, &data); |
567 |
signals_unblock(); |
598 |
signals_unblock(); |
|
|
599 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction abort (cache_get_entry)"); |
600 |
mdb_txn_abort(txn); |
568 |
|
601 |
|
569 |
if (rv != 0 && rv != DB_NOTFOUND) { |
602 |
if (rv != 0 && rv != MDB_NOTFOUND) { |
570 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
603 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
571 |
"reading %s from database failed", dn); |
604 |
"reading %s from database failed", dn); |
572 |
dbp->err(dbp, rv, "get"); |
605 |
cache_error_message(rv, "mdb_get"); |
573 |
return rv; |
606 |
return rv; |
574 |
} else if (rv == DB_NOTFOUND) { |
607 |
} else if (rv == MDB_NOTFOUND) { |
575 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "no cache entry found for %s", |
608 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "no cache entry found for %s", |
576 |
dn); |
609 |
dn); |
577 |
return rv; |
610 |
return rv; |
578 |
} |
611 |
} |
579 |
|
612 |
|
580 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "got %d bytes for %s", |
613 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "got %zu bytes for %s", |
581 |
data.size, dn); |
614 |
data.mv_size, dn); |
582 |
|
615 |
|
583 |
if ((rv=parse_entry(data.data, data.size, entry)) != 0) { |
616 |
if ((rv=parse_entry(data.mv_data, data.mv_size, entry)) != 0) { |
584 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
617 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
585 |
"parsing entry failed"); |
618 |
"parsing entry failed"); |
586 |
free(data.data); |
|
|
587 |
exit(1); |
619 |
exit(1); |
588 |
} |
620 |
} |
589 |
|
621 |
|
590 |
free(data.data); |
|
|
591 |
return rv; |
622 |
return rv; |
592 |
} |
623 |
} |
593 |
|
624 |
|
|
604 |
} |
635 |
} |
605 |
|
636 |
|
606 |
rv = cache_get_entry(lower_dn, entry); |
637 |
rv = cache_get_entry(lower_dn, entry); |
607 |
if (rv == DB_NOTFOUND && mixedcase ) { |
638 |
if (rv == MDB_NOTFOUND && mixedcase ) { |
608 |
// try again with original dn |
639 |
// try again with original dn |
609 |
rv = cache_get_entry(dn, entry); |
640 |
rv = cache_get_entry(dn, entry); |
610 |
} |
641 |
} |
|
613 |
return rv; |
644 |
return rv; |
614 |
} |
645 |
} |
615 |
|
646 |
|
616 |
int cache_first_entry(DBC **cur, char **dn, CacheEntry *entry) |
647 |
int cache_first_entry(MDB_cursor **cursor, char **dn, CacheEntry *entry) |
617 |
{ |
648 |
{ |
|
|
649 |
MDB_txn *txn; |
618 |
int rv; |
650 |
int rv; |
619 |
|
651 |
|
620 |
if ((rv=dbp->cursor(dbp, NULL, cur, 0)) != 0) { |
652 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction begin (cache_first_entry)"); |
621 |
dbp->err(dbp, rv, "cursor"); |
653 |
if ((rv = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)) != 0) { |
|
|
654 |
cache_error_message(rv, "mdb_txn_begin"); |
622 |
return rv; |
655 |
return rv; |
623 |
} |
656 |
} |
|
|
657 |
if ((rv = mdb_cursor_open(txn, dbi, cursor)) != 0) { |
658 |
cache_error_message(rv, "mdb_cursor_open"); |
659 |
mdb_txn_abort(txn); |
660 |
return rv; |
661 |
} |
624 |
|
662 |
|
625 |
return cache_next_entry(cur, dn, entry); |
663 |
/* |
|
|
664 |
// mdb_reader_list(env, &mdb_message_func, NULL); |
665 |
MDB_envinfo stat; |
666 |
MDB_env *env = mdb_txn_env(txn); |
667 |
mdb_env_info(env, &stat); |
668 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "LAST COMMITTED TXN: %zu", stat.me_last_txnid); |
669 |
*/ |
670 |
|
671 |
return cache_next_entry(cursor, dn, entry); |
626 |
} |
672 |
} |
627 |
|
673 |
|
628 |
int cache_print_entries(char *dn) |
674 |
int cache_print_entries(char *dn) |
629 |
{ |
675 |
{ |
630 |
DBT key, data; |
676 |
MDB_txn *txn; |
631 |
DBC *cur; |
677 |
MDB_val key, data; |
632 |
memset(&key, 0, sizeof(DBT)); |
678 |
MDB_cursor *cursor; |
633 |
memset(&data, 0, sizeof(DBT)); |
679 |
int rv = 0; |
634 |
key.data = strdup(dn); |
|
|
635 |
key.size = strlen(dn)+1; |
636 |
key.flags = DB_DBT_REALLOC; |
637 |
data.flags = DB_DBT_REALLOC; |
638 |
|
680 |
|
639 |
dbp->cursor(dbp, NULL, &cur, 0); |
681 |
memset(&key, 0, sizeof(MDB_val)); |
640 |
cur->c_get(cur, &key, &data, DB_FIRST); |
682 |
memset(&data, 0, sizeof(MDB_val)); |
|
|
683 |
key.mv_data = strdup(dn); |
684 |
key.mv_size = strlen(dn)+1; |
685 |
|
686 |
if ((rv = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)) != 0) { |
687 |
cache_error_message(rv, "mdb_txn_begin"); |
688 |
return rv; |
689 |
} |
690 |
if ((rv = mdb_cursor_open(txn, dbi, &cursor)) != 0) { |
691 |
cache_error_message(rv, "mdb_cursor_open"); |
692 |
mdb_txn_abort(txn); |
693 |
return rv; |
694 |
} |
695 |
rv = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); |
641 |
do { |
696 |
do { |
642 |
printf("%s\n", (char*)key.data); |
697 |
if (rv != 0) { |
643 |
} while (cur->c_get(cur, &key, &data, DB_NEXT) == 0); |
698 |
cache_error_message(rv, "mdb_cursor_get"); |
|
|
699 |
mdb_txn_abort(txn); |
700 |
return rv; |
701 |
} |
702 |
printf("%s\n", (char*)key.mv_data); |
703 |
} while ((rv = mdb_cursor_get(cursor, &key, &data, MDB_NEXT))); |
644 |
|
704 |
|
645 |
cur->c_close(cur); |
705 |
mdb_cursor_close(cursor); |
646 |
free(key.data); |
706 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction abort (cache_print_entries)"); |
647 |
free(data.data); |
707 |
mdb_txn_abort(txn); |
648 |
return 0; |
708 |
return 0; |
649 |
} |
709 |
} |
650 |
|
710 |
|
651 |
int cache_next_entry(DBC **cur, char **dn, CacheEntry *entry) |
711 |
int cache_next_entry(MDB_cursor **cursor, char **dn, CacheEntry *entry) |
652 |
{ |
712 |
{ |
653 |
DBT key, data; |
713 |
MDB_val key, data; |
654 |
int rv; |
714 |
int rv; |
655 |
|
715 |
|
656 |
memset(&key, 0, sizeof(DBT)); |
716 |
memset(&key, 0, sizeof(MDB_val)); |
657 |
key.flags = DB_DBT_REALLOC; |
717 |
memset(&data, 0, sizeof(MDB_val)); |
658 |
memset(&data, 0, sizeof(DBT)); |
|
|
659 |
data.flags = DB_DBT_REALLOC; |
660 |
|
718 |
|
661 |
if ((rv=(*cur)->c_get(*cur, &key, &data, DB_NEXT)) == DB_NOTFOUND) { |
719 |
if ((rv=mdb_cursor_get(*cursor, &key, &data, MDB_NEXT)) == MDB_NOTFOUND) { |
662 |
return rv; |
720 |
return rv; |
663 |
} else if (rv != 0) { |
721 |
} else if (rv != 0) { |
664 |
dbp->err(dbp, rv, "c_get"); |
722 |
cache_error_message(rv, "mdb_cursor_get"); |
665 |
return rv; |
723 |
return rv; |
666 |
} |
724 |
} |
667 |
|
725 |
|
668 |
/* skip master entry */ |
726 |
/* skip master entry */ |
669 |
if (strcmp(key.data, MASTER_KEY) == 0) { |
727 |
if (strcmp(key.mv_data, MASTER_KEY) == 0) { |
670 |
free(key.data); |
728 |
return cache_next_entry(cursor, dn, entry); |
671 |
free(data.data); |
|
|
672 |
return cache_next_entry(cur, dn, entry); |
673 |
} |
729 |
} |
674 |
|
730 |
|
675 |
if (*dn) |
731 |
if (*dn) |
676 |
free(*dn); |
732 |
free(*dn); |
677 |
*dn = strdup(key.data); |
733 |
*dn = strdup(key.mv_data); |
678 |
|
734 |
|
679 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "got %d bytes", data.size); |
735 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "got %zu bytes", data.mv_size); |
680 |
|
736 |
|
681 |
if ((rv=parse_entry(data.data, data.size, entry)) != 0) { |
737 |
if ((rv=parse_entry(data.mv_data, data.mv_size, entry)) != 0) { |
682 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
738 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
683 |
"parsing entry failed: %s", *dn); |
739 |
"parsing entry failed: %s", *dn); |
684 |
printf("%d\n", data.size); |
740 |
printf("%zu\n", data.mv_size); |
685 |
free(key.data); |
|
|
686 |
free(data.data); |
687 |
return rv; |
741 |
return rv; |
688 |
} |
742 |
} |
689 |
|
743 |
|
690 |
free(key.data); |
|
|
691 |
free(data.data); |
692 |
|
693 |
return 0; |
744 |
return 0; |
694 |
} |
745 |
} |
695 |
|
746 |
|
696 |
int cache_free_cursor(DBC *cur) |
747 |
int cache_free_cursor(MDB_cursor *cursor) |
697 |
{ |
748 |
{ |
698 |
return cur->c_close(cur); |
749 |
int rv; |
|
|
750 |
MDB_txn *txn; |
751 |
|
752 |
/* |
753 |
// mdb_reader_list(env, &mdb_message_func, NULL); |
754 |
MDB_envinfo stat; |
755 |
MDB_env *env = mdb_txn_env(txn); |
756 |
mdb_env_info(env, &stat); |
757 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "LAST COMMITTED TXN: %zu", stat.me_last_txnid); |
758 |
*/ |
759 |
|
760 |
txn = mdb_cursor_txn(cursor); |
761 |
mdb_cursor_close(cursor); |
762 |
|
763 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ALL, "Transaction commit (cache_free_cursor)"); |
764 |
if ((rv = mdb_txn_commit(txn)) != 0) { |
765 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
766 |
"Transation commit failed"); |
767 |
cache_error_message(rv, "mdb_txn_commit"); |
768 |
} |
769 |
return rv; |
699 |
} |
770 |
} |
700 |
|
771 |
|
701 |
int cache_close(void) |
772 |
void cache_close(void) |
702 |
{ |
773 |
{ |
703 |
int rv; |
774 |
mdb_close(env, dbi); |
|
|
775 |
mdb_env_close(env); |
704 |
|
776 |
|
705 |
if (dbp && (rv = dbp->close(dbp, 0)) != 0) { |
|
|
706 |
dbp->err(dbp, rv, "close"); |
707 |
} |
708 |
dbp = NULL; |
709 |
#ifdef WITH_DB42 |
710 |
if ((rv = dbenvp->close(dbenvp, 0)) != 0) { |
711 |
univention_debug(UV_DEBUG_LISTENER, UV_DEBUG_ERROR, |
712 |
"closing database environment failed"); |
713 |
} |
714 |
#endif |
715 |
if (lock_fp != NULL) { |
777 |
if (lock_fp != NULL) { |
716 |
fclose(lock_fp); |
778 |
fclose(lock_fp); |
717 |
lock_fp = NULL; |
779 |
lock_fp = NULL; |
718 |
} |
780 |
} |
719 |
return rv; |
|
|
720 |
} |
781 |
} |