3 * Author: Mingqiang Zhuang
5 * Created on February 10, 2009
7 * (c) Copyright 2009, Schooner Information Technology, Inc.
8 * http://www.schoonerinfotech.com/
12 #include "ms_setting.h"
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 */
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 */
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.-";
35 ms_setting_t ms_setting
; /* store the settings specified by user */
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
);
47 /* initialize setting structure */
48 static void ms_init_random_block(void);
49 static void ms_calc_avg_size(void);
50 static int ms_shuffle_distr(ms_distr_t
*distr
, int length
);
51 static void ms_build_distr(void);
52 static void ms_print_setting(void);
53 static void ms_setting_slapmode_init_pre(void);
54 static void ms_setting_slapmode_init_post(void);
58 * parse the server list string, and build the servers
59 * information structure array. this function is used to parse
60 * the command line options specified by user.
62 * @param str, the string of server list
64 static void ms_get_serverlist(char *str
)
69 char *end_ptr
= str
+ strlen(str
);
70 ms_mcd_server_t
*srvs
= NULL
;
75 * Servers list format is like this. For example:
76 * "localhost:11108, localhost:11109"
78 for (begin_ptr
= str
, string
= index(str
, ',');
80 string
= index(begin_ptr
, ',')) {
84 memcpy(buffer
, begin_ptr
, (size_t)(string
- begin_ptr
));
85 buffer
[(unsigned int)(string
- begin_ptr
)]= '\0';
88 size_t length
= strlen(begin_ptr
);
89 memcpy(buffer
, begin_ptr
, length
);
90 buffer
[length
] = '\0';
94 ptr
= index(buffer
, ':');
99 port
= strtol(ptr
, (char **)NULL
, 10);
102 assert(ms_setting
.srv_cnt
< ms_setting
.total_srv_cnt
);
103 strcpy(ms_setting
.servers
[ms_setting
.srv_cnt
].srv_host_name
, buffer
);
104 ms_setting
.servers
[ms_setting
.srv_cnt
].srv_port
= (int)port
;
105 ms_setting
.servers
[ms_setting
.srv_cnt
].disconn_cnt
= 0;
106 ms_setting
.servers
[ms_setting
.srv_cnt
].reconn_cnt
= 0;
107 ms_setting
.srv_cnt
++;
109 if (ms_setting
.srv_cnt
>= ms_setting
.total_srv_cnt
) {
110 srvs
= (ms_mcd_server_t
*)realloc(ms_setting
.servers
,
111 (uint64_t)ms_setting
.total_srv_cnt
* sizeof(ms_mcd_server_t
) * 2);
113 fprintf(stderr
, "Can't reallocate servers structure.\n");
116 ms_setting
.servers
= srvs
;
117 ms_setting
.total_srv_cnt
*= 2;
120 if (isspace(*begin_ptr
))
126 * used to get the CPU count of the current system
128 * @return return the cpu count if get, else return 1
130 static int ms_get_cpu_count()
132 #ifdef HAVE__SC_NPROCESSORS_ONLN
133 return (sysconf(_SC_NPROCESSORS_CONF
));
135 #ifdef HAVE_CPU_SET_T
139 sched_getaffinity(0, sizeof(cpu_set_t
), &cpu_set
);
141 for (int i
= 0; i
< (sizeof(cpu_set_t
) * 8); i
++) {
142 if (CPU_ISSET(i
, &cpu_set
)) {
151 /* the system with one cpu at least */
156 * used to get the configure type based on the type string read
157 * from the configuration file.
159 * @param line, string of one line
161 * @return ms_conf_type_t
163 ms_conf_type_t
ms_get_conf_type(char *line
)
165 if (!memcmp(line
, "key", strlen("key")) ) {
167 } else if (!memcmp(line
, "value", strlen("value"))) {
169 } else if (!memcmp(line
, "cmd", strlen("cmd"))) {
177 * judge whether the line is a line with useful data. used to
178 * parse the configuration file.
180 * @param line, string of one line
182 * @return if success, return 1, else return 0
184 static int ms_is_line_data(char* line
)
186 assert(line
!= NULL
);
188 char* begin_ptr
= line
;
190 while(isspace(*begin_ptr
))
192 if (begin_ptr
[0] == '\0' || begin_ptr
[0] == '#')
198 * function to bypass blank line and comments
200 * @param line, string of one line
201 * @param nread, length of the line
203 * @return if it's EOF or not line data, return 0, else return 1
205 static int ms_read_is_data(char* line
, ssize_t nread
)
207 if (nread
== EOF
|| !ms_is_line_data(line
))
213 * if no configuration file, use this function to create the default
214 * configuration file.
216 static void ms_no_config_file()
218 FILE *fd
= fopen("config", "w+");
219 fprintf(fd
, "%s", DEFAULT_CONGIF_STR
);
222 ms_setting
.cfg_file
= strdup("config");
226 * parse the configuration file
228 * @param cfg_file, the configuration file name
230 static void ms_parse_cfg_file(char *cfg_file
)
233 size_t start_len
, end_len
;
240 ms_conf_type_t conf_type
;
242 ms_key_distr_t
*key_distr
= NULL
;
243 ms_value_distr_t
*val_distr
= NULL
;
246 if (cfg_file
== NULL
) {
248 cfg_file
= ms_setting
.cfg_file
;
252 /*read key value configure file*/
253 if ( (f
= fopen(cfg_file
, "r")) == NULL
) {
254 fprintf(stderr
, "Can not open file: '%s'.\n", cfg_file
);
259 if ((((nread
= getline(&line
, &read_len
, f
)) == 1) ||
260 !ms_read_is_data(line
, nread
)) && (nread
!= EOF
))/* bypass blank line */
263 fprintf(stderr
, "Bad configuration file, no configuration find.\n");
266 conf_type
= ms_get_conf_type(line
);
270 while (!end_of_file
) {
274 if ((((nread
= getline(&line
, &read_len
, f
)) == 1) ||
275 !ms_read_is_data(line
, nread
)) && (nread
!= EOF
)) /* bypass blank line */
279 if (sscanf(line
, "%lu %lu %lf ", &start_len
,
280 &end_len
, &proportion
) != 3) {
281 conf_type
= ms_get_conf_type(line
);
284 ms_setting
.key_distr
[ms_setting
.key_rng_cnt
].start_len
= start_len
;
285 ms_setting
.key_distr
[ms_setting
.key_rng_cnt
].end_len
= end_len
;
286 ms_setting
.key_distr
[ms_setting
.key_rng_cnt
].key_prop
= proportion
;
287 ms_setting
.key_rng_cnt
++;
289 if (ms_setting
.key_rng_cnt
>= ms_setting
.total_key_rng_cnt
) {
290 key_distr
= (ms_key_distr_t
*)realloc(ms_setting
.key_distr
,
291 (uint64_t)ms_setting
.total_key_rng_cnt
* sizeof(ms_key_distr_t
) * 2);
292 if (key_distr
== NULL
) {
293 fprintf(stderr
, "Can't reallocate key distribution structure.\n");
296 ms_setting
.key_distr
= key_distr
;
297 ms_setting
.total_key_rng_cnt
*= 2;
308 if ((((nread
= getline(&line
, &read_len
, f
)) == 1) ||
309 !ms_read_is_data(line
, nread
)) && (nread
!= EOF
)) /* bypass blank line */
313 if (sscanf(line
, "%lu %lu %lf %lu", &start_len
, &end_len
,
314 &proportion
, &frequence
) !=3 ) {
315 conf_type
= ms_get_conf_type(line
);
318 ms_setting
.value_distr
[ms_setting
.val_rng_cnt
].start_len
= start_len
;
319 ms_setting
.value_distr
[ms_setting
.val_rng_cnt
].end_len
= end_len
;
320 ms_setting
.value_distr
[ms_setting
.val_rng_cnt
].value_prop
= proportion
;
321 ms_setting
.val_rng_cnt
++;
323 if (ms_setting
.val_rng_cnt
>= ms_setting
.total_val_rng_cnt
) {
324 val_distr
= (ms_value_distr_t
*)realloc(ms_setting
.value_distr
,
325 (uint64_t)ms_setting
.total_val_rng_cnt
* sizeof(ms_value_distr_t
) * 2);
326 if (val_distr
== NULL
) {
327 fprintf(stderr
, "Can't reallocate key distribution structure.\n");
330 ms_setting
.value_distr
= val_distr
;
331 ms_setting
.total_val_rng_cnt
*= 2;
342 if ((((nread
= getline(&line
, &read_len
, f
)) == 1) ||
343 !ms_read_is_data(line
, nread
)) && (nread
!= EOF
)) /* bypass blank line */
347 if (sscanf(line
, "%d %lf\n", &cmd_type
, &proportion
) != 2) {
348 conf_type
= ms_get_conf_type(line
);
351 ms_setting
.cmd_distr
[ms_setting
.cmd_used_count
].cmd_type
= cmd_type
;
352 ms_setting
.cmd_distr
[ms_setting
.cmd_used_count
].cmd_prop
= proportion
;
353 ms_setting
.cmd_used_count
++;
362 if ((((nread
= getline(&line
, &read_len
, f
)) == 1) ||
363 !ms_read_is_data(line
, nread
)) && (nread
!= EOF
)) /* bypass blank line */
367 if ((conf_type
= ms_get_conf_type(line
)) != CONF_NULL
) {
385 remove(ms_setting
.cfg_file
);
392 /* calculate the average size of key and value */
393 static void ms_calc_avg_size()
395 double avg_val_size
= 0.0;
396 double avg_key_size
= 0.0;
397 double val_pro
= 0.0;
398 double key_pro
= 0.0;
399 double averge_len
= 0.0;
400 size_t start_len
= 0;
403 for (int j
= 0; j
< ms_setting
.val_rng_cnt
; j
++) {
404 val_pro
= ms_setting
.value_distr
[j
].value_prop
;
405 start_len
= ms_setting
.value_distr
[j
].start_len
;
406 end_len
= ms_setting
.value_distr
[j
].end_len
;
408 averge_len
= val_pro
* ((double)(start_len
+ end_len
)) / 2;
409 avg_val_size
+= averge_len
;
412 for (int j
= 0; j
< ms_setting
.key_rng_cnt
; j
++) {
413 key_pro
= ms_setting
.key_distr
[j
].key_prop
;
414 start_len
= ms_setting
.key_distr
[j
].start_len
;
415 end_len
= ms_setting
.key_distr
[j
].end_len
;
417 averge_len
= key_pro
* ((double)(start_len
+ end_len
)) / 2;
418 avg_key_size
+= averge_len
;
421 ms_setting
.avg_val_size
= (size_t)avg_val_size
;
422 ms_setting
.avg_key_size
= (size_t)avg_key_size
;
426 * used to shuffle key and value distribution array to ensure
427 * (key, value) pair with different set.
429 * @param distr, pointer of distribution structure array
430 * @param length, length of the array
432 * @return always return 0
434 static int ms_shuffle_distr(ms_distr_t
*distr
, int length
)
441 for (i
= 0; i
< length
; i
++) {
443 j
= (int)(rnd
% (length
- i
)) + i
;
447 tmp_size
= distr
[j
].key_size
;
448 distr
[j
].key_size
= distr
[i
].key_size
;
449 distr
[i
].key_size
= tmp_size
;
452 tmp_offset
= distr
[j
].key_offset
;
453 distr
[j
].key_offset
= distr
[i
].key_offset
;
454 distr
[i
].key_offset
= tmp_offset
;
457 tmp_size
= distr
[j
].value_size
;
458 distr
[j
].value_size
= distr
[i
].value_size
;
459 distr
[i
].value_size
= tmp_size
;
470 * according to the key and value distribution, to build the
471 * (key, value) pair distribution. the (key, value) pair
472 * distribution array is global, each connection set or get
473 * object keeping this distribution, for the final result, we
474 * can reach the expected key and value distribution.
476 static void ms_build_distr()
482 size_t average_len
= 0;
484 size_t start_len
= 0;
487 ms_distr_t
*distr
= NULL
;
488 int units
= (int)ms_setting
.win_size
/ UNIT_ITEMS_COUNT
;
490 /* calculate average value size and key size */
493 ms_setting
.char_blk_size
= RAND_CHAR_SIZE
;
494 int key_scope_size
= (int)((ms_setting
.char_blk_size
- RESERVED_RAND_CHAR_SIZE
)
497 ms_setting
.distr
= (ms_distr_t
*)malloc(sizeof(ms_distr_t
) * ms_setting
.win_size
);
498 if (ms_setting
.distr
== NULL
) {
499 fprintf(stderr
, "Can't allocate distribution array.");
504 * character block is divided by how many different key
505 * size, each different key size has the same size character
508 for (int m
= 0; m
< units
; m
++) {
509 for (int i
= 0; i
< UNIT_ITEMS_COUNT
; i
++) {
510 ms_setting
.distr
[m
* UNIT_ITEMS_COUNT
+ i
].key_offset
=
511 ADDR_ALIGN(key_scope_size
* i
);
515 /* initialize key size distribution */
516 for (int m
= 0; m
< units
; m
++) {
517 for (int j
= 0; j
< ms_setting
.key_rng_cnt
; j
++) {
518 key_cnt
= (int)(UNIT_ITEMS_COUNT
* ms_setting
.key_distr
[j
].key_prop
);
519 start_len
= ms_setting
.key_distr
[j
].start_len
;
520 end_len
= ms_setting
.key_distr
[j
].end_len
;
521 if (start_len
< MIN_KEY_SIZE
|| end_len
< MIN_KEY_SIZE
) {
522 fprintf(stderr
, "key length must be greater than 16 bytes.\n");
526 if (!ms_setting
.binary_prot
&& (start_len
> MAX_KEY_SIZE
|| end_len
> MAX_KEY_SIZE
)) {
527 fprintf(stderr
, "key length must be less than 250 bytes.\n");
531 average_len
= (start_len
+ end_len
) / 2;
532 diff_len
= (end_len
- start_len
) / 2;
533 for (int k
= 0; k
< key_cnt
; k
++) {
534 if (offset
>= (m
+ 1) * UNIT_ITEMS_COUNT
) {
539 ms_setting
.distr
[offset
].key_size
= (diff_len
== 0) ? average_len
:
540 average_len
+ (size_t)rnd
% diff_len
;
542 ms_setting
.distr
[offset
].key_size
= (diff_len
== 0) ? average_len
:
543 average_len
- (size_t)rnd
% diff_len
;
549 if (offset
< (m
+ 1) * UNIT_ITEMS_COUNT
) {
550 end
= (m
+ 1) * UNIT_ITEMS_COUNT
- offset
;
551 for (int i
= 0; i
< end
; i
++) {
552 ms_setting
.distr
[offset
].key_size
= ms_setting
.avg_key_size
;
559 /* initialize value distribution */
560 if (ms_setting
.fixed_value_size
!= 0) {
561 for (int i
= 0; i
< units
* UNIT_ITEMS_COUNT
; i
++) {
562 ms_setting
.distr
[i
].value_size
= ms_setting
.fixed_value_size
;
565 for (int m
= 0; m
< units
; m
++) {
566 for (int j
= 0; j
< ms_setting
.val_rng_cnt
; j
++) {
567 value_cnt
= (int)(UNIT_ITEMS_COUNT
* ms_setting
.value_distr
[j
].value_prop
);
568 start_len
= ms_setting
.value_distr
[j
].start_len
;
569 end_len
= ms_setting
.value_distr
[j
].end_len
;
570 if (start_len
<= 0 || end_len
<= 0) {
571 fprintf(stderr
, "value length must be greater than 0 bytes.\n");
575 if (start_len
> MAX_VALUE_SIZE
|| end_len
> MAX_VALUE_SIZE
) {
576 fprintf(stderr
, "key length must be less than or equal to 1M.\n");
580 average_len
= (start_len
+ end_len
) / 2;
581 diff_len
= (end_len
- start_len
) / 2;
582 for (int k
= 0; k
< value_cnt
; k
++) {
583 if (offset
>= (m
+ 1) * UNIT_ITEMS_COUNT
) {
588 ms_setting
.distr
[offset
].value_size
= (diff_len
== 0) ? average_len
:
589 average_len
+ (size_t)rnd
% diff_len
;
591 ms_setting
.distr
[offset
].value_size
= (diff_len
== 0) ? average_len
:
592 average_len
- (size_t)rnd
% diff_len
;
598 if (offset
< (m
+ 1) * UNIT_ITEMS_COUNT
) {
599 end
= (m
+ 1) * UNIT_ITEMS_COUNT
- offset
;
600 for (int i
=0; i
< end
; i
++) {
601 ms_setting
.distr
[offset
++].value_size
= ms_setting
.avg_val_size
;
607 /* shuffle distribution */
608 for (int i
= 0; i
< units
; i
++) {
609 distr
= &ms_setting
.distr
[i
* UNIT_ITEMS_COUNT
];
610 for (int j
= 0; j
< 4; j
++) {
611 ms_shuffle_distr(distr
, UNIT_ITEMS_COUNT
);
617 * used to initialize the global character block. The character
618 * block is used to generate the suffix of the key and value. we
619 * only store a pointer in the character block for each key
620 * suffix or value string. It can save much memory to store key
623 static void ms_init_random_block()
627 assert(ms_setting
.char_blk_size
> 0);
629 ms_setting
.char_block
= (char *)malloc(ms_setting
.char_blk_size
);
630 if (ms_setting
.char_block
== NULL
) {
631 fprintf(stderr
, "Can't allocate global char block.");
634 ptr
= ms_setting
.char_block
;
636 for (int i
= 0; (size_t)i
< ms_setting
.char_blk_size
; i
++) {
637 *(ptr
++) = ALPHANUMBERICS
[random() % CHAR_COUNT
];
642 * after initialization, call this function to output the main
643 * configuration user specified.
645 static void ms_print_setting()
647 fprintf(stdout
, "threads count: %d\n", ms_setting
.nthreads
);
648 fprintf(stdout
, "concurrency: %d\n", ms_setting
.nconns
);
649 if (ms_setting
.run_time
> 0) {
650 fprintf(stdout
, "run time: %ds\n", ms_setting
.run_time
);
652 fprintf(stdout
, "execute number: %ld\n", ms_setting
.exec_num
);
654 fprintf(stdout
, "windows size: %ldk\n", (int64_t)(ms_setting
.win_size
/ 1024));
655 fprintf(stdout
, "set proportion: set_prop=%.2f\n",
656 ms_setting
.cmd_distr
[CMD_SET
].cmd_prop
);
657 fprintf(stdout
, "get proportion: get_prop=%.2f\n",
658 ms_setting
.cmd_distr
[CMD_GET
].cmd_prop
);
663 * previous part of slap mode initialization of setting structure
665 static void ms_setting_slapmode_init_pre()
667 ms_setting
.exec_num
= DEFAULT_EXE_NUM
;
668 ms_setting
.verify_percent
= DEFAULT_VERIFY_RATE
;
669 ms_setting
.exp_ver_per
= DEFAULT_VERIFY_RATE
;
670 ms_setting
.overwrite_percent
= DEFAULT_OVERWRITE_RATE
;
671 ms_setting
.mult_key_num
= DEFAULT_DIV
;
672 ms_setting
.fixed_value_size
= 0;
673 ms_setting
.win_size
= DEFAULT_WINDOW_SIZE
;
674 ms_setting
.udp
= false;
675 ms_setting
.reconnect
= false;
676 ms_setting
.verbose
= false;
677 ms_setting
.facebook_test
= false;
678 ms_setting
.binary_prot
= false;
679 ms_setting
.stat_freq
= 0;
680 ms_setting
.srv_str
= NULL
;
681 ms_setting
.cfg_file
= NULL
;
682 ms_setting
.sock_per_conn
= DEFAULT_SOCK_PER_CONN
;
683 ms_setting
.expected_tps
= 0;
684 ms_setting
.rep_write_srv
= 0;
688 * previous part of initialization of setting structure
690 void ms_setting_init_pre()
692 memset(&ms_setting
, 0, sizeof(ms_setting_t
));
694 /* common initialize */
695 ms_setting
.ncpu
= ms_get_cpu_count();
696 ms_setting
.nthreads
= DEFAULT_THREADS_NUM
;
697 ms_setting
.nconns
= DEFAULT_CONNS_NUM
;
698 ms_setting
.run_time
= DEFAULT_RUN_TIME
;
699 ms_setting
.total_srv_cnt
= MCD_SRVS_NUM_INIT
;
700 ms_setting
.servers
= (ms_mcd_server_t
*)malloc((uint64_t)ms_setting
.total_srv_cnt
701 * sizeof(ms_mcd_server_t
));
702 if (ms_setting
.servers
== NULL
) {
703 fprintf(stderr
, "Can't allocate servers structure.\n");
707 ms_setting_slapmode_init_pre();
711 * post part of slap mode initialization of setting structure
713 static void ms_setting_slapmode_init_post()
715 ms_setting
.total_key_rng_cnt
= KEY_RANGE_COUNT_INIT
;
716 ms_setting
.key_distr
= (ms_key_distr_t
*)malloc((uint64_t)ms_setting
.total_key_rng_cnt
717 * sizeof(ms_key_distr_t
));
718 if (ms_setting
.key_distr
== NULL
) {
719 fprintf(stderr
, "Can't allocate key distribution structure.\n");
723 ms_setting
.total_val_rng_cnt
= VALUE_RANGE_COUNT_INIT
;
724 ms_setting
.value_distr
= (ms_value_distr_t
*)malloc((uint64_t)ms_setting
.total_val_rng_cnt
725 * sizeof(ms_value_distr_t
));
726 if (ms_setting
.value_distr
== NULL
) {
727 fprintf(stderr
, "Can't allocate value distribution structure.\n");
731 ms_parse_cfg_file(ms_setting
.cfg_file
);
734 if (ms_setting
.exec_num
== 0 && ms_setting
.run_time
!= 0) {
735 ms_setting
.exec_num
= (int64_t)MAX_EXEC_NUM
;
737 /* execute number mode */
738 ms_setting
.run_time
= 0;
741 if (ms_setting
.rep_write_srv
> 0) {
742 /* for replication test, need enable reconnect feature */
743 ms_setting
.reconnect
= true;
746 if (ms_setting
.facebook_test
&& ms_setting
.mult_key_num
< 2) {
747 fprintf(stderr
, "facebook test must work with multi-get, "
748 "please specify multi-get key number "
749 "with '--division' option.\n");
753 if (ms_setting
.facebook_test
&& ms_setting
.udp
) {
754 fprintf(stderr
, "facebook test couldn't work with UDP.\n");
758 if (ms_setting
.udp
&& ms_setting
.sock_per_conn
> 1) {
759 fprintf(stderr
, "UDP doesn't support multi-socks "
760 "in one connection structure.\n");
764 if ((ms_setting
.udp
|| ms_setting
.facebook_test
) && ms_setting
.binary_prot
) {
765 fprintf(stderr
, "Binary protocol doesn't support UDP now.\n");
769 if (ms_setting
.rep_write_srv
> 0 && ms_setting
.srv_cnt
< 2) {
770 fprintf(stderr
, "Please specify 2 servers at least for replication\n");
774 if (ms_setting
.rep_write_srv
> 0 && ms_setting
.srv_cnt
< ms_setting
.rep_write_srv
) {
775 fprintf(stderr
, "Servers to do replication writing "
776 "is larger than the total servers\n");
780 if (ms_setting
.udp
&& ms_setting
.rep_write_srv
> 0) {
781 fprintf(stderr
, "UDP doesn't support replication.\n");
785 if (ms_setting
.rep_write_srv
> 0 && ms_setting
.sock_per_conn
> 1) {
786 fprintf(stderr
, "Replication doesn't support multi-socks "
787 "in one connection structure.\n");
791 if (ms_setting
.facebook_test
&& ms_setting
.rep_write_srv
> 0) {
792 fprintf(stderr
, "facebook test couldn't work with replication.\n");
796 if (ms_setting
.reconnect
&& ms_setting
.sock_per_conn
> 1) {
797 fprintf(stderr
, "Reconnection doesn't support multi-socks "
798 "in one connection structure.\n");
804 /* initialize global character block */
805 ms_init_random_block();
810 * post part of initialization of setting structure
812 void ms_setting_init_post()
814 ms_get_serverlist(ms_setting
.srv_str
);
815 ms_setting_slapmode_init_post();
819 * clean up the global setting structure
821 void ms_setting_cleanup()
823 if (ms_setting
.distr
!= NULL
) {
824 free(ms_setting
.distr
);
827 if (ms_setting
.char_block
!= NULL
) {
828 free(ms_setting
.char_block
);
831 if (ms_setting
.srv_str
!= NULL
) {
832 free(ms_setting
.srv_str
);
835 if (ms_setting
.cfg_file
!= NULL
) {
836 free(ms_setting
.cfg_file
);
839 if (ms_setting
.servers
!= NULL
) {
840 free(ms_setting
.servers
);
843 if (ms_setting
.key_distr
!= NULL
) {
844 free(ms_setting
.key_distr
);
847 if (ms_setting
.value_distr
!= NULL
) {
848 free(ms_setting
.value_distr
);