MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mi_test2.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 av isam-databas: stor test */
17 
18 #ifndef USE_MY_FUNC /* We want to be able to dbug this !! */
19 #define USE_MY_FUNC
20 #endif
21 #ifdef DBUG_OFF
22 #undef DBUG_OFF
23 #endif
24 #include "myisamdef.h"
25 #include <m_ctype.h>
26 #include <my_bit.h>
27 
28 #define STANDARD_LENGTH 37
29 #define MYISAM_KEYS 6
30 #define MAX_PARTS 4
31 #if !defined(labs)
32 #define labs(a) abs(a)
33 #endif
34 
35 static void get_options(int argc, char *argv[]);
36 static uint rnd(uint max_value);
37 static void fix_length(uchar *record,uint length);
38 static void put_blob_in_record(uchar *blob_pos,char **blob_buffer);
39 static void copy_key(struct st_myisam_info *info,uint inx,
40  uchar *record,uchar *key);
41 
42 static int verbose=0,testflag=0,
43  first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,locking=0,
44  rec_pointer_size=0,pack_fields=1,use_log=0,silent=0,
45  opt_quick_mode=0;
46 static int pack_seg=HA_SPACE_PACK,pack_type=HA_PACK_KEY,remove_count=-1,
47  create_flag=0;
48 static ulong key_cache_size=IO_SIZE*16;
49 static uint key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
50 
51 static uint keys=MYISAM_KEYS,recant=1000;
52 static uint use_blob=0;
53 static uint16 key1[1001],key3[5000];
54 static uchar record[300],record2[300],key[100],key2[100];
55 static uchar read_record[300],read_record2[300],read_record3[300];
56 static HA_KEYSEG glob_keyseg[MYISAM_KEYS][MAX_PARTS];
57 
58  /* Test program */
59 
60 int main(int argc, char *argv[])
61 {
62  uint i;
63  int j,n1,n2,n3,error,k;
64  uint write_count,update,dupp_keys,opt_delete,start,length,blob_pos,
65  reclength,ant,found_parts;
66  my_off_t lastpos;
67  ha_rows range_records,records;
68  MI_INFO *file;
69  MI_KEYDEF keyinfo[10];
70  MI_COLUMNDEF recinfo[10];
71  MI_ISAMINFO info;
72  const char *filename;
73  char *blob_buffer;
74  MI_CREATE_INFO create_info;
75  MY_INIT(argv[0]);
76 
77  filename= "test2";
78  get_options(argc,argv);
79  if (! async_io)
80  my_disable_async_io=1;
81 
82  reclength=STANDARD_LENGTH+60+(use_blob ? 8 : 0);
83  blob_pos=STANDARD_LENGTH+60;
84  keyinfo[0].seg= &glob_keyseg[0][0];
85  keyinfo[0].seg[0].start=0;
86  keyinfo[0].seg[0].length=6;
87  keyinfo[0].seg[0].type=HA_KEYTYPE_TEXT;
88  keyinfo[0].seg[0].language= default_charset_info->number;
89  keyinfo[0].seg[0].flag=(uint8) pack_seg;
90  keyinfo[0].seg[0].null_bit=0;
91  keyinfo[0].seg[0].null_pos=0;
92  keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
93  keyinfo[0].keysegs=1;
94  keyinfo[0].flag = pack_type;
95  keyinfo[0].block_length= 0; /* Default block length */
96  keyinfo[1].seg= &glob_keyseg[1][0];
97  keyinfo[1].seg[0].start=7;
98  keyinfo[1].seg[0].length=6;
99  keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY;
100  keyinfo[1].seg[0].flag=0;
101  keyinfo[1].seg[0].null_bit=0;
102  keyinfo[1].seg[0].null_pos=0;
103  keyinfo[1].seg[1].start=0; /* two part key */
104  keyinfo[1].seg[1].length=6;
105  keyinfo[1].seg[1].type=HA_KEYTYPE_NUM;
106  keyinfo[1].seg[1].flag=HA_REVERSE_SORT;
107  keyinfo[1].seg[1].null_bit=0;
108  keyinfo[1].seg[1].null_pos=0;
109  keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
110  keyinfo[1].keysegs=2;
111  keyinfo[1].flag =0;
112  keyinfo[1].block_length= MI_MIN_KEY_BLOCK_LENGTH; /* Diff blocklength */
113  keyinfo[2].seg= &glob_keyseg[2][0];
114  keyinfo[2].seg[0].start=12;
115  keyinfo[2].seg[0].length=8;
116  keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY;
117  keyinfo[2].seg[0].flag=HA_REVERSE_SORT;
118  keyinfo[2].seg[0].null_bit=0;
119  keyinfo[2].seg[0].null_pos=0;
120  keyinfo[2].key_alg=HA_KEY_ALG_BTREE;
121  keyinfo[2].keysegs=1;
122  keyinfo[2].flag =HA_NOSAME;
123  keyinfo[2].block_length= 0; /* Default block length */
124  keyinfo[3].seg= &glob_keyseg[3][0];
125  keyinfo[3].seg[0].start=0;
126  keyinfo[3].seg[0].length=reclength-(use_blob ? 8 : 0);
127  keyinfo[3].seg[0].type=HA_KEYTYPE_TEXT;
128  keyinfo[3].seg[0].language=default_charset_info->number;
129  keyinfo[3].seg[0].flag=(uint8) pack_seg;
130  keyinfo[3].seg[0].null_bit=0;
131  keyinfo[3].seg[0].null_pos=0;
132  keyinfo[3].key_alg=HA_KEY_ALG_BTREE;
133  keyinfo[3].keysegs=1;
134  keyinfo[3].flag = pack_type;
135  keyinfo[3].block_length= 0; /* Default block length */
136  keyinfo[4].seg= &glob_keyseg[4][0];
137  keyinfo[4].seg[0].start=0;
138  keyinfo[4].seg[0].length=5;
139  keyinfo[4].seg[0].type=HA_KEYTYPE_TEXT;
140  keyinfo[4].seg[0].language=default_charset_info->number;
141  keyinfo[4].seg[0].flag=0;
142  keyinfo[4].seg[0].null_bit=0;
143  keyinfo[4].seg[0].null_pos=0;
144  keyinfo[4].key_alg=HA_KEY_ALG_BTREE;
145  keyinfo[4].keysegs=1;
146  keyinfo[4].flag = pack_type;
147  keyinfo[4].block_length= 0; /* Default block length */
148  keyinfo[5].seg= &glob_keyseg[5][0];
149  keyinfo[5].seg[0].start=0;
150  keyinfo[5].seg[0].length=4;
151  keyinfo[5].seg[0].type=HA_KEYTYPE_TEXT;
152  keyinfo[5].seg[0].language=default_charset_info->number;
153  keyinfo[5].seg[0].flag=pack_seg;
154  keyinfo[5].seg[0].null_bit=0;
155  keyinfo[5].seg[0].null_pos=0;
156  keyinfo[5].key_alg=HA_KEY_ALG_BTREE;
157  keyinfo[5].keysegs=1;
158  keyinfo[5].flag = pack_type;
159  keyinfo[5].block_length= 0; /* Default block length */
160 
161  recinfo[0].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
162  recinfo[0].length=7;
163  recinfo[0].null_bit=0;
164  recinfo[0].null_pos=0;
165  recinfo[1].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
166  recinfo[1].length=5;
167  recinfo[1].null_bit=0;
168  recinfo[1].null_pos=0;
169  recinfo[2].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
170  recinfo[2].length=9;
171  recinfo[2].null_bit=0;
172  recinfo[2].null_pos=0;
173  recinfo[3].type=FIELD_NORMAL;
174  recinfo[3].length=STANDARD_LENGTH-7-5-9-4;
175  recinfo[3].null_bit=0;
176  recinfo[3].null_pos=0;
177  recinfo[4].type=pack_fields ? FIELD_SKIP_ZERO : 0;
178  recinfo[4].length=4;
179  recinfo[4].null_bit=0;
180  recinfo[4].null_pos=0;
181  recinfo[5].type=pack_fields ? FIELD_SKIP_ENDSPACE : 0;
182  recinfo[5].length=60;
183  recinfo[5].null_bit=0;
184  recinfo[5].null_pos=0;
185  if (use_blob)
186  {
187  recinfo[6].type=FIELD_BLOB;
188  recinfo[6].length=4+portable_sizeof_char_ptr;
189  recinfo[6].null_bit=0;
190  recinfo[6].null_pos=0;
191  }
192 
193  write_count=update=dupp_keys=opt_delete=0;
194  blob_buffer=0;
195 
196  for (i=1000 ; i>0 ; i--) key1[i]=0;
197  for (i=4999 ; i>0 ; i--) key3[i]=0;
198 
199  if (!silent)
200  printf("- Creating isam-file\n");
201  /* DBUG_PUSH(""); */
202  /* my_delete(filename,MYF(0)); */ /* Remove old locks under gdb */
203  file= 0;
204  memset(&create_info, 0, sizeof(create_info));
205  create_info.max_rows=(ha_rows) (rec_pointer_size ?
206  (1L << (rec_pointer_size*8))/
207  reclength : 0);
208  create_info.reloc_rows=(ha_rows) 100;
209  if (mi_create(filename,keys,&keyinfo[first_key],
210  use_blob ? 7 : 6, &recinfo[0],
211  0,(MI_UNIQUEDEF*) 0,
212  &create_info,create_flag))
213  goto err;
214  if (use_log)
215  mi_log(1);
216  if (!(file=mi_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
217  goto err;
218  if (!silent)
219  printf("- Writing key:s\n");
220  if (key_cacheing)
221  init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0);
222  if (locking)
223  mi_lock_database(file,F_WRLCK);
224  if (write_cacheing)
225  mi_extra(file,HA_EXTRA_WRITE_CACHE,0);
226  if (opt_quick_mode)
227  mi_extra(file,HA_EXTRA_QUICK,0);
228 
229  for (i=0 ; i < recant ; i++)
230  {
231  n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
232  sprintf((char*) record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count);
233  int4store(record+STANDARD_LENGTH-4,(long) i);
234  fix_length(record,(uint) STANDARD_LENGTH+rnd(60));
235  put_blob_in_record(record+blob_pos,&blob_buffer);
236  DBUG_PRINT("test",("record: %d",i));
237 
238  if (mi_write(file,record))
239  {
240  if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
241  {
242  printf("Error: %d in write at record: %d\n",my_errno,i);
243  goto err;
244  }
245  if (verbose) printf(" Double key: %d\n",n3);
246  }
247  else
248  {
249  if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3)
250  {
251  printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
252  goto err;
253  }
254  write_count++; key1[n1]++; key3[n3]=1;
255  }
256 
257  /* Check if we can find key without flushing database */
258  if (i == recant/2)
259  {
260  for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
261  if (!j)
262  for (j=999 ; j>0 && key1[j] == 0 ; j--) ;
263  sprintf((char*) key,"%6d",j);
264  if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
265  {
266  printf("Test in loop: Can't find key: \"%s\"\n",key);
267  goto err;
268  }
269  }
270  }
271  if (testflag==1) goto end;
272 
273  if (write_cacheing)
274  {
275  if (mi_extra(file,HA_EXTRA_NO_CACHE,0))
276  {
277  puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
278  goto end;
279  }
280  }
281  if (key_cacheing)
282  resize_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size*2,0,0);
283 
284  if (!silent)
285  printf("- Delete\n");
286  for (i=0 ; i<recant/10 ; i++)
287  {
288  for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
289  if (j != 0)
290  {
291  sprintf((char*) key,"%6d",j);
292  if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
293  {
294  printf("can't find key1: \"%s\"\n",key);
295  goto err;
296  }
297  if (opt_delete == (uint) remove_count) /* While testing */
298  goto end;
299  if (mi_delete(file,read_record))
300  {
301  printf("error: %d; can't delete record: \"%s\"\n", my_errno,read_record);
302  goto err;
303  }
304  opt_delete++;
305  key1[atoi((char*) read_record+keyinfo[0].seg[0].start)]--;
306  key3[atoi((char*) read_record+keyinfo[2].seg[0].start)]=0;
307  }
308  else
309  puts("Warning: Skipping delete test because no dupplicate keys");
310  }
311  if (testflag==2) goto end;
312 
313  if (!silent)
314  printf("- Update\n");
315  for (i=0 ; i<recant/10 ; i++)
316  {
317  n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
318  sprintf((char*) record2,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update);
319  int4store(record2+STANDARD_LENGTH-4,(long) i);
320  fix_length(record2,(uint) STANDARD_LENGTH+rnd(60));
321 
322  for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
323  if (j != 0)
324  {
325  sprintf((char*) key,"%6d",j);
326  if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
327  {
328  printf("can't find key1: \"%s\"\n",(char*) key);
329  goto err;
330  }
331  if (use_blob)
332  {
333  if (i & 1)
334  put_blob_in_record(record+blob_pos,&blob_buffer);
335  else
336  bmove(record+blob_pos,read_record+blob_pos,8);
337  }
338  if (mi_update(file,read_record,record2))
339  {
340  if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
341  {
342  printf("error: %d; can't update:\nFrom: \"%s\"\nTo: \"%s\"\n",
343  my_errno,read_record,record2);
344  goto err;
345  }
346  if (verbose)
347  printf("Double key when tried to update:\nFrom: \"%s\"\nTo: \"%s\"\n",record,record2);
348  }
349  else
350  {
351  key1[atoi((char*) read_record+keyinfo[0].seg[0].start)]--;
352  key3[atoi((char*) read_record+keyinfo[2].seg[0].start)]=0;
353  key1[n1]++; key3[n3]=1;
354  update++;
355  }
356  }
357  }
358  if (testflag == 3)
359  goto end;
360 
361  for (i=999, dupp_keys=j=0 ; i>0 ; i--)
362  {
363  if (key1[i] > dupp_keys)
364  {
365  dupp_keys=key1[i]; j=i;
366  }
367  }
368  sprintf((char*) key,"%6d",j);
369  start=keyinfo[0].seg[0].start;
370  length=keyinfo[0].seg[0].length;
371  if (dupp_keys)
372  {
373  if (!silent)
374  printf("- Same key: first - next -> last - prev -> first\n");
375  DBUG_PRINT("progpos",("first - next -> last - prev -> first"));
376  if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys);
377 
378  if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
379  goto err;
380  if (mi_rsame(file,read_record2,-1))
381  goto err;
382  if (memcmp(read_record,read_record2,reclength) != 0)
383  {
384  printf("mi_rsame didn't find same record\n");
385  goto end;
386  }
387  info.recpos=mi_position(file);
388  if (mi_rfirst(file,read_record2,0) ||
389  mi_rsame_with_pos(file,read_record2,0,info.recpos) ||
390  memcmp(read_record,read_record2,reclength) != 0)
391  {
392  printf("mi_rsame_with_pos didn't find same record\n");
393  goto end;
394  }
395  {
396  int skr=mi_rnext(file,read_record2,0);
397  if ((skr && my_errno != HA_ERR_END_OF_FILE) ||
398  mi_rprev(file,read_record2,-1) ||
399  memcmp(read_record,read_record2,reclength) != 0)
400  {
401  printf("mi_rsame_with_pos lost position\n");
402  goto end;
403  }
404  }
405  ant=1;
406  while (mi_rnext(file,read_record2,0) == 0 &&
407  memcmp(read_record2+start,key,length) == 0) ant++;
408  if (ant != dupp_keys)
409  {
410  printf("next: Found: %d keys of %d\n",ant,dupp_keys);
411  goto end;
412  }
413  ant=0;
414  while (mi_rprev(file,read_record3,0) == 0 &&
415  memcmp(read_record3+start,key,length) == 0) ant++;
416  if (ant != dupp_keys)
417  {
418  printf("prev: Found: %d records of %d\n",ant,dupp_keys);
419  goto end;
420  }
421 
422  /* Check of mi_rnext_same */
423  if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
424  goto err;
425  ant=1;
426  while (!mi_rnext_same(file,read_record3) && ant < dupp_keys+10)
427  ant++;
428  if (ant != dupp_keys || my_errno != HA_ERR_END_OF_FILE)
429  {
430  printf("mi_rnext_same: Found: %d records of %d\n",ant,dupp_keys);
431  goto end;
432  }
433  }
434 
435  if (!silent)
436  printf("- All keys: first - next -> last - prev -> first\n");
437  DBUG_PRINT("progpos",("All keys: first - next -> last - prev -> first"));
438  ant=1;
439  if (mi_rfirst(file,read_record,0))
440  {
441  printf("Can't find first record\n");
442  goto end;
443  }
444  while ((error=mi_rnext(file,read_record3,0)) == 0 && ant < write_count+10)
445  ant++;
446  if (ant != write_count - opt_delete || error != HA_ERR_END_OF_FILE)
447  {
448  printf("next: I found: %d records of %d (error: %d)\n",
449  ant, write_count - opt_delete, error);
450  goto end;
451  }
452  if (mi_rlast(file,read_record2,0) ||
453  memcmp(read_record2,read_record3,reclength))
454  {
455  printf("Can't find last record\n");
456  DBUG_DUMP("record2",(uchar*) read_record2,reclength);
457  DBUG_DUMP("record3",(uchar*) read_record3,reclength);
458  goto end;
459  }
460  ant=1;
461  while (mi_rprev(file,read_record3,0) == 0 && ant < write_count+10)
462  ant++;
463  if (ant != write_count - opt_delete)
464  {
465  printf("prev: I found: %d records of %d\n",ant,write_count);
466  goto end;
467  }
468  if (memcmp(read_record,read_record3,reclength))
469  {
470  printf("Can't find first record\n");
471  goto end;
472  }
473 
474  if (!silent)
475  printf("- Test if: Read first - next - prev - prev - next == first\n");
476  DBUG_PRINT("progpos",("- Read first - next - prev - prev - next == first"));
477  if (mi_rfirst(file,read_record,0) ||
478  mi_rnext(file,read_record3,0) ||
479  mi_rprev(file,read_record3,0) ||
480  mi_rprev(file,read_record3,0) == 0 ||
481  mi_rnext(file,read_record3,0))
482  goto err;
483  if (memcmp(read_record,read_record3,reclength) != 0)
484  printf("Can't find first record\n");
485 
486  if (!silent)
487  printf("- Test if: Read last - prev - next - next - prev == last\n");
488  DBUG_PRINT("progpos",("Read last - prev - next - next - prev == last"));
489  if (mi_rlast(file,read_record2,0) ||
490  mi_rprev(file,read_record3,0) ||
491  mi_rnext(file,read_record3,0) ||
492  mi_rnext(file,read_record3,0) == 0 ||
493  mi_rprev(file,read_record3,0))
494  goto err;
495  if (memcmp(read_record2,read_record3,reclength))
496  printf("Can't find last record\n");
497 #ifdef NOT_ANYMORE
498  if (!silent)
499  puts("- Test read key-part");
500  strmov(key2,key);
501  for(i=strlen(key2) ; i-- > 1 ;)
502  {
503  key2[i]=0;
504 
505  /* The following row is just to catch some bugs in the key code */
506  memset(file->lastkey, 0, file->s->base.max_key_length*2);
507  if (mi_rkey(file,read_record,0,key2,(uint) i,HA_READ_PREFIX))
508  goto err;
509  if (memcmp(read_record+start,key,(uint) i))
510  {
511  puts("Didn't find right record");
512  goto end;
513  }
514  }
515 #endif
516  if (dupp_keys > 2)
517  {
518  if (!silent)
519  printf("- Read key (first) - next - delete - next -> last\n");
520  DBUG_PRINT("progpos",("first - next - delete - next -> last"));
521  if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
522  goto err;
523  if (mi_rnext(file,read_record3,0)) goto err;
524  if (mi_delete(file,read_record3)) goto err;
525  opt_delete++;
526  ant=1;
527  while (mi_rnext(file,read_record3,0) == 0 &&
528  memcmp(read_record3+start,key,length) == 0) ant++;
529  if (ant != dupp_keys-1)
530  {
531  printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1);
532  goto end;
533  }
534  }
535  if (dupp_keys>4)
536  {
537  if (!silent)
538  printf("- Read last of key - prev - delete - prev -> first\n");
539  DBUG_PRINT("progpos",("last - prev - delete - prev -> first"));
540  if (mi_rprev(file,read_record3,0)) goto err;
541  if (mi_rprev(file,read_record3,0)) goto err;
542  if (mi_delete(file,read_record3)) goto err;
543  opt_delete++;
544  ant=1;
545  while (mi_rprev(file,read_record3,0) == 0 &&
546  memcmp(read_record3+start,key,length) == 0) ant++;
547  if (ant != dupp_keys-2)
548  {
549  printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2);
550  goto end;
551  }
552  }
553  if (dupp_keys > 6)
554  {
555  if (!silent)
556  printf("- Read first - delete - next -> last\n");
557  DBUG_PRINT("progpos",("first - delete - next -> last"));
558  if (mi_rkey(file,read_record3,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
559  goto err;
560  if (mi_delete(file,read_record3)) goto err;
561  opt_delete++;
562  ant=1;
563  if (mi_rnext(file,read_record,0))
564  goto err; /* Skall finnas poster */
565  while (mi_rnext(file,read_record3,0) == 0 &&
566  memcmp(read_record3+start,key,length) == 0) ant++;
567  if (ant != dupp_keys-3)
568  {
569  printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3);
570  goto end;
571  }
572 
573  if (!silent)
574  printf("- Read last - delete - prev -> first\n");
575  DBUG_PRINT("progpos",("last - delete - prev -> first"));
576  if (mi_rprev(file,read_record3,0)) goto err;
577  if (mi_delete(file,read_record3)) goto err;
578  opt_delete++;
579  ant=0;
580  while (mi_rprev(file,read_record3,0) == 0 &&
581  memcmp(read_record3+start,key,length) == 0) ant++;
582  if (ant != dupp_keys-4)
583  {
584  printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4);
585  goto end;
586  }
587  }
588 
589  if (!silent)
590  puts("- Test if: Read rrnd - same");
591  DBUG_PRINT("progpos",("Read rrnd - same"));
592  for (i=0 ; i < write_count ; i++)
593  {
594  if (mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR) == 0)
595  break;
596  }
597  if (i == write_count)
598  goto err;
599 
600  bmove(read_record2,read_record,reclength);
601  for (i=min(2,keys) ; i-- > 0 ;)
602  {
603  if (mi_rsame(file,read_record2,(int) i)) goto err;
604  if (memcmp(read_record,read_record2,reclength) != 0)
605  {
606  printf("is_rsame didn't find same record\n");
607  goto end;
608  }
609  }
610  if (!silent)
611  puts("- Test mi_records_in_range");
612  mi_status(file,&info,HA_STATUS_VARIABLE);
613  for (i=0 ; i < info.keys ; i++)
614  {
615  key_range min_key, max_key;
616  if (mi_rfirst(file,read_record,(int) i) ||
617  mi_rlast(file,read_record2,(int) i))
618  goto err;
619  copy_key(file,(uint) i,(uchar*) read_record,(uchar*) key);
620  copy_key(file,(uint) i,(uchar*) read_record2,(uchar*) key2);
621  min_key.key= key;
622  min_key.keypart_map= HA_WHOLE_KEY;
623  min_key.flag= HA_READ_KEY_EXACT;
624  max_key.key= key2;
625  max_key.keypart_map= HA_WHOLE_KEY;
626  max_key.flag= HA_READ_AFTER_KEY;
627 
628  range_records= mi_records_in_range(file,(int) i, &min_key, &max_key);
629  if (range_records < info.records*8/10 ||
630  range_records > info.records*12/10)
631  {
632  printf("mi_records_range returned %ld; Should be about %ld\n",
633  (long) range_records,(long) info.records);
634  goto end;
635  }
636  if (verbose)
637  {
638  printf("mi_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n",
639  (long) range_records, (long) info.records,
640  labs((long) range_records - (long) info.records)*100.0/
641  info.records);
642  }
643  }
644  for (i=0 ; i < 5 ; i++)
645  {
646  for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
647  for (k=rnd(1000)+1 ; k>0 && key1[k] == 0 ; k--) ;
648  if (j != 0 && k != 0)
649  {
650  key_range min_key, max_key;
651  if (j > k)
652  swap_variables(int, j, k);
653  sprintf((char*) key,"%6d",j);
654  sprintf((char*) key2,"%6d",k);
655 
656  min_key.key= key;
657  min_key.length= USE_WHOLE_KEY;
658  min_key.flag= HA_READ_AFTER_KEY;
659  max_key.key= key2;
660  max_key.length= USE_WHOLE_KEY;
661  max_key.flag= HA_READ_BEFORE_KEY;
662  range_records= mi_records_in_range(file, 0, &min_key, &max_key);
663  records=0;
664  for (j++ ; j < k ; j++)
665  records+=key1[j];
666  if ((long) range_records < (long) records*7/10-2 ||
667  (long) range_records > (long) records*14/10+2)
668  {
669  printf("mi_records_range for key: %d returned %lu; Should be about %lu\n",
670  i, (ulong) range_records, (ulong) records);
671  goto end;
672  }
673  if (verbose && records)
674  {
675  printf("mi_records_range returned %lu; Exact is %lu (diff: %4.2g %%)\n",
676  (ulong) range_records, (ulong) records,
677  labs((long) range_records-(long) records)*100.0/records);
678 
679  }
680  }
681  }
682 
683  if (!silent)
684  printf("- mi_info\n");
685  mi_status(file,&info,HA_STATUS_VARIABLE | HA_STATUS_CONST);
686  if (info.records != write_count-opt_delete || info.deleted > opt_delete + update
687  || info.keys != keys)
688  {
689  puts("Wrong info from mi_info");
690  printf("Got: records: %lu delete: %lu i_keys: %d\n",
691  (ulong) info.records, (ulong) info.deleted, info.keys);
692  }
693  if (verbose)
694  {
695  char buff[80];
696  get_date(buff,3,info.create_time);
697  printf("info: Created %s\n",buff);
698  get_date(buff,3,info.check_time);
699  printf("info: checked %s\n",buff);
700  get_date(buff,3,info.update_time);
701  printf("info: Modified %s\n",buff);
702  }
703 
704  mi_panic(HA_PANIC_WRITE);
705  mi_panic(HA_PANIC_READ);
706  if (mi_is_changed(file))
707  puts("Warning: mi_is_changed reported that datafile was changed");
708 
709  if (!silent)
710  printf("- mi_extra(CACHE) + mi_rrnd.... + mi_extra(NO_CACHE)\n");
711  if (mi_reset(file) || mi_extra(file,HA_EXTRA_CACHE,0))
712  {
713  if (locking || (!use_blob && !pack_fields))
714  {
715  puts("got error from mi_extra(HA_EXTRA_CACHE)");
716  goto end;
717  }
718  }
719  ant=0;
720  while ((error=mi_rrnd(file,record,HA_OFFSET_ERROR)) != HA_ERR_END_OF_FILE &&
721  ant < write_count + 10)
722  ant+= error ? 0 : 1;
723  if (ant != write_count-opt_delete)
724  {
725  printf("rrnd with cache: I can only find: %d records of %d\n",
726  ant,write_count-opt_delete);
727  goto end;
728  }
729  if (mi_extra(file,HA_EXTRA_NO_CACHE,0))
730  {
731  puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
732  goto end;
733  }
734 
735  ant=0;
736  mi_scan_init(file);
737  while ((error=mi_scan(file,record)) != HA_ERR_END_OF_FILE &&
738  ant < write_count + 10)
739  ant+= error ? 0 : 1;
740  if (ant != write_count-opt_delete)
741  {
742  printf("scan with cache: I can only find: %d records of %d\n",
743  ant,write_count-opt_delete);
744  goto end;
745  }
746 
747  if (testflag == 4) goto end;
748 
749  if (!silent)
750  printf("- Removing keys\n");
751  DBUG_PRINT("progpos",("Removing keys"));
752  lastpos = HA_OFFSET_ERROR;
753  /* DBUG_POP(); */
754  mi_reset(file);
755  found_parts=0;
756  while ((error=mi_rrnd(file,read_record,HA_OFFSET_ERROR)) !=
757  HA_ERR_END_OF_FILE)
758  {
759  info.recpos=mi_position(file);
760  if (lastpos >= info.recpos && lastpos != HA_OFFSET_ERROR)
761  {
762  printf("mi_rrnd didn't advance filepointer; old: %ld, new: %ld\n",
763  (long) lastpos, (long) info.recpos);
764  goto err;
765  }
766  lastpos=info.recpos;
767  if (error == 0)
768  {
769  if (opt_delete == (uint) remove_count) /* While testing */
770  goto end;
771  if (mi_rsame(file,read_record,-1))
772  {
773  printf("can't find record %lx\n",(long) info.recpos);
774  goto err;
775  }
776  if (use_blob)
777  {
778  ulong blob_length,pos;
779  uchar *ptr;
780  longget(blob_length,read_record+blob_pos+4);
781  ptr=(uchar*) blob_length;
782  longget(blob_length,read_record+blob_pos);
783  for (pos=0 ; pos < blob_length ; pos++)
784  {
785  if (ptr[pos] != (uchar) (blob_length+pos))
786  {
787  printf("found blob with wrong info at %ld\n",(long) lastpos);
788  use_blob=0;
789  break;
790  }
791  }
792  }
793  if (mi_delete(file,read_record))
794  {
795  printf("can't delete record: %6.6s, delete_count: %d\n",
796  read_record, opt_delete);
797  goto err;
798  }
799  opt_delete++;
800  }
801  else
802  found_parts++;
803  }
804  if (my_errno != HA_ERR_END_OF_FILE && my_errno != HA_ERR_RECORD_DELETED)
805  printf("error: %d from mi_rrnd\n",my_errno);
806  if (write_count != opt_delete)
807  {
808  printf("Deleted only %d of %d records (%d parts)\n",opt_delete,write_count,
809  found_parts);
810  goto err;
811  }
812 end:
813  if (mi_close(file))
814  goto err;
815  mi_panic(HA_PANIC_CLOSE); /* Should close log */
816  if (!silent)
817  {
818  printf("\nFollowing test have been made:\n");
819  printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete);
820  if (rec_pointer_size)
821  printf("Record pointer size: %d\n",rec_pointer_size);
822  printf("myisam_block_size: %lu\n", myisam_block_size);
823  if (key_cacheing)
824  {
825  puts("Key cache used");
826  printf("key_cache_block_size: %u\n", key_cache_block_size);
827  if (write_cacheing)
828  puts("Key cache resized");
829  }
830  if (write_cacheing)
831  puts("Write cacheing used");
832  if (write_cacheing)
833  puts("quick mode");
834  if (async_io && locking)
835  puts("Asyncron io with locking used");
836  else if (locking)
837  puts("Locking used");
838  if (use_blob)
839  puts("blobs used");
840  printf("key cache status: \n\
841 blocks used:%10lu\n\
842 not flushed:%10lu\n\
843 w_requests: %10lu\n\
844 writes: %10lu\n\
845 r_requests: %10lu\n\
846 reads: %10lu\n",
847  dflt_key_cache->blocks_used,
848  dflt_key_cache->global_blocks_changed,
849  (ulong) dflt_key_cache->global_cache_w_requests,
850  (ulong) dflt_key_cache->global_cache_write,
851  (ulong) dflt_key_cache->global_cache_r_requests,
852  (ulong) dflt_key_cache->global_cache_read);
853  }
854  end_key_cache(dflt_key_cache,1);
855  if (blob_buffer)
856  my_free(blob_buffer);
857  my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO);
858  return(0);
859 err:
860  printf("got error: %d when using MyISAM-database\n",my_errno);
861  if (file)
862  (void) mi_close(file);
863  return(1);
864 } /* main */
865 
866 
867  /* l{ser optioner */
868  /* OBS! intierar endast DEBUG - ingen debuggning h{r ! */
869 
870 static void get_options(int argc, char **argv)
871 {
872  char *pos,*progname;
873 
874  progname= argv[0];
875 
876  while (--argc >0 && *(pos = *(++argv)) == '-' ) {
877  switch(*++pos) {
878  case 'B':
879  pack_type= HA_BINARY_PACK_KEY;
880  break;
881  case 'b':
882  use_blob=1;
883  break;
884  case 'K': /* Use key cacheing */
885  key_cacheing=1;
886  if (*++pos)
887  key_cache_size=atol(pos);
888  break;
889  case 'W': /* Use write cacheing */
890  write_cacheing=1;
891  if (*++pos)
892  my_default_record_cache_size=atoi(pos);
893  break;
894  case 'd':
895  remove_count= atoi(++pos);
896  break;
897  case 'i':
898  if (*++pos)
899  srand(atoi(pos));
900  break;
901  case 'l':
902  use_log=1;
903  break;
904  case 'L':
905  locking=1;
906  break;
907  case 'A': /* use asyncron io */
908  async_io=1;
909  if (*++pos)
910  my_default_record_cache_size=atoi(pos);
911  break;
912  case 'v': /* verbose */
913  verbose=1;
914  break;
915  case 'm': /* records */
916  if ((recant=atoi(++pos)) < 10)
917  {
918  fprintf(stderr,"record count must be >= 10\n");
919  exit(1);
920  }
921  break;
922  case 'e': /* myisam_block_length */
923  if ((myisam_block_size= atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
924  myisam_block_size > MI_MAX_KEY_BLOCK_LENGTH)
925  {
926  fprintf(stderr,"Wrong myisam_block_length\n");
927  exit(1);
928  }
929  myisam_block_size= my_round_up_to_next_power(myisam_block_size);
930  break;
931  case 'E': /* myisam_block_length */
932  if ((key_cache_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
933  key_cache_block_size > MI_MAX_KEY_BLOCK_LENGTH)
934  {
935  fprintf(stderr,"Wrong key_cache_block_size\n");
936  exit(1);
937  }
938  key_cache_block_size= my_round_up_to_next_power(key_cache_block_size);
939  break;
940  case 'f':
941  if ((first_key=atoi(++pos)) < 0 || first_key >= MYISAM_KEYS)
942  first_key=0;
943  break;
944  case 'k':
945  if ((keys=(uint) atoi(++pos)) < 1 ||
946  keys > (uint) (MYISAM_KEYS-first_key))
947  keys=MYISAM_KEYS-first_key;
948  break;
949  case 'P':
950  pack_type=0; /* Don't use DIFF_LENGTH */
951  pack_seg=0;
952  break;
953  case 'R': /* Length of record pointer */
954  rec_pointer_size=atoi(++pos);
955  if (rec_pointer_size > 7)
956  rec_pointer_size=0;
957  break;
958  case 'S':
959  pack_fields=0; /* Static-length-records */
960  break;
961  case 's':
962  silent=1;
963  break;
964  case 't':
965  testflag=atoi(++pos); /* testmod */
966  break;
967  case 'q':
968  opt_quick_mode=1;
969  break;
970  case 'c':
971  create_flag|= HA_CREATE_CHECKSUM;
972  break;
973  case 'D':
974  create_flag|=HA_CREATE_DELAY_KEY_WRITE;
975  break;
976  case '?':
977  case 'I':
978  case 'V':
979  printf("%s Ver 1.2 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
980  puts("By Monty, for your professional use\n");
981  printf("Usage: %s [-?AbBcDIKLPRqSsVWltv] [-k#] [-f#] [-m#] [-e#] [-E#] [-t#]\n",
982  progname);
983  exit(0);
984  case '#':
985  DBUG_PUSH (++pos);
986  break;
987  default:
988  printf("Illegal option: '%c'\n",*pos);
989  break;
990  }
991  }
992  return;
993 } /* get options */
994 
995  /* Get a random value 0 <= x <= n */
996 
997 static uint rnd(uint max_value)
998 {
999  return (uint) ((rand() & 32767)/32767.0*max_value);
1000 } /* rnd */
1001 
1002 
1003  /* Create a variable length record */
1004 
1005 static void fix_length(uchar *rec, uint length)
1006 {
1007  bmove(rec+STANDARD_LENGTH,
1008  "0123456789012345678901234567890123456789012345678901234567890",
1009  length-STANDARD_LENGTH);
1010  strfill((char*) rec+length,STANDARD_LENGTH+60-length,' ');
1011 } /* fix_length */
1012 
1013 
1014  /* Put maybe a blob in record */
1015 
1016 static void put_blob_in_record(uchar *blob_pos, char **blob_buffer)
1017 {
1018  ulong i,length;
1019  if (use_blob)
1020  {
1021  if (rnd(10) == 0)
1022  {
1023  if (! *blob_buffer &&
1024  !(*blob_buffer=my_malloc((uint) use_blob,MYF(MY_WME))))
1025  {
1026  use_blob=0;
1027  return;
1028  }
1029  length=rnd(use_blob);
1030  for (i=0 ; i < length ; i++)
1031  (*blob_buffer)[i]=(char) (length+i);
1032  int4store(blob_pos,length);
1033  memcpy(blob_pos+4, blob_buffer, sizeof(char*));
1034  }
1035  else
1036  {
1037  int4store(blob_pos,0);
1038  }
1039  }
1040  return;
1041 }
1042 
1043 
1044 static void copy_key(MI_INFO *info,uint inx,uchar *rec,uchar *key_buff)
1045 {
1046  HA_KEYSEG *keyseg;
1047 
1048  for (keyseg=info->s->keyinfo[inx].seg ; keyseg->type ; keyseg++)
1049  {
1050  memcpy(key_buff,rec+keyseg->start,(size_t) keyseg->length);
1051  key_buff+=keyseg->length;
1052  }
1053  return;
1054 }
1055 
1056 #include "mi_extrafunc.h"