mi_test2.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:30k
源码类别:

MySQL数据库

开发平台:

Visual C++

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