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