Added/restructured all additional hostname information
[m6w6/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
18 /* Global Thread counter */
19 unsigned int thread_counter;
20 pthread_mutex_t counter_mutex;
21 pthread_cond_t count_threshhold;
22 unsigned int master_wakeup;
23 pthread_mutex_t sleeper_mutex;
24 pthread_cond_t sleep_threshhold;
25
26 void *run_task(void *p);
27
28 /* Types */
29 typedef struct conclusions_st conclusions_st;
30 typedef struct thread_context_st thread_context_st;
31 typedef enum {
32 AC_SET,
33 AC_GET,
34 } run_action;
35
36 struct thread_context_st {
37 unsigned int x;
38 pairs_st *pairs;
39 run_action action;
40 };
41
42 struct conclusions_st {
43 long int load_time;
44 long int read_time;
45 unsigned int rows_loaded;
46 unsigned int rows_read;
47 };
48
49 /* Prototypes */
50 void options_parse(int argc, char *argv[]);
51 void conclusions_print(conclusions_st *conclusion);
52 void scheduler(conclusions_st *conclusion);
53
54 static int opt_verbose= 0;
55 static unsigned int opt_default_pairs= 100;
56 static unsigned int opt_concurrency= 1;
57 static int opt_displayflag= 0;
58 static char *opt_servers= NULL;
59
60 int main(int argc, char *argv[])
61 {
62 unsigned int x;
63 memcached_return rc;
64 memcached_st *memc;
65 pairs_st *pairs;
66 conclusions_st conclusion;
67
68 memset(&conclusion, 0, sizeof(conclusions_st));
69
70 srandom(time(NULL));
71 memc= memcached_init(NULL);
72 options_parse(argc, argv);
73
74 if (!opt_servers)
75 exit(0);
76
77 parse_opt_servers(memc, opt_servers);
78
79 pairs= pairs_generate(opt_default_pairs);
80
81 pthread_mutex_init(&counter_mutex, NULL);
82 pthread_cond_init(&count_threshhold, NULL);
83 pthread_mutex_init(&sleeper_mutex, NULL);
84 pthread_cond_init(&sleep_threshhold, NULL);
85
86 scheduler(&conclusion);
87
88 pairs_free(pairs);
89
90 free(opt_servers);
91
92 memcached_deinit(memc);
93
94 (void)pthread_mutex_init(&counter_mutex, NULL);
95 (void)pthread_cond_init(&count_threshhold, NULL);
96 (void)pthread_mutex_init(&sleeper_mutex, NULL);
97 (void)pthread_cond_init(&sleep_threshhold, NULL);
98 conclusions_print(&conclusion);
99
100 return 0;
101 }
102
103 void scheduler(conclusions_st *conclusion)
104 {
105 unsigned int x;
106 struct timeval start_time, end_time;
107 pthread_t mainthread; /* Thread descriptor */
108 pthread_attr_t attr; /* Thread attributes */
109
110 pthread_attr_init(&attr);
111 pthread_attr_setdetachstate(&attr,
112 PTHREAD_CREATE_DETACHED);
113
114 pthread_mutex_lock(&counter_mutex);
115 thread_counter= 0;
116
117 pthread_mutex_lock(&sleeper_mutex);
118 master_wakeup= 1;
119 pthread_mutex_unlock(&sleeper_mutex);
120
121 for (x= 0; x < opt_concurrency; x++)
122 {
123 thread_context_st *context;
124 context= (thread_context_st *)malloc(sizeof(thread_context_st));
125
126 /* now you create the thread */
127 if (pthread_create(&mainthread, &attr, run_task,
128 (void *)context) != 0)
129 {
130 fprintf(stderr,"Could not create thread\n");
131 exit(1);
132 }
133 thread_counter++;
134 }
135
136 pthread_mutex_unlock(&counter_mutex);
137 pthread_attr_destroy(&attr);
138
139 pthread_mutex_lock(&sleeper_mutex);
140 master_wakeup= 0;
141 pthread_mutex_unlock(&sleeper_mutex);
142 pthread_cond_broadcast(&sleep_threshhold);
143
144 gettimeofday(&start_time, NULL);
145 /*
146 We loop until we know that all children have cleaned up.
147 */
148 pthread_mutex_lock(&counter_mutex);
149 while (thread_counter)
150 {
151 struct timespec abstime;
152
153 memset(&abstime, 0, sizeof(struct timespec));
154 abstime.tv_sec= 1;
155
156 pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
157 }
158 pthread_mutex_unlock(&counter_mutex);
159
160 gettimeofday(&end_time, NULL);
161
162 conclusion->load_time= timedif(end_time, start_time);
163 conclusion->read_time= timedif(end_time, start_time);
164 }
165
166 void options_parse(int argc, char *argv[])
167 {
168 static struct option long_options[]=
169 {
170 {"version", no_argument, NULL, OPT_VERSION},
171 {"help", no_argument, NULL, OPT_HELP},
172 {"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
173 {"debug", no_argument, &opt_verbose, OPT_DEBUG},
174 {"servers", required_argument, NULL, OPT_SERVERS},
175 {"flag", no_argument, &opt_displayflag, OPT_FLAG},
176 {"default-pairs", required_argument, NULL, OPT_SLAP_DEFAULT_PAIRS},
177 {0, 0, 0, 0},
178 };
179
180 int option_index= 0;
181 int option_rv;
182
183 while (1)
184 {
185 option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
186 if (option_rv == -1) break;
187 switch (option_rv)
188 {
189 case 0:
190 break;
191 case OPT_VERBOSE: /* --verbose or -v */
192 opt_verbose = OPT_VERBOSE;
193 break;
194 case OPT_DEBUG: /* --debug or -d */
195 opt_verbose = OPT_DEBUG;
196 break;
197 case OPT_VERSION: /* --version or -V */
198 printf("memcache tools, memcat, v1.0\n");
199 exit(0);
200 break;
201 case OPT_HELP: /* --help or -h */
202 printf("useful help messages go here\n");
203 exit(0);
204 break;
205 case OPT_SERVERS: /* --servers or -s */
206 opt_servers= strdup(optarg);
207 break;
208 case OPT_SLAP_DEFAULT_PAIRS:
209 opt_default_pairs= strtol(optarg, (char **)NULL, 10);
210 break;
211 case '?':
212 /* getopt_long already printed an error message. */
213 exit(1);
214 default:
215 abort();
216 }
217 }
218 }
219
220 void conclusions_print(conclusions_st *conclusion)
221 {
222 printf("\tLoaded %u rows\n", conclusion->rows_loaded);
223 printf("\tRead %u rows\n", conclusion->rows_read);
224 printf("\tTook %ld.%03ld seconds to load data\n", conclusion->load_time / 1000,
225 conclusion->load_time % 1000);
226 printf("\tTook %ld.%03ld seconds to read data\n", conclusion->read_time / 1000,
227 conclusion->read_time % 1000);
228 }
229
230 void *run_task(void *p)
231 {
232 unsigned int x;
233 thread_context_st *context= (thread_context_st *)p;
234
235 pthread_mutex_lock(&sleeper_mutex);
236 while (master_wakeup)
237 {
238 pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
239 }
240 pthread_mutex_unlock(&sleeper_mutex);
241
242 /* Do Stuff */
243
244 switch (context->action)
245 {
246 case AC_SET:
247 for (x= 0; x < opt_default_pairs; x++)
248 {
249 rc= memcached_set(memc, pairs[x].key, pairs[x].key_length,
250 pairs[x].value, pairs[x].value_length,
251 0, 0);
252 if (rc != MEMCACHED_SUCCESS)
253 fprintf(stderr, "Failured on insert of %.*s\n",
254 (unsigned int)pairs[x].key_length, pairs[x].key);
255 conclusion->rows_loaded++;
256 }
257 break;
258 case AC_GET:
259 for (x= 0; x < opt_default_pairs; x++)
260 {
261 char *value;
262 size_t value_length;
263 uint16_t flags;
264
265 value= memcached_get(memc, pairs[x].key, pairs[x].key_length,
266 &value_length,
267 &flags, &rc);
268
269 if (rc != MEMCACHED_SUCCESS)
270 fprintf(stderr, "Failured on read of %.*s\n",
271 (unsigned int)pairs[x].key_length, pairs[x].key);
272 conclusion->rows_read++;
273 free(value);
274 }
275 break;
276 }
277
278 pthread_mutex_lock(&counter_mutex);
279 thread_counter--;
280 pthread_cond_signal(&count_threshhold);
281 pthread_mutex_unlock(&counter_mutex);
282
283 free(context);
284 }