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