~stewart/drizzle/embedded-innodb-create-select-transaction-arrgh

« back to all changes in this revision

Viewing changes to tests/deadlock_test.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2001, 2003-2004, 2006 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 <mysql.h>
 
17
#include <stdio.h>
 
18
#include <stdarg.h>
 
19
#include <stdio.h>
 
20
#include <string.h>
 
21
#include <stdlib.h>
 
22
 
 
23
typedef unsigned char uchar;
 
24
static void die(char* fmt, ...);
 
25
static void safe_query(MYSQL* mysql, char* query, int read_ok);
 
26
static void run_query_batch(int* order, int num_queries);
 
27
static void permute(int *order, int num_queries);
 
28
static void permute_aux(int *order, int num_queries, int* fixed);
 
29
static void dump_result(MYSQL* mysql, char* query);
 
30
 
 
31
int count = 0;
 
32
 
 
33
 
 
34
struct query
 
35
{
 
36
  MYSQL* mysql;
 
37
  char* query;
 
38
  int read_ok;
 
39
  int pri;
 
40
  int dump_result;
 
41
};
 
42
 
 
43
MYSQL lock, sel, del_ins;
 
44
 
 
45
struct query queries[] =
 
46
{
 
47
  {&del_ins, "insert delayed into foo values(1)", 1, 0, 0},
 
48
  {&del_ins, "insert delayed into foo values(1)", 1, 0, 0},
 
49
  {&lock, "lock tables foo write", 1, 1, 0},
 
50
  {&lock, "unlock tables", 1,2, 0},
 
51
  {&sel, "select * from foo", 0,0, 0},
 
52
  {&del_ins, "insert  into foo values(4)", 0,3, 0},
 
53
  {0,0,0}
 
54
};
 
55
 
 
56
static void die(char* fmt, ...)
 
57
{
 
58
  va_list args;
 
59
  va_start(args, fmt);
 
60
  fprintf(stderr, "ERROR: ");
 
61
  vfprintf(stderr, fmt, args);
 
62
  fprintf(stderr, "\n");
 
63
  va_end(args);
 
64
  exit(1);
 
65
}
 
66
 
 
67
static void permute(int *order, int num_queries)
 
68
{
 
69
  int *fixed;
 
70
  if(num_queries < 2) return;
 
71
  if(!(fixed = (int*)malloc(num_queries * sizeof(int))))
 
72
    die("malloc() failed");
 
73
 
 
74
  memset(fixed, 0, num_queries * sizeof(int));
 
75
  permute_aux(order, num_queries, fixed);
 
76
 
 
77
  free(fixed);
 
78
}
 
79
 
 
80
static order_ok(int *order, int num_queries)
 
81
{
 
82
  int i,j, pri_i, pri_j;
 
83
  for(i = 0; i < num_queries; i++)
 
84
    {
 
85
      if((pri_i = queries[order[i]].pri))
 
86
        for(j = i + 1; j < num_queries; j++)
 
87
          {
 
88
            pri_j = queries[order[j]].pri;
 
89
            if(pri_j && pri_i > pri_j)
 
90
              return 0;
 
91
          }
 
92
    }
 
93
 
 
94
  return 1;
 
95
}
 
96
 
 
97
static void permute_aux(int *order, int num_queries, int* fixed)
 
98
{
 
99
  int *p,*p1,j,i,tmp, num_free = 0;
 
100
  p = fixed;
 
101
  for(i = 0; i < num_queries; i++, p++)
 
102
    {
 
103
      if(!*p)
 
104
        {
 
105
          num_free++;
 
106
          *p = 1;
 
107
          for(j = 0, p1 = fixed ;
 
108
              j < num_queries; j++,p1++)
 
109
            {
 
110
              if(!*p1)
 
111
                {
 
112
                  tmp = order[i];
 
113
                  order[i] = order[j];
 
114
                  order[j] = tmp;
 
115
                  *p1 = 1;
 
116
                  permute_aux(order, num_queries, fixed);
 
117
                  tmp = order[i];
 
118
                  order[i] = order[j];
 
119
                  order[j] = tmp;
 
120
                  *p1 = 0;
 
121
                }
 
122
            }
 
123
          *p = 0;
 
124
        }
 
125
    }
 
126
 
 
127
  /*printf("num_free = %d\n", num_free); */
 
128
 
 
129
  if(num_free <= 1)
 
130
    {
 
131
      count++;
 
132
      if(order_ok(order, num_queries))
 
133
        run_query_batch(order, num_queries);
 
134
    }
 
135
}
 
