cldap benchmarks hacks ...
[metze/samba/wip.git] / source4 / torture / ldap / cldapbench.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    CLDAP benchmark test
5
6    Copyright (C) Andrew Tridgell 2005
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 #include "includes.h"
23 #include "libcli/cldap/cldap.h"
24 #include "libcli/resolve/resolve.h"
25 #include "torture/torture.h"
26 #include "param/param.h"
27 #include "../lib/tsocket/tsocket.h"
28
29 #define CHECK_VAL(v, correct) torture_assert_int_equal(tctx, (v), (correct), "incorrect value");
30
31 struct bench_state {
32         struct torture_context *tctx;
33         int pass_count, fail_count;
34 };
35
36 static void request_netlogon_handler(struct tevent_req *req)
37 {
38         struct cldap_netlogon io;
39         struct bench_state *state = tevent_req_callback_data(req, struct bench_state);
40         NTSTATUS status;
41         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
42         io.in.version = 6;
43         status = cldap_netlogon_recv(req, tmp_ctx, &io);
44         talloc_free(req);
45         if (NT_STATUS_IS_OK(status)) {
46                 state->pass_count++;
47         } else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
48                 state->pass_count++;
49         } else {
50                 printf("error: %s\n", nt_errstr(status));
51                 exit(1);
52                 state->fail_count++;
53         }
54         talloc_free(tmp_ctx);
55 }
56
57 /*
58   benchmark cldap netlogon calls
59 */
60 static bool bench_cldap_netlogon(struct torture_context *tctx, const char *address)
61 {
62         struct cldap_socket *cldap;
63         int num_sent=0;
64         struct timeval tv = timeval_current();
65         int timelimit = torture_setting_int(tctx, "timelimit", 10);
66         struct cldap_netlogon search;
67         struct bench_state *state;
68         NTSTATUS status;
69         struct tsocket_address *dest_addr;
70         int ret;
71
72         ret = tsocket_address_inet_from_strings(tctx, "ip",
73                                                 address,
74                                                 lpcfg_cldap_port(tctx->lp_ctx),
75                                                 &dest_addr);
76         CHECK_VAL(ret, 0);
77
78         status = cldap_socket_init(tctx, NULL, dest_addr, &cldap);
79         torture_assert_ntstatus_ok(tctx, status, "cldap_socket_init");
80
81         state = talloc_zero(tctx, struct bench_state);
82         state->tctx = tctx;
83
84         ZERO_STRUCT(search);
85         search.in.dest_address = NULL;
86         search.in.dest_port = 0;
87         search.in.acct_control = -1;
88         search.in.version = 6;
89
90         printf("Running CLDAP/netlogon for %d seconds\n", timelimit);
91         while (timeval_elapsed(&tv) < timelimit) {
92                 while (num_sent - (state->pass_count+state->fail_count) < 10) {
93                         struct tevent_req *req;
94                         req = cldap_netlogon_send(state, tctx->ev,
95                                                   cldap, &search);
96
97                         tevent_req_set_callback(req, request_netlogon_handler, state);
98
99                         num_sent++;
100                         if (num_sent % 50 == 0) {
101                                 if (torture_setting_bool(tctx, "progress", true)) {
102                                         printf("%.1f queries per second (%d failures)  \r", 
103                                                state->pass_count / timeval_elapsed(&tv),
104                                                state->fail_count);
105                                         fflush(stdout);
106                                 }
107                         }
108                 }
109
110                 tevent_loop_once(tctx->ev);
111         }
112
113         while (num_sent != (state->pass_count + state->fail_count)) {
114                 tevent_loop_once(tctx->ev);
115         }
116
117         printf("%.1f queries per second (%d failures)  \n", 
118                state->pass_count / timeval_elapsed(&tv),
119                state->fail_count);
120
121         talloc_free(cldap);
122         return true;
123 }
124
125 static void request_rootdse_handler(struct tevent_req *req)
126 {
127         struct cldap_search io;
128         struct bench_state *state = tevent_req_callback_data(req, struct bench_state);
129         NTSTATUS status;
130         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
131         status = cldap_search_recv(req, tmp_ctx, &io);
132         talloc_free(req);
133         if (NT_STATUS_IS_OK(status)) {
134                 state->pass_count++;
135         } else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
136                 state->pass_count++;
137         } else {
138                 printf("error: %s\n", nt_errstr(status));
139                 exit(1);
140                 state->fail_count++;
141         }
142         talloc_free(tmp_ctx);
143 }
144
145 /*
146   benchmark cldap netlogon calls
147 */
148 static bool bench_cldap_rootdse(struct torture_context *tctx, const char *address)
149 {
150         struct cldap_socket *cldap;
151         int num_sent=0;
152         struct timeval tv = timeval_current();
153         int timelimit = torture_setting_int(tctx, "timelimit", 10);
154         struct cldap_search search;
155         struct bench_state *state;
156         NTSTATUS status;
157         struct tsocket_address *dest_addr;
158         int ret;
159
160         ret = tsocket_address_inet_from_strings(tctx, "ip",
161                                                 address,
162                                                 lpcfg_cldap_port(tctx->lp_ctx),
163                                                 &dest_addr);
164         CHECK_VAL(ret, 0);
165
166         /* cldap_socket_init should now know about the dest. address */
167         status = cldap_socket_init(tctx, NULL, dest_addr, &cldap);
168         torture_assert_ntstatus_ok(tctx, status, "cldap_socket_init");
169
170         state = talloc_zero(tctx, struct bench_state);
171
172         ZERO_STRUCT(search);
173         search.in.dest_address  = NULL;
174         search.in.dest_port     = 0;
175         search.in.filter        = "(objectClass=*)";
176         search.in.timeout       = 2;
177         search.in.retries       = 1;
178
179         printf("Running CLDAP/rootdse for %d seconds\n", timelimit);
180         while (timeval_elapsed(&tv) < timelimit) {
181                 while (num_sent - (state->pass_count+state->fail_count) < 10) {
182                         struct tevent_req *req;
183                         req = cldap_search_send(state, tctx->ev, cldap, &search);
184
185                         tevent_req_set_callback(req, request_rootdse_handler, state);
186
187                         num_sent++;
188                         if (num_sent % 50 == 0) {
189                                 if (torture_setting_bool(tctx, "progress", true)) {
190                                         printf("%.1f queries per second (%d failures)  \r",
191                                                state->pass_count / timeval_elapsed(&tv),
192                                                state->fail_count);
193                                         fflush(stdout);
194                                 }
195                         }
196                 }
197
198                 tevent_loop_once(tctx->ev);
199         }
200
201         while (num_sent != (state->pass_count + state->fail_count)) {
202                 tevent_loop_once(tctx->ev);
203         }
204
205         printf("%.1f queries per second (%d failures)  \n",
206                state->pass_count / timeval_elapsed(&tv),
207                state->fail_count);
208
209         talloc_free(cldap);
210         return true;
211 }
212
213 /*
214   benchmark how fast a CLDAP server can respond to a series of parallel
215   requests 
216 */
217 bool torture_bench_cldap(struct torture_context *torture)
218 {
219         const char *address;
220         struct nbt_name name;
221         NTSTATUS status;
222         bool ret = true;
223         
224         make_nbt_name_server(&name, torture_setting_string(torture, "host", NULL));
225
226         /* do an initial name resolution to find its IP */
227         status = resolve_name_ex(lpcfg_resolve_context(torture->lp_ctx),
228                                  0, 0, &name, torture, &address, torture->ev);
229         if (!NT_STATUS_IS_OK(status)) {
230                 printf("Failed to resolve %s - %s\n",
231                        name.name, nt_errstr(status));
232                 return false;
233         }
234
235 //      ret &= bench_cldap_netlogon(torture, address);
236         ret &= bench_cldap_rootdse(torture, address);
237
238         return ret;
239 }