/*
 * mysql-con-stress.cc  by Sasha Pachev
 * Stresses a running mysqld to see the maximum number of additional concurrent 
 * connections it can handle
 * to compile: g++ -o mysql-con-stress -I<where_mysql.h_is_found>  -L<where-libmysqlclient-is-found> mysql-con-stress.cc -lmysqlclient
 * to use:  mysql-con-stress host user pass max_tries
 * If the first three parameters are not obvious, you should not be using this program 
 * max_tries is the maximum number of concurrent connection mysql-con-stress will try to
 * estabilsh
 */
#include <mysql.h>
#include <iostream.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>

int num_cons = 0;
MYSQL* glob_cons = NULL;

void clean_up(int )
 {
   int i;
   cerr << "Cleaning up " << num_cons << " connections ..." << endl;


   for(i = 0; i < num_cons; i++)
     {
       mysql_close(glob_cons + i);
     }
 
   cerr << "Clean up complete" << endl;
   exit(0);
 }

void usage()
  {
    cerr << "Usage: mysql-con-stress host user pass max_tries" << endl;
    exit(1);
  }

int main(int argc, char** argv)
 {
   if(argc != 5) usage();
   char* user, *host, *pass;
   int max_tries;

   user = argv[2];
   host = argv[1];
   pass = argv[3];
   max_tries = atoi(argv[4]);

   MYSQL cons[max_tries];
   glob_cons = cons;

   int i;
   int  never_failed = 1;
   int port = 0;

    // if we get a signal, clean up first

    signal(SIGTERM, clean_up);
    signal(SIGINT,  clean_up);

   // establish as many connections as we can

   for(i = 0; i < max_tries; i++)
     {
       mysql_connect(cons + i, host, user, pass);
       num_cons = i ;
       
       if((mysql_error(cons + i))[0])
         {
           never_failed = 0;
           cout << "Successefully established " << num_cons << " connections" << endl;
           cout << "Failed because " << mysql_error(cons + i) << endl;
           break;
         }
     }
   

   if(never_failed)
     {
        num_cons = i ;
        cout << "Successefully established " << num_cons << " connections" << endl;
        cout << "Never failed " << endl;
     }

  // this is really not necessary, because exiting will close all the connection,
  // but it is good practice to clean up

   clean_up(0);

   return 0;
 }