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