1
by brian
clean slate |
1 |
/* Copyright (C) 2000 MySQL AB
|
2 |
||
3 |
This program is free software; you can redistribute it and/or modify
|
|
4 |
it under the terms of the GNU General Public License as published by
|
|
5 |
the Free Software Foundation; version 2 of the License.
|
|
6 |
||
7 |
This program is distributed in the hope that it will be useful,
|
|
8 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10 |
GNU General Public License for more details.
|
|
11 |
||
12 |
You should have received a copy of the GNU General Public License
|
|
13 |
along with this program; if not, write to the Free Software
|
|
14 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
15 |
||
16 |
#include <my_global.h> |
|
17 |
||
18 |
#ifndef THREAD
|
|
19 |
||
20 |
int main(int argc __attribute__((unused)), char **argv __attribute__((unused))) |
|
21 |
{
|
|
22 |
printf("This test must be compiled with multithread support to work\n"); |
|
23 |
exit(1); |
|
24 |
}
|
|
25 |
#else
|
|
26 |
||
27 |
#include <my_sys.h> |
|
28 |
#include <my_pthread.h> |
|
29 |
#include "mysql.h" |
|
30 |
#include <my_getopt.h> |
|
31 |
||
32 |
static my_bool version, verbose, tty_password= 0; |
|
33 |
static uint thread_count,number_of_tests=1000,number_of_threads=2; |
|
34 |
static pthread_cond_t COND_thread_count; |
|
35 |
static pthread_mutex_t LOCK_thread_count; |
|
36 |
||
37 |
static char *database,*host,*user,*password,*unix_socket,*query; |
|
38 |
uint tcp_port; |
|
39 |
||
40 |
#ifndef __WIN__
|
|
41 |
void *test_thread(void *arg __attribute__((unused))) |
|
42 |
#else
|
|
43 |
unsigned __stdcall test_thread(void *arg __attribute__((unused))) |
|
44 |
#endif
|
|
45 |
{
|
|
46 |
MYSQL *mysql; |
|
47 |
uint count; |
|
48 |
||
49 |
mysql=mysql_init(NULL); |
|
50 |
if (!mysql_real_connect(mysql,host,user,password,database,tcp_port, |
|
51 |
unix_socket,0)) |
|
52 |
{
|
|
53 |
fprintf(stderr,"Couldn't connect to engine!\n%s\n\n",mysql_error(mysql)); |
|
54 |
perror(""); |
|
55 |
goto end; |
|
56 |
}
|
|
57 |
mysql.reconnect= 1; |
|
58 |
if (verbose) { putchar('*'); fflush(stdout); } |
|
59 |
for (count=0 ; count < number_of_tests ; count++) |
|
60 |
{
|
|
61 |
MYSQL_RES *res; |
|
62 |
if (mysql_query(mysql,query)) |
|
63 |
{
|
|
64 |
fprintf(stderr,"Query failed (%s)\n",mysql_error(mysql)); |
|
65 |
goto end; |
|
66 |
}
|
|
67 |
if (!(res=mysql_store_result(mysql))) |
|
68 |
{
|
|
69 |
fprintf(stderr,"Couldn't get result from %s\n", mysql_error(mysql)); |
|
70 |
goto end; |
|
71 |
}
|
|
72 |
mysql_free_result(res); |
|
73 |
if (verbose) { putchar('.'); fflush(stdout); } |
|
74 |
}
|
|
75 |
end: |
|
76 |
if (verbose) { putchar('#'); fflush(stdout); } |
|
77 |
mysql_close(mysql); |
|
78 |
pthread_mutex_lock(&LOCK_thread_count); |
|
79 |
thread_count--; |
|
80 |
VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */ |
|
81 |
pthread_mutex_unlock(&LOCK_thread_count); |
|
82 |
pthread_exit(0); |
|
83 |
return 0; |
|
84 |
}
|
|
85 |
||
86 |
||
87 |
static struct my_option my_long_options[] = |
|
88 |
{
|
|
89 |
{"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, |
|
90 |
0, 0, 0, 0, 0}, |
|
91 |
{"database", 'D', "Database to use", (uchar**) &database, (uchar**) &database, |
|
92 |
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, |
|
93 |
{"host", 'h', "Connect to host", (uchar**) &host, (uchar**) &host, 0, GET_STR, |
|
94 |
REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, |
|
95 |
{"password", 'p', |
|
96 |
"Password to use when connecting to server. If password is not given it's asked from the tty.", |
|
97 |
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, |
|
98 |
{"user", 'u', "User for login if not current user", (uchar**) &user, |
|
99 |
(uchar**) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, |
|
100 |
{"version", 'V', "Output version information and exit", |
|
101 |
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, |
|
102 |
{"verbose", 'v', "Write some progress indicators", (uchar**) &verbose, |
|
103 |
(uchar**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, |
|
104 |
{"query", 'Q', "Query to execute in each threads", (uchar**) &query, |
|
105 |
(uchar**) &query, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, |
|
106 |
{"port", 'P', "Port number to use for connection or 0 for default to, in " |
|
107 |
"order of preference, my.cnf, $MYSQL_TCP_PORT, "
|
|
108 |
#if MYSQL_PORT_DEFAULT == 0
|
|
109 |
"/etc/services, "
|
|
110 |
#endif
|
|
111 |
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", |
|
112 |
(uchar**) &tcp_port, |
|
113 |
(uchar**) &tcp_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, |
|
114 |
{"socket", 'S', "Socket file to use for connection", (uchar**) &unix_socket, |
|
115 |
(uchar**) &unix_socket, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, |
|
116 |
{"test-count", 'c', "Run test count times (default %d)", |
|
117 |
(uchar**) &number_of_tests, (uchar**) &number_of_tests, 0, GET_UINT, |
|
118 |
REQUIRED_ARG, 1000, 0, 0, 0, 0, 0}, |
|
119 |
{"thread-count", 't', "Number of threads to start", |
|
120 |
(uchar**) &number_of_threads, (uchar**) &number_of_threads, 0, GET_UINT, |
|
121 |
REQUIRED_ARG, 2, 0, 0, 0, 0, 0}, |
|
122 |
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} |
|
123 |
};
|
|
124 |
||
125 |
||
126 |
static const char *load_default_groups[]= { "client",0 }; |
|
127 |
||
128 |
static void usage() |
|
129 |
{
|
|
130 |
printf("Connection to a mysql server with multiple threads\n"); |
|
131 |
if (version) |
|
132 |
return; |
|
133 |
puts("This software comes with ABSOLUTELY NO WARRANTY.\n"); |
|
134 |
printf("Usage: %s [OPTIONS] [database]\n", my_progname); |
|
135 |
||
136 |
my_print_help(my_long_options); |
|
137 |
print_defaults("my",load_default_groups); |
|
138 |
my_print_variables(my_long_options); |
|
139 |
printf("\nExample usage:\n\n\ |
|
140 |
%s -Q 'select * from mysql.user' -c %d -t %d\n", |
|
141 |
my_progname, number_of_tests, number_of_threads); |
|
142 |
}
|
|
143 |
||
144 |
||
145 |
static my_bool |
|
146 |
get_one_option(int optid, const struct my_option *opt __attribute__((unused)), |
|
147 |
char *argument) |
|
148 |
{
|
|
149 |
switch (optid) { |
|
150 |
case 'p': |
|
151 |
if (argument) |
|
152 |
{
|
|
153 |
my_free(password, MYF(MY_ALLOW_ZERO_PTR)); |
|
154 |
password= my_strdup(argument, MYF(MY_FAE)); |
|
155 |
while (*argument) *argument++= 'x'; /* Destroy argument */ |
|
156 |
}
|
|
157 |
else
|
|
158 |
tty_password= 1; |
|
159 |
break; |
|
160 |
case 'V': |
|
161 |
version= 1; |
|
162 |
usage(); |
|
163 |
exit(0); |
|
164 |
break; |
|
165 |
case '?': |
|
166 |
case 'I': /* Info */ |
|
167 |
usage(); |
|
168 |
exit(1); |
|
169 |
break; |
|
170 |
}
|
|
171 |
return 0; |
|
172 |
}
|
|
173 |
||
174 |
||
175 |
static void get_options(int argc, char **argv) |
|
176 |
{
|
|
177 |
int ho_error; |
|
178 |
||
179 |
load_defaults("my",load_default_groups,&argc,&argv); |
|
180 |
||
181 |
if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) |
|
182 |
exit(ho_error); |
|
183 |
||
184 |
free_defaults(argv); |
|
185 |
if (tty_password) |
|
186 |
password=get_tty_password(NullS); |
|
187 |
return; |
|
188 |
}
|
|
189 |
||
190 |
||
191 |
int main(int argc, char **argv) |
|
192 |
{
|
|
193 |
pthread_t tid; |
|
194 |
pthread_attr_t thr_attr; |
|
195 |
uint i; |
|
196 |
int error; |
|
197 |
MY_INIT(argv[0]); |
|
198 |
get_options(argc,argv); |
|
199 |
||
200 |
if ((error=pthread_cond_init(&COND_thread_count,NULL))) |
|
201 |
{
|
|
202 |
fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)", |
|
203 |
error,errno); |
|
204 |
exit(1); |
|
205 |
}
|
|
206 |
pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST); |
|
207 |
||
208 |
if ((error=pthread_attr_init(&thr_attr))) |
|
209 |
{
|
|
210 |
fprintf(stderr,"Got error: %d from pthread_attr_init (errno: %d)", |
|
211 |
error,errno); |
|
212 |
exit(1); |
|
213 |
}
|
|
214 |
if ((error=pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED))) |
|
215 |
{
|
|
216 |
fprintf(stderr, |
|
217 |
"Got error: %d from pthread_attr_setdetachstate (errno: %d)", |
|
218 |
error,errno); |
|
219 |
exit(1); |
|
220 |
}
|
|
221 |
||
222 |
printf("Init ok. Creating %d threads\n",number_of_threads); |
|
223 |
for (i=1 ; i <= number_of_threads ; i++) |
|
224 |
{
|
|
225 |
int *param= &i; |
|
226 |
||
227 |
if (verbose) { putchar('+'); fflush(stdout); } |
|
228 |
pthread_mutex_lock(&LOCK_thread_count); |
|
229 |
if ((error=pthread_create(&tid,&thr_attr,test_thread,(void*) param))) |
|
230 |
{
|
|
231 |
fprintf(stderr,"\nGot error: %d from pthread_create (errno: %d) when creating thread: %i\n", |
|
232 |
error,errno,i); |
|
233 |
pthread_mutex_unlock(&LOCK_thread_count); |
|
234 |
exit(1); |
|
235 |
}
|
|
236 |
thread_count++; |
|
237 |
pthread_mutex_unlock(&LOCK_thread_count); |
|
238 |
}
|
|
239 |
||
240 |
printf("Waiting for threads to finnish\n"); |
|
241 |
error=pthread_mutex_lock(&LOCK_thread_count); |
|
242 |
while (thread_count) |
|
243 |
{
|
|
244 |
if ((error=pthread_cond_wait(&COND_thread_count,&LOCK_thread_count))) |
|
245 |
fprintf(stderr,"\nGot error: %d from pthread_cond_wait\n",error); |
|
246 |
}
|
|
247 |
pthread_mutex_unlock(&LOCK_thread_count); |
|
248 |
pthread_attr_destroy(&thr_attr); |
|
249 |
printf("\nend\n"); |
|
250 |
||
251 |
my_end(0); |
|
252 |
return 0; |
|
253 |
||
254 |
exit(0); |
|
255 |
return 0; /* Keep some compilers happy */ |
|
256 |
}
|
|
257 |
||
258 |
#endif /* THREAD */ |