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