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 "mem_config.h"
14 #include <libmemcached/memcached.h>
21 #include <sys/types.h>
26 #include "ms_setting.h"
29 #define MAX_EXEC_NUM 0x4000000000000000 /* 1 << 62 */
30 #define ADDR_ALIGN(addr) ((addr + 15) & ~(16 - 1)) /* 16 bytes aligned */
31 #define RAND_CHAR_SIZE (10 * 1024 * 1024) /* 10M character table */
32 #define RESERVED_RAND_CHAR_SIZE (2 * 1024 * 1024) /* reserved 2M to avoid pointer sloping over */
34 #define DEFAULT_CONFIG_NAME ".memslap.cnf"
36 #define DEFAULT_THREADS_NUM 1 /* default start one thread */
37 #define DEFAULT_CONNS_NUM 16 /* default each thread with 16 connections */
38 #define DEFAULT_EXE_NUM 0 /* default execute number is 0 */
39 #define DEFAULT_VERIFY_RATE 0.0 /* default it doesn't do data verification */
40 #define DEFAULT_OVERWRITE_RATE 0.0 /* default it doesn't do overwrite */
41 #define DEFAULT_DIV 1 /* default it runs single get */
42 #define DEFAULT_RUN_TIME 600 /* default run time 10 minutes */
43 #define DEFAULT_WINDOW_SIZE (10 * UNIT_ITEMS_COUNT) /* default window size is 10k */
44 #define DEFAULT_SOCK_PER_CONN 1 /* default socks per connection is 1 */
46 /* Use this for string generation */
47 #define CHAR_COUNT 64 /* number of characters used to generate character table */
48 const char ALPHANUMBERICS
[]=
49 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-";
51 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
);
64 /* initialize setting structure */
65 static void ms_init_random_block(void);
66 static void ms_calc_avg_size(void);
67 static int ms_shuffle_distr(ms_distr_t
*distr
, int length
);
68 static void ms_build_distr(void);
69 static void ms_print_setting(void);
70 static void ms_setting_slapmode_init_pre(void);
71 static void ms_setting_slapmode_init_post(void);
73 #if !defined(HAVE_GETLINE)
75 static ssize_t
getline (char **line
, size_t *line_size
, FILE *fp
)
81 if (line
== NULL
|| line_size
== NULL
|| fp
== NULL
)
87 if (*line
== NULL
|| *line_size
== 0)
91 new_line
= (char *) realloc (*line
, *line_size
);
109 /* Make enough space for len+1 (for final NUL) bytes. */
110 if (cur_len
+ 1 >= *line_size
)
113 SSIZE_MAX
< SIZE_MAX
? (size_t) SSIZE_MAX
+ 1 : SIZE_MAX
;
114 size_t needed
= (2 * (*line_size
)) + 1;
117 if (needed_max
< needed
)
119 if (cur_len
+ 1 >= needed
)
126 new_line
= (char *)realloc(*line
, needed
);
127 if (new_line
== NULL
)
137 (*line
)[cur_len
]= (char)i
;
143 (*line
)[cur_len
] = '\0';
145 return (ssize_t
)cur_len
;
151 * parse the server list string, and build the servers
152 * information structure array. this function is used to parse
153 * the command line options specified by user.
155 * @param str, the string of server list
157 static void ms_get_serverlist(char *str
)
159 ms_mcd_server_t
*srvs
= NULL
;
162 * Servers list format is like this. For example:
163 * "localhost:11108, localhost:11109"
165 memcached_server_st
*server_pool
;
166 server_pool
= memcached_servers_parse(str
);
168 for (uint32_t loop
= 0; loop
< memcached_server_list_count(server_pool
); loop
++)
170 assert(ms_setting
.srv_cnt
< ms_setting
.total_srv_cnt
);
171 strcpy(ms_setting
.servers
[ms_setting
.srv_cnt
].srv_host_name
, server_pool
[loop
].hostname
);
172 ms_setting
.servers
[ms_setting
.srv_cnt
].srv_port
= server_pool
[loop
].port
;
173 ms_setting
.servers
[ms_setting
.srv_cnt
].disconn_cnt
= 0;
174 ms_setting
.servers
[ms_setting
.srv_cnt
].reconn_cnt
= 0;
175 ms_setting
.srv_cnt
++;
177 if (ms_setting
.srv_cnt
>= ms_setting
.total_srv_cnt
)
179 srvs
= (ms_mcd_server_t
*)realloc( ms_setting
.servers
,
180 (size_t)ms_setting
.total_srv_cnt
* sizeof(ms_mcd_server_t
) * 2);
183 fprintf(stderr
, "Can't reallocate servers structure.\n");
186 ms_setting
.servers
= srvs
;
187 ms_setting
.total_srv_cnt
*= 2;
191 memcached_server_free(server_pool
);
192 } /* ms_get_serverlist */
196 * used to get the CPU count of the current system
198 * @return return the cpu count if get, else return EXIT_FAILURE
200 static uint32_t ms_get_cpu_count()
202 #ifdef HAVE__SC_NPROCESSORS_ONLN
203 return sysconf(_SC_NPROCESSORS_CONF
);
206 # ifdef HAVE_CPU_SET_T
210 sched_getaffinity(0, sizeof(cpu_set_t
), &cpu_set
);
212 for (int i
= 0; i
< (sizeof(cpu_set_t
) * 8); i
++)
214 if (CPU_ISSET(i
, &cpu_set
))
225 /* the system with one cpu at least */
227 } /* ms_get_cpu_count */
231 * used to get the configure type based on the type string read
232 * from the configuration file.
234 * @param line, string of one line
236 * @return ms_conf_type_t
238 ms_conf_type_t
ms_get_conf_type(char *line
)
240 if (! memcmp(line
, "key", strlen("key")))
244 else if (! memcmp(line
, "value", strlen("value")))
248 else if (! memcmp(line
, "cmd", strlen("cmd")))
256 } /* ms_get_conf_type */
260 * judge whether the line is a line with useful data. used to
261 * parse the configuration file.
263 * @param line, string of one line
265 * @return if success, return EXIT_FAILURE, else return EXIT_SUCCESS
267 static int ms_is_line_data(char *line
)
269 assert(line
!= NULL
);
271 char *begin_ptr
= line
;
273 while (isspace(*begin_ptr
))
277 if ((begin_ptr
[0] == '\0') || (begin_ptr
[0] == '#'))
281 } /* ms_is_line_data */
285 * function to bypass blank line and comments
287 * @param line, string of one line
288 * @param nread, length of the line
290 * @return if it's EOF or not line data, return EXIT_SUCCESS, else return EXIT_FAILURE
292 static int ms_read_is_data(char *line
, ssize_t nread
)
294 if ((nread
== EOF
) || ! ms_is_line_data(line
))
298 } /* ms_read_is_data */
302 * if no configuration file, use this function to create the default
303 * configuration file.
305 static void ms_no_config_file()
307 char userpath
[PATH_MAX
];
308 struct passwd
*usr
= NULL
;
311 usr
= getpwuid(getuid());
313 snprintf(userpath
, PATH_MAX
, "%s/%s", usr
->pw_dir
, DEFAULT_CONFIG_NAME
);
315 if (access (userpath
, F_OK
| R_OK
) == 0)
318 fd
= fopen(userpath
, "w+");
322 fprintf(stderr
, "Could not create default configure file %s\n", userpath
);
323 perror(strerror(errno
));
326 fprintf(fd
, "%s", DEFAULT_CONGIF_STR
);
330 ms_setting
.cfg_file
= strdup(userpath
);
331 } /* ms_no_config_file */
335 * parse the configuration file
337 * @param cfg_file, the configuration file name
339 static void ms_parse_cfg_file(char *cfg_file
)
342 size_t start_len
, end_len
;
348 ms_conf_type_t conf_type
;
350 ms_key_distr_t
*key_distr
= NULL
;
351 ms_value_distr_t
*val_distr
= NULL
;
353 if (cfg_file
== NULL
)
356 cfg_file
= ms_setting
.cfg_file
;
359 /*read key value configure file*/
360 if ((f
= fopen(cfg_file
, "r")) == NULL
)
362 fprintf(stderr
, "Can not open file: '%s'.\n", cfg_file
);
368 if ((((nread
= getline(&line
, &read_len
, f
)) == 1)
369 || ! ms_read_is_data(line
, nread
)) && (nread
!= EOF
)) /* bypass blank line */
374 fprintf(stderr
, "Bad configuration file, no configuration find.\n");
377 conf_type
= ms_get_conf_type(line
);
381 while (! end_of_file
)
388 if ((((nread
= getline(&line
, &read_len
, f
)) == 1)
389 || ! ms_read_is_data(line
, nread
)) && (nread
!= EOF
)) /* bypass blank line */
394 if (sscanf(line
, "%zu %zu %lf ", &start_len
,
395 &end_len
, &proportion
) != 3)
397 conf_type
= ms_get_conf_type(line
);
400 ms_setting
.key_distr
[ms_setting
.key_rng_cnt
].start_len
= start_len
;
401 ms_setting
.key_distr
[ms_setting
.key_rng_cnt
].end_len
= end_len
;
402 ms_setting
.key_distr
[ms_setting
.key_rng_cnt
].key_prop
= proportion
;
403 ms_setting
.key_rng_cnt
++;
405 if (ms_setting
.key_rng_cnt
>= ms_setting
.total_key_rng_cnt
)
407 key_distr
= (ms_key_distr_t
*)realloc(
408 ms_setting
.key_distr
,
410 total_key_rng_cnt
* sizeof(ms_key_distr_t
) * 2);
411 if (key_distr
== NULL
)
414 "Can't reallocate key distribution structure.\n");
417 ms_setting
.key_distr
= key_distr
;
418 ms_setting
.total_key_rng_cnt
*= 2;
430 if ((((nread
= getline(&line
, &read_len
, f
)) == 1)
431 || ! ms_read_is_data(line
, nread
)) && (nread
!= EOF
)) /* bypass blank line */
436 if (sscanf(line
, "%zu %zu %lf", &start_len
, &end_len
,
439 conf_type
= ms_get_conf_type(line
);
442 ms_setting
.value_distr
[ms_setting
.val_rng_cnt
].start_len
=
444 ms_setting
.value_distr
[ms_setting
.val_rng_cnt
].end_len
= end_len
;
445 ms_setting
.value_distr
[ms_setting
.val_rng_cnt
].value_prop
=
447 ms_setting
.val_rng_cnt
++;
449 if (ms_setting
.val_rng_cnt
>= ms_setting
.total_val_rng_cnt
)
451 val_distr
= (ms_value_distr_t
*)realloc(
452 ms_setting
.value_distr
,
454 total_val_rng_cnt
* sizeof(ms_value_distr_t
) * 2);
455 if (val_distr
== NULL
)
458 "Can't reallocate key distribution structure.\n");
461 ms_setting
.value_distr
= val_distr
;
462 ms_setting
.total_val_rng_cnt
*= 2;
474 if ((((nread
= getline(&line
, &read_len
, f
)) == 1)
475 || ! ms_read_is_data(line
, nread
)) && (nread
!= EOF
)) /* bypass blank line */
480 if (sscanf(line
, "%d %lf", &cmd_type
, &proportion
) != 2)
482 conf_type
= ms_get_conf_type(line
);
485 if (cmd_type
>= CMD_NULL
)
489 ms_setting
.cmd_distr
[ms_setting
.cmd_used_count
].cmd_type
=
491 ms_setting
.cmd_distr
[ms_setting
.cmd_used_count
].cmd_prop
=
493 ms_setting
.cmd_used_count
++;
503 if ((((nread
= getline(&line
, &read_len
, f
)) == 1)
504 || ! ms_read_is_data(line
, nread
)) && (nread
!= EOF
)) /* bypass blank line */
509 if ((conf_type
= ms_get_conf_type(line
)) != CONF_NULL
)
532 } /* ms_parse_cfg_file */
535 /* calculate the average size of key and value */
536 static void ms_calc_avg_size()
538 double avg_val_size
= 0.0;
539 double avg_key_size
= 0.0;
542 double averge_len
= 0.0;
546 for (int j
= 0; j
< ms_setting
.val_rng_cnt
; j
++)
548 val_pro
= ms_setting
.value_distr
[j
].value_prop
;
549 start_len
= ms_setting
.value_distr
[j
].start_len
;
550 end_len
= ms_setting
.value_distr
[j
].end_len
;
552 averge_len
= val_pro
* ((double)(start_len
+ end_len
)) / 2;
553 avg_val_size
+= averge_len
;
556 for (int j
= 0; j
< ms_setting
.key_rng_cnt
; j
++)
558 key_pro
= ms_setting
.key_distr
[j
].key_prop
;
559 start_len
= ms_setting
.key_distr
[j
].start_len
;
560 end_len
= ms_setting
.key_distr
[j
].end_len
;
562 averge_len
= key_pro
* ((double)(start_len
+ end_len
)) / 2;
563 avg_key_size
+= averge_len
;
566 ms_setting
.avg_val_size
= (size_t)avg_val_size
;
567 ms_setting
.avg_key_size
= (size_t)avg_key_size
;
568 } /* ms_calc_avg_size */
572 * used to shuffle key and value distribution array to ensure
573 * (key, value) pair with different set.
575 * @param distr, pointer of distribution structure array
576 * @param length, length of the array
578 * @return always return EXIT_SUCCESS
580 static int ms_shuffle_distr(ms_distr_t
*distr
, int length
)
587 for (i
= 0; i
< length
; i
++)
590 j
= (int)(rnd
% (length
- i
)) + i
;
595 tmp_size
= distr
[j
].key_size
;
596 distr
[j
].key_size
= distr
[i
].key_size
;
597 distr
[i
].key_size
= tmp_size
;
601 tmp_offset
= distr
[j
].key_offset
;
602 distr
[j
].key_offset
= distr
[i
].key_offset
;
603 distr
[i
].key_offset
= tmp_offset
;
607 tmp_size
= distr
[j
].value_size
;
608 distr
[j
].value_size
= distr
[i
].value_size
;
609 distr
[i
].value_size
= tmp_size
;
618 } /* ms_shuffle_distr */
622 * according to the key and value distribution, to build the
623 * (key, value) pair distribution. the (key, value) pair
624 * distribution array is global, each connection set or get
625 * object keeping this distribution, for the final result, we
626 * can reach the expected key and value distribution.
628 static void ms_build_distr()
634 size_t average_len
= 0;
639 ms_distr_t
*distr
= NULL
;
640 int units
= (int)ms_setting
.win_size
/ UNIT_ITEMS_COUNT
;
642 /* calculate average value size and key size */
645 ms_setting
.char_blk_size
= RAND_CHAR_SIZE
;
647 (int)((ms_setting
.char_blk_size
- RESERVED_RAND_CHAR_SIZE
)
650 ms_setting
.distr
= (ms_distr_t
*)malloc(
651 sizeof(ms_distr_t
) * ms_setting
.win_size
);
652 if (ms_setting
.distr
== NULL
)
654 fprintf(stderr
, "Can't allocate distribution array.");
659 * character block is divided by how many different key
660 * size, each different key size has the same size character
663 for (int m
= 0; m
< units
; m
++)
665 for (int i
= 0; i
< UNIT_ITEMS_COUNT
; i
++)
667 ms_setting
.distr
[m
* UNIT_ITEMS_COUNT
+ i
].key_offset
=
668 ADDR_ALIGN(key_scope_size
* i
);
672 /* initialize key size distribution */
673 for (int m
= 0; m
< units
; m
++)
675 for (int j
= 0; j
< ms_setting
.key_rng_cnt
; j
++)
677 key_cnt
= (int)(UNIT_ITEMS_COUNT
* ms_setting
.key_distr
[j
].key_prop
);
678 start_len
= ms_setting
.key_distr
[j
].start_len
;
679 end_len
= ms_setting
.key_distr
[j
].end_len
;
680 if ((start_len
< MIN_KEY_SIZE
) || (end_len
< MIN_KEY_SIZE
))
682 fprintf(stderr
, "key length must be greater than 16 bytes.\n");
686 if (! ms_setting
.binary_prot_
687 && ((start_len
> MAX_KEY_SIZE
) || (end_len
> MAX_KEY_SIZE
)))
689 fprintf(stderr
, "key length must be less than 250 bytes.\n");
693 average_len
= (start_len
+ end_len
) / 2;
694 diff_len
= (end_len
- start_len
) / 2;
695 for (int k
= 0; k
< key_cnt
; k
++)
697 if (offset
>= (m
+ 1) * UNIT_ITEMS_COUNT
)
704 ms_setting
.distr
[offset
].key_size
=
705 (diff_len
== 0) ? average_len
:
706 average_len
+ (size_t)rnd
711 ms_setting
.distr
[offset
].key_size
=
712 (diff_len
== 0) ? average_len
:
713 average_len
- (size_t)rnd
720 if (offset
< (m
+ 1) * UNIT_ITEMS_COUNT
)
722 end
= (m
+ 1) * UNIT_ITEMS_COUNT
- offset
;
723 for (int i
= 0; i
< end
; i
++)
725 ms_setting
.distr
[offset
].key_size
= ms_setting
.avg_key_size
;
732 /* initialize value distribution */
733 if (ms_setting
.fixed_value_size
!= 0)
735 for (int i
= 0; i
< units
* UNIT_ITEMS_COUNT
; i
++)
737 ms_setting
.distr
[i
].value_size
= ms_setting
.fixed_value_size
;
742 for (int m
= 0; m
< units
; m
++)
744 for (int j
= 0; j
< ms_setting
.val_rng_cnt
; j
++)
747 (int)(UNIT_ITEMS_COUNT
* ms_setting
.value_distr
[j
].value_prop
);
748 start_len
= ms_setting
.value_distr
[j
].start_len
;
749 end_len
= ms_setting
.value_distr
[j
].end_len
;
750 if ((start_len
<= 0) || (end_len
<= 0))
752 fprintf(stderr
, "value length must be greater than 0 bytes.\n");
756 if ((start_len
> MAX_VALUE_SIZE
) || (end_len
> MAX_VALUE_SIZE
))
758 fprintf(stderr
, "key length must be less than or equal to 1M.\n");
762 average_len
= (start_len
+ end_len
) / 2;
763 diff_len
= (end_len
- start_len
) / 2;
764 for (int k
= 0; k
< value_cnt
; k
++)
766 if (offset
>= (m
+ 1) * UNIT_ITEMS_COUNT
)
773 ms_setting
.distr
[offset
].value_size
=
774 (diff_len
== 0) ? average_len
:
776 + (size_t)rnd
% diff_len
;
780 ms_setting
.distr
[offset
].value_size
=
781 (diff_len
== 0) ? average_len
:
783 - (size_t)rnd
% diff_len
;
789 if (offset
< (m
+ 1) * UNIT_ITEMS_COUNT
)
791 end
= (m
+ 1) * UNIT_ITEMS_COUNT
- offset
;
792 for (int i
= 0; i
< end
; i
++)
794 ms_setting
.distr
[offset
++].value_size
= ms_setting
.avg_val_size
;
800 /* shuffle distribution */
801 for (int i
= 0; i
< units
; i
++)
803 distr
= &ms_setting
.distr
[i
* UNIT_ITEMS_COUNT
];
804 for (int j
= 0; j
< 4; j
++)
806 ms_shuffle_distr(distr
, UNIT_ITEMS_COUNT
);
809 } /* ms_build_distr */
813 * used to initialize the global character block. The character
814 * block is used to generate the suffix of the key and value. we
815 * only store a pointer in the character block for each key
816 * suffix or value string. It can save much memory to store key
819 static void ms_init_random_block()
823 assert(ms_setting
.char_blk_size
> 0);
825 ms_setting
.char_block
= (char *)malloc(ms_setting
.char_blk_size
);
826 if (ms_setting
.char_block
== NULL
)
828 fprintf(stderr
, "Can't allocate global char block.");
831 ptr
= ms_setting
.char_block
;
833 for (int i
= 0; (size_t)i
< ms_setting
.char_blk_size
; i
++)
835 *(ptr
++)= ALPHANUMBERICS
[random() % CHAR_COUNT
];
837 } /* ms_init_random_block */
841 * after initialization, call this function to output the main
842 * configuration user specified.
844 static void ms_print_setting()
846 fprintf(stdout
, "servers : %s\n", ms_setting
.srv_str
);
847 fprintf(stdout
, "threads count: %d\n", ms_setting
.nthreads
);
848 fprintf(stdout
, "concurrency: %d\n", ms_setting
.nconns
);
849 if (ms_setting
.run_time
> 0)
851 fprintf(stdout
, "run time: %ds\n", ms_setting
.run_time
);
855 fprintf(stdout
, "execute number: %" PRId64
"\n", ms_setting
.exec_num
);
857 fprintf(stdout
, "windows size: %" PRId64
"k\n",
858 (int64_t)(ms_setting
.win_size
/ 1024));
859 fprintf(stdout
, "set proportion: set_prop=%.2f\n",
860 ms_setting
.cmd_distr
[CMD_SET
].cmd_prop
);
861 fprintf(stdout
, "get proportion: get_prop=%.2f\n",
862 ms_setting
.cmd_distr
[CMD_GET
].cmd_prop
);
864 } /* ms_print_setting */
868 * previous part of slap mode initialization of setting structure
870 static void ms_setting_slapmode_init_pre()
872 ms_setting
.exec_num
= DEFAULT_EXE_NUM
;
873 ms_setting
.verify_percent
= DEFAULT_VERIFY_RATE
;
874 ms_setting
.exp_ver_per
= DEFAULT_VERIFY_RATE
;
875 ms_setting
.overwrite_percent
= DEFAULT_OVERWRITE_RATE
;
876 ms_setting
.mult_key_num
= DEFAULT_DIV
;
877 ms_setting
.fixed_value_size
= 0;
878 ms_setting
.win_size
= DEFAULT_WINDOW_SIZE
;
879 ms_setting
.udp
= false;
880 ms_setting
.reconnect
= false;
881 ms_setting
.verbose
= false;
882 ms_setting
.facebook_test
= false;
883 ms_setting
.binary_prot_
= false;
884 ms_setting
.stat_freq
= 0;
885 ms_setting
.srv_str
= NULL
;
886 ms_setting
.cfg_file
= NULL
;
887 ms_setting
.sock_per_conn
= DEFAULT_SOCK_PER_CONN
;
888 ms_setting
.expected_tps
= 0;
889 ms_setting
.rep_write_srv
= 0;
890 } /* ms_setting_slapmode_init_pre */
894 * previous part of initialization of setting structure
896 void ms_setting_init_pre()
898 memset(&ms_setting
, 0, sizeof(ms_setting
));
900 /* common initialize */
901 ms_setting
.ncpu
= ms_get_cpu_count();
902 ms_setting
.nthreads
= DEFAULT_THREADS_NUM
;
903 ms_setting
.nconns
= DEFAULT_CONNS_NUM
;
904 ms_setting
.run_time
= DEFAULT_RUN_TIME
;
905 ms_setting
.total_srv_cnt
= MCD_SRVS_NUM_INIT
;
906 ms_setting
.servers
= (ms_mcd_server_t
*)malloc(
907 (size_t)ms_setting
.total_srv_cnt
908 * sizeof(ms_mcd_server_t
));
909 if (ms_setting
.servers
== NULL
)
911 fprintf(stderr
, "Can't allocate servers structure.\n");
915 ms_setting_slapmode_init_pre();
916 } /* ms_setting_init_pre */
920 * post part of slap mode initialization of setting structure
922 static void ms_setting_slapmode_init_post()
924 ms_setting
.total_key_rng_cnt
= KEY_RANGE_COUNT_INIT
;
925 ms_setting
.key_distr
=
926 (ms_key_distr_t
*)malloc((size_t)ms_setting
.total_key_rng_cnt
* sizeof(ms_key_distr_t
));
928 if (ms_setting
.key_distr
== NULL
)
930 fprintf(stderr
, "Can't allocate key distribution structure.\n");
934 ms_setting
.total_val_rng_cnt
= VALUE_RANGE_COUNT_INIT
;
936 ms_setting
.value_distr
=
937 (ms_value_distr_t
*)malloc((size_t)ms_setting
.total_val_rng_cnt
* sizeof( ms_value_distr_t
));
939 if (ms_setting
.value_distr
== NULL
)
941 fprintf(stderr
, "Can't allocate value distribution structure.\n");
945 ms_parse_cfg_file(ms_setting
.cfg_file
);
948 if ((ms_setting
.exec_num
== 0) && (ms_setting
.run_time
!= 0))
950 ms_setting
.exec_num
= (int64_t)MAX_EXEC_NUM
;
954 /* execute number mode */
955 ms_setting
.run_time
= 0;
958 if (ms_setting
.rep_write_srv
> 0)
960 /* for replication test, need enable reconnect feature */
961 ms_setting
.reconnect
= true;
964 if (ms_setting
.facebook_test
&& (ms_setting
.mult_key_num
< 2))
966 fprintf(stderr
, "facebook test must work with multi-get, "
967 "please specify multi-get key number "
968 "with '--division' option.\n");
972 if (ms_setting
.facebook_test
&& ms_setting
.udp
)
974 fprintf(stderr
, "facebook test couldn't work with UDP.\n");
978 if (ms_setting
.udp
&& (ms_setting
.sock_per_conn
> 1))
980 fprintf(stderr
, "UDP doesn't support multi-socks "
981 "in one connection structure.\n");
985 if ((ms_setting
.rep_write_srv
> 0) && (ms_setting
.srv_cnt
< 2))
987 fprintf(stderr
, "Please specify 2 servers at least for replication\n");
991 if ((ms_setting
.rep_write_srv
> 0)
992 && (ms_setting
.srv_cnt
< ms_setting
.rep_write_srv
))
994 fprintf(stderr
, "Servers to do replication writing "
995 "is larger than the total servers\n");
999 if (ms_setting
.udp
&& (ms_setting
.rep_write_srv
> 0))
1001 fprintf(stderr
, "UDP doesn't support replication.\n");
1005 if (ms_setting
.facebook_test
&& (ms_setting
.rep_write_srv
> 0))
1007 fprintf(stderr
, "facebook test couldn't work with replication.\n");
1013 /* initialize global character block */
1014 ms_init_random_block();
1016 } /* ms_setting_slapmode_init_post */
1020 * post part of initialization of setting structure
1022 void ms_setting_init_post()
1024 ms_get_serverlist(ms_setting
.srv_str
);
1025 ms_setting_slapmode_init_post();
1030 * clean up the global setting structure
1032 void ms_setting_cleanup()
1034 if (ms_setting
.distr
!= NULL
)
1036 free(ms_setting
.distr
);
1039 if (ms_setting
.char_block
!= NULL
)
1041 free(ms_setting
.char_block
);
1044 if (ms_setting
.srv_str
!= NULL
)
1046 free(ms_setting
.srv_str
);
1049 if (ms_setting
.cfg_file
!= NULL
)
1051 free(ms_setting
.cfg_file
);
1054 if (ms_setting
.servers
!= NULL
)
1056 free(ms_setting
.servers
);
1059 if (ms_setting
.key_distr
!= NULL
)
1061 free(ms_setting
.key_distr
);
1064 if (ms_setting
.value_distr
!= NULL
)
1066 free(ms_setting
.value_distr
);
1068 } /* ms_setting_cleanup */