Missing hosts file.
[awesomized/libmemcached] / src / memslap.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <sys/types.h>
6 #include <sys/mman.h>
7 #include <fcntl.h>
8 #include <sys/time.h>
9 #include <getopt.h>
10 #include <pthread.h>
11
12 #include <memcached.h>
13
14 #include "client_options.h"
15 #include "utilities.h"
16 #include "generator.h"
17 #include "execute.h"
18
19 #define DEFAULT_INITIAL_LOAD 10000
20 #define DEFAULT_EXECUTE_NUMBER 10000
21 #define DEFAULT_CONCURRENCY 1
22
23 #define PROGRAM_NAME "memslap"
24 #define PROGRAM_DESCRIPTION "Generates a load against a memcached custer of servers."
25
26 /* Global Thread counter */
27 unsigned int thread_counter;
28 pthread_mutex_t counter_mutex;
29 pthread_cond_t count_threshhold;
30 unsigned int master_wakeup;
31 pthread_mutex_t sleeper_mutex;
32 pthread_cond_t sleep_threshhold;
33
34 void *run_task(void *p);
35
36 /* Types */
37 typedef struct conclusions_st conclusions_st;
38 typedef struct thread_context_st thread_context_st;
39 typedef enum {
40 SET_TEST,
41 GET_TEST,
42 } test_type;
43
44 struct thread_context_st {
45 unsigned int key_count;
46 pairs_st *initial_pairs;
47 unsigned int initial_number;
48 pairs_st *execute_pairs;
49 unsigned int execute_number;
50 test_type test;
51 memcached_server_st *servers;
52 };
53
54 struct conclusions_st {
55 long int load_time;
56 long int read_time;
57 unsigned int rows_loaded;
58 unsigned int rows_read;
59 };
60
61 /* Prototypes */
62 void options_parse(int argc, char *argv[]);
63 void conclusions_print(conclusions_st *conclusion);
64 void scheduler(memcached_server_st *servers, conclusions_st *conclusion);
65 pairs_st *load_createial_data(memcached_server_st *servers, unsigned int number_of,
66 unsigned int *actual_loaded);
67
68 static int opt_verbose= 0;
69 static unsigned int opt_execute_number= 0;
70 static unsigned int opt_createial_load= 0;
71 static unsigned int opt_concurrency= 0;
72 static int opt_displayflag= 0;
73 static char *opt_servers= NULL;
74 test_type opt_test= SET_TEST;
75
76 int main(int argc, char *argv[])
77 {
78 conclusions_st conclusion;
79 memcached_server_st *servers;
80
81 memset(&conclusion, 0, sizeof(conclusions_st));
82
83 srandom(time(NULL));
84 options_parse(argc, argv);
85
86 if (!opt_servers)
87 exit(0);
88
89 servers= parse_opt_servers(opt_servers);
90
91 pthread_mutex_init(&counter_mutex, NULL);
92 pthread_cond_init(&count_threshhold, NULL);
93 pthread_mutex_init(&sleeper_mutex, NULL);
94 pthread_cond_init(&sleep_threshhold, NULL);
95
96 scheduler(servers, &conclusion);
97
98 free(opt_servers);
99
100 (void)pthread_mutex_destroy(&counter_mutex);
101 (void)pthread_cond_destroy(&count_threshhold);
102 (void)pthread_mutex_destroy(&sleeper_mutex);
103 (void)pthread_cond_destroy(&sleep_threshhold);
104 conclusions_print(&conclusion);
105 memcached_server_list_free(servers);
106
107 return 0;
108 }
109
110 void scheduler(memcached_server_st *servers, conclusions_st *conclusion)
111 {
112 unsigned int x;
113 unsigned int actual_loaded;
114
115 struct timeval start_time, end_time;
116 pthread_t mainthread; /* Thread descriptor */
117 pthread_attr_t attr; /* Thread attributes */
118 pairs_st *pairs= NULL;
119
120 pthread_attr_init(&attr);
121 pthread_attr_setdetachstate(&attr,
122 PTHREAD_CREATE_DETACHED);
123
124 if (opt_createial_load)
125 pairs= load_createial_data(servers, opt_createial_load, &actual_loaded);
126
127 pthread_mutex_lock(&counter_mutex);
128 thread_counter= 0;
129
130 pthread_mutex_lock(&sleeper_mutex);
131 master_wakeup= 1;
132 pthread_mutex_unlock(&sleeper_mutex);
133
134 for (x= 0; x < opt_concurrency; x++)
135 {
136 thread_context_st *context;
137 context= (thread_context_st *)malloc(sizeof(thread_context_st));
138
139 context->servers= servers;
140 context->test= opt_test;
141
142 context->initial_pairs= pairs;
143 context->initial_number= actual_loaded;
144
145 if (opt_test == SET_TEST)
146 {
147 context->execute_pairs= pairs_generate(opt_execute_number);
148 context->execute_number= opt_execute_number;
149 }
150
151 /* now you create the thread */
152 if (pthread_create(&mainthread, &attr, run_task,
153 (void *)context) != 0)
154 {
155 fprintf(stderr,"Could not create thread\n");
156 exit(1);
157 }
158 thread_counter++;
159 }
160
161 pthread_mutex_unlock(&counter_mutex);
162 pthread_attr_destroy(&attr);
163
164 pthread_mutex_lock(&sleeper_mutex);
165 master_wakeup= 0;
166 pthread_mutex_unlock(&sleeper_mutex);
167 pthread_cond_broadcast(&sleep_threshhold);
168
169 gettimeofday(&start_time, NULL);
170 /*
171 We loop until we know that all children have cleaned up.
172 */
173 pthread_mutex_lock(&counter_mutex);
174 while (thread_counter)
175 {
176 struct timespec abstime;
177
178 memset(&abstime, 0, sizeof(struct timespec));
179 abstime.tv_sec= 1;
180
181 pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
182 }
183 pthread_mutex_unlock(&counter_mutex);
184
185 gettimeofday(&end_time, NULL);
186
187 conclusion->load_time= timedif(end_time, start_time);
188 conclusion->read_time= timedif(end_time, start_time);
189 pairs_free(pairs);
190 }
191
192 void options_parse(int argc, char *argv[])
193 {
194 memcached_programs_help_st help_options[]=
195 {
196 {0},
197 };
198
199 static struct option long_options[]=
200 {
201 {"concurrency", required_argument, NULL, OPT_SLAP_CONCURRENCY},
202 {"debug", no_argument, &opt_verbose, OPT_DEBUG},
203 {"execute-number", required_argument, NULL, OPT_SLAP_EXECUTE_NUMBER},
204 {"flag", no_argument, &opt_displayflag, OPT_FLAG},
205 {"help", no_argument, NULL, OPT_HELP},
206 {"initial-load", required_argument, NULL, OPT_SLAP_INITIAL_LOAD}, /* Number to load initially */
207 {"servers", required_argument, NULL, OPT_SERVERS},
208 {"test", required_argument, NULL, OPT_SLAP_TEST},
209 {"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
210 {"version", no_argument, NULL, OPT_VERSION},
211 {0, 0, 0, 0},
212 };
213
214 int option_index= 0;
215 int option_rv;
216
217 while (1)
218 {
219 option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
220 if (option_rv == -1) break;
221 switch (option_rv)
222 {
223 case 0:
224 break;
225 case OPT_VERBOSE: /* --verbose or -v */
226 opt_verbose = OPT_VERBOSE;
227 break;
228 case OPT_DEBUG: /* --debug or -d */
229 opt_verbose = OPT_DEBUG;
230 break;
231 case OPT_VERSION: /* --version or -V */
232 version_command(PROGRAM_NAME);
233 break;
234 case OPT_HELP: /* --help or -h */
235 help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
236 break;
237 case OPT_SERVERS: /* --servers or -s */
238 opt_servers= strdup(optarg);
239 break;
240 case OPT_SLAP_TEST:
241 if (!strcmp(optarg, "get"))
242 opt_test= GET_TEST ;
243 else if (!strcmp(optarg, "set"))
244 opt_test= SET_TEST;
245 else
246 {
247 fprintf(stderr, "Your test, %s, is not a known test\n", optarg);
248 exit(1);
249 }
250 break;
251 case OPT_SLAP_CONCURRENCY:
252 opt_concurrency= strtol(optarg, (char **)NULL, 10);
253 case OPT_SLAP_EXECUTE_NUMBER:
254 opt_execute_number= strtol(optarg, (char **)NULL, 10);
255 break;
256 case OPT_SLAP_INITIAL_LOAD:
257 opt_createial_load= strtol(optarg, (char **)NULL, 10);
258 break;
259 case '?':
260 /* getopt_long already printed an error message. */
261 exit(1);
262 default:
263 abort();
264 }
265 }
266
267 if (opt_test == GET_TEST && opt_createial_load == 0)
268 opt_createial_load= DEFAULT_INITIAL_LOAD;
269
270 if (opt_execute_number == 0)
271 opt_execute_number= DEFAULT_EXECUTE_NUMBER;
272
273 if (opt_concurrency == 0)
274 opt_concurrency= DEFAULT_CONCURRENCY;
275 }
276
277 void conclusions_print(conclusions_st *conclusion)
278 {
279 printf("\tThreads connecting to servers %u\n", opt_concurrency);
280 #ifdef NOT_FINISHED
281 printf("\tLoaded %u rows\n", conclusion->rows_loaded);
282 printf("\tRead %u rows\n", conclusion->rows_read);
283 #endif
284 if (opt_test == SET_TEST)
285 printf("\tTook %ld.%03ld seconds to load data\n", conclusion->load_time / 1000,
286 conclusion->load_time % 1000);
287 else
288 printf("\tTook %ld.%03ld seconds to read data\n", conclusion->read_time / 1000,
289 conclusion->read_time % 1000);
290 }
291
292 void *run_task(void *p)
293 {
294 thread_context_st *context= (thread_context_st *)p;
295 memcached_st *memc;
296
297 memc= memcached_create(NULL);
298
299 memcached_server_push(memc, context->servers);
300
301 pthread_mutex_lock(&sleeper_mutex);
302 while (master_wakeup)
303 {
304 pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
305 }
306 pthread_mutex_unlock(&sleeper_mutex);
307
308 /* Do Stuff */
309 switch (context->test)
310 {
311 case SET_TEST:
312 execute_set(memc, context->execute_pairs, context->execute_number);
313 break;
314 case GET_TEST:
315 execute_get(memc, context->initial_pairs, context->initial_number);
316 break;
317 }
318
319 pthread_mutex_lock(&counter_mutex);
320 thread_counter--;
321 pthread_cond_signal(&count_threshhold);
322 pthread_mutex_unlock(&counter_mutex);
323 memcached_free(memc);
324
325 if (context->execute_pairs)
326 pairs_free(context->execute_pairs);
327 free(context);
328
329 return NULL;
330 }
331
332 pairs_st *load_createial_data(memcached_server_st *servers, unsigned int number_of,
333 unsigned int *actual_loaded)
334 {
335 memcached_st *memc;
336 pairs_st *pairs;
337
338 memc= memcached_create(NULL);
339 memcached_server_push(memc, servers);
340
341 pairs= pairs_generate(number_of);
342 *actual_loaded= execute_set(memc, pairs, number_of);
343
344 memcached_free(memc);
345
346 return pairs;
347 }