~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 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
/* 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
  bzero((char*) key1,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,MYF(0));
290
}