From 58898092c1ce043f6d698db5065f372b79109e22 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 3 Jul 2006 06:40:56 +0000 Subject: [PATCH] r16774: This patch modifies the tdb API to allow the logging function to be used as part of ldb. This allows tdb failures to be passed all the way up to Samba's DEBUG system, which allowed easier debugging. Unfortunately I had to extend the tdb API, as the logging function didn't have a context pointer. I've worked over the 'debug levels' in TDB. Most of them were 0, which didn't seem right, as some were trace-like messages. We didn't see any of these previously, except when accessing TDB directly. Andrew Bartlett --- source/lib/db_wrap.c | 26 ++++++-- source/lib/ldb/ldb_tdb/ldb_tdb.c | 4 +- source/lib/ldb/ldb_tdb/ldb_tdb.h | 3 +- source/lib/ldb/ldb_tdb/ldb_tdb_wrap.c | 42 ++++++++++++- source/lib/tdb/common/freelist.c | 22 +++---- source/lib/tdb/common/io.c | 20 +++---- source/lib/tdb/common/lock.c | 14 ++--- source/lib/tdb/common/open.c | 57 ++++++++++-------- source/lib/tdb/common/tdb.c | 2 +- source/lib/tdb/common/tdb_private.h | 3 +- source/lib/tdb/common/transaction.c | 86 +++++++++++++-------------- source/lib/tdb/common/traverse.c | 20 +++---- source/lib/tdb/include/tdb.h | 12 +++- source/lib/tdb/tools/tdbtool.c | 10 ++-- source/lib/tdb/tools/tdbtorture.c | 6 +- 15 files changed, 198 insertions(+), 129 deletions(-) diff --git a/source/lib/db_wrap.c b/source/lib/db_wrap.c index 43ad3d0faed..4a21648403b 100644 --- a/source/lib/db_wrap.c +++ b/source/lib/db_wrap.c @@ -144,22 +144,40 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx, /* Log tdb messages via DEBUG(). */ -static void tdb_wrap_log(TDB_CONTEXT *tdb, int level, +static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); -static void tdb_wrap_log(TDB_CONTEXT *tdb, int level, +static void tdb_wrap_log(TDB_CONTEXT *tdb, enum tdb_debug_level level, const char *format, ...) { va_list ap; char *ptr = NULL; + int debug_level; va_start(ap, format); vasprintf(&ptr, format, ap); va_end(ap); + switch (level) { + case TDB_DEBUG_FATAL: + debug_level = 0; + break; + case TDB_DEBUG_ERROR: + debug_level = 1; + break; + case TDB_DEBUG_WARNING: + debug_level = 2; + break; + case TDB_DEBUG_TRACE: + debug_level = 5; + break; + default: + debug_level = 0; + } + if (ptr != NULL) { const char *name = tdb_name(tdb); - DEBUG(level, ("tdb(%s): %s", name ? name : "unnamed", ptr)); + DEBUG(debug_level, ("tdb(%s): %s", name ? name : "unnamed", ptr)); free(ptr); } } @@ -197,7 +215,7 @@ struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx, w->name = talloc_strdup(w, name); w->tdb = tdb_open_ex(name, hash_size, tdb_flags, - open_flags, mode, tdb_wrap_log, NULL); + open_flags, mode, tdb_wrap_log, NULL, NULL); if (w->tdb == NULL) { talloc_free(w); return NULL; diff --git a/source/lib/ldb/ldb_tdb/ldb_tdb.c b/source/lib/ldb/ldb_tdb/ldb_tdb.c index c6b0ab4c633..15f34db5e15 100644 --- a/source/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source/lib/ldb/ldb_tdb/ldb_tdb.c @@ -969,7 +969,6 @@ static const struct ldb_module_ops ltdb_ops = { .sequence_number = ltdb_sequence_number }; - /* connect to the database */ @@ -1012,7 +1011,8 @@ static int ltdb_connect(struct ldb_context *ldb, const char *url, } /* note that we use quite a large default hash size */ - ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000, tdb_flags, open_flags, 0666); + ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000, + tdb_flags, open_flags, 0666, ldb); if (!ltdb->tdb) { ldb_debug(ldb, LDB_DEBUG_ERROR, "Unable to open tdb '%s'\n", path); talloc_free(ltdb); diff --git a/source/lib/ldb/ldb_tdb/ldb_tdb.h b/source/lib/ldb/ldb_tdb/ldb_tdb.h index 0c44a80edd8..069a07d3193 100644 --- a/source/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source/lib/ldb/ldb_tdb/ldb_tdb.h @@ -116,5 +116,6 @@ int ltdb_index_del_value(struct ldb_module *module, const char *dn, struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx, const char *path, int hash_size, int tdb_flags, - int open_flags, mode_t mode); + int open_flags, mode_t mode, + struct ldb_context *ldb); diff --git a/source/lib/ldb/ldb_tdb/ldb_tdb_wrap.c b/source/lib/ldb/ldb_tdb/ldb_tdb_wrap.c index fdce36b24ca..31276d39487 100644 --- a/source/lib/ldb/ldb_tdb/ldb_tdb_wrap.c +++ b/source/lib/ldb/ldb_tdb/ldb_tdb_wrap.c @@ -58,6 +58,40 @@ static int ltdb_wrap_destructor(struct ltdb_wrap *w) return 0; } +static void ltdb_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); +static void ltdb_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) +{ + va_list ap; + const char *name = tdb_name(tdb); + struct ldb_context *ldb = talloc_get_type(tdb_logging_private(tdb), struct ldb_context); + enum ldb_debug_level ldb_level; + char *message; + va_start(ap, fmt); + message = talloc_vasprintf(ldb, fmt, ap); + va_end(ap); + + switch (level) { + case TDB_DEBUG_FATAL: + ldb_level = LDB_DEBUG_FATAL; + break; + case TDB_DEBUG_ERROR: + ldb_level = LDB_DEBUG_ERROR; + break; + case TDB_DEBUG_WARNING: + ldb_level = LDB_DEBUG_WARNING; + break; + case TDB_DEBUG_TRACE: + ldb_level = LDB_DEBUG_TRACE; + break; + default: + ldb_level = LDB_DEBUG_FATAL; + } + + ldb_debug(ldb, ldb_level, "ltdb: tdb(%s): %s", name, message); + talloc_free(message); +} + + /* wrapped connection to a tdb database. The caller should _not_ free this as it is not a talloc structure (as tdb does not use talloc @@ -65,8 +99,10 @@ static int ltdb_wrap_destructor(struct ltdb_wrap *w) passed to this call */ struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx, - const char *path, int hash_size, int tdb_flags, - int open_flags, mode_t mode) + const char *path, int hash_size, + int tdb_flags, + int open_flags, mode_t mode, + struct ldb_context *ldb) { struct ltdb_wrap *w; struct stat st; @@ -85,7 +121,7 @@ struct tdb_context *ltdb_wrap_open(TALLOC_CTX *mem_ctx, return NULL; } - w->tdb = tdb_open(path, hash_size, tdb_flags, open_flags, mode); + w->tdb = tdb_open_ex(path, hash_size, tdb_flags, open_flags, mode, ltdb_log_fn, ldb, NULL); if (w->tdb == NULL) { talloc_free(w); return NULL; diff --git a/source/lib/tdb/common/freelist.c b/source/lib/tdb/common/freelist.c index 34837511647..9d1ae59801d 100644 --- a/source/lib/tdb/common/freelist.c +++ b/source/lib/tdb/common/freelist.c @@ -37,7 +37,7 @@ static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_str if (rec->magic == TDB_MAGIC) { /* this happens when a app is showdown while deleting a record - we should not completely fail when this happens */ - TDB_LOG((tdb, 0,"rec_free_read non-free magic 0x%x at offset=%d - fixing\n", + TDB_LOG((tdb, TDB_DEBUG_WARNING, "rec_free_read non-free magic 0x%x at offset=%d - fixing\n", rec->magic, off)); rec->magic = TDB_FREE_MAGIC; if (tdb->methods->tdb_write(tdb, off, rec, sizeof(*rec)) == -1) @@ -47,7 +47,7 @@ static int rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_str if (rec->magic != TDB_FREE_MAGIC) { /* Ensure ecode is set for log fn. */ tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, 0,"rec_free_read bad magic 0x%x at offset=%d\n", + TDB_LOG((tdb, TDB_DEBUG_WARNING, "rec_free_read bad magic 0x%x at offset=%d\n", rec->magic, off)); return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); } @@ -73,7 +73,7 @@ static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_ /* Follow chain (next offset is at start of record) */ last_ptr = i; } - TDB_LOG((tdb, 0,"remove_from_freelist: not on list at off=%d\n", off)); + TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off)); return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); } @@ -102,7 +102,7 @@ int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) /* set an initial tailer, so if we fail we don't leave a bogus record */ if (update_tailer(tdb, offset, rec) != 0) { - TDB_LOG((tdb, 0, "tdb_free: upfate_tailer failed!\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed!\n")); goto fail; } @@ -112,14 +112,14 @@ int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct list_struct *rec) struct list_struct r; if (tdb->methods->tdb_read(tdb, right, &r, sizeof(r), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_free: right read failed at %u\n", right)); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right read failed at %u\n", right)); goto left; } /* If it's free, expand to include it. */ if (r.magic == TDB_FREE_MAGIC) { if (remove_from_freelist(tdb, right, r.next) == -1) { - TDB_LOG((tdb, 0, "tdb_free: right free failed at %u\n", right)); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: right free failed at %u\n", right)); goto left; } rec->rec_len += sizeof(r) + r.rec_len; @@ -135,7 +135,7 @@ left: /* Read in tailer and jump back to header */ if (tdb_ofs_read(tdb, left, &leftsize) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left offset read failed at %u\n", left)); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left offset read failed at %u\n", left)); goto update; } @@ -148,14 +148,14 @@ left: /* Now read in record */ if (tdb->methods->tdb_read(tdb, left, &l, sizeof(l), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left read failed at %u (%u)\n", left, leftsize)); goto update; } /* If it's free, expand to include it. */ if (l.magic == TDB_FREE_MAGIC) { if (remove_from_freelist(tdb, left, l.next) == -1) { - TDB_LOG((tdb, 0, "tdb_free: left free failed at %u\n", left)); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: left free failed at %u\n", left)); goto update; } else { offset = left; @@ -166,7 +166,7 @@ left: update: if (update_tailer(tdb, offset, rec) == -1) { - TDB_LOG((tdb, 0, "tdb_free: update_tailer failed at %u\n", offset)); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free: update_tailer failed at %u\n", offset)); goto fail; } @@ -176,7 +176,7 @@ update: if (tdb_ofs_read(tdb, FREELIST_TOP, &rec->next) == -1 || tdb_rec_write(tdb, offset, rec) == -1 || tdb_ofs_write(tdb, FREELIST_TOP, &offset) == -1) { - TDB_LOG((tdb, 0, "tdb_free record write failed at offset=%d\n", offset)); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_free record write failed at offset=%d\n", offset)); goto fail; } diff --git a/source/lib/tdb/common/io.c b/source/lib/tdb/common/io.c index f4f866a4c4e..21d591b67d3 100644 --- a/source/lib/tdb/common/io.c +++ b/source/lib/tdb/common/io.c @@ -65,7 +65,7 @@ static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) if (!probe) { /* Ensure ecode is set for log fn. */ tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_oob len %d beyond internal malloc size %d\n", + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond internal malloc size %d\n", (int)len, (int)tdb->map_size)); } return TDB_ERRCODE(TDB_ERR_IO, -1); @@ -79,7 +79,7 @@ static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) if (!probe) { /* Ensure ecode is set for log fn. */ tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_oob len %d beyond eof at %d\n", + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_oob len %d beyond eof at %d\n", (int)len, (int)st.st_size)); } return TDB_ERRCODE(TDB_ERR_IO, -1); @@ -114,7 +114,7 @@ static int tdb_write(struct tdb_context *tdb, tdb_off_t off, } else if (pwrite(tdb->fd, buf, len, off) != (ssize_t)len) { /* Ensure ecode is set for log fn. */ tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_write failed at %d len=%d (%s)\n", + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_write failed at %d len=%d (%s)\n", off, len, strerror(errno))); return TDB_ERRCODE(TDB_ERR_IO, -1); } @@ -146,7 +146,7 @@ static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, if (ret != (ssize_t)len) { /* Ensure ecode is set for log fn. */ tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0,"tdb_read failed at %d len=%d ret=%d (%s) map_size=%d\n", + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_read failed at %d len=%d ret=%d (%s) map_size=%d\n", off, len, ret, strerror(errno), tdb->map_size)); return TDB_ERRCODE(TDB_ERR_IO, -1); } @@ -217,7 +217,7 @@ void tdb_mmap(struct tdb_context *tdb) if (tdb->map_ptr == MAP_FAILED) { tdb->map_ptr = NULL; - TDB_LOG((tdb, 2, "tdb_mmap failed for size %d (%s)\n", + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_mmap failed for size %d (%s)\n", tdb->map_size, strerror(errno))); } } else { @@ -242,7 +242,7 @@ static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t ad if (ftruncate(tdb->fd, size+addition) == -1) { char b = 0; if (pwrite(tdb->fd, &b, 1, (size+addition) - 1) != 1) { - TDB_LOG((tdb, 0, "expand_file to %d failed (%s)\n", + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file to %d failed (%s)\n", size+addition, strerror(errno))); return -1; } @@ -256,7 +256,7 @@ static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t ad int n = addition>sizeof(buf)?sizeof(buf):addition; int ret = pwrite(tdb->fd, buf, n, size); if (ret != n) { - TDB_LOG((tdb, 0, "expand_file write of %d failed (%s)\n", + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of %d failed (%s)\n", n, strerror(errno))); return -1; } @@ -275,7 +275,7 @@ int tdb_expand(struct tdb_context *tdb, tdb_off_t size) tdb_off_t offset; if (tdb_lock(tdb, -1, F_WRLCK) == -1) { - TDB_LOG((tdb, 0, "lock failed in tdb_expand\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "lock failed in tdb_expand\n")); return -1; } @@ -363,7 +363,7 @@ unsigned char *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len if (!(buf = malloc(len))) { /* Ensure ecode is set for log fn. */ tdb->ecode = TDB_ERR_OOM; - TDB_LOG((tdb, 0,"tdb_alloc_read malloc failed len=%d (%s)\n", + TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_alloc_read malloc failed len=%d (%s)\n", len, strerror(errno))); return TDB_ERRCODE(TDB_ERR_OOM, buf); } @@ -382,7 +382,7 @@ int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct list_struct * if (TDB_BAD_MAGIC(rec)) { /* Ensure ecode is set for log fn. */ tdb->ecode = TDB_ERR_CORRUPT; - TDB_LOG((tdb, 0,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); + TDB_LOG((tdb, TDB_DEBUG_FATAL,"tdb_rec_read bad magic 0x%x at offset=%d\n", rec->magic, offset)); return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); } return tdb->methods->tdb_oob(tdb, rec->next+sizeof(*rec), 0); diff --git a/source/lib/tdb/common/lock.c b/source/lib/tdb/common/lock.c index 976cf2cfa09..821fd351861 100644 --- a/source/lib/tdb/common/lock.c +++ b/source/lib/tdb/common/lock.c @@ -68,7 +68,7 @@ int tdb_brlock_len(struct tdb_context *tdb, tdb_off_t offset, if (!probe && lck_type != F_SETLK) { /* Ensure error code is set for log fun to examine. */ tdb->ecode = TDB_ERR_LOCK; - TDB_LOG((tdb, 5,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n", + TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n", tdb->fd, offset, rw_type, lck_type, len)); } return TDB_ERRCODE(TDB_ERR_LOCK, -1); @@ -99,7 +99,7 @@ int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len) tv.tv_usec = 1; select(0, NULL, NULL, NULL, &tv); } - TDB_LOG((tdb, 5,"tdb_brlock_upgrade failed at offset %d\n", offset)); + TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock_upgrade failed at offset %d\n", offset)); return -1; } @@ -119,7 +119,7 @@ int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int tdb_lock(struct tdb_context *tdb, int list, int ltype) { if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, 0,"tdb_lock: invalid list %d for ltype=%d\n", + TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n", list, ltype)); return -1; } @@ -130,7 +130,7 @@ int tdb_lock(struct tdb_context *tdb, int list, int ltype) and simply bump the count for future ones */ if (tdb->locked[list+1].count == 0) { if (tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list,ltype,F_SETLKW, 0)) { - TDB_LOG((tdb, 0,"tdb_lock failed on list %d ltype=%d (%s)\n", + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d ltype=%d (%s)\n", list, ltype, strerror(errno))); return -1; } @@ -153,12 +153,12 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype) /* Sanity checks */ if (list < -1 || list >= (int)tdb->header.hash_size) { - TDB_LOG((tdb, 0, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size)); return ret; } if (tdb->locked[list+1].count==0) { - TDB_LOG((tdb, 0, "tdb_unlock: count is 0\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n")); return ret; } @@ -172,7 +172,7 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype) tdb->locked[list+1].count--; if (ret) - TDB_LOG((tdb, 0,"tdb_unlock: An error occurred unlocking!\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: An error occurred unlocking!\n")); return ret; } diff --git a/source/lib/tdb/common/open.c b/source/lib/tdb/common/open.c index cb4a9cd9945..c8f836490b4 100644 --- a/source/lib/tdb/common/open.c +++ b/source/lib/tdb/common/open.c @@ -119,19 +119,20 @@ static int tdb_already_open(dev_t device, struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode) { - return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL); + return tdb_open_ex(name, hash_size, tdb_flags, open_flags, mode, NULL, NULL, NULL); } /* a default logging function */ -static void null_log_fn(struct tdb_context *tdb, int level, const char *fmt, ...) +static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); +static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) { } struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode, - tdb_log_func log_fn, - tdb_hash_func hash_fn) + int open_flags, mode_t mode, + tdb_log_func log_fn, void *log_private, + tdb_hash_func hash_fn) { struct tdb_context *tdb; struct stat st; @@ -151,6 +152,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, tdb->flags = tdb_flags; tdb->open_flags = open_flags; tdb->log_fn = log_fn?log_fn:null_log_fn; + tdb->log_private = log_fn?log_private:NULL; tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; /* cache the page size */ @@ -160,7 +162,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, } if ((open_flags & O_ACCMODE) == O_WRONLY) { - TDB_LOG((tdb, 0, "tdb_open_ex: can't open tdb %s write-only\n", + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't open tdb %s write-only\n", name)); errno = EINVAL; goto fail; @@ -180,21 +182,21 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, tdb->flags |= (TDB_NOLOCK | TDB_NOMMAP); tdb->flags &= ~TDB_CLEAR_IF_FIRST; if (tdb_new_database(tdb, hash_size) != 0) { - TDB_LOG((tdb, 0, "tdb_open_ex: tdb_new_database failed!")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: tdb_new_database failed!")); goto fail; } goto internal; } if ((tdb->fd = open(name, open_flags, mode)) == -1) { - TDB_LOG((tdb, 5, "tdb_open_ex: could not open file %s: %s\n", + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_open_ex: could not open file %s: %s\n", name, strerror(errno))); goto fail; /* errno set by open(2) */ } /* ensure there is only one process initialising at once */ if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: failed to get global lock on %s: %s\n", + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get global lock on %s: %s\n", name, strerror(errno))); goto fail; /* errno set by tdb_brlock */ } @@ -204,7 +206,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0) == 0))) { open_flags |= O_CREAT; if (ftruncate(tdb->fd, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: " + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: " "failed to truncate %s: %s\n", name, strerror(errno))); goto fail; /* errno set by ftruncate */ @@ -236,13 +238,13 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, goto fail; if (tdb->header.rwlocks != 0) { - TDB_LOG((tdb, 5, "tdb_open_ex: spinlocks no longer supported\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n")); goto fail; } /* Is it already in the open list? If so, fail. */ if (tdb_already_open(st.st_dev, st.st_ino)) { - TDB_LOG((tdb, 2, "tdb_open_ex: " + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " "%s (%d,%d) is already open in this process\n", name, (int)st.st_dev, (int)st.st_ino)); errno = EBUSY; @@ -259,7 +261,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, tdb->inode = st.st_ino; tdb->locked = calloc(tdb->header.hash_size+1, sizeof(tdb->locked[0])); if (!tdb->locked) { - TDB_LOG((tdb, 2, "tdb_open_ex: " + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " "failed to allocate lock structure for %s\n", name)); errno = ENOMEM; @@ -268,7 +270,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, tdb_mmap(tdb); if (locked) { if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_open_ex: " + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " "failed to take ACTIVE_LOCK on %s: %s\n", name, strerror(errno))); goto fail; @@ -316,7 +318,7 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, SAFE_FREE(tdb->name); if (tdb->fd != -1) if (close(tdb->fd) != 0) - TDB_LOG((tdb, 5, "tdb_open_ex: failed to close tdb->fd on error!\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n")); SAFE_FREE(tdb->locked); SAFE_FREE(tdb); errno = save_errno; @@ -364,11 +366,16 @@ int tdb_close(struct tdb_context *tdb) } /* register a loging function */ -void tdb_logging_function(struct tdb_context *tdb, void (*fn)(struct tdb_context *, int , const char *, ...)) +void tdb_logging_function(struct tdb_context *tdb, tdb_log_func log_fn, void *log_private) { - tdb->log_fn = fn?fn:null_log_fn; + tdb->log_fn = log_fn?log_fn:null_log_fn; + tdb->log_fn = log_fn?log_private:NULL; } +void *tdb_logging_private(struct tdb_context *tdb) +{ + return tdb->log_private; +} /* reopen a tdb - this can be used after a fork to ensure that we have an independent seek pointer from our parent and to re-establish locks */ @@ -381,37 +388,37 @@ int tdb_reopen(struct tdb_context *tdb) } if (tdb->num_locks != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: reopen not allowed with locks held\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n")); goto fail; } if (tdb->transaction != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: reopen not allowed inside a transaction\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed inside a transaction\n")); goto fail; } if (tdb_munmap(tdb) != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: munmap failed (%s)\n", strerror(errno))); goto fail; } if (close(tdb->fd) != 0) - TDB_LOG((tdb, 0, "tdb_reopen: WARNING closing tdb->fd failed!\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: WARNING closing tdb->fd failed!\n")); tdb->fd = open(tdb->name, tdb->open_flags & ~(O_CREAT|O_TRUNC), 0); if (tdb->fd == -1) { - TDB_LOG((tdb, 0, "tdb_reopen: open failed (%s)\n", strerror(errno))); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: open failed (%s)\n", strerror(errno))); goto fail; } if ((tdb->flags & TDB_CLEAR_IF_FIRST) && (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0) == -1)) { - TDB_LOG((tdb, 0, "tdb_reopen: failed to obtain active lock\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n")); goto fail; } if (fstat(tdb->fd, &st) != 0) { - TDB_LOG((tdb, 0, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: fstat failed (%s)\n", strerror(errno))); goto fail; } if (st.st_ino != tdb->inode || st.st_dev != tdb->device) { - TDB_LOG((tdb, 0, "tdb_reopen: file dev/inode has changed!\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: file dev/inode has changed!\n")); goto fail; } tdb_mmap(tdb); diff --git a/source/lib/tdb/common/tdb.c b/source/lib/tdb/common/tdb.c index b0411601eb4..2513eecfb12 100644 --- a/source/lib/tdb/common/tdb.c +++ b/source/lib/tdb/common/tdb.c @@ -236,7 +236,7 @@ static int tdb_delete_hash(struct tdb_context *tdb, TDB_DATA key, u32 hash) } if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_delete: WARNING tdb_unlock failed!\n")); + TDB_LOG((tdb, TDB_DEBUG_WARNING, "tdb_delete: WARNING tdb_unlock failed!\n")); return ret; } diff --git a/source/lib/tdb/common/tdb_private.h b/source/lib/tdb/common/tdb_private.h index d01a88695d8..90afb64b728 100644 --- a/source/lib/tdb/common/tdb_private.h +++ b/source/lib/tdb/common/tdb_private.h @@ -197,7 +197,8 @@ struct tdb_context { struct tdb_context *next; /* all tdbs to avoid multiple opens */ dev_t device; /* uniquely identifies this tdb */ ino_t inode; /* uniquely identifies this tdb */ - void (*log_fn)(struct tdb_context *tdb, int level, const char *, ...) PRINTF_ATTRIBUTE(3,4); /* logging function */ + tdb_log_func log_fn; + void *log_private; unsigned int (*hash_fn)(TDB_DATA *key); int open_flags; /* flags used in the open - needed by reopen */ unsigned int num_locks; /* number of chain locks held */ diff --git a/source/lib/tdb/common/transaction.c b/source/lib/tdb/common/transaction.c index 5ddeb69c47e..a6fa8a7f664 100644 --- a/source/lib/tdb/common/transaction.c +++ b/source/lib/tdb/common/transaction.c @@ -182,7 +182,7 @@ static int transaction_read(struct tdb_context *tdb, tdb_off_t off, void *buf, return tdb->transaction->io_methods->tdb_read(tdb, off, buf, len, cv); fail: - TDB_LOG((tdb, 0, "transaction_read: failed at off=%d len=%d\n", off, len)); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_read: failed at off=%d len=%d\n", off, len)); tdb->ecode = TDB_ERR_IO; tdb->transaction->transaction_error = 1; return -1; @@ -306,7 +306,7 @@ static int transaction_write(struct tdb_context *tdb, tdb_off_t off, return 0; fail: - TDB_LOG((tdb, 0, "transaction_write: failed at off=%d len=%d\n", off, len)); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "transaction_write: failed at off=%d len=%d\n", off, len)); tdb->ecode = TDB_ERR_IO; tdb->transaction->transaction_error = 1; return -1; @@ -380,7 +380,7 @@ int tdb_transaction_start(struct tdb_context *tdb) { /* some sanity checks */ if (tdb->read_only || (tdb->flags & TDB_INTERNAL) || tdb->traverse_read) { - TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction on a read-only or internal db\n")); tdb->ecode = TDB_ERR_EINVAL; return -1; } @@ -388,7 +388,7 @@ int tdb_transaction_start(struct tdb_context *tdb) /* cope with nested tdb_transaction_start() calls */ if (tdb->transaction != NULL) { tdb->transaction->nesting++; - TDB_LOG((tdb, 0, "tdb_transaction_start: nesting %d\n", + TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n", tdb->transaction->nesting)); return 0; } @@ -397,7 +397,7 @@ int tdb_transaction_start(struct tdb_context *tdb) /* the caller must not have any locks when starting a transaction as otherwise we'll be screwed by lack of nested locks in posix */ - TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction with locks held\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction with locks held\n")); tdb->ecode = TDB_ERR_LOCK; return -1; } @@ -406,7 +406,7 @@ int tdb_transaction_start(struct tdb_context *tdb) /* you cannot use transactions inside a traverse (although you can use traverse inside a transaction) as otherwise you can end up with deadlock */ - TDB_LOG((tdb, 0, "tdb_transaction_start: cannot start a transaction within a traverse\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: cannot start a transaction within a traverse\n")); tdb->ecode = TDB_ERR_LOCK; return -1; } @@ -421,7 +421,7 @@ int tdb_transaction_start(struct tdb_context *tdb) discussed with Volker, there are a number of ways we could make this async, which we will probably do in the future */ if (tdb_brlock_len(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_start: failed to get transaction lock\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get transaction lock\n")); tdb->ecode = TDB_ERR_LOCK; SAFE_FREE(tdb->transaction); return -1; @@ -430,7 +430,7 @@ int tdb_transaction_start(struct tdb_context *tdb) /* get a read lock from the freelist to the end of file. This is upgraded to a write lock during the commit */ if (tdb_brlock_len(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_start: failed to get hash locks\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n")); tdb->ecode = TDB_ERR_LOCK; goto fail; } @@ -444,7 +444,7 @@ int tdb_transaction_start(struct tdb_context *tdb) } if (tdb->methods->tdb_read(tdb, FREELIST_TOP, tdb->transaction->hash_heads, TDB_HASHTABLE_SIZE(tdb), 0) != 0) { - TDB_LOG((tdb, 0, "tdb_transaction_start: failed to read hash heads\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to read hash heads\n")); tdb->ecode = TDB_ERR_IO; goto fail; } @@ -463,7 +463,7 @@ int tdb_transaction_start(struct tdb_context *tdb) transaction linked list due to hash table updates */ if (transaction_write(tdb, FREELIST_TOP, tdb->transaction->hash_heads, TDB_HASHTABLE_SIZE(tdb)) != 0) { - TDB_LOG((tdb, 0, "tdb_transaction_start: failed to prime hash table\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_start: failed to prime hash table\n")); tdb->ecode = TDB_ERR_IO; goto fail; } @@ -485,7 +485,7 @@ fail: int tdb_transaction_cancel(struct tdb_context *tdb) { if (tdb->transaction == NULL) { - TDB_LOG((tdb, 0, "tdb_transaction_cancel: no transaction\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_cancel: no transaction\n")); return -1; } @@ -535,7 +535,7 @@ static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t { if (fsync(tdb->fd) != 0) { tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0, "tdb_transaction: fsync failed\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n")); return -1; } #ifdef MS_SYNC @@ -544,7 +544,7 @@ static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t if (msync(moffset + (char *)tdb->map_ptr, length + (offset - moffset), MS_SYNC) != 0) { tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0, "tdb_transaction: msync failed - %s\n", + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: msync failed - %s\n", strerror(errno))); return -1; } @@ -587,7 +587,7 @@ static int tdb_recovery_allocate(struct tdb_context *tdb, tdb_off_t recovery_head; if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { - TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to read recovery head\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n")); return -1; } @@ -595,7 +595,7 @@ static int tdb_recovery_allocate(struct tdb_context *tdb, if (recovery_head != 0 && methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to read recovery record\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n")); return -1; } @@ -615,7 +615,7 @@ static int tdb_recovery_allocate(struct tdb_context *tdb, the transaction) */ if (recovery_head != 0) { if (tdb_free(tdb, recovery_head, &rec) == -1) { - TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to free previous recovery area\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to free previous recovery area\n")); return -1; } } @@ -631,7 +631,7 @@ static int tdb_recovery_allocate(struct tdb_context *tdb, if (methods->tdb_expand_file(tdb, tdb->transaction->old_map_size, (tdb->map_size - tdb->transaction->old_map_size) + sizeof(rec) + *recovery_max_size) == -1) { - TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to create recovery area\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to create recovery area\n")); return -1; } @@ -647,7 +647,7 @@ static int tdb_recovery_allocate(struct tdb_context *tdb, CONVERT(recovery_head); if (methods->tdb_write(tdb, TDB_RECOVERY_HEAD, &recovery_head, sizeof(tdb_off_t)) == -1) { - TDB_LOG((tdb, 0, "tdb_recovery_allocate: failed to write recovery head\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to write recovery head\n")); return -1; } @@ -701,7 +701,7 @@ static int transaction_setup_recovery(struct tdb_context *tdb, continue; } if (el->offset + el->length > tdb->transaction->old_map_size) { - TDB_LOG((tdb, 0, "tdb_transaction_setup_recovery: transaction data over new region boundary\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: transaction data over new region boundary\n")); free(data); tdb->ecode = TDB_ERR_CORRUPT; return -1; @@ -729,7 +729,7 @@ static int transaction_setup_recovery(struct tdb_context *tdb, /* write the recovery data to the recovery area */ if (methods->tdb_write(tdb, recovery_offset, data, sizeof(*rec) + recovery_size) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_setup_recovery: failed to write recovery data\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery data\n")); free(data); tdb->ecode = TDB_ERR_IO; return -1; @@ -751,7 +751,7 @@ static int transaction_setup_recovery(struct tdb_context *tdb, *magic_offset = recovery_offset + offsetof(struct list_struct, magic); if (methods->tdb_write(tdb, *magic_offset, &magic, sizeof(magic)) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_setup_recovery: failed to write recovery magic\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_setup_recovery: failed to write recovery magic\n")); tdb->ecode = TDB_ERR_IO; return -1; } @@ -774,14 +774,14 @@ int tdb_transaction_commit(struct tdb_context *tdb) u32 zero = 0; if (tdb->transaction == NULL) { - TDB_LOG((tdb, 0, "tdb_transaction_commit: no transaction\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: no transaction\n")); return -1; } if (tdb->transaction->transaction_error) { tdb->ecode = TDB_ERR_IO; tdb_transaction_cancel(tdb); - TDB_LOG((tdb, 0, "tdb_transaction_commit: transaction error pending\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: transaction error pending\n")); return -1; } @@ -802,14 +802,14 @@ int tdb_transaction_commit(struct tdb_context *tdb) nested their locks properly, so fail the transaction */ if (tdb->num_locks) { tdb->ecode = TDB_ERR_LOCK; - TDB_LOG((tdb, 0, "tdb_transaction_commit: locks pending on commit\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: locks pending on commit\n")); tdb_transaction_cancel(tdb); return -1; } /* upgrade the main transaction lock region to a write lock */ if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_start: failed to upgrade hash locks\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to upgrade hash locks\n")); tdb->ecode = TDB_ERR_LOCK; tdb_transaction_cancel(tdb); return -1; @@ -818,7 +818,7 @@ int tdb_transaction_commit(struct tdb_context *tdb) /* get the global lock - this prevents new users attaching to the database during the commit */ if (tdb_brlock_len(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to get global lock\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_commit: failed to get global lock\n")); tdb->ecode = TDB_ERR_LOCK; tdb_transaction_cancel(tdb); return -1; @@ -827,7 +827,7 @@ int tdb_transaction_commit(struct tdb_context *tdb) if (!(tdb->flags & TDB_NOSYNC)) { /* write the recovery data to the end of the file */ if (transaction_setup_recovery(tdb, &magic_offset) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to setup recovery data\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to setup recovery data\n")); tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); tdb_transaction_cancel(tdb); return -1; @@ -840,7 +840,7 @@ int tdb_transaction_commit(struct tdb_context *tdb) tdb->map_size - tdb->transaction->old_map_size) == -1) { tdb->ecode = TDB_ERR_IO; - TDB_LOG((tdb, 0, "tdb_transaction_commit: expansion failed\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: expansion failed\n")); tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); tdb_transaction_cancel(tdb); return -1; @@ -854,7 +854,7 @@ int tdb_transaction_commit(struct tdb_context *tdb) struct tdb_transaction_el *el = tdb->transaction->elements; if (methods->tdb_write(tdb, el->offset, el->data, el->length) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_commit: write failed during commit\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n")); /* we've overwritten part of the data and possibly expanded the file, so we need to @@ -865,7 +865,7 @@ int tdb_transaction_commit(struct tdb_context *tdb) tdb_transaction_cancel(tdb); tdb_brlock_len(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1); - TDB_LOG((tdb, 0, "tdb_transaction_commit: write failed\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n")); return -1; } tdb->transaction->elements = el->next; @@ -881,7 +881,7 @@ int tdb_transaction_commit(struct tdb_context *tdb) /* remove the recovery marker */ if (methods->tdb_write(tdb, magic_offset, &zero, 4) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_commit: failed to remove recovery magic\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: failed to remove recovery magic\n")); return -1; } @@ -929,7 +929,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) /* find the recovery area */ if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery head\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery head\n")); tdb->ecode = TDB_ERR_IO; return -1; } @@ -942,7 +942,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) /* read the recovery record */ if (tdb->methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery record\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery record\n")); tdb->ecode = TDB_ERR_IO; return -1; } @@ -953,7 +953,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) } if (tdb->read_only) { - TDB_LOG((tdb, 0, "tdb_transaction_recover: attempt to recover read only database\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: attempt to recover read only database\n")); tdb->ecode = TDB_ERR_CORRUPT; return -1; } @@ -962,7 +962,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) data = malloc(rec.data_len); if (data == NULL) { - TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to allocate recovery data\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to allocate recovery data\n")); tdb->ecode = TDB_ERR_OOM; return -1; } @@ -970,7 +970,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) /* read the full recovery data */ if (tdb->methods->tdb_read(tdb, recovery_head + sizeof(rec), data, rec.data_len, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to read recovery data\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n")); tdb->ecode = TDB_ERR_IO; return -1; } @@ -987,7 +987,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) if (tdb->methods->tdb_write(tdb, ofs, p+8, len) == -1) { free(data); - TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs)); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to recover %d bytes at offset %d\n", len, ofs)); tdb->ecode = TDB_ERR_IO; return -1; } @@ -997,7 +997,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) free(data); if (transaction_sync(tdb, 0, tdb->map_size) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to sync recovery\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync recovery\n")); tdb->ecode = TDB_ERR_IO; return -1; } @@ -1005,7 +1005,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) /* if the recovery area is after the recovered eof then remove it */ if (recovery_eof <= recovery_head) { if (tdb_ofs_write(tdb, TDB_RECOVERY_HEAD, &zero) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to remove recovery head\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery head\n")); tdb->ecode = TDB_ERR_IO; return -1; } @@ -1014,7 +1014,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) /* remove the recovery magic */ if (tdb_ofs_write(tdb, recovery_head + offsetof(struct list_struct, magic), &zero) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to remove recovery magic\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to remove recovery magic\n")); tdb->ecode = TDB_ERR_IO; return -1; } @@ -1022,7 +1022,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) /* reduce the file size to the old size */ tdb_munmap(tdb); if (ftruncate(tdb->fd, recovery_eof) != 0) { - TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to reduce to recovery size\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n")); tdb->ecode = TDB_ERR_IO; return -1; } @@ -1030,12 +1030,12 @@ int tdb_transaction_recover(struct tdb_context *tdb) tdb_mmap(tdb); if (transaction_sync(tdb, 0, recovery_eof) == -1) { - TDB_LOG((tdb, 0, "tdb_transaction_recover: failed to sync2 recovery\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to sync2 recovery\n")); tdb->ecode = TDB_ERR_IO; return -1; } - TDB_LOG((tdb, 0, "tdb_transaction_recover: recovered %d byte database\n", + TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_recover: recovered %d byte database\n", recovery_eof)); /* all done */ diff --git a/source/lib/tdb/common/traverse.c b/source/lib/tdb/common/traverse.c index 65f64c777b7..90c92042ad2 100644 --- a/source/lib/tdb/common/traverse.c +++ b/source/lib/tdb/common/traverse.c @@ -100,7 +100,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc /* Detect infinite loops. From "Shlomi Yaakobovich" . */ if (tlock->off == rec->next) { - TDB_LOG((tdb, 0, "tdb_next_lock: loop detected.\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: loop detected.\n")); goto fail; } @@ -127,7 +127,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc fail: tlock->off = 0; if (tdb_unlock(tdb, tlock->hash, tlock->lock_rw) != 0) - TDB_LOG((tdb, 0, "tdb_next_lock: On error unlock failed!\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_next_lock: On error unlock failed!\n")); return -1; } @@ -163,7 +163,7 @@ static int tdb_traverse_internal(struct tdb_context *tdb, if (tdb_unlock(tdb, tl->hash, tl->lock_rw) != 0) goto out; if (tdb_unlock_record(tdb, tl->off) != 0) - TDB_LOG((tdb, 0, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: key.dptr == NULL and unlock_record failed!\n")); goto out; } key.dsize = rec.key_len; @@ -180,7 +180,7 @@ static int tdb_traverse_internal(struct tdb_context *tdb, /* They want us to terminate traversal */ ret = count; if (tdb_unlock_record(tdb, tl->off) != 0) { - TDB_LOG((tdb, 0, "tdb_traverse: unlock_record failed!\n"));; + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_traverse: unlock_record failed!\n"));; ret = -1; } SAFE_FREE(key.dptr); @@ -209,7 +209,7 @@ int tdb_traverse_read(struct tdb_context *tdb, /* we need to get a read lock on the transaction lock here to cope with the lock ordering semantics of solaris10 */ if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_RDLCK, F_SETLKW, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_traverse_read: failed to get transaction lock\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_traverse_read: failed to get transaction lock\n")); tdb->ecode = TDB_ERR_LOCK; return -1; } @@ -238,7 +238,7 @@ int tdb_traverse(struct tdb_context *tdb, } if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_WRLCK, F_SETLKW, 0) == -1) { - TDB_LOG((tdb, 0, "tdb_traverse: failed to get transaction lock\n")); + TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_traverse: failed to get transaction lock\n")); tdb->ecode = TDB_ERR_LOCK; return -1; } @@ -268,7 +268,7 @@ TDB_DATA tdb_firstkey(struct tdb_context *tdb) key.dsize = rec.key_len; key.dptr =tdb_alloc_read(tdb,tdb->travlocks.off+sizeof(rec),key.dsize); if (tdb_unlock(tdb, BUCKET(tdb->travlocks.hash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_firstkey: error occurred while tdb_unlocking!\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_firstkey: error occurred while tdb_unlocking!\n")); return key; } @@ -310,7 +310,7 @@ TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey) return tdb_null; tdb->travlocks.hash = BUCKET(rec.full_hash); if (tdb_lock_record(tdb, tdb->travlocks.off) != 0) { - TDB_LOG((tdb, 0, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: lock_record failed (%s)!\n", strerror(errno))); return tdb_null; } } @@ -324,11 +324,11 @@ TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey) key.dsize); /* Unlock the chain of this new record */ if (tdb_unlock(tdb, tdb->travlocks.hash, F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); } /* Unlock the chain of old record */ if (tdb_unlock(tdb, BUCKET(oldhash), F_WRLCK) != 0) - TDB_LOG((tdb, 0, "tdb_nextkey: WARNING tdb_unlock failed!\n")); + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_nextkey: WARNING tdb_unlock failed!\n")); return key; } diff --git a/source/lib/tdb/include/tdb.h b/source/lib/tdb/include/tdb.h index 4004c734608..785bbbe29bb 100644 --- a/source/lib/tdb/include/tdb.h +++ b/source/lib/tdb/include/tdb.h @@ -55,6 +55,10 @@ enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK, TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT, TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY}; +/* debugging uses one of the following levels */ +enum tdb_debug_level {TDB_DEBUG_FATAL = 0, TDB_DEBUG_ERROR, + TDB_DEBUG_WARNING, TDB_DEBUG_TRACE}; + typedef struct TDB_DATA { unsigned char *dptr; size_t dsize; @@ -76,19 +80,20 @@ typedef struct TDB_DATA { typedef struct tdb_context TDB_CONTEXT; typedef int (*tdb_traverse_func)(struct tdb_context *, TDB_DATA, TDB_DATA, void *); -typedef void (*tdb_log_func)(struct tdb_context *, int , const char *, ...); +typedef void (*tdb_log_func)(struct tdb_context *, enum tdb_debug_level, const char *, ...) PRINTF_ATTRIBUTE(3, 4); typedef unsigned int (*tdb_hash_func)(TDB_DATA *key); struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode); struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, int open_flags, mode_t mode, - tdb_log_func log_fn, + tdb_log_func log_fn, void *log_private, tdb_hash_func hash_fn); +void *tdb_logging_private(struct tdb_context *tdb); int tdb_reopen(struct tdb_context *tdb); int tdb_reopen_all(int parent_longlived); -void tdb_logging_function(struct tdb_context *tdb, tdb_log_func); +void tdb_logging_function(struct tdb_context *tdb, tdb_log_func log_fn, void *log_private); enum TDB_ERROR tdb_error(struct tdb_context *tdb); const char *tdb_errorstr(struct tdb_context *tdb); TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key); @@ -106,6 +111,7 @@ void tdb_unlockall(struct tdb_context *tdb); const char *tdb_name(struct tdb_context *tdb); int tdb_fd(struct tdb_context *tdb); tdb_log_func tdb_log_fn(struct tdb_context *tdb); +void *tdb_get_logging_private(struct tdb_context *tdb); int tdb_transaction_start(struct tdb_context *tdb); int tdb_transaction_commit(struct tdb_context *tdb); int tdb_transaction_cancel(struct tdb_context *tdb); diff --git a/source/lib/tdb/tools/tdbtool.c b/source/lib/tdb/tools/tdbtool.c index 0941a73118d..5aa47bd9f5f 100644 --- a/source/lib/tdb/tools/tdbtool.c +++ b/source/lib/tdb/tools/tdbtool.c @@ -79,9 +79,9 @@ static void print_asc(unsigned char *buf,int len) } #ifdef PRINTF_ATTRIBUTE -static void tdb_log(struct tdb_context *t, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +static void tdb_log(struct tdb_context *t, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); #endif -static void tdb_log(struct tdb_context *t, int level, const char *format, ...) +static void tdb_log(struct tdb_context *t, enum tdb_debug_level level, const char *format, ...) { va_list ap; @@ -190,7 +190,7 @@ static void create_tdb(void) } if (tdb) tdb_close(tdb); tdb = tdb_open_ex(tok, 0, TDB_CLEAR_IF_FIRST, - O_RDWR | O_CREAT | O_TRUNC, 0600, tdb_log, NULL); + O_RDWR | O_CREAT | O_TRUNC, 0600, tdb_log, NULL, NULL); if (!tdb) { printf("Could not create %s: %s\n", tok, strerror(errno)); } @@ -204,7 +204,7 @@ static void open_tdb(void) return; } if (tdb) tdb_close(tdb); - tdb = tdb_open_ex(tok, 0, 0, O_RDWR, 0600, tdb_log, NULL); + tdb = tdb_open_ex(tok, 0, 0, O_RDWR, 0600, tdb_log, NULL, NULL); if (!tdb) { printf("Could not open %s: %s\n", tok, strerror(errno)); } @@ -340,7 +340,7 @@ static void move_rec(void) print_rec(tdb, key, dbuf, NULL); - dst_tdb = tdb_open_ex(file, 0, 0, O_RDWR, 0600, tdb_log, NULL); + dst_tdb = tdb_open_ex(file, 0, 0, O_RDWR, 0600, tdb_log, NULL, NULL); if ( !dst_tdb ) { terror("unable to open destination tdb"); return; diff --git a/source/lib/tdb/tools/tdbtorture.c b/source/lib/tdb/tools/tdbtorture.c index ac098986961..559a84d99bd 100644 --- a/source/lib/tdb/tools/tdbtorture.c +++ b/source/lib/tdb/tools/tdbtorture.c @@ -53,9 +53,9 @@ static int in_transaction; static int error_count; #ifdef PRINTF_ATTRIBUTE -static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); +static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); #endif -static void tdb_log(struct tdb_context *tdb, int level, const char *format, ...) +static void tdb_log(struct tdb_context *tdb, enum tdb_debug_level level, const char *format, ...) { va_list ap; @@ -266,7 +266,7 @@ static void usage(void) } db = tdb_open_ex("torture.tdb", hash_size, TDB_CLEAR_IF_FIRST, - O_RDWR | O_CREAT, 0600, tdb_log, NULL); + O_RDWR | O_CREAT, 0600, tdb_log, NULL, NULL); if (!db) { fatal("db open failed"); }