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