TMP: add a ctdb snapshot of current ctdb master (git://git.samba.org/ctdb.git) to...
[obnox/samba/samba-obnox.git] / ctdb / lib / util / db_wrap.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    database wrap functions
5
6    Copyright (C) Andrew Tridgell 2004
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /*
23   the stupidity of the unix fcntl locking design forces us to never
24   allow a database file to be opened twice in the same process. These
25   wrappers provide convenient access to a tdb or ldb, taking advantage
26   of talloc destructors to ensure that only a single open is done
27 */
28
29 #include "includes.h"
30 #include "lib/util/dlinklist.h"
31 #include "lib/tevent/tevent.h"
32 #include "lib/tdb/include/tdb.h"
33 #include "db_wrap.h"
34
35 static struct tdb_wrap *tdb_list;
36
37
38
39 /* destroy the last connection to a tdb */
40 static int tdb_wrap_destructor(struct tdb_wrap *w)
41 {
42         tdb_close(w->tdb);
43         DLIST_REMOVE(tdb_list, w);
44         return 0;
45 }                                
46
47 static void log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...)
48 {
49         if (level <= TDB_DEBUG_ERROR) {
50                 va_list ap;
51                 char newfmt[strlen(tdb_name(tdb)) + 1 + strlen(fmt) + 1];
52                 sprintf(newfmt, "%s:%s", tdb_name(tdb), fmt);
53                 va_start(ap, fmt);
54                 do_debug_v(newfmt, ap);
55                 va_end(ap);
56         }
57 }
58
59
60 /*
61   wrapped connection to a tdb database
62   to close just talloc_free() the tdb_wrap pointer
63  */
64 struct tdb_wrap *tdb_wrap_open(TALLOC_CTX *mem_ctx,
65                                const char *name, int hash_size, int tdb_flags,
66                                int open_flags, mode_t mode)
67 {
68         struct tdb_wrap *w;
69         struct tdb_logging_context log_ctx;
70
71         log_ctx.log_fn = log_fn;
72         log_ctx.log_private = NULL;
73
74         for (w=tdb_list;w;w=w->next) {
75                 if (strcmp(name, w->name) == 0) {
76                         return talloc_reference(mem_ctx, w);
77                 }
78         }
79
80         w = talloc(mem_ctx, struct tdb_wrap);
81         if (w == NULL) {
82                 return NULL;
83         }
84
85         w->name = talloc_strdup(w, name);
86         if (w->name == NULL) {
87                 talloc_free(w);
88                 return NULL;
89         }
90
91         w->tdb = tdb_open_ex(name, hash_size, tdb_flags, 
92                              open_flags, mode, &log_ctx, NULL);
93         if (w->tdb == NULL) {
94                 talloc_free(w);
95                 return NULL;
96         }
97
98         talloc_set_destructor(w, tdb_wrap_destructor);
99
100         DLIST_ADD(tdb_list, w);
101
102         return w;
103 }