r25554: Convert last instances of BOOL, True and False to the standard types.
[jra/samba/.git] / source4 / torture / nbench / nbench.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB torture tester - NBENCH test
4    Copyright (C) Andrew Tridgell 1997-2004
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 #include "includes.h"
21 #include "libcli/libcli.h"
22 #include "torture/ui.h"
23 #include "torture/util.h"
24 #include "torture/torture.h"
25 #include "system/filesys.h"
26 #include "system/locale.h"
27 #include "pstring.h"
28
29 #include "torture/nbench/proto.h"
30
31 int nbench_line_count = 0;
32 static int timelimit = 600;
33 static int warmup;
34 static const char *loadfile;
35 static int read_only;
36
37 #define ival(s) strtoll(s, NULL, 0)
38
39 static unsigned long nb_max_retries;
40
41 #define NB_RETRY(op) \
42         for (n=0;n<=nb_max_retries && !op;n++) do_reconnect(&cli, client)
43
44 static void do_reconnect(struct smbcli_state **cli, int client)
45 {
46         int n;
47         printf("[%d] Reconnecting client %d\n", nbench_line_count, client);
48         for (n=0;n<nb_max_retries;n++) {
49                 if (nb_reconnect(cli, client)) {
50                         printf("[%d] Reconnected client %d\n", nbench_line_count, client);
51                         return;
52                 }
53         }
54         printf("[%d] Failed to reconnect client %d\n", nbench_line_count, client);
55         nb_exit(1);
56 }
57
58 /* run a test that simulates an approximate netbench client load */
59 static bool run_netbench(struct torture_context *tctx, struct smbcli_state *cli, int client)
60 {
61         int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
62         int i;
63         pstring line;
64         char *cname;
65         FILE *f;
66         bool correct = true;
67         double target_rate = torture_setting_double(tctx, "targetrate", 0);     
68         int n;
69
70         if (target_rate != 0 && client == 0) {
71                 printf("Targetting %.4f MByte/sec\n", target_rate);
72         }
73
74         nb_setup(cli, client);
75
76         if (torture_nprocs == 1) {
77                 if (!read_only) {
78                         NB_RETRY(torture_setup_dir(cli, "\\clients"));
79                 }
80         }
81
82         asprintf(&cname, "client%d", client+1);
83
84         f = fopen(loadfile, "r");
85
86         if (!f) {
87                 perror(loadfile);
88                 return false;
89         }
90
91 again:
92         nbio_time_reset();
93
94         while (fgets(line, sizeof(line)-1, f)) {
95                 NTSTATUS status;
96                 const char **params0, **params;
97
98                 nbench_line_count++;
99
100                 line[strlen(line)-1] = 0;
101
102                 all_string_sub(line,"client1", cname, sizeof(line));
103                 
104                 params = params0 = str_list_make_shell(NULL, line, " ");
105                 i = str_list_length(params);
106
107                 if (i > 0 && isdigit(params[0][0])) {
108                         double targett = strtod(params[0], NULL);
109                         if (target_rate != 0) {
110                                 nbio_target_rate(target_rate);
111                         } else {
112                                 nbio_time_delay(targett);
113                         }
114                         params++;
115                         i--;
116                 } else if (target_rate != 0) {
117                         nbio_target_rate(target_rate);
118                 }
119
120                 if (i < 2 || params[0][0] == '#') continue;
121
122                 if (!strncmp(params[0],"SMB", 3)) {
123                         printf("ERROR: You are using a dbench 1 load file\n");
124                         nb_exit(1);
125                 }
126
127                 if (strncmp(params[i-1], "NT_STATUS_", 10) != 0 &&
128                     strncmp(params[i-1], "0x", 2) != 0) {
129                         printf("Badly formed status at line %d\n", nbench_line_count);
130                         talloc_free(params);
131                         continue;
132                 }
133
134                 /* accept numeric or string status codes */
135                 if (strncmp(params[i-1], "0x", 2) == 0) {
136                         status = NT_STATUS(strtoul(params[i-1], NULL, 16));
137                 } else {
138                         status = nt_status_string_to_code(params[i-1]);
139                 }
140
141                 DEBUG(9,("run_netbench(%d): %s %s\n", client, params[0], params[1]));
142
143                 if (!strcmp(params[0],"NTCreateX")) {
144                         NB_RETRY(nb_createx(params[1], ival(params[2]), ival(params[3]), 
145                                             ival(params[4]), status));
146                 } else if (!strcmp(params[0],"Close")) {
147                         NB_RETRY(nb_close(ival(params[1]), status));
148                 } else if (!read_only && !strcmp(params[0],"Rename")) {
149                         NB_RETRY(nb_rename(params[1], params[2], status, n>0));
150                 } else if (!read_only && !strcmp(params[0],"Unlink")) {
151                         NB_RETRY(nb_unlink(params[1], ival(params[2]), status, n>0));
152                 } else if (!read_only && !strcmp(params[0],"Deltree")) {
153                         NB_RETRY(nb_deltree(params[1], n>0));
154                 } else if (!read_only && !strcmp(params[0],"Rmdir")) {
155                         NB_RETRY(nb_rmdir(params[1], status, n>0));
156                 } else if (!read_only && !strcmp(params[0],"Mkdir")) {
157                         NB_RETRY(nb_mkdir(params[1], status, n>0));
158                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
159                         NB_RETRY(nb_qpathinfo(params[1], ival(params[2]), status));
160                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
161                         NB_RETRY(nb_qfileinfo(ival(params[1]), ival(params[2]), status));
162                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
163                         NB_RETRY(nb_qfsinfo(ival(params[1]), status));
164                 } else if (!read_only && !strcmp(params[0],"SET_FILE_INFORMATION")) {
165                         NB_RETRY(nb_sfileinfo(ival(params[1]), ival(params[2]), status));
166                 } else if (!strcmp(params[0],"FIND_FIRST")) {
167                         NB_RETRY(nb_findfirst(params[1], ival(params[2]), 
168                                               ival(params[3]), ival(params[4]), status));
169                 } else if (!read_only && !strcmp(params[0],"WriteX")) {
170                         NB_RETRY(nb_writex(ival(params[1]), 
171                                            ival(params[2]), ival(params[3]), ival(params[4]),
172                                            status));
173                 } else if (!read_only && !strcmp(params[0],"Write")) {
174                         NB_RETRY(nb_write(ival(params[1]), 
175                                           ival(params[2]), ival(params[3]), ival(params[4]),
176                                           status));
177                 } else if (!strcmp(params[0],"LockX")) {
178                         NB_RETRY(nb_lockx(ival(params[1]), 
179                                           ival(params[2]), ival(params[3]), status));
180                 } else if (!strcmp(params[0],"UnlockX")) {
181                         NB_RETRY(nb_unlockx(ival(params[1]), 
182                                             ival(params[2]), ival(params[3]), status));
183                 } else if (!strcmp(params[0],"ReadX")) {
184                         NB_RETRY(nb_readx(ival(params[1]), 
185                                           ival(params[2]), ival(params[3]), ival(params[4]),
186                                           status));
187                 } else if (!strcmp(params[0],"Flush")) {
188                         NB_RETRY(nb_flush(ival(params[1]), status));
189                 } else if (!strcmp(params[0],"Sleep")) {
190                         nb_sleep(ival(params[1]), status);
191                 } else {
192                         printf("[%d] Unknown operation %s\n", nbench_line_count, params[0]);
193                 }
194
195                 if (n > nb_max_retries) {
196                         printf("Maximum reconnect retries reached for op '%s'\n", params[0]);
197                         nb_exit(1);
198                 }
199
200                 talloc_free(params0);
201                 
202                 if (nb_tick()) goto done;
203         }
204
205         rewind(f);
206         goto again;
207
208 done:
209         fclose(f);
210
211         if (!read_only && torture_nprocs == 1) {
212                 smbcli_deltree(cli->tree, "\\clients");
213         }
214         if (!torture_close_connection(cli)) {
215                 correct = false;
216         }
217         
218         return correct;
219 }
220
221
222 /* run a test that simulates an approximate netbench client load */
223 bool torture_nbench(struct torture_context *torture)
224 {
225         bool correct = true;
226         int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
227         struct smbcli_state *cli;
228         const char *p;
229
230         read_only = torture_setting_bool(torture, "readonly", false);
231
232         nb_max_retries = torture_setting_int(torture, "nretries", 1);
233
234         p = torture_setting_string(torture, "timelimit", NULL);
235         if (p && *p) {
236                 timelimit = atoi(p);
237         }
238
239         warmup = timelimit / 20;
240
241         loadfile = torture_setting_string(torture, "loadfile", NULL);
242         if (!loadfile || !*loadfile) {
243                 loadfile = "client.txt";
244         }
245
246         if (torture_nprocs > 1) {
247                 if (!torture_open_connection(&cli, 0)) {
248                         return false;
249                 }
250
251                 if (!read_only && !torture_setup_dir(cli, "\\clients")) {
252                         return false;
253                 }
254         }
255
256         nbio_shmem(torture_nprocs, timelimit, warmup);
257
258         printf("Running for %d seconds with load '%s' and warmup %d secs\n", 
259                timelimit, loadfile, warmup);
260
261         /* we need to reset SIGCHLD here as the name resolution
262            library may have changed it. We rely on correct signals
263            from childs in the main torture code which reaps
264            children. This is why smbtorture BENCH-NBENCH was sometimes
265            failing */
266         signal(SIGCHLD, SIG_DFL);
267
268
269         signal(SIGALRM, nb_alarm);
270         alarm(1);
271         torture_create_procs(torture, run_netbench, &correct);
272         alarm(0);
273
274         if (!read_only && torture_nprocs > 1) {
275                 smbcli_deltree(cli->tree, "\\clients");
276         }
277
278         printf("\nThroughput %g MB/sec\n", nbio_result());
279         return correct;
280 }
281
282 NTSTATUS torture_nbench_init(void)
283 {
284         struct torture_suite *suite = 
285                 torture_suite_create(
286                         talloc_autofree_context(),
287                         "BENCH");
288
289         torture_suite_add_simple_test(suite, "NBENCH", torture_nbench);
290
291         suite->description = talloc_strdup(suite, "Benchmarks");
292
293         torture_register_suite(suite);
294         return NT_STATUS_OK;
295 }