3bc83b98d5f048aa8d97267983c71ceab40b5583
[nivanova/samba-autobuild/.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 #include "smbd/smbd.h"
23
24 static struct smb_perfcount_handlers *g_smb_perfcount_handlers = NULL;
25
26 struct smb_perfcount_module {
27         char *name;
28         struct smb_perfcount_handlers *handlers;
29         struct smb_perfcount_module *prev, *next;
30 };
31
32 struct smb_perfcount_module *modules = NULL;
33
34
35 /*
36  * a module is registered before it is actually loaded - keep a list
37  *
38  * @todo - currently perfcount modules are globally configured, so
39  * building the list is not strictly required.
40  * However, its a proven concept in VFS, and is here to allow a
41  * move to eventual per-service perfcount configuration.
42  *
43  * Note many pre-connection statistics are interesting
44  * (e.g. before binding to an individual share).
45  *
46  */
47 static struct smb_perfcount_module *smb_perfcount_find_module(const char *name)
48 {
49         struct smb_perfcount_module *entry = modules;
50
51         while (entry) {
52                 if (strcmp(entry->name, name)==0)
53                         return entry;
54
55                 entry = entry->next;
56         }
57
58         return NULL;
59 }
60 NTSTATUS smb_register_perfcounter(int interface_version, const char *name,
61                                   const struct smb_perfcount_handlers *handlers)
62 {
63         struct smb_perfcount_module *entry = modules;
64
65         if (interface_version != SMB_PERFCOUNTER_INTERFACE_VERSION) {
66                 DEBUG(0, ("Failed to register perfcount module.\n"
67                           "The module was compiled against "
68                           "SMB_PERFCOUNTER_INTERFACE_VERSION %d,\n"
69                           "current SMB_PERFCOUNTER_INTERFACE_VERSION is %d.\n"
70                           "Please recompile against the current Samba Version!\n",
71                           interface_version, SMB_PERFCOUNTER_INTERFACE_VERSION));
72                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
73         }
74
75         if (!name || !name[0] || !handlers) {
76                 DEBUG(0,("smb_register_perfcounter() called with NULL pointer "
77                         "or empty name!\n"));
78                 return NT_STATUS_INVALID_PARAMETER;
79         }
80
81         if (smb_perfcount_find_module(name)) {
82                 DEBUG(3,("Perfcount Module %s already loaded!\n", name));
83                 return NT_STATUS_OK;
84         }
85
86         entry = SMB_XMALLOC_P(struct smb_perfcount_module);
87         entry->name = smb_xstrdup(name);
88         entry->handlers = (struct smb_perfcount_handlers*) handlers;
89
90         DLIST_ADD(modules, entry);
91         DEBUG(3, ("Successfully added perfcounter module '%s'\n", name));
92         return NT_STATUS_OK;
93 }
94
95 /****************************************************************************
96   initialise smb perf counters
97  ****************************************************************************/
98 static bool smb_load_perfcount_module(const char *name)
99 {
100         char *module_path = NULL;
101         char *module_name = NULL;
102         char *module_param = NULL, *p;
103
104         const struct smb_perfcount_module *entry;
105
106         DEBUG(3, ("Initialising perfcounter module [%s]\n", name));
107
108         if (g_smb_perfcount_handlers) {
109                 DEBUG(3,("Only 1 perfcount handler may be registered in "
110                         "smb.conf\n"));
111                 return true;
112         }
113
114         module_path = smb_xstrdup(name);
115
116         p = strchr_m(module_path, ':');
117
118         if (p) {
119                 *p = 0;
120                 module_param = p+1;
121                 trim_char(module_param, ' ', ' ');
122         }
123
124         trim_char(module_path, ' ', ' ');
125
126         module_name = smb_xstrdup(module_path);
127
128         if (module_name[0] == '/') {
129
130                 /*
131                  * Extract the module name from the path. Just use the base
132                  * name of the last path component.
133                  */
134
135                 SAFE_FREE(module_name);
136                 module_name = smb_xstrdup(strrchr_m(module_path, '/')+1);
137
138                 p = strchr_m(module_name, '.');
139
140                 if (p != NULL) {
141                         *p = '\0';
142                 }
143         }
144
145         /* load the perfcounter module */
146         if((entry = smb_perfcount_find_module(module_name)) ||
147            (NT_STATUS_IS_OK(smb_probe_module("perfcount", module_path)) &&
148                 (entry = smb_perfcount_find_module(module_name)))) {
149
150                 DEBUG(3,("Successfully loaded perfcounter module [%s] \n", name));
151         } else {
152                 DEBUG(0,("Can't find a perfcounter module [%s]\n",name));
153                 goto fail;
154         }
155
156         g_smb_perfcount_handlers = entry->handlers;
157
158         SAFE_FREE(module_path);
159         SAFE_FREE(module_name);
160         return True;
161
162  fail:
163         SAFE_FREE(module_path);
164         SAFE_FREE(module_name);
165         return False;
166 }
167
168 void smb_init_perfcount_data(struct smb_perfcount_data *pcd)
169 {
170
171         ZERO_STRUCTP(pcd);
172         pcd->handlers = g_smb_perfcount_handlers;
173 }
174
175 bool smb_perfcount_init(void)
176 {
177         char *perfcount_object;
178
179         perfcount_object = lp_perfcount_module();
180
181         /* don't init */
182         if (!perfcount_object || !perfcount_object[0])
183                 return True;
184
185         if (!smb_load_perfcount_module(perfcount_object)) {
186                 DEBUG(0, ("smbd_load_percount_module failed for %s\n",
187                         perfcount_object));
188                 return False;
189         }
190
191
192         return True;
193 }