298453dda31727fafc7da54c87c7b41db47c615b
[awesomized/libmemcached] / clients / memslap.c
1 /*
2 * memslap
3 *
4 * (c) Copyright 2009, Schooner Information Technology, Inc.
5 * All rights reserved.
6 * http://www.schoonerinfotech.com/
7 *
8 * Use and distribution licensed under the BSD license. See
9 * the COPYING file for full text.
10 *
11 * Authors:
12 * Brian Aker
13 * Mingqiang Zhuang <mingqiangzhuang@hengtiansoft.com>
14 *
15 */
16 #include <getopt.h>
17 #include <limits.h>
18
19 #include "ms_sigsegv.h"
20 #include "ms_setting.h"
21 #include "ms_thread.h"
22
23 #define PROGRAM_NAME "memslap"
24 #define PROGRAM_DESCRIPTION \
25 "Generates workload against memcached servers."
26
27 /* options */
28 static struct option long_options[]=
29 {
30 { "servers", required_argument, NULL,
31 OPT_SERVERS },
32 { "threads", required_argument, NULL,
33 OPT_THREAD_NUMBER },
34 { "concurrency", required_argument, NULL,
35 OPT_CONCURRENCY },
36 { "conn_sock", required_argument, NULL,
37 OPT_SOCK_PER_CONN },
38 { "execute_number", required_argument, NULL,
39 OPT_EXECUTE_NUMBER },
40 { "time", required_argument, NULL,
41 OPT_TIME },
42 { "cfg_cmd", required_argument, NULL,
43 OPT_CONFIG_CMD },
44 { "win_size", required_argument, NULL,
45 OPT_WINDOW_SIZE },
46 { "fixed_size", required_argument, NULL,
47 OPT_FIXED_LTH },
48 { "verify", required_argument, NULL,
49 OPT_VERIFY },
50 { "division", required_argument, NULL,
51 OPT_GETS_DIVISION },
52 { "stat_freq", required_argument, NULL,
53 OPT_STAT_FREQ },
54 { "exp_verify", required_argument, NULL,
55 OPT_EXPIRE },
56 { "overwrite", required_argument, NULL,
57 OPT_OVERWRITE },
58 { "reconnect", no_argument, NULL,
59 OPT_RECONNECT },
60 { "udp", no_argument, NULL,
61 OPT_UDP },
62 { "facebook", no_argument, NULL,
63 OPT_FACEBOOK_TEST },
64 { "binary", no_argument, NULL,
65 OPT_BINARY_PROTOCOL },
66 { "tps", required_argument, NULL,
67 OPT_TPS },
68 { "rep_write", required_argument, NULL,
69 OPT_REP_WRITE_SRV },
70 { "verbose", no_argument, NULL,
71 OPT_VERBOSE },
72 { "help", no_argument, NULL,
73 OPT_HELP },
74 { "version", no_argument, NULL,
75 OPT_VERSION },
76 { 0, 0, 0, 0 },
77 };
78
79 /* Prototypes */
80 static void ms_sync_lock_init(void);
81 static void ms_sync_lock_destroy(void);
82 static void ms_global_struct_init(void);
83 static void ms_global_struct_destroy(void);
84 static void ms_version_command(const char *command_name);
85 static const char *ms_lookup_help(ms_options_t option);
86 static int64_t ms_parse_time(void);
87 static int64_t ms_parse_size(void);
88 static void ms_options_parse(int argc, char *argv[]);
89 static int ms_check_para(void);
90 static void ms_statistic_init(void);
91 static void ms_stats_init(void);
92 static void ms_print_statistics(int time);
93 static void ms_print_memslap_stats(struct timeval *start_time,
94 struct timeval *end_time);
95 static void ms_monitor_slap_mode(void);
96 void ms_help_command(const char *command_name, const char *description);
97
98
99 /* initialize the global locks */
100 static void ms_sync_lock_init()
101 {
102 ms_global.init_lock.count= 0;
103 pthread_mutex_init(&ms_global.init_lock.lock, NULL);
104 pthread_cond_init(&ms_global.init_lock.cond, NULL);
105
106 ms_global.run_lock.count= 0;
107 pthread_mutex_init(&ms_global.run_lock.lock, NULL);
108 pthread_cond_init(&ms_global.run_lock.cond, NULL);
109
110 pthread_mutex_init(&ms_global.quit_mutex, NULL);
111 pthread_mutex_init(&ms_global.seq_mutex, NULL);
112 } /* ms_sync_lock_init */
113
114
115 /* destroy the global locks */
116 static void ms_sync_lock_destroy()
117 {
118 pthread_mutex_destroy(&ms_global.init_lock.lock);
119 pthread_cond_destroy(&ms_global.init_lock.cond);
120
121 pthread_mutex_destroy(&ms_global.run_lock.lock);
122 pthread_cond_destroy(&ms_global.run_lock.cond);
123
124 pthread_mutex_destroy(&ms_global.quit_mutex);
125 pthread_mutex_destroy(&ms_global.seq_mutex);
126
127 if (ms_setting.stat_freq > 0)
128 {
129 pthread_mutex_destroy(&ms_statistic.stat_mutex);
130 }
131 } /* ms_sync_lock_destroy */
132
133
134 /* initialize the global structure */
135 static void ms_global_struct_init()
136 {
137 ms_sync_lock_init();
138 ms_global.finish_warmup= false;
139 ms_global.time_out= false;
140 }
141
142
143 /* destroy the global structure */
144 static void ms_global_struct_destroy()
145 {
146 ms_sync_lock_destroy();
147 }
148
149
150 /**
151 * output the version information
152 *
153 * @param command_name, the string of this process
154 */
155 static void ms_version_command(const char *command_name)
156 {
157 printf("%s v%u.%u\n", command_name, 1, 0);
158 exit(0);
159 }
160
161
162 /**
163 * get the description of the option
164 *
165 * @param option, option of command line
166 *
167 * @return char*, description of the command option
168 */
169 static const char *ms_lookup_help(ms_options_t option)
170 {
171 switch (option)
172 {
173 case OPT_SERVERS:
174 return
175 "List one or more servers to connect. Servers count must be less than\n"
176 " threads count. e.g.: --servers=localhost:1234,localhost:11211";
177
178 case OPT_VERSION:
179 return "Display the version of the application and then exit.";
180
181 case OPT_HELP:
182 return "Display this message and then exit.";
183
184 case OPT_EXECUTE_NUMBER:
185 return "Number of operations(get and set) to execute for the\n"
186 " given test. Default 1000000.";
187
188 case OPT_THREAD_NUMBER:
189 return
190 "Number of threads to startup, better equal to CPU numbers. Default 8.";
191
192 case OPT_CONCURRENCY:
193 return "Number of concurrency to simulate with load. Default 128.";
194
195 case OPT_FIXED_LTH:
196 return "Fixed length of value.";
197
198 case OPT_VERIFY:
199 return "The proportion of date verification, e.g.: --verify=0.01";
200
201 case OPT_GETS_DIVISION:
202 return "Number of keys to multi-get once. Default 1, means single get.";
203
204 case OPT_TIME:
205 return
206 "How long the test to run, suffix: s-seconds, m-minutes, h-hours,\n"
207 " d-days e.g.: --time=2h.";
208
209 case OPT_CONFIG_CMD:
210 return
211 "Load the configure file to get command,key and value distribution list.";
212
213 case OPT_WINDOW_SIZE:
214 return
215 "Task window size of each concurrency, suffix: K, M e.g.: --win_size=10k.\n"
216 " Default 10k.";
217
218 case OPT_UDP:
219 return
220 "UDP support, default memslap uses TCP, TCP port and UDP port of\n"
221 " server must be same.";
222
223 case OPT_EXPIRE:
224 return
225 "The proportion of objects with expire time, e.g.: --exp_verify=0.01.\n"
226 " Default no object with expire time";
227
228 case OPT_OVERWRITE:
229 return
230 "The proportion of objects need overwrite, e.g.: --overwrite=0.01.\n"
231 " Default never overwrite object.";
232
233 case OPT_STAT_FREQ:
234 return
235 "Frequency of dumping statistic information. suffix: s-seconds,\n"
236 " m-minutes, e.g.: --resp_freq=10s.";
237
238 case OPT_SOCK_PER_CONN:
239 return "Number of TCP socks per concurrency. Default 1.";
240
241 case OPT_RECONNECT:
242 return
243 "Reconnect support, when connection is closed it will be reconnected.";
244
245 case OPT_VERBOSE:
246 return
247 "Whether it outputs detailed information when verification fails.";
248
249 case OPT_FACEBOOK_TEST:
250 return
251 "Whether it enables facebook test feature, set with TCP and multi-get with UDP.";
252
253 case OPT_BINARY_PROTOCOL:
254 return
255 "Whether it enables binary protocol. Default with ASCII protocol.";
256
257 case OPT_TPS:
258 return "Expected throughput, suffix: K, e.g.: --tps=10k.";
259
260 case OPT_REP_WRITE_SRV:
261 return "The first nth servers can write data, e.g.: --rep_write=2.";
262
263 default:
264 return "Forgot to document this option :)";
265 } /* switch */
266 } /* ms_lookup_help */
267
268
269 /**
270 * output the help information
271 *
272 * @param command_name, the string of this process
273 * @param description, description of this process
274 * @param long_options, global options array
275 */
276 void ms_help_command(const char *command_name, const char *description)
277 {
278 char *help_message= NULL;
279
280 printf("%s v%u.%u\n", command_name, 1, 0);
281 printf(" %s\n\n", description);
282 printf(
283 "Usage:\n"
284 " memslap -hV | -s servers [-F config_file] [-t time | -x exe_num] [...]\n\n"
285 "Options:\n");
286
287 for (int x= 0; long_options[x].name; x++)
288 {
289 printf(" -%c, --%s%c\n", long_options[x].val, long_options[x].name,
290 long_options[x].has_arg ? '=' : ' ');
291 if ((help_message= (char *)ms_lookup_help(long_options[x].val)) != NULL)
292 {
293 printf(" %s\n", help_message);
294 }
295 }
296
297 printf(
298 "\nExamples:\n"
299 " memslap -s 127.0.0.1:11211 -S 5s\n"
300 " memslap -s 127.0.0.1:11211 -t 2m -v 0.2 -e 0.05 -b\n"
301 " memslap -s 127.0.0.1:11211 -F config -t 2m -w 40k -S 20s -o 0.2\n"
302 " memslap -s 127.0.0.1:11211 -F config -t 2m -T 4 -c 128 -d 20 -P 40k\n"
303 " memslap -s 127.0.0.1:11211 -F config -t 2m -d 50 -a -n 40\n"
304 " memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m\n"
305 " memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m -p 2\n\n");
306
307 exit(0);
308 } /* ms_help_command */
309
310
311 /* used to parse the time string */
312 static int64_t ms_parse_time()
313 {
314 int64_t ret= 0;
315 char unit= optarg[strlen(optarg) - 1];
316
317 optarg[strlen(optarg) - 1]= '\0';
318 ret= atoi(optarg);
319
320 switch (unit)
321 {
322 case 'd':
323 case 'D':
324 ret*= 24;
325
326 case 'h':
327 case 'H':
328 ret*= 60;
329
330 case 'm':
331 case 'M':
332 ret*= 60;
333
334 case 's':
335 case 'S':
336 break;
337
338 default:
339 ret= -1;
340 break;
341 } /* switch */
342
343 return ret;
344 } /* ms_parse_time */
345
346
347 /* used to parse the size string */
348 static int64_t ms_parse_size()
349 {
350 int64_t ret= -1;
351 char unit= optarg[strlen(optarg) - 1];
352
353 optarg[strlen(optarg) - 1]= '\0';
354 ret= strtoll(optarg, (char **)NULL, 10);
355
356 switch (unit)
357 {
358 case 'k':
359 case 'K':
360 ret*= 1024;
361 break;
362
363 case 'm':
364 case 'M':
365 ret*= 1024 * 1024;
366 break;
367
368 case 'g':
369 case 'G':
370 ret*= 1024 * 1024 * 1024;
371 break;
372
373 default:
374 ret= -1;
375 break;
376 } /* switch */
377
378 return ret;
379 } /* ms_parse_size */
380
381
382 /* used to parse the options of command line */
383 static void ms_options_parse(int argc, char *argv[])
384 {
385 int option_index= 0;
386 int option_rv;
387
388 while ((option_rv= getopt_long(argc, argv, "VhURbaBs:x:T:c:X:v:d:"
389 "t:S:F:w:e:o:n:P:p:",
390 long_options, &option_index)) != -1)
391 {
392 switch (option_rv)
393 {
394 case 0:
395 break;
396
397 case OPT_VERSION: /* --version or -V */
398 ms_version_command(PROGRAM_NAME);
399 break;
400
401 case OPT_HELP: /* --help or -h */
402 ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION);
403 break;
404
405 case OPT_SERVERS: /* --servers or -s */
406 ms_setting.srv_str= strdup(optarg);
407 break;
408
409 case OPT_CONCURRENCY: /* --concurrency or -c */
410 ms_setting.nconns= atoi(optarg);
411 if (ms_setting.nconns <= 0)
412 {
413 fprintf(stderr, "Concurrency must be greater than 0.:-)\n");
414 exit(1);
415 }
416 break;
417
418 case OPT_EXECUTE_NUMBER: /* --execute_number or -x */
419 ms_setting.exec_num= atoll(optarg);
420 if (ms_setting.exec_num <= 0)
421 {
422 fprintf(stderr, "Execute number must be greater than 0.:-)\n");
423 exit(1);
424 }
425 break;
426
427 case OPT_THREAD_NUMBER: /* --threads or -T */
428 ms_setting.nthreads= atoi(optarg);
429 if (ms_setting.nthreads <= 0)
430 {
431 fprintf(stderr, "Threads number must be greater than 0.:-)\n");
432 exit(1);
433 }
434 break;
435
436 case OPT_FIXED_LTH: /* --fixed_size or -X */
437 ms_setting.fixed_value_size= (size_t)atoi(optarg);
438 if ((ms_setting.fixed_value_size <= 0)
439 || (ms_setting.fixed_value_size > MAX_VALUE_SIZE))
440 {
441 fprintf(stderr, "Value size must be between 0 and 1M.:-)\n");
442 exit(1);
443 }
444 break;
445
446 case OPT_VERIFY: /* --verify or -v */
447 ms_setting.verify_percent= atof(optarg);
448 if ((ms_setting.verify_percent <= 0)
449 || (ms_setting.verify_percent > 1.0))
450 {
451 fprintf(stderr, "Data verification rate must be "
452 "greater than 0 and less than 1.0. :-)\n");
453 exit(1);
454 }
455 break;
456
457 case OPT_GETS_DIVISION: /* --division or -d */
458 ms_setting.mult_key_num= atoi(optarg);
459 if (ms_setting.mult_key_num <= 0)
460 {
461 fprintf(stderr, "Multi-get key number must be greater than 0.:-)\n");
462 exit(1);
463 }
464 break;
465
466 case OPT_TIME: /* --time or -t */
467 ms_setting.run_time= (int)ms_parse_time();
468 if (ms_setting.run_time == -1)
469 {
470 fprintf(stderr, "Please specify the run time. :-)\n"
471 "'s' for second, 'm' for minute, 'h' for hour, "
472 "'d' for day. e.g.: --time=24h (means 24 hours).\n");
473 exit(1);
474 }
475
476 if (ms_setting.run_time == 0)
477 {
478 fprintf(stderr, "Running time can not be 0. :-)\n");
479 exit(1);
480 }
481 break;
482
483 case OPT_CONFIG_CMD: /* --cfg_cmd or -F */
484 ms_setting.cfg_file= strdup(optarg);
485 break;
486
487 case OPT_WINDOW_SIZE: /* --win_size or -w */
488 ms_setting.win_size= (size_t)ms_parse_size();
489 if (ms_setting.win_size == (size_t)-1)
490 {
491 fprintf(
492 stderr,
493 "Please specify the item window size. :-)\n"
494 "e.g.: --win_size=10k (means 10k task window size).\n");
495 exit(1);
496 }
497 break;
498
499 case OPT_UDP: /* --udp or -U*/
500 ms_setting.udp= true;
501 break;
502
503 case OPT_EXPIRE: /* --exp_verify or -e */
504 ms_setting.exp_ver_per= atof(optarg);
505 if ((ms_setting.exp_ver_per <= 0) || (ms_setting.exp_ver_per > 1.0))
506 {
507 fprintf(stderr, "Expire time verification rate must be "
508 "greater than 0 and less than 1.0. :-)\n");
509 exit(1);
510 }
511 break;
512
513 case OPT_OVERWRITE: /* --overwrite or -o */
514 ms_setting.overwrite_percent= atof(optarg);
515 if ((ms_setting.overwrite_percent <= 0)
516 || (ms_setting.overwrite_percent > 1.0))
517 {
518 fprintf(stderr, "Objects overwrite rate must be "
519 "greater than 0 and less than 1.0. :-)\n");
520 exit(1);
521 }
522 break;
523
524 case OPT_STAT_FREQ: /* --stat_freq or -S */
525 ms_setting.stat_freq= (int)ms_parse_time();
526 if (ms_setting.stat_freq == -1)
527 {
528 fprintf(stderr, "Please specify the frequency of dumping "
529 "statistic information. :-)\n"
530 "'s' for second, 'm' for minute, 'h' for hour, "
531 "'d' for day. e.g.: --time=24h (means 24 hours).\n");
532 exit(1);
533 }
534
535 if (ms_setting.stat_freq == 0)
536 {
537 fprintf(stderr, "The frequency of dumping statistic information "
538 "can not be 0. :-)\n");
539 exit(1);
540 }
541 break;
542
543 case OPT_SOCK_PER_CONN: /* --conn_sock or -n */
544 ms_setting.sock_per_conn= atoi(optarg);
545 if (ms_setting.sock_per_conn <= 0)
546 {
547 fprintf(stderr, "Number of socks of each concurrency "
548 "must be greater than 0.:-)\n");
549 exit(1);
550 }
551 break;
552
553 case OPT_RECONNECT: /* --reconnect or -R */
554 ms_setting.reconnect= true;
555 break;
556
557 case OPT_VERBOSE: /* --verbose or -b */
558 ms_setting.verbose= true;
559 break;
560
561 case OPT_FACEBOOK_TEST: /* --facebook or -a */
562 ms_setting.facebook_test= true;
563 break;
564
565 case OPT_BINARY_PROTOCOL: /* --binary or -B */
566 ms_setting.binary_prot= true;
567 break;
568
569 case OPT_TPS: /* --tps or -P */
570 ms_setting.expected_tps= (int)ms_parse_size();
571 if (ms_setting.expected_tps == -1)
572 {
573 fprintf(stderr,
574 "Please specify the item expected throughput. :-)\n"
575 "e.g.: --tps=10k (means 10k throughput).\n");
576 exit(1);
577 }
578 break;
579
580 case OPT_REP_WRITE_SRV: /* --rep_write or -p */
581 ms_setting.rep_write_srv= atoi(optarg);
582 if (ms_setting.rep_write_srv <= 0)
583 {
584 fprintf(stderr,
585 "Number of replication writing server must be greater "
586 "than 0.:-)\n");
587 exit(1);
588 }
589 break;
590
591 case '?':
592 /* getopt_long already printed an error message. */
593 exit(1);
594
595 default:
596 abort();
597 } /* switch */
598 }
599 } /* ms_options_parse */
600
601
602 static int ms_check_para()
603 {
604 if (ms_setting.srv_str == NULL)
605 {
606 fprintf(stderr, "No Servers provided.\n\n");
607 return -1;
608 }
609
610 if (ms_setting.nconns % ms_setting.nthreads != 0)
611 {
612 fprintf(stderr, "Concurrency must be the multiples of threads count.\n");
613 return -1;
614 }
615
616 if (ms_setting.win_size % UNIT_ITEMS_COUNT != 0)
617 {
618 fprintf(stderr, "Window size must be the multiples of 1024.\n\n");
619 return -1;
620 }
621
622 return 0;
623 } /* ms_check_para */
624
625
626 /* initialize the statistic structure */
627 static void ms_statistic_init()
628 {
629 pthread_mutex_init(&ms_statistic.stat_mutex, NULL);
630 ms_init_stats(&ms_statistic.get_stat, "Get");
631 ms_init_stats(&ms_statistic.set_stat, "Set");
632 ms_init_stats(&ms_statistic.total_stat, "Total");
633 } /* ms_statistic_init */
634
635
636 /* initialize the global state structure */
637 static void ms_stats_init()
638 {
639 memset(&ms_stats, 0, sizeof(ms_stats_t));
640 if (ms_setting.stat_freq > 0)
641 {
642 ms_statistic_init();
643 }
644 } /* ms_stats_init */
645
646
647 /* use to output the statistic */
648 static void ms_print_statistics(int in_time)
649 {
650 int obj_size= (int)(ms_setting.avg_key_size + ms_setting.avg_val_size);
651
652 printf("\033[1;1H\033[2J\n");
653 ms_dump_format_stats(&ms_statistic.get_stat, in_time,
654 ms_setting.stat_freq, obj_size);
655 ms_dump_format_stats(&ms_statistic.set_stat, in_time,
656 ms_setting.stat_freq, obj_size);
657 ms_dump_format_stats(&ms_statistic.total_stat, in_time,
658 ms_setting.stat_freq, obj_size);
659 } /* ms_print_statistics */
660
661
662 /* used to print the states of memslap */
663 static void ms_print_memslap_stats(struct timeval *start_time,
664 struct timeval *end_time)
665 {
666 char buf[1024];
667 char *pos= buf;
668
669 pos+= sprintf(pos,
670 "cmd_get: %llu\n",
671 (unsigned long long)ms_stats.cmd_get);
672 pos+= sprintf(pos,
673 "cmd_set: %llu\n",
674 (unsigned long long)ms_stats.cmd_set);
675 pos+= sprintf(pos,
676 "get_misses: %llu\n",
677 (unsigned long long)ms_stats.get_misses);
678
679 if (ms_setting.verify_percent > 0)
680 {
681 pos+= sprintf(pos, "verify_misses: %llu\n",
682 (unsigned long long)ms_stats.vef_miss);
683 pos+= sprintf(pos, "verify_failed: %llu\n",
684 (unsigned long long)ms_stats.vef_failed);
685 }
686
687 if (ms_setting.exp_ver_per > 0)
688 {
689 pos+= sprintf(pos, "expired_get: %llu\n",
690 (unsigned long long)ms_stats.exp_get);
691 pos+= sprintf(pos, "unexpired_unget: %llu\n",
692 (unsigned long long)ms_stats.unexp_unget);
693 }
694
695 pos+= sprintf(pos,
696 "written_bytes: %llu\n",
697 (unsigned long long)ms_stats.bytes_written);
698 pos+= sprintf(pos,
699 "read_bytes: %llu\n",
700 (unsigned long long)ms_stats.bytes_read);
701 pos+= sprintf(pos,
702 "object_bytes: %llu\n",
703 (unsigned long long)ms_stats.obj_bytes);
704
705 if (ms_setting.udp || ms_setting.facebook_test)
706 {
707 pos+= sprintf(pos,
708 "packet_disorder: %llu\n",
709 (unsigned long long)ms_stats.pkt_disorder);
710 pos+= sprintf(pos,
711 "packet_drop: %llu\n",
712 (unsigned long long)ms_stats.pkt_drop);
713 pos+= sprintf(pos,
714 "udp_timeout: %llu\n",
715 (unsigned long long)ms_stats.udp_timeout);
716 }
717
718 if (ms_setting.stat_freq > 0)
719 {
720 ms_dump_stats(&ms_statistic.get_stat);
721 ms_dump_stats(&ms_statistic.set_stat);
722 ms_dump_stats(&ms_statistic.total_stat);
723 }
724
725 int64_t time_diff= ms_time_diff(start_time, end_time);
726 pos+= sprintf(
727 pos,
728 "\nRun time: %.1fs Ops: %llu TPS: %.0Lf Net_rate: %.1fM/s\n",
729 (double)time_diff / 1000000,
730 (unsigned long long)(ms_stats.cmd_get + ms_stats.cmd_set),
731 (ms_stats.cmd_get
732 + ms_stats.cmd_set) / ((long double)time_diff / 1000000),
733 (double)(
734 ms_stats.bytes_written
735 + ms_stats.bytes_read) / 1024 / 1024
736 / ((double)time_diff / 1000000));
737
738 fprintf(stdout, "%s", buf);
739 fflush(stdout);
740 } /* ms_print_memslap_stats */
741
742
743 /* the loop of the main thread, wait the work threads to complete */
744 static void ms_monitor_slap_mode()
745 {
746 int second= 0;
747 struct timeval start_time, end_time;
748
749 /* only when there is no set operation it need warm up */
750 if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR)
751 {
752 /* Wait all the connects complete warm up. */
753 pthread_mutex_lock(&ms_global.init_lock.lock);
754 while (ms_global.init_lock.count < ms_setting.nconns)
755 {
756 pthread_cond_wait(&ms_global.init_lock.cond,
757 &ms_global.init_lock.lock);
758 }
759 pthread_mutex_unlock(&ms_global.init_lock.lock);
760 }
761
762 ms_global.finish_warmup= true;
763
764 /* running in "run time" mode, user specify run time */
765 if (ms_setting.run_time > 0)
766 {
767 gettimeofday(&start_time, NULL);
768 while (1)
769 {
770 sleep(1);
771 second++;
772
773 if ((ms_setting.stat_freq > 0) && (second % ms_setting.stat_freq == 0)
774 && ((int32_t)ms_stats.active_conns >= ms_setting.nconns)
775 && (ms_stats.active_conns <= (uint32_t)INT_MAX))
776 {
777 ms_print_statistics(second);
778 }
779
780 if (ms_setting.run_time <= second)
781 {
782 ms_global.time_out= true;
783 break;
784 }
785
786 /* all connections disconnect */
787 if ((second > 5) && (ms_stats.active_conns == 0))
788 {
789 break;
790 }
791 }
792 gettimeofday(&end_time, NULL);
793 sleep(1); /* wait all threads clean up */
794 }
795 else
796 {
797 /* running in "execute number" mode, user specify execute number */
798 gettimeofday(&start_time, NULL);
799
800 /*
801 * We loop until we know that all connects have cleaned up.
802 */
803 pthread_mutex_lock(&ms_global.run_lock.lock);
804 while (ms_global.run_lock.count < ms_setting.nconns)
805 {
806 pthread_cond_wait(&ms_global.run_lock.cond, &ms_global.run_lock.lock);
807 }
808 pthread_mutex_unlock(&ms_global.run_lock.lock);
809
810 gettimeofday(&end_time, NULL);
811 }
812
813 ms_print_memslap_stats(&start_time, &end_time);
814 } /* ms_monitor_slap_mode */
815
816
817 /* the main function */
818 int main(int argc, char *argv[])
819 {
820 srandom((unsigned int)time(NULL));
821 ms_global_struct_init();
822
823 /* initialization */
824 ms_setting_init_pre();
825 ms_options_parse(argc, argv);
826 if (ms_check_para())
827 {
828 ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION);
829 exit(1);
830 }
831 ms_setting_init_post();
832 ms_stats_init();
833 ms_thread_init();
834
835 /* waiting work thread complete its task */
836 ms_monitor_slap_mode();
837
838 /* clean up */
839 ms_thread_cleanup();
840 ms_global_struct_destroy();
841 ms_setting_cleanup();
842
843 return 0;
844 } /* main */