12 #include <memcached.h>
14 #include "client_options.h"
15 #include "utilities.h"
16 #include "generator.h"
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
;
26 void *run_task(void *p
);
29 typedef struct conclusions_st conclusions_st
;
30 typedef struct thread_context_st thread_context_st
;
36 struct thread_context_st
{
42 struct conclusions_st
{
45 unsigned int rows_loaded
;
46 unsigned int rows_read
;
50 void options_parse(int argc
, char *argv
[]);
51 void conclusions_print(conclusions_st
*conclusion
);
52 void scheduler(conclusions_st
*conclusion
);
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
;
60 int main(int argc
, char *argv
[])
66 conclusions_st conclusion
;
68 memset(&conclusion
, 0, sizeof(conclusions_st
));
71 memc
= memcached_init(NULL
);
72 options_parse(argc
, argv
);
77 parse_opt_servers(memc
, opt_servers
);
79 pairs
= pairs_generate(opt_default_pairs
);
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
);
86 scheduler(&conclusion
);
92 memcached_deinit(memc
);
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
);
103 void scheduler(conclusions_st
*conclusion
)
106 struct timeval start_time
, end_time
;
107 pthread_t mainthread
; /* Thread descriptor */
108 pthread_attr_t attr
; /* Thread attributes */
110 pthread_attr_init(&attr
);
111 pthread_attr_setdetachstate(&attr
,
112 PTHREAD_CREATE_DETACHED
);
114 pthread_mutex_lock(&counter_mutex
);
117 pthread_mutex_lock(&sleeper_mutex
);
119 pthread_mutex_unlock(&sleeper_mutex
);
121 for (x
= 0; x
< opt_concurrency
; x
++)
123 thread_context_st
*context
;
124 context
= (thread_context_st
*)malloc(sizeof(thread_context_st
));
126 /* now you create the thread */
127 if (pthread_create(&mainthread
, &attr
, run_task
,
128 (void *)context
) != 0)
130 fprintf(stderr
,"Could not create thread\n");
136 pthread_mutex_unlock(&counter_mutex
);
137 pthread_attr_destroy(&attr
);
139 pthread_mutex_lock(&sleeper_mutex
);
141 pthread_mutex_unlock(&sleeper_mutex
);
142 pthread_cond_broadcast(&sleep_threshhold
);
144 gettimeofday(&start_time
, NULL
);
146 We loop until we know that all children have cleaned up.
148 pthread_mutex_lock(&counter_mutex
);
149 while (thread_counter
)
151 struct timespec abstime
;
153 memset(&abstime
, 0, sizeof(struct timespec
));
156 pthread_cond_timedwait(&count_threshhold
, &counter_mutex
, &abstime
);
158 pthread_mutex_unlock(&counter_mutex
);
160 gettimeofday(&end_time
, NULL
);
162 conclusion
->load_time
= timedif(end_time
, start_time
);
163 conclusion
->read_time
= timedif(end_time
, start_time
);
166 void options_parse(int argc
, char *argv
[])
168 static struct option long_options
[]=
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
},
185 option_rv
= getopt_long(argc
, argv
, "Vhvds:", long_options
, &option_index
);
186 if (option_rv
== -1) break;
191 case OPT_VERBOSE
: /* --verbose or -v */
192 opt_verbose
= OPT_VERBOSE
;
194 case OPT_DEBUG
: /* --debug or -d */
195 opt_verbose
= OPT_DEBUG
;
197 case OPT_VERSION
: /* --version or -V */
198 printf("memcache tools, memcat, v1.0\n");
201 case OPT_HELP
: /* --help or -h */
202 printf("useful help messages go here\n");
205 case OPT_SERVERS
: /* --servers or -s */
206 opt_servers
= strdup(optarg
);
208 case OPT_SLAP_DEFAULT_PAIRS
:
209 opt_default_pairs
= strtol(optarg
, (char **)NULL
, 10);
212 /* getopt_long already printed an error message. */
220 void conclusions_print(conclusions_st
*conclusion
)
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);
230 void *run_task(void *p
)
233 thread_context_st
*context
= (thread_context_st
*)p
;
235 pthread_mutex_lock(&sleeper_mutex
);
236 while (master_wakeup
)
238 pthread_cond_wait(&sleep_threshhold
, &sleeper_mutex
);
240 pthread_mutex_unlock(&sleeper_mutex
);
244 switch (context
->action
)
247 for (x
= 0; x
< opt_default_pairs
; x
++)
249 rc
= memcached_set(memc
, pairs
[x
].key
, pairs
[x
].key_length
,
250 pairs
[x
].value
, pairs
[x
].value_length
,
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
++;
259 for (x
= 0; x
< opt_default_pairs
; x
++)
265 value
= memcached_get(memc
, pairs
[x
].key
, pairs
[x
].key_length
,
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
++;
278 pthread_mutex_lock(&counter_mutex
);
280 pthread_cond_signal(&count_threshhold
);
281 pthread_mutex_unlock(&counter_mutex
);