adab65a1a78a27057299fab6ebaef90d294bf68e
2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
16 #include "mem_config.h"
18 #include "libmemcached/memcached.h"
25 #include <sys/types.h>
28 #include "ms_setting.h"
31 #define MAX_EXEC_NUM 0x4000000000000000 /* 1 << 62 */
32 #define ADDR_ALIGN(addr) ((addr + 15) & ~(16 - 1)) /* 16 bytes aligned */
33 #define RAND_CHAR_SIZE (10 * 1024 * 1024) /* 10M character table */
34 #define RESERVED_RAND_CHAR_SIZE (2 * 1024 * 1024) /* reserved 2M to avoid pointer sloping over */
36 #define DEFAULT_CONFIG_NAME ".memslap.cnf"
38 #define DEFAULT_THREADS_NUM 1 /* default start one thread */
39 #define DEFAULT_CONNS_NUM 16 /* default each thread with 16 connections */
40 #define DEFAULT_EXE_NUM 0 /* default execute number is 0 */
41 #define DEFAULT_VERIFY_RATE 0.0 /* default it doesn't do data verification */
42 #define DEFAULT_OVERWRITE_RATE 0.0 /* default it doesn't do overwrite */
43 #define DEFAULT_DIV 1 /* default it runs single get */
44 #define DEFAULT_RUN_TIME 600 /* default run time 10 minutes */
45 #define DEFAULT_WINDOW_SIZE (10 * UNIT_ITEMS_COUNT) /* default window size is 10k */
46 #define DEFAULT_SOCK_PER_CONN 1 /* default socks per connection is 1 */
48 /* Use this for string generation */
49 #define CHAR_COUNT 64 /* number of characters used to generate character table */
50 const char ALPHANUMBERICS
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-";
52 ms_setting_st ms_setting
; /* store the settings specified by user */
54 /* read setting from configuration file */
55 static void ms_get_serverlist(char *str
);
56 static uint32_t ms_get_cpu_count(void);
57 ms_conf_type_t
ms_get_conf_type(char *line
);
58 static int ms_is_line_data(char *line
);
59 static int ms_read_is_data(char *line
, ssize_t nread
);
60 static void ms_no_config_file(void);
61 static void ms_parse_cfg_file(char *cfg_file
);
63 /* initialize setting structure */
64 static void ms_init_random_block(void);
65 static void ms_calc_avg_size(void);
66 static int ms_shuffle_distr(ms_distr_t
*distr
, int length
);
67 static void ms_build_distr(void);
68 static void ms_print_setting(void);
69 static void ms_setting_slapmode_init_pre(void);
70 static void ms_setting_slapmode_init_post(void);
72 #if !defined(HAVE_GETLINE)
74 static ssize_t
getline(char **line
, size_t *line_size
, FILE *fp
) {
79 if (line
== NULL
|| line_size
== NULL
|| fp
== NULL
) {
84 if (*line
== NULL
|| *line_size
== 0) {
87 new_line
= (char *) realloc(*line
, *line_size
);
88 if (new_line
== NULL
) {
102 /* Make enough space for len+1 (for final NUL) bytes. */
103 if (cur_len
+ 1 >= *line_size
) {
104 size_t needed_max
= SSIZE_MAX
< SIZE_MAX
? (size_t) SSIZE_MAX
+ 1 : SIZE_MAX
;
105 size_t needed
= (2 * (*line_size
)) + 1;
108 if (needed_max
< needed
)
110 if (cur_len
+ 1 >= needed
) {
116 new_line
= (char *) realloc(*line
, needed
);
117 if (new_line
== NULL
) {
126 (*line
)[cur_len
] = (char) i
;
132 (*line
)[cur_len
] = '\0';
134 return (ssize_t
) cur_len
;
140 * parse the server list string, and build the servers
141 * information structure array. this function is used to parse
142 * the command line options specified by user.
144 * @param str, the string of server list
146 static void ms_get_serverlist(char *str
) {
147 ms_mcd_server_t
*srvs
= NULL
;
150 * Servers list format is like this. For example:
151 * "localhost:11108, localhost:11109"
153 memcached_server_st
*server_pool
;
154 server_pool
= memcached_servers_parse(str
);
156 for (uint32_t loop
= 0; loop
< memcached_server_list_count(server_pool
); loop
++) {
157 assert(ms_setting
.srv_cnt
< ms_setting
.total_srv_cnt
);
158 strcpy(ms_setting
.servers
[ms_setting
.srv_cnt
].srv_host_name
, server_pool
[loop
].hostname
);
159 ms_setting
.servers
[ms_setting
.srv_cnt
].srv_port
= server_pool
[loop
].port
;
160 ms_setting
.servers
[ms_setting
.srv_cnt
].disconn_cnt
= 0;
161 ms_setting
.servers
[ms_setting
.srv_cnt
].reconn_cnt
= 0;
162 ms_setting
.srv_cnt
++;
164 if (ms_setting
.srv_cnt
>= ms_setting
.total_srv_cnt
) {
165 srvs
= (ms_mcd_server_t
*) realloc(
166 ms_setting
.servers
, (size_t) ms_setting
.total_srv_cnt
* sizeof(ms_mcd_server_t
) * 2);
168 fprintf(stderr
, "Can't reallocate servers structure.\n");
171 ms_setting
.servers
= srvs
;
172 ms_setting
.total_srv_cnt
*= 2;
176 memcached_server_free(server_pool
);
177 } /* ms_get_serverlist */
180 * used to get the CPU count of the current system
182 * @return return the cpu count if get, else return EXIT_FAILURE
184 static uint32_t ms_get_cpu_count() {
185 #ifdef HAVE__SC_NPROCESSORS_ONLN
186 return sysconf(_SC_NPROCESSORS_CONF
);
189 # ifdef HAVE_CPU_SET_T
193 sched_getaffinity(0, sizeof(cpu_set_t
), &cpu_set
);
195 for (int i
= 0; i
< (sizeof(cpu_set_t
) * 8); i
++) {
196 if (CPU_ISSET(i
, &cpu_set
)) {
206 /* the system with one cpu at least */
208 } /* ms_get_cpu_count */
211 * used to get the configure type based on the type string read
212 * from the configuration file.
214 * @param line, string of one line
216 * @return ms_conf_type_t
218 ms_conf_type_t
ms_get_conf_type(char *line
) {
219 if (!memcmp(line
, "key", strlen("key"))) {
221 } else if (!memcmp(line
, "value", strlen("value"))) {
223 } else if (!memcmp(line
, "cmd", strlen("cmd"))) {
228 } /* ms_get_conf_type */
231 * judge whether the line is a line with useful data. used to
232 * parse the configuration file.
234 * @param line, string of one line
236 * @return if success, return EXIT_FAILURE, else return EXIT_SUCCESS
238 static int ms_is_line_data(char *line
) {
239 assert(line
!= NULL
);
241 char *begin_ptr
= line
;
243 while (isspace(*begin_ptr
)) {
246 if ((begin_ptr
[0] == '\0') || (begin_ptr
[0] == '#'))
250 } /* ms_is_line_data */
253 * function to bypass blank line and comments
255 * @param line, string of one line
256 * @param nread, length of the line
258 * @return if it's EOF or not line data, return EXIT_SUCCESS, else return EXIT_FAILURE
260 static int ms_read_is_data(char *line
, ssize_t nread
) {
261 if ((nread
== EOF
) || !ms_is_line_data(line
))
265 } /* ms_read_is_data */
268 * if no configuration file, use this function to create the default
269 * configuration file.
271 static void ms_no_config_file() {
272 char userpath
[PATH_MAX
];
273 struct passwd
*usr
= NULL
;
276 usr
= getpwuid(getuid());
278 snprintf(userpath
, PATH_MAX
, "%s/%s", usr
->pw_dir
, DEFAULT_CONFIG_NAME
);
280 if (access(userpath
, F_OK
| R_OK
) == 0)
283 fd
= fopen(userpath
, "w+");
286 fprintf(stderr
, "Could not create default configure file %s\n", userpath
);
290 fprintf(fd
, "%s", DEFAULT_CONGIF_STR
);
294 ms_setting
.cfg_file
= strdup(userpath
);
295 } /* ms_no_config_file */
298 * parse the configuration file
300 * @param cfg_file, the configuration file name
302 static void ms_parse_cfg_file(char *cfg_file
) {
304 size_t start_len
, end_len
;
310 ms_conf_type_t conf_type
;
312 ms_key_distr_t
*key_distr
= NULL
;
313 ms_value_distr_t
*val_distr
= NULL
;
315 if (cfg_file
== NULL
) {
317 cfg_file
= ms_setting
.cfg_file
;
320 /*read key value configure file*/
321 if ((f
= fopen(cfg_file
, "r")) == NULL
) {
322 fprintf(stderr
, "Can not open file: '%s'.\n", cfg_file
);
327 if ((((nread
= getline(&line
, &read_len
, f
)) == 1) || !ms_read_is_data(line
, nread
))
328 && (nread
!= EOF
)) /* bypass blank line */
332 fprintf(stderr
, "Bad configuration file, no configuration find.\n");
335 conf_type
= ms_get_conf_type(line
);
339 while (!end_of_file
) {
343 if ((((nread
= getline(&line
, &read_len
, f
)) == 1) || !ms_read_is_data(line
, nread
))
344 && (nread
!= EOF
)) /* bypass blank line */
348 if (sscanf(line
, "%zu %zu %lf ", &start_len
, &end_len
, &proportion
) != 3) {
349 conf_type
= ms_get_conf_type(line
);
352 ms_setting
.key_distr
[ms_setting
.key_rng_cnt
].start_len
= start_len
;
353 ms_setting
.key_distr
[ms_setting
.key_rng_cnt
].end_len
= end_len
;
354 ms_setting
.key_distr
[ms_setting
.key_rng_cnt
].key_prop
= proportion
;
355 ms_setting
.key_rng_cnt
++;
357 if (ms_setting
.key_rng_cnt
>= ms_setting
.total_key_rng_cnt
) {
358 key_distr
= (ms_key_distr_t
*) realloc(ms_setting
.key_distr
,
359 (size_t) ms_setting
.total_key_rng_cnt
360 * sizeof(ms_key_distr_t
) * 2);
361 if (key_distr
== NULL
) {
362 fprintf(stderr
, "Can't reallocate key distribution structure.\n");
365 ms_setting
.key_distr
= key_distr
;
366 ms_setting
.total_key_rng_cnt
*= 2;
377 if ((((nread
= getline(&line
, &read_len
, f
)) == 1) || !ms_read_is_data(line
, nread
))
378 && (nread
!= EOF
)) /* bypass blank line */
382 if (sscanf(line
, "%zu %zu %lf", &start_len
, &end_len
, &proportion
) != 3) {
383 conf_type
= ms_get_conf_type(line
);
386 ms_setting
.value_distr
[ms_setting
.val_rng_cnt
].start_len
= start_len
;
387 ms_setting
.value_distr
[ms_setting
.val_rng_cnt
].end_len
= end_len
;
388 ms_setting
.value_distr
[ms_setting
.val_rng_cnt
].value_prop
= proportion
;
389 ms_setting
.val_rng_cnt
++;
391 if (ms_setting
.val_rng_cnt
>= ms_setting
.total_val_rng_cnt
) {
392 val_distr
= (ms_value_distr_t
*) realloc(ms_setting
.value_distr
,
393 (size_t) ms_setting
.total_val_rng_cnt
394 * sizeof(ms_value_distr_t
) * 2);
395 if (val_distr
== NULL
) {
396 fprintf(stderr
, "Can't reallocate key distribution structure.\n");
399 ms_setting
.value_distr
= val_distr
;
400 ms_setting
.total_val_rng_cnt
*= 2;
411 if ((((nread
= getline(&line
, &read_len
, f
)) == 1) || !ms_read_is_data(line
, nread
))
412 && (nread
!= EOF
)) /* bypass blank line */
416 if (sscanf(line
, "%d %lf", &cmd_type
, &proportion
) != 2) {
417 conf_type
= ms_get_conf_type(line
);
420 if (cmd_type
>= CMD_NULL
) {
423 ms_setting
.cmd_distr
[ms_setting
.cmd_used_count
].cmd_type
= cmd_type
;
424 ms_setting
.cmd_distr
[ms_setting
.cmd_used_count
].cmd_prop
= proportion
;
425 ms_setting
.cmd_used_count
++;
434 if ((((nread
= getline(&line
, &read_len
, f
)) == 1) || !ms_read_is_data(line
, nread
))
435 && (nread
!= EOF
)) /* bypass blank line */
439 if ((conf_type
= ms_get_conf_type(line
)) != CONF_NULL
) {
449 default: assert(0); break;
458 } /* ms_parse_cfg_file */
460 /* calculate the average size of key and value */
461 static void ms_calc_avg_size() {
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;
470 for (int j
= 0; j
< ms_setting
.val_rng_cnt
; j
++) {
471 val_pro
= ms_setting
.value_distr
[j
].value_prop
;
472 start_len
= ms_setting
.value_distr
[j
].start_len
;
473 end_len
= ms_setting
.value_distr
[j
].end_len
;
475 averge_len
= val_pro
* ((double) (start_len
+ end_len
)) / 2;
476 avg_val_size
+= averge_len
;
479 for (int j
= 0; j
< ms_setting
.key_rng_cnt
; j
++) {
480 key_pro
= ms_setting
.key_distr
[j
].key_prop
;
481 start_len
= ms_setting
.key_distr
[j
].start_len
;
482 end_len
= ms_setting
.key_distr
[j
].end_len
;
484 averge_len
= key_pro
* ((double) (start_len
+ end_len
)) / 2;
485 avg_key_size
+= averge_len
;
488 ms_setting
.avg_val_size
= (size_t) avg_val_size
;
489 ms_setting
.avg_key_size
= (size_t) avg_key_size
;
490 } /* ms_calc_avg_size */
493 * used to shuffle key and value distribution array to ensure
494 * (key, value) pair with different set.
496 * @param distr, pointer of distribution structure array
497 * @param length, length of the array
499 * @return always return EXIT_SUCCESS
501 static int ms_shuffle_distr(ms_distr_t
*distr
, int length
) {
507 for (i
= 0; i
< length
; i
++) {
509 j
= (int) (rnd
% (length
- i
)) + i
;
513 tmp_size
= distr
[j
].key_size
;
514 distr
[j
].key_size
= distr
[i
].key_size
;
515 distr
[i
].key_size
= tmp_size
;
519 tmp_offset
= distr
[j
].key_offset
;
520 distr
[j
].key_offset
= distr
[i
].key_offset
;
521 distr
[i
].key_offset
= tmp_offset
;
525 tmp_size
= distr
[j
].value_size
;
526 distr
[j
].value_size
= distr
[i
].value_size
;
527 distr
[i
].value_size
= tmp_size
;
535 } /* ms_shuffle_distr */
538 * according to the key and value distribution, to build the
539 * (key, value) pair distribution. the (key, value) pair
540 * distribution array is global, each connection set or get
541 * object keeping this distribution, for the final result, we
542 * can reach the expected key and value distribution.
544 static void ms_build_distr() {
549 size_t average_len
= 0;
551 size_t start_len
= 0;
554 ms_distr_t
*distr
= NULL
;
555 int units
= (int) ms_setting
.win_size
/ UNIT_ITEMS_COUNT
;
557 /* calculate average value size and key size */
560 ms_setting
.char_blk_size
= RAND_CHAR_SIZE
;
562 (int) ((ms_setting
.char_blk_size
- RESERVED_RAND_CHAR_SIZE
) / UNIT_ITEMS_COUNT
);
564 ms_setting
.distr
= (ms_distr_t
*) malloc(sizeof(ms_distr_t
) * ms_setting
.win_size
);
565 if (ms_setting
.distr
== NULL
) {
566 fprintf(stderr
, "Can't allocate distribution array.");
571 * character block is divided by how many different key
572 * size, each different key size has the same size character
575 for (int m
= 0; m
< units
; m
++) {
576 for (int i
= 0; i
< UNIT_ITEMS_COUNT
; i
++) {
577 ms_setting
.distr
[m
* UNIT_ITEMS_COUNT
+ i
].key_offset
= ADDR_ALIGN(key_scope_size
* i
);
581 /* initialize key size distribution */
582 for (int m
= 0; m
< units
; m
++) {
583 for (int j
= 0; j
< ms_setting
.key_rng_cnt
; j
++) {
584 key_cnt
= (int) (UNIT_ITEMS_COUNT
* ms_setting
.key_distr
[j
].key_prop
);
585 start_len
= ms_setting
.key_distr
[j
].start_len
;
586 end_len
= ms_setting
.key_distr
[j
].end_len
;
587 if ((start_len
< MIN_KEY_SIZE
) || (end_len
< MIN_KEY_SIZE
)) {
588 fprintf(stderr
, "key length must be greater than 16 bytes.\n");
592 if (!ms_setting
.binary_prot_
&& ((start_len
> MAX_KEY_SIZE
) || (end_len
> MAX_KEY_SIZE
))) {
593 fprintf(stderr
, "key length must be less than 250 bytes.\n");
597 average_len
= (start_len
+ end_len
) / 2;
598 diff_len
= (end_len
- start_len
) / 2;
599 for (int k
= 0; k
< key_cnt
; k
++) {
600 if (offset
>= (m
+ 1) * UNIT_ITEMS_COUNT
) {
603 rnd
= (int) random();
605 ms_setting
.distr
[offset
].key_size
=
606 (diff_len
== 0) ? average_len
: average_len
+ (size_t) rnd
% diff_len
;
608 ms_setting
.distr
[offset
].key_size
=
609 (diff_len
== 0) ? average_len
: average_len
- (size_t) rnd
% diff_len
;
615 if (offset
< (m
+ 1) * UNIT_ITEMS_COUNT
) {
616 end
= (m
+ 1) * UNIT_ITEMS_COUNT
- offset
;
617 for (int i
= 0; i
< end
; i
++) {
618 ms_setting
.distr
[offset
].key_size
= ms_setting
.avg_key_size
;
625 /* initialize value distribution */
626 if (ms_setting
.fixed_value_size
!= 0) {
627 for (int i
= 0; i
< units
* UNIT_ITEMS_COUNT
; i
++) {
628 ms_setting
.distr
[i
].value_size
= ms_setting
.fixed_value_size
;
631 for (int m
= 0; m
< units
; m
++) {
632 for (int j
= 0; j
< ms_setting
.val_rng_cnt
; j
++) {
633 value_cnt
= (int) (UNIT_ITEMS_COUNT
* ms_setting
.value_distr
[j
].value_prop
);
634 start_len
= ms_setting
.value_distr
[j
].start_len
;
635 end_len
= ms_setting
.value_distr
[j
].end_len
;
636 if ((start_len
<= 0) || (end_len
<= 0)) {
637 fprintf(stderr
, "value length must be greater than 0 bytes.\n");
641 if ((start_len
> MAX_VALUE_SIZE
) || (end_len
> MAX_VALUE_SIZE
)) {
642 fprintf(stderr
, "key length must be less than or equal to 1M.\n");
646 average_len
= (start_len
+ end_len
) / 2;
647 diff_len
= (end_len
- start_len
) / 2;
648 for (int k
= 0; k
< value_cnt
; k
++) {
649 if (offset
>= (m
+ 1) * UNIT_ITEMS_COUNT
) {
652 rnd
= (int) random();
654 ms_setting
.distr
[offset
].value_size
=
655 (diff_len
== 0) ? average_len
: average_len
+ (size_t) rnd
% diff_len
;
657 ms_setting
.distr
[offset
].value_size
=
658 (diff_len
== 0) ? average_len
: average_len
- (size_t) rnd
% diff_len
;
664 if (offset
< (m
+ 1) * UNIT_ITEMS_COUNT
) {
665 end
= (m
+ 1) * UNIT_ITEMS_COUNT
- offset
;
666 for (int i
= 0; i
< end
; i
++) {
667 ms_setting
.distr
[offset
++].value_size
= ms_setting
.avg_val_size
;
673 /* shuffle distribution */
674 for (int i
= 0; i
< units
; i
++) {
675 distr
= &ms_setting
.distr
[i
* UNIT_ITEMS_COUNT
];
676 for (int j
= 0; j
< 4; j
++) {
677 ms_shuffle_distr(distr
, UNIT_ITEMS_COUNT
);
680 } /* ms_build_distr */
683 * used to initialize the global character block. The character
684 * block is used to generate the suffix of the key and value. we
685 * only store a pointer in the character block for each key
686 * suffix or value string. It can save much memory to store key
689 static void ms_init_random_block() {
692 assert(ms_setting
.char_blk_size
> 0);
694 ms_setting
.char_block
= (char *) malloc(ms_setting
.char_blk_size
);
695 if (ms_setting
.char_block
== NULL
) {
696 fprintf(stderr
, "Can't allocate global char block.");
699 ptr
= ms_setting
.char_block
;
701 for (int i
= 0; (size_t) i
< ms_setting
.char_blk_size
; i
++) {
702 *(ptr
++) = ALPHANUMBERICS
[random() % CHAR_COUNT
];
704 } /* ms_init_random_block */
707 * after initialization, call this function to output the main
708 * configuration user specified.
710 static void ms_print_setting() {
711 fprintf(stdout
, "servers: %s\n", ms_setting
.srv_str
);
712 fprintf(stdout
, "threads count: %d\n", ms_setting
.nthreads
);
713 fprintf(stdout
, "concurrency: %d\n", ms_setting
.nconns
);
714 if (ms_setting
.run_time
> 0) {
715 fprintf(stdout
, "run time: %ds\n", ms_setting
.run_time
);
717 fprintf(stdout
, "execute number: %" PRId64
"\n", ms_setting
.exec_num
);
719 fprintf(stdout
, "windows size: %" PRId64
"k\n", (int64_t)(ms_setting
.win_size
/ 1024));
720 fprintf(stdout
, "set proportion: set_prop=%.2f\n", ms_setting
.cmd_distr
[CMD_SET
].cmd_prop
);
721 fprintf(stdout
, "get proportion: get_prop=%.2f\n", ms_setting
.cmd_distr
[CMD_GET
].cmd_prop
);
723 } /* ms_print_setting */
726 * previous part of slap mode initialization of setting structure
728 static void ms_setting_slapmode_init_pre() {
729 ms_setting
.exec_num
= DEFAULT_EXE_NUM
;
730 ms_setting
.verify_percent
= DEFAULT_VERIFY_RATE
;
731 ms_setting
.exp_ver_per
= DEFAULT_VERIFY_RATE
;
732 ms_setting
.overwrite_percent
= DEFAULT_OVERWRITE_RATE
;
733 ms_setting
.mult_key_num
= DEFAULT_DIV
;
734 ms_setting
.fixed_value_size
= 0;
735 ms_setting
.win_size
= DEFAULT_WINDOW_SIZE
;
736 ms_setting
.udp
= false;
737 ms_setting
.reconnect
= false;
738 ms_setting
.verbose
= false;
739 ms_setting
.facebook_test
= false;
740 ms_setting
.binary_prot_
= false;
741 ms_setting
.stat_freq
= 0;
742 ms_setting
.srv_str
= NULL
;
743 ms_setting
.cfg_file
= NULL
;
744 ms_setting
.sock_per_conn
= DEFAULT_SOCK_PER_CONN
;
745 ms_setting
.expected_tps
= 0;
746 ms_setting
.rep_write_srv
= 0;
747 } /* ms_setting_slapmode_init_pre */
750 * previous part of initialization of setting structure
752 void ms_setting_init_pre() {
753 memset(&ms_setting
, 0, sizeof(ms_setting
));
755 /* common initialize */
756 ms_setting
.ncpu
= ms_get_cpu_count();
757 ms_setting
.nthreads
= DEFAULT_THREADS_NUM
;
758 ms_setting
.nconns
= DEFAULT_CONNS_NUM
;
759 ms_setting
.run_time
= DEFAULT_RUN_TIME
;
760 ms_setting
.total_srv_cnt
= MCD_SRVS_NUM_INIT
;
762 (ms_mcd_server_t
*) malloc((size_t) ms_setting
.total_srv_cnt
* sizeof(ms_mcd_server_t
));
763 if (ms_setting
.servers
== NULL
) {
764 fprintf(stderr
, "Can't allocate servers structure.\n");
768 ms_setting_slapmode_init_pre();
769 } /* ms_setting_init_pre */
772 * post part of slap mode initialization of setting structure
774 static void ms_setting_slapmode_init_post() {
775 ms_setting
.total_key_rng_cnt
= KEY_RANGE_COUNT_INIT
;
776 ms_setting
.key_distr
=
777 (ms_key_distr_t
*) malloc((size_t) ms_setting
.total_key_rng_cnt
* sizeof(ms_key_distr_t
));
779 if (ms_setting
.key_distr
== NULL
) {
780 fprintf(stderr
, "Can't allocate key distribution structure.\n");
784 ms_setting
.total_val_rng_cnt
= VALUE_RANGE_COUNT_INIT
;
786 ms_setting
.value_distr
=
787 (ms_value_distr_t
*) malloc((size_t) ms_setting
.total_val_rng_cnt
* sizeof(ms_value_distr_t
));
789 if (ms_setting
.value_distr
== NULL
) {
790 fprintf(stderr
, "Can't allocate value distribution structure.\n");
794 ms_parse_cfg_file(ms_setting
.cfg_file
);
797 if ((ms_setting
.exec_num
== 0) && (ms_setting
.run_time
!= 0)) {
798 ms_setting
.exec_num
= (int64_t) MAX_EXEC_NUM
;
800 /* execute number mode */
801 ms_setting
.run_time
= 0;
804 if (ms_setting
.rep_write_srv
> 0) {
805 /* for replication test, need enable reconnect feature */
806 ms_setting
.reconnect
= true;
809 if (ms_setting
.facebook_test
&& (ms_setting
.mult_key_num
< 2)) {
811 "facebook test must work with multi-get, "
812 "please specify multi-get key number "
813 "with '--division' option.\n");
817 if (ms_setting
.facebook_test
&& ms_setting
.udp
) {
818 fprintf(stderr
, "facebook test couldn't work with UDP.\n");
822 if (ms_setting
.udp
&& (ms_setting
.sock_per_conn
> 1)) {
824 "UDP doesn't support multi-socks "
825 "in one connection structure.\n");
829 if ((ms_setting
.rep_write_srv
> 0) && (ms_setting
.srv_cnt
< 2)) {
830 fprintf(stderr
, "Please specify 2 servers at least for replication\n");
834 if ((ms_setting
.rep_write_srv
> 0) && (ms_setting
.srv_cnt
< ms_setting
.rep_write_srv
)) {
836 "Servers to do replication writing "
837 "is larger than the total servers\n");
841 if (ms_setting
.udp
&& (ms_setting
.rep_write_srv
> 0)) {
842 fprintf(stderr
, "UDP doesn't support replication.\n");
846 if (ms_setting
.facebook_test
&& (ms_setting
.rep_write_srv
> 0)) {
847 fprintf(stderr
, "facebook test couldn't work with replication.\n");
853 /* initialize global character block */
854 ms_init_random_block();
856 } /* ms_setting_slapmode_init_post */
859 * post part of initialization of setting structure
861 void ms_setting_init_post() {
862 ms_get_serverlist(ms_setting
.srv_str
);
863 ms_setting_slapmode_init_post();
867 * clean up the global setting structure
869 void ms_setting_cleanup() {
870 if (ms_setting
.distr
!= NULL
) {
871 free(ms_setting
.distr
);
874 if (ms_setting
.char_block
!= NULL
) {
875 free(ms_setting
.char_block
);
878 if (ms_setting
.srv_str
!= NULL
) {
879 free(ms_setting
.srv_str
);
882 if (ms_setting
.cfg_file
!= NULL
) {
883 free(ms_setting
.cfg_file
);
886 if (ms_setting
.servers
!= NULL
) {
887 free(ms_setting
.servers
);
890 if (ms_setting
.key_distr
!= NULL
) {
891 free(ms_setting
.key_distr
);
894 if (ms_setting
.value_distr
!= NULL
) {
895 free(ms_setting
.value_distr
);
897 } /* ms_setting_cleanup */