Merged trunk.
[m6w6/libmemcached] / clients / ms_setting.c
1 /*
2 * File: ms_setting.c
3 * Author: Mingqiang Zhuang
4 *
5 * Created on February 10, 2009
6 *
7 * (c) Copyright 2009, Schooner Information Technology, Inc.
8 * http://www.schoonerinfotech.com/
9 *
10 */
11
12 #include "config.h"
13
14 #include <ctype.h>
15 #include "ms_setting.h"
16 #include "ms_conn.h"
17
18 #define MAX_EXEC_NUM 0x4000000000000000 /* 1 << 62 */
19 #define ADDR_ALIGN(addr) ((addr + 15) & ~(16 - 1)) /* 16 bytes aligned */
20 #define RAND_CHAR_SIZE (10 * 1024 * 1024) /* 10M character table */
21 #define RESERVED_RAND_CHAR_SIZE (2 * 1024 * 1024) /* reserved 2M to avoid pointer sloping over */
22
23 #define DEFAULT_THREADS_NUM 1 /* default start one thread */
24 #define DEFAULT_CONNS_NUM 16 /* default each thread with 16 connections */
25 #define DEFAULT_EXE_NUM 0 /* default execute number is 0 */
26 #define DEFAULT_VERIFY_RATE 0.0 /* default it doesn't do data verification */
27 #define DEFAULT_OVERWRITE_RATE 0.0 /* default it doesn't do overwrite */
28 #define DEFAULT_DIV 1 /* default it runs single get */
29 #define DEFAULT_RUN_TIME 600 /* default run time 10 minutes */
30 #define DEFAULT_WINDOW_SIZE (10 * UNIT_ITEMS_COUNT) /* default window size is 10k */
31 #define DEFAULT_SOCK_PER_CONN 1 /* default socks per connection is 1 */
32
33 /* Use this for string generation */
34 #define CHAR_COUNT 64 /* number of characters used to generate character table */
35 const char ALPHANUMBERICS[]=
36 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-";
37
38 ms_setting_st ms_setting; /* store the settings specified by user */
39
40
41 /* read setting from configuration file */
42 static void ms_get_serverlist(char *str);
43 static int ms_get_cpu_count(void);
44 ms_conf_type_t ms_get_conf_type(char *line);
45 static int ms_is_line_data(char *line);
46 static int ms_read_is_data(char *line, ssize_t nread);
47 static void ms_no_config_file(void);
48 static void ms_parse_cfg_file(char *cfg_file);
49
50
51 /* initialize setting structure */
52 static void ms_init_random_block(void);
53 static void ms_calc_avg_size(void);
54 static int ms_shuffle_distr(ms_distr_t *distr, int length);
55 static void ms_build_distr(void);
56 static void ms_print_setting(void);
57 static void ms_setting_slapmode_init_pre(void);
58 static void ms_setting_slapmode_init_post(void);
59
60
61 /**
62 * parse the server list string, and build the servers
63 * information structure array. this function is used to parse
64 * the command line options specified by user.
65 *
66 * @param str, the string of server list
67 */
68 static void ms_get_serverlist(char *str)
69 {
70 char *string;
71 int64_t port;
72 char *begin_ptr;
73 char *end_ptr= str + strlen(str);
74 ms_mcd_server_t *srvs= NULL;
75 char buffer[512];
76 char *ptr= NULL;
77
78 /**
79 * Servers list format is like this. For example:
80 * "localhost:11108, localhost:11109"
81 */
82 for (begin_ptr= str, string= index(str, ',');
83 begin_ptr != end_ptr;
84 string= index(begin_ptr, ','))
85 {
86 port= 0;
87
88 if (string)
89 {
90 memcpy(buffer, begin_ptr, (size_t)(string - begin_ptr));
91 buffer[(unsigned int)(string - begin_ptr)]= '\0';
92 begin_ptr= string + 1;
93 }
94 else
95 {
96 size_t length= strlen(begin_ptr);
97 memcpy(buffer, begin_ptr, length);
98 buffer[length]= '\0';
99 begin_ptr= end_ptr;
100 }
101
102 ptr= index(buffer, ':');
103
104 if (ptr != NULL)
105 {
106 ptr[0]= '\0';
107 ptr++;
108 port= strtol(ptr, (char **)NULL, 10);
109 }
110
111 assert(ms_setting.srv_cnt < ms_setting.total_srv_cnt);
112 strcpy(ms_setting.servers[ms_setting.srv_cnt].srv_host_name, buffer);
113 ms_setting.servers[ms_setting.srv_cnt].srv_port= (int)port;
114 ms_setting.servers[ms_setting.srv_cnt].disconn_cnt= 0;
115 ms_setting.servers[ms_setting.srv_cnt].reconn_cnt= 0;
116 ms_setting.srv_cnt++;
117
118 if (ms_setting.srv_cnt >= ms_setting.total_srv_cnt)
119 {
120 srvs= (ms_mcd_server_t *)realloc(
121 ms_setting.servers,
122 (uint64_t)ms_setting.total_srv_cnt
123 * sizeof(ms_mcd_server_t) * 2);
124 if (srvs == NULL)
125 {
126 fprintf(stderr, "Can't reallocate servers structure.\n");
127 exit(1);
128 }
129 ms_setting.servers= srvs;
130 ms_setting.total_srv_cnt*= 2;
131 }
132
133 if (isspace(*begin_ptr))
134 begin_ptr++;
135 }
136 } /* ms_get_serverlist */
137
138
139 /**
140 * used to get the CPU count of the current system
141 *
142 * @return return the cpu count if get, else return 1
143 */
144 static int ms_get_cpu_count()
145 {
146 #ifdef HAVE__SC_NPROCESSORS_ONLN
147 return sysconf(_SC_NPROCESSORS_CONF);
148
149 #else
150 # ifdef HAVE_CPU_SET_T
151 int cpu_count= 0;
152 cpu_set_t cpu_set;
153
154 sched_getaffinity(0, sizeof(cpu_set_t), &cpu_set);
155
156 for (int i= 0; i < (sizeof(cpu_set_t) * 8); i++)
157 {
158 if (CPU_ISSET(i, &cpu_set))
159 {
160 cpu_count++;
161 }
162 }
163
164 return cpu_count;
165
166 # endif
167 #endif
168
169 /* the system with one cpu at least */
170 return 1;
171 } /* ms_get_cpu_count */
172
173
174 /**
175 * used to get the configure type based on the type string read
176 * from the configuration file.
177 *
178 * @param line, string of one line
179 *
180 * @return ms_conf_type_t
181 */
182 ms_conf_type_t ms_get_conf_type(char *line)
183 {
184 if (! memcmp(line, "key", strlen("key")))
185 {
186 return CONF_KEY;
187 }
188 else if (! memcmp(line, "value", strlen("value")))
189 {
190 return CONF_VALUE;
191 }
192 else if (! memcmp(line, "cmd", strlen("cmd")))
193 {
194 return CONF_CMD;
195 }
196 else
197 {
198 return CONF_NULL;
199 }
200 } /* ms_get_conf_type */
201
202
203 /**
204 * judge whether the line is a line with useful data. used to
205 * parse the configuration file.
206 *
207 * @param line, string of one line
208 *
209 * @return if success, return 1, else return 0
210 */
211 static int ms_is_line_data(char *line)
212 {
213 assert(line != NULL);
214
215 char *begin_ptr= line;
216
217 while (isspace(*begin_ptr))
218 {
219 begin_ptr++;
220 }
221 if ((begin_ptr[0] == '\0') || (begin_ptr[0] == '#'))
222 return 0;
223
224 return 1;
225 } /* ms_is_line_data */
226
227
228 /**
229 * function to bypass blank line and comments
230 *
231 * @param line, string of one line
232 * @param nread, length of the line
233 *
234 * @return if it's EOF or not line data, return 0, else return 1
235 */
236 static int ms_read_is_data(char *line, ssize_t nread)
237 {
238 if ((nread == EOF) || ! ms_is_line_data(line))
239 return 0;
240
241 return 1;
242 } /* ms_read_is_data */
243
244
245 /**
246 * if no configuration file, use this function to create the default
247 * configuration file.
248 */
249 static void ms_no_config_file()
250 {
251 FILE *fd= fopen("config", "w+");
252
253 fprintf(fd, "%s", DEFAULT_CONGIF_STR);
254 fclose(fd);
255
256 ms_setting.cfg_file= strdup("config");
257 } /* ms_no_config_file */
258
259
260 /**
261 * parse the configuration file
262 *
263 * @param cfg_file, the configuration file name
264 */
265 static void ms_parse_cfg_file(char *cfg_file)
266 {
267 FILE *f;
268 size_t start_len, end_len;
269 double proportion;
270 size_t frequence;
271 char *line= NULL;
272 size_t read_len;
273 ssize_t nread;
274 int cmd_type;
275 ms_conf_type_t conf_type;
276 int end_of_file= 0;
277 ms_key_distr_t *key_distr= NULL;
278 ms_value_distr_t *val_distr= NULL;
279 bool no_cfg= false;
280
281 if (cfg_file == NULL)
282 {
283 ms_no_config_file();
284 cfg_file= ms_setting.cfg_file;
285 no_cfg= true;
286 }
287
288 /*read key value configure file*/
289 if ((f= fopen(cfg_file, "r")) == NULL)
290 {
291 fprintf(stderr, "Can not open file: '%s'.\n", cfg_file);
292 exit(1);
293 }
294
295 while (1)
296 {
297 if ((((nread= getline(&line, &read_len, f)) == 1)
298 || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */
299 continue;
300 if (nread == EOF)
301 {
302 fprintf(stderr, "Bad configuration file, no configuration find.\n");
303 exit(1);
304 }
305 conf_type= ms_get_conf_type(line);
306 break;
307 }
308
309 while (! end_of_file)
310 {
311 switch (conf_type)
312 {
313 case CONF_KEY:
314 while (1)
315 {
316 if ((((nread= getline(&line, &read_len, f)) == 1)
317 || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */
318 continue;
319
320 if (nread != EOF)
321 {
322 if (sscanf(line, "%lu %lu %lf ", &start_len,
323 &end_len, &proportion) != 3)
324 {
325 conf_type= ms_get_conf_type(line);
326 break;
327 }
328 ms_setting.key_distr[ms_setting.key_rng_cnt].start_len= start_len;
329 ms_setting.key_distr[ms_setting.key_rng_cnt].end_len= end_len;
330 ms_setting.key_distr[ms_setting.key_rng_cnt].key_prop= proportion;
331 ms_setting.key_rng_cnt++;
332
333 if (ms_setting.key_rng_cnt >= ms_setting.total_key_rng_cnt)
334 {
335 key_distr= (ms_key_distr_t *)realloc(
336 ms_setting.key_distr,
337 (uint64_t)ms_setting.
338 total_key_rng_cnt * sizeof(ms_key_distr_t) * 2);
339 if (key_distr == NULL)
340 {
341 fprintf(stderr,
342 "Can't reallocate key distribution structure.\n");
343 exit(1);
344 }
345 ms_setting.key_distr= key_distr;
346 ms_setting.total_key_rng_cnt*= 2;
347 }
348 continue;
349 }
350 end_of_file= 1;
351 break;
352 }
353 break;
354
355 case CONF_VALUE:
356 while (1)
357 {
358 if ((((nread= getline(&line, &read_len, f)) == 1)
359 || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */
360 continue;
361
362 if (nread != EOF)
363 {
364 if (sscanf(line, "%lu %lu %lf %lu", &start_len, &end_len,
365 &proportion, &frequence) != 3)
366 {
367 conf_type= ms_get_conf_type(line);
368 break;
369 }
370 ms_setting.value_distr[ms_setting.val_rng_cnt].start_len=
371 start_len;
372 ms_setting.value_distr[ms_setting.val_rng_cnt].end_len= end_len;
373 ms_setting.value_distr[ms_setting.val_rng_cnt].value_prop=
374 proportion;
375 ms_setting.val_rng_cnt++;
376
377 if (ms_setting.val_rng_cnt >= ms_setting.total_val_rng_cnt)
378 {
379 val_distr= (ms_value_distr_t *)realloc(
380 ms_setting.value_distr,
381 (uint64_t)ms_setting.
382 total_val_rng_cnt * sizeof(ms_value_distr_t) * 2);
383 if (val_distr == NULL)
384 {
385 fprintf(stderr,
386 "Can't reallocate key distribution structure.\n");
387 exit(1);
388 }
389 ms_setting.value_distr= val_distr;
390 ms_setting.total_val_rng_cnt*= 2;
391 }
392 continue;
393 }
394 end_of_file= 1;
395 break;
396 }
397 break;
398
399 case CONF_CMD:
400 while (1)
401 {
402 if ((((nread= getline(&line, &read_len, f)) == 1)
403 || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */
404 continue;
405
406 if (nread != EOF)
407 {
408 if (sscanf(line, "%d %lf\n", &cmd_type, &proportion) != 2)
409 {
410 conf_type= ms_get_conf_type(line);
411 break;
412 }
413 ms_setting.cmd_distr[ms_setting.cmd_used_count].cmd_type=
414 cmd_type;
415 ms_setting.cmd_distr[ms_setting.cmd_used_count].cmd_prop=
416 proportion;
417 ms_setting.cmd_used_count++;
418 continue;
419 }
420 end_of_file= 1;
421 break;
422 }
423
424 case CONF_NULL:
425 while (1)
426 {
427 if ((((nread= getline(&line, &read_len, f)) == 1)
428 || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */
429 continue;
430
431 if (nread != EOF)
432 {
433 if ((conf_type= ms_get_conf_type(line)) != CONF_NULL)
434 {
435 break;
436 }
437 continue;
438 }
439 end_of_file= 1;
440 break;
441 }
442 break;
443
444 default:
445 assert(0);
446 break;
447 } /* switch */
448 }
449
450 fclose(f);
451
452 if (no_cfg)
453 {
454 remove(ms_setting.cfg_file);
455 }
456
457 if (line != NULL)
458 free(line);
459 } /* ms_parse_cfg_file */
460
461
462 /* calculate the average size of key and value */
463 static void ms_calc_avg_size()
464 {
465 double avg_val_size= 0.0;
466 double avg_key_size= 0.0;
467 double val_pro= 0.0;
468 double key_pro= 0.0;
469 double averge_len= 0.0;
470 size_t start_len= 0;
471 size_t end_len= 0;
472
473 for (int j= 0; j < ms_setting.val_rng_cnt; j++)
474 {
475 val_pro= ms_setting.value_distr[j].value_prop;
476 start_len= ms_setting.value_distr[j].start_len;
477 end_len= ms_setting.value_distr[j].end_len;
478
479 averge_len= val_pro * ((double)(start_len + end_len)) / 2;
480 avg_val_size+= averge_len;
481 }
482
483 for (int j= 0; j < ms_setting.key_rng_cnt; j++)
484 {
485 key_pro= ms_setting.key_distr[j].key_prop;
486 start_len= ms_setting.key_distr[j].start_len;
487 end_len= ms_setting.key_distr[j].end_len;
488
489 averge_len= key_pro * ((double)(start_len + end_len)) / 2;
490 avg_key_size+= averge_len;
491 }
492
493 ms_setting.avg_val_size= (size_t)avg_val_size;
494 ms_setting.avg_key_size= (size_t)avg_key_size;
495 } /* ms_calc_avg_size */
496
497
498 /**
499 * used to shuffle key and value distribution array to ensure
500 * (key, value) pair with different set.
501 *
502 * @param distr, pointer of distribution structure array
503 * @param length, length of the array
504 *
505 * @return always return 0
506 */
507 static int ms_shuffle_distr(ms_distr_t *distr, int length)
508 {
509 int i, j;
510 int tmp_offset;
511 size_t tmp_size;
512 int64_t rnd;
513
514 for (i= 0; i < length; i++)
515 {
516 rnd= random();
517 j= (int)(rnd % (length - i)) + i;
518
519 switch (rnd % 3)
520 {
521 case 0:
522 tmp_size= distr[j].key_size;
523 distr[j].key_size= distr[i].key_size;
524 distr[i].key_size= tmp_size;
525 break;
526
527 case 1:
528 tmp_offset= distr[j].key_offset;
529 distr[j].key_offset= distr[i].key_offset;
530 distr[i].key_offset= tmp_offset;
531 break;
532
533 case 2:
534 tmp_size= distr[j].value_size;
535 distr[j].value_size= distr[i].value_size;
536 distr[i].value_size= tmp_size;
537 break;
538
539 default:
540 break;
541 } /* switch */
542 }
543
544 return 0;
545 } /* ms_shuffle_distr */
546
547
548 /**
549 * according to the key and value distribution, to build the
550 * (key, value) pair distribution. the (key, value) pair
551 * distribution array is global, each connection set or get
552 * object keeping this distribution, for the final result, we
553 * can reach the expected key and value distribution.
554 */
555 static void ms_build_distr()
556 {
557 int offset= 0;
558 int end= 0;
559 int key_cnt= 0;
560 int value_cnt= 0;
561 size_t average_len= 0;
562 size_t diff_len= 0;
563 size_t start_len= 0;
564 size_t end_len= 0;
565 int rnd= 0;
566 ms_distr_t *distr= NULL;
567 int units= (int)ms_setting.win_size / UNIT_ITEMS_COUNT;
568
569 /* calculate average value size and key size */
570 ms_calc_avg_size();
571
572 ms_setting.char_blk_size= RAND_CHAR_SIZE;
573 int key_scope_size=
574 (int)((ms_setting.char_blk_size - RESERVED_RAND_CHAR_SIZE)
575 / UNIT_ITEMS_COUNT);
576
577 ms_setting.distr= (ms_distr_t *)malloc(
578 sizeof(ms_distr_t) * ms_setting.win_size);
579 if (ms_setting.distr == NULL)
580 {
581 fprintf(stderr, "Can't allocate distribution array.");
582 exit(1);
583 }
584
585 /**
586 * character block is divided by how many different key
587 * size, each different key size has the same size character
588 * range.
589 */
590 for (int m= 0; m < units; m++)
591 {
592 for (int i= 0; i < UNIT_ITEMS_COUNT; i++)
593 {
594 ms_setting.distr[m * UNIT_ITEMS_COUNT + i].key_offset=
595 ADDR_ALIGN(key_scope_size * i);
596 }
597 }
598
599 /* initialize key size distribution */
600 for (int m= 0; m < units; m++)
601 {
602 for (int j= 0; j < ms_setting.key_rng_cnt; j++)
603 {
604 key_cnt= (int)(UNIT_ITEMS_COUNT * ms_setting.key_distr[j].key_prop);
605 start_len= ms_setting.key_distr[j].start_len;
606 end_len= ms_setting.key_distr[j].end_len;
607 if ((start_len < MIN_KEY_SIZE) || (end_len < MIN_KEY_SIZE))
608 {
609 fprintf(stderr, "key length must be greater than 16 bytes.\n");
610 exit(1);
611 }
612
613 if (! ms_setting.binary_prot
614 && ((start_len > MAX_KEY_SIZE) || (end_len > MAX_KEY_SIZE)))
615 {
616 fprintf(stderr, "key length must be less than 250 bytes.\n");
617 exit(1);
618 }
619
620 average_len= (start_len + end_len) / 2;
621 diff_len= (end_len - start_len) / 2;
622 for (int k= 0; k < key_cnt; k++)
623 {
624 if (offset >= (m + 1) * UNIT_ITEMS_COUNT)
625 {
626 break;
627 }
628 rnd= (int)random();
629 if (k % 2 == 0)
630 {
631 ms_setting.distr[offset].key_size=
632 (diff_len == 0) ? average_len :
633 average_len + (size_t)rnd
634 % diff_len;
635 }
636 else
637 {
638 ms_setting.distr[offset].key_size=
639 (diff_len == 0) ? average_len :
640 average_len - (size_t)rnd
641 % diff_len;
642 }
643 offset++;
644 }
645 }
646
647 if (offset < (m + 1) * UNIT_ITEMS_COUNT)
648 {
649 end= (m + 1) * UNIT_ITEMS_COUNT - offset;
650 for (int i= 0; i < end; i++)
651 {
652 ms_setting.distr[offset].key_size= ms_setting.avg_key_size;
653 offset++;
654 }
655 }
656 }
657 offset= 0;
658
659 /* initialize value distribution */
660 if (ms_setting.fixed_value_size != 0)
661 {
662 for (int i= 0; i < units * UNIT_ITEMS_COUNT; i++)
663 {
664 ms_setting.distr[i].value_size= ms_setting.fixed_value_size;
665 }
666 }
667 else
668 {
669 for (int m= 0; m < units; m++)
670 {
671 for (int j= 0; j < ms_setting.val_rng_cnt; j++)
672 {
673 value_cnt=
674 (int)(UNIT_ITEMS_COUNT * ms_setting.value_distr[j].value_prop);
675 start_len= ms_setting.value_distr[j].start_len;
676 end_len= ms_setting.value_distr[j].end_len;
677 if ((start_len <= 0) || (end_len <= 0))
678 {
679 fprintf(stderr, "value length must be greater than 0 bytes.\n");
680 exit(1);
681 }
682
683 if ((start_len > MAX_VALUE_SIZE) || (end_len > MAX_VALUE_SIZE))
684 {
685 fprintf(stderr, "key length must be less than or equal to 1M.\n");
686 exit(1);
687 }
688
689 average_len= (start_len + end_len) / 2;
690 diff_len= (end_len - start_len) / 2;
691 for (int k= 0; k < value_cnt; k++)
692 {
693 if (offset >= (m + 1) * UNIT_ITEMS_COUNT)
694 {
695 break;
696 }
697 rnd= (int)random();
698 if (k % 2 == 0)
699 {
700 ms_setting.distr[offset].value_size=
701 (diff_len == 0) ? average_len :
702 average_len
703 + (size_t)rnd % diff_len;
704 }
705 else
706 {
707 ms_setting.distr[offset].value_size=
708 (diff_len == 0) ? average_len :
709 average_len
710 - (size_t)rnd % diff_len;
711 }
712 offset++;
713 }
714 }
715
716 if (offset < (m + 1) * UNIT_ITEMS_COUNT)
717 {
718 end= (m + 1) * UNIT_ITEMS_COUNT - offset;
719 for (int i= 0; i < end; i++)
720 {
721 ms_setting.distr[offset++].value_size= ms_setting.avg_val_size;
722 }
723 }
724 }
725 }
726
727 /* shuffle distribution */
728 for (int i= 0; i < units; i++)
729 {
730 distr= &ms_setting.distr[i * UNIT_ITEMS_COUNT];
731 for (int j= 0; j < 4; j++)
732 {
733 ms_shuffle_distr(distr, UNIT_ITEMS_COUNT);
734 }
735 }
736 } /* ms_build_distr */
737
738
739 /**
740 * used to initialize the global character block. The character
741 * block is used to generate the suffix of the key and value. we
742 * only store a pointer in the character block for each key
743 * suffix or value string. It can save much memory to store key
744 * or value string.
745 */
746 static void ms_init_random_block()
747 {
748 char *ptr= NULL;
749
750 assert(ms_setting.char_blk_size > 0);
751
752 ms_setting.char_block= (char *)malloc(ms_setting.char_blk_size);
753 if (ms_setting.char_block == NULL)
754 {
755 fprintf(stderr, "Can't allocate global char block.");
756 exit(1);
757 }
758 ptr= ms_setting.char_block;
759
760 for (int i= 0; (size_t)i < ms_setting.char_blk_size; i++)
761 {
762 *(ptr++)= ALPHANUMBERICS[random() % CHAR_COUNT];
763 }
764 } /* ms_init_random_block */
765
766
767 /**
768 * after initialization, call this function to output the main
769 * configuration user specified.
770 */
771 static void ms_print_setting()
772 {
773 fprintf(stdout, "threads count: %d\n", ms_setting.nthreads);
774 fprintf(stdout, "concurrency: %d\n", ms_setting.nconns);
775 if (ms_setting.run_time > 0)
776 {
777 fprintf(stdout, "run time: %ds\n", ms_setting.run_time);
778 }
779 else
780 {
781 fprintf(stdout, "execute number: %ld\n", ms_setting.exec_num);
782 }
783 fprintf(stdout, "windows size: %ldk\n",
784 (int64_t)(ms_setting.win_size / 1024));
785 fprintf(stdout, "set proportion: set_prop=%.2f\n",
786 ms_setting.cmd_distr[CMD_SET].cmd_prop);
787 fprintf(stdout, "get proportion: get_prop=%.2f\n",
788 ms_setting.cmd_distr[CMD_GET].cmd_prop);
789 fflush(stdout);
790 } /* ms_print_setting */
791
792
793 /**
794 * previous part of slap mode initialization of setting structure
795 */
796 static void ms_setting_slapmode_init_pre()
797 {
798 ms_setting.exec_num= DEFAULT_EXE_NUM;
799 ms_setting.verify_percent= DEFAULT_VERIFY_RATE;
800 ms_setting.exp_ver_per= DEFAULT_VERIFY_RATE;
801 ms_setting.overwrite_percent= DEFAULT_OVERWRITE_RATE;
802 ms_setting.mult_key_num= DEFAULT_DIV;
803 ms_setting.fixed_value_size= 0;
804 ms_setting.win_size= DEFAULT_WINDOW_SIZE;
805 ms_setting.udp= false;
806 ms_setting.reconnect= false;
807 ms_setting.verbose= false;
808 ms_setting.facebook_test= false;
809 ms_setting.binary_prot= false;
810 ms_setting.stat_freq= 0;
811 ms_setting.srv_str= NULL;
812 ms_setting.cfg_file= NULL;
813 ms_setting.sock_per_conn= DEFAULT_SOCK_PER_CONN;
814 ms_setting.expected_tps= 0;
815 ms_setting.rep_write_srv= 0;
816 } /* ms_setting_slapmode_init_pre */
817
818
819 /**
820 * previous part of initialization of setting structure
821 */
822 void ms_setting_init_pre()
823 {
824 memset(&ms_setting, 0, sizeof(ms_setting));
825
826 /* common initialize */
827 ms_setting.ncpu= ms_get_cpu_count();
828 ms_setting.nthreads= DEFAULT_THREADS_NUM;
829 ms_setting.nconns= DEFAULT_CONNS_NUM;
830 ms_setting.run_time= DEFAULT_RUN_TIME;
831 ms_setting.total_srv_cnt= MCD_SRVS_NUM_INIT;
832 ms_setting.servers= (ms_mcd_server_t *)malloc(
833 (uint64_t)ms_setting.total_srv_cnt
834 * sizeof(ms_mcd_server_t));
835 if (ms_setting.servers == NULL)
836 {
837 fprintf(stderr, "Can't allocate servers structure.\n");
838 exit(1);
839 }
840
841 ms_setting_slapmode_init_pre();
842 } /* ms_setting_init_pre */
843
844
845 /**
846 * post part of slap mode initialization of setting structure
847 */
848 static void ms_setting_slapmode_init_post()
849 {
850 ms_setting.total_key_rng_cnt= KEY_RANGE_COUNT_INIT;
851 ms_setting.key_distr= (ms_key_distr_t *)malloc(
852 (uint64_t)ms_setting.total_key_rng_cnt
853 * sizeof(ms_key_distr_t));
854 if (ms_setting.key_distr == NULL)
855 {
856 fprintf(stderr, "Can't allocate key distribution structure.\n");
857 exit(1);
858 }
859
860 ms_setting.total_val_rng_cnt= VALUE_RANGE_COUNT_INIT;
861 ms_setting.value_distr= (ms_value_distr_t *)malloc(
862 (uint64_t)ms_setting.total_val_rng_cnt
863 * sizeof(
864 ms_value_distr_t));
865 if (ms_setting.value_distr == NULL)
866 {
867 fprintf(stderr, "Can't allocate value distribution structure.\n");
868 exit(1);
869 }
870
871 ms_parse_cfg_file(ms_setting.cfg_file);
872
873 /* run time mode */
874 if ((ms_setting.exec_num == 0) && (ms_setting.run_time != 0))
875 {
876 ms_setting.exec_num= (int64_t)MAX_EXEC_NUM;
877 }
878 else
879 {
880 /* execute number mode */
881 ms_setting.run_time= 0;
882 }
883
884 if (ms_setting.rep_write_srv > 0)
885 {
886 /* for replication test, need enable reconnect feature */
887 ms_setting.reconnect= true;
888 }
889
890 if (ms_setting.facebook_test && (ms_setting.mult_key_num < 2))
891 {
892 fprintf(stderr, "facebook test must work with multi-get, "
893 "please specify multi-get key number "
894 "with '--division' option.\n");
895 exit(1);
896 }
897
898 if (ms_setting.facebook_test && ms_setting.udp)
899 {
900 fprintf(stderr, "facebook test couldn't work with UDP.\n");
901 exit(1);
902 }
903
904 if (ms_setting.udp && (ms_setting.sock_per_conn > 1))
905 {
906 fprintf(stderr, "UDP doesn't support multi-socks "
907 "in one connection structure.\n");
908 exit(1);
909 }
910
911 if ((ms_setting.udp
912 || ms_setting.facebook_test) && ms_setting.binary_prot)
913 {
914 fprintf(stderr, "Binary protocol doesn't support UDP now.\n");
915 exit(1);
916 }
917
918 if ((ms_setting.rep_write_srv > 0) && (ms_setting.srv_cnt < 2))
919 {
920 fprintf(stderr, "Please specify 2 servers at least for replication\n");
921 exit(1);
922 }
923
924 if ((ms_setting.rep_write_srv > 0)
925 && (ms_setting.srv_cnt < ms_setting.rep_write_srv))
926 {
927 fprintf(stderr, "Servers to do replication writing "
928 "is larger than the total servers\n");
929 exit(1);
930 }
931
932 if (ms_setting.udp && (ms_setting.rep_write_srv > 0))
933 {
934 fprintf(stderr, "UDP doesn't support replication.\n");
935 exit(1);
936 }
937
938 if ((ms_setting.rep_write_srv > 0) && (ms_setting.sock_per_conn > 1))
939 {
940 fprintf(stderr, "Replication doesn't support multi-socks "
941 "in one connection structure.\n");
942 exit(1);
943 }
944
945 if (ms_setting.facebook_test && (ms_setting.rep_write_srv > 0))
946 {
947 fprintf(stderr, "facebook test couldn't work with replication.\n");
948 exit(1);
949 }
950
951 if (ms_setting.reconnect && (ms_setting.sock_per_conn > 1))
952 {
953 fprintf(stderr, "Reconnection doesn't support multi-socks "
954 "in one connection structure.\n");
955 exit(1);
956 }
957
958 ms_build_distr();
959
960 /* initialize global character block */
961 ms_init_random_block();
962 ms_print_setting();
963 } /* ms_setting_slapmode_init_post */
964
965
966 /**
967 * post part of initialization of setting structure
968 */
969 void ms_setting_init_post()
970 {
971 ms_get_serverlist(ms_setting.srv_str);
972 ms_setting_slapmode_init_post();
973 }
974
975
976 /**
977 * clean up the global setting structure
978 */
979 void ms_setting_cleanup()
980 {
981 if (ms_setting.distr != NULL)
982 {
983 free(ms_setting.distr);
984 }
985
986 if (ms_setting.char_block != NULL)
987 {
988 free(ms_setting.char_block);
989 }
990
991 if (ms_setting.srv_str != NULL)
992 {
993 free(ms_setting.srv_str);
994 }
995
996 if (ms_setting.cfg_file != NULL)
997 {
998 free(ms_setting.cfg_file);
999 }
1000
1001 if (ms_setting.servers != NULL)
1002 {
1003 free(ms_setting.servers);
1004 }
1005
1006 if (ms_setting.key_distr != NULL)
1007 {
1008 free(ms_setting.key_distr);
1009 }
1010
1011 if (ms_setting.value_distr != NULL)
1012 {
1013 free(ms_setting.value_distr);
1014 }
1015 } /* ms_setting_cleanup */