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