Finish removal of iconv_convenience in public API's.
[bbaumbach/samba-autobuild/.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 {
48                 state->fail_count++;
49         }
50         talloc_free(tmp_ctx);
51 }
52
53 /*
54   benchmark cldap netlogon calls
55 */
56 static bool bench_cldap_netlogon(struct torture_context *tctx, const char *address)
57 {
58         struct cldap_socket *cldap;
59         int num_sent=0;
60         struct timeval tv = timeval_current();
61         int timelimit = torture_setting_int(tctx, "timelimit", 10);
62         struct cldap_netlogon search;
63         struct bench_state *state;
64         NTSTATUS status;
65         struct tsocket_address *dest_addr;
66         int ret;
67
68         ret = tsocket_address_inet_from_strings(tctx, "ip",
69                                                 address,
70                                                 lp_cldap_port(tctx->lp_ctx),
71                                                 &dest_addr);
72         CHECK_VAL(ret, 0);
73
74         status = cldap_socket_init(tctx, tctx->ev, NULL, dest_addr, &cldap);
75         torture_assert_ntstatus_ok(tctx, status, "cldap_socket_init");
76
77         state = talloc_zero(tctx, struct bench_state);
78         state->tctx = tctx;
79
80         ZERO_STRUCT(search);
81         search.in.dest_address = NULL;
82         search.in.dest_port = 0;
83         search.in.acct_control = -1;
84         search.in.version = 6;
85
86         printf("Running CLDAP/netlogon for %d seconds\n", timelimit);
87         while (timeval_elapsed(&tv) < timelimit) {
88                 while (num_sent - (state->pass_count+state->fail_count) < 10) {
89                         struct tevent_req *req;
90                         req = cldap_netlogon_send(state, cldap, &search);
91
92                         tevent_req_set_callback(req, request_netlogon_handler, state);
93
94                         num_sent++;
95                         if (num_sent % 50 == 0) {
96                                 if (torture_setting_bool(tctx, "progress", true)) {
97                                         printf("%.1f queries per second (%d failures)  \r", 
98                                                state->pass_count / timeval_elapsed(&tv),
99                                                state->fail_count);
100                                         fflush(stdout);
101                                 }
102                         }
103                 }
104
105                 tevent_loop_once(tctx->ev);
106         }
107
108         while (num_sent != (state->pass_count + state->fail_count)) {
109                 tevent_loop_once(tctx->ev);
110         }
111
112         printf("%.1f queries per second (%d failures)  \n", 
113                state->pass_count / timeval_elapsed(&tv),
114                state->fail_count);
115
116         talloc_free(cldap);
117         return true;
118 }
119
120 static void request_rootdse_handler(struct tevent_req *req)
121 {
122         struct cldap_search io;
123         struct bench_state *state = tevent_req_callback_data(req, struct bench_state);
124         NTSTATUS status;
125         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
126         status = cldap_search_recv(req, tmp_ctx, &io);
127         talloc_free(req);
128         if (NT_STATUS_IS_OK(status)) {
129                 state->pass_count++;
130         } else {
131                 state->fail_count++;
132         }
133         talloc_free(tmp_ctx);
134 }
135
136 /*
137   benchmark cldap netlogon calls
138 */
139 static bool bench_cldap_rootdse(struct torture_context *tctx, const char *address)
140 {
141         struct cldap_socket *cldap;
142         int num_sent=0;
143         struct timeval tv = timeval_current();
144         int timelimit = torture_setting_int(tctx, "timelimit", 10);
145         struct cldap_search search;
146         struct bench_state *state;
147         NTSTATUS status;
148         struct tsocket_address *dest_addr;
149         int ret;
150
151         ret = tsocket_address_inet_from_strings(tctx, "ip",
152                                                 address,
153                                                 lp_cldap_port(tctx->lp_ctx),
154                                                 &dest_addr);
155         CHECK_VAL(ret, 0);
156
157         /* cldap_socket_init should now know about the dest. address */
158         status = cldap_socket_init(tctx, tctx->ev, NULL, dest_addr, &cldap);
159         torture_assert_ntstatus_ok(tctx, status, "cldap_socket_init");
160
161         state = talloc_zero(tctx, struct bench_state);
162
163         ZERO_STRUCT(search);
164         search.in.dest_address  = NULL;
165         search.in.dest_port     = 0;
166         search.in.filter        = "(objectClass=*)";
167         search.in.timeout       = 2;
168         search.in.retries       = 1;
169
170         printf("Running CLDAP/rootdse for %d seconds\n", timelimit);
171         while (timeval_elapsed(&tv) < timelimit) {
172                 while (num_sent - (state->pass_count+state->fail_count) < 10) {
173                         struct tevent_req *req;
174                         req = cldap_search_send(state, cldap, &search);
175
176                         tevent_req_set_callback(req, request_rootdse_handler, state);
177
178                         num_sent++;
179                         if (num_sent % 50 == 0) {
180                                 if (torture_setting_bool(tctx, "progress", true)) {
181                                         printf("%.1f queries per second (%d failures)  \r",
182                                                state->pass_count / timeval_elapsed(&tv),
183                                                state->fail_count);
184                                         fflush(stdout);
185                                 }
186                         }
187                 }
188
189                 tevent_loop_once(tctx->ev);
190         }
191
192         while (num_sent != (state->pass_count + state->fail_count)) {
193                 tevent_loop_once(tctx->ev);
194         }
195
196         printf("%.1f queries per second (%d failures)  \n",
197                state->pass_count / timeval_elapsed(&tv),
198                state->fail_count);
199
200         talloc_free(cldap);
201         return true;
202 }
203
204 /*
205   benchmark how fast a CLDAP server can respond to a series of parallel
206   requests 
207 */
208 bool torture_bench_cldap(struct torture_context *torture)
209 {
210         const char *address;
211         struct nbt_name name;
212         NTSTATUS status;
213         bool ret = true;
214         
215         make_nbt_name_server(&name, torture_setting_string(torture, "host", NULL));
216
217         /* do an initial name resolution to find its IP */
218         status = resolve_name(lp_resolve_context(torture->lp_ctx), &name, torture, &address, torture->ev);
219         if (!NT_STATUS_IS_OK(status)) {
220                 printf("Failed to resolve %s - %s\n",
221                        name.name, nt_errstr(status));
222                 return false;
223         }
224
225         ret &= bench_cldap_netlogon(torture, address);
226         ret &= bench_cldap_rootdse(torture, address);
227
228         return ret;
229 }