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