r21076: Two pieces of infrastructure from Samba4: An API-compatible messaging wrapper
[sfrench/samba-autobuild/.git] / source / lib / util_tdb.c
index 4db39095a64ec2dc7d5a4e8a4867d83aa6bdd49d..b559f589dc53e801ff446fd752571504b7fe83c0 100644 (file)
@@ -846,3 +846,101 @@ int tdb_trans_delete(struct tdb_context *tdb, TDB_DATA key)
 
        return res;
 }
+
+/*
+ Log tdb messages via DEBUG().
+*/
+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, enum tdb_debug_level level, 
+                        const char *format, ...)
+{
+       va_list ap;
+       char *ptr = NULL;
+       int debuglevel = 0;
+
+       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:
+               debuglevel = 1;
+               break;
+       case TDB_DEBUG_WARNING:
+               debuglevel = 2;
+               break;
+       case TDB_DEBUG_TRACE:
+               debuglevel = 5;
+               break;
+       default:
+               debuglevel = 0;
+       }               
+
+       if (ptr != NULL) {
+               const char *name = tdb_name(tdb);
+               DEBUG(debuglevel, ("tdb(%s): %s", name ? name : "unnamed", ptr));
+               free(ptr);
+       }
+}
+
+static struct tdb_wrap *tdb_list;
+
+/* destroy the last connection to a tdb */
+static int tdb_wrap_destructor(struct tdb_wrap *w)
+{
+       tdb_close(w->tdb);
+       DLIST_REMOVE(tdb_list, w);
+       return 0;
+}                               
+
+/*
+  wrapped connection to a tdb database
+  to close just talloc_free() the tdb_wrap pointer
+ */
+struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx,
+                              const char *name, int hash_size, int tdb_flags,
+                              int open_flags, mode_t mode)
+{
+       struct tdb_wrap *w;
+       struct tdb_logging_context log_ctx;
+       log_ctx.log_fn = tdb_wrap_log;
+
+       for (w=tdb_list;w;w=w->next) {
+               if (strcmp(name, w->name) == 0) {
+                       /*
+                        * Yes, talloc_reference is exactly what we want
+                        * here. Otherwise we would have to implement our own
+                        * reference counting.
+                        */
+                       return talloc_reference(mem_ctx, w);
+               }
+       }
+
+       w = talloc(mem_ctx, struct tdb_wrap);
+       if (w == NULL) {
+               return NULL;
+       }
+
+       if (!(w->name = talloc_strdup(w, name))) {
+               talloc_free(w);
+               return NULL;
+       }
+
+       w->tdb = tdb_open_ex(name, hash_size, tdb_flags, 
+                            open_flags, mode, &log_ctx, NULL);
+       if (w->tdb == NULL) {
+               talloc_free(w);
+               return NULL;
+       }
+
+       talloc_set_destructor(w, tdb_wrap_destructor);
+
+       DLIST_ADD(tdb_list, w);
+
+       return w;
+}