home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / isam / test2.c < prev    next >
C/C++ Source or Header  |  2000-08-31  |  25KB  |  853 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16.  
  17. /* Test av isam-databas: stor test */
  18.  
  19. #ifndef USE_MY_FUNC        /* We want to be able to dbug this !! */
  20. #define USE_MY_FUNC
  21. #endif
  22. #ifdef DBUG_OFF
  23. #undef DBUG_OFF
  24. #endif
  25. #ifndef SAFEMALLOC
  26. #define SAFEMALLOC
  27. #endif
  28.  
  29. #include "isamdef.h"
  30.  
  31. #define STANDAR_LENGTH 37
  32. #define NISAM_KEYS 6
  33. #if !defined(MSDOS) && !defined(labs)
  34. #define labs(a) abs(a)
  35. #endif
  36.  
  37. static void get_options(int argc, char *argv[]);
  38. static uint rnd(uint max_value);
  39. static void fix_length(byte *record,uint length);
  40. static void put_blob_in_record(char *blob_pos,char **blob_buffer);
  41. static void copy_key(struct st_isam_info *info,uint inx,
  42.              uchar *record,uchar *key);
  43.  
  44. static    int verbose=0,testflag=0,pack_type=HA_SPACE_PACK,
  45.         first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,locking=0,
  46.         rec_pointer_size=0,pack_fields=1,use_log=0;
  47. static uint keys=NISAM_KEYS,recant=1000;
  48. static uint use_blob=0;
  49. static uint16 key1[1000],key3[5000];
  50. static char record[300],record2[300],key[100],key2[100],
  51.         read_record[300],read_record2[300],read_record3[300];
  52.  
  53.  
  54.         /* Test program */
  55.  
  56. int main(argc,argv)
  57. int argc;
  58. char *argv[];
  59. {
  60.   uint i;
  61.   int j,n1,n2,n3,error,k;
  62.   uint write_count,update,dupp_keys,delete,start,length,blob_pos,
  63.        reclength,ant;
  64.   ulong lastpos,range_records,records;
  65.   N_INFO *file;
  66.   N_KEYDEF keyinfo[10];
  67.   N_RECINFO recinfo[10];
  68.   N_ISAMINFO info;
  69.   char *filename,*blob_buffer;
  70.   MY_INIT(argv[0]);
  71.  
  72.   filename= (char*) "test2.ISM";
  73.   get_options(argc,argv);
  74.   if (! async_io)
  75.     my_disable_async_io=1;
  76.  
  77.   reclength=STANDAR_LENGTH+60+(use_blob ? 8 : 0);
  78.   blob_pos=STANDAR_LENGTH+60;
  79.   keyinfo[0].seg[0].base.start=0;
  80.   keyinfo[0].seg[0].base.length=6;
  81.   keyinfo[0].seg[0].base.type=HA_KEYTYPE_TEXT;
  82.   keyinfo[0].seg[0].base.flag=(uint8) pack_type;
  83.   keyinfo[0].seg[1].base.type=0;
  84.   keyinfo[0].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
  85.   keyinfo[1].seg[0].base.start=7;
  86.   keyinfo[1].seg[0].base.length=6;
  87.   keyinfo[1].seg[0].base.type=HA_KEYTYPE_BINARY;
  88.   keyinfo[1].seg[0].base.flag=0;
  89.   keyinfo[1].seg[1].base.start=0;            /* Tv}delad nyckel */
  90.   keyinfo[1].seg[1].base.length=6;
  91.   keyinfo[1].seg[1].base.type=HA_KEYTYPE_NUM;
  92.   keyinfo[1].seg[1].base.flag=HA_REVERSE_SORT;
  93.   keyinfo[1].seg[2].base.type=0;
  94.   keyinfo[1].base.flag =0;
  95.   keyinfo[2].seg[0].base.start=12;
  96.   keyinfo[2].seg[0].base.length=8;
  97.   keyinfo[2].seg[0].base.type=HA_KEYTYPE_BINARY;
  98.   keyinfo[2].seg[0].base.flag=HA_REVERSE_SORT;
  99.   keyinfo[2].seg[1].base.type=0;
  100.   keyinfo[2].base.flag =HA_NOSAME;
  101.   keyinfo[3].seg[0].base.start=0;
  102.   keyinfo[3].seg[0].base.length=reclength-(use_blob ? 8 : 0);
  103.   keyinfo[3].seg[0].base.type=HA_KEYTYPE_TEXT;
  104.   keyinfo[3].seg[0].base.flag=(uint8) pack_type;
  105.   keyinfo[3].seg[1].base.type=0;
  106.   keyinfo[3].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
  107.   keyinfo[4].seg[0].base.start=0;
  108.   keyinfo[4].seg[0].base.length=5;
  109.   keyinfo[4].seg[0].base.type=HA_KEYTYPE_TEXT;
  110.   keyinfo[4].seg[0].base.flag=0;
  111.   keyinfo[4].seg[1].base.type=0;
  112.   keyinfo[4].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
  113.   keyinfo[5].seg[0].base.start=0;
  114.   keyinfo[5].seg[0].base.length=4;
  115.   keyinfo[5].seg[0].base.type=HA_KEYTYPE_TEXT;
  116.   keyinfo[5].seg[0].base.flag=(uint8) pack_type;
  117.   keyinfo[5].seg[1].base.type=0;
  118.   keyinfo[5].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
  119.  
  120.   recinfo[0].base.type=pack_fields ? FIELD_SKIPP_PRESPACE : 0;
  121.   recinfo[0].base.length=7;
  122.   recinfo[1].base.type=pack_fields ? FIELD_SKIPP_PRESPACE : 0;
  123.   recinfo[1].base.length=5;
  124.   recinfo[2].base.type=pack_fields ? FIELD_SKIPP_PRESPACE : 0;
  125.   recinfo[2].base.length=9;
  126.   recinfo[3].base.type=FIELD_NORMAL;
  127.   recinfo[3].base.length=STANDAR_LENGTH-7-5-9-4;
  128.   recinfo[4].base.type=pack_fields ? FIELD_SKIPP_ZERO : 0;
  129.   recinfo[4].base.length=4;
  130.   recinfo[5].base.type=pack_fields ? FIELD_SKIPP_ENDSPACE : 0;
  131.   recinfo[5].base.length=60;
  132.   if (use_blob)
  133.   {
  134.     recinfo[6].base.type=FIELD_BLOB;
  135.     recinfo[6].base.length=4+sizeof(char*);    /* 4 byte ptr, 4 byte length */
  136.     recinfo[7].base.type= FIELD_LAST;
  137.   }
  138.   else
  139.     recinfo[6].base.type= FIELD_LAST;
  140.  
  141.   write_count=update=dupp_keys=delete=0;
  142.   blob_buffer=0;
  143.  
  144.   for (i=999 ; i>0 ; i--) key1[i]=0;
  145.   for (i=4999 ; i>0 ; i--) key3[i]=0;
  146.  
  147.   printf("- Creating isam-file\n");
  148.   /*  DBUG_PUSH(""); */
  149.   my_delete(filename,MYF(0));        /* Remove old locks under gdb */
  150.   file= 0;
  151.   if (nisam_create(filename,keys,&keyinfo[first_key],&recinfo[0],
  152.            (ulong) (rec_pointer_size ? (1L << (rec_pointer_size*8))/
  153.                 reclength : 0),100l,0,0,0L))
  154.     goto err;
  155.   if (use_log)
  156.     nisam_log(1);
  157.   if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
  158.     goto err;
  159.   printf("- Writing key:s\n");
  160.   if (key_cacheing)
  161.     init_key_cache(IO_SIZE*16,(uint) IO_SIZE*4*10);    /* Use a small cache */
  162.   if (locking)
  163.     nisam_lock_database(file,F_WRLCK);
  164.   if (write_cacheing)
  165.     nisam_extra(file,HA_EXTRA_WRITE_CACHE);
  166.  
  167.   for (i=0 ; i < recant ; i++)
  168.   {
  169.     n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
  170.     sprintf(record,"%6d:%4d:%8d:Pos: %4d    ",n1,n2,n3,write_count);
  171.     longstore(record+STANDAR_LENGTH-4,(long) i);
  172.     fix_length(record,(uint) STANDAR_LENGTH+rnd(60));
  173.     put_blob_in_record(record+blob_pos,&blob_buffer);
  174.     DBUG_PRINT("test",("record: %d",i));
  175.  
  176.     if (nisam_write(file,record))
  177.     {
  178.       if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
  179.       {
  180.     printf("Error: %d in write at record: %d\n",my_errno,i);
  181.     goto err;
  182.       }
  183.       if (verbose) printf("   Double key: %d\n",n3);
  184.     }
  185.     else
  186.     {
  187.       if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3)
  188.       {
  189.     printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
  190.     goto err;
  191.       }
  192.       write_count++; key1[n1]++; key3[n3]=1;
  193.     }
  194.  
  195.     /* Check if we can find key without flushing database */
  196.     if (i == recant/2)
  197.     {
  198.       for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
  199.       if (!j)
  200.     for (j=999 ; j>0 && key1[j] == 0 ; j--) ;
  201.       sprintf(key,"%6d",j);
  202.       if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
  203.       {
  204.     printf("Test in loop: Can't find key: \"%s\"\n",key);
  205.     goto err;
  206.       }
  207.     }
  208.   }
  209.   if (testflag==1) goto end;
  210.  
  211.   if (write_cacheing)
  212.     if (nisam_extra(file,HA_EXTRA_NO_CACHE))
  213.     {
  214.       puts("got error from nisam_extra(HA_EXTRA_NO_CACHE)");
  215.       goto end;
  216.     }
  217.  
  218.   printf("- Delete\n");
  219.   for (i=0 ; i<recant/10 ; i++)
  220.   {
  221.     for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
  222.     if (j != 0)
  223.     {
  224.       sprintf(key,"%6d",j);
  225.       if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
  226.       {
  227.     printf("can't find key1: \"%s\"\n",key);
  228.     goto err;
  229.       }
  230.       if (nisam_delete(file,read_record))
  231.       {
  232.     printf("error: %d; can't delete record: \"%s\"\n", my_errno,read_record);
  233.     goto err;
  234.       }
  235.       delete++;
  236.       key1[atoi(read_record+keyinfo[0].seg[0].base.start)]--;
  237.       key3[atoi(read_record+keyinfo[2].seg[0].base.start)]=0;
  238.     }
  239.   }
  240.   if (testflag==2) goto end;
  241.  
  242.   printf("- Update\n");
  243.   for (i=0 ; i<recant/10 ; i++)
  244.   {
  245.     n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
  246.     sprintf(record2,"%6d:%4d:%8d:XXX: %4d     ",n1,n2,n3,update);
  247.     longstore(record2+STANDAR_LENGTH-4,(long) i);
  248.     fix_length(record2,(uint) STANDAR_LENGTH+rnd(60));
  249.  
  250.     for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
  251.     if (j != 0)
  252.     {
  253.       sprintf(key,"%6d",j);
  254.       if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
  255.       {
  256.     printf("can't find key1: \"%s\"\n",key);
  257.     goto err;
  258.       }
  259.       if (use_blob)
  260.       {
  261.     if (i & 1)
  262.       put_blob_in_record(record+blob_pos,&blob_buffer);
  263.     else
  264.       bmove(record+blob_pos,read_record+blob_pos,8);
  265.       }
  266.       if (nisam_update(file,read_record,record2))
  267.       {
  268.     if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
  269.     {
  270.       printf("error: %d; can't uppdate:\nFrom: \"%s\"\nTo:   \"%s\"\n",
  271.          my_errno,read_record,record2);
  272.       goto err;
  273.     }
  274.     if (verbose)
  275.       printf("Double key when tryed to uppdate:\nFrom: \"%s\"\nTo:   \"%s\"\n",record,record2);
  276.       }
  277.       else
  278.       {
  279.     key1[atoi(read_record+keyinfo[0].seg[0].base.start)]--;
  280.     key3[atoi(read_record+keyinfo[2].seg[0].base.start)]=0;
  281.     key1[n1]++; key3[n3]=1;
  282.     update++;
  283.       }
  284.     }
  285.   }
  286.   if (testflag==3) goto end;
  287.  
  288.   printf("- Same key: first - next -> last - prev -> first\n");
  289.   DBUG_PRINT("progpos",("first - next -> last - prev -> first"));
  290.   for (i=999, dupp_keys=j=0 ; i>0 ; i--)
  291.   {
  292.     if (key1[i] >dupp_keys) { dupp_keys=key1[i]; j=i; }
  293.   }
  294.   sprintf(key,"%6d",j);
  295.   if (verbose) printf("     Using key: \"%s\"  Keys: %d\n",key,dupp_keys);
  296.   if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err;
  297.   if (nisam_rsame(file,read_record2,-1)) goto err;
  298.   if (memcmp(read_record,read_record2,reclength) != 0)
  299.   {
  300.     printf("nisam_rsame didn't find same record\n");
  301.     goto end;
  302.   }
  303.   nisam_info(file,&info,0);
  304.   if (nisam_rfirst(file,read_record2,0) ||
  305.       nisam_rsame_with_pos(file,read_record2,0,info.recpos) ||
  306.       memcmp(read_record,read_record2,reclength) != 0)
  307.   {
  308.     printf("nisam_rsame_with_pos didn't find same record\n");
  309.     goto end;
  310.   }
  311.   {
  312.     int skr=nisam_rnext(file,read_record2,0);
  313.     if ((skr && my_errno != HA_ERR_END_OF_FILE) ||
  314.     nisam_rprev(file,read_record2,-1) ||
  315.     memcmp(read_record,read_record2,reclength) != 0)
  316.     {
  317.       printf("nisam_rsame_with_pos lost position\n");
  318.       goto end;
  319.     }
  320.   }
  321.   ant=1;
  322.   start=keyinfo[0].seg[0].base.start; length=keyinfo[0].seg[0].base.length;
  323.   while (nisam_rnext(file,read_record2,0) == 0 &&
  324.      memcmp(read_record2+start,key,length) == 0) ant++;
  325.   if (ant != dupp_keys)
  326.   {
  327.     printf("next: I can only find: %d keys of %d\n",ant,dupp_keys);
  328.     goto end;
  329.   }
  330.   ant=0;
  331.   while (nisam_rprev(file,read_record3,0) == 0 &&
  332.      bcmp(read_record3+start,key,length) == 0) ant++;
  333.   if (ant != dupp_keys)
  334.   {
  335.     printf("prev: I can only find: %d records of %d\n",ant,dupp_keys);
  336.     goto end;
  337.   }
  338.  
  339.   printf("- All keys: first - next -> last - prev -> first\n");
  340.   DBUG_PRINT("progpos",("All keys: first - next -> last - prev -> first"));
  341.   ant=1;
  342.   if (nisam_rfirst(file,read_record,0))
  343.   {
  344.     printf("Can't find first record\n");
  345.     goto end;
  346.   }
  347.   while (nisam_rnext(file,read_record3,0) == 0 && ant < write_count+10)
  348.     ant++;
  349.   if (ant != write_count - delete)
  350.   {
  351.     printf("next: I found: %d records of %d\n",ant,write_count - delete);
  352.     goto end;
  353.   }
  354.   if (nisam_rlast(file,read_record2,0) ||
  355.       bcmp(read_record2,read_record3,reclength))
  356.   {
  357.     printf("Can't find last record\n");
  358.     DBUG_DUMP("record2",(byte*) read_record2,reclength);
  359.     DBUG_DUMP("record3",(byte*) read_record3,reclength);
  360.     goto end;
  361.   }
  362.   ant=1;
  363.   while (nisam_rprev(file,read_record3,0) == 0 && ant < write_count+10)
  364.     ant++;
  365.   if (ant != write_count - delete)
  366.   {
  367.     printf("prev: I found: %d records of %d\n",ant,write_count);
  368.     goto end;
  369.   }
  370.   if (bcmp(read_record,read_record3,reclength))
  371.   {
  372.     printf("Can't find first record\n");
  373.     goto end;
  374.   }
  375.  
  376.   printf("- Test if: Read first - next - prev - prev - next == first\n");
  377.   DBUG_PRINT("progpos",("- Read first - next - prev - prev - next == first"));
  378.   if (nisam_rfirst(file,read_record,0) ||
  379.       nisam_rnext(file,read_record3,0) ||
  380.       nisam_rprev(file,read_record3,0) ||
  381.       nisam_rprev(file,read_record3,0) == 0 ||
  382.       nisam_rnext(file,read_record3,0))
  383.       goto err;
  384.   if (bcmp(read_record,read_record3,reclength) != 0)
  385.      printf("Can't find first record\n");
  386.  
  387.   printf("- Test if: Read last - prev - next - next - prev == last\n");
  388.   DBUG_PRINT("progpos",("Read last - prev - next - next - prev == last"));
  389.   if (nisam_rlast(file,read_record2,0) ||
  390.       nisam_rprev(file,read_record3,0) ||
  391.       nisam_rnext(file,read_record3,0) ||
  392.       nisam_rnext(file,read_record3,0) == 0 ||
  393.       nisam_rprev(file,read_record3,0))
  394.       goto err;
  395.   if (bcmp(read_record2,read_record3,reclength))
  396.      printf("Can't find last record\n");
  397.  
  398.   puts("- Test read key-part");
  399.   strmov(key2,key);
  400.   for(i=strlen(key2) ; i-- > 1 ;)
  401.   {
  402.     key2[i]=0;
  403.     if (nisam_rkey(file,read_record,0,key2,(uint) i,HA_READ_KEY_EXACT)) goto err;
  404.     if (bcmp(read_record+start,key,(uint) i))
  405.     {
  406.       puts("Didn't find right record");
  407.       goto end;
  408.     }
  409.   }
  410.   if (dupp_keys > 2)
  411.   {
  412.     printf("- Read key (first) - next - delete - next -> last\n");
  413.     DBUG_PRINT("progpos",("first - next - delete - next -> last"));
  414.     if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err;
  415.     if (nisam_rnext(file,read_record3,0)) goto err;
  416.     if (nisam_delete(file,read_record3)) goto err;
  417.     delete++;
  418.     ant=1;
  419.     while (nisam_rnext(file,read_record3,0) == 0 &&
  420.        bcmp(read_record3+start,key,length) == 0) ant++;
  421.     if (ant != dupp_keys-1)
  422.     {
  423.       printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1);
  424.       goto end;
  425.     }
  426.   }
  427.   if (dupp_keys>4)
  428.   {
  429.     printf("- Read last of key - prev - delete - prev -> first\n");
  430.     DBUG_PRINT("progpos",("last - prev - delete - prev -> first"));
  431.     if (nisam_rprev(file,read_record3,0)) goto err;
  432.     if (nisam_rprev(file,read_record3,0)) goto err;
  433.     if (nisam_delete(file,read_record3)) goto err;
  434.     delete++;
  435.     ant=1;
  436.     while (nisam_rprev(file,read_record3,0) == 0 &&
  437.        bcmp(read_record3+start,key,length) == 0) ant++;
  438.     if (ant != dupp_keys-2)
  439.     {
  440.       printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2);
  441.       goto end;
  442.     }
  443.   }
  444.   if (dupp_keys > 6)
  445.   {
  446.     printf("- Read first - delete - next -> last\n");
  447.     DBUG_PRINT("progpos",("first - delete - next -> last"));
  448.     if (nisam_rkey(file,read_record3,0,key,0,HA_READ_KEY_EXACT)) goto err;
  449.     if (nisam_delete(file,read_record3)) goto err;
  450.     delete++;
  451.     ant=1;
  452.     if (nisam_rnext(file,read_record,0))
  453.       goto err;                    /* Skall finnas poster */
  454.     while (nisam_rnext(file,read_record3,0) == 0 &&
  455.        bcmp(read_record3+start,key,length) == 0) ant++;
  456.     if (ant != dupp_keys-3)
  457.     {
  458.       printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3);
  459.       goto end;
  460.     }
  461.  
  462.     printf("- Read last - delete - prev -> first\n");
  463.     DBUG_PRINT("progpos",("last - delete - prev -> first"));
  464.     if (nisam_rprev(file,read_record3,0)) goto err;
  465.     if (nisam_delete(file,read_record3)) goto err;
  466.     delete++;
  467.     ant=0;
  468.     while (nisam_rprev(file,read_record3,0) == 0 &&
  469.        bcmp(read_record3+start,key,length) == 0) ant++;
  470.     if (ant != dupp_keys-4)
  471.     {
  472.       printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4);
  473.       goto end;
  474.     }
  475.   }
  476.  
  477.   puts("- Test if: Read rrnd - same");
  478.   DBUG_PRINT("progpos",("Read rrnd - same"));
  479.   for (i=0 ; i < write_count ; i++)
  480.   {
  481.     if (nisam_rrnd(file,read_record,i == 0 ? 0L : NI_POS_ERROR) == 0)
  482.       break;
  483.   }
  484.   if (i == write_count)
  485.     goto err;
  486.  
  487.   bmove(read_record2,read_record,reclength);
  488.   for (i=2 ; i-- > 0 ;)
  489.   {
  490.     if (nisam_rsame(file,read_record2,(int) i)) goto err;
  491.     if (bcmp(read_record,read_record2,reclength) != 0)
  492.     {
  493.       printf("is_rsame didn't find same record\n");
  494.       goto end;
  495.     }
  496.   }
  497.   puts("- Test nisam_records_in_range");
  498.   nisam_info(file,&info,HA_STATUS_VARIABLE);
  499.   for (i=0 ; i < info.keys ; i++)
  500.   {
  501.     if (nisam_rfirst(file,read_record,(int) i) ||
  502.     nisam_rlast(file,read_record2,(int) i))
  503.       goto err;
  504.     copy_key(file,(uint) i,(uchar*) read_record,(uchar*) key);
  505.     copy_key(file,(uint) i,(uchar*) read_record2,(uchar*) key2);
  506.     range_records=nisam_records_in_range(file,(int) i,key,0,HA_READ_KEY_EXACT,
  507.                       key2,0,HA_READ_AFTER_KEY);
  508.     if (range_records < info.records*8/10 ||
  509.     range_records > info.records*12/10)
  510.     {
  511.       printf("ni_records_range returned %lu; Should be about %lu\n",
  512.          range_records,info.records);
  513.       goto end;
  514.     }
  515.     if (verbose)
  516.     {
  517.       printf("ni_records_range returned %ld;  Exact is %ld  (diff: %4.2g %%)\n",
  518.          range_records,info.records,
  519.          labs((long) range_records - (long) info.records)*100.0/
  520.          info.records);
  521.  
  522.     }
  523.   }
  524.   for (i=0 ; i < 5 ; i++)
  525.   {
  526.     for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
  527.     for (k=rnd(1000) ; k>0 && key1[k] == 0 ; k--) ;
  528.     if (j != 0 && k != 0)
  529.     {
  530.       if (j > k)
  531.     swap(int,j,k);
  532.       sprintf(key,"%6d",j);
  533.       sprintf(key2,"%6d",k);
  534.       range_records=nisam_records_in_range(file,0,key,0,HA_READ_AFTER_KEY,
  535.                     key2,0,HA_READ_BEFORE_KEY);
  536.       records=0;
  537.       for (j++ ; j < k ; j++)
  538.     records+=key1[j];
  539.       if ((long) range_records < (long) records*7/10-2 ||
  540.       (long) range_records > (long) records*13/10+2)
  541.       {
  542.     printf("ni_records_range returned %ld; Should be about %ld\n",
  543.            range_records,records);
  544.     goto end;
  545.       }
  546.       if (verbose && records)
  547.       {
  548.     printf("ni_records_range returned %ld;  Exact is %ld  (diff: %4.2g %%)\n",
  549.            range_records,records,
  550.            labs((long) range_records-(long) records)*100.0/records);
  551.  
  552.       }
  553.     }
  554.     }
  555.  
  556.   printf("- nisam_info\n");
  557.   nisam_info(file,&info,0);
  558.   if (info.records != write_count-delete || info.deleted > delete + update
  559.       || info.keys != keys)
  560.   {
  561.     puts("Wrong info from nisam_info");
  562.     printf("Got: records: %ld  delete: %ld  i_keys: %d\n",
  563.        info.records,info.deleted,info.keys);
  564.   }
  565.   if (verbose)
  566.   {
  567.     char buff[80];
  568.     get_date(buff,3,info.create_time);
  569.     printf("info: Created %s\n",buff);
  570.     get_date(buff,3,info.isamchk_time);
  571.     printf("info: checked %s\n",buff);
  572.     get_date(buff,3,info.update_time);
  573.     printf("info: Modified %s\n",buff);
  574.   }
  575.  
  576.   nisam_panic(HA_PANIC_WRITE);
  577.   nisam_panic(HA_PANIC_READ);
  578.   if (nisam_is_changed(file))
  579.     puts("Warning: nisam_is_changed reported that datafile was changed");
  580.  
  581.   printf("- nisam_extra(CACHE) + nisam_rrnd.... + nisam_extra(NO_CACHE)\n");
  582.   if (nisam_extra(file,HA_EXTRA_RESET) || nisam_extra(file,HA_EXTRA_CACHE))
  583.   {
  584.     if (locking || (!use_blob && !pack_fields))
  585.     {
  586.       puts("got error from nisam_extra(HA_EXTRA_CACHE)");
  587.       goto end;
  588.     }
  589.   }
  590.   ant=0;
  591.   while ((error=nisam_rrnd(file,record,NI_POS_ERROR)) >= 0 &&
  592.      ant < write_count + 10)
  593.     ant+= error ? 0 : 1;
  594.   if (ant != write_count-delete)
  595.   {
  596.     printf("rrnd with cache: I can only find: %d records of %d\n",
  597.        ant,write_count-delete);
  598.     goto end;
  599.   }
  600.   if (nisam_extra(file,HA_EXTRA_NO_CACHE))
  601.   {
  602.     puts("got error from nisam_extra(HA_EXTRA_NO_CACHE)");
  603.     goto end;
  604.   }
  605.  
  606.   if (testflag == 4) goto end;
  607.  
  608.   printf("- Removing keys\n");
  609.   lastpos = NI_POS_ERROR;
  610.   /* DBUG_POP(); */
  611.   nisam_extra(file,HA_EXTRA_RESET);
  612.   while ((error=nisam_rrnd(file,read_record,NI_POS_ERROR)) >=0)
  613.   {
  614.     nisam_info(file,&info,1);
  615.     if (lastpos >= info.recpos && lastpos != NI_POS_ERROR)
  616.     {
  617.       printf("nisam_rrnd didn't advance filepointer; old: %ld, new: %ld\n",
  618.          lastpos,info.recpos);
  619.       goto err;
  620.     }
  621.     lastpos=info.recpos;
  622.     if (error == 0)
  623.     {
  624.       if (nisam_rsame(file,read_record,-1))
  625.       {
  626.     printf("can't find record %lx\n",info.recpos);
  627.     goto err;
  628.       }
  629.       if (use_blob)
  630.       {
  631.     ulong blob_length,pos;
  632.     uchar *ptr;
  633.     longget(blob_length,read_record+blob_pos+4);
  634.     ptr=(uchar*) blob_length;
  635.     longget(blob_length,read_record+blob_pos);
  636.     for (pos=0 ; pos < blob_length ; pos++)
  637.     {
  638.       if (ptr[pos] != (uchar) (blob_length+pos))
  639.       {
  640.         printf("found blob with wrong info at %ld\n",lastpos);
  641.         use_blob=0;
  642.         break;
  643.       }
  644.     }
  645.       }
  646.       if (nisam_delete(file,read_record))
  647.       {
  648.     printf("can't delete record: %s\n",read_record);
  649.     goto err;
  650.       }
  651.       delete++;
  652.     }
  653.   }
  654.   if (my_errno != HA_ERR_END_OF_FILE && my_errno != HA_ERR_RECORD_DELETED)
  655.     printf("error: %d from nisam_rrnd\n",my_errno);
  656.   if (write_count != delete)
  657.   {
  658.     printf("Deleted only %d of %d records\n",write_count,delete);
  659.     goto err;
  660.   }
  661. end:
  662.   if (nisam_close(file))
  663.     goto err;
  664.   nisam_panic(HA_PANIC_CLOSE);            /* Should close log */
  665.   printf("\nFollowing test have been made:\n");
  666.   printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,delete);
  667.   if (rec_pointer_size)
  668.     printf("Record pointer size: %d\n",rec_pointer_size);
  669.   if (key_cacheing)
  670.     puts("Key cacheing used");
  671.   if (write_cacheing)
  672.     puts("Write cacheing used");
  673.   if (async_io && locking)
  674.     puts("Asyncron io with locking used");
  675.   else if (locking)
  676.     puts("Locking used");
  677.   if (use_blob)
  678.     puts("blobs used");
  679.   end_key_cache();
  680.   if (blob_buffer)
  681.     my_free(blob_buffer,MYF(0));
  682.   my_end(MY_CHECK_ERROR | MY_GIVE_INFO);
  683.   return(0);
  684. err:
  685.   printf("got error: %d when using NISAM-database\n",my_errno);
  686.   if (file)
  687.     VOID(nisam_close(file));
  688.   return(1);
  689. } /* main */
  690.  
  691.  
  692.     /* l{ser optioner */
  693.     /* OBS! intierar endast DEBUG - ingen debuggning h{r ! */
  694.  
  695. static void get_options(argc,argv)
  696. int argc;
  697. char *argv[];
  698. {
  699.   char *pos,*progname;
  700.   DEBUGGER_OFF;
  701.  
  702.   progname= argv[0];
  703.  
  704.   while (--argc >0 && *(pos = *(++argv)) == '-' ) {
  705.     switch(*++pos) {
  706.     case 'b':
  707.       if (*++pos)
  708.     nisam_block_size= MY_ALIGN(atoi(pos),512);
  709.       set_if_bigger(nisam_block_size,8192);    /* Max block size */
  710.       set_if_smaller(nisam_block_size,1024);
  711.       break;
  712.     case 'B':
  713.       use_blob=1;
  714.       break;
  715.     case 'K':                /* Use key cacheing */
  716.       key_cacheing=1;
  717.       break;
  718.     case 'W':                /* Use write cacheing */
  719.       write_cacheing=1;
  720.       if (*++pos)
  721.     my_default_record_cache_size=atoi(pos);
  722.       break;
  723.     case 'i':
  724.       if (*++pos)
  725.     srand(atoi(pos));
  726.       break;
  727.     case 'l':
  728.       use_log=1;
  729.       break;
  730.     case 'L':
  731.       locking=1;
  732.       break;
  733.     case 'A':                /* use asyncron io */
  734.       async_io=1;
  735.       if (*++pos)
  736.     my_default_record_cache_size=atoi(pos);
  737.       break;
  738.     case 'v':                /* verbose */
  739.       verbose=1;
  740.       break;
  741.     case 'm':                /* records */
  742.       recant=atoi(++pos);
  743.       break;
  744.     case 'f':
  745.       if ((first_key=atoi(++pos)) <0 || first_key >= NISAM_KEYS)
  746.     first_key=0;
  747.       break;
  748.     case 'k':
  749.       if ((keys=(uint) atoi(++pos)) < 1 ||
  750.        keys > (uint) (NISAM_KEYS-first_key))
  751.     keys=NISAM_KEYS-first_key;
  752.       break;
  753.     case 'P':
  754.       pack_type=0;            /* Don't use DIFF_LENGTH */
  755.       break;
  756.     case 'R':                /* Length of record pointer */
  757.       rec_pointer_size=atoi(++pos);
  758.       if (rec_pointer_size > 3)
  759.     rec_pointer_size=0;
  760.       break;
  761.     case 'S':
  762.       pack_fields=0;            /* Static-length-records */
  763.       break;
  764.     case 't':
  765.       testflag=atoi(++pos);        /* testmod */
  766.       break;
  767.     case '?':
  768.     case 'I':
  769.     case 'V':
  770.       printf("%s  Ver 1.4 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
  771.       puts("TCX Datakonsult AB, by Monty, for your professional use\n");
  772.       printf("Usage: %s [-?ABIKLPRSVWltv] [-b#] [-k#] [-f#] [-m#] [-t#]\n",progname);
  773.       exit(0);
  774.     case '#':
  775.       DEBUGGER_ON;
  776.       DBUG_PUSH (++pos);
  777.       break;
  778.     default:
  779.       printf("Illegal option: '%c'\n",*pos);
  780.       break;
  781.     }
  782.   }
  783.   return;
  784. } /* get options */
  785.  
  786.     /* Ge ett randomv{rde inom ett intervall 0 <=x <= n */
  787.  
  788. static uint rnd(max_value)
  789. uint max_value;
  790. {
  791.   return (uint) ((rand() & 32767)/32767.0*max_value);
  792. } /* rnd */
  793.  
  794.  
  795.     /* G|r en record av skiftande length */
  796.  
  797. static void fix_length(rec,length)
  798. byte *rec;
  799. uint length;
  800. {
  801.   bmove(rec+STANDAR_LENGTH,
  802.     "0123456789012345678901234567890123456789012345678901234567890",
  803.     length-STANDAR_LENGTH);
  804.   strfill(rec+length,STANDAR_LENGTH+60-length,' ');
  805. } /* fix_length */
  806.  
  807.  
  808.     /* Put maybe a blob in record */
  809.  
  810. static void put_blob_in_record(blob_pos,blob_buffer)
  811. char *blob_pos,**blob_buffer;
  812. {
  813.   ulong i,length;
  814.   if (use_blob)
  815.   {
  816.     if (rnd(10) == 0)
  817.     {
  818.       if (! *blob_buffer &&
  819.       !(*blob_buffer=my_malloc((uint) use_blob,MYF(MY_WME))))
  820.       {
  821.     use_blob=0;
  822.     return;
  823.       }
  824.       length=rnd(use_blob);
  825.       for (i=0 ; i < length ; i++)
  826.     (*blob_buffer)[i]=(char) (length+i);
  827.       longstore(blob_pos,length);
  828.       bmove(blob_pos+4,(char*) blob_buffer,sizeof(char*));
  829.     }
  830.     else
  831.     {
  832.       longstore(blob_pos,0);
  833.     }
  834.   }
  835.   return;
  836. }
  837.  
  838.  
  839. static void copy_key(info,inx,rec,key_buff)
  840. N_INFO *info;
  841. uint inx;
  842. uchar *rec,*key_buff;
  843. {
  844.   N_KEYSEG *keyseg;
  845.  
  846.   for (keyseg=info->s->keyinfo[inx].seg ; keyseg->base.type ; keyseg++)
  847.   {
  848.     memcpy(key_buff,rec+keyseg->base.start,(size_t) keyseg->base.length);
  849.     key_buff+=keyseg->base.length;
  850.   }
  851.   return;
  852. }
  853.