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