1/*
2 Copyright (c) 2000, 2010, Oracle and/or its affiliates
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
17/* Test av isam-databas: stor test */
18
19#ifndef USE_MY_FUNC /* We want to be able to dbug this !! */
20#define USE_MY_FUNC
21#endif
22#include "myisamdef.h"
23#include <m_ctype.h>
24#include <my_bit.h>
25
26#define STANDARD_LENGTH 37
27#define MYISAM_KEYS 6
28#define MAX_PARTS 4
29
30static void get_options(int argc, char *argv[]);
31static uint rnd(uint max_value);
32static void fix_length(uchar *record,uint length);
33static void put_blob_in_record(uchar *blob_pos,char **blob_buffer);
34static void copy_key(struct st_myisam_info *info,uint inx,
35 uchar *record,uchar *key);
36
37static int verbose=0,testflag=0,
38 first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,do_locking=0,
39 rec_pointer_size=0,pack_fields=1,use_log=0,silent=0,
40 opt_quick_mode=0;
41static int pack_seg=HA_SPACE_PACK,pack_type=HA_PACK_KEY,remove_count=-1,
42 create_flag=0;
43static ulong key_cache_size=IO_SIZE*16;
44static uint key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
45
46static uint keys=MYISAM_KEYS,recant=1000;
47static uint use_blob=0;
48static uint16 key1[1001],key3[5000];
49static uchar record[300],record2[300],key[100],key2[100];
50static uchar read_record[300],read_record2[300],read_record3[300];
51static HA_KEYSEG glob_keyseg[MYISAM_KEYS][MAX_PARTS];
52
53 /* Test program */
54
55int main(int argc, char *argv[])
56{
57 uint i;
58 int j,n1,n2,n3,error,k;
59 uint write_count,update,dupp_keys,opt_delete,start,length,blob_pos,
60 reclength,ant,found_parts;
61 my_off_t lastpos;
62 ha_rows range_records,records;
63 MI_INFO *file;
64 MI_KEYDEF keyinfo[10];
65 MI_COLUMNDEF recinfo[10];
66 MI_ISAMINFO info;
67 const char *filename;
68 char *blob_buffer;
69 MI_CREATE_INFO create_info;
70 MY_INIT(argv[0]);
71
72 filename= "test2";
73 get_options(argc,argv);
74 if (! async_io)
75 my_disable_async_io=1;
76
77 reclength=STANDARD_LENGTH+60+(use_blob ? 8 : 0);
78 blob_pos=STANDARD_LENGTH+60;
79 keyinfo[0].seg= &glob_keyseg[0][0];
80 keyinfo[0].seg[0].start=0;
81 keyinfo[0].seg[0].length=6;
82 keyinfo[0].seg[0].type=HA_KEYTYPE_TEXT;
83 keyinfo[0].seg[0].language= default_charset_info->number;
84 keyinfo[0].seg[0].flag=(uint8) pack_seg;
85 keyinfo[0].seg[0].null_bit=0;
86 keyinfo[0].seg[0].null_pos=0;
87 keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
88 keyinfo[0].keysegs=1;
89 keyinfo[0].flag = pack_type;
90 keyinfo[0].block_length= 0; /* Default block length */
91 keyinfo[1].seg= &glob_keyseg[1][0];
92 keyinfo[1].seg[0].start=7;
93 keyinfo[1].seg[0].length=6;
94 keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY;
95 keyinfo[1].seg[0].flag=0;
96 keyinfo[1].seg[0].null_bit=0;
97 keyinfo[1].seg[0].null_pos=0;
98 keyinfo[1].seg[1].start=0; /* two part key */
99 keyinfo[1].seg[1].length=6;
100 keyinfo[1].seg[1].type=HA_KEYTYPE_NUM;
101 keyinfo[1].seg[1].flag=HA_REVERSE_SORT;
102 keyinfo[1].seg[1].null_bit=0;
103 keyinfo[1].seg[1].null_pos=0;
104 keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
105 keyinfo[1].keysegs=2;
106 keyinfo[1].flag =0;
107 keyinfo[1].block_length= MI_MIN_KEY_BLOCK_LENGTH; /* Diff blocklength */
108 keyinfo[2].seg= &glob_keyseg[2][0];
109 keyinfo[2].seg[0].start=12;
110 keyinfo[2].seg[0].length=8;
111 keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY;
112 keyinfo[2].seg[0].flag=HA_REVERSE_SORT;
113 keyinfo[2].seg[0].null_bit=0;
114 keyinfo[2].seg[0].null_pos=0;
115 keyinfo[2].key_alg=HA_KEY_ALG_BTREE;
116 keyinfo[2].keysegs=1;
117 keyinfo[2].flag =HA_NOSAME;
118 keyinfo[2].block_length= 0; /* Default block length */
119 keyinfo[3].seg= &glob_keyseg[3][0];
120 keyinfo[3].seg[0].start=0;
121 keyinfo[3].seg[0].length=reclength-(use_blob ? 8 : 0);
122 keyinfo[3].seg[0].type=HA_KEYTYPE_TEXT;
123 keyinfo[3].seg[0].language=default_charset_info->number;
124 keyinfo[3].seg[0].flag=(uint8) pack_seg;
125 keyinfo[3].seg[0].null_bit=0;
126 keyinfo[3].seg[0].null_pos=0;
127 keyinfo[3].key_alg=HA_KEY_ALG_BTREE;
128 keyinfo[3].keysegs=1;
129 keyinfo[3].flag = pack_type;
130 keyinfo[3].block_length= 0; /* Default block length */
131 keyinfo[4].seg= &glob_keyseg[4][0];
132 keyinfo[4].seg[0].start=0;
133 keyinfo[4].seg[0].length=5;
134 keyinfo[4].seg[0].type=HA_KEYTYPE_TEXT;
135 keyinfo[4].seg[0].language=default_charset_info->number;
136 keyinfo[4].seg[0].flag=0;
137 keyinfo[4].seg[0].null_bit=0;
138 keyinfo[4].seg[0].null_pos=0;
139 keyinfo[4].key_alg=HA_KEY_ALG_BTREE;
140 keyinfo[4].keysegs=1;
141 keyinfo[4].flag = pack_type;
142 keyinfo[4].block_length= 0; /* Default block length */
143 keyinfo[5].seg= &glob_keyseg[5][0];
144 keyinfo[5].seg[0].start=0;
145 keyinfo[5].seg[0].length=4;
146 keyinfo[5].seg[0].type=HA_KEYTYPE_TEXT;
147 keyinfo[5].seg[0].language=default_charset_info->number;
148 keyinfo[5].seg[0].flag=pack_seg;
149 keyinfo[5].seg[0].null_bit=0;
150 keyinfo[5].seg[0].null_pos=0;
151 keyinfo[5].key_alg=HA_KEY_ALG_BTREE;
152 keyinfo[5].keysegs=1;
153 keyinfo[5].flag = pack_type;
154 keyinfo[5].block_length= 0; /* Default block length */
155
156 recinfo[0].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
157 recinfo[0].length=7;
158 recinfo[0].null_bit=0;
159 recinfo[0].null_pos=0;
160 recinfo[1].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
161 recinfo[1].length=5;
162 recinfo[1].null_bit=0;
163 recinfo[1].null_pos=0;
164 recinfo[2].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
165 recinfo[2].length=9;
166 recinfo[2].null_bit=0;
167 recinfo[2].null_pos=0;
168 recinfo[3].type=FIELD_NORMAL;
169 recinfo[3].length=STANDARD_LENGTH-7-5-9-4;
170 recinfo[3].null_bit=0;
171 recinfo[3].null_pos=0;
172 recinfo[4].type=pack_fields ? FIELD_SKIP_ZERO : 0;
173 recinfo[4].length=4;
174 recinfo[4].null_bit=0;
175 recinfo[4].null_pos=0;
176 recinfo[5].type=pack_fields ? FIELD_SKIP_ENDSPACE : 0;
177 recinfo[5].length=60;
178 recinfo[5].null_bit=0;
179 recinfo[5].null_pos=0;
180 if (use_blob)
181 {
182 recinfo[6].type=FIELD_BLOB;
183 recinfo[6].length=4+portable_sizeof_char_ptr;
184 recinfo[6].null_bit=0;
185 recinfo[6].null_pos=0;
186 }
187
188 write_count=update=dupp_keys=opt_delete=0;
189 blob_buffer=0;
190
191 for (i=1000 ; i>0 ; i--) key1[i]=0;
192 for (i=4999 ; i>0 ; i--) key3[i]=0;
193
194 if (!silent)
195 printf("- Creating isam-file\n");
196 /* DBUG_PUSH(""); */
197 /* my_delete(filename,MYF(0)); */ /* Remove old locks under gdb */
198 file= 0;
199 bzero((char*) &create_info,sizeof(create_info));
200 create_info.max_rows=(ha_rows) (rec_pointer_size ?
201 (1L << (rec_pointer_size*8))/
202 reclength : 0);
203 create_info.reloc_rows=(ha_rows) 100;
204 if (mi_create(filename,keys,&keyinfo[first_key],
205 use_blob ? 7 : 6, &recinfo[0],
206 0,(MI_UNIQUEDEF*) 0,
207 &create_info,create_flag))
208 goto err;
209 if (use_log)
210 mi_log(1);
211 if (!(file=mi_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
212 goto err;
213 if (!silent)
214 printf("- Writing key:s\n");
215 if (key_cacheing)
216 init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0,
217 0, DEFAULT_KEY_CACHE_PARTITIONS);
218 if (do_locking)
219 mi_lock_database(file,F_WRLCK);
220 if (write_cacheing)
221 mi_extra(file,HA_EXTRA_WRITE_CACHE,0);
222 if (opt_quick_mode)
223 mi_extra(file,HA_EXTRA_QUICK,0);
224
225 for (i=0 ; i < recant ; i++)
226 {
227 n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
228 sprintf((char*) record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count);
229 int4store(record+STANDARD_LENGTH-4,(long) i);
230 fix_length(record,(uint) STANDARD_LENGTH+rnd(60));
231 put_blob_in_record(record+blob_pos,&blob_buffer);
232 DBUG_PRINT("test",("record: %d",i));
233
234 if (mi_write(file,record))
235 {
236 if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
237 {
238 printf("Error: %d in write at record: %d\n",my_errno,i);
239 goto err;
240 }
241 if (verbose) printf(" Double key: %d\n",n3);
242 }
243 else
244 {
245 if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3)
246 {
247 printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
248 goto err;
249 }
250 write_count++; key1[n1]++; key3[n3]=1;
251 }
252
253 /* Check if we can find key without flushing database */
254 if (i == recant/2)
255 {
256 for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
257 if (!j)
258 for (j=999 ; j>0 && key1[j] == 0 ; j--) ;
259 sprintf((char*) key,"%6d",j);
260 if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
261 {
262 printf("Test in loop: Can't find key: \"%s\"\n",key);
263 goto err;
264 }
265 }
266 }
267 if (testflag==1) goto end;
268
269 if (write_cacheing)
270 {
271 if (mi_extra(file,HA_EXTRA_NO_CACHE,0))
272 {
273 puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
274 goto end;
275 }
276 }
277 if (key_cacheing)
278 resize_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size*2,
279 0, 0, 0);
280
281 if (!silent)
282 printf("- Delete\n");
283 for (i=0 ; i<recant/10 ; i++)
284 {
285 for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
286 if (j != 0)
287 {
288 sprintf((char*) key,"%6d",j);
289 if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
290 {
291 printf("can't find key1: \"%s\"\n",key);
292 goto err;
293 }
294 if (opt_delete == (uint) remove_count) /* While testing */
295 goto end;
296 if (mi_delete(file,read_record))
297 {
298 printf("error: %d; can't delete record: \"%s\"\n", my_errno,read_record);
299 goto err;
300 }
301 opt_delete++;
302 key1[atoi((char*) read_record+keyinfo[0].seg[0].start)]--;
303 key3[atoi((char*) read_record+keyinfo[2].seg[0].start)]=0;
304 }
305 else
306 puts("Warning: Skipping delete test because no dupplicate keys");
307 }
308 if (testflag==2) goto end;
309
310 if (!silent)
311 printf("- Update\n");
312 for (i=0 ; i<recant/10 ; i++)
313 {
314 n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
315 sprintf((char*) record2,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update);
316 int4store(record2+STANDARD_LENGTH-4,(long) i);
317 fix_length(record2,(uint) STANDARD_LENGTH+rnd(60));
318
319 for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
320 if (j != 0)
321 {
322 sprintf((char*) key,"%6d",j);
323 if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
324 {
325 printf("can't find key1: \"%s\"\n",(char*) key);
326 goto err;
327 }
328 if (use_blob)
329 {
330 if (i & 1)
331 put_blob_in_record(record2+blob_pos,&blob_buffer);
332 else
333 bmove(record2+blob_pos,read_record+blob_pos,8);
334 }
335 if (mi_update(file,read_record,record2))
336 {
337 if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
338 {
339 printf("error: %d; can't update:\nFrom: \"%s\"\nTo: \"%s\"\n",
340 my_errno,read_record,record2);
341 goto err;
342 }
343 if (verbose)
344 printf("Double key when tried to update:\nFrom: \"%s\"\nTo: \"%s\"\n",record,record2);
345 }
346 else
347 {
348 key1[atoi((char*) read_record+keyinfo[0].seg[0].start)]--;
349 key3[atoi((char*) read_record+keyinfo[2].seg[0].start)]=0;
350 key1[n1]++; key3[n3]=1;
351 update++;
352 }
353 }
354 }
355 if (testflag == 3)
356 goto end;
357
358 for (i=999, dupp_keys=j=0 ; i>0 ; i--)
359 {
360 if (key1[i] > dupp_keys)
361 {
362 dupp_keys=key1[i]; j=i;
363 }
364 }
365 sprintf((char*) key,"%6d",j);
366 start=keyinfo[0].seg[0].start;
367 length=keyinfo[0].seg[0].length;
368 if (dupp_keys)
369 {
370 if (!silent)
371 printf("- Same key: first - next -> last - prev -> first\n");
372 DBUG_PRINT("progpos",("first - next -> last - prev -> first"));
373 if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys);
374
375 if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
376 goto err;
377 if (mi_rsame(file,read_record2,-1))
378 goto err;
379 if (memcmp(read_record,read_record2,reclength) != 0)
380 {
381 printf("mi_rsame didn't find same record\n");
382 goto end;
383 }
384 info.recpos=mi_position(file);
385 if (mi_rfirst(file,read_record2,0) ||
386 mi_rsame_with_pos(file,read_record2,0,info.recpos) ||
387 memcmp(read_record,read_record2,reclength) != 0)
388 {
389 printf("mi_rsame_with_pos didn't find same record\n");
390 goto end;
391 }
392 {
393 int skr=mi_rnext(file,read_record2,0);
394 if ((skr && my_errno != HA_ERR_END_OF_FILE) ||
395 mi_rprev(file,read_record2,-1) ||
396 memcmp(read_record,read_record2,reclength) != 0)
397 {
398 printf("mi_rsame_with_pos lost position\n");
399 goto end;
400 }
401 }
402 ant=1;
403 while (mi_rnext(file,read_record2,0) == 0 &&
404 memcmp(read_record2+start,key,length) == 0) ant++;
405 if (ant != dupp_keys)
406 {
407 printf("next: Found: %d keys of %d\n",ant,dupp_keys);
408 goto end;
409 }
410 ant=0;
411 while (mi_rprev(file,read_record3,0) == 0 &&
412 memcmp(read_record3+start,key,length) == 0) ant++;
413 if (ant != dupp_keys)
414 {
415 printf("prev: Found: %d records of %d\n",ant,dupp_keys);
416 goto end;
417 }
418
419 /* Check of mi_rnext_same */
420 if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
421 goto err;
422 ant=1;
423 while (!mi_rnext_same(file,read_record3) && ant < dupp_keys+10)
424 ant++;
425 if (ant != dupp_keys || my_errno != HA_ERR_END_OF_FILE)
426 {
427 printf("mi_rnext_same: Found: %d records of %d\n",ant,dupp_keys);
428 goto end;
429 }
430 }
431
432 if (!silent)
433 printf("- All keys: first - next -> last - prev -> first\n");
434 DBUG_PRINT("progpos",("All keys: first - next -> last - prev -> first"));
435 ant=1;
436 if (mi_rfirst(file,read_record,0))
437 {
438 printf("Can't find first record\n");
439 goto end;
440 }
441 while ((error=mi_rnext(file,read_record3,0)) == 0 && ant < write_count+10)
442 ant++;
443 if (ant != write_count - opt_delete || error != HA_ERR_END_OF_FILE)
444 {
445 printf("next: I found: %d records of %d (error: %d)\n",
446 ant, write_count - opt_delete, error);
447 goto end;
448 }
449 if (mi_rlast(file,read_record2,0) ||
450 memcmp(read_record2,read_record3,reclength))
451 {
452 printf("Can't find last record\n");
453 DBUG_DUMP("record2",(uchar*) read_record2,reclength);
454 DBUG_DUMP("record3",(uchar*) read_record3,reclength);
455 goto end;
456 }
457 ant=1;
458 while (mi_rprev(file,read_record3,0) == 0 && ant < write_count+10)
459 ant++;
460 if (ant != write_count - opt_delete)
461 {
462 printf("prev: I found: %d records of %d\n",ant,write_count);
463 goto end;
464 }
465 if (memcmp(read_record,read_record3,reclength))
466 {
467 printf("Can't find first record\n");
468 goto end;
469 }
470
471 if (!silent)
472 printf("- Test if: Read first - next - prev - prev - next == first\n");
473 DBUG_PRINT("progpos",("- Read first - next - prev - prev - next == first"));
474 if (mi_rfirst(file,read_record,0) ||
475 mi_rnext(file,read_record3,0) ||
476 mi_rprev(file,read_record3,0) ||
477 mi_rprev(file,read_record3,0) == 0 ||
478 mi_rnext(file,read_record3,0))
479 goto err;
480 if (memcmp(read_record,read_record3,reclength) != 0)
481 printf("Can't find first record\n");
482
483 if (!silent)
484 printf("- Test if: Read last - prev - next - next - prev == last\n");
485 DBUG_PRINT("progpos",("Read last - prev - next - next - prev == last"));
486 if (mi_rlast(file,read_record2,0) ||
487 mi_rprev(file,read_record3,0) ||
488 mi_rnext(file,read_record3,0) ||
489 mi_rnext(file,read_record3,0) == 0 ||
490 mi_rprev(file,read_record3,0))
491 goto err;
492 if (memcmp(read_record2,read_record3,reclength))
493 printf("Can't find last record\n");
494#ifdef NOT_ANYMORE
495 if (!silent)
496 puts("- Test read key-part");
497 strmov(key2,key);
498 for(i=strlen(key2) ; i-- > 1 ;)
499 {
500 key2[i]=0;
501
502 /* The following row is just to catch some bugs in the key code */
503 bzero((char*) file->lastkey,file->s->base.max_key_length*2);
504 if (mi_rkey(file,read_record,0,key2,(uint) i,HA_READ_PREFIX))
505 goto err;
506 if (memcmp(read_record+start,key,(uint) i))
507 {
508 puts("Didn't find right record");
509 goto end;
510 }
511 }
512#endif
513 if (dupp_keys > 2)
514 {
515 if (!silent)
516 printf("- Read key (first) - next - delete - next -> last\n");
517 DBUG_PRINT("progpos",("first - next - delete - next -> last"));
518 if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
519 goto err;
520 if (mi_rnext(file,read_record3,0)) goto err;
521 if (mi_delete(file,read_record3)) goto err;
522 opt_delete++;
523 ant=1;
524 while (mi_rnext(file,read_record3,0) == 0 &&
525 memcmp(read_record3+start,key,length) == 0) ant++;
526 if (ant != dupp_keys-1)
527 {
528 printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1);
529 goto end;
530 }
531 }
532 if (dupp_keys>4)
533 {
534 if (!silent)
535 printf("- Read last of key - prev - delete - prev -> first\n");
536 DBUG_PRINT("progpos",("last - prev - delete - prev -> first"));
537 if (mi_rprev(file,read_record3,0)) goto err;
538 if (mi_rprev(file,read_record3,0)) goto err;
539 if (mi_delete(file,read_record3)) goto err;
540 opt_delete++;
541 ant=1;
542 while (mi_rprev(file,read_record3,0) == 0 &&
543 memcmp(read_record3+start,key,length) == 0) ant++;
544 if (ant != dupp_keys-2)
545 {
546 printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2);
547 goto end;
548 }
549 }
550 if (dupp_keys > 6)
551 {
552 if (!silent)
553 printf("- Read first - delete - next -> last\n");
554 DBUG_PRINT("progpos",("first - delete - next -> last"));
555 if (mi_rkey(file,read_record3,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
556 goto err;
557 if (mi_delete(file,read_record3)) goto err;
558 opt_delete++;
559 ant=1;
560 if (mi_rnext(file,read_record,0))
561 goto err; /* Skall finnas poster */
562 while (mi_rnext(file,read_record3,0) == 0 &&
563 memcmp(read_record3+start,key,length) == 0) ant++;
564 if (ant != dupp_keys-3)
565 {
566 printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3);
567 goto end;
568 }
569
570 if (!silent)
571 printf("- Read last - delete - prev -> first\n");
572 DBUG_PRINT("progpos",("last - delete - prev -> first"));
573 if (mi_rprev(file,read_record3,0)) goto err;
574 if (mi_delete(file,read_record3)) goto err;
575 opt_delete++;
576 ant=0;
577 while (mi_rprev(file,read_record3,0) == 0 &&
578 memcmp(read_record3+start,key,length) == 0) ant++;
579 if (ant != dupp_keys-4)
580 {
581 printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4);
582 goto end;
583 }
584 }
585
586 if (!silent)
587 puts("- Test if: Read rrnd - same");
588 DBUG_PRINT("progpos",("Read rrnd - same"));
589 for (i=0 ; i < write_count ; i++)
590 {
591 if (mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR) == 0)
592 break;
593 }
594 if (i == write_count)
595 goto err;
596
597 bmove(read_record2,read_record,reclength);
598 for (i=MY_MIN(2,keys) ; i-- > 0 ;)
599 {
600 if (mi_rsame(file,read_record2,(int) i)) goto err;
601 if (memcmp(read_record,read_record2,reclength) != 0)
602 {
603 printf("mi_rsame didn't find same record\n");
604 goto end;
605 }
606 }
607 if (!silent)
608 puts("- Test mi_records_in_range");
609 mi_status(file,&info,HA_STATUS_VARIABLE);
610 for (i=0 ; i < info.keys ; i++)
611 {
612 key_range min_key, max_key;
613 if (mi_rfirst(file,read_record,(int) i) ||
614 mi_rlast(file,read_record2,(int) i))
615 goto err;
616 copy_key(file,(uint) i,(uchar*) read_record,(uchar*) key);
617 copy_key(file,(uint) i,(uchar*) read_record2,(uchar*) key2);
618 min_key.key= key;
619 min_key.keypart_map= HA_WHOLE_KEY;
620 min_key.flag= HA_READ_KEY_EXACT;
621 max_key.key= key2;
622 max_key.keypart_map= HA_WHOLE_KEY;
623 max_key.flag= HA_READ_AFTER_KEY;
624
625 range_records= mi_records_in_range(file,(int) i, &min_key, &max_key);
626 if (range_records < info.records*8/10 ||
627 range_records > info.records*12/10)
628 {
629 printf("mi_records_range returned %ld; Should be about %ld\n",
630 (long) range_records,(long) info.records);
631 goto end;
632 }
633 if (verbose)
634 {
635 printf("mi_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n",
636 (long) range_records, (long) info.records,
637 labs((long) range_records - (long) info.records)*100.0/
638 info.records);
639 }
640 }
641 for (i=0 ; i < 5 ; i++)
642 {
643 for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
644 for (k=rnd(1000)+1 ; k>0 && key1[k] == 0 ; k--) ;
645 if (j != 0 && k != 0)
646 {
647 key_range min_key, max_key;
648 if (j > k)
649 swap_variables(int, j, k);
650 sprintf((char*) key,"%6d",j);
651 sprintf((char*) key2,"%6d",k);
652
653 min_key.key= key;
654 min_key.keypart_map= HA_WHOLE_KEY;
655 min_key.flag= HA_READ_AFTER_KEY;
656 max_key.key= key2;
657 max_key.keypart_map= HA_WHOLE_KEY;
658 max_key.flag= HA_READ_BEFORE_KEY;
659 range_records= mi_records_in_range(file, 0, &min_key, &max_key);
660 records=0;
661 for (j++ ; j < k ; j++)
662 records+=key1[j];
663 if ((long) range_records < (long) records*7/10-2 ||
664 (long) range_records > (long) records*14/10+2)
665 {
666 printf("mi_records_range for key: %d returned %lu; Should be about %lu\n",
667 i, (ulong) range_records, (ulong) records);
668 goto end;
669 }
670 if (verbose && records)
671 {
672 printf("mi_records_range returned %lu; Exact is %lu (diff: %4.2g %%)\n",
673 (ulong) range_records, (ulong) records,
674 labs((long) range_records-(long) records)*100.0/records);
675
676 }
677 }
678 }
679
680 if (!silent)
681 printf("- mi_info\n");
682 mi_status(file,&info,HA_STATUS_VARIABLE | HA_STATUS_CONST);
683 if (info.records != write_count-opt_delete || info.deleted > opt_delete + update
684 || info.keys != keys)
685 {
686 puts("Wrong info from mi_info");
687 printf("Got: records: %lu delete: %lu i_keys: %d\n",
688 (ulong) info.records, (ulong) info.deleted, info.keys);
689 }
690 if (verbose)
691 {
692 char buff[80];
693 get_date(buff,3,info.create_time);
694 printf("info: Created %s\n",buff);
695 get_date(buff,3,info.check_time);
696 printf("info: checked %s\n",buff);
697 get_date(buff,3,info.update_time);
698 printf("info: Modified %s\n",buff);
699 }
700
701 mi_panic(HA_PANIC_WRITE);
702 mi_panic(HA_PANIC_READ);
703 if (mi_is_changed(file))
704 puts("Warning: mi_is_changed reported that datafile was changed");
705
706 if (!silent)
707 printf("- mi_extra(CACHE) + mi_rrnd.... + mi_extra(NO_CACHE)\n");
708 if (mi_reset(file) || mi_extra(file,HA_EXTRA_CACHE,0))
709 {
710 if (do_locking || (!use_blob && !pack_fields))
711 {
712 puts("got error from mi_extra(HA_EXTRA_CACHE)");
713 goto end;
714 }
715 }
716 ant=0;
717 while ((error=mi_rrnd(file,record,HA_OFFSET_ERROR)) != HA_ERR_END_OF_FILE &&
718 ant < write_count + 10)
719 ant+= error ? 0 : 1;
720 if (ant != write_count-opt_delete)
721 {
722 printf("rrnd with cache: I can only find: %d records of %d\n",
723 ant,write_count-opt_delete);
724 goto end;
725 }
726 if (mi_extra(file,HA_EXTRA_NO_CACHE,0))
727 {
728 puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
729 goto end;
730 }
731
732 ant=0;
733 mi_scan_init(file);
734 while ((error=mi_scan(file,record)) != HA_ERR_END_OF_FILE &&
735 ant < write_count + 10)
736 ant+= error ? 0 : 1;
737 if (ant != write_count-opt_delete)
738 {
739 printf("scan with cache: I can only find: %d records of %d\n",
740 ant,write_count-opt_delete);
741 goto end;
742 }
743
744 if (testflag == 4) goto end;
745
746 if (!silent)
747 printf("- Removing keys\n");
748 DBUG_PRINT("progpos",("Removing keys"));
749 lastpos = HA_OFFSET_ERROR;
750 /* DBUG_POP(); */
751 mi_reset(file);
752 found_parts=0;
753 while ((error=mi_rrnd(file,read_record,HA_OFFSET_ERROR)) !=
754 HA_ERR_END_OF_FILE)
755 {
756 info.recpos=mi_position(file);
757 if (lastpos >= info.recpos && lastpos != HA_OFFSET_ERROR)
758 {
759 printf("mi_rrnd didn't advance filepointer; old: %ld, new: %ld\n",
760 (long) lastpos, (long) info.recpos);
761 goto err;
762 }
763 lastpos=info.recpos;
764 if (error == 0)
765 {
766 if (opt_delete == (uint) remove_count) /* While testing */
767 goto end;
768 if (mi_rsame(file,read_record,-1))
769 {
770 printf("can't find record %lx\n",(long) info.recpos);
771 goto err;
772 }
773 if (use_blob)
774 {
775 ulong blob_length,pos;
776 uchar *ptr;
777 memcpy(&ptr, read_record+blob_pos+4, sizeof(ptr));
778 blob_length= uint4korr(read_record+blob_pos);
779 for (pos=0 ; pos < blob_length ; pos++)
780 {
781 if (ptr[pos] != (uchar) (blob_length+pos))
782 {
783 printf("found blob with wrong info at %ld\n",(long) lastpos);
784 use_blob=0;
785 break;
786 }
787 }
788 }
789 if (mi_delete(file,read_record))
790 {
791 printf("can't delete record: %6.6s, delete_count: %d\n",
792 read_record, opt_delete);
793 goto err;
794 }
795 opt_delete++;
796 }
797 else
798 found_parts++;
799 }
800 if (my_errno != HA_ERR_END_OF_FILE && my_errno != HA_ERR_RECORD_DELETED)
801 printf("error: %d from mi_rrnd\n",my_errno);
802 if (write_count != opt_delete)
803 {
804 printf("Deleted only %d of %d records (%d parts)\n",opt_delete,write_count,
805 found_parts);
806 goto err;
807 }
808end:
809 if (mi_close(file))
810 goto err;
811 mi_panic(HA_PANIC_CLOSE); /* Should close log */
812 if (!silent)
813 {
814 KEY_CACHE_STATISTICS stats;
815
816 printf("\nFollowing test have been made:\n");
817 printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete);
818 if (rec_pointer_size)
819 printf("Record pointer size: %d\n",rec_pointer_size);
820 printf("myisam_block_size: %lu\n", myisam_block_size);
821 if (key_cacheing)
822 {
823 puts("Key cache used");
824 printf("key_cache_block_size: %u\n", key_cache_block_size);
825 if (write_cacheing)
826 puts("Key cache resized");
827 }
828 if (write_cacheing)
829 puts("Write cacheing used");
830 if (write_cacheing)
831 puts("quick mode");
832 if (async_io && do_locking)
833 puts("Asyncron io with locking used");
834 else if (do_locking)
835 puts("Locking used");
836 if (use_blob)
837 puts("blobs used");
838 bzero(&stats, sizeof(stats));
839 get_key_cache_statistics(dflt_key_cache, 0, &stats);
840 printf("key cache status: \n\
841blocks used:%10lu\n\
842not flushed:%10lu\n\
843w_requests: %10lu\n\
844writes: %10lu\n\
845r_requests: %10lu\n\
846reads: %10lu\n",
847 (ulong) stats.blocks_used,
848 (ulong) stats.blocks_changed,
849 (ulong) stats.write_requests,
850 (ulong) stats.writes,
851 (ulong) stats.read_requests,
852 (ulong) stats.reads);
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);
859err:
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
870static 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 do_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
997static 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
1005static 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
1016static 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
1044static 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"
1057