Schooner memslap changes
[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 #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 /* 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);
55
56
57 /**
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.
61 *
62 * @param str, the string of server list
63 */
64 static void ms_get_serverlist(char *str)
65 {
66 char *string;
67 int64_t port;
68 char *begin_ptr;
69 char *end_ptr = str + strlen(str);
70 ms_mcd_server_t *srvs = NULL;
71 char buffer[512];
72 char *ptr = NULL;
73
74 /**
75 * Servers list format is like this. For example:
76 * "localhost:11108, localhost:11109"
77 */
78 for (begin_ptr = str, string = index(str, ',');
79 begin_ptr != end_ptr;
80 string = index(begin_ptr, ',')) {
81 port = 0;
82
83 if (string) {
84 memcpy(buffer, begin_ptr, (size_t)(string - begin_ptr));
85 buffer[(unsigned int)(string - begin_ptr)]= '\0';
86 begin_ptr = string+1;
87 } else {
88 size_t length= strlen(begin_ptr);
89 memcpy(buffer, begin_ptr, length);
90 buffer[length] = '\0';
91 begin_ptr = end_ptr;
92 }
93
94 ptr = index(buffer, ':');
95
96 if (ptr != NULL) {
97 ptr[0] = '\0';
98 ptr++;
99 port = strtol(ptr, (char **)NULL, 10);
100 }
101
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++;
108
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);
112 if (srvs == NULL) {
113 fprintf(stderr, "Can't reallocate servers structure.\n");
114 exit(1);
115 }
116 ms_setting.servers = srvs;
117 ms_setting.total_srv_cnt *= 2;
118 }
119
120 if (isspace(*begin_ptr))
121 begin_ptr++;
122 }
123 }
124
125 /**
126 * used to get the CPU count of the current system
127 *
128 * @return return the cpu count if get, else return 1
129 */
130 static int ms_get_cpu_count()
131 {
132 #ifdef HAVE__SC_NPROCESSORS_ONLN
133 return (sysconf(_SC_NPROCESSORS_CONF));
134 #else
135 #ifdef HAVE_CPU_SET_T
136 int cpu_count = 0;
137 cpu_set_t cpu_set;
138
139 sched_getaffinity(0, sizeof(cpu_set_t), &cpu_set);
140
141 for (int i = 0; i < (sizeof(cpu_set_t) * 8); i++) {
142 if (CPU_ISSET(i, &cpu_set)) {
143 cpu_count++;
144 }
145 }
146
147 return cpu_count;
148 #endif
149 #endif
150
151 /* the system with one cpu at least */
152 return 1;
153 }
154
155 /**
156 * used to get the configure type based on the type string read
157 * from the configuration file.
158 *
159 * @param line, string of one line
160 *
161 * @return ms_conf_type_t
162 */
163 ms_conf_type_t ms_get_conf_type(char *line)
164 {
165 if (!memcmp(line, "key", strlen("key")) ) {
166 return CONF_KEY;
167 } else if (!memcmp(line, "value", strlen("value"))) {
168 return CONF_VALUE;
169 } else if (!memcmp(line, "cmd", strlen("cmd"))) {
170 return CONF_CMD;
171 } else {
172 return CONF_NULL;
173 }
174 }
175
176 /**
177 * judge whether the line is a line with useful data. used to
178 * parse the configuration file.
179 *
180 * @param line, string of one line
181 *
182 * @return if success, return 1, else return 0
183 */
184 static int ms_is_line_data(char* line)
185 {
186 assert(line != NULL);
187
188 char* begin_ptr = line;
189
190 while(isspace(*begin_ptr))
191 begin_ptr++;
192 if (begin_ptr[0] == '\0' || begin_ptr[0] == '#')
193 return 0;
194 return 1;
195 }
196
197 /**
198 * function to bypass blank line and comments
199 *
200 * @param line, string of one line
201 * @param nread, length of the line
202 *
203 * @return if it's EOF or not line data, return 0, else return 1
204 */
205 static int ms_read_is_data(char* line, ssize_t nread)
206 {
207 if (nread == EOF || !ms_is_line_data(line))
208 return 0;
209 return 1;
210 }
211
212 /**
213 * if no configuration file, use this function to create the default
214 * configuration file.
215 */
216 static void ms_no_config_file()
217 {
218 FILE *fd = fopen("config", "w+");
219 fprintf(fd, "%s", DEFAULT_CONGIF_STR);
220 fclose(fd);
221
222 ms_setting.cfg_file = strdup("config");
223 }
224
225 /**
226 * parse the configuration file
227 *
228 * @param cfg_file, the configuration file name
229 */
230 static void ms_parse_cfg_file(char *cfg_file)
231 {
232 FILE *f;
233 size_t start_len, end_len;
234 double proportion;
235 size_t frequence;
236 char* line = NULL;
237 size_t read_len;
238 ssize_t nread;
239 int cmd_type;
240 ms_conf_type_t conf_type;
241 int end_of_file = 0;
242 ms_key_distr_t *key_distr = NULL;
243 ms_value_distr_t *val_distr = NULL;
244 bool no_cfg = false;
245
246 if (cfg_file == NULL) {
247 ms_no_config_file();
248 cfg_file = ms_setting.cfg_file;
249 no_cfg = true;
250 }
251
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);
255 exit(1);
256 }
257
258 while (1) {
259 if ((((nread = getline(&line, &read_len, f)) == 1) ||
260 !ms_read_is_data(line, nread)) && (nread != EOF))/* bypass blank line */
261 continue;
262 if (nread == EOF) {
263 fprintf(stderr, "Bad configuration file, no configuration find.\n");
264 exit(1);
265 }
266 conf_type = ms_get_conf_type(line);
267 break;
268 }
269
270 while (!end_of_file) {
271 switch (conf_type) {
272 case CONF_KEY:
273 while (1) {
274 if ((((nread = getline(&line, &read_len, f)) == 1) ||
275 !ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */
276 continue;
277
278 if (nread != EOF) {
279 if (sscanf(line, "%lu %lu %lf ", &start_len,
280 &end_len, &proportion) != 3) {
281 conf_type = ms_get_conf_type(line);
282 break;
283 }
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++;
288
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");
294 exit(1);
295 }
296 ms_setting.key_distr = key_distr;
297 ms_setting.total_key_rng_cnt *= 2;
298 }
299 continue;
300 }
301 end_of_file = 1;
302 break;
303 }
304 break;
305
306 case CONF_VALUE:
307 while (1) {
308 if ((((nread = getline(&line, &read_len, f)) == 1) ||
309 !ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */
310 continue;
311
312 if (nread != EOF) {
313 if (sscanf(line, "%lu %lu %lf %lu", &start_len, &end_len,
314 &proportion, &frequence) !=3 ) {
315 conf_type = ms_get_conf_type(line);
316 break;
317 }
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++;
322
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");
328 exit(1);
329 }
330 ms_setting.value_distr = val_distr;
331 ms_setting.total_val_rng_cnt *= 2;
332 }
333 continue;
334 }
335 end_of_file = 1;
336 break;
337 }
338 break;
339
340 case CONF_CMD:
341 while (1) {
342 if ((((nread = getline(&line, &read_len, f)) == 1) ||
343 !ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */
344 continue;
345
346 if (nread != EOF) {
347 if (sscanf(line, "%d %lf\n", &cmd_type, &proportion) != 2) {
348 conf_type = ms_get_conf_type(line);
349 break;
350 }
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++;
354 continue;
355 }
356 end_of_file = 1;
357 break;
358 }
359
360 case CONF_NULL:
361 while (1) {
362 if ((((nread = getline(&line, &read_len, f)) == 1) ||
363 !ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */
364 continue;
365
366 if (nread != EOF) {
367 if ((conf_type = ms_get_conf_type(line)) != CONF_NULL) {
368 break;
369 }
370 continue;
371 }
372 end_of_file = 1;
373 break;
374 }
375 break;
376 default:
377 assert(0);
378 break;
379 }
380 }
381
382 fclose(f);
383
384 if (no_cfg) {
385 remove(ms_setting.cfg_file);
386 }
387
388 if (line != NULL)
389 free(line);
390 }
391
392 /* calculate the average size of key and value */
393 static void ms_calc_avg_size()
394 {
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;
401 size_t end_len = 0;
402
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;
407
408 averge_len = val_pro * ((double)(start_len + end_len)) / 2;
409 avg_val_size += averge_len;
410 }
411
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;
416
417 averge_len = key_pro * ((double)(start_len + end_len)) / 2;
418 avg_key_size += averge_len;
419 }
420
421 ms_setting.avg_val_size = (size_t)avg_val_size;
422 ms_setting.avg_key_size = (size_t)avg_key_size;
423 }
424
425 /**
426 * used to shuffle key and value distribution array to ensure
427 * (key, value) pair with different set.
428 *
429 * @param distr, pointer of distribution structure array
430 * @param length, length of the array
431 *
432 * @return always return 0
433 */
434 static int ms_shuffle_distr(ms_distr_t *distr, int length)
435 {
436 int i, j;
437 int tmp_offset;
438 size_t tmp_size;
439 int64_t rnd;
440
441 for (i = 0; i < length; i++) {
442 rnd = random();
443 j = (int)(rnd % (length - i)) + i;
444
445 switch (rnd % 3) {
446 case 0:
447 tmp_size = distr[j].key_size;
448 distr[j].key_size = distr[i].key_size;
449 distr[i].key_size = tmp_size;
450 break;
451 case 1:
452 tmp_offset = distr[j].key_offset;
453 distr[j].key_offset = distr[i].key_offset;
454 distr[i].key_offset = tmp_offset;
455 break;
456 case 2:
457 tmp_size = distr[j].value_size;
458 distr[j].value_size = distr[i].value_size;
459 distr[i].value_size = tmp_size;
460 break;
461 default:
462 break;
463 }
464 }
465
466 return 0;
467 }
468
469 /**
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.
475 */
476 static void ms_build_distr()
477 {
478 int offset = 0;
479 int end = 0;
480 int key_cnt = 0;
481 int value_cnt = 0;
482 size_t average_len = 0;
483 size_t diff_len = 0;
484 size_t start_len = 0;
485 size_t end_len = 0;
486 int rnd = 0;
487 ms_distr_t *distr = NULL;
488 int units = (int)ms_setting.win_size / UNIT_ITEMS_COUNT;
489
490 /* calculate average value size and key size */
491 ms_calc_avg_size();
492
493 ms_setting.char_blk_size = RAND_CHAR_SIZE;
494 int key_scope_size = (int)((ms_setting.char_blk_size - RESERVED_RAND_CHAR_SIZE)
495 / UNIT_ITEMS_COUNT);
496
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.");
500 exit(1);
501 }
502
503 /**
504 * character block is divided by how many different key
505 * size, each different key size has the same size character
506 * range.
507 */
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);
512 }
513 }
514
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");
523 exit(1);
524 }
525
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");
528 exit(1);
529 }
530
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) {
535 break;
536 }
537 rnd = (int)random();
538 if (k % 2 == 0) {
539 ms_setting.distr[offset].key_size = (diff_len == 0) ? average_len :
540 average_len + (size_t)rnd % diff_len;
541 } else {
542 ms_setting.distr[offset].key_size = (diff_len == 0) ? average_len :
543 average_len - (size_t)rnd % diff_len;
544 }
545 offset++;
546 }
547 }
548
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;
553 offset++;
554 }
555 }
556 }
557 offset = 0;
558
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;
563 }
564 } else {
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");
572 exit(1);
573 }
574
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");
577 exit(1);
578 }
579
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) {
584 break;
585 }
586 rnd = (int)random();
587 if (k % 2 == 0) {
588 ms_setting.distr[offset].value_size = (diff_len == 0) ? average_len :
589 average_len + (size_t)rnd % diff_len;
590 } else {
591 ms_setting.distr[offset].value_size = (diff_len == 0) ? average_len :
592 average_len - (size_t)rnd % diff_len;
593 }
594 offset++;
595 }
596 }
597
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;
602 }
603 }
604 }
605 }
606
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);
612 }
613 }
614 }
615
616 /**
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
621 * or value string.
622 */
623 static void ms_init_random_block()
624 {
625 char *ptr = NULL;
626
627 assert(ms_setting.char_blk_size > 0);
628
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.");
632 exit(1);
633 }
634 ptr = ms_setting.char_block;
635
636 for (int i = 0; (size_t)i < ms_setting.char_blk_size; i++) {
637 *(ptr++) = ALPHANUMBERICS[random() % CHAR_COUNT];
638 }
639 }
640
641 /**
642 * after initialization, call this function to output the main
643 * configuration user specified.
644 */
645 static void ms_print_setting()
646 {
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);
651 } else {
652 fprintf(stdout, "execute number: %ld\n", ms_setting.exec_num);
653 }
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);
659 fflush(stdout);
660 }
661
662 /**
663 * previous part of slap mode initialization of setting structure
664 */
665 static void ms_setting_slapmode_init_pre()
666 {
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;
685 }
686
687 /**
688 * previous part of initialization of setting structure
689 */
690 void ms_setting_init_pre()
691 {
692 memset(&ms_setting, 0, sizeof(ms_setting_t));
693
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");
704 exit(1);
705 }
706
707 ms_setting_slapmode_init_pre();
708 }
709
710 /**
711 * post part of slap mode initialization of setting structure
712 */
713 static void ms_setting_slapmode_init_post()
714 {
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");
720 exit(1);
721 }
722
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");
728 exit(1);
729 }
730
731 ms_parse_cfg_file(ms_setting.cfg_file);
732
733 /* run time mode */
734 if (ms_setting.exec_num == 0 && ms_setting.run_time != 0) {
735 ms_setting.exec_num = (int64_t)MAX_EXEC_NUM;
736 } else {
737 /* execute number mode */
738 ms_setting.run_time = 0;
739 }
740
741 if (ms_setting.rep_write_srv > 0) {
742 /* for replication test, need enable reconnect feature */
743 ms_setting.reconnect = true;
744 }
745
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");
750 exit(1);
751 }
752
753 if (ms_setting.facebook_test && ms_setting.udp) {
754 fprintf(stderr, "facebook test couldn't work with UDP.\n");
755 exit(1);
756 }
757
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");
761 exit(1);
762 }
763
764 if ((ms_setting.udp || ms_setting.facebook_test) && ms_setting.binary_prot) {
765 fprintf(stderr, "Binary protocol doesn't support UDP now.\n");
766 exit(1);
767 }
768
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");
771 exit(1);
772 }
773
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");
777 exit(1);
778 }
779
780 if (ms_setting.udp && ms_setting.rep_write_srv > 0) {
781 fprintf(stderr, "UDP doesn't support replication.\n");
782 exit(1);
783 }
784
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");
788 exit(1);
789 }
790
791 if (ms_setting.facebook_test && ms_setting.rep_write_srv > 0) {
792 fprintf(stderr, "facebook test couldn't work with replication.\n");
793 exit(1);
794 }
795
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");
799 exit(1);
800 }
801
802 ms_build_distr();
803
804 /* initialize global character block */
805 ms_init_random_block();
806 ms_print_setting();
807 }
808
809 /**
810 * post part of initialization of setting structure
811 */
812 void ms_setting_init_post()
813 {
814 ms_get_serverlist(ms_setting.srv_str);
815 ms_setting_slapmode_init_post();
816 }
817
818 /**
819 * clean up the global setting structure
820 */
821 void ms_setting_cleanup()
822 {
823 if (ms_setting.distr != NULL) {
824 free(ms_setting.distr);
825 }
826
827 if (ms_setting.char_block != NULL) {
828 free(ms_setting.char_block);
829 }
830
831 if (ms_setting.srv_str != NULL) {
832 free(ms_setting.srv_str);
833 }
834
835 if (ms_setting.cfg_file != NULL) {
836 free(ms_setting.cfg_file);
837 }
838
839 if (ms_setting.servers != NULL) {
840 free(ms_setting.servers);
841 }
842
843 if (ms_setting.key_distr != NULL) {
844 free(ms_setting.key_distr);
845 }
846
847 if (ms_setting.value_distr != NULL) {
848 free(ms_setting.value_distr);
849 }
850 }