s3:winbind: remove the method SET_MAPPING from winbind's API
[ira/wip.git] / source3 / smbd / perfcount.c
1 /*
2    Unix SMB/Netbios implementation.
3    Perfcounter initialization and support functions
4    Copyright (C) Todd Stecher 2009
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21 #include "includes.h"
22
23 static struct smb_perfcount_handlers *g_smb_perfcount_handlers = NULL;
24
25 struct smb_perfcount_module {
26         char *name;
27         struct smb_perfcount_handlers *handlers;
28         struct smb_perfcount_module *prev, *next;
29 };
30
31 struct smb_perfcount_module *modules = NULL;
32
33
34 /*
35  * a module is registered before it is actually loaded - keep a list
36  *
37  * @todo - currently perfcount modules are globally configured, so
38  * building the list is not strictly required.
39  * However, its a proven concept in VFS, and is here to allow a
40  * move to eventual per-service perfcount configuration.
41  *
42  * Note many pre-connection statistics are interesting
43  * (e.g. before binding to an individual share).
44  *
45  */
46 static struct smb_perfcount_module *smb_perfcount_find_module(const char *name)
47 {
48         struct smb_perfcount_module *entry = modules;
49
50         while (entry) {
51                 if (strcmp(entry->name, name)==0)
52                         return entry;
53
54                 entry = entry->next;
55         }
56
57         return NULL;
58 }
59 NTSTATUS smb_register_perfcounter(int interface_version, const char *name,
60                                   const struct smb_perfcount_handlers *handlers)
61 {
62         struct smb_perfcount_module *entry = modules;
63
64         if (interface_version != SMB_PERFCOUNTER_INTERFACE_VERSION) {
65                 DEBUG(0, ("Failed to register perfcount module.\n"
66                           "The module was compiled against "
67                           "SMB_PERFCOUNTER_INTERFACE_VERSION %d,\n"
68                           "current SMB_PERFCOUNTER_INTERFACE_VERSION is %d.\n"
69                           "Please recompile against the current Samba Version!\n",
70                           interface_version, SMB_PERFCOUNTER_INTERFACE_VERSION));
71                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
72         }
73
74         if (!name || !name[0] || !handlers) {
75                 DEBUG(0,("smb_register_perfcounter() called with NULL pointer "
76                         "or empty name!\n"));
77                 return NT_STATUS_INVALID_PARAMETER;
78         }
79
80         if (smb_perfcount_find_module(name)) {
81                 DEBUG(3,("Perfcount Module %s already loaded!\n", name));
82                 return NT_STATUS_OK;
83         }
84
85         entry = SMB_XMALLOC_P(struct smb_perfcount_module);
86         entry->name = smb_xstrdup(name);
87         entry->handlers = (struct smb_perfcount_handlers*) handlers;
88
89         DLIST_ADD(modules, entry);
90         DEBUG(3, ("Successfully added perfcounter module '%s'\n", name));
91         return NT_STATUS_OK;
92 }
93
94 /****************************************************************************
95   initialise smb perf counters
96  ****************************************************************************/
97 static bool smb_load_perfcount_module(const char *name)
98 {
99         char *module_path = NULL;
100         char *module_name = NULL;
101         char *module_param = NULL, *p;
102
103         const struct smb_perfcount_module *entry;
104
105         DEBUG(3, ("Initialising perfcounter module [%s]\n", name));
106
107         if (g_smb_perfcount_handlers) {
108                 DEBUG(3,("Only 1 perfcount handler may be registered in "
109                         "smb.conf\n"));
110                 return true;
111         }
112
113         module_path = smb_xstrdup(name);
114
115         p = strchr_m(module_path, ':');
116
117         if (p) {
118                 *p = 0;
119                 module_param = p+1;
120                 trim_char(module_param, ' ', ' ');
121         }
122
123         trim_char(module_path, ' ', ' ');
124
125         module_name = smb_xstrdup(module_path);
126
127         if (module_name[0] == '/') {
128
129                 /*
130                  * Extract the module name from the path. Just use the base
131                  * name of the last path component.
132                  */
133
134                 SAFE_FREE(module_name);
135                 module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
136
137                 p = strchr_m(module_name, '.');
138
139                 if (p != NULL) {
140                         *p = '\0';
141                 }
142         }
143
144         /* load the perfcounter module */
145         if((entry = smb_perfcount_find_module(module_name)) ||
146            (NT_STATUS_IS_OK(smb_probe_module("perfcount", module_path)) &&
147                 (entry = smb_perfcount_find_module(module_name)))) {
148
149                 DEBUG(3,("Successfully loaded perfcounter module [%s] \n", name));
150         } else {
151                 DEBUG(0,("Can't find a perfcounter module [%s]\n",name));
152                 goto fail;
153         }
154
155         g_smb_perfcount_handlers = entry->handlers;
156
157         SAFE_FREE(module_path);
158         SAFE_FREE(module_name);
159         return True;
160
161  fail:
162         SAFE_FREE(module_path);
163         SAFE_FREE(module_name);
164         return False;
165 }
166
167 void smb_init_perfcount_data(struct smb_perfcount_data *pcd)
168 {
169
170         ZERO_STRUCTP(pcd);
171         pcd->handlers = g_smb_perfcount_handlers;
172 }
173
174 bool smb_perfcount_init(void)
175 {
176         char *perfcount_object;
177
178         perfcount_object = lp_perfcount_module();
179
180         /* don't init */
181         if (!perfcount_object || !perfcount_object[0])
182                 return True;
183
184         if (!smb_load_perfcount_module(perfcount_object)) {
185                 DEBUG(0, ("smbd_load_percount_module failed for %s\n",
186                         perfcount_object));
187                 return False;
188         }
189
190
191         return True;
192 }