int myrg_update(register MYRG_INFO *info,const uchar *oldrec, uchar *newrec) { if (!info->current_table) return (my_errno=HA_ERR_NO_ACTIVE_RECORD); return mi_update(info->current_table->table,oldrec,newrec); }
int main(int argc, char *argv[]) { uint i; int j,n1,n2,n3,error,k; uint write_count,update,dupp_keys,opt_delete,start,length,blob_pos, reclength,ant,found_parts; my_off_t lastpos; ha_rows range_records,records; MI_INFO *file; MI_KEYDEF keyinfo[10]; MI_COLUMNDEF recinfo[10]; MI_ISAMINFO info; const char *filename; char *blob_buffer; MI_CREATE_INFO create_info; MY_INIT(argv[0]); filename= "test2"; get_options(argc,argv); if (! async_io) my_disable_async_io=1; reclength=STANDARD_LENGTH+60+(use_blob ? 8 : 0); blob_pos=STANDARD_LENGTH+60; keyinfo[0].seg= &glob_keyseg[0][0]; keyinfo[0].seg[0].start=0; keyinfo[0].seg[0].length=6; keyinfo[0].seg[0].type=HA_KEYTYPE_TEXT; keyinfo[0].seg[0].language= default_charset_info->number; keyinfo[0].seg[0].flag=(uint8) pack_seg; keyinfo[0].seg[0].null_bit=0; keyinfo[0].seg[0].null_pos=0; keyinfo[0].key_alg=HA_KEY_ALG_BTREE; keyinfo[0].keysegs=1; keyinfo[0].flag = pack_type; keyinfo[0].block_length= 0; /* Default block length */ keyinfo[1].seg= &glob_keyseg[1][0]; keyinfo[1].seg[0].start=7; keyinfo[1].seg[0].length=6; keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY; keyinfo[1].seg[0].flag=0; keyinfo[1].seg[0].null_bit=0; keyinfo[1].seg[0].null_pos=0; keyinfo[1].seg[1].start=0; /* two part key */ keyinfo[1].seg[1].length=6; keyinfo[1].seg[1].type=HA_KEYTYPE_NUM; keyinfo[1].seg[1].flag=HA_REVERSE_SORT; keyinfo[1].seg[1].null_bit=0; keyinfo[1].seg[1].null_pos=0; keyinfo[1].key_alg=HA_KEY_ALG_BTREE; keyinfo[1].keysegs=2; keyinfo[1].flag =0; keyinfo[1].block_length= MI_MIN_KEY_BLOCK_LENGTH; /* Diff blocklength */ keyinfo[2].seg= &glob_keyseg[2][0]; keyinfo[2].seg[0].start=12; keyinfo[2].seg[0].length=8; keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY; keyinfo[2].seg[0].flag=HA_REVERSE_SORT; keyinfo[2].seg[0].null_bit=0; keyinfo[2].seg[0].null_pos=0; keyinfo[2].key_alg=HA_KEY_ALG_BTREE; keyinfo[2].keysegs=1; keyinfo[2].flag =HA_NOSAME; keyinfo[2].block_length= 0; /* Default block length */ keyinfo[3].seg= &glob_keyseg[3][0]; keyinfo[3].seg[0].start=0; keyinfo[3].seg[0].length=reclength-(use_blob ? 8 : 0); keyinfo[3].seg[0].type=HA_KEYTYPE_TEXT; keyinfo[3].seg[0].language=default_charset_info->number; keyinfo[3].seg[0].flag=(uint8) pack_seg; keyinfo[3].seg[0].null_bit=0; keyinfo[3].seg[0].null_pos=0; keyinfo[3].key_alg=HA_KEY_ALG_BTREE; keyinfo[3].keysegs=1; keyinfo[3].flag = pack_type; keyinfo[3].block_length= 0; /* Default block length */ keyinfo[4].seg= &glob_keyseg[4][0]; keyinfo[4].seg[0].start=0; keyinfo[4].seg[0].length=5; keyinfo[4].seg[0].type=HA_KEYTYPE_TEXT; keyinfo[4].seg[0].language=default_charset_info->number; keyinfo[4].seg[0].flag=0; keyinfo[4].seg[0].null_bit=0; keyinfo[4].seg[0].null_pos=0; keyinfo[4].key_alg=HA_KEY_ALG_BTREE; keyinfo[4].keysegs=1; keyinfo[4].flag = pack_type; keyinfo[4].block_length= 0; /* Default block length */ keyinfo[5].seg= &glob_keyseg[5][0]; keyinfo[5].seg[0].start=0; keyinfo[5].seg[0].length=4; keyinfo[5].seg[0].type=HA_KEYTYPE_TEXT; keyinfo[5].seg[0].language=default_charset_info->number; keyinfo[5].seg[0].flag=pack_seg; keyinfo[5].seg[0].null_bit=0; keyinfo[5].seg[0].null_pos=0; keyinfo[5].key_alg=HA_KEY_ALG_BTREE; keyinfo[5].keysegs=1; keyinfo[5].flag = pack_type; keyinfo[5].block_length= 0; /* Default block length */ recinfo[0].type=pack_fields ? FIELD_SKIP_PRESPACE : 0; recinfo[0].length=7; recinfo[0].null_bit=0; recinfo[0].null_pos=0; recinfo[1].type=pack_fields ? FIELD_SKIP_PRESPACE : 0; recinfo[1].length=5; recinfo[1].null_bit=0; recinfo[1].null_pos=0; recinfo[2].type=pack_fields ? FIELD_SKIP_PRESPACE : 0; recinfo[2].length=9; recinfo[2].null_bit=0; recinfo[2].null_pos=0; recinfo[3].type=FIELD_NORMAL; recinfo[3].length=STANDARD_LENGTH-7-5-9-4; recinfo[3].null_bit=0; recinfo[3].null_pos=0; recinfo[4].type=pack_fields ? FIELD_SKIP_ZERO : 0; recinfo[4].length=4; recinfo[4].null_bit=0; recinfo[4].null_pos=0; recinfo[5].type=pack_fields ? FIELD_SKIP_ENDSPACE : 0; recinfo[5].length=60; recinfo[5].null_bit=0; recinfo[5].null_pos=0; if (use_blob) { recinfo[6].type=FIELD_BLOB; recinfo[6].length=4+portable_sizeof_char_ptr; recinfo[6].null_bit=0; recinfo[6].null_pos=0; } write_count=update=dupp_keys=opt_delete=0; blob_buffer=0; for (i=1000 ; i>0 ; i--) key1[i]=0; for (i=4999 ; i>0 ; i--) key3[i]=0; if (!silent) printf("- Creating isam-file\n"); /* DBUG_PUSH(""); */ /* my_delete(filename,MYF(0)); */ /* Remove old locks under gdb */ file= 0; bzero((char*) &create_info,sizeof(create_info)); create_info.max_rows=(ha_rows) (rec_pointer_size ? (1L << (rec_pointer_size*8))/ reclength : 0); create_info.reloc_rows=(ha_rows) 100; if (mi_create(filename,keys,&keyinfo[first_key], use_blob ? 7 : 6, &recinfo[0], 0,(MI_UNIQUEDEF*) 0, &create_info,create_flag)) goto err; if (use_log) mi_log(1); if (!(file=mi_open(filename,2,HA_OPEN_ABORT_IF_LOCKED))) goto err; if (!silent) printf("- Writing key:s\n"); if (key_cacheing) init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0); if (locking) mi_lock_database(file,F_WRLCK); if (write_cacheing) mi_extra(file,HA_EXTRA_WRITE_CACHE,0); if (opt_quick_mode) mi_extra(file,HA_EXTRA_QUICK,0); for (i=0 ; i < recant ; i++) { n1=rnd(1000); n2=rnd(100); n3=rnd(5000); sprintf((char*) record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count); int4store(record+STANDARD_LENGTH-4,(long) i); fix_length(record,(uint) STANDARD_LENGTH+rnd(60)); put_blob_in_record(record+blob_pos,&blob_buffer); DBUG_PRINT("test",("record: %d",i)); if (mi_write(file,record)) { if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0) { printf("Error: %d in write at record: %d\n",my_errno,i); goto err; } if (verbose) printf(" Double key: %d\n",n3); } else { if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3) { printf("Error: Didn't get error when writing second key: '%8d'\n",n3); goto err; } write_count++; key1[n1]++; key3[n3]=1; } /* Check if we can find key without flushing database */ if (i == recant/2) { for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ; if (!j) for (j=999 ; j>0 && key1[j] == 0 ; j--) ; sprintf((char*) key,"%6d",j); if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) { printf("Test in loop: Can't find key: \"%s\"\n",key); goto err; } } } if (testflag==1) goto end; if (write_cacheing) { if (mi_extra(file,HA_EXTRA_NO_CACHE,0)) { puts("got error from mi_extra(HA_EXTRA_NO_CACHE)"); goto end; } } if (key_cacheing) resize_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size*2,0,0); if (!silent) printf("- Delete\n"); for (i=0 ; i<recant/10 ; i++) { for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ; if (j != 0) { sprintf((char*) key,"%6d",j); if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) { printf("can't find key1: \"%s\"\n",key); goto err; } if (opt_delete == (uint) remove_count) /* While testing */ goto end; if (mi_delete(file,read_record)) { printf("error: %d; can't delete record: \"%s\"\n", my_errno,read_record); goto err; } opt_delete++; key1[atoi((char*) read_record+keyinfo[0].seg[0].start)]--; key3[atoi((char*) read_record+keyinfo[2].seg[0].start)]=0; } else puts("Warning: Skipping delete test because no dupplicate keys"); } if (testflag==2) goto end; if (!silent) printf("- Update\n"); for (i=0 ; i<recant/10 ; i++) { n1=rnd(1000); n2=rnd(100); n3=rnd(5000); sprintf((char*) record2,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update); int4store(record2+STANDARD_LENGTH-4,(long) i); fix_length(record2,(uint) STANDARD_LENGTH+rnd(60)); for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ; if (j != 0) { sprintf((char*) key,"%6d",j); if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) { printf("can't find key1: \"%s\"\n",(char*) key); goto err; } if (use_blob) { if (i & 1) put_blob_in_record(record+blob_pos,&blob_buffer); else bmove(record+blob_pos,read_record+blob_pos,8); } if (mi_update(file,read_record,record2)) { if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0) { printf("error: %d; can't update:\nFrom: \"%s\"\nTo: \"%s\"\n", my_errno,read_record,record2); goto err; } if (verbose) printf("Double key when tried to update:\nFrom: \"%s\"\nTo: \"%s\"\n",record,record2); } else { key1[atoi((char*) read_record+keyinfo[0].seg[0].start)]--; key3[atoi((char*) read_record+keyinfo[2].seg[0].start)]=0; key1[n1]++; key3[n3]=1; update++; } } } if (testflag == 3) goto end; for (i=999, dupp_keys=j=0 ; i>0 ; i--) { if (key1[i] > dupp_keys) { dupp_keys=key1[i]; j=i; } } sprintf((char*) key,"%6d",j); start=keyinfo[0].seg[0].start; length=keyinfo[0].seg[0].length; if (dupp_keys) { if (!silent) printf("- Same key: first - next -> last - prev -> first\n"); DBUG_PRINT("progpos",("first - next -> last - prev -> first")); if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys); if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) goto err; if (mi_rsame(file,read_record2,-1)) goto err; if (memcmp(read_record,read_record2,reclength) != 0) { printf("mi_rsame didn't find same record\n"); goto end; } info.recpos=mi_position(file); if (mi_rfirst(file,read_record2,0) || mi_rsame_with_pos(file,read_record2,0,info.recpos) || memcmp(read_record,read_record2,reclength) != 0) { printf("mi_rsame_with_pos didn't find same record\n"); goto end; } { int skr=mi_rnext(file,read_record2,0); if ((skr && my_errno != HA_ERR_END_OF_FILE) || mi_rprev(file,read_record2,-1) || memcmp(read_record,read_record2,reclength) != 0) { printf("mi_rsame_with_pos lost position\n"); goto end; } } ant=1; while (mi_rnext(file,read_record2,0) == 0 && memcmp(read_record2+start,key,length) == 0) ant++; if (ant != dupp_keys) { printf("next: Found: %d keys of %d\n",ant,dupp_keys); goto end; } ant=0; while (mi_rprev(file,read_record3,0) == 0 && memcmp(read_record3+start,key,length) == 0) ant++; if (ant != dupp_keys) { printf("prev: Found: %d records of %d\n",ant,dupp_keys); goto end; } /* Check of mi_rnext_same */ if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) goto err; ant=1; while (!mi_rnext_same(file,read_record3) && ant < dupp_keys+10) ant++; if (ant != dupp_keys || my_errno != HA_ERR_END_OF_FILE) { printf("mi_rnext_same: Found: %d records of %d\n",ant,dupp_keys); goto end; } } if (!silent) printf("- All keys: first - next -> last - prev -> first\n"); DBUG_PRINT("progpos",("All keys: first - next -> last - prev -> first")); ant=1; if (mi_rfirst(file,read_record,0)) { printf("Can't find first record\n"); goto end; } while ((error=mi_rnext(file,read_record3,0)) == 0 && ant < write_count+10) ant++; if (ant != write_count - opt_delete || error != HA_ERR_END_OF_FILE) { printf("next: I found: %d records of %d (error: %d)\n", ant, write_count - opt_delete, error); goto end; } if (mi_rlast(file,read_record2,0) || memcmp(read_record2,read_record3,reclength)) { printf("Can't find last record\n"); DBUG_DUMP("record2",(uchar*) read_record2,reclength); DBUG_DUMP("record3",(uchar*) read_record3,reclength); goto end; } ant=1; while (mi_rprev(file,read_record3,0) == 0 && ant < write_count+10) ant++; if (ant != write_count - opt_delete) { printf("prev: I found: %d records of %d\n",ant,write_count); goto end; } if (memcmp(read_record,read_record3,reclength)) { printf("Can't find first record\n"); goto end; } if (!silent) printf("- Test if: Read first - next - prev - prev - next == first\n"); DBUG_PRINT("progpos",("- Read first - next - prev - prev - next == first")); if (mi_rfirst(file,read_record,0) || mi_rnext(file,read_record3,0) || mi_rprev(file,read_record3,0) || mi_rprev(file,read_record3,0) == 0 || mi_rnext(file,read_record3,0)) goto err; if (memcmp(read_record,read_record3,reclength) != 0) printf("Can't find first record\n"); if (!silent) printf("- Test if: Read last - prev - next - next - prev == last\n"); DBUG_PRINT("progpos",("Read last - prev - next - next - prev == last")); if (mi_rlast(file,read_record2,0) || mi_rprev(file,read_record3,0) || mi_rnext(file,read_record3,0) || mi_rnext(file,read_record3,0) == 0 || mi_rprev(file,read_record3,0)) goto err; if (memcmp(read_record2,read_record3,reclength)) printf("Can't find last record\n"); #ifdef NOT_ANYMORE if (!silent) puts("- Test read key-part"); strmov(key2,key); for(i=strlen(key2) ; i-- > 1 ;) { key2[i]=0; /* The following row is just to catch some bugs in the key code */ bzero((char*) file->lastkey,file->s->base.max_key_length*2); if (mi_rkey(file,read_record,0,key2,(uint) i,HA_READ_PREFIX)) goto err; if (memcmp(read_record+start,key,(uint) i)) { puts("Didn't find right record"); goto end; } } #endif if (dupp_keys > 2) { if (!silent) printf("- Read key (first) - next - delete - next -> last\n"); DBUG_PRINT("progpos",("first - next - delete - next -> last")); if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) goto err; if (mi_rnext(file,read_record3,0)) goto err; if (mi_delete(file,read_record3)) goto err; opt_delete++; ant=1; while (mi_rnext(file,read_record3,0) == 0 && memcmp(read_record3+start,key,length) == 0) ant++; if (ant != dupp_keys-1) { printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1); goto end; } } if (dupp_keys>4) { if (!silent) printf("- Read last of key - prev - delete - prev -> first\n"); DBUG_PRINT("progpos",("last - prev - delete - prev -> first")); if (mi_rprev(file,read_record3,0)) goto err; if (mi_rprev(file,read_record3,0)) goto err; if (mi_delete(file,read_record3)) goto err; opt_delete++; ant=1; while (mi_rprev(file,read_record3,0) == 0 && memcmp(read_record3+start,key,length) == 0) ant++; if (ant != dupp_keys-2) { printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2); goto end; } } if (dupp_keys > 6) { if (!silent) printf("- Read first - delete - next -> last\n"); DBUG_PRINT("progpos",("first - delete - next -> last")); if (mi_rkey(file,read_record3,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT)) goto err; if (mi_delete(file,read_record3)) goto err; opt_delete++; ant=1; if (mi_rnext(file,read_record,0)) goto err; /* Skall finnas poster */ while (mi_rnext(file,read_record3,0) == 0 && memcmp(read_record3+start,key,length) == 0) ant++; if (ant != dupp_keys-3) { printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3); goto end; } if (!silent) printf("- Read last - delete - prev -> first\n"); DBUG_PRINT("progpos",("last - delete - prev -> first")); if (mi_rprev(file,read_record3,0)) goto err; if (mi_delete(file,read_record3)) goto err; opt_delete++; ant=0; while (mi_rprev(file,read_record3,0) == 0 && memcmp(read_record3+start,key,length) == 0) ant++; if (ant != dupp_keys-4) { printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4); goto end; } } if (!silent) puts("- Test if: Read rrnd - same"); DBUG_PRINT("progpos",("Read rrnd - same")); for (i=0 ; i < write_count ; i++) { if (mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR) == 0) break; } if (i == write_count) goto err; bmove(read_record2,read_record,reclength); for (i=min(2,keys) ; i-- > 0 ;) { if (mi_rsame(file,read_record2,(int) i)) goto err; if (memcmp(read_record,read_record2,reclength) != 0) { printf("is_rsame didn't find same record\n"); goto end; } } if (!silent) puts("- Test mi_records_in_range"); mi_status(file,&info,HA_STATUS_VARIABLE); for (i=0 ; i < info.keys ; i++) { key_range min_key, max_key; if (mi_rfirst(file,read_record,(int) i) || mi_rlast(file,read_record2,(int) i)) goto err; copy_key(file,(uint) i,(uchar*) read_record,(uchar*) key); copy_key(file,(uint) i,(uchar*) read_record2,(uchar*) key2); min_key.key= key; min_key.keypart_map= HA_WHOLE_KEY; min_key.flag= HA_READ_KEY_EXACT; max_key.key= key2; max_key.keypart_map= HA_WHOLE_KEY; max_key.flag= HA_READ_AFTER_KEY; range_records= mi_records_in_range(file,(int) i, &min_key, &max_key); if (range_records < info.records*8/10 || range_records > info.records*12/10) { printf("mi_records_range returned %ld; Should be about %ld\n", (long) range_records,(long) info.records); goto end; } if (verbose) { printf("mi_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n", (long) range_records, (long) info.records, labs((long) range_records - (long) info.records)*100.0/ info.records); } } for (i=0 ; i < 5 ; i++) { for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ; for (k=rnd(1000)+1 ; k>0 && key1[k] == 0 ; k--) ; if (j != 0 && k != 0) { key_range min_key, max_key; if (j > k) swap_variables(int, j, k); sprintf((char*) key,"%6d",j); sprintf((char*) key2,"%6d",k); min_key.key= key; min_key.length= USE_WHOLE_KEY; min_key.flag= HA_READ_AFTER_KEY; max_key.key= key2; max_key.length= USE_WHOLE_KEY; max_key.flag= HA_READ_BEFORE_KEY; range_records= mi_records_in_range(file, 0, &min_key, &max_key); records=0; for (j++ ; j < k ; j++) records+=key1[j]; if ((long) range_records < (long) records*7/10-2 || (long) range_records > (long) records*14/10+2) { printf("mi_records_range for key: %d returned %lu; Should be about %lu\n", i, (ulong) range_records, (ulong) records); goto end; } if (verbose && records) { printf("mi_records_range returned %lu; Exact is %lu (diff: %4.2g %%)\n", (ulong) range_records, (ulong) records, labs((long) range_records-(long) records)*100.0/records); } } } if (!silent) printf("- mi_info\n"); mi_status(file,&info,HA_STATUS_VARIABLE | HA_STATUS_CONST); if (info.records != write_count-opt_delete || info.deleted > opt_delete + update || info.keys != keys) { puts("Wrong info from mi_info"); printf("Got: records: %lu delete: %lu i_keys: %d\n", (ulong) info.records, (ulong) info.deleted, info.keys); } if (verbose) { char buff[80]; get_date(buff,3,info.create_time); printf("info: Created %s\n",buff); get_date(buff,3,info.check_time); printf("info: checked %s\n",buff); get_date(buff,3,info.update_time); printf("info: Modified %s\n",buff); } mi_panic(HA_PANIC_WRITE); mi_panic(HA_PANIC_READ); if (mi_is_changed(file)) puts("Warning: mi_is_changed reported that datafile was changed"); if (!silent) printf("- mi_extra(CACHE) + mi_rrnd.... + mi_extra(NO_CACHE)\n"); if (mi_reset(file) || mi_extra(file,HA_EXTRA_CACHE,0)) { if (locking || (!use_blob && !pack_fields)) { puts("got error from mi_extra(HA_EXTRA_CACHE)"); goto end; } } ant=0; while ((error=mi_rrnd(file,record,HA_OFFSET_ERROR)) != HA_ERR_END_OF_FILE && ant < write_count + 10) ant+= error ? 0 : 1; if (ant != write_count-opt_delete) { printf("rrnd with cache: I can only find: %d records of %d\n", ant,write_count-opt_delete); goto end; } if (mi_extra(file,HA_EXTRA_NO_CACHE,0)) { puts("got error from mi_extra(HA_EXTRA_NO_CACHE)"); goto end; } ant=0; mi_scan_init(file); while ((error=mi_scan(file,record)) != HA_ERR_END_OF_FILE && ant < write_count + 10) ant+= error ? 0 : 1; if (ant != write_count-opt_delete) { printf("scan with cache: I can only find: %d records of %d\n", ant,write_count-opt_delete); goto end; } if (testflag == 4) goto end; if (!silent) printf("- Removing keys\n"); DBUG_PRINT("progpos",("Removing keys")); lastpos = HA_OFFSET_ERROR; /* DBUG_POP(); */ mi_reset(file); found_parts=0; while ((error=mi_rrnd(file,read_record,HA_OFFSET_ERROR)) != HA_ERR_END_OF_FILE) { info.recpos=mi_position(file); if (lastpos >= info.recpos && lastpos != HA_OFFSET_ERROR) { printf("mi_rrnd didn't advance filepointer; old: %ld, new: %ld\n", (long) lastpos, (long) info.recpos); goto err; } lastpos=info.recpos; if (error == 0) { if (opt_delete == (uint) remove_count) /* While testing */ goto end; if (mi_rsame(file,read_record,-1)) { printf("can't find record %lx\n",(long) info.recpos); goto err; } if (use_blob) { ulong blob_length,pos; uchar *ptr; longget(blob_length,read_record+blob_pos+4); ptr=(uchar*) blob_length; longget(blob_length,read_record+blob_pos); for (pos=0 ; pos < blob_length ; pos++) { if (ptr[pos] != (uchar) (blob_length+pos)) { printf("found blob with wrong info at %ld\n",(long) lastpos); use_blob=0; break; } } } if (mi_delete(file,read_record)) { printf("can't delete record: %6.6s, delete_count: %d\n", read_record, opt_delete); goto err; } opt_delete++; } else found_parts++; } if (my_errno != HA_ERR_END_OF_FILE && my_errno != HA_ERR_RECORD_DELETED) printf("error: %d from mi_rrnd\n",my_errno); if (write_count != opt_delete) { printf("Deleted only %d of %d records (%d parts)\n",opt_delete,write_count, found_parts); goto err; } end: if (mi_close(file)) goto err; mi_panic(HA_PANIC_CLOSE); /* Should close log */ if (!silent) { printf("\nFollowing test have been made:\n"); printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete); if (rec_pointer_size) printf("Record pointer size: %d\n",rec_pointer_size); printf("myisam_block_size: %lu\n", myisam_block_size); if (key_cacheing) { puts("Key cache used"); printf("key_cache_block_size: %u\n", key_cache_block_size); if (write_cacheing) puts("Key cache resized"); } if (write_cacheing) puts("Write cacheing used"); if (write_cacheing) puts("quick mode"); if (async_io && locking) puts("Asyncron io with locking used"); else if (locking) puts("Locking used"); if (use_blob) puts("blobs used"); printf("key cache status: \n\ blocks used:%10lu\n\ not flushed:%10lu\n\ w_requests: %10lu\n\ writes: %10lu\n\ r_requests: %10lu\n\ reads: %10lu\n", dflt_key_cache->blocks_used, dflt_key_cache->global_blocks_changed, (ulong) dflt_key_cache->global_cache_w_requests, (ulong) dflt_key_cache->global_cache_write, (ulong) dflt_key_cache->global_cache_r_requests, (ulong) dflt_key_cache->global_cache_read); }
int run_test(const char *filename) { MI_INFO *file; int i , j, error, deleted, rec_length, uniques = 0; ha_rows found , row_count; my_off_t pos; char record [MAX_REC_LENGTH], key[MAX_REC_LENGTH], read_record[MAX_REC_LENGTH]; MI_UNIQUEDEF uniquedef; MI_CREATE_INFO create_info; bzero((char *)recinfo, sizeof(recinfo)); /* First define 2 columns */ recinfo[0].type = FIELD_NORMAL; recinfo[0].length = 1; /* For NULL bits */ recinfo[1].type = key_field; recinfo[1].length = (key_field == FIELD_BLOB ? 4 + mi_portable_sizeof_char_ptr : key_length); if (key_field == FIELD_VARCHAR) recinfo[1].length += 2; recinfo[2].type = extra_field; recinfo[2].length = (extra_field == FIELD_BLOB ? 4 + mi_portable_sizeof_char_ptr : 24); if (extra_field == FIELD_VARCHAR) recinfo[2].length += 2; if (opt_unique) { recinfo[3].type = FIELD_CHECK; recinfo[3].length = MI_UNIQUE_HASH_LENGTH; } rec_length = recinfo[0].length + recinfo[1].length + recinfo[2].length + recinfo[3].length; /* Define a key over the first column */ keyinfo[0].seg = keyseg; keyinfo[0].keysegs = 1; keyinfo[0].seg[0].type = key_type; keyinfo[0].seg[0].flag = pack_seg; keyinfo[0].seg[0].start = 1; keyinfo[0].seg[0].length = key_length; keyinfo[0].seg[0].null_bit = null_fields ? 2 : 0; keyinfo[0].seg[0].null_pos = 0; keyinfo[0].seg[0].language = MY_CHARSET_CURRENT; if (pack_seg & HA_BLOB_PART) { keyinfo[0].seg[0].bit_start = 4; /* Length of blob length */ } keyinfo[0].flag = (uint8) (pack_keys | unique_key); bzero((byte *) flags, sizeof(flags)); if (opt_unique) { uint start; uniques = 1; bzero((char *)&uniquedef, sizeof(uniquedef)); bzero((char *)uniqueseg, sizeof(uniqueseg)); uniquedef.seg = uniqueseg; uniquedef.keysegs = 2; /* Make a unique over all columns (except first NULL fields) */ for (i = 0, start = 1; i < 2; i++) { uniqueseg[i].start = start; start += recinfo[i + 1].length; uniqueseg[i].length = recinfo[i + 1].length; uniqueseg[i].language = MY_CHARSET_CURRENT; } uniqueseg[0].type = key_type; uniqueseg[0].null_bit = null_fields ? 2 : 0; uniqueseg[1].type = HA_KEYTYPE_TEXT; if (extra_field == FIELD_BLOB) { uniqueseg[1].length = 0; /* The whole blob */ uniqueseg[1].bit_start = 4; /* long blob */ uniqueseg[1].flag |= HA_BLOB_PART; } else if (extra_field == FIELD_VARCHAR) uniqueseg[1].flag |= HA_VAR_LENGTH; } else uniques = 0; if (!silent) printf("- Creating isam-file\n"); bzero((char *)&create_info, sizeof(create_info)); create_info.max_rows = (ulong) (rec_pointer_size ? (1L << (rec_pointer_size * 8)) / 40 : 0); if (mi_create(filename, 1, keyinfo, 3 + opt_unique, recinfo, uniques, &uniquedef, &create_info, create_flag)) goto err; if (!(file = mi_open(filename, 2, HA_OPEN_ABORT_IF_LOCKED))) goto err; if (!silent) printf("- Writing key:s\n"); my_errno = 0; row_count = deleted = 0; for (i = 49; i >= 1; i -= 2) { if (insert_count-- == 0) { VOID(mi_close(file)); exit(0); } j = i % 25 + 1; create_record(record, j); error = mi_write(file, record); if (!error) row_count++; flags[j] = 1; if (verbose || error) printf("J= %2d mi_write: %d errno: %d\n", j, error, my_errno); } /* Insert 2 rows with null values */ if (null_fields) { create_record(record, 0); error = mi_write(file, record); if (!error) row_count++; if (verbose || error) printf("J= NULL mi_write: %d errno: %d\n", error, my_errno); error = mi_write(file, record); if (!error) row_count++; if (verbose || error) printf("J= NULL mi_write: %d errno: %d\n", error, my_errno); flags[0] = 2; } if (!skip_update) { if (opt_unique) { if (!silent) printf("- Checking unique constraint\n"); create_record(record, j); if (!mi_write(file, record) || my_errno != HA_ERR_FOUND_DUPP_UNIQUE) { printf("unique check failed\n"); } } if (!silent) printf("- Updating rows\n"); /* Update first last row to force extend of file */ if (mi_rsame(file, read_record, -1)) { printf("Can't find last row with mi_rsame\n"); } else { memcpy(record, read_record, rec_length); update_record(record); if (mi_update(file, read_record, record)) { printf("Can't update last row: %.*s\n", keyinfo[0].seg[0].length, read_record + 1); } } /* Read through all rows and update them */ pos = (my_off_t) 0; found = 0; while ((error = mi_rrnd(file, read_record, pos)) == 0) { if (update_count-- == 0) { VOID(mi_close(file)); exit(0); } memcpy(record, read_record, rec_length); update_record(record); if (mi_update(file, read_record, record)) { printf("Can't update row: %.*s, error: %d\n", keyinfo[0].seg[0].length, record + 1, my_errno); } found++; pos = HA_OFFSET_ERROR; } if (found != row_count) printf("Found %ld of %ld rows\n", found, row_count); } if (!silent) printf("- Reopening file\n"); if (mi_close(file)) goto err; if (!(file = mi_open(filename, 2, HA_OPEN_ABORT_IF_LOCKED))) goto err; if (!skip_update) { if (!silent) printf("- Removing keys\n"); for (i = 0; i <= 10; i++) { /* testing */ if (remove_count-- == 0) { VOID(mi_close(file)); exit(0); } j = i * 2; if (!flags[j]) continue; create_key(key, j); my_errno = 0; if ((error = mi_rkey(file, read_record, 0, key, 0, HA_READ_KEY_EXACT))) { if (verbose || (flags[j] >= 1 || (error && my_errno != HA_ERR_KEY_NOT_FOUND))) printf("key: '%.*s' mi_rkey: %3d errno: %3d\n", (int)key_length, key + test(null_fields), error, my_errno); } else { error = mi_delete(file, read_record); if (verbose || error) printf("key: '%.*s' mi_delete: %3d errno: %3d\n", (int)key_length, key + test(null_fields), error, my_errno); if (!error) { deleted++; flags[j]--; } } } } if (!silent) printf("- Reading rows with key\n"); for (i = 0; i <= 25; i++) { create_key(key, i); my_errno = 0; error = mi_rkey(file, read_record, 0, key, 0, HA_READ_KEY_EXACT); if (verbose || (error == 0 && flags[i] == 0 && unique_key) || (error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND))) { printf("key: '%.*s' mi_rkey: %3d errno: %3d record: %s\n", (int)key_length, key + test(null_fields), error, my_errno, record + 1); } } if (!silent) printf("- Reading rows with position\n"); for (i = 1, found = 0; i <= 30; i++) { my_errno = 0; if ((error = mi_rrnd(file, read_record, i == 1 ? 0L : HA_OFFSET_ERROR)) == -1) { if (found != row_count - deleted) printf("Found only %ld of %ld rows\n", found, row_count - deleted); break; } if (!error) found++; if (verbose || (error != 0 && error != HA_ERR_RECORD_DELETED && error != HA_ERR_END_OF_FILE)) { printf("pos: %2d mi_rrnd: %3d errno: %3d record: %s\n", i - 1, error, my_errno, read_record + 1); } } if (mi_close(file)) goto err; my_end(MY_CHECK_ERROR); return (0); err: printf("got error: %3d when using myisam-database\n", my_errno); return 1; /* skipp warning */ }
int test_update(MI_INFO *file,int id,int lock_type) { uint i,lock,found,next,prev,update; uint32 tmp; char find[4]; struct record new_record; lock=0; if (rnd(2) == 0 || lock_type == F_RDLCK) { lock=1; if (mi_lock_database(file,F_WRLCK)) { if (lock_type == F_RDLCK && my_errno == EDEADLK) { printf("%2d: write: deadlock\n",id); fflush(stdout); return 0; } fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno); return 1; } } bzero((char*) &new_record,sizeof(new_record)); strmov((char*) new_record.text,"Updated"); found=next=prev=update=0; for (i=0 ; i < 100 ; i++) { tmp=rnd(100000); int4store(find,tmp); if (!mi_rkey(file,record.id,1,(uchar*) find, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) found++; else { if (my_errno != HA_ERR_KEY_NOT_FOUND) { fprintf(stderr,"%2d: Got error %d from read in update\n",id,my_errno); return 1; } else if (!mi_rnext(file,record.id,1)) next++; else { if (my_errno != HA_ERR_END_OF_FILE) { fprintf(stderr,"%2d: Got error %d from rnext in update\n", id,my_errno); return 1; } else if (!mi_rprev(file,record.id,1)) prev++; else { if (my_errno != HA_ERR_END_OF_FILE) { fprintf(stderr,"%2d: Got error %d from rnext in update\n", id,my_errno); return 1; } continue; } } } memcpy(new_record.id, record.id, sizeof(record.id)); tmp=rnd(20000)+40000; int4store(new_record.nr,tmp); if (!mi_update(file,record.id,new_record.id)) update++; else { if (my_errno != HA_ERR_RECORD_CHANGED && my_errno != HA_ERR_RECORD_DELETED && my_errno != HA_ERR_FOUND_DUPP_KEY) { fprintf(stderr,"%2d: Got error %d from update\n",id,my_errno); return 1; } } } if (lock) { if (mi_lock_database(file,F_UNLCK)) { fprintf(stderr,"Can't unlock table,id, error%d\n",my_errno); return 1; } } printf("%2d: update: %5d\n",id,update); fflush(stdout); return 0; }
static int examine_log(my_string file_name, char **table_names) { uint command,result,files_open; ulong access_time,length; my_off_t filepos; int lock_command,mi_result; char isam_file_name[FN_REFLEN],llbuff[21],llbuff2[21]; uchar head[20]; gptr buff; struct test_if_open_param open_param; IO_CACHE cache; File file; FILE *write_file; enum ha_extra_function extra_command; TREE tree; struct file_info file_info,*curr_file_info; DBUG_ENTER("examine_log"); if ((file=my_open(file_name,O_RDONLY,MYF(MY_WME))) < 0) DBUG_RETURN(1); write_file=0; if (write_filename) { if (!(write_file=my_fopen(write_filename,O_WRONLY,MYF(MY_WME)))) { my_close(file,MYF(0)); DBUG_RETURN(1); } } init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0)); bzero((gptr) com_count,sizeof(com_count)); init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1, (tree_element_free) file_info_free, NULL); VOID(init_key_cache(KEY_CACHE_SIZE)); files_open=0; access_time=0; while (access_time++ != number_of_commands && !my_b_read(&cache,(byte*) head,9)) { isamlog_filepos=my_b_tell(&cache)-9L; file_info.filenr= mi_uint2korr(head+1); isamlog_process=file_info.process=(long) mi_uint4korr(head+3); if (!opt_processes) file_info.process=0; result= mi_uint2korr(head+7); if ((curr_file_info=(struct file_info*) tree_search(&tree,&file_info))) { curr_file_info->accessed=access_time; if (update && curr_file_info->used && curr_file_info->closed) { if (reopen_closed_file(&tree,curr_file_info)) { command=sizeof(com_count)/sizeof(com_count[0][0])/3; result=0; goto com_err; } } } command=(uint) head[0]; if (command < sizeof(com_count)/sizeof(com_count[0][0])/3 && (!table_names[0] || (curr_file_info && curr_file_info->used))) { com_count[command][0]++; if (result) com_count[command][1]++; } switch ((enum myisam_log_commands) command) { case MI_LOG_OPEN: if (!table_names[0]) { com_count[command][0]--; /* Must be counted explicite */ if (result) com_count[command][1]--; } if (curr_file_info) printf("\nWarning: %s is opened with same process and filenumber\nMaybe you should use the -P option ?\n", curr_file_info->show_name); if (my_b_read(&cache,(byte*) head,2)) goto err; file_info.name=0; file_info.show_name=0; file_info.record=0; if (read_string(&cache,(gptr*) &file_info.name, (uint) mi_uint2korr(head))) goto err; { uint i; char *pos,*to; /* Fix if old DOS files to new format */ for (pos=file_info.name; (pos=strchr(pos,'\\')) ; pos++) *pos= '/'; pos=file_info.name; for (i=0 ; i < prefix_remove ; i++) { char *next; if (!(next=strchr(pos,'/'))) break; pos=next+1; } to=isam_file_name; if (filepath) to=convert_dirname(isam_file_name,filepath,NullS); strmov(to,pos); fn_ext(isam_file_name)[0]=0; /* Remove extension */ } open_param.name=file_info.name; open_param.max_id=0; VOID(tree_walk(&tree,(tree_walk_action) test_if_open,(void*) &open_param, left_root_right)); file_info.id=open_param.max_id+1; /* * In the line below +10 is added to accomodate '<' and '>' chars * plus '\0' at the end, so that there is place for 7 digits. * It is improbable that same table can have that many entries in * the table cache. * The additional space is needed for the sprintf commands two lines * below. */ file_info.show_name=my_memdup(isam_file_name, (uint) strlen(isam_file_name)+10, MYF(MY_WME)); if (file_info.id > 1) sprintf(strend(file_info.show_name),"<%d>",file_info.id); file_info.closed=1; file_info.accessed=access_time; file_info.used=1; if (table_names[0]) { char **name; file_info.used=0; for (name=table_names ; *name ; name++) { if (!strcmp(*name,isam_file_name)) file_info.used=1; /* Update/log only this */ } } if (update && file_info.used) { if (files_open >= max_files) { if (close_some_file(&tree)) goto com_err; files_open--; } if (!(file_info.isam= mi_open(isam_file_name,O_RDWR, HA_OPEN_WAIT_IF_LOCKED))) goto com_err; if (!(file_info.record=my_malloc(file_info.isam->s->base.reclength, MYF(MY_WME)))) goto end; files_open++; file_info.closed=0; if (opt_myisam_with_debug) file_info.isam->s->rnd= 0; else file_info.isam->s->rnd= isamlog_process; } VOID(tree_insert(&tree,(gptr) &file_info,0)); if (file_info.used) { if (verbose && !record_pos_file) printf_log("%s: open -> %d",file_info.show_name, file_info.filenr); com_count[command][0]++; if (result) com_count[command][1]++; } break; case MI_LOG_CLOSE: if (verbose && !record_pos_file && (!table_names[0] || (curr_file_info && curr_file_info->used))) printf_log("%s: %s -> %d",FILENAME(curr_file_info), command_name[command],result); if (curr_file_info) { if (!curr_file_info->closed) files_open--; VOID(tree_delete(&tree,(gptr) curr_file_info)); } break; case MI_LOG_EXTRA: if (my_b_read(&cache,(byte*) head,1)) goto err; extra_command=(enum ha_extra_function) head[0]; if (verbose && !record_pos_file && (!table_names[0] || (curr_file_info && curr_file_info->used))) printf_log("%s: %s(%d) -> %d",FILENAME(curr_file_info), command_name[command], (int) extra_command,result); if (update && curr_file_info && !curr_file_info->closed) { if (mi_extra(curr_file_info->isam, extra_command, 0) != (int) result) { fflush(stdout); VOID(fprintf(stderr, "Warning: error %d, expected %d on command %s at %s\n", my_errno,result,command_name[command], llstr(isamlog_filepos,llbuff))); fflush(stderr); } } break; case MI_LOG_DELETE: if (my_b_read(&cache,(byte*) head,8)) goto err; filepos=mi_sizekorr(head); if (verbose && (!record_pos_file || ((record_pos == filepos || record_pos == NO_FILEPOS) && !cmp_filename(curr_file_info,record_pos_file))) && (!table_names[0] || (curr_file_info && curr_file_info->used))) printf_log("%s: %s at %ld -> %d",FILENAME(curr_file_info), command_name[command],(long) filepos,result); if (update && curr_file_info && !curr_file_info->closed) { if (mi_rrnd(curr_file_info->isam,curr_file_info->record,filepos)) { if (!recover) goto com_err; if (verbose) printf_log("error: Didn't find row to delete with mi_rrnd"); com_count[command][2]++; /* Mark error */ } mi_result=mi_delete(curr_file_info->isam,curr_file_info->record); if ((mi_result == 0 && result) || (mi_result && (uint) my_errno != result)) { if (!recover) goto com_err; if (mi_result) com_count[command][2]++; /* Mark error */ if (verbose) printf_log("error: Got result %d from mi_delete instead of %d", mi_result, result); } } break; case MI_LOG_WRITE: case MI_LOG_UPDATE: if (my_b_read(&cache,(byte*) head,12)) goto err; filepos=mi_sizekorr(head); length=mi_uint4korr(head+8); buff=0; if (read_string(&cache,&buff,(uint) length)) goto err; if ((!record_pos_file || ((record_pos == filepos || record_pos == NO_FILEPOS) && !cmp_filename(curr_file_info,record_pos_file))) && (!table_names[0] || (curr_file_info && curr_file_info->used))) { if (write_file && (my_fwrite(write_file,buff,length,MYF(MY_WAIT_IF_FULL | MY_NABP)))) goto end; if (verbose) printf_log("%s: %s at %ld, length=%ld -> %d", FILENAME(curr_file_info), command_name[command], filepos,length,result); } if (update && curr_file_info && !curr_file_info->closed) { if (curr_file_info->isam->s->base.blobs) fix_blob_pointers(curr_file_info->isam,buff); if ((enum myisam_log_commands) command == MI_LOG_UPDATE) { if (mi_rrnd(curr_file_info->isam,curr_file_info->record,filepos)) { if (!recover) { result=0; goto com_err; } if (verbose) printf_log("error: Didn't find row to update with mi_rrnd"); if (recover == 1 || result || find_record_with_key(curr_file_info,buff)) { com_count[command][2]++; /* Mark error */ break; } } mi_result=mi_update(curr_file_info->isam,curr_file_info->record, buff); if ((mi_result == 0 && result) || (mi_result && (uint) my_errno != result)) { if (!recover) goto com_err; if (verbose) printf_log("error: Got result %d from mi_update instead of %d", mi_result, result); if (mi_result) com_count[command][2]++; /* Mark error */ } } else { mi_result=mi_write(curr_file_info->isam,buff); if ((mi_result == 0 && result) || (mi_result && (uint) my_errno != result)) { if (!recover) goto com_err; if (verbose) printf_log("error: Got result %d from mi_write instead of %d", mi_result, result); if (mi_result) com_count[command][2]++; /* Mark error */ } if (!recover && filepos != curr_file_info->isam->lastpos) { printf("error: Wrote at position: %s, should have been %s", llstr(curr_file_info->isam->lastpos,llbuff), llstr(filepos,llbuff2)); goto end; } } } my_free(buff,MYF(0)); break; case MI_LOG_LOCK: if (my_b_read(&cache,(byte*) head,sizeof(lock_command))) goto err; memcpy_fixed(&lock_command,head,sizeof(lock_command)); if (verbose && !record_pos_file && (!table_names[0] || (curr_file_info && curr_file_info->used))) printf_log("%s: %s(%d) -> %d\n",FILENAME(curr_file_info), command_name[command],lock_command,result); if (update && curr_file_info && !curr_file_info->closed) { if (mi_lock_database(curr_file_info->isam,lock_command) != (int) result) goto com_err; } break; case MI_LOG_DELETE_ALL: if (verbose && !record_pos_file && (!table_names[0] || (curr_file_info && curr_file_info->used))) printf_log("%s: %s -> %d\n",FILENAME(curr_file_info), command_name[command],result); break; default: fflush(stdout); VOID(fprintf(stderr, "Error: found unknown command %d in logfile, aborted\n", command)); fflush(stderr); goto end; } } end_key_cache(); delete_tree(&tree); VOID(end_io_cache(&cache)); VOID(my_close(file,MYF(0))); if (write_file && my_fclose(write_file,MYF(MY_WME))) DBUG_RETURN(1); DBUG_RETURN(0); err: fflush(stdout); VOID(fprintf(stderr,"Got error %d when reading from logfile\n",my_errno)); fflush(stderr); goto end; com_err: fflush(stdout); VOID(fprintf(stderr,"Got error %d, expected %d on command %s at %s\n", my_errno,result,command_name[command], llstr(isamlog_filepos,llbuff))); fflush(stderr); end: end_key_cache(); delete_tree(&tree); VOID(end_io_cache(&cache)); VOID(my_close(file,MYF(0))); if (write_file) VOID(my_fclose(write_file,MYF(MY_WME))); DBUG_RETURN(1); }