1 /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
17 #include "../config.h"
18
19 #include <ctype.h>
20 #include <math.h>
21
22 #include "die.h"
23 #include "smack.h"
24 #include "engines.h"
25 #include "parse.h"
26
27 extern int yylineno;
28
29 map <string, Query*, less<string> > query_pool;
30 map <string, Dictionary*, less<string> > dict_pool;
31 map <string, Client*, less<string> > client_pool;
32 map<string, Val*, less<string> > var_hash;
33 string current_client = "main";
34 vector<int> client_pids;
35
Query_def_line(string & str)36 Query_def_line::Query_def_line(string& str):str(str)
37 {
38 }
39
set_q_param(Query * q)40 void Query_name_def_line::set_q_param(Query* q)
41 {
42 q->name = str;
43 }
44
set_q_param(Query * q)45 void Query_query_def_line::set_q_param(Query* q)
46 {
47 q->query = str;
48 }
49
set_q_param(Query * q)50 void Query_type_def_line::set_q_param(Query* q)
51 {
52 q->type_name = str;
53 }
54
set_q_param(Query * q)55 void Query_has_result_set_def_line::set_q_param(Query* q)
56 {
57 q->has_result_set = (tolower(str[0]) == 'y');
58 }
59
set_q_param(Query * q)60 void Query_parsed_def_line::set_q_param(Query* q)
61 {
62 q->parsed = (tolower(str[0]) == 'y');
63 }
64
make_dict()65 Dictionary* Dict_def::make_dict()
66 {
67 Dictionary* dict = NULL;
68
69 if(dict_type == "rand")
70 {
71 dict = new Rand_dictionary;
72 }
73 else if(dict_type == "seq")
74 {
75 dict = new Seq_dictionary;
76 }
77 else if(dict_type == "unique")
78 {
79 dict = new Unique_dictionary;
80 }
81 else
82 die(0, "unknown dictionary type '%s' on line %d", dict_type.c_str(),
83 yylineno);
84
85 if(file_size_equiv.length())
86 dict->file_size_equiv = atoi(file_size_equiv.c_str());
87 if(delim.length())
88 dict->delim = delim[0];
89
90 if(source_type == "file")
91 {
92 dict->load_file(source.c_str());
93 }
94 else if(source_type == "list")
95 {
96 dict->load_list(source.c_str());
97 }
98 else if(source_type == "template")
99 {
100 if(!(dict_type == "unique"))
101 die(0, "line %d: template source type is supported only for \
102 dictionaries of type 'unique'", yylineno);
103 ((Unique_dictionary*)dict)->set_template(source.c_str());
104 }
105 else
106 die(0, "unknown dictionary source type: '%s' on line %d",
107 source_type.c_str(), yylineno);
108
109 dict->name = name;
110
111 return dict;
112 }
113
update_dict_def(Dict_def & d)114 void Dict_dict_type_def_line::update_dict_def(Dict_def& d)
115 {
116 d.dict_type = str;
117 }
118
update_dict_def(Dict_def & d)119 void Dict_source_type_def_line::update_dict_def(Dict_def& d)
120 {
121 d.source_type = str;
122 }
123
update_dict_def(Dict_def & d)124 void Dict_source_def_line::update_dict_def(Dict_def& d)
125 {
126 d.source = str;
127 }
128
update_dict_def(Dict_def & d)129 void Dict_delim_def_line::update_dict_def(Dict_def& d)
130 {
131 d.delim = str;
132 }
133
update_dict_def(Dict_def & d)134 void Dict_file_size_equiv_def_line::update_dict_def(Dict_def& d)
135 {
136 d.file_size_equiv = str;
137 }
138
Table_def_line(string & str)139 Table_def_line::Table_def_line(string& str):str(str)
140 {
141 }
142
validate_table(string & name)143 void Table_def::validate_table(string& name)
144 {
145 Client* c = client_pool[client];
146 if(!c)
147 die(0, "Missing or undefined client in the table section on line %d",
148 yylineno);
149 Table t;
150 bool do_create = 0, do_drop = 0;
151 int min_rows_lim = atoi(min_rows.c_str());
152 c->connect();
153 t.name = name;
154 if(c->get_table_info(t))
155 {
156 do_create = 1;
157 }
158 else
159 {
160 if(t.num_rows < min_rows_lim)
161 {
162 do_drop = 1;
163 do_create = 1;
164 }
165 }
166
167 if(do_drop)
168 {
169 cout << "Table '" << name <<
170 "' does not meet condtions, will be dropped" << endl;
171 string query = "drop table ";
172 query += name;
173 c->safe_query(query.c_str());
174 }
175
176 if(do_create)
177 {
178 char path[MAX_PATH];
179 const char* file = mk_data_path(path, data_file.c_str());
180 struct stat f;
181 cout << "Creating table '" << name << "'" << endl;
182 c->safe_query(create_st.c_str());
183 if(stat(file, &f) && populate_data_file(file, gen_data_file.c_str()))
184 die(1, "Error generating data file");
185 cout << "Loading data from file '" << file << "' into table '" << name <<
186 "'" << endl;
187 c->load_table_data(name, file);
188 cout << "Table " << name << " is now ready for the test" << endl;
189 }
190
191 c->disconnect();
192 }
193
update_table_def(Table_def * t)194 void Table_client_def_line::update_table_def(Table_def* t)
195 {
196 t->client = str;
197 }
198
update_table_def(Table_def * t)199 void Table_create_def_line::update_table_def(Table_def* t)
200 {
201 t->create_st = str;
202 }
203
update_table_def(Table_def * t)204 void Table_min_rows_def_line::update_table_def(Table_def* t)
205 {
206 t->min_rows = str;
207 }
208
update_table_def(Table_def * t)209 void Table_data_file_def_line::update_table_def(Table_def* t)
210 {
211 t->data_file = str;
212 }
213
update_table_def(Table_def * t)214 void Table_gen_data_file_def_line::update_table_def(Table_def* t)
215 {
216 t->gen_data_file = str;
217 }
218
219
make_client()220 Client* Client_def::make_client()
221 {
222 Client* c;
223 c = new_client(db_type);
224 c->user = user;
225 c->pass = pass;
226 c->db = db;
227 c->host = host;
228 c->socket = this->socket;
229 c->port = port;
230
231 if(qb)
232 c->set_query_barrel(qb);
233
234 c->set_dictionary_pool(&dict_pool);
235
236 return c;
237 }
238
update_client_def(Client_def & cd)239 void Client_query_barrel_def_line::update_client_def(Client_def& cd)
240 {
241 int str_len = str.size();
242 char buf[str_len + 1];
243 int i,j = 0;
244 int last_was_space = 1;
245 int num_shots = 0;
246 enum {NUM_SHOTS, QUERY_NAME,SLEEP_TIME} parse_state = NUM_SHOTS;
247 cd.qb = new Query_barrel;
248
249 for(i = 0; i < str_len; i++)
250 {
251 if(str[i] == ' ')
252 if(last_was_space)
253 continue;
254 else
255 {
256 last_was_space = 1;
257 buf[j] = 0;
258 j = 0;
259
260 switch(parse_state)
261 {
262 case NUM_SHOTS:
263 if(buf[0] == '-')
264 {
265 float sl = atof(buf+1);
266 int sec,usec;
267 sec = (int)floor(sl);
268 sl -= sec;
269 usec = (int)floor(sl*1000000);
270 cd.qb->add_sleep_action(sec,usec);
271 break;
272 }
273 num_shots = atoi(buf);
274 parse_state = QUERY_NAME;
275 break;
276
277 case QUERY_NAME:
278 {
279 Query* q = query_pool[buf];
280 if(!q)
281 die(0, "query '%s' referenced on line %d has not \
282 been defined", buf, yylineno);
283 cd.qb->add_query_charge(*q, num_shots);
284 parse_state = NUM_SHOTS;
285 break;
286 }
287 }
288 } // else
289 else
290 {
291 last_was_space = 0;
292 buf[j++] = str[i];
293 }
294
295 }
296
297 if(!last_was_space)
298 {
299 buf[j] = 0;
300 if(buf[0] == '-')
301 {
302 float sl = atof(buf+1);
303 int sec,usec;
304 sec = (int)floor(sl);
305 sl -= sec;
306 usec = (int)floor(sl*1000000);
307 cd.qb->add_sleep_action(sec,usec);
308 return;
309 }
310 Query* q = query_pool[buf];
311 if(!q)
312 die(0, "query '%s' referenced on line %d has not been defined",
313 buf, yylineno);
314 cd.qb->add_query_charge(*q, num_shots);
315 }
316 }
317
update_client_def(Client_def & cd)318 void Client_user_def_line::update_client_def(Client_def& cd)
319 {
320 cd.user = str;
321 }
322
update_client_def(Client_def & cd)323 void Client_pass_def_line::update_client_def(Client_def& cd)
324 {
325 cd.pass = str;
326 }
327
update_client_def(Client_def & cd)328 void Client_host_def_line::update_client_def(Client_def& cd)
329 {
330 cd.host = str;
331 }
332
update_client_def(Client_def & cd)333 void Client_socket_def_line::update_client_def(Client_def& cd)
334 {
335 cd.socket = str;
336 }
337
update_client_def(Client_def & cd)338 void Client_port_def_line::update_client_def(Client_def& cd)
339 {
340 cd.port = str;
341 }
342
343
update_client_def(Client_def & cd)344 void Client_db_def_line::update_client_def(Client_def& cd)
345 {
346 cd.db = str;
347 }
348
print()349 void Param_list::print()
350 {
351 if(params.size() > 0)
352 cout << params[0];
353
354 for(int i = 1; i < params.size(); i++)
355 {
356 cout << "," << params[i];
357 }
358 }
359
print()360 void Main_line::print()
361 {
362 cout << "main_line: client: " << client << ",method=" << method ;
363 if(param_list)
364 {
365 cout << ",param_list: " ;
366 param_list->print();
367 }
368
369 cout << endl;
370 }
371
execute()372 void Main_line::execute()
373 {
374 if(!(client == current_client) && !(method == "init"))
375 return;
376
377 Client* c = client_pool[client];
378 if(!c)
379 die(0, "client '%s' referenced on line %d is not defined",
380 client.c_str(), yylineno);
381 if(method == "connect")
382 {
383 c->connect();
384 }
385 else if(method == "init")
386 {
387 if(!(current_client == "main")) return;
388 pid_t pid;
389 switch(pid = fork())
390 {
391 case 0:
392 c->init();
393 current_client = client;
394 break;
395 case -1:
396 die(1, "could not fork()");
397 break;
398
399 default:
400 client_pids.insert(client_pids.end(), pid);
401 break;
402 }
403
404 }
405 else if(method == "sleep")
406 {
407 if(param_list->size() != 2)
408 die(0, "line %d: sleep takes two parameters (sec,ms), you have %d",
409 yylineno, param_list->size());
410 sleep(atoi(param_list->pchar_val(0)));
411 usleep(atoi(param_list->pchar_val(1))/1000);
412 }
413 else if(method == "print")
414 {
415 if(param_list->size() != 1)
416 die(0, "line %d: print takes one parameter, you have %d",
417 yylineno, param_list->size());
418 cout << param_list->pchar_val(0) << endl;
419 }
420 else if(method == "query")
421 {
422 if(param_list->size() != 1)
423 die(0, "line %d: query takes one parameter, you have %d",
424 yylineno, param_list->size());
425 const char* q = param_list->pchar_val(0);
426 c->safe_query(q);
427 }
428 else if(method == "run_save_result")
429 {
430 if(param_list->size() != 2)
431 die(0, "line %d: run_save_result takes two parameters, you have %d",
432 yylineno, param_list->size());
433 const char* q_name = param_list->pchar_val(0);
434 const char* fname = param_list->pchar_val(1);
435 Query *q = query_pool[q_name];
436
437 if(!q)
438 die(0, "line %d: query '%s' has not been defined", yylineno,
439 q_name);
440
441 c->safe_query(*q);
442 if(fname[0] == '-' && !fname[1])
443 fname = NULL;
444 if(q->has_result_set)
445 c->dump_result(fname);
446
447 }
448 else if(method == "run_check_result")
449 {
450 }
451 else if(method == "set_num_rounds")
452 {
453 if(param_list->size() != 1)
454 die(0, "line %d: set_num_rounds takes one parameter, you have %d",
455 yylineno, param_list->size());
456 int num_rounds = param_list->int_val(0);
457 c->set_num_rounds(num_rounds);
458 }
459 else if(method == "disconnect")
460 {
461 c->disconnect();
462 }
463 else if(method == "create_threads")
464 {
465 c->start_clock();
466 if(param_list->size() != 1)
467 die(0, "line %d: create_threads takes one parameter, you have %d",
468 yylineno, param_list->size());
469 int num_threads = param_list->int_val(0);
470 c->create_threads(num_threads);
471 }
472 else if(method == "collect_threads")
473 {
474 c->thread_sync();
475 c->stop_clock();
476 cout << "Query Barrel Report for client " << client << endl;
477 c->print_connect_times();
478 c->print_barrel_report();
479 }
480 else if(method == "unload_query_barrel")
481 {
482 c->unload_query_barrel();
483 }
484 else
485 {
486 die(0, "unknown method '%s' called for client '%s' on line %d",
487 method.c_str(), client.c_str(), yylineno);
488 }
489 }
490
491
492
493
494
495
496