1 /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
2 reserved
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, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24 /* Test av isam-databas: stor test */
25
26 #include "heapdef.h" /* Because of hp_find_block */
27 #include <signal.h>
28
29 #define MAX_RECORDS 100000
30 #define MAX_KEYS 4
31
32 static int get_options(int argc, char *argv[]);
33 static int rnd(int max_value);
34 static sig_handler endprog(int sig_number);
35
36 static uint flag=0,verbose=0,testflag=0,recant=10000,silent=0;
37 static uint keys=MAX_KEYS;
38 static uint16 key1[1001];
39 static my_bool key3[MAX_RECORDS];
40 static int reclength=39;
41
42
43 static int calc_check(uchar *buf,uint length);
44 static void make_record(uchar *record, uint n1, uint n2, uint n3,
45 const char *mark, uint count);
46
47 /* Main program */
48
main(int argc,char * argv[])49 int main(int argc, char *argv[])
50 {
51 register uint i,j;
52 uint ant,n1,n2,n3;
53 uint write_count,update,opt_delete,check2,dupp_keys,found_key;
54 int error;
55 ulong pos;
56 unsigned long key_check;
57 uchar record[128],record2[128],record3[128],key[10];
58 const char *filename,*filename2;
59 HP_INFO *file,*file2;
60 HP_SHARE *tmp_share;
61 HP_KEYDEF keyinfo[MAX_KEYS];
62 HA_KEYSEG keyseg[MAX_KEYS*5];
63 HEAP_PTR UNINIT_VAR(position);
64 HP_CREATE_INFO hp_create_info;
65 CHARSET_INFO *cs= &my_charset_latin1;
66 my_bool unused;
67 MY_INIT(argv[0]); /* init my_sys library & pthreads */
68
69 filename= "test2";
70 filename2= "test2_2";
71 file=file2=0;
72 get_options(argc,argv);
73
74 memset(&hp_create_info, 0, sizeof(hp_create_info));
75 hp_create_info.max_table_size= 1024L*1024L;
76 hp_create_info.keys= keys;
77 hp_create_info.keydef= keyinfo;
78 hp_create_info.reclength= reclength;
79 hp_create_info.max_records= (ulong) flag*100000L;
80 hp_create_info.min_records= (ulong) recant/2;
81
82 write_count=update=opt_delete=0;
83 key_check=0;
84
85 keyinfo[0].seg=keyseg;
86 keyinfo[0].keysegs=1;
87 keyinfo[0].flag= 0;
88 keyinfo[0].algorithm= HA_KEY_ALG_HASH;
89 keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY;
90 keyinfo[0].seg[0].start=0;
91 keyinfo[0].seg[0].length=6;
92 keyinfo[0].seg[0].null_bit=0;
93 keyinfo[0].seg[0].charset=cs;
94 keyinfo[1].seg=keyseg+1;
95 keyinfo[1].keysegs=2;
96 keyinfo[1].flag=0;
97 keyinfo[1].algorithm= HA_KEY_ALG_HASH;
98 keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY;
99 keyinfo[1].seg[0].start=7;
100 keyinfo[1].seg[0].length=6;
101 keyinfo[1].seg[0].null_bit=0;
102 keyinfo[1].seg[0].charset=cs;
103 keyinfo[1].seg[1].type=HA_KEYTYPE_TEXT;
104 keyinfo[1].seg[1].start=0; /* key in two parts */
105 keyinfo[1].seg[1].length=6;
106 keyinfo[1].seg[1].null_bit=0;
107 keyinfo[1].seg[1].charset=cs;
108 keyinfo[2].seg=keyseg+3;
109 keyinfo[2].keysegs=1;
110 keyinfo[2].flag=HA_NOSAME;
111 keyinfo[2].algorithm= HA_KEY_ALG_HASH;
112 keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY;
113 keyinfo[2].seg[0].start=12;
114 keyinfo[2].seg[0].length=8;
115 keyinfo[2].seg[0].null_bit=0;
116 keyinfo[2].seg[0].charset=cs;
117 keyinfo[3].seg=keyseg+4;
118 keyinfo[3].keysegs=1;
119 keyinfo[3].flag=HA_NOSAME;
120 keyinfo[3].algorithm= HA_KEY_ALG_HASH;
121 keyinfo[3].seg[0].type=HA_KEYTYPE_BINARY;
122 keyinfo[3].seg[0].start=37;
123 keyinfo[3].seg[0].length=1;
124 keyinfo[3].seg[0].null_bit=1;
125 keyinfo[3].seg[0].null_pos=38;
126 keyinfo[3].seg[0].charset=cs;
127
128 memset(key1, 0, sizeof(key1));
129 memset(key3, 0, sizeof(key3));
130
131 printf("- Creating heap-file\n");
132 if (heap_create(filename, &hp_create_info, &tmp_share, &unused) ||
133 !(file= heap_open(filename, 2)))
134 goto err;
135 signal(SIGINT,endprog);
136
137 printf("- Writing records:s\n");
138 strmov((char*) record," ..... key");
139
140 for (i=0 ; i < recant ; i++)
141 {
142 n1= rnd(1000);
143 n2= rnd(100);
144 n3= rnd(MY_MIN(recant * 5, MAX_RECORDS));
145 make_record(record,n1,n2,n3,"Pos",write_count);
146
147 if (heap_write(file,record))
148 {
149 if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
150 {
151 printf("Error: %d in write at record: %d\n",my_errno,i);
152 goto err;
153 }
154 if (verbose) printf(" Double key: %d\n",n3);
155 }
156 else
157 {
158 if (key3[n3] == 1)
159 {
160 printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
161 goto err;
162 }
163 write_count++; key1[n1]++; key3[n3]=1;
164 key_check+=n1;
165 }
166 if (testflag == 1 && heap_check_heap(file,0))
167 {
168 puts("Heap keys crashed");
169 goto err;
170 }
171 }
172 if (testflag == 1)
173 goto end;
174 if (heap_check_heap(file,0))
175 {
176 puts("Heap keys crashed");
177 goto err;
178 }
179
180 printf("- Delete\n");
181 for (i=0 ; i < write_count/10 ; i++)
182 {
183 for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
184 if (j != 0)
185 {
186 sprintf((char*) key,"%6d",j);
187 if (heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT))
188 {
189 printf("can't find key1: \"%s\"\n",(char*) key);
190 goto err;
191 }
192 if (heap_delete(file,record))
193 {
194 printf("error: %d; can't delete record: \"%s\"\n", my_errno,(char*) record);
195 goto err;
196 }
197 opt_delete++;
198 key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
199 key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
200 key_check-=atoi((char*) record);
201 if (testflag == 2 && heap_check_heap(file,0))
202 {
203 puts("Heap keys crashed");
204 goto err;
205 }
206 }
207 else
208 puts("Warning: Skipping delete test because no dupplicate keys");
209 }
210 if (testflag==2) goto end;
211 if (heap_check_heap(file,0))
212 {
213 puts("Heap keys crashed");
214 goto err;
215 }
216
217 printf("- Update\n");
218 for (i=0 ; i < write_count/10 ; i++)
219 {
220 n1= rnd(1000);
221 n2= rnd(100);
222 n3= rnd(MY_MIN(recant * 2, MAX_RECORDS));
223 make_record(record2, n1, n2, n3, "XXX", update);
224 if (rnd(2) == 1)
225 {
226 if (heap_scan_init(file))
227 goto err;
228 j=rnd(write_count-opt_delete);
229 while ((error=heap_scan(file,record) == HA_ERR_RECORD_DELETED) ||
230 (!error && j))
231 {
232 if (!error)
233 j--;
234 }
235 if (error)
236 goto err;
237 }
238 else
239 {
240 for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
241 if (!key1[j])
242 continue;
243 sprintf((char*) key,"%6d",j);
244 if (heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT))
245 {
246 printf("can't find key1: \"%s\"\n",(char*) key);
247 goto err;
248 }
249 }
250 if (heap_update(file,record,record2))
251 {
252 if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
253 {
254 printf("error: %d; can't update:\nFrom: \"%s\"\nTo: \"%s\"\n",
255 my_errno,(char*) record, (char*) record2);
256 goto err;
257 }
258 if (verbose)
259 printf("Double key when tried to update:\nFrom: \"%s\"\nTo: \"%s\"\n",
260 (char*) record, (char*) record2);
261 }
262 else
263 {
264 key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
265 key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
266 key1[n1]++; key3[n3]=1;
267 update++;
268 key_check=key_check-atoi((char*) record)+n1;
269 }
270 if (testflag == 3 && heap_check_heap(file,0))
271 {
272 puts("Heap keys crashed");
273 goto err;
274 }
275 }
276 if (testflag == 3) goto end;
277 if (heap_check_heap(file,0))
278 {
279 puts("Heap keys crashed");
280 goto err;
281 }
282
283 for (i=999, dupp_keys=found_key=0 ; i>0 ; i--)
284 {
285 if (key1[i] > dupp_keys) { dupp_keys=key1[i]; found_key=i; }
286 sprintf((char*) key,"%6d",found_key);
287 }
288
289 if (dupp_keys > 3)
290 {
291 if (!silent)
292 printf("- Read first key - next - delete - next -> last\n");
293 DBUG_PRINT("progpos",("first - next - delete - next -> last"));
294
295 if (heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT))
296 goto err;
297 if (heap_rnext(file,record3)) goto err;
298 if (heap_delete(file,record3)) goto err;
299 key_check-=atoi((char*) record3);
300 key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
301 key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
302 opt_delete++;
303 ant=2;
304 while ((error=heap_rnext(file,record3)) == 0 ||
305 error == HA_ERR_RECORD_DELETED)
306 if (! error)
307 ant++;
308 if (ant != dupp_keys)
309 {
310 printf("next: I can only find: %d records of %d\n",
311 ant,dupp_keys);
312 goto end;
313 }
314 dupp_keys--;
315 if (heap_check_heap(file,0))
316 {
317 puts("Heap keys crashed");
318 goto err;
319 }
320
321 if (!silent)
322 printf("- Read last key - delete - prev - prev - opt_delete - prev -> first\n");
323
324 if (heap_rlast(file,record3,0)) goto err;
325 if (heap_delete(file,record3)) goto err;
326 key_check-=atoi((char*) record3);
327 key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
328 key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
329 opt_delete++;
330 if (heap_rprev(file,record3) || heap_rprev(file,record3))
331 goto err;
332 if (heap_delete(file,record3)) goto err;
333 key_check-=atoi((char*) record3);
334 key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
335 key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
336 opt_delete++;
337 ant=3;
338 while ((error=heap_rprev(file,record3)) == 0 ||
339 error == HA_ERR_RECORD_DELETED)
340 {
341 if (! error)
342 ant++;
343 }
344 if (ant != dupp_keys)
345 {
346 printf("next: I can only find: %d records of %d\n",
347 ant,dupp_keys);
348 goto end;
349 }
350 dupp_keys-=2;
351 if (heap_check_heap(file,0))
352 {
353 puts("Heap keys crashed");
354 goto err;
355 }
356 }
357 else
358 puts("Warning: Not enough duplicated keys: Skipping delete key check");
359
360 if (!silent)
361 printf("- Read (first) - next - delete - next -> last\n");
362 DBUG_PRINT("progpos",("first - next - delete - next -> last"));
363
364 if (heap_scan_init(file))
365 goto err;
366 while ((error=heap_scan(file,record3) == HA_ERR_RECORD_DELETED)) ;
367 if (error)
368 goto err;
369 if (heap_delete(file,record3)) goto err;
370 key_check-=atoi((char*) record3);
371 opt_delete++;
372 key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
373 key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
374 ant=0;
375 while ((error=heap_scan(file,record3)) == 0 ||
376 error == HA_ERR_RECORD_DELETED)
377 if (! error)
378 ant++;
379 if (ant != write_count-opt_delete)
380 {
381 printf("next: Found: %d records of %d\n",ant,write_count-opt_delete);
382 goto end;
383 }
384 if (heap_check_heap(file,0))
385 {
386 puts("Heap keys crashed");
387 goto err;
388 }
389
390 puts("- Test if: Read rrnd - same - rkey - same");
391 DBUG_PRINT("progpos",("Read rrnd - same"));
392 pos=rnd(write_count-opt_delete-5)+5;
393 heap_scan_init(file);
394 i=5;
395 while ((error=heap_scan(file,record)) == HA_ERR_RECORD_DELETED ||
396 (error == 0 && pos))
397 {
398 if (!error)
399 pos--;
400 if (!error && (i-- == 0))
401 {
402 bmove(record3,record,reclength);
403 position=heap_position(file);
404 }
405 }
406 if (error)
407 goto err;
408 bmove(record2,record,reclength);
409 if (heap_rsame(file,record,-1) || heap_rsame(file,record2,2))
410 goto err;
411 if (memcmp(record2,record,reclength))
412 {
413 puts("heap_rsame didn't find right record");
414 goto end;
415 }
416
417 puts("- Test of read through position");
418 if (heap_rrnd(file,record,position))
419 goto err;
420 if (memcmp(record3,record,reclength))
421 {
422 puts("heap_frnd didn't find right record");
423 goto end;
424 }
425
426 printf("- heap_info\n");
427 {
428 HEAPINFO info;
429 heap_info(file,&info,0);
430 /* We have to test with opt_delete +1 as this may be the case if the last
431 inserted row was a duplicate key */
432 if (info.records != write_count-opt_delete ||
433 (info.deleted != opt_delete && info.deleted != opt_delete+1))
434 {
435 puts("Wrong info from heap_info");
436 printf("Got: records: %ld(%d) deleted: %ld(%d)\n",
437 info.records,write_count-opt_delete,info.deleted,opt_delete);
438 }
439 }
440
441 #ifdef OLD_HEAP_VERSION
442 {
443 uint check;
444 printf("- Read through all records with rnd\n");
445 if (heap_extra(file,HA_EXTRA_RESET) || heap_extra(file,HA_EXTRA_CACHE))
446 {
447 puts("got error from heap_extra");
448 goto end;
449 }
450 ant=check=0;
451 while ((error=heap_rrnd(file,record,(ulong) -1)) != HA_ERR_END_OF_FILE &&
452 ant < write_count + 10)
453 {
454 if (!error)
455 {
456 ant++;
457 check+=calc_check(record,reclength);
458 }
459 }
460 if (ant != write_count-opt_delete)
461 {
462 printf("rrnd: I can only find: %d records of %d\n", ant,
463 write_count-opt_delete);
464 goto end;
465 }
466 if (heap_extra(file,HA_EXTRA_NO_CACHE))
467 {
468 puts("got error from heap_extra(HA_EXTRA_NO_CACHE)");
469 goto end;
470 }
471 }
472 #endif
473
474 printf("- Read through all records with scan\n");
475 if (heap_reset(file) || heap_extra(file,HA_EXTRA_CACHE))
476 {
477 puts("got error from heap_extra");
478 goto end;
479 }
480 ant=check2=0;
481 heap_scan_init(file);
482 while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE &&
483 ant < write_count + 10)
484 {
485 if (!error)
486 {
487 ant++;
488 check2+=calc_check(record,reclength);
489 }
490 }
491 if (ant != write_count-opt_delete)
492 {
493 printf("scan: I can only find: %d records of %d\n", ant,
494 write_count-opt_delete);
495 goto end;
496 }
497 #ifdef OLD_HEAP_VERSION
498 if (check != check2)
499 {
500 puts("scan: Checksum didn't match reading with rrnd");
501 goto end;
502 }
503 #endif
504
505
506 if (heap_extra(file,HA_EXTRA_NO_CACHE))
507 {
508 puts("got error from heap_extra(HA_EXTRA_NO_CACHE)");
509 goto end;
510 }
511
512 for (i=999, dupp_keys=found_key=0 ; i>0 ; i--)
513 {
514 if (key1[i] > dupp_keys) { dupp_keys=key1[i]; found_key=i; }
515 sprintf((char*) key,"%6d",found_key);
516 }
517 printf("- Read through all keys with first-next-last-prev\n");
518 ant=0;
519 for (error=heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT);
520 ! error ;
521 error=heap_rnext(file,record))
522 ant++;
523 if (ant != dupp_keys)
524 {
525 printf("first-next: I can only find: %d records of %d\n", ant,
526 dupp_keys);
527 goto end;
528 }
529
530 ant=0;
531 for (error=heap_rlast(file,record,0) ;
532 ! error ;
533 error=heap_rprev(file,record))
534 {
535 ant++;
536 check2+=calc_check(record,reclength);
537 }
538 if (ant != dupp_keys)
539 {
540 printf("last-prev: I can only find: %d records of %d\n", ant,
541 dupp_keys);
542 goto end;
543 }
544
545 if (testflag == 4) goto end;
546
547 printf("- Reading through all rows through keys\n");
548 if (!(file2=heap_open(filename, 2)))
549 goto err;
550 if (heap_scan_init(file))
551 goto err;
552 while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE)
553 {
554 if (error == 0)
555 {
556 if (heap_rkey(file2,record2,2,record+keyinfo[2].seg[0].start,8,
557 HA_READ_KEY_EXACT))
558 {
559 printf("can't find key3: \"%.8s\"\n",
560 record+keyinfo[2].seg[0].start);
561 goto err;
562 }
563 }
564 }
565 heap_close(file2);
566
567 printf("- Creating output heap-file 2\n");
568 hp_create_info.keys= 1;
569 hp_create_info.max_records= 0;
570 hp_create_info.min_records= 0;
571 if (heap_create(filename2, &hp_create_info, &tmp_share, &unused) ||
572 !(file2= heap_open_from_share_and_register(tmp_share, 2)))
573 goto err;
574
575 printf("- Copying and removing records\n");
576 if (heap_scan_init(file))
577 goto err;
578 while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE)
579 {
580 if (error == 0)
581 {
582 if (heap_write(file2,record))
583 goto err;
584 key_check-=atoi((char*) record);
585 write_count++;
586 if (heap_delete(file,record))
587 goto err;
588 opt_delete++;
589 }
590 pos++;
591 }
592 printf("- Checking heap tables\n");
593 if (heap_check_heap(file,1) || heap_check_heap(file2,1))
594 {
595 puts("Heap keys crashed");
596 goto err;
597 }
598
599 if (my_errno != HA_ERR_END_OF_FILE)
600 printf("error: %d from heap_rrnd\n",my_errno);
601 if (key_check)
602 printf("error: Some read got wrong: check is %ld\n",(long) key_check);
603
604 end:
605 printf("\nFollowing test have been made:\n");
606 printf("Write records: %d\nUpdate records: %d\nDelete records: %d\n", write_count,update,opt_delete);
607 heap_clear(file);
608 heap_clear(file2);
609 if (heap_close(file) || (file2 && heap_close(file2)))
610 goto err;
611 heap_delete_table(filename2);
612 hp_panic(HA_PANIC_CLOSE);
613 my_end(MY_GIVE_INFO);
614 return(0);
615 err:
616 printf("Got error: %d when using heap-database\n",my_errno);
617 (void) heap_close(file);
618 return(1);
619 } /* main */
620
621
622 /* Read options */
623
get_options(int argc,char * argv[])624 static int get_options(int argc,char *argv[])
625 {
626 char *pos,*progname;
627
628 progname= argv[0];
629
630 while (--argc >0 && *(pos = *(++argv)) == '-' ) {
631 switch(*++pos) {
632 case 'B': /* Big file */
633 flag=1;
634 break;
635 case 'v': /* verbose */
636 verbose=1;
637 break;
638 case 'm': /* records */
639 recant=atoi(++pos);
640 break;
641 case 's':
642 silent=1;
643 break;
644 case 't':
645 testflag=atoi(++pos); /* testmod */
646 break;
647 case 'V':
648 case 'I':
649 case '?':
650 printf("%s Ver 1.1 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
651 puts("TCX Datakonsult AB, by Monty, for your professional use\n");
652 printf("Usage: %s [-?ABIKLsWv] [-m#] [-t#]\n",progname);
653 exit(0);
654 case '#':
655 DBUG_PUSH (++pos);
656 break;
657 }
658 }
659 return 0;
660 } /* get options */
661
662 /* Generate a random value in intervall 0 <=x <= n */
663
rnd(int max_value)664 static int rnd(int max_value)
665 {
666 return (int) ((rand() & 32767)/32767.0*max_value);
667 } /* rnd */
668
669
endprog(int sig_number MY_ATTRIBUTE ((unused)))670 static sig_handler endprog(int sig_number MY_ATTRIBUTE((unused)))
671 {
672 {
673 hp_panic(HA_PANIC_CLOSE);
674 my_end(1);
675 exit(1);
676 }
677 }
678
calc_check(uchar * buf,uint length)679 static int calc_check(uchar *buf, uint length)
680 {
681 int check=0;
682 while (length--)
683 check+= (int) (uchar) *(buf++);
684 return check;
685 }
686
make_record(uchar * record,uint n1,uint n2,uint n3,const char * mark,uint count)687 static void make_record(uchar *record, uint n1, uint n2, uint n3,
688 const char *mark, uint count)
689 {
690 memset(record, ' ', reclength);
691 sprintf((char*) record,"%6d:%4d:%8d:%3.3s: %4d",
692 n1,n2,n3,mark,count);
693 record[37]='A'; /* Store A in null key */
694 record[38]=1; /* set as null */
695 }
696