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
{
39 memcached_server_st
*servers
;
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(memcached_server_st
*servers
, conclusions_st
*conclusion
);
54 static int opt_verbose
= 0;
55 static unsigned int opt_default_pairs
= 100;
56 static unsigned int opt_concurrency
= 10;
57 static int opt_displayflag
= 0;
58 static char *opt_servers
= NULL
;
60 int main(int argc
, char *argv
[])
62 conclusions_st conclusion
;
63 memcached_server_st
*servers
;
65 memset(&conclusion
, 0, sizeof(conclusions_st
));
68 options_parse(argc
, argv
);
73 servers
= parse_opt_servers(opt_servers
);
75 pthread_mutex_init(&counter_mutex
, NULL
);
76 pthread_cond_init(&count_threshhold
, NULL
);
77 pthread_mutex_init(&sleeper_mutex
, NULL
);
78 pthread_cond_init(&sleep_threshhold
, NULL
);
80 scheduler(servers
, &conclusion
);
84 (void)pthread_mutex_init(&counter_mutex
, NULL
);
85 (void)pthread_cond_init(&count_threshhold
, NULL
);
86 (void)pthread_mutex_init(&sleeper_mutex
, NULL
);
87 (void)pthread_cond_init(&sleep_threshhold
, NULL
);
88 conclusions_print(&conclusion
);
89 memcached_server_list_free(servers
);
94 void scheduler(memcached_server_st
*servers
, conclusions_st
*conclusion
)
97 struct timeval start_time
, end_time
;
98 pthread_t mainthread
; /* Thread descriptor */
99 pthread_attr_t attr
; /* Thread attributes */
102 pthread_attr_init(&attr
);
103 pthread_attr_setdetachstate(&attr
,
104 PTHREAD_CREATE_DETACHED
);
106 pairs
= pairs_generate(opt_default_pairs
);
108 pthread_mutex_lock(&counter_mutex
);
111 pthread_mutex_lock(&sleeper_mutex
);
113 pthread_mutex_unlock(&sleeper_mutex
);
115 for (x
= 0; x
< opt_concurrency
; x
++)
117 thread_context_st
*context
;
118 context
= (thread_context_st
*)malloc(sizeof(thread_context_st
));
120 context
->servers
= servers
;
121 context
->pairs
= pairs
;
122 context
->action
= AC_SET
;
124 /* now you create the thread */
125 if (pthread_create(&mainthread
, &attr
, run_task
,
126 (void *)context
) != 0)
128 fprintf(stderr
,"Could not create thread\n");
134 pthread_mutex_unlock(&counter_mutex
);
135 pthread_attr_destroy(&attr
);
137 pthread_mutex_lock(&sleeper_mutex
);
139 pthread_mutex_unlock(&sleeper_mutex
);
140 pthread_cond_broadcast(&sleep_threshhold
);
142 gettimeofday(&start_time
, NULL
);
144 We loop until we know that all children have cleaned up.
146 pthread_mutex_lock(&counter_mutex
);
147 while (thread_counter
)
149 struct timespec abstime
;
151 memset(&abstime
, 0, sizeof(struct timespec
));
154 pthread_cond_timedwait(&count_threshhold
, &counter_mutex
, &abstime
);
156 pthread_mutex_unlock(&counter_mutex
);
158 gettimeofday(&end_time
, NULL
);
160 conclusion
->load_time
= timedif(end_time
, start_time
);
161 conclusion
->read_time
= timedif(end_time
, start_time
);
165 void options_parse(int argc
, char *argv
[])
167 static struct option long_options
[]=
169 {"version", no_argument
, NULL
, OPT_VERSION
},
170 {"help", no_argument
, NULL
, OPT_HELP
},
171 {"verbose", no_argument
, &opt_verbose
, OPT_VERBOSE
},
172 {"debug", no_argument
, &opt_verbose
, OPT_DEBUG
},
173 {"servers", required_argument
, NULL
, OPT_SERVERS
},
174 {"flag", no_argument
, &opt_displayflag
, OPT_FLAG
},
175 {"default-pairs", required_argument
, NULL
, OPT_SLAP_DEFAULT_PAIRS
},
184 option_rv
= getopt_long(argc
, argv
, "Vhvds:", long_options
, &option_index
);
185 if (option_rv
== -1) break;
190 case OPT_VERBOSE
: /* --verbose or -v */
191 opt_verbose
= OPT_VERBOSE
;
193 case OPT_DEBUG
: /* --debug or -d */
194 opt_verbose
= OPT_DEBUG
;
196 case OPT_VERSION
: /* --version or -V */
197 printf("memcache tools, memcat, v1.0\n");
200 case OPT_HELP
: /* --help or -h */
201 printf("useful help messages go here\n");
204 case OPT_SERVERS
: /* --servers or -s */
205 opt_servers
= strdup(optarg
);
207 case OPT_SLAP_DEFAULT_PAIRS
:
208 opt_default_pairs
= strtol(optarg
, (char **)NULL
, 10);
211 /* getopt_long already printed an error message. */
219 void conclusions_print(conclusions_st
*conclusion
)
221 printf("\tLoaded %u rows\n", conclusion
->rows_loaded
);
222 printf("\tRead %u rows\n", conclusion
->rows_read
);
223 printf("\tTook %ld.%03ld seconds to load data\n", conclusion
->load_time
/ 1000,
224 conclusion
->load_time
% 1000);
225 printf("\tTook %ld.%03ld seconds to read data\n", conclusion
->read_time
/ 1000,
226 conclusion
->read_time
% 1000);
229 void *run_task(void *p
)
232 thread_context_st
*context
= (thread_context_st
*)p
;
235 pairs_st
*pairs
= context
->pairs
;
237 memc
= memcached_init(NULL
);
239 memcached_server_push(memc
, context
->servers
);
241 pthread_mutex_lock(&sleeper_mutex
);
242 while (master_wakeup
)
244 pthread_cond_wait(&sleep_threshhold
, &sleeper_mutex
);
246 pthread_mutex_unlock(&sleeper_mutex
);
249 switch (context
->action
)
252 for (x
= 0; x
< opt_default_pairs
; x
++)
254 rc
= memcached_set(memc
, pairs
[x
].key
, pairs
[x
].key_length
,
255 pairs
[x
].value
, pairs
[x
].value_length
,
257 if (rc
!= MEMCACHED_SUCCESS
)
258 fprintf(stderr
, "Failured on insert of %.*s\n",
259 (unsigned int)pairs
[x
].key_length
, pairs
[x
].key
);
263 for (x
= 0; x
< opt_default_pairs
; x
++)
269 value
= memcached_get(memc
, pairs
[x
].key
, pairs
[x
].key_length
,
273 if (rc
!= MEMCACHED_SUCCESS
)
274 fprintf(stderr
, "Failured on read of %.*s\n",
275 (unsigned int)pairs
[x
].key_length
, pairs
[x
].key
);
281 pthread_mutex_lock(&counter_mutex
);
283 pthread_cond_signal(&count_threshhold
);
284 pthread_mutex_unlock(&counter_mutex
);
285 memcached_deinit(memc
);