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