[dbench @ tridge@samba.org-20070716022637-ylnbp60t9smd08gv]
[tridge/dbench.git] / child.c
1 /* 
2    dbench version 3
3
4    Copyright (C) Andrew Tridgell 1999-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 /* This file links against either fileio.c to do operations against a
21    local filesystem (making dbench), or sockio.c to issue SMB-like
22    command packets over a socket (making tbench).
23
24    So, the pattern of operations and the control structure is the same
25    for both benchmarks, but the operations performed are different.
26 */
27
28 #include "dbench.h"
29
30 #define ival(s) strtol(s, NULL, 0)
31
32 static void nb_target_rate(struct child_struct *child, double rate)
33 {
34         static double last_bytes;
35         static struct timeval last_time;
36         double tdelay;
37
38         if (last_bytes == 0) {
39                 last_bytes = child->bytes;
40                 last_time = timeval_current();
41                 return;
42         }
43
44         if (rate != 0) {
45                 tdelay = (child->bytes - last_bytes)/(1.0e6*rate) - timeval_elapsed(&last_time);
46         } else {
47                 tdelay = - timeval_elapsed(&last_time);
48         }
49         if (tdelay > 0 && rate != 0) {
50                 msleep(tdelay*1000);
51         } else {
52                 child->max_latency = MAX(child->max_latency, -tdelay);
53         }
54
55         last_time = timeval_current();
56         last_bytes = child->bytes;
57 }
58
59 static void nb_time_reset(struct child_struct *child)
60 {
61         child->starttime = timeval_current();   
62 }
63
64 static void nb_time_delay(struct child_struct *child, double targett)
65 {
66         double elapsed = timeval_elapsed(&child->starttime);
67         if (targett > elapsed) {
68                 msleep(1000*(targett - elapsed));
69         } else if (elapsed - targett > child->max_latency) {
70                 child->max_latency = MAX(elapsed - targett, child->max_latency);
71         }
72 }
73
74
75
76 /* run a test that simulates an approximate netbench client load */
77 void child_run(struct child_struct *child, const char *loadfile)
78 {
79         int i;
80         char line[1024];
81         char *cname;
82         char **sparams, **params;
83         char *p;
84         const char *status;
85         char *fname = NULL;
86         char *fname2 = NULL;
87         FILE *f = fopen(loadfile, "r");
88         pid_t parent = getppid();
89         double targett;
90
91         child->line = 0;
92
93         asprintf(&cname,"client%d", child->id);
94
95         sparams = calloc(20, sizeof(char *));
96         for (i=0;i<20;i++) {
97                 sparams[i] = malloc(100);
98         }
99
100 again:
101         nb_time_reset(child);
102
103         while (fgets(line, sizeof(line)-1, f)) {
104                 params = sparams;
105
106                 if (child->done || kill(parent, 0) == -1) {
107                         goto done;
108                 }
109
110                 child->line++;
111
112                 line[strlen(line)-1] = 0;
113
114                 all_string_sub(line,"client1", cname);
115                 all_string_sub(line,"\\", "/");
116                 all_string_sub(line," /", " ");
117                 
118                 p = line;
119                 for (i=0; 
120                      i<19 && next_token(&p, params[i], " ");
121                      i++) ;
122
123                 params[i][0] = 0;
124
125                 if (i < 2 || params[0][0] == '#') continue;
126
127                 if (!strncmp(params[0],"SMB", 3)) {
128                         printf("ERROR: You are using a dbench 1 load file\n");
129                         exit(1);
130                 }
131
132                 if (i > 0 && isdigit(params[0][0])) {
133                         targett = strtod(params[0], NULL);
134                         params++;
135                         i--;
136                 } else {
137                         targett = 0.0;
138                 }
139
140                 if (options.targetrate != 0 || targett == 0.0) {
141                         nb_target_rate(child, options.targetrate);
142                 } else {
143                         nb_time_delay(child, targett);
144                 }
145                 child->lasttime = timeval_current();
146
147                 if (strncmp(params[i-1], "NT_STATUS_", 10) != 0 &&
148                     strncmp(params[i-1], "0x", 2) != 0) {
149                         printf("Badly formed status at line %d\n", child->line);
150                         continue;
151                 }
152
153                 if (fname) {
154                         free(fname);
155                         fname = NULL;
156                 }
157                 if (fname2) {
158                         free(fname2);
159                         fname2 = NULL;
160                 }
161
162                 if (i>1 && params[1][0] == '/') {
163                         asprintf(&fname, "%s%s", child->directory, params[1]);
164                 }
165                 if (i>2 && params[2][0] == '/') {
166                         asprintf(&fname2, "%s%s", child->directory, params[2]);
167                 }
168
169                 status = params[i-1];
170
171                 if (!strcmp(params[0],"NTCreateX")) {
172                         nb_createx(child, fname, ival(params[2]), ival(params[3]), 
173                                    ival(params[4]), status);
174                 } else if (!strcmp(params[0],"Close")) {
175                         nb_close(child, ival(params[1]), status);
176                 } else if (!strcmp(params[0],"Rename")) {
177                         nb_rename(child, fname, fname2, status);
178                 } else if (!strcmp(params[0],"Unlink")) {
179                         nb_unlink(child, fname, ival(params[2]), status);
180                 } else if (!strcmp(params[0],"Deltree")) {
181                         nb_deltree(child, fname);
182                 } else if (!strcmp(params[0],"Rmdir")) {
183                         nb_rmdir(child, fname, status);
184                 } else if (!strcmp(params[0],"Mkdir")) {
185                         nb_mkdir(child, fname, status);
186                 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
187                         nb_qpathinfo(child, fname, ival(params[2]), status);
188                 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
189                         nb_qfileinfo(child, ival(params[1]), ival(params[2]), status);
190                 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
191                         nb_qfsinfo(child, ival(params[1]), status);
192                 } else if (!strcmp(params[0],"SET_FILE_INFORMATION")) {
193                         nb_sfileinfo(child, ival(params[1]), ival(params[2]), status);
194                 } else if (!strcmp(params[0],"FIND_FIRST")) {
195                         nb_findfirst(child, fname, ival(params[2]), 
196                                      ival(params[3]), ival(params[4]), status);
197                 } else if (!strcmp(params[0],"WriteX")) {
198                         nb_writex(child, ival(params[1]), 
199                                   ival(params[2]), ival(params[3]), ival(params[4]),
200                                   status);
201                 } else if (!strcmp(params[0],"LockX")) {
202                         nb_lockx(child, ival(params[1]), 
203                                  ival(params[2]), ival(params[3]), status);
204                 } else if (!strcmp(params[0],"UnlockX")) {
205                         nb_unlockx(child, ival(params[1]), 
206                                  ival(params[2]), ival(params[3]), status);
207                 } else if (!strcmp(params[0],"ReadX")) {
208                         nb_readx(child, ival(params[1]), 
209                                  ival(params[2]), ival(params[3]), ival(params[4]),
210                                  status);
211                 } else if (!strcmp(params[0],"Flush")) {
212                         nb_flush(child, ival(params[1]), status);
213                 } else if (!strcmp(params[0],"Sleep")) {
214                         nb_sleep(child, ival(params[1]), status);
215                 } else {
216                         printf("[%d] Unknown operation %s\n", child->line, params[0]);
217                 }
218         }
219
220         rewind(f);
221         goto again;
222
223 done:
224         child->cleanup = 1;
225         fclose(f);
226         nb_cleanup(child);
227 }