mi_test2.c 29.5 KB
Newer Older
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3 4 5 6
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
7

bk@work.mysql.com's avatar
bk@work.mysql.com committed
8 9 10 11
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
12

bk@work.mysql.com's avatar
bk@work.mysql.com committed
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/* Test av isam-databas: stor test */

#ifndef USE_MY_FUNC		/* We want to be able to dbug this !! */
#define USE_MY_FUNC
#endif
#ifdef DBUG_OFF
#undef DBUG_OFF
#endif
#ifndef SAFEMALLOC
#define SAFEMALLOC
#endif
#include "myisamdef.h"
#include <m_ctype.h>

#define STANDARD_LENGTH 37
#define MYISAM_KEYS 6
#define MAX_PARTS 4
#if !defined(MSDOS) && !defined(labs)
#define labs(a) abs(a)
#endif

static void get_options(int argc, char *argv[]);
static uint rnd(uint max_value);
static void fix_length(byte *record,uint length);
static void put_blob_in_record(char *blob_pos,char **blob_buffer);
static void copy_key(struct st_myisam_info *info,uint inx,
		     uchar *record,uchar *key);

static	int verbose=0,testflag=0,
	    first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,locking=0,
47 48
            rec_pointer_size=0,pack_fields=1,use_log=0,silent=0,
            opt_quick_mode=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
49 50 51
static int pack_seg=HA_SPACE_PACK,pack_type=HA_PACK_KEY,remove_count=-1,
	   create_flag=0;
static ulong key_cache_size=IO_SIZE*16;
52
static uint key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
53 54 55 56 57 58

static uint keys=MYISAM_KEYS,recant=1000;
static uint use_blob=0;
static uint16 key1[1001],key3[5000];
static char record[300],record2[300],key[100],key2[100],
	    read_record[300],read_record2[300],read_record3[300];
59
static HA_KEYSEG glob_keyseg[MYISAM_KEYS][MAX_PARTS];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
60 61 62

		/* Test program */

monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
63
int main(int argc, char *argv[])
bk@work.mysql.com's avatar
bk@work.mysql.com committed
64 65 66
{
  uint i;
  int j,n1,n2,n3,error,k;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
67
  uint write_count,update,dupp_keys,opt_delete,start,length,blob_pos,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
       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;
91
  keyinfo[0].seg[0].language= default_charset_info->number;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
92 93 94
  keyinfo[0].seg[0].flag=(uint8) pack_seg;
  keyinfo[0].seg[0].null_bit=0;
  keyinfo[0].seg[0].null_pos=0;
95
  keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
  keyinfo[0].keysegs=1;
  keyinfo[0].flag = pack_type;
  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;
111
  keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
112 113 114 115 116 117 118 119 120
  keyinfo[1].keysegs=2;
  keyinfo[1].flag =0;
  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;
121
  keyinfo[2].key_alg=HA_KEY_ALG_BTREE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
122 123 124 125 126 127
  keyinfo[2].keysegs=1;
  keyinfo[2].flag =HA_NOSAME;
  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;
128
  keyinfo[3].seg[0].language=default_charset_info->number;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
129 130 131
  keyinfo[3].seg[0].flag=(uint8) pack_seg;
  keyinfo[3].seg[0].null_bit=0;
  keyinfo[3].seg[0].null_pos=0;
132
  keyinfo[3].key_alg=HA_KEY_ALG_BTREE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
133 134 135 136 137 138
  keyinfo[3].keysegs=1;
  keyinfo[3].flag = pack_type;
  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;
139
  keyinfo[4].seg[0].language=default_charset_info->number;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
140 141 142
  keyinfo[4].seg[0].flag=0;
  keyinfo[4].seg[0].null_bit=0;
  keyinfo[4].seg[0].null_pos=0;
143
  keyinfo[4].key_alg=HA_KEY_ALG_BTREE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
144 145 146 147 148 149
  keyinfo[4].keysegs=1;
  keyinfo[4].flag = pack_type;
  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;
150
  keyinfo[5].seg[0].language=default_charset_info->number;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
151 152 153
  keyinfo[5].seg[0].flag=pack_seg;
  keyinfo[5].seg[0].null_bit=0;
  keyinfo[5].seg[0].null_pos=0;
154
  keyinfo[5].key_alg=HA_KEY_ALG_BTREE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
155 156 157
  keyinfo[5].keysegs=1;
  keyinfo[5].flag = pack_type;

monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
158
  recinfo[0].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
159 160 161
  recinfo[0].length=7;
  recinfo[0].null_bit=0;
  recinfo[0].null_pos=0;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
162
  recinfo[1].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
163 164 165
  recinfo[1].length=5;
  recinfo[1].null_bit=0;
  recinfo[1].null_pos=0;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
166
  recinfo[2].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
167 168 169 170 171 172 173
  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;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
174
  recinfo[4].type=pack_fields ? FIELD_SKIP_ZERO : 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
175 176 177
  recinfo[4].length=4;
  recinfo[4].null_bit=0;
  recinfo[4].null_pos=0;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
178
  recinfo[5].type=pack_fields ? FIELD_SKIP_ENDSPACE : 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
179 180 181 182 183 184 185 186 187 188 189
  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+mi_portable_sizeof_char_ptr;
    recinfo[6].null_bit=0;
    recinfo[6].null_pos=0;
  }

monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
190
  write_count=update=dupp_keys=opt_delete=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
  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)
218
    init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
219 220 221
  if (locking)
    mi_lock_database(file,F_WRLCK);
  if (write_cacheing)
222
    mi_extra(file,HA_EXTRA_WRITE_CACHE,0);
223
  if (opt_quick_mode)
224
    mi_extra(file,HA_EXTRA_QUICK,0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270

  for (i=0 ; i < recant ; i++)
  {
    n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
    sprintf(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(key,"%6d",j);
      if (mi_rkey(file,read_record,0,key,0,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)
271 272
  {
    if (mi_extra(file,HA_EXTRA_NO_CACHE,0))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
273 274 275 276
    {
      puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
      goto end;
    }
277
  }
278
  if (key_cacheing)
279
    resize_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size*2,0,0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
280 281 282 283 284 285 286 287 288 289 290 291 292 293

  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(key,"%6d",j);
      if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
      {
	printf("can't find key1: \"%s\"\n",key);
	goto err;
      }
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
294
      if (opt_delete == (uint) remove_count)		/* While testing */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
295 296 297 298 299 300
	goto end;
      if (mi_delete(file,read_record))
      {
	printf("error: %d; can't delete record: \"%s\"\n", my_errno,read_record);
	goto err;
      }
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
301
      opt_delete++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
      key1[atoi(read_record+keyinfo[0].seg[0].start)]--;
      key3[atoi(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(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(key,"%6d",j);
      if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
      {
	printf("can't find key1: \"%s\"\n",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)
	{
339
	  printf("error: %d; can't update:\nFrom: \"%s\"\nTo:   \"%s\"\n",
bk@work.mysql.com's avatar
bk@work.mysql.com committed
340 341 342 343
		 my_errno,read_record,record2);
	  goto err;
	}
	if (verbose)
344
	  printf("Double key when tried to update:\nFrom: \"%s\"\nTo:   \"%s\"\n",record,record2);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
345 346 347 348 349 350 351 352 353 354
      }
      else
      {
	key1[atoi(read_record+keyinfo[0].seg[0].start)]--;
	key3[atoi(read_record+keyinfo[2].seg[0].start)]=0;
	key1[n1]++; key3[n3]=1;
	update++;
      }
    }
  }
355 356
  if (testflag == 3)
    goto end;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
357 358 359

  for (i=999, dupp_keys=j=0 ; i>0 ; i--)
  {
360 361 362 363
    if (key1[i] > dupp_keys)
    {
      dupp_keys=key1[i]; j=i;
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
364 365
  }
  sprintf(key,"%6d",j);
366 367
  start=keyinfo[0].seg[0].start;
  length=keyinfo[0].seg[0].length;
368
  if (dupp_keys)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
369
  {
370 371 372 373 374
    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);

375 376 377 378
    if (mi_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
      goto err;
    if (mi_rsame(file,read_record2,-1))
      goto err;
379 380 381 382 383 384 385 386
    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) ||
bk@work.mysql.com's avatar
bk@work.mysql.com committed
387 388
	memcmp(read_record,read_record2,reclength) != 0)
    {
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415
      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 &&
	   bcmp(read_record3+start,key,length) == 0) ant++;
    if (ant != dupp_keys)
    {
      printf("prev: Found: %d records of %d\n",ant,dupp_keys);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
416 417 418
      goto end;
    }

419 420 421 422 423 424 425 426 427 428 429
    /* Check of mi_rnext_same */
    if (mi_rkey(file,read_record,0,key,0,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;
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
430 431 432 433 434 435 436 437 438 439 440 441 442
  }

  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++;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
443
  if (ant != write_count - opt_delete || error != HA_ERR_END_OF_FILE)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
444 445
  {
    printf("next: I found: %d records of %d (error: %d)\n",
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
446
	   ant, write_count - opt_delete, error);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
447 448 449 450 451 452 453 454 455 456 457 458 459
    goto end;
  }
  if (mi_rlast(file,read_record2,0) ||
      bcmp(read_record2,read_record3,reclength))
  {
    printf("Can't find last record\n");
    DBUG_DUMP("record2",(byte*) read_record2,reclength);
    DBUG_DUMP("record3",(byte*) read_record3,reclength);
    goto end;
  }
  ant=1;
  while (mi_rprev(file,read_record3,0) == 0 && ant < write_count+10)
    ant++;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
460
  if (ant != write_count - opt_delete)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
  {
    printf("prev: I found: %d records of %d\n",ant,write_count);
    goto end;
  }
  if (bcmp(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 (bcmp(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 (bcmp(read_record2,read_record3,reclength))
     printf("Can't find last record\n");

  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 (bcmp(read_record+start,key,(uint) i))
    {
      puts("Didn't find right record");
      goto end;
    }
  }
  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,0,HA_READ_KEY_EXACT)) goto err;
    if (mi_rnext(file,read_record3,0)) goto err;
    if (mi_delete(file,read_record3)) goto err;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
520
    opt_delete++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
    ant=1;
    while (mi_rnext(file,read_record3,0) == 0 &&
	   bcmp(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;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
538
    opt_delete++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
    ant=1;
    while (mi_rprev(file,read_record3,0) == 0 &&
	   bcmp(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,0,HA_READ_KEY_EXACT)) goto err;
    if (mi_delete(file,read_record3)) goto err;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
555
    opt_delete++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
    ant=1;
    if (mi_rnext(file,read_record,0))
      goto err;					/* Skall finnas poster */
    while (mi_rnext(file,read_record3,0) == 0 &&
	   bcmp(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;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
572
    opt_delete++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
    ant=0;
    while (mi_rprev(file,read_record3,0) == 0 &&
	   bcmp(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 (bcmp(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++)
  {
609
    key_range min_key, max_key;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
610 611 612 613 614
    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);
615 616 617 618 619 620 621 622
    min_key.key= key;
    min_key.length= USE_WHOLE_KEY;
    min_key.flag= HA_READ_KEY_EXACT;
    max_key.key= key2;
    max_key.length= USE_WHOLE_KEY;
    max_key.flag= HA_READ_AFTER_KEY;

    range_records= mi_records_in_range(file,(int) i, &min_key, &max_key);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
    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)
    {
644
      key_range min_key, max_key;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
645
      if (j > k)
646
	swap_variables(int, j, k);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
647 648
      sprintf(key,"%6d",j);
      sprintf(key2,"%6d",k);
649 650 651 652 653 654 655 656

      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);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
657 658 659 660 661 662
      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)
      {
663 664
	printf("mi_records_range for key: %d returned %lu; Should be about %lu\n",
	       i, (ulong) range_records, (ulong) records);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
665 666 667 668
	goto end;
      }
      if (verbose && records)
      {
669 670
	printf("mi_records_range returned %lu;  Exact is %lu  (diff: %4.2g %%)\n",
	       (ulong) range_records, (ulong) records,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
671 672 673 674 675 676 677 678 679
	       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);
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
680
  if (info.records != write_count-opt_delete || info.deleted > opt_delete + update
bk@work.mysql.com's avatar
bk@work.mysql.com committed
681 682 683
      || info.keys != keys)
  {
    puts("Wrong info from mi_info");
684 685
    printf("Got: records: %lu  delete: %lu  i_keys: %d\n",
	   (ulong) info.records, (ulong) info.deleted, info.keys);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
  }
  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");
705
  if (mi_extra(file,HA_EXTRA_RESET,0) || mi_extra(file,HA_EXTRA_CACHE,0))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
706 707 708 709 710 711 712 713 714 715 716
  {
    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;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
717
  if (ant != write_count-opt_delete)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
718 719
  {
    printf("rrnd with cache: I can only find: %d records of %d\n",
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
720
	   ant,write_count-opt_delete);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
721 722
    goto end;
  }
723
  if (mi_extra(file,HA_EXTRA_NO_CACHE,0))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
724 725 726 727 728 729 730 731 732 733
  {
    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;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
734
  if (ant != write_count-opt_delete)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
735 736
  {
    printf("scan with cache: I can only find: %d records of %d\n",
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
737
	   ant,write_count-opt_delete);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
738 739 740 741 742 743 744 745 746 747
    goto end;
  }

  if (testflag == 4) goto end;

  if (!silent)
    printf("- Removing keys\n");
  DBUG_PRINT("progpos",("Removing keys"));
  lastpos = HA_OFFSET_ERROR;
  /* DBUG_POP(); */
748
  mi_extra(file,HA_EXTRA_RESET,0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
749 750 751 752 753 754 755 756 757 758 759 760 761 762
  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)
    {
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
763
      if (opt_delete == (uint) remove_count)		/* While testing */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789
	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",
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
790
	       read_record, opt_delete);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
791 792
	goto err;
      }
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
793
      opt_delete++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
794 795 796 797 798 799
    }
    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);
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
800
  if (write_count != opt_delete)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
801
  {
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
802
    printf("Deleted only %d of %d records (%d parts)\n",opt_delete,write_count,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
803 804 805 806 807 808 809 810 811 812
	   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");
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
813
    printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
814
    if (rec_pointer_size)
815 816
      printf("Record pointer size:  %d\n",rec_pointer_size);
    printf("myisam_block_size:    %u\n", myisam_block_size);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
817
    if (key_cacheing)
818
    {
819
      puts("Key cache used");
820
      printf("key_cache_block_size: %u\n", key_cache_block_size);
821 822
      if (write_cacheing)
	puts("Key cache resized");
823
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
824 825
    if (write_cacheing)
      puts("Write cacheing used");
826 827
    if (write_cacheing)
      puts("quick mode");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
828 829 830 831 832 833 834 835
    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\
836
not flushed:%10lu\n\
bk@work.mysql.com's avatar
bk@work.mysql.com committed
837 838 839 840
w_requests: %10lu\n\
writes:     %10lu\n\
r_requests: %10lu\n\
reads:      %10lu\n",
841 842 843 844 845 846
           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);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
847
  }
848
  end_key_cache(dflt_key_cache,1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
849 850
  if (blob_buffer)
    my_free(blob_buffer,MYF(0));
851
  my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910
  return(0);
err:
  printf("got error: %d when using MyISAM-database\n",my_errno);
  if (file)
    VOID(mi_close(file));
  return(1);
} /* main */


	/* l{ser optioner */
	/* OBS! intierar endast DEBUG - ingen debuggning h{r ! */

static void get_options(int argc, char **argv)
{
  char *pos,*progname;
  DEBUGGER_OFF;

  progname= argv[0];

  while (--argc >0 && *(pos = *(++argv)) == '-' ) {
    switch(*++pos) {
    case 'B':
      pack_type= HA_BINARY_PACK_KEY;
      break;
    case 'b':
      use_blob=1;
      break;
    case 'K':				/* Use key cacheing */
      key_cacheing=1;
      if (*++pos)
	key_cache_size=atol(pos);
      break;
    case 'W':				/* Use write cacheing */
      write_cacheing=1;
      if (*++pos)
	my_default_record_cache_size=atoi(pos);
      break;
    case 'd':
      remove_count= atoi(++pos);
      break;
    case 'i':
      if (*++pos)
	srand(atoi(pos));
      break;
    case 'l':
      use_log=1;
      break;
    case 'L':
      locking=1;
      break;
    case 'A':				/* use asyncron io */
      async_io=1;
      if (*++pos)
	my_default_record_cache_size=atoi(pos);
      break;
    case 'v':				/* verbose */
      verbose=1;
      break;
    case 'm':				/* records */
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
      if ((recant=atoi(++pos)) < 10)
      {
	fprintf(stderr,"record count must be >= 10\n");
	exit(1);
      }
      break;
    case 'e':				/* myisam_block_length */
      if ((myisam_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
	  myisam_block_size > MI_MAX_KEY_BLOCK_LENGTH)
      {
	fprintf(stderr,"Wrong myisam_block_length\n");
	exit(1);
      }
      myisam_block_size=1 << my_bit_log2(myisam_block_size);
      break;
    case 'E':				/* myisam_block_length */
      if ((key_cache_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
	  key_cache_block_size > MI_MAX_KEY_BLOCK_LENGTH)
      {
	fprintf(stderr,"Wrong key_cache_block_size\n");
	exit(1);
      }
      key_cache_block_size=1 << my_bit_log2(key_cache_block_size);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
      break;
    case 'f':
      if ((first_key=atoi(++pos)) < 0 || first_key >= MYISAM_KEYS)
	first_key=0;
      break;
    case 'k':
      if ((keys=(uint) atoi(++pos)) < 1 ||
	   keys > (uint) (MYISAM_KEYS-first_key))
	keys=MYISAM_KEYS-first_key;
      break;
    case 'P':
      pack_type=0;			/* Don't use DIFF_LENGTH */
      pack_seg=0;
      break;
    case 'R':				/* Length of record pointer */
      rec_pointer_size=atoi(++pos);
      if (rec_pointer_size > 7)
	rec_pointer_size=0;
      break;
    case 'S':
      pack_fields=0;			/* Static-length-records */
      break;
    case 's':
      silent=1;
      break;
    case 't':
      testflag=atoi(++pos);		/* testmod */
      break;
962 963 964
    case 'q':
      opt_quick_mode=1;
      break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
965 966 967 968 969 970 971 972 973
    case 'c':
      create_flag|= HA_CREATE_CHECKSUM;
      break;
    case 'D':
      create_flag|=HA_CREATE_DELAY_KEY_WRITE;
      break;
    case '?':
    case 'I':
    case 'V':
974
      printf("%s  Ver 1.2 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
975
      puts("By Monty, for your professional use\n");
976
      printf("Usage: %s [-?AbBcDIKLPRqSsVWltv] [-k#] [-f#] [-m#] [-e#] [-E#] [-t#]\n",
bk@work.mysql.com's avatar
bk@work.mysql.com committed
977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
	     progname);
      exit(0);
    case '#':
      DEBUGGER_ON;
      DBUG_PUSH (++pos);
      break;
    default:
      printf("Illegal option: '%c'\n",*pos);
      break;
    }
  }
  return;
} /* get options */

	/* Get a random value 0 <= x <= n */

static uint rnd(uint max_value)
{
  return (uint) ((rand() & 32767)/32767.0*max_value);
} /* rnd */


	/* Create a variable length record */

static void fix_length(byte *rec, uint length)
{
  bmove(rec+STANDARD_LENGTH,
	"0123456789012345678901234567890123456789012345678901234567890",
	length-STANDARD_LENGTH);
  strfill(rec+length,STANDARD_LENGTH+60-length,' ');
} /* fix_length */


	/* Put maybe a blob in record */

static void put_blob_in_record(char *blob_pos, char **blob_buffer)
{
  ulong i,length;
  if (use_blob)
  {
    if (rnd(10) == 0)
    {
      if (! *blob_buffer &&
	  !(*blob_buffer=my_malloc((uint) use_blob,MYF(MY_WME))))
      {
	use_blob=0;
	return;
      }
      length=rnd(use_blob);
      for (i=0 ; i < length ; i++)
	(*blob_buffer)[i]=(char) (length+i);
      int4store(blob_pos,length);
      memcpy_fixed(blob_pos+4,(char*) blob_buffer,sizeof(char*));
    }
    else
    {
      int4store(blob_pos,0);
    }
  }
  return;
}


static void copy_key(MI_INFO *info,uint inx,uchar *rec,uchar *key_buff)
{
1042
  HA_KEYSEG *keyseg;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1043 1044 1045 1046 1047 1048 1049 1050

  for (keyseg=info->s->keyinfo[inx].seg ; keyseg->type ; keyseg++)
  {
    memcpy(key_buff,rec+keyseg->start,(size_t) keyseg->length);
    key_buff+=keyseg->length;
  }
  return;
}