home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / tests / thr_insert_test.c
C/C++ Source or Header  |  2000-09-17  |  13KB  |  536 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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; either version 2 of the License, or
  6.    (at your option) any later version.
  7.  
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.  
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16.  
  17. #include <my_global.h>
  18. #include <my_sys.h>
  19. #include <m_string.h>
  20. #include <m_ctype.h>
  21. #include "mysql.h"
  22. #include "errmsg.h"
  23. #include <errno.h>
  24. #include <getopt.h>
  25.  
  26.  
  27. static pthread_cond_t COND_thread_count;
  28. static pthread_mutex_t LOCK_thread_count;
  29. static uint thread_count,number_of_threads;
  30. static my_bool opt_verbose;
  31.  
  32. static char *opt_db="test", *opt_user="test", *opt_password=NullS;
  33. static char *lock_priority="";
  34. static char *opt_host=0, *opt_mysql_unix_port=0;
  35. static uint opt_mysql_port;
  36. static uint number_of_insert_threads=10, insert_loop_count=10000;
  37. static uint time_for_check=0;
  38.  
  39. char *table_name="bench1";
  40.  
  41. char *table_def="\
  42. CREATE TABLE bench1 (\n\
  43.   URL varchar(200) DEFAULT '' NOT NULL,\n\
  44.   ID int(11) DEFAULT '-1' NOT NULL,\n\
  45.   DIGEST varchar(32) DEFAULT '' NOT NULL,\n\
  46.   TITLE blob,\n\
  47.   EXPIRY timestamp(14),\n\
  48.   MODIFIED_DATE datetime,\n\
  49.   FIRST_ACC_DATE date,\n\
  50.   LAST_ACC_DATE date DEFAULT '0000-00-00' NOT NULL,\n\
  51.   TIMES_INDEXED int(11) DEFAULT '0' NOT NULL,\n\
  52.   ABSTRACT blob,\n\
  53.   FILE_SIZE int(11),\n\
  54.   DELETED char(1) DEFAULT '' NOT NULL,\n\
  55.   TIMES_ACCESSED int(11) DEFAULT '0' NOT NULL,\n\
  56.   LAST_RESPONSE_CODE int(11),\n\
  57.   PRIMARY KEY (URL),\n\
  58.   KEY INDEXEDPAGES_DIGEST (DIGEST,DELETED),\n\
  59.   KEY INDEXEDPAGES_ID (ID,DELETED),\n\
  60.   KEY INDEXEDPAGES_EXPIRY (EXPIRY)\n\
  61. )";
  62.  
  63. pthread_handler_decl(test_insert,arg);
  64. pthread_handler_decl(test_update,arg);
  65.  
  66. static void get_options(register int *argc,register char ***argv);
  67. static int init_test_tables();
  68. static int check_table(char *table_name, my_bool verbose);
  69.  
  70.  
  71. int main(int argc ,char **argv)
  72. {
  73.   pthread_t tid;
  74.   pthread_attr_t thr_attr;
  75.   uint i;
  76.   int *param, error;
  77.   MY_INIT(argv[0]);
  78.   get_options(&argc,&argv);
  79.  
  80.   number_of_threads=number_of_insert_threads+1;
  81.  
  82.   if ((error=pthread_cond_init(&COND_thread_count,NULL)))
  83.   {
  84.     fprintf(stderr,"Got error: %d from pthread_cond_init (errno: %d)",
  85.         error,errno);
  86.     exit(1);
  87.   }
  88.  
  89.   pthread_mutex_init(&LOCK_thread_count,NULL);
  90.   if ((error=pthread_attr_init(&thr_attr)))
  91.   {
  92.     fprintf(stderr,"Got error: %d from pthread_attr_init (errno: %d)",
  93.         error,errno);
  94.     exit(1);
  95.   }
  96.  
  97.   if ((error=pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED)))
  98.   {
  99.     fprintf(stderr,
  100.         "Got error: %d from pthread_attr_setdetachstate (errno: %d)",
  101.         error,errno);
  102.     exit(1);
  103.   }
  104. #ifndef pthread_attr_setstacksize        /* void return value */
  105.   if ((error=pthread_attr_setstacksize(&thr_attr,65536L)))
  106.   {
  107.     fprintf(stderr,"Got error: %d from pthread_attr_setstacksize (errno: %d)",
  108.         error,errno);
  109.     exit(1);
  110.   }
  111. #endif
  112. #ifdef HAVE_THR_SETCONCURRENCY
  113.   VOID(thr_setconcurrency(2));
  114. #endif
  115.  
  116.   if (opt_verbose)
  117.   {
  118.     printf("Creating test table %s.%s\n",opt_db,table_name);
  119.     fflush(stdout);
  120.   }
  121.   if (init_test_tables())
  122.     exit(1);
  123.  
  124.   param= (int*) my_malloc(sizeof(int) * number_of_threads,MYF(0));
  125.   for (i=0 ; i < number_of_insert_threads ; i++)
  126.   {
  127.     pthread_mutex_lock(&LOCK_thread_count);
  128.     param[i]=i+1;
  129.     if ((error=pthread_create(&tid,&thr_attr,test_insert,(void*) (param+i))))
  130.     {
  131.       fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n",
  132.           error,errno);
  133.       pthread_mutex_unlock(&LOCK_thread_count);
  134.       exit(1);
  135.     }
  136.     thread_count++;
  137.     pthread_mutex_unlock(&LOCK_thread_count);
  138.   }
  139.  
  140.   pthread_mutex_lock(&LOCK_thread_count);
  141.   param[i]=1;
  142.   if ((error=pthread_create(&tid,&thr_attr,test_update,(void*) (param+i))))
  143.   {
  144.     fprintf(stderr,"Got error: %d from pthread_create (errno: %d)\n",
  145.         error,errno);
  146.     pthread_mutex_unlock(&LOCK_thread_count);
  147.     exit(1);
  148.   }
  149.   thread_count++; i++;
  150.   pthread_mutex_unlock(&LOCK_thread_count);
  151.  
  152.  
  153.   /* Now wait until all threads have finnished */
  154.   pthread_attr_destroy(&thr_attr);
  155.   pthread_mutex_lock(&LOCK_thread_count);
  156.   while (thread_count)
  157.   {
  158.     if ((error=pthread_cond_wait(&COND_thread_count,&LOCK_thread_count)))
  159.       fprintf(stderr,"Got error: %d from pthread_cond_wait\n",error);
  160.   }
  161.   pthread_mutex_unlock(&LOCK_thread_count);
  162.  
  163.   error=check_table(table_name,opt_verbose);
  164.   for (i=0 ; i < number_of_threads ; i++)
  165.   {
  166.     if (param[i])
  167.     {
  168.       fprintf(stderr, "Thread %d returned error %d\n",i+1,param[i]);
  169.       error=1;
  170.     }
  171.   }
  172.   my_free((char*) param,MYF(0));
  173.   if (!error)
  174.     printf("ok\n");
  175.   return error;
  176. }
  177.  
  178.  
  179. static struct option long_options[] =
  180. {
  181.   {"database",       required_argument,    0, 'D'},
  182.   {"debug",       required_argument,    0, '#'},
  183.   {"host",       required_argument,    0, 'h'},
  184. #ifdef __WIN__
  185.   {"pipe",        no_argument,    0, 'W'},
  186. #endif
  187.   {"port",        required_argument,    0, 'P'},
  188.   {"socket",        required_argument,    0, 'S'},
  189.   {"user",        required_argument,    0, 'u'},
  190.   {"verbose",        no_argument,    0, 'v'},
  191.   {"version",        no_argument,    0, 'V'},
  192.  
  193.   {"insert-threads", required_argument, 0, 'i'},
  194.   {"count",        required_argument,    0, 'c'},
  195.   {"low-priority",  no_argument,    0, 'l'},
  196.   {"check-time",    no_argument,    0, 'C'},
  197.   {0, 0, 0, 0}
  198. };
  199.  
  200.  
  201. static void print_version(void)
  202. {
  203.   printf("%s  Ver 1.0 for %s at %s\n",my_progname,SYSTEM_TYPE,
  204.      MACHINE_TYPE);
  205. }
  206.  
  207. static void usage(void)
  208. {
  209.   print_version();
  210.   puts("By Monty, for your professional use");
  211.   puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n");
  212.   puts("Testing of inserting into a table from many threads");
  213. }
  214.  
  215.  
  216. static void get_options(register int *argc,register char ***argv)
  217. {
  218.   int c,option_index=0;
  219.  
  220.   while ((c=getopt_long(*argc,*argv,"D:#:h:WP:S:u:i:Vc:vlC:",
  221.             long_options, &option_index)) != EOF)
  222.   {
  223.     switch(c) {
  224.     case 'D':
  225.       opt_db=optarg;
  226.       break;
  227.     case '#':
  228.       DBUG_PUSH(optarg ? optarg : "d:t:o");
  229.       break;
  230.     case 'h':
  231.       opt_host=optarg;
  232.       break;
  233.     case 'l':
  234.       lock_priority="LOW_PRIORITY";
  235.       break;
  236.     case 'W':
  237. #ifdef __WIN__
  238.       opt_mysql_unix_port=MYSQL_NAMEDPIPE;
  239. #endif
  240.       break;
  241.     case 'P':
  242.       opt_mysql_port= (unsigned int) atoi(optarg);
  243.       break;
  244.     case 'S':
  245.       opt_mysql_unix_port= optarg;
  246.       break;
  247.     case 'u':
  248.       opt_user=optarg;
  249.       break;
  250.     case 'p':
  251.       opt_password=my_strdup(optarg,MYF(0));
  252.       while (*optarg) *optarg++= 'x';     /* Destroy argument */
  253.       break;
  254.     case 'v':
  255.       opt_verbose=1;
  256.       break;
  257.     case 'd':
  258.     case 'V':
  259.       print_version();
  260.       exit(0);
  261.     case '?':
  262.       usage();
  263.       exit(0);
  264.  
  265.     case 'i':
  266.       number_of_insert_threads=atoi(optarg);
  267.       break;
  268.     case 'c':
  269.       insert_loop_count=atoi(optarg);
  270.       break;
  271.     case 'C':
  272.       time_for_check=atoi(optarg);
  273.       break;
  274.     }
  275.   }
  276.   (*argc)-=optind;
  277.   (*argv)+=optind;
  278.   if (*argc != 0)
  279.   {
  280.     fprintf(stderr,"Too many arguments (%d)\n",*argc);
  281.     usage();
  282.     exit(-1);
  283.   }
  284.   number_of_threads=number_of_insert_threads+2;
  285.   return;
  286. }
  287.  
  288. static MYSQL *test_connect()
  289. {
  290.   MYSQL *mysql;
  291.  
  292.   if (!(mysql=mysql_init((MYSQL*) 0)))
  293.     return 0;
  294.   if (!(mysql_real_connect(mysql,opt_host,opt_user,
  295.                opt_password, opt_db, opt_mysql_port,
  296.                opt_mysql_unix_port, 0)))
  297.   {
  298.     fprintf(stderr,"Couldn't connect to engine!\n%s\n\n",mysql_error(mysql));
  299.     my_free((char*) mysql,MYF(0));
  300.     return (0);
  301.   }
  302.   return mysql;
  303. }
  304.  
  305. static my_bool safe_stmt(MYSQL *mysql, char *query)
  306. {
  307.   if (mysql_query(mysql,query))
  308.   {
  309.     fprintf(stderr, "Got error '%s' (%d) when executing %-.160s\n",
  310.         mysql_error(mysql),mysql_errno(mysql),query);
  311.     fflush(stderr);
  312.     return 1;
  313.   }
  314.   return 0;
  315. }
  316.  
  317. static int init_test_tables()
  318. {
  319.   char buff[120];
  320.   MYSQL *mysql;
  321.   int error;
  322.  
  323.   if (!(mysql=test_connect()))
  324.     return 1;
  325.   sprintf(buff,"drop table if exists %s",table_name);
  326.   error=(safe_stmt(mysql,buff) ||
  327.      safe_stmt(mysql,table_def));
  328.   mysql_close(mysql);
  329.   return error;
  330. }
  331.  
  332.  
  333. static int check_table(char *table_name, my_bool verbose)
  334. {
  335.   char buff[120];
  336.   MYSQL *mysql;
  337.   int error;
  338.   DBUG_ENTER("check_table");
  339.  
  340.   if (!(mysql=test_connect()))
  341.     return 1;
  342.   sprintf(buff,"check table %s",table_name);
  343.   if (!(error=(safe_stmt(mysql,buff))))
  344.   {
  345.     MYSQL_RES *res;
  346.     MYSQL_ROW row;
  347.     error=1;
  348.     if (!(res=mysql_store_result(mysql)))
  349.     {
  350.       fprintf(stderr,
  351.           "Got error %s (%d) from mysql_store_result() in check_table",
  352.           mysql_error(mysql),mysql_errno(mysql));
  353.       goto end;
  354.     }
  355.     while ((row=mysql_fetch_row(res)))
  356.     {
  357.       if (!strcmp(row[1],"status"))
  358.     goto end;
  359.     }
  360.     error=0;
  361.   }
  362.  
  363. end:
  364.   if (error)
  365.   {
  366.     fprintf(stderr,"ERROR: Table %s is corrupted\n",table_name);
  367.     fflush(stderr);
  368.   }
  369.   else if (verbose)
  370.   {
  371.     printf("Table %s is ok\n",table_name);
  372.     fflush(stdout);
  373.   }
  374.   mysql_close(mysql);
  375.   DBUG_RETURN(error);
  376. }
  377.  
  378.  
  379. static char *generate_url(char *to,struct rand_struct *random)
  380. {
  381.   uint name_length=(uint) (rnd(random)*10+50);
  382.   char *pos=strmov(to,"http://www.");
  383.   while (name_length--)
  384.     *pos++= (char) (rnd(random)*27+65);
  385.   *pos=0;
  386.   return to;
  387. }
  388.  
  389. static char NEAR dig_vec[] =
  390.   "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  391.  
  392. static char *generate_digest(char *to,struct rand_struct *random)
  393. {
  394.   uint name_length=32;
  395.   char *pos=to;
  396.  
  397.   while (name_length--)
  398.     *pos++= dig_vec[(int) (rnd(random)*16)];
  399.   *pos=0;
  400.   return to;
  401. }
  402.  
  403.  
  404. pthread_handler_decl(test_insert,arg)
  405. {
  406.   int *param=(int*) arg;
  407.   int result=1,thread_nr= *param;
  408.   uint i;
  409.   char buff[255],url[160];
  410.   struct rand_struct random;
  411.   MYSQL *mysql;
  412.  
  413.   my_thread_init();
  414.   randominit(&random,(ulong) time((time_t*) 0), *param * 1024);
  415.  
  416.   if (opt_verbose)
  417.   {
  418.     printf("Insert thread %d (%s) started\n",thread_nr,my_thread_name());
  419.     fflush(stdout);
  420.   }
  421.  
  422.   if (!(mysql=test_connect()))
  423.     goto end;
  424.  
  425.   for (i=0 ; i < insert_loop_count ; i++)
  426.   {
  427.     sprintf(buff,
  428.         "INSERT %s INTO %s (URL, EXPIRY, LAST_ACC_DATE, TIMES_INDEXED, DELETED, TIMES_ACCESSED) VALUES ('%s','%s','%s', 0, 'F', 0)",
  429.         lock_priority,
  430.         table_name,
  431.         generate_url(url,&random),
  432.         "2000-09-13 17:57:37","2000-09-13 17:57:37");
  433.     if (safe_stmt(mysql,buff))
  434.       goto end;
  435.   }
  436.   result=0;
  437.  
  438. end:
  439.   *param= result;
  440.   if (mysql)
  441.     mysql_close(mysql);
  442.   pthread_mutex_lock(&LOCK_thread_count);
  443.   thread_count--;
  444.   VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
  445.   pthread_mutex_unlock(&LOCK_thread_count);
  446.   if (opt_verbose)
  447.   {
  448.     printf("insert thread %d (%s) ended\n",thread_nr,my_thread_name());
  449.     fflush(stdout);
  450.   }
  451.   my_thread_end();
  452.   pthread_exit(0);
  453.   return 0;
  454. }
  455.  
  456.  
  457. pthread_handler_decl(test_update,arg)
  458. {
  459.   int *param=(int*) arg;
  460.   int result=1,not_found=0,thread_nr= *param;
  461.   ulong used_id=0;
  462.   char buff[1024],digest[64];
  463.   struct rand_struct random;
  464.   MYSQL *mysql;
  465.   MYSQL_ROW row;
  466.   MYSQL_RES *res;
  467.  
  468.   my_thread_init();
  469.   randominit(&random,(ulong) time((time_t*) 0), *param * 1024);
  470.  
  471.   if (opt_verbose)
  472.   {
  473.     printf("update thread %d (%s) started\n",thread_nr,my_thread_name());
  474.     fflush(stdout);
  475.   }
  476.  
  477.   if (!(mysql=test_connect()))
  478.     goto end;
  479.  
  480.   /* Loop until there is no ID's and no threads that updates them */
  481.   for (; ; )
  482.   {
  483.     if (time_for_check && (used_id % time_for_check) == time_for_check-1)
  484.     {
  485.       if (check_table(table_name,0))
  486.     goto end;
  487.     }
  488.     if (used_id & 1)
  489.       sprintf(buff,"SELECT HIGH_PRIORITY url from %s where id=-1",table_name);
  490.     else
  491.       sprintf(buff,"SELECT HIGH_PRIORITY url from %s where digest=''",table_name);
  492.     if (safe_stmt(mysql,buff))
  493.       goto end;
  494.     if (!(res=mysql_store_result(mysql)))
  495.     {
  496.       fprintf(stderr,"Got error %s (%d) from mysql_store_result()",
  497.           mysql_error(mysql),mysql_errno(mysql));
  498.       goto end;
  499.     }
  500.     if (!mysql_num_rows(res))
  501.     {
  502.       if (not_found++ > 0)
  503.     break;                    /* end of test */
  504.       sleep(5);
  505.       continue;
  506.     }
  507.     not_found=0;
  508.     while ((row=mysql_fetch_row(res)))
  509.     {
  510.       sprintf(buff,"UPDATE LOW_PRIORITY %s SET ID=%ld, DIGEST='%s', TITLE = '%s', EXPIRY = '2000-09-01 17:11:02', MODIFIED_DATE = '2000-07-11 18:10:02', FIRST_ACC_DATE = '2000-08-18', LAST_ACC_DATE = '2000-08-18', TIMES_INDEXED = TIMES_INDEXED + 1, ABSTRACT = 'abstract', FILE_SIZE = 2230, DELETED = 'F', TIMES_ACCESSED = TIMES_ACCESSED + 1, LAST_RESPONSE_CODE = 200 WHERE URL = '%s'",
  511.           table_name,++used_id, generate_digest(digest, &random), "test-title", row[0]);
  512.       if (safe_stmt(mysql,buff))
  513.     goto end;
  514.     }
  515.     mysql_free_result(res);
  516.   }
  517.   result=0;
  518.  
  519. end:
  520.   *param= result;
  521.   if (mysql)
  522.     mysql_close(mysql);
  523.   pthread_mutex_lock(&LOCK_thread_count);
  524.   thread_count--;
  525.   VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */
  526.   pthread_mutex_unlock(&LOCK_thread_count);
  527.   if (opt_verbose)
  528.   {
  529.     printf("update thread %d (%s) ended\n",thread_nr,my_thread_name());
  530.     fflush(stdout);
  531.   }
  532.   my_thread_end();
  533.   pthread_exit(0);
  534.   return 0;
  535. }
  536.