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