MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
testhash.c
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-1301 USA */
15 
16 /* Test of hash library: big test */
17 
18 #include <my_global.h>
19 #include <my_sys.h>
20 #include <hash.h>
21 #include <m_string.h>
22 
23 #define MAX_RECORDS 100000
24 #define MAX_KEYS 3
25 
26 static int get_options(int argc, char *argv[]);
27 static int do_test();
28 static int rnd(int max_value);
29 
30 static uint testflag=0,recant=10000,reclength=37;
31 static uint16 key1[1000];
32 
33 #ifdef DBUG_OFF
34 #define hash_check(A) 0
35 #else
36 my_bool hash_check(HASH *hash);
37 #endif
38 
39 void free_record(void *record);
40 
41 static uchar *hash2_key(const uchar *rec,uint *length,
42  my_bool not_used __attribute__((unused)))
43 {
44  *length=(uint) (uchar) rec[reclength-1];
45  return (uchar*) rec;
46 }
47 
48 /* main program */
49 
50 int main(int argc,char *argv[])
51 {
52  MY_INIT(argv[0]);
53  DBUG_PROCESS(argv[0]);
54 
55  get_options(argc,argv);
56 
57  exit(do_test());
58 }
59 
60 static int do_test()
61 {
62  register uint i,j;
63  uint n1,n2,n3;
64  uint write_count,update,delete;
65  ulong pos;
66  unsigned long key_check;
67  char *record,*recpos,oldrecord[120],key[10];
68  HASH hash,hash2;
69  DBUG_ENTER("do_test");
70 
71  write_count=update=delete=0;
72  key_check=0;
73  memset(key1, 0, sizeof(key1[0])*1000);
74 
75  printf("- Creating hash\n");
76  if (hash_init(&hash, default_charset_info, recant/2, 0, 6, 0, free_record, 0))
77  goto err;
78  printf("- Writing records:\n");
79 
80  for (i=0 ; i < recant ; i++)
81  {
82  n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*5,MAX_RECORDS));
83  record= (char*) my_malloc(reclength,MYF(MY_FAE));
84  sprintf(record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count);
85  if (my_hash_insert(&hash,record))
86  {
87  printf("Error: %d in write at record: %d\n",my_errno,i);
88  goto err;
89  }
90  key1[n1]++;
91  key_check+=n1;
92  write_count++;
93  }
94  if (hash_check(&hash))
95  {
96  puts("Heap keys crashed");
97  goto err;
98  }
99  printf("- Delete\n");
100  for (i=0 ; i < write_count/10 ; i++)
101  {
102  for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
103  if (j != 0)
104  {
105  sprintf(key,"%6d",j);
106  if (!(recpos=hash_search(&hash,key,0)))
107  {
108  printf("can't find key1: \"%s\"\n",key);
109  goto err;
110  }
111  key1[atoi(recpos)]--;
112  key_check-=atoi(recpos);
113  memcpy(oldrecord,recpos,reclength);
114  if (hash_delete(&hash,recpos))
115  {
116  printf("error: %d; can't delete record: \"%s\"\n", my_errno,oldrecord);
117  goto err;
118  }
119  delete++;
120  if (testflag == 2 && hash_check(&hash))
121  {
122  puts("Heap keys crashed");
123  goto err;
124  }
125  }
126  }
127  if (hash_check(&hash))
128  {
129  puts("Hash keys crashed");
130  goto err;
131  }
132 
133  printf("- Update\n");
134  for (i=0 ; i < write_count/10 ; i++)
135  {
136  n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*2,MAX_RECORDS));
137  for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
138  if (j)
139  {
140  sprintf(key,"%6d",j);
141  if (!(recpos=hash_search(&hash,key,0)))
142  {
143  printf("can't find key1: \"%s\"\n",key);
144  goto err;
145  }
146  key1[atoi(recpos)]--;
147  key_check=key_check-atoi(recpos)+n1;
148  key1[n1]++;
149  sprintf(recpos,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update);
150  update++;
151  if (hash_update(&hash,recpos,key,0))
152  {
153  printf("can't update key1: \"%s\"\n",key);
154  goto err;
155  }
156  if (testflag == 3 && hash_check(&hash))
157  {
158  printf("Heap keys crashed for %d update\n",update);
159  goto err;
160  }
161  }
162  }
163  if (hash_check(&hash))
164  {
165  puts("Heap keys crashed");
166  goto err;
167  }
168 
169  for (j=0 ; j < 1000 ; j++)
170  if (key1[j] > 1)
171  break;
172  if (key1[j] > 1)
173  {
174  HASH_SEARCH_STATE state;
175  printf("- Testing identical read\n");
176  sprintf(key,"%6d",j);
177  pos=1;
178  if (!(recpos= hash_first(&hash, key, 0, &state)))
179  {
180  printf("can't find key1: \"%s\"\n",key);
181  goto err;
182  }
183  while (hash_next(&hash, key, 0, &state) && pos < (ulong) (key1[j]+10))
184  pos++;
185  if (pos != (ulong) key1[j])
186  {
187  printf("Found %ld copies of key: %s. Should be %d",pos,key,key1[j]);
188  goto err;
189  }
190  }
191  printf("- Creating output heap-file 2\n");
192  if (hash_init(&hash2, default_charset_info, hash.records, 0, 0, hash2_key, free_record,0))
193  goto err;
194 
195  printf("- Copying and removing records\n");
196  pos=0;
197  while ((recpos=hash_element(&hash,0)))
198  {
199  record=(uchar*) my_malloc(reclength,MYF(MY_FAE));
200  memcpy(record,recpos,reclength);
201  record[reclength-1]=rnd(5)+1;
202  if (my_hash_insert(&hash2,record))
203  {
204  printf("Got error when inserting record: %*s",reclength,record);
205  goto err;
206  }
207  key_check-=atoi(record);
208  write_count++;
209  if (hash_delete(&hash,recpos))
210  {
211  printf("Got error when deleting record: %*s",reclength,recpos);
212  goto err;
213  }
214  if (testflag==4)
215  {
216  if (hash_check(&hash) || hash_check(&hash2))
217  {
218  puts("Hash keys crashed");
219  goto err;
220  }
221  }
222  pos++;
223  }
224  if (hash_check(&hash) || hash_check(&hash2))
225  {
226  puts("Hash keys crashed");
227  goto err;
228  }
229  if (key_check != 0)
230  {
231  printf("Key check didn't get to 0 (%ld)\n",key_check);
232  }
233 
234  printf("\nFollowing test have been made:\n");
235  printf("Write records: %d\nUpdate records: %d\nDelete records: %d\n", write_count,
236  update,delete);
237  hash_free(&hash); hash_free(&hash2);
238  my_end(MY_GIVE_INFO);
239  DBUG_RETURN(0);
240 err:
241  printf("Got error: %d when using hashing\n",my_errno);
242  DBUG_RETURN(-1);
243 } /* main */
244 
245 
246 /* read options */
247 /* NOTE! DBUG not initialised - no debugging here! */
248 
249 static int get_options(int argc, char **argv)
250 {
251  char *pos,*progname;
252 
253  progname= argv[0];
254 
255  while (--argc >0 && *(pos = *(++argv)) == '-' ) {
256  switch(*++pos) {
257  case 'm': /* records */
258  recant=atoi(++pos);
259  break;
260  case 't':
261  testflag=atoi(++pos); /* testmod */
262  break;
263  case 'V':
264  case 'I':
265  case '?':
266  printf("%s Ver 1.0 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
267  printf("MySQL AB, by Monty\n\n");
268  printf("Usage: %s [-?ABIKLWv] [-m#] [-t#]\n",progname);
269  exit(0);
270  case '#':
271  DBUG_PUSH (++pos);
272  break;
273  }
274  }
275  return 0;
276 } /* get_options */
277 
278 
279 /* Get a random number in the interval 0 <= x <= n */
280 
281 static int rnd(int max_value)
282 {
283  return (int) ((rand() & 32767)/32767.0*max_value);
284 } /* rnd */
285 
286 
287 void free_record(void *record)
288 {
289  my_free(record);
290 }