136
 
 
137
static void run_query_batch(int* order, int num_queries)
 
138
{
 
139
  int i;
 
140
  struct query* q;
 
141
  int *save_order;
 
142
  safe_query(&lock, "delete from foo", 1);
 
143
  save_order = order;
 
144
  for(i = 0; i < num_queries; i++,order++)
 
145
    {
 
146
      q = queries + *order;
 
147
      printf("query='%s'\n", q->query);
 
148
      safe_query(q->mysql, q->query, q->read_ok);
 
149
    }
 
150
  order = save_order;
 
151
  for(i = 0; i < num_queries; i++,order++)
 
152
    {
 
153
      q = queries + *order;
 
154
      if(q->dump_result)
 
155
       dump_result(q->mysql, q->query);
 
156
    }
 
157
  printf("\n");
 
158
 
 
159
}
 
160
 
 
161
static void safe_net_read(NET* net, char* query)
 
162
{
 
163
  int len;
 
164
  len = my_net_read(net); 
 
165
  if(len == packet_error || !len)
 
166
    die("Error running query '%s'", query);
 
167
  if(net->read_pos[0] == 255)
 
168
    die("Error running query '%s'", query);
 
169
}
 
170
 
 
171
 
 
172
static void safe_query(MYSQL* mysql, char* query, int read_ok)
 
173
{
 
174
  int len;
 
175
  NET* net = &mysql->net;
 
176
  net_clear(net);
 
177
  if(net_write_command(net,(uchar)COM_QUERY, query,strlen(query)))
 
178
    die("Error running query '%s': %s", query, mysql_error(mysql));
 
179
  if(read_ok)
 
180
    {
 
181
      safe_net_read(net, query);
 
182
    }
 
183
}
 
184
 
 
185
static void dump_result(MYSQL* mysql, char* query)
 
186
{
 
187
  MYSQL_RES* res;
 
188
  safe_net_read(&mysql->net, query);
 
189
  res = mysql_store_result(mysql);
 
190
  if(res)
 
191
   mysql_free_result(res);
 
192
}
 
193
 
 
194
static int* init_order(int* num_queries)
 
195
{
 
196
  struct query* q;
 
197
  int *order, *order_end, *p;
 
198
  int n,i;
 
199
 
 
200
  for(q = queries; q->mysql; q++)
 
201
    ;
 
202
 
 
203
  n = q - queries;
 
204
  if(!(order = (int*) malloc(n * sizeof(int))))
 
205
    die("malloc() failed");
 
206
  order_end = order + n;
 
207
  for(p = order,i = 0; p < order_end; p++,i++)
 
208
    *p = i;
 
209
  *num_queries = n;
 
210
  return order;
 
211
}
 
212
 
 
213
int main()
 
214
{
 
215
  char* user = "root", *pass = "", *host = "localhost", *db = "test";
 
216
  int *order, num_queries;
 
217
  order = init_order(&num_queries);
 
218
  if(!mysql_init(&lock) || !mysql_init(&sel) || !mysql_init(&del_ins))
 
219
    die("error in mysql_init()");
 
220
 
 
221
  mysql_options(&lock, MYSQL_READ_DEFAULT_GROUP, "mysql");
 
222
  mysql_options(&sel, MYSQL_READ_DEFAULT_GROUP, "mysql");
 
223
  mysql_options(&del_ins, MYSQL_READ_DEFAULT_GROUP, "mysql");
 
224
 
 
225
  if(!mysql_real_connect(&lock, host, user, pass, db, 0,0,0 ) ||
 
226
     !mysql_real_connect(&sel, host, user, pass, db, 0,0,0 ) ||
 
227
     !mysql_real_connect(&del_ins, host, user, pass, db, 0,0,0 ))
 
228
    die("Error in mysql_real_connect(): %s", mysql_error(&lock));
 
229
  lock.reconnect= sel.reconnect= del_ins.reconnect= 1;
 
230
 
 
231
  permute(order, num_queries);
 
232
  printf("count = %d\n", count);
 
233
 
 
234
  mysql_close(&lock);
 
235
  mysql_close(&sel);
 
236
  mysql_close(&del_ins);
 
237
  free(order);
 
238
}