diff options
Diffstat (limited to 'source4/lib')
-rw-r--r-- | source4/lib/basic.mk | 2 | ||||
-rw-r--r-- | source4/lib/db_wrap.c | 170 | ||||
-rw-r--r-- | source4/lib/gencache.c | 27 | ||||
-rw-r--r-- | source4/lib/messages.c | 42 | ||||
-rw-r--r-- | source4/lib/tdb/config.mk | 6 | ||||
-rw-r--r-- | source4/lib/tdb_helper.c | 42 |
6 files changed, 208 insertions, 81 deletions
diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index addef77a20..93309ce68b 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -50,7 +50,7 @@ ADD_OBJ_FILES = \ lib/crypto/md5.o \ lib/crypto/hmacmd5.o \ lib/crypto/md4.o \ - lib/tdb_helper.o \ + lib/db_wrap.o \ lib/server_mutex.o REQUIRED_SUBSYSTEMS = \ LIBTDB CHARSET diff --git a/source4/lib/db_wrap.c b/source4/lib/db_wrap.c new file mode 100644 index 0000000000..251741c5b0 --- /dev/null +++ b/source4/lib/db_wrap.c @@ -0,0 +1,170 @@ +/* + Unix SMB/CIFS implementation. + + database wrap functions + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + the stupidity of the unix fcntl locking design forces us to never + allow a database file to be opened twice in the same process. These + wrappers provide convenient access to a tdb or ldb, taking advantage + of talloc destructors to ensure that only a single open is done +*/ + +#include "includes.h" + +static struct ldb_wrap *ldb_list; +static struct tdb_wrap *tdb_list; + +/* + this is used to catch debug messages from ldb +*/ +static void ldb_wrap_debug(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); + +static void ldb_wrap_debug(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) +{ + char *s = NULL; + if (DEBUGLEVEL < 4 && level > LDB_DEBUG_WARNING) { + return; + } + vasprintf(&s, fmt, ap); + if (!s) return; + DEBUG(level, ("ldb: %s\n", s)); + free(s); +} + + +/* destroy the last connection to a ldb */ +static int ldb_wrap_destructor(void *ctx) +{ + struct ldb_wrap *w = ctx; + ldb_close(w->ldb); + DLIST_REMOVE(ldb_list, w); + return 0; +} + +/* + wrapped connection to a ldb database + to close just talloc_free() the ldb_wrap pointer + */ +struct ldb_wrap *ldb_wrap_connect(TALLOC_CTX *mem_ctx, + const char *url, + unsigned int flags, + const char *options[]) +{ + struct ldb_wrap *w; + + for (w=ldb_list;w;w=w->next) { + if (strcmp(url, w->url) == 0) { + return talloc_reference(mem_ctx, w); + } + } + + w = talloc_p(mem_ctx, struct ldb_wrap); + if (w == NULL) { + return NULL; + } + + w->url = talloc_strdup(w, url); + + w->ldb = ldb_connect(url, flags, options); + if (w->ldb == NULL) { + talloc_free(w); + return NULL; + } + + talloc_set_destructor(w, ldb_wrap_destructor); + ldb_set_debug(w->ldb, ldb_wrap_debug, NULL); + + DLIST_ADD(ldb_list, w); + + return w; +} + + +/* + Log tdb messages via DEBUG(). +*/ +static void tdb_wrap_log(TDB_CONTEXT *tdb, int level, + const char *format, ...) PRINTF_ATTRIBUTE(3,4); + +static void tdb_wrap_log(TDB_CONTEXT *tdb, int level, + const char *format, ...) +{ + va_list ap; + char *ptr = NULL; + + va_start(ap, format); + vasprintf(&ptr, format, ap); + va_end(ap); + + if (ptr != NULL) { + DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); + free(ptr); + } +} + + +/* destroy the last connection to a tdb */ +static int tdb_wrap_destructor(void *ctx) +{ + struct tdb_wrap *w = ctx; + 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; + + for (w=tdb_list;w;w=w->next) { + if (strcmp(name, w->name) == 0) { + return talloc_reference(mem_ctx, w); + } + } + + w = talloc_p(mem_ctx, struct tdb_wrap); + if (w == NULL) { + return NULL; + } + + w->name = talloc_strdup(w, name); + + w->tdb = tdb_open_ex(name, hash_size, tdb_flags, + open_flags, mode, tdb_wrap_log, NULL); + if (w->tdb == NULL) { + talloc_free(w); + return NULL; + } + + talloc_set_destructor(w, tdb_wrap_destructor); + + DLIST_ADD(tdb_list, w); + + return w; +} diff --git a/source4/lib/gencache.c b/source4/lib/gencache.c index 1a66d8dc3d..a176dc5ae8 100644 --- a/source4/lib/gencache.c +++ b/source4/lib/gencache.c @@ -29,7 +29,7 @@ #define TIMEOUT_LEN 12 #define CACHE_DATA_FMT "%12u/%s" -static TDB_CONTEXT *cache; +static struct tdb_wrap *cache; /** * @file gencache.c @@ -62,8 +62,8 @@ BOOL gencache_init(void) return False; } - cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, - O_RDWR|O_CREAT, 0644); + cache = tdb_wrap_open(NULL, cache_fname, 0, TDB_DEFAULT, + O_RDWR|O_CREAT, 0644); SAFE_FREE(cache_fname); if (!cache) { @@ -83,10 +83,10 @@ BOOL gencache_init(void) BOOL gencache_shutdown(void) { - /* tdb_close routine returns -1 on error */ if (!cache) return False; DEBUG(5, ("Closing cache file\n")); - return tdb_close(cache) != -1; + talloc_free(cache); + return True; } @@ -125,7 +125,7 @@ BOOL gencache_set(const char *keystr, const char *value, time_t timeout) = %s (%d seconds %s)\n", keybuf.dptr, value, ctime(&timeout), (int)(timeout - time(NULL)), timeout > time(NULL) ? "ahead" : "in the past")); - ret = tdb_store(cache, keybuf, databuf, 0); + ret = tdb_store(cache->tdb, keybuf, databuf, 0); SAFE_FREE(valstr); SAFE_FREE(keybuf.dptr); SAFE_FREE(databuf.dptr); @@ -178,7 +178,7 @@ BOOL gencache_set_only(const char *keystr, const char *valstr, time_t timeout) timeout > time(NULL) ? "ahead" : "in the past")); - ret = tdb_store(cache, keybuf, databuf, TDB_REPLACE); + ret = tdb_store(cache->tdb, keybuf, databuf, TDB_REPLACE); SAFE_FREE(datastr); SAFE_FREE(old_valstr); @@ -211,7 +211,7 @@ BOOL gencache_del(const char *keystr) keybuf.dptr = strdup(keystr); keybuf.dsize = strlen(keystr)+1; DEBUG(10, ("Deleting cache entry (key = %s)\n", keystr)); - ret = tdb_delete(cache, keybuf); + ret = tdb_delete(cache->tdb, keybuf); SAFE_FREE(keybuf.dptr); return ret == 0; @@ -243,7 +243,7 @@ BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout) keybuf.dptr = strdup(keystr); keybuf.dsize = strlen(keystr)+1; - databuf = tdb_fetch(cache, keybuf); + databuf = tdb_fetch(cache->tdb, keybuf); SAFE_FREE(keybuf.dptr); if (databuf.dptr && databuf.dsize > TIMEOUT_LEN) { @@ -317,7 +317,7 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time if (!gencache_init()) return; DEBUG(5, ("Searching cache keys with pattern %s\n", keystr_pattern)); - node = tdb_search_keys(cache, keystr_pattern); + node = tdb_search_keys(cache->tdb, keystr_pattern); first_node = node; while (node) { @@ -328,7 +328,7 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time * We don't use gencache_get function, because we need to iterate through * all of the entries. Validity verification is up to fn routine. */ - databuf = tdb_fetch(cache, node->node_key); + databuf = tdb_fetch(cache->tdb, node->node_key); if (!databuf.dptr || databuf.dsize <= TIMEOUT_LEN) { SAFE_FREE(databuf.dptr); SAFE_FREE(keystr); @@ -360,7 +360,7 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time int gencache_lock_entry( const char *key ) { - return tdb_lock_bystring(cache, key, 0); + return tdb_lock_bystring(cache->tdb, key, 0); } /******************************************************************** @@ -369,8 +369,7 @@ int gencache_lock_entry( const char *key ) void gencache_unlock_entry( const char *key ) { - tdb_unlock_bystring(cache, key); - return; + tdb_unlock_bystring(cache->tdb, key); } diff --git a/source4/lib/messages.c b/source4/lib/messages.c index b4de7c0145..64dc2f510a 100644 --- a/source4/lib/messages.c +++ b/source4/lib/messages.c @@ -48,7 +48,7 @@ #include "includes.h" /* the locking database handle */ -static TDB_CONTEXT *tdb; +static struct tdb_wrap *tdb; static int received_signal; /* change the message version with any incompatible changes in the protocol */ @@ -105,9 +105,9 @@ BOOL message_init(void) DEBUG(0,("ERROR: No memory to initialise messages database\n")); return False; } - tdb = tdb_open_log(lock_path(mem_ctx, "messages.tdb"), - 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, - O_RDWR|O_CREAT,0600); + tdb = tdb_wrap_open(NULL, lock_path(mem_ctx, "messages.tdb"), + 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, + O_RDWR|O_CREAT,0600); talloc_destroy(mem_ctx); if (!tdb) { @@ -155,7 +155,7 @@ static BOOL message_notify(pid_t pid) if (kill(pid, SIGUSR1) == -1) { if (errno == ESRCH) { DEBUG(2,("pid %d doesn't exist - deleting messages record\n", (int)pid)); - tdb_delete(tdb, message_key_pid(pid)); + tdb_delete(tdb->tdb, message_key_pid(pid)); } else { DEBUG(2,("message to process %d failed - %s\n", (int)pid, strerror(errno))); } @@ -209,18 +209,18 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, /* lock the record for the destination */ if (timeout) { - if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) { + if (tdb_chainlock_with_timeout(tdb->tdb, kbuf, timeout) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); return False; } } else { - if (tdb_chainlock(tdb, kbuf) == -1) { + if (tdb_chainlock(tdb->tdb, kbuf) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); return False; } } - tdb_append(tdb, kbuf, dbuf); - tdb_chainunlock(tdb, kbuf); + tdb_append(tdb->tdb, kbuf, dbuf); + tdb_chainunlock(tdb->tdb, kbuf); SAFE_FREE(dbuf.dptr); errno = 0; /* paranoia */ @@ -229,24 +229,24 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, /* lock the record for the destination */ if (timeout) { - if (tdb_chainlock_with_timeout(tdb, kbuf, timeout) == -1) { + if (tdb_chainlock_with_timeout(tdb->tdb, kbuf, timeout) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock with timeout %ul.\n", timeout)); return False; } } else { - if (tdb_chainlock(tdb, kbuf) == -1) { + if (tdb_chainlock(tdb->tdb, kbuf) == -1) { DEBUG(0,("message_send_pid_internal: failed to get chainlock.\n")); return False; } } - old_dbuf = tdb_fetch(tdb, kbuf); + old_dbuf = tdb_fetch(tdb->tdb, kbuf); if (!old_dbuf.dptr) { /* its a new record */ - tdb_store(tdb, kbuf, dbuf, TDB_REPLACE); - tdb_chainunlock(tdb, kbuf); + tdb_store(tdb->tdb, kbuf, dbuf, TDB_REPLACE); + tdb_chainunlock(tdb->tdb, kbuf); SAFE_FREE(dbuf.dptr); errno = 0; /* paranoia */ @@ -264,7 +264,7 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, if (!memcmp(ptr, &rec, sizeof(rec))) { if (!len || (len && !memcmp( ptr + sizeof(rec), buf, len))) { - tdb_chainunlock(tdb, kbuf); + tdb_chainunlock(tdb->tdb, kbuf); DEBUG(10,("message_send_pid_internal: discarding duplicate message.\n")); SAFE_FREE(dbuf.dptr); SAFE_FREE(old_dbuf.dptr); @@ -277,8 +277,8 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, /* we're adding to an existing entry */ - tdb_append(tdb, kbuf, dbuf); - tdb_chainunlock(tdb, kbuf); + tdb_append(tdb->tdb, kbuf, dbuf); + tdb_chainunlock(tdb->tdb, kbuf); SAFE_FREE(old_dbuf.dptr); SAFE_FREE(dbuf.dptr); @@ -323,14 +323,14 @@ static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len) kbuf = message_key_pid(getpid()); - tdb_chainlock(tdb, kbuf); - dbuf = tdb_fetch(tdb, kbuf); + tdb_chainlock(tdb->tdb, kbuf); + dbuf = tdb_fetch(tdb->tdb, kbuf); /* * Replace with an empty record to keep the allocated * space in the tdb. */ - tdb_store(tdb, kbuf, null_dbuf, TDB_REPLACE); - tdb_chainunlock(tdb, kbuf); + tdb_store(tdb->tdb, kbuf, null_dbuf, TDB_REPLACE); + tdb_chainunlock(tdb->tdb, kbuf); if (dbuf.dptr == NULL || dbuf.dsize == 0) { SAFE_FREE(dbuf.dptr); diff --git a/source4/lib/tdb/config.mk b/source4/lib/tdb/config.mk index fdde6e7b4f..dba0d3e1d4 100644 --- a/source4/lib/tdb/config.mk +++ b/source4/lib/tdb/config.mk @@ -28,7 +28,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/tdb/tools/tdbtest.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBTDB + LIBTDB REQUIRED_LIBRARIES = GDBM # End BINARY tdbtest ################################################ @@ -49,7 +49,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/tdb/tools/tdbtorture.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBTDB + LIBTDB # End BINARY tdbtorture ################################################ @@ -59,7 +59,7 @@ REQUIRED_SUBSYSTEMS = \ OBJ_FILES= \ lib/tdb/tools/tdbdump.o REQUIRED_SUBSYSTEMS = \ - LIBBASIC CONFIG LIBCMDLINE LIBTDB + LIBTDB # End BINARY tdbdump ################################################ diff --git a/source4/lib/tdb_helper.c b/source4/lib/tdb_helper.c index 2698e3cc71..e29a8a7211 100644 --- a/source4/lib/tdb_helper.c +++ b/source4/lib/tdb_helper.c @@ -25,45 +25,3 @@ dealing with a tdb database a little less cumbersome in Samba */ -/**************************************************************************** - Log tdb messages via DEBUG(). -****************************************************************************/ - -static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) PRINTF_ATTRIBUTE(3,4); - -static void tdb_log(TDB_CONTEXT *tdb, int level, const char *format, ...) -{ - va_list ap; - char *ptr = NULL; - - va_start(ap, format); - vasprintf(&ptr, format, ap); - va_end(ap); - - if (!ptr || !*ptr) - return; - - DEBUG(level, ("tdb(%s): %s", tdb->name ? tdb->name : "unnamed", ptr)); - SAFE_FREE(ptr); -} - -/**************************************************************************** - Like tdb_open() but also setup a logging function that redirects to - the samba DEBUG() system. -****************************************************************************/ - -TDB_CONTEXT *tdb_open_log(const char *name, int hash_size, int tdb_flags, - int open_flags, mode_t mode) -{ - TDB_CONTEXT *tdb; - - if (!lp_use_mmap()) - tdb_flags |= TDB_NOMMAP; - - tdb = tdb_open_ex(name, hash_size, tdb_flags, - open_flags, mode, tdb_log, NULL); - if (!tdb) - return NULL; - - return tdb; -} |