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