Exemplo n.º 1
0
void start_test(int id)
{
  uint i;
  int error,lock_type;
  MI_ISAMINFO isam_info;
  MI_INFO *file,*file1,*file2=0,*lock;

  if (use_log)
    mi_log(1);
  if (!(file1=mi_open(filename,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)) ||
      !(file2=mi_open(filename,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)))
  {
    fprintf(stderr,"Can't open isam-file: %s\n",filename);
    exit(1);
  }
  if (key_cacheing && rnd(2) == 0)
    init_key_cache(dflt_key_cache, KEY_CACHE_BLOCK_SIZE, 65536L, 0, 0);
  printf("Process %d, pid: %d\n",id,getpid()); fflush(stdout);

  for (error=i=0 ; i < tests && !error; i++)
  {
    file= (rnd(2) == 1) ? file1 : file2;
    lock=0 ; lock_type=0;
    if (rnd(10) == 0)
    {
      if (mi_lock_database(lock=(rnd(2) ? file1 : file2),
			   lock_type=(rnd(2) == 0 ? F_RDLCK : F_WRLCK)))
      {
	fprintf(stderr,"%2d: start: Can't lock table %d\n",id,my_errno);
	error=1;
	break;
      }
    }
    switch (rnd(4)) {
    case 0: error=test_read(file,id); break;
    case 1: error=test_rrnd(file,id); break;
    case 2: error=test_write(file,id,lock_type); break;
    case 3: error=test_update(file,id,lock_type); break;
    }
    if (lock)
      mi_lock_database(lock,F_UNLCK);
  }
  if (!error)
  {
    mi_status(file1,&isam_info,HA_STATUS_VARIABLE);
    printf("%2d: End of test.  Records:  %ld  Deleted:  %ld\n",
	   id,(long) isam_info.records, (long) isam_info.deleted);
    fflush(stdout);
  }

  mi_close(file1);
  mi_close(file2);
  if (use_log)
    mi_log(0);
  if (error)
  {
    printf("%2d: Aborted\n",id); fflush(stdout);
    exit(1);
  }
}
Exemplo n.º 2
0
int mi_panic(enum ha_panic_function flag)
{
  int error=0;
  LIST *list_element,*next_open;
  MI_INFO *info;
  DBUG_ENTER("mi_panic");

  mysql_mutex_lock(&THR_LOCK_myisam);
  for (list_element=myisam_open_list ; list_element ; list_element=next_open)
  {
    next_open=list_element->next;		/* Save if close */
    info=(MI_INFO*) list_element->data;
    switch (flag) {
    case HA_PANIC_CLOSE:
      mysql_mutex_unlock(&THR_LOCK_myisam);     /* Not exactly right... */
      if (mi_close(info))
	error=my_errno();
      mysql_mutex_lock(&THR_LOCK_myisam);
      break;
    case HA_PANIC_WRITE:		/* Do this to free databases */
      if (flush_key_blocks(info->s->key_cache, keycache_thread_var(),
                           info->s->kfile, FLUSH_RELEASE))
	error=my_errno();
      if (info->opt_flag & WRITE_CACHE_USED)
	if (flush_io_cache(&info->rec_cache))
	  error=my_errno();
      if (info->opt_flag & READ_CACHE_USED)
      {
	if (flush_io_cache(&info->rec_cache))
	  error=my_errno();
	reinit_io_cache(&info->rec_cache,READ_CACHE,0,
		       (pbool) (info->lock_type != F_UNLCK),1);
      }
      if (info->lock_type != F_UNLCK && ! info->was_locked)
      {
	info->was_locked=info->lock_type;
	if (mi_lock_database(info,F_UNLCK))
	  error=my_errno();
      }
    case HA_PANIC_READ:			/* Restore to before WRITE */
      if (info->was_locked)
      {
	if (mi_lock_database(info, info->was_locked))
	  error=my_errno();
	info->was_locked=0;
      }
      break;
    }
  }
  if (flag == HA_PANIC_CLOSE)
  {
    (void) mi_log(0);				/* Close log if neaded */
    ft_free_stopwords();
  }
  mysql_mutex_unlock(&THR_LOCK_myisam);
  if (!error)
    DBUG_RETURN(0);
  set_my_errno(error);
  DBUG_RETURN(error);
} /* mi_panic */
Exemplo n.º 3
0
int test_write(MI_INFO *file,int id,int lock_type)
{
  uint i,tries,count,lock;

  lock=0;
  if (rnd(2) == 0 || lock_type == F_RDLCK)
  {
    lock=1;
    if (mi_lock_database(file,F_WRLCK))
    {
      if (lock_type == F_RDLCK && my_errno == EDEADLK)
      {
	printf("%2d: write:  deadlock\n",id); fflush(stdout);
	return 0;
      }
      fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
      mi_close(file);
      return 1;
    }
    if (rnd(2) == 0)
      mi_extra(file,HA_EXTRA_WRITE_CACHE,0);
  }

  sprintf((char*) record.id,"%7d",getpid());
  strnmov((char*) record.text,"Testing...", sizeof(record.text));

  tries=(uint) rnd(100)+10;
  for (i=count=0 ; i < tries ; i++)
  {
    uint32 tmp=rnd(80000)+20000;
    int4store(record.nr,tmp);
    if (!mi_write(file,record.id))
      count++;
    else
    {
      if (my_errno != HA_ERR_FOUND_DUPP_KEY)
      {
	fprintf(stderr,"%2d: Got error %d (errno %d) from write\n",id,my_errno,
		errno);
	return 1;
      }
    }
  }
  if (lock)
  {
    mi_extra(file,HA_EXTRA_NO_CACHE,0);
    if (mi_lock_database(file,F_UNLCK))
    {
      fprintf(stderr,"%2d: Can't unlock table\n",id);
      exit(0);
    }
  }
  printf("%2d: write:  %5d\n",id,count); fflush(stdout);
  return 0;
}
Exemplo n.º 4
0
int test_rrnd(MI_INFO *file,int id)
{
  uint count,lock;

  lock=0;
  if (rnd(2) == 0)
  {
    lock=1;
    if (mi_lock_database(file,F_RDLCK))
    {
      fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
      mi_close(file);
      return 1;
    }
    if (rnd(2) == 0)
      mi_extra(file,HA_EXTRA_CACHE,0);
  }

  count=0;
  if (mi_rrnd(file,record.id,0L))
  {
    if (my_errno == HA_ERR_END_OF_FILE)
      goto end;
    fprintf(stderr,"%2d: Can't read first record (%d)\n",id,my_errno);
    return 1;
  }
  for (count=1 ; !mi_rrnd(file,record.id,HA_OFFSET_ERROR) ;count++) ;
  if (my_errno != HA_ERR_END_OF_FILE)
  {
    fprintf(stderr,"%2d: Got error %d from rrnd\n",id,my_errno);
    return 1;
  }

end:
  if (lock)
  {
    mi_extra(file,HA_EXTRA_NO_CACHE,0);
    if (mi_lock_database(file,F_UNLCK))
    {
      fprintf(stderr,"%2d: Can't unlock table\n",id);
      exit(0);
    }
  }
  printf("%2d: rrnd:   %5d\n",id,count); fflush(stdout);
  return 0;
}
int myrg_lock_database(MYRG_INFO *info, int lock_type)
{
  int error,new_error;
  MYRG_TABLE *file;

  error=0;
  for (file=info->open_tables ; file != info->end_table ; file++) 
  {
    DBUG_ASSERT(file->table->open_flag & HA_OPEN_MERGE_TABLE);

    if ((new_error=mi_lock_database(file->table,lock_type)))
    {
      error=new_error;
      if (lock_type != F_UNLCK)
      {
        while (--file >= info->open_tables)
          mi_lock_database(file->table, F_UNLCK);
        break;
      }
    }
  }
  return(error);
}
Exemplo n.º 6
0
int _mi_decrement_open_count(MI_INFO *info)
{
  uchar buff[2];
  MYISAM_SHARE *share=info->s;
  int lock_error=0,write_error=0;
  if (share->global_changed)
  {
    uint old_lock=info->lock_type;
    share->global_changed=0;
    lock_error=mi_lock_database(info,F_WRLCK);
    /* Its not fatal even if we couldn't get the lock ! */
    if (share->state.open_count > 0)
    {
      share->state.open_count--;
      mi_int2store(buff,share->state.open_count);
      write_error= mysql_file_pwrite(share->kfile, buff, sizeof(buff),
                                     sizeof(share->state.header),
                                     MYF(MY_NABP));
    }
    if (!lock_error)
      lock_error=mi_lock_database(info,old_lock);
  }
  return MY_TEST(lock_error || write_error);
}
Exemplo n.º 7
0
int main(int argc, char *argv[])
{
  uint i;
  int j,n1,n2,n3,error,k;
  uint write_count,update,dupp_keys,opt_delete,start,length,blob_pos,
       reclength,ant,found_parts;
  my_off_t lastpos;
  ha_rows range_records,records;
  MI_INFO *file;
  MI_KEYDEF keyinfo[10];
  MI_COLUMNDEF recinfo[10];
  MI_ISAMINFO info;
  const char *filename;
  char *blob_buffer;
  MI_CREATE_INFO create_info;
  MY_INIT(argv[0]);

  filename= "test2";
  get_options(argc,argv);
  if (! async_io)
    my_disable_async_io=1;

  reclength=STANDARD_LENGTH+60+(use_blob ? 8 : 0);
  blob_pos=STANDARD_LENGTH+60;
  keyinfo[0].seg= &glob_keyseg[0][0];
  keyinfo[0].seg[0].start=0;
  keyinfo[0].seg[0].length=6;
  keyinfo[0].seg[0].type=HA_KEYTYPE_TEXT;
  keyinfo[0].seg[0].language= default_charset_info->number;
  keyinfo[0].seg[0].flag=(uint8) pack_seg;
  keyinfo[0].seg[0].null_bit=0;
  keyinfo[0].seg[0].null_pos=0;
  keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
  keyinfo[0].keysegs=1;
  keyinfo[0].flag = pack_type;
  keyinfo[0].block_length= 0;                   /* Default block length */
  keyinfo[1].seg= &glob_keyseg[1][0];
  keyinfo[1].seg[0].start=7;
  keyinfo[1].seg[0].length=6;
  keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY;
  keyinfo[1].seg[0].flag=0;
  keyinfo[1].seg[0].null_bit=0;
  keyinfo[1].seg[0].null_pos=0;
  keyinfo[1].seg[1].start=0;			/* two part key */
  keyinfo[1].seg[1].length=6;
  keyinfo[1].seg[1].type=HA_KEYTYPE_NUM;
  keyinfo[1].seg[1].flag=HA_REVERSE_SORT;
  keyinfo[1].seg[1].null_bit=0;
  keyinfo[1].seg[1].null_pos=0;
  keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
  keyinfo[1].keysegs=2;
  keyinfo[1].flag =0;
  keyinfo[1].block_length= MI_MIN_KEY_BLOCK_LENGTH;  /* Diff blocklength */
  keyinfo[2].seg= &glob_keyseg[2][0];
  keyinfo[2].seg[0].start=12;
  keyinfo[2].seg[0].length=8;
  keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY;
  keyinfo[2].seg[0].flag=HA_REVERSE_SORT;
  keyinfo[2].seg[0].null_bit=0;
  keyinfo[2].seg[0].null_pos=0;
  keyinfo[2].key_alg=HA_KEY_ALG_BTREE;
  keyinfo[2].keysegs=1;
  keyinfo[2].flag =HA_NOSAME;
  keyinfo[2].block_length= 0;                   /* Default block length */
  keyinfo[3].seg= &glob_keyseg[3][0];
  keyinfo[3].seg[0].start=0;
  keyinfo[3].seg[0].length=reclength-(use_blob ? 8 : 0);
  keyinfo[3].seg[0].type=HA_KEYTYPE_TEXT;
  keyinfo[3].seg[0].language=default_charset_info->number;
  keyinfo[3].seg[0].flag=(uint8) pack_seg;
  keyinfo[3].seg[0].null_bit=0;
  keyinfo[3].seg[0].null_pos=0;
  keyinfo[3].key_alg=HA_KEY_ALG_BTREE;
  keyinfo[3].keysegs=1;
  keyinfo[3].flag = pack_type;
  keyinfo[3].block_length= 0;                   /* Default block length */
  keyinfo[4].seg= &glob_keyseg[4][0];
  keyinfo[4].seg[0].start=0;
  keyinfo[4].seg[0].length=5;
  keyinfo[4].seg[0].type=HA_KEYTYPE_TEXT;
  keyinfo[4].seg[0].language=default_charset_info->number;
  keyinfo[4].seg[0].flag=0;
  keyinfo[4].seg[0].null_bit=0;
  keyinfo[4].seg[0].null_pos=0;
  keyinfo[4].key_alg=HA_KEY_ALG_BTREE;
  keyinfo[4].keysegs=1;
  keyinfo[4].flag = pack_type;
  keyinfo[4].block_length= 0;                   /* Default block length */
  keyinfo[5].seg= &glob_keyseg[5][0];
  keyinfo[5].seg[0].start=0;
  keyinfo[5].seg[0].length=4;
  keyinfo[5].seg[0].type=HA_KEYTYPE_TEXT;
  keyinfo[5].seg[0].language=default_charset_info->number;
  keyinfo[5].seg[0].flag=pack_seg;
  keyinfo[5].seg[0].null_bit=0;
  keyinfo[5].seg[0].null_pos=0;
  keyinfo[5].key_alg=HA_KEY_ALG_BTREE;
  keyinfo[5].keysegs=1;
  keyinfo[5].flag = pack_type;
  keyinfo[5].block_length= 0;                   /* Default block length */

  recinfo[0].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
  recinfo[0].length=7;
  recinfo[0].null_bit=0;
  recinfo[0].null_pos=0;
  recinfo[1].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
  recinfo[1].length=5;
  recinfo[1].null_bit=0;
  recinfo[1].null_pos=0;
  recinfo[2].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
  recinfo[2].length=9;
  recinfo[2].null_bit=0;
  recinfo[2].null_pos=0;
  recinfo[3].type=FIELD_NORMAL;
  recinfo[3].length=STANDARD_LENGTH-7-5-9-4;
  recinfo[3].null_bit=0;
  recinfo[3].null_pos=0;
  recinfo[4].type=pack_fields ? FIELD_SKIP_ZERO : 0;
  recinfo[4].length=4;
  recinfo[4].null_bit=0;
  recinfo[4].null_pos=0;
  recinfo[5].type=pack_fields ? FIELD_SKIP_ENDSPACE : 0;
  recinfo[5].length=60;
  recinfo[5].null_bit=0;
  recinfo[5].null_pos=0;
  if (use_blob)
  {
    recinfo[6].type=FIELD_BLOB;
    recinfo[6].length=4+portable_sizeof_char_ptr;
    recinfo[6].null_bit=0;
    recinfo[6].null_pos=0;
  }

  write_count=update=dupp_keys=opt_delete=0;
  blob_buffer=0;

  for (i=1000 ; i>0 ; i--) key1[i]=0;
  for (i=4999 ; i>0 ; i--) key3[i]=0;

  if (!silent)
    printf("- Creating isam-file\n");
  /*  DBUG_PUSH(""); */
  /* my_delete(filename,MYF(0)); */	/* Remove old locks under gdb */
  file= 0;
  bzero((char*) &create_info,sizeof(create_info));
  create_info.max_rows=(ha_rows) (rec_pointer_size ?
				  (1L << (rec_pointer_size*8))/
				  reclength : 0);
  create_info.reloc_rows=(ha_rows) 100;
  if (mi_create(filename,keys,&keyinfo[first_key],
		use_blob ? 7 : 6, &recinfo[0],
		0,(MI_UNIQUEDEF*) 0,
		&create_info,create_flag))
    goto err;
  if (use_log)
    mi_log(1);
  if (!(file=mi_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
    goto err;
  if (!silent)
    printf("- Writing key:s\n");
  if (key_cacheing)
    init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0);
  if (locking)
    mi_lock_database(file,F_WRLCK);
  if (write_cacheing)
    mi_extra(file,HA_EXTRA_WRITE_CACHE,0);
  if (opt_quick_mode)
    mi_extra(file,HA_EXTRA_QUICK,0);

  for (i=0 ; i < recant ; i++)
  {
    n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
    sprintf((char*) record,"%6d:%4d:%8d:Pos: %4d    ",n1,n2,n3,write_count);
    int4store(record+STANDARD_LENGTH-4,(long) i);
    fix_length(record,(uint) STANDARD_LENGTH+rnd(60));
    put_blob_in_record(record+blob_pos,&blob_buffer);
    DBUG_PRINT("test",("record: %d",i));

    if (mi_write(file,record))
    {
      if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
      {
	printf("Error: %d in write at record: %d\n",my_errno,i);
	goto err;
      }
      if (verbose) printf("   Double key: %d\n",n3);
    }
    else
    {
      if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3)
      {
	printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
	goto err;
      }
      write_count++; key1[n1]++; key3[n3]=1;
    }

    /* Check if we can find key without flushing database */
    if (i == recant/2)
    {
      for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
      if (!j)
	for (j=999 ; j>0 && key1[j] == 0 ; j--) ;
      sprintf((char*) key,"%6d",j);
      if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
      {
	printf("Test in loop: Can't find key: \"%s\"\n",key);
	goto err;
      }
    }
  }
  if (testflag==1) goto end;

  if (write_cacheing)
  {
    if (mi_extra(file,HA_EXTRA_NO_CACHE,0))
    {
      puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
      goto end;
    }
  }
  if (key_cacheing)
    resize_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size*2,0,0);

  if (!silent)
    printf("- Delete\n");
  for (i=0 ; i<recant/10 ; i++)
  {
    for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
    if (j != 0)
    {
      sprintf((char*) key,"%6d",j);
      if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
      {
	printf("can't find key1: \"%s\"\n",key);
	goto err;
      }
      if (opt_delete == (uint) remove_count)		/* While testing */
	goto end;
      if (mi_delete(file,read_record))
      {
	printf("error: %d; can't delete record: \"%s\"\n", my_errno,read_record);
	goto err;
      }
      opt_delete++;
      key1[atoi((char*) read_record+keyinfo[0].seg[0].start)]--;
      key3[atoi((char*) read_record+keyinfo[2].seg[0].start)]=0;
    }
    else
      puts("Warning: Skipping delete test because no dupplicate keys");
  }
  if (testflag==2) goto end;

  if (!silent)
    printf("- Update\n");
  for (i=0 ; i<recant/10 ; i++)
  {
    n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
    sprintf((char*) record2,"%6d:%4d:%8d:XXX: %4d     ",n1,n2,n3,update);
    int4store(record2+STANDARD_LENGTH-4,(long) i);
    fix_length(record2,(uint) STANDARD_LENGTH+rnd(60));

    for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
    if (j != 0)
    {
      sprintf((char*) key,"%6d",j);
      if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
      {
	printf("can't find key1: \"%s\"\n",(char*) key);
	goto err;
      }
      if (use_blob)
      {
	if (i & 1)
	  put_blob_in_record(record+blob_pos,&blob_buffer);
	else
	  bmove(record+blob_pos,read_record+blob_pos,8);
      }
      if (mi_update(file,read_record,record2))
      {
	if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
	{
	  printf("error: %d; can't update:\nFrom: \"%s\"\nTo:   \"%s\"\n",
		 my_errno,read_record,record2);
	  goto err;
	}
	if (verbose)
	  printf("Double key when tried to update:\nFrom: \"%s\"\nTo:   \"%s\"\n",record,record2);
      }
      else
      {
	key1[atoi((char*) read_record+keyinfo[0].seg[0].start)]--;
	key3[atoi((char*) read_record+keyinfo[2].seg[0].start)]=0;
	key1[n1]++; key3[n3]=1;
	update++;
      }
    }
  }
  if (testflag == 3)
    goto end;

  for (i=999, dupp_keys=j=0 ; i>0 ; i--)
  {
    if (key1[i] > dupp_keys)
    {
      dupp_keys=key1[i]; j=i;
    }
  }
  sprintf((char*) key,"%6d",j);
  start=keyinfo[0].seg[0].start;
  length=keyinfo[0].seg[0].length;
  if (dupp_keys)
  {
    if (!silent)
      printf("- Same key: first - next -> last - prev -> first\n");
    DBUG_PRINT("progpos",("first - next -> last - prev -> first"));
    if (verbose) printf("	 Using key: \"%s\"  Keys: %d\n",key,dupp_keys);

    if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
      goto err;
    if (mi_rsame(file,read_record2,-1))
      goto err;
    if (memcmp(read_record,read_record2,reclength) != 0)
    {
      printf("mi_rsame didn't find same record\n");
      goto end;
    }
    info.recpos=mi_position(file);
    if (mi_rfirst(file,read_record2,0) ||
	mi_rsame_with_pos(file,read_record2,0,info.recpos) ||
	memcmp(read_record,read_record2,reclength) != 0)
    {
      printf("mi_rsame_with_pos didn't find same record\n");
      goto end;
    }
    {
      int skr=mi_rnext(file,read_record2,0);
      if ((skr && my_errno != HA_ERR_END_OF_FILE) ||
	  mi_rprev(file,read_record2,-1) ||
	  memcmp(read_record,read_record2,reclength) != 0)
      {
	printf("mi_rsame_with_pos lost position\n");
	goto end;
      }
    }
    ant=1;
    while (mi_rnext(file,read_record2,0) == 0 &&
	   memcmp(read_record2+start,key,length) == 0) ant++;
    if (ant != dupp_keys)
    {
      printf("next: Found: %d keys of %d\n",ant,dupp_keys);
      goto end;
    }
    ant=0;
    while (mi_rprev(file,read_record3,0) == 0 &&
	   memcmp(read_record3+start,key,length) == 0) ant++;
    if (ant != dupp_keys)
    {
      printf("prev: Found: %d records of %d\n",ant,dupp_keys);
      goto end;
    }

    /* Check of mi_rnext_same */
    if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
      goto err;
    ant=1;
    while (!mi_rnext_same(file,read_record3) && ant < dupp_keys+10)
      ant++;
    if (ant != dupp_keys || my_errno != HA_ERR_END_OF_FILE)
    {
      printf("mi_rnext_same: Found: %d records of %d\n",ant,dupp_keys);
      goto end;
    }
  }

  if (!silent)
    printf("- All keys: first - next -> last - prev -> first\n");
  DBUG_PRINT("progpos",("All keys: first - next -> last - prev -> first"));
  ant=1;
  if (mi_rfirst(file,read_record,0))
  {
    printf("Can't find first record\n");
    goto end;
  }
  while ((error=mi_rnext(file,read_record3,0)) == 0 && ant < write_count+10)
    ant++;
  if (ant != write_count - opt_delete || error != HA_ERR_END_OF_FILE)
  {
    printf("next: I found: %d records of %d (error: %d)\n",
	   ant, write_count - opt_delete, error);
    goto end;
  }
  if (mi_rlast(file,read_record2,0) ||
      memcmp(read_record2,read_record3,reclength))
  {
    printf("Can't find last record\n");
    DBUG_DUMP("record2",(uchar*) read_record2,reclength);
    DBUG_DUMP("record3",(uchar*) read_record3,reclength);
    goto end;
  }
  ant=1;
  while (mi_rprev(file,read_record3,0) == 0 && ant < write_count+10)
    ant++;
  if (ant != write_count - opt_delete)
  {
    printf("prev: I found: %d records of %d\n",ant,write_count);
    goto end;
  }
  if (memcmp(read_record,read_record3,reclength))
  {
    printf("Can't find first record\n");
    goto end;
  }

  if (!silent)
    printf("- Test if: Read first - next - prev - prev - next == first\n");
  DBUG_PRINT("progpos",("- Read first - next - prev - prev - next == first"));
  if (mi_rfirst(file,read_record,0) ||
      mi_rnext(file,read_record3,0) ||
      mi_rprev(file,read_record3,0) ||
      mi_rprev(file,read_record3,0) == 0 ||
      mi_rnext(file,read_record3,0))
      goto err;
  if (memcmp(read_record,read_record3,reclength) != 0)
     printf("Can't find first record\n");

  if (!silent)
    printf("- Test if: Read last - prev - next - next - prev == last\n");
  DBUG_PRINT("progpos",("Read last - prev - next - next - prev == last"));
  if (mi_rlast(file,read_record2,0) ||
      mi_rprev(file,read_record3,0) ||
      mi_rnext(file,read_record3,0) ||
      mi_rnext(file,read_record3,0) == 0 ||
      mi_rprev(file,read_record3,0))
      goto err;
  if (memcmp(read_record2,read_record3,reclength))
     printf("Can't find last record\n");
#ifdef NOT_ANYMORE
  if (!silent)
    puts("- Test read key-part");
  strmov(key2,key);
  for(i=strlen(key2) ; i-- > 1 ;)
  {
    key2[i]=0;

    /* The following row is just to catch some bugs in the key code */
    bzero((char*) file->lastkey,file->s->base.max_key_length*2);
    if (mi_rkey(file,read_record,0,key2,(uint) i,HA_READ_PREFIX))
      goto err;
    if (memcmp(read_record+start,key,(uint) i))
    {
      puts("Didn't find right record");
      goto end;
    }
  }
#endif
  if (dupp_keys > 2)
  {
    if (!silent)
      printf("- Read key (first) - next - delete - next -> last\n");
    DBUG_PRINT("progpos",("first - next - delete - next -> last"));
    if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
      goto err;
    if (mi_rnext(file,read_record3,0)) goto err;
    if (mi_delete(file,read_record3)) goto err;
    opt_delete++;
    ant=1;
    while (mi_rnext(file,read_record3,0) == 0 &&
	   memcmp(read_record3+start,key,length) == 0) ant++;
    if (ant != dupp_keys-1)
    {
      printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1);
      goto end;
    }
  }
  if (dupp_keys>4)
  {
    if (!silent)
      printf("- Read last of key - prev - delete - prev -> first\n");
    DBUG_PRINT("progpos",("last - prev - delete - prev -> first"));
    if (mi_rprev(file,read_record3,0)) goto err;
    if (mi_rprev(file,read_record3,0)) goto err;
    if (mi_delete(file,read_record3)) goto err;
    opt_delete++;
    ant=1;
    while (mi_rprev(file,read_record3,0) == 0 &&
	   memcmp(read_record3+start,key,length) == 0) ant++;
    if (ant != dupp_keys-2)
    {
      printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2);
      goto end;
    }
  }
  if (dupp_keys > 6)
  {
    if (!silent)
      printf("- Read first - delete - next -> last\n");
    DBUG_PRINT("progpos",("first - delete - next -> last"));
    if (mi_rkey(file,read_record3,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
      goto err;
    if (mi_delete(file,read_record3)) goto err;
    opt_delete++;
    ant=1;
    if (mi_rnext(file,read_record,0))
      goto err;					/* Skall finnas poster */
    while (mi_rnext(file,read_record3,0) == 0 &&
	   memcmp(read_record3+start,key,length) == 0) ant++;
    if (ant != dupp_keys-3)
    {
      printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3);
      goto end;
    }

    if (!silent)
      printf("- Read last - delete - prev -> first\n");
    DBUG_PRINT("progpos",("last - delete - prev -> first"));
    if (mi_rprev(file,read_record3,0)) goto err;
    if (mi_delete(file,read_record3)) goto err;
    opt_delete++;
    ant=0;
    while (mi_rprev(file,read_record3,0) == 0 &&
	   memcmp(read_record3+start,key,length) == 0) ant++;
    if (ant != dupp_keys-4)
    {
      printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4);
      goto end;
    }
  }

  if (!silent)
    puts("- Test if: Read rrnd - same");
  DBUG_PRINT("progpos",("Read rrnd - same"));
  for (i=0 ; i < write_count ; i++)
  {
    if (mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR) == 0)
      break;
  }
  if (i == write_count)
    goto err;

  bmove(read_record2,read_record,reclength);
  for (i=min(2,keys) ; i-- > 0 ;)
  {
    if (mi_rsame(file,read_record2,(int) i)) goto err;
    if (memcmp(read_record,read_record2,reclength) != 0)
    {
      printf("is_rsame didn't find same record\n");
      goto end;
    }
  }
  if (!silent)
    puts("- Test mi_records_in_range");
  mi_status(file,&info,HA_STATUS_VARIABLE);
  for (i=0 ; i < info.keys ; i++)
  {
    key_range min_key, max_key;
    if (mi_rfirst(file,read_record,(int) i) ||
	mi_rlast(file,read_record2,(int) i))
      goto err;
    copy_key(file,(uint) i,(uchar*) read_record,(uchar*) key);
    copy_key(file,(uint) i,(uchar*) read_record2,(uchar*) key2);
    min_key.key= key;
    min_key.keypart_map= HA_WHOLE_KEY;
    min_key.flag= HA_READ_KEY_EXACT;
    max_key.key= key2;
    max_key.keypart_map= HA_WHOLE_KEY;
    max_key.flag= HA_READ_AFTER_KEY;

    range_records= mi_records_in_range(file,(int) i, &min_key, &max_key);
    if (range_records < info.records*8/10 ||
	range_records > info.records*12/10)
    {
      printf("mi_records_range returned %ld; Should be about %ld\n",
	     (long) range_records,(long) info.records);
      goto end;
    }
    if (verbose)
    {
      printf("mi_records_range returned %ld;  Exact is %ld  (diff: %4.2g %%)\n",
	     (long) range_records, (long) info.records,
	     labs((long) range_records - (long) info.records)*100.0/
	     info.records);
    }
  }
  for (i=0 ; i < 5 ; i++)
  {
    for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
    for (k=rnd(1000)+1 ; k>0 && key1[k] == 0 ; k--) ;
    if (j != 0 && k != 0)
    {
      key_range min_key, max_key;
      if (j > k)
	swap_variables(int, j, k);
      sprintf((char*) key,"%6d",j);
      sprintf((char*) key2,"%6d",k);

      min_key.key= key;
      min_key.length= USE_WHOLE_KEY;
      min_key.flag= HA_READ_AFTER_KEY;
      max_key.key= key2;
      max_key.length= USE_WHOLE_KEY;
      max_key.flag= HA_READ_BEFORE_KEY;
      range_records= mi_records_in_range(file, 0, &min_key, &max_key);
      records=0;
      for (j++ ; j < k ; j++)
	records+=key1[j];
      if ((long) range_records < (long) records*7/10-2 ||
	  (long) range_records > (long) records*14/10+2)
      {
	printf("mi_records_range for key: %d returned %lu; Should be about %lu\n",
	       i, (ulong) range_records, (ulong) records);
	goto end;
      }
      if (verbose && records)
      {
	printf("mi_records_range returned %lu;  Exact is %lu  (diff: %4.2g %%)\n",
	       (ulong) range_records, (ulong) records,
	       labs((long) range_records-(long) records)*100.0/records);

      }
    }
    }

  if (!silent)
    printf("- mi_info\n");
  mi_status(file,&info,HA_STATUS_VARIABLE | HA_STATUS_CONST);
  if (info.records != write_count-opt_delete || info.deleted > opt_delete + update
      || info.keys != keys)
  {
    puts("Wrong info from mi_info");
    printf("Got: records: %lu  delete: %lu  i_keys: %d\n",
	   (ulong) info.records, (ulong) info.deleted, info.keys);
  }
  if (verbose)
  {
    char buff[80];
    get_date(buff,3,info.create_time);
    printf("info: Created %s\n",buff);
    get_date(buff,3,info.check_time);
    printf("info: checked %s\n",buff);
    get_date(buff,3,info.update_time);
    printf("info: Modified %s\n",buff);
  }

  mi_panic(HA_PANIC_WRITE);
  mi_panic(HA_PANIC_READ);
  if (mi_is_changed(file))
    puts("Warning: mi_is_changed reported that datafile was changed");

  if (!silent)
    printf("- mi_extra(CACHE) + mi_rrnd.... + mi_extra(NO_CACHE)\n");
  if (mi_reset(file) || mi_extra(file,HA_EXTRA_CACHE,0))
  {
    if (locking || (!use_blob && !pack_fields))
    {
      puts("got error from mi_extra(HA_EXTRA_CACHE)");
      goto end;
    }
  }
  ant=0;
  while ((error=mi_rrnd(file,record,HA_OFFSET_ERROR)) != HA_ERR_END_OF_FILE &&
	 ant < write_count + 10)
	ant+= error ? 0 : 1;
  if (ant != write_count-opt_delete)
  {
    printf("rrnd with cache: I can only find: %d records of %d\n",
	   ant,write_count-opt_delete);
    goto end;
  }
  if (mi_extra(file,HA_EXTRA_NO_CACHE,0))
  {
    puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
    goto end;
  }

  ant=0;
  mi_scan_init(file);
  while ((error=mi_scan(file,record)) != HA_ERR_END_OF_FILE &&
	 ant < write_count + 10)
	ant+= error ? 0 : 1;
  if (ant != write_count-opt_delete)
  {
    printf("scan with cache: I can only find: %d records of %d\n",
	   ant,write_count-opt_delete);
    goto end;
  }

  if (testflag == 4) goto end;

  if (!silent)
    printf("- Removing keys\n");
  DBUG_PRINT("progpos",("Removing keys"));
  lastpos = HA_OFFSET_ERROR;
  /* DBUG_POP(); */
  mi_reset(file);
  found_parts=0;
  while ((error=mi_rrnd(file,read_record,HA_OFFSET_ERROR)) !=
	 HA_ERR_END_OF_FILE)
  {
    info.recpos=mi_position(file);
    if (lastpos >= info.recpos && lastpos != HA_OFFSET_ERROR)
    {
      printf("mi_rrnd didn't advance filepointer; old: %ld, new: %ld\n",
	     (long) lastpos, (long) info.recpos);
      goto err;
    }
    lastpos=info.recpos;
    if (error == 0)
    {
      if (opt_delete == (uint) remove_count)		/* While testing */
	goto end;
      if (mi_rsame(file,read_record,-1))
      {
	printf("can't find record %lx\n",(long) info.recpos);
	goto err;
      }
      if (use_blob)
      {
	ulong blob_length,pos;
	uchar *ptr;
	longget(blob_length,read_record+blob_pos+4);
	ptr=(uchar*) blob_length;
	longget(blob_length,read_record+blob_pos);
	for (pos=0 ; pos < blob_length ; pos++)
	{
	  if (ptr[pos] != (uchar) (blob_length+pos))
	  {
	    printf("found blob with wrong info at %ld\n",(long) lastpos);
	    use_blob=0;
	    break;
	  }
	}
      }
      if (mi_delete(file,read_record))
      {
	printf("can't delete record: %6.6s,  delete_count: %d\n",
	       read_record, opt_delete);
	goto err;
      }
      opt_delete++;
    }
    else
      found_parts++;
  }
  if (my_errno != HA_ERR_END_OF_FILE && my_errno != HA_ERR_RECORD_DELETED)
    printf("error: %d from mi_rrnd\n",my_errno);
  if (write_count != opt_delete)
  {
    printf("Deleted only %d of %d records (%d parts)\n",opt_delete,write_count,
	   found_parts);
    goto err;
  }
end:
  if (mi_close(file))
    goto err;
  mi_panic(HA_PANIC_CLOSE);			/* Should close log */
  if (!silent)
  {
    printf("\nFollowing test have been made:\n");
    printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete);
    if (rec_pointer_size)
      printf("Record pointer size:  %d\n",rec_pointer_size);
    printf("myisam_block_size:    %lu\n", myisam_block_size);
    if (key_cacheing)
    {
      puts("Key cache used");
      printf("key_cache_block_size: %u\n", key_cache_block_size);
      if (write_cacheing)
	puts("Key cache resized");
    }
    if (write_cacheing)
      puts("Write cacheing used");
    if (write_cacheing)
      puts("quick mode");
    if (async_io && locking)
      puts("Asyncron io with locking used");
    else if (locking)
      puts("Locking used");
    if (use_blob)
      puts("blobs used");
    printf("key cache status: \n\
blocks used:%10lu\n\
not flushed:%10lu\n\
w_requests: %10lu\n\
writes:     %10lu\n\
r_requests: %10lu\n\
reads:      %10lu\n",
           dflt_key_cache->blocks_used,
           dflt_key_cache->global_blocks_changed,
           (ulong) dflt_key_cache->global_cache_w_requests,
           (ulong) dflt_key_cache->global_cache_write,
           (ulong) dflt_key_cache->global_cache_r_requests,
           (ulong) dflt_key_cache->global_cache_read);
  }
Exemplo n.º 8
0
int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
{
  int error=0;
  ulong cache_size;
  MYISAM_SHARE *share=info->s;
  DBUG_ENTER("mi_extra");
  DBUG_PRINT("enter",("function: %d",(int) function));

  switch (function) {
  case HA_EXTRA_RESET_STATE:		/* Reset state (don't free buffers) */
    info->lastinx= 0;			/* Use first index as def */
    info->last_search_keypage=info->lastpos= HA_OFFSET_ERROR;
    info->page_changed=1;
					/* Next/prev gives first/last */
    if (info->opt_flag & READ_CACHE_USED)
    {
      reinit_io_cache(&info->rec_cache,READ_CACHE,0,
		      (pbool) (info->lock_type != F_UNLCK),
		      (pbool) test(info->update & HA_STATE_ROW_CHANGED)
		      );
    }
    info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND |
		   HA_STATE_PREV_FOUND);
    break;
  case HA_EXTRA_CACHE:
    if (info->lock_type == F_UNLCK &&
	(share->options & HA_OPTION_PACK_RECORD))
    {
      error=1;			/* Not possibly if not locked */
      my_errno=EACCES;
      break;
    }
    if (info->s->file_map) /* Don't use cache if mmap */
      break;
#if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
    if ((share->options & HA_OPTION_COMPRESS_RECORD))
    {
      mysql_mutex_lock(&share->intern_lock);
      if (_mi_memmap_file(info))
      {
	/* We don't nead MADV_SEQUENTIAL if small file */
	madvise((char*) share->file_map, share->state.state.data_file_length,
		share->state.state.data_file_length <= RECORD_CACHE_SIZE*16 ?
		MADV_RANDOM : MADV_SEQUENTIAL);
        mysql_mutex_unlock(&share->intern_lock);
	break;
      }
      mysql_mutex_unlock(&share->intern_lock);
    }
#endif
    if (info->opt_flag & WRITE_CACHE_USED)
    {
      info->opt_flag&= ~WRITE_CACHE_USED;
      if ((error=end_io_cache(&info->rec_cache)))
	break;
    }
    if (!(info->opt_flag &
	  (READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED)))
    {
      cache_size= (extra_arg ? *(ulong*) extra_arg :
		   my_default_record_cache_size);
      if (!(init_io_cache(&info->rec_cache,info->dfile,
			 (uint) min(info->state->data_file_length+1,
				    cache_size),
			  READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK),
			  MYF(share->write_flag & MY_WAIT_IF_FULL))))
      {
	info->opt_flag|=READ_CACHE_USED;
	info->update&= ~HA_STATE_ROW_CHANGED;
      }
      if (share->concurrent_insert)
	info->rec_cache.end_of_file=info->state->data_file_length;
    }
    break;
  case HA_EXTRA_REINIT_CACHE:
    if (info->opt_flag & READ_CACHE_USED)
    {
      reinit_io_cache(&info->rec_cache,READ_CACHE,info->nextpos,
		      (pbool) (info->lock_type != F_UNLCK),
		      (pbool) test(info->update & HA_STATE_ROW_CHANGED));
      info->update&= ~HA_STATE_ROW_CHANGED;
      if (share->concurrent_insert)
	info->rec_cache.end_of_file=info->state->data_file_length;
    }
    break;
  case HA_EXTRA_WRITE_CACHE:
    if (info->lock_type == F_UNLCK)
    {
      error=1;			/* Not possibly if not locked */
      break;
    }

    cache_size= (extra_arg ? *(ulong*) extra_arg :
		 my_default_record_cache_size);
    if (!(info->opt_flag &
	  (READ_CACHE_USED | WRITE_CACHE_USED | OPT_NO_ROWS)) &&
	!share->state.header.uniques)
      if (!(init_io_cache(&info->rec_cache,info->dfile, cache_size,
			 WRITE_CACHE,info->state->data_file_length,
			  (pbool) (info->lock_type != F_UNLCK),
			  MYF(share->write_flag & MY_WAIT_IF_FULL))))
      {
	info->opt_flag|=WRITE_CACHE_USED;
	info->update&= ~(HA_STATE_ROW_CHANGED |
			 HA_STATE_WRITE_AT_END |
			 HA_STATE_EXTEND_BLOCK);
      }
    break;
  case HA_EXTRA_PREPARE_FOR_UPDATE:
    if (info->s->data_file_type != DYNAMIC_RECORD)
      break;
    /* Remove read/write cache if dynamic rows */
  case HA_EXTRA_NO_CACHE:
    if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
    {
      info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
      error=end_io_cache(&info->rec_cache);
      /* Sergei will insert full text index caching here */
    }
#if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
    if (info->opt_flag & MEMMAP_USED)
      madvise((char*) share->file_map, share->state.state.data_file_length,
              MADV_RANDOM);
#endif
    break;
  case HA_EXTRA_FLUSH_CACHE:
    if (info->opt_flag & WRITE_CACHE_USED)
    {
      if ((error=flush_io_cache(&info->rec_cache)))
      {
        mi_print_error(info->s, HA_ERR_CRASHED);
	mi_mark_crashed(info);			/* Fatal error found */
      }
    }
    break;
  case HA_EXTRA_NO_READCHECK:
    info->opt_flag&= ~READ_CHECK_USED;		/* No readcheck */
    break;
  case HA_EXTRA_READCHECK:
    info->opt_flag|= READ_CHECK_USED;
    break;
  case HA_EXTRA_KEYREAD:			/* Read only keys to record */
  case HA_EXTRA_REMEMBER_POS:
    info->opt_flag |= REMEMBER_OLD_POS;
    bmove((uchar*) info->lastkey+share->base.max_key_length*2,
	  (uchar*) info->lastkey,info->lastkey_length);
    info->save_update=	info->update;
    info->save_lastinx= info->lastinx;
    info->save_lastpos= info->lastpos;
    info->save_lastkey_length=info->lastkey_length;
    if (function == HA_EXTRA_REMEMBER_POS)
      break;
    /* fall through */
  case HA_EXTRA_KEYREAD_CHANGE_POS:
    info->opt_flag |= KEY_READ_USED;
    info->read_record=_mi_read_key_record;
    break;
  case HA_EXTRA_NO_KEYREAD:
  case HA_EXTRA_RESTORE_POS:
    if (info->opt_flag & REMEMBER_OLD_POS)
    {
      bmove((uchar*) info->lastkey,
	    (uchar*) info->lastkey+share->base.max_key_length*2,
	    info->save_lastkey_length);
      info->update=	info->save_update | HA_STATE_WRITTEN;
      info->lastinx=	info->save_lastinx;
      info->lastpos=	info->save_lastpos;
      info->lastkey_length=info->save_lastkey_length;
    }
    info->read_record=	share->read_record;
    info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
    break;
  case HA_EXTRA_NO_USER_CHANGE: /* Database is somehow locked agains changes */
    info->lock_type= F_EXTRA_LCK; /* Simulate as locked */
    break;
  case HA_EXTRA_WAIT_LOCK:
    info->lock_wait=0;
    break;
  case HA_EXTRA_NO_WAIT_LOCK:
    info->lock_wait=MY_DONT_WAIT;
    break;
  case HA_EXTRA_NO_KEYS:
    if (info->lock_type == F_UNLCK)
    {
      error=1;					/* Not possibly if not lock */
      break;
    }
    if (mi_is_any_key_active(share->state.key_map))
    {
      MI_KEYDEF *key=share->keyinfo;
      uint i;
      for (i=0 ; i < share->base.keys ; i++,key++)
      {
        if (!(key->flag & HA_NOSAME) && info->s->base.auto_key != i+1)
        {
          mi_clear_key_active(share->state.key_map, i);
          info->update|= HA_STATE_CHANGED;
        }
      }

      if (!share->changed)
      {
	share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED;
	share->changed=1;			/* Update on close */
	if (!share->global_changed)
	{
	  share->global_changed=1;
	  share->state.open_count++;
	}
      }
      share->state.state= *info->state;
      error=mi_state_info_write(share->kfile,&share->state,1 | 2);
    }
    break;
  case HA_EXTRA_FORCE_REOPEN:
    mysql_mutex_lock(&THR_LOCK_myisam);
    share->last_version= 0L;			/* Impossible version */
    mysql_mutex_unlock(&THR_LOCK_myisam);
    break;
  case HA_EXTRA_PREPARE_FOR_DROP:
    mysql_mutex_lock(&THR_LOCK_myisam);
    share->last_version= 0L;			/* Impossible version */
#ifdef __WIN__REMOVE_OBSOLETE_WORKAROUND
    /* Close the isam and data files as Win32 can't drop an open table */
    mysql_mutex_lock(&share->intern_lock);
    if (flush_key_blocks(share->key_cache, share->kfile,
			 (function == HA_EXTRA_FORCE_REOPEN ?
			  FLUSH_RELEASE : FLUSH_IGNORE_CHANGED)))
    {
      error=my_errno;
      share->changed=1;
      mi_print_error(info->s, HA_ERR_CRASHED);
      mi_mark_crashed(info);			/* Fatal error found */
    }
    if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
    {
      info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
      error=end_io_cache(&info->rec_cache);
    }
    if (info->lock_type != F_UNLCK && ! info->was_locked)
    {
      info->was_locked=info->lock_type;
      if (mi_lock_database(info,F_UNLCK))
	error=my_errno;
      info->lock_type = F_UNLCK;
    }
    if (share->kfile >= 0)
      _mi_decrement_open_count(info);
    if (share->kfile >= 0 && mysql_file_close(share->kfile, MYF(0)))
      error=my_errno;
    {
      LIST *list_element ;
      for (list_element=myisam_open_list ;
	   list_element ;
	   list_element=list_element->next)
      {
	MI_INFO *tmpinfo=(MI_INFO*) list_element->data;
	if (tmpinfo->s == info->s)
	{
          if (tmpinfo->dfile >= 0 && mysql_file_close(tmpinfo->dfile, MYF(0)))
	    error = my_errno;
	  tmpinfo->dfile= -1;
	}
      }
    }
    share->kfile= -1;				/* Files aren't open anymore */
    mysql_mutex_unlock(&share->intern_lock);
#endif
    mysql_mutex_unlock(&THR_LOCK_myisam);
    break;
  case HA_EXTRA_FLUSH:
    if (!share->temporary)
      flush_key_blocks(share->key_cache, share->kfile, FLUSH_KEEP);
#ifdef HAVE_PWRITE
    _mi_decrement_open_count(info);
#endif
    if (share->not_flushed)
    {
      share->not_flushed=0;
      if (mysql_file_sync(share->kfile, MYF(0)))
	error= my_errno;
      if (mysql_file_sync(info->dfile, MYF(0)))
	error= my_errno;
      if (error)
      {
	share->changed=1;
        mi_print_error(info->s, HA_ERR_CRASHED);
	mi_mark_crashed(info);			/* Fatal error found */
      }
    }
    if (share->base.blobs)
      mi_alloc_rec_buff(info, -1, &info->rec_buff);
    break;
  case HA_EXTRA_NORMAL:				/* Theese isn't in use */
    info->quick_mode=0;
    break;
  case HA_EXTRA_QUICK:
    info->quick_mode=1;
    break;
  case HA_EXTRA_NO_ROWS:
    if (!share->state.header.uniques)
      info->opt_flag|= OPT_NO_ROWS;
    break;
  case HA_EXTRA_PRELOAD_BUFFER_SIZE:
    info->preload_buff_size= *((ulong *) extra_arg); 
    break;
  case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
  case HA_EXTRA_CHANGE_KEY_TO_DUP:
    mi_extra_keyflag(info, function);
    break;
  case HA_EXTRA_MMAP:
#ifdef HAVE_MMAP
    mysql_mutex_lock(&share->intern_lock);
    /*
      Memory map the data file if it is not already mapped. It is safe
      to memory map a file while other threads are using file I/O on it.
      Assigning a new address to a function pointer is an atomic
      operation. intern_lock prevents that two or more mappings are done
      at the same time.
    */
    if (!share->file_map)
    {
      if (mi_dynmap_file(info, share->state.state.data_file_length))
      {
        DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
        error= my_errno= errno;
      }
    }
    mysql_mutex_unlock(&share->intern_lock);
#endif
    break;
  case HA_EXTRA_MARK_AS_LOG_TABLE:
    mysql_mutex_lock(&share->intern_lock);
    share->is_log_table= TRUE;
    mysql_mutex_unlock(&share->intern_lock);
    break;
  case HA_EXTRA_KEY_CACHE:
  case HA_EXTRA_NO_KEY_CACHE:
  default:
    break;
  }
  {
    char tmp[1];
    tmp[0]=function;
    myisam_log_command(MI_LOG_EXTRA,info,(uchar*) tmp,1,error);
  }
  DBUG_RETURN(error);
} /* mi_extra */
Exemplo n.º 9
0
int main(int argc,char *argv[])
{
  int error=0, subkeys;
  uint keylen, keylen2=0, inx, doc_cnt=0;
  float weight= 1.0;
  double gws, min_gws=0, avg_gws=0;
  MI_INFO *info;
  char buf[MAX_LEN], buf2[MAX_LEN], buf_maxlen[MAX_LEN], buf_min_gws[MAX_LEN];
  ulong total=0, maxlen=0, uniq=0, max_doc_cnt=0;
  struct { MI_INFO *info; } aio0, *aio=&aio0; /* for GWS_IN_USE */

  MY_INIT(argv[0]);

  memset(&main_thread_keycache_var, 0, sizeof(st_keycache_thread_var));
  mysql_cond_init(PSI_NOT_INSTRUMENTED,
                  &main_thread_keycache_var.suspend);

  if ((error= handle_options(&argc, &argv, my_long_options, get_one_option)))
    exit(error);
  if (count || dump)
    verbose=0;
  if (!count && !dump && !lstats && !query)
    stats=1;

  if (verbose)
    setbuf(stdout,NULL);

  if (argc < 2)
    usage();

  {
    char *end;
    inx= (uint) my_strtoll(argv[1], &end, 10);
    if (*end)
      usage();
  }

  init_key_cache(dflt_key_cache,MI_KEY_BLOCK_LENGTH,USE_BUFFER_INIT, 0, 0);

  if (!(info=mi_open(argv[0], O_RDONLY,
                     HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER)))
  {
    error=my_errno();
    goto err;
  }

  *buf2=0;
  aio->info=info;

  if ((inx >= info->s->base.keys) ||
      !(info->s->keyinfo[inx].flag & HA_FULLTEXT))
  {
    printf("Key %d in table %s is not a FULLTEXT key\n", inx, info->filename);
    goto err;
  }

  mi_lock_database(info, F_EXTRA_LCK);

  info->lastpos= HA_OFFSET_ERROR;
  info->update|= HA_STATE_PREV_FOUND;

  while (!(error=mi_rnext(info,NULL,inx)))
  {
    keylen=*(info->lastkey);

    subkeys=ft_sintXkorr(info->lastkey+keylen+1);
    if (subkeys >= 0)
      ft_floatXget(weight, info->lastkey+keylen+1);

    my_snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey+1);
    my_casedn_str(default_charset_info,buf);
    total++;
    lengths[keylen]++;

    if (count || stats)
    {
      if (strcmp(buf, buf2))
      {
        if (*buf2)
        {
          uniq++;
          avg_gws+=gws=GWS_IN_USE;
          if (count)
            printf("%9u %20.7f %s\n",doc_cnt,gws,buf2);
          if (maxlen<keylen2)
          {
            maxlen=keylen2;
            my_stpcpy(buf_maxlen, buf2);
          }
          if (max_doc_cnt < doc_cnt)
          {
            max_doc_cnt=doc_cnt;
            my_stpcpy(buf_min_gws, buf2);
            min_gws=gws;
          }
        }
        my_stpcpy(buf2, buf);
        keylen2=keylen;
        doc_cnt=0;
      }
      doc_cnt+= (subkeys >= 0 ? 1 : -subkeys);
    }
    if (dump)
    {
      if (subkeys>=0)
        printf("%9lx %20.7f %s\n", (long) info->lastpos,weight,buf);
      else
        printf("%9lx => %17d %s\n",(long) info->lastpos,-subkeys,buf);
    }
    if (verbose && (total%HOW_OFTEN_TO_WRITE)==0)
      printf("%10ld\r",total);
  }
  mi_lock_database(info, F_UNLCK);

  if (count || stats)
  {
    if (*buf2)
    {
      uniq++;
      avg_gws+=gws=GWS_IN_USE;
      if (count)
        printf("%9u %20.7f %s\n",doc_cnt,gws,buf2);
      if (maxlen<keylen2)
      {
        maxlen=keylen2;
        my_stpcpy(buf_maxlen, buf2);
      }
      if (max_doc_cnt < doc_cnt)
      {
        max_doc_cnt=doc_cnt;
        my_stpcpy(buf_min_gws, buf2);
        min_gws=gws;
      }
    }
  }

  if (stats)
  {
    count=0;
    for (inx=0;inx<256;inx++)
    {
      count+=lengths[inx];
      if ((ulong) count >= total/2)
        break;
    }
    printf("Total rows: %lu\nTotal words: %lu\n"
           "Unique words: %lu\nLongest word: %lu chars (%s)\n"
           "Median length: %u\n"
           "Average global weight: %f\n"
           "Most common word: %lu times, weight: %f (%s)\n",
           (long) info->state->records, total, uniq, maxlen, buf_maxlen,
           inx, avg_gws/uniq, max_doc_cnt, min_gws, buf_min_gws);
  }
  if (lstats)
  {
    count=0;
    for (inx=0; inx<256; inx++)
    {
      count+=lengths[inx];
      if (count && lengths[inx])
        printf("%3u: %10lu %5.2f%% %20lu %4.1f%%\n", inx,
               (ulong) lengths[inx],100.0*lengths[inx]/total,(ulong) count,
               100.0*count/total);
    }
  }

err:
  if (error && error != HA_ERR_END_OF_FILE)
    printf("got error %d\n",my_errno());
  if (info)
    mi_close(info);
  mysql_cond_destroy(&main_thread_keycache_var.suspend);
  return 0;
}
Exemplo n.º 10
0
int 
mi_extra(MI_INFO * info, enum ha_extra_function function)
{
	int		error = 0;
	MYISAM_SHARE   *share = info->s;
	DBUG_ENTER("mi_extra");

	switch (function) {
	case HA_EXTRA_RESET:
		/*
		 * Free buffers and reset the following flags: EXTRA_CACHE,
		 * EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK
		 */
		if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) {
			info->opt_flag &= ~(READ_CACHE_USED | WRITE_CACHE_USED);
			error = end_io_cache(&info->rec_cache);
		}
#if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
		if (info->opt_flag & MEMMAP_USED)
			madvise(share->file_map, share->state.state.data_file_length, MADV_RANDOM);
#endif
		info->opt_flag &= ~(KEY_READ_USED | REMEMBER_OLD_POS);
		info->quick_mode = 0;
		/* Fall through */

	case HA_EXTRA_RESET_STATE:	/* Reset state (don't free buffers) */
		info->lastinx = 0;	/* Use first index as def */
		info->last_search_keypage = info->lastpos = HA_OFFSET_ERROR;
		info->page_changed = 1;
		/* Next/prev gives first/last */
		if (info->opt_flag & READ_CACHE_USED) {
			reinit_io_cache(&info->rec_cache, READ_CACHE, 0,
					(pbool) (info->lock_type != F_UNLCK),
			   (pbool) test(info->update & HA_STATE_ROW_CHANGED)
				);
		}
		info->update = ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND |
				HA_STATE_PREV_FOUND);
		break;
	case HA_EXTRA_CACHE:
		if (info->lock_type == F_UNLCK &&
		    (share->options & HA_OPTION_PACK_RECORD)) {
			error = 1;	/* Not possibly if not locked */
			my_errno = EACCES;
			break;
		}
#if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
		if ((share->options & HA_OPTION_COMPRESS_RECORD)) {
			pthread_mutex_lock(&share->intern_lock);
			if (_mi_memmap_file(info)) {
				/*
				 * We don't nead MADV_SEQUENTIAL if small
				 * file
				 */
				madvise(share->file_map, share->state.state.data_file_length,
					share->state.state.data_file_length <= RECORD_CACHE_SIZE * 16 ?
					MADV_RANDOM : MADV_SEQUENTIAL);
				pthread_mutex_unlock(&share->intern_lock);
				break;
			}
			pthread_mutex_unlock(&share->intern_lock);
		}
#endif
		if (info->opt_flag & WRITE_CACHE_USED) {
			info->opt_flag &= ~WRITE_CACHE_USED;
			if ((error = end_io_cache(&info->rec_cache)))
				break;
		}
		if (!(info->opt_flag &
		      (READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED))) {
			if (!(init_io_cache(&info->rec_cache, info->dfile,
			       (uint) min(info->state->data_file_length + 1,
					  my_default_record_cache_size),
			READ_CACHE, 0L, (pbool) (info->lock_type != F_UNLCK),
			       MYF(share->write_flag & MY_WAIT_IF_FULL)))) {
				info->opt_flag |= READ_CACHE_USED;
				info->update &= ~HA_STATE_ROW_CHANGED;
			}
			if (share->concurrent_insert)
				info->rec_cache.end_of_file = info->state->data_file_length;
		}
		break;
	case HA_EXTRA_REINIT_CACHE:
		if (info->opt_flag & READ_CACHE_USED) {
			reinit_io_cache(&info->rec_cache, READ_CACHE, info->nextpos,
					(pbool) (info->lock_type != F_UNLCK),
			 (pbool) test(info->update & HA_STATE_ROW_CHANGED));
			info->update &= ~HA_STATE_ROW_CHANGED;
			if (share->concurrent_insert)
				info->rec_cache.end_of_file = info->state->data_file_length;
		}
		break;
	case HA_EXTRA_WRITE_CACHE:
		if (info->lock_type == F_UNLCK) {
			error = 1;	/* Not possibly if not locked */
			break;
		}
		if (!(info->opt_flag &
		      (READ_CACHE_USED | WRITE_CACHE_USED | OPT_NO_ROWS)) &&
		    !share->state.header.uniques)
			if (!(init_io_cache(&info->rec_cache, info->dfile, 0,
				 WRITE_CACHE, info->state->data_file_length,
				       (pbool) (info->lock_type != F_UNLCK),
			       MYF(share->write_flag & MY_WAIT_IF_FULL)))) {
				info->opt_flag |= WRITE_CACHE_USED;
				info->update &= ~(HA_STATE_ROW_CHANGED |
						  HA_STATE_WRITE_AT_END |
						  HA_STATE_EXTEND_BLOCK);
			}
		break;
	case HA_EXTRA_NO_CACHE:
		if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) {
			info->opt_flag &= ~(READ_CACHE_USED | WRITE_CACHE_USED);
			error = end_io_cache(&info->rec_cache);
			/* Sergei will insert full text index caching here */
		}
#if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
		if (info->opt_flag & MEMMAP_USED)
			madvise(share->file_map, share->state.state.data_file_length, MADV_RANDOM);
#endif
		break;
	case HA_EXTRA_FLUSH_CACHE:
		if (info->opt_flag & WRITE_CACHE_USED) {
			if ((error = flush_io_cache(&info->rec_cache)))
				mi_mark_crashed(info);	/* Fatal error found */
		}
		break;
	case HA_EXTRA_NO_READCHECK:
		info->opt_flag &= ~READ_CHECK_USED;	/* No readcheck */
		break;
	case HA_EXTRA_READCHECK:
		info->opt_flag |= READ_CHECK_USED;
		break;
	case HA_EXTRA_KEYREAD:	/* Read only keys to record */
	case HA_EXTRA_REMEMBER_POS:
		info->opt_flag |= REMEMBER_OLD_POS;
		bmove((byte *) info->lastkey + share->base.max_key_length * 2,
		      (byte *) info->lastkey, info->lastkey_length);
		info->save_update = info->update;
		info->save_lastinx = info->lastinx;
		info->save_lastpos = info->lastpos;
		info->save_lastkey_length = info->lastkey_length;
		if (function == HA_EXTRA_REMEMBER_POS)
			break;
		/* fall through */
	case HA_EXTRA_KEYREAD_CHANGE_POS:
		info->opt_flag |= KEY_READ_USED;
		info->read_record = _mi_read_key_record;
		break;
	case HA_EXTRA_NO_KEYREAD:
	case HA_EXTRA_RESTORE_POS:
		if (info->opt_flag & REMEMBER_OLD_POS) {
			bmove((byte *) info->lastkey,
			      (byte *) info->lastkey + share->base.max_key_length * 2,
			      info->save_lastkey_length);
			info->update = info->save_update | HA_STATE_WRITTEN;
			info->lastinx = info->save_lastinx;
			info->lastpos = info->save_lastpos;
			info->lastkey_length = info->save_lastkey_length;
		}
		info->read_record = share->read_record;
		info->opt_flag &= ~(KEY_READ_USED | REMEMBER_OLD_POS);
		break;
	case HA_EXTRA_NO_USER_CHANGE:	/* Database is somehow locked agains
					 * changes */
		info->lock_type = F_EXTRA_LCK;	/* Simulate as locked */
		break;
	case HA_EXTRA_WAIT_LOCK:
		info->lock_wait = 0;
		break;
	case HA_EXTRA_NO_WAIT_LOCK:
		info->lock_wait = MY_DONT_WAIT;
		break;
	case HA_EXTRA_NO_KEYS:
		if (info->lock_type == F_UNLCK) {
			error = 1;	/* Not possibly if not lock */
			break;
		}
		if (share->state.key_map) {
			share->state.key_map = 0;
			info->state->key_file_length = share->state.state.key_file_length =
				share->base.keystart;
			if (!share->changed) {
				share->state.changed |= STATE_CHANGED | STATE_NOT_ANALYZED;
				share->changed = 1;	/* Update on close */
				if (!share->global_changed) {
					share->global_changed = 1;
					share->state.open_count++;
				}
			}
			share->state.state = *info->state;
			error = mi_state_info_write(share->kfile, &share->state, 1 | 2);
		}
		break;
	case HA_EXTRA_FORCE_REOPEN:
		pthread_mutex_lock(&THR_LOCK_myisam);
		share->last_version = 0L;	/* Impossible version */
#ifdef __WIN__
		/*
		 * Close the isam and data files as Win32 can't drop an open
		 * table
		 */
		pthread_mutex_lock(&share->intern_lock);
		if (flush_key_blocks(share->kfile, FLUSH_RELEASE)) {
			error = my_errno;
			share->changed = 1;
			mi_mark_crashed(info);	/* Fatal error found */
		}
		if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) {
			info->opt_flag &= ~(READ_CACHE_USED | WRITE_CACHE_USED);
			error = end_io_cache(&info->rec_cache);
		}
		if (info->lock_type != F_UNLCK && !info->was_locked) {
			info->was_locked = info->lock_type;
			if (mi_lock_database(info, F_UNLCK))
				error = my_errno;
			info->lock_type = F_UNLCK;
		}
		if (share->kfile >= 0)
			_mi_decrement_open_count(info);
		if (share->kfile >= 0 && my_close(share->kfile, MYF(0)))
			error = my_errno;
		{
			LIST           *list_element;
			for (list_element = myisam_open_list;
			     list_element;
			     list_element = list_element->next) {
				MI_INFO        *tmpinfo = (MI_INFO *) list_element->data;
				if (tmpinfo->s == info->s) {
					if (tmpinfo->dfile >= 0 && my_close(tmpinfo->dfile, MYF(0)))
						error = my_errno;
					tmpinfo->dfile = -1;
				}
			}
		}
		share->kfile = -1;	/* Files aren't open anymore */
		pthread_mutex_unlock(&share->intern_lock);
#endif
		pthread_mutex_unlock(&THR_LOCK_myisam);
		break;
	case HA_EXTRA_FLUSH:
		if (!share->temporary)
			flush_key_blocks(share->kfile, FLUSH_KEEP);
#ifdef HAVE_PWRITE
		_mi_decrement_open_count(info);
#endif
		if (share->not_flushed) {
			share->not_flushed = 0;
#if defined(__WIN__)
			if (_commit(share->kfile))
				error = errno;
			if (_commit(info->dfile))
				error = errno;
#elif defined(HAVE_FDATASYNC)
			if (fdatasync(share->kfile))
				error = errno;
			if (fdatasync(share->dfile))
				error = errno;
#elif defined(HAVE_FSYNC)
			if (fsync(share->kfile))
				error = errno;
			if (fsync(share->dfile))
				error = errno;
#endif
			if (error) {
				share->changed = 1;
				mi_mark_crashed(info);	/* Fatal error found */
			}
		}
		if (share->base.blobs) {
			my_free(info->rec_alloc, MYF(MY_ALLOW_ZERO_PTR));
			info->rec_alloc = info->rec_buff = 0;
			mi_fix_rec_buff_for_blob(info, info->s->base.pack_reclength);
		}
		break;
	case HA_EXTRA_NORMAL:	/* Theese isn't in use */
		info->quick_mode = 0;
		break;
	case HA_EXTRA_QUICK:
		info->quick_mode = 1;
		break;
	case HA_EXTRA_NO_ROWS:
		if (!share->state.header.uniques)
			info->opt_flag |= OPT_NO_ROWS;
		break;
	case HA_EXTRA_KEY_CACHE:
	case HA_EXTRA_NO_KEY_CACHE:
	default:
		break;
	}
	{
		char		tmp       [1];
		tmp[0] = function;
		myisam_log_command(MI_LOG_EXTRA, info, (byte *) tmp, 1, error);
	}
	DBUG_RETURN(error);
}				/* mi_extra */
Exemplo n.º 11
0
int mi_close(register MI_INFO *info)
{
  int error=0,flag;
  MYISAM_SHARE *share=info->s;
  DBUG_ENTER("mi_close");
  DBUG_PRINT("enter",("base: 0x%lx  reopen: %u  locks: %u",
		      (long) info, (uint) share->reopen,
                      (uint) share->tot_locks));

  pthread_mutex_lock(&THR_LOCK_myisam);
  if (info->lock_type == F_EXTRA_LCK)
    info->lock_type=F_UNLCK;			/* HA_EXTRA_NO_USER_CHANGE */

  if (share->reopen == 1 && share->kfile >= 0)
    _mi_decrement_open_count(info);

  if (info->lock_type != F_UNLCK)
  {
    if (mi_lock_database(info,F_UNLCK))
      error=my_errno;
  }
  pthread_mutex_lock(&share->intern_lock);

  if (share->options & HA_OPTION_READ_ONLY_DATA)
  {
    share->r_locks--;
    share->tot_locks--;
  }
  if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
  {
    if (end_io_cache(&info->rec_cache))
      error=my_errno;
    info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
  }
  flag= !--share->reopen;
  myisam_open_list=list_delete(myisam_open_list,&info->open_list);
  pthread_mutex_unlock(&share->intern_lock);

  my_free(mi_get_rec_buff_ptr(info, info->rec_buff), MYF(MY_ALLOW_ZERO_PTR));
  if (flag)
  {
    if (share->kfile >= 0 &&
	flush_key_blocks(share->key_cache, share->kfile,
			 share->temporary ? FLUSH_IGNORE_CHANGED :
			 FLUSH_RELEASE))
      error=my_errno;
    if (share->kfile >= 0)
    {
      /*
        If we are crashed, we can safely flush the current state as it will
        not change the crashed state.
        We can NOT write the state in other cases as other threads
        may be using the file at this point
      */
      if (share->mode != O_RDONLY && mi_is_crashed(info))
	mi_state_info_write(share->kfile, &share->state, 1);
      if (my_close(share->kfile,MYF(0)))
        error = my_errno;
    }
#ifdef HAVE_MMAP
    if (share->file_map)
      _mi_unmap_file(info);
#endif
    if (share->decode_trees)
    {
      my_free((uchar*) share->decode_trees,MYF(0));
      my_free((uchar*) share->decode_tables,MYF(0));
    }
#ifdef THREAD
    thr_lock_delete(&share->lock);
    VOID(pthread_mutex_destroy(&share->intern_lock));
    {
      int i,keys;
      keys = share->state.header.keys;
      VOID(rwlock_destroy(&share->mmap_lock));
      for(i=0; i<keys; i++) {
	VOID(rwlock_destroy(&share->key_root_lock[i]));
      }
    }
#endif
    my_free((uchar*) info->s,MYF(0));
  }
  pthread_mutex_unlock(&THR_LOCK_myisam);
  if (info->ftparser_param)
  {
    my_free((uchar*)info->ftparser_param, MYF(0));
    info->ftparser_param= 0;
  }
  if (info->dfile >= 0 && my_close(info->dfile,MYF(0)))
    error = my_errno;

  myisam_log_command(MI_LOG_CLOSE,info,NULL,0,error);
  my_free((uchar*) info,MYF(0));

  if (error)
  {
    DBUG_RETURN(my_errno=error);
  }
  DBUG_RETURN(0);
} /* mi_close */
Exemplo n.º 12
0
int test_update(MI_INFO *file,int id,int lock_type)
{
  uint i,lock,found,next,prev,update;
  uint32 tmp;
  char find[4];
  struct record new_record;

  lock=0;
  if (rnd(2) == 0 || lock_type == F_RDLCK)
  {
    lock=1;
    if (mi_lock_database(file,F_WRLCK))
    {
      if (lock_type == F_RDLCK && my_errno == EDEADLK)
      {
	printf("%2d: write:  deadlock\n",id); fflush(stdout);
	return 0;
      }
      fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
      return 1;
    }
  }
  bzero((char*) &new_record,sizeof(new_record));
  strmov((char*) new_record.text,"Updated");

  found=next=prev=update=0;
  for (i=0 ; i < 100 ; i++)
  {
    tmp=rnd(100000);
    int4store(find,tmp);
    if (!mi_rkey(file,record.id,1,(uchar*) find, HA_WHOLE_KEY,
                 HA_READ_KEY_EXACT))
      found++;
    else
    {
      if (my_errno != HA_ERR_KEY_NOT_FOUND)
      {
	fprintf(stderr,"%2d: Got error %d from read in update\n",id,my_errno);
	return 1;
      }
      else if (!mi_rnext(file,record.id,1))
	next++;
      else
      {
	if (my_errno != HA_ERR_END_OF_FILE)
	{
	  fprintf(stderr,"%2d: Got error %d from rnext in update\n",
		  id,my_errno);
	  return 1;
	}
	else if (!mi_rprev(file,record.id,1))
	  prev++;
	else
	{
	  if (my_errno != HA_ERR_END_OF_FILE)
	  {
	    fprintf(stderr,"%2d: Got error %d from rnext in update\n",
		    id,my_errno);
	    return 1;
	  }
	  continue;
	}
      }
    }
    memcpy(new_record.id, record.id, sizeof(record.id));
    tmp=rnd(20000)+40000;
    int4store(new_record.nr,tmp);
    if (!mi_update(file,record.id,new_record.id))
      update++;
    else
    {
      if (my_errno != HA_ERR_RECORD_CHANGED &&
	  my_errno != HA_ERR_RECORD_DELETED &&
	  my_errno != HA_ERR_FOUND_DUPP_KEY)
      {
	fprintf(stderr,"%2d: Got error %d from update\n",id,my_errno);
	return 1;
      }
    }
  }
  if (lock)
  {
    if (mi_lock_database(file,F_UNLCK))
    {
      fprintf(stderr,"Can't unlock table,id, error%d\n",my_errno);
      return 1;
    }
  }
  printf("%2d: update: %5d\n",id,update); fflush(stdout);
  return 0;
}
Exemplo n.º 13
0
int test_read(MI_INFO *file,int id)
{
  uint i,lock,found,next,prev;
  ulong find;

  lock=0;
  if (rnd(2) == 0)
  {
    lock=1;
    if (mi_lock_database(file,F_RDLCK))
    {
      fprintf(stderr,"%2d: Can't lock table %d\n",id,my_errno);
      return 1;
    }
  }

  found=next=prev=0;
  for (i=0 ; i < 100 ; i++)
  {
    find=rnd(100000);
    if (!mi_rkey(file,record.id,1,(uchar*) &find, HA_WHOLE_KEY,
                 HA_READ_KEY_EXACT))
      found++;
    else
    {
      if (my_errno != HA_ERR_KEY_NOT_FOUND)
      {
	fprintf(stderr,"%2d: Got error %d from read in read\n",id,my_errno);
	return 1;
      }
      else if (!mi_rnext(file,record.id,1))
	next++;
      else
      {
	if (my_errno != HA_ERR_END_OF_FILE)
	{
	  fprintf(stderr,"%2d: Got error %d from rnext in read\n",id,my_errno);
	  return 1;
	}
	else if (!mi_rprev(file,record.id,1))
	  prev++;
	else
	{
	  if (my_errno != HA_ERR_END_OF_FILE)
	  {
	    fprintf(stderr,"%2d: Got error %d from rnext in read\n",
		    id,my_errno);
	    return 1;
	  }
	}
      }
    }
  }
  if (lock)
  {
    if (mi_lock_database(file,F_UNLCK))
    {
      fprintf(stderr,"%2d: Can't unlock table\n",id);
      return 1;
    }
  }
  printf("%2d: read:   found: %5d  next: %5d   prev: %5d\n",
	 id,found,next,prev);
  fflush(stdout);
  return 0;
}
Exemplo n.º 14
0
static int examine_log(my_string file_name, char **table_names)
{
  uint command,result,files_open;
  ulong access_time,length;
  my_off_t filepos;
  int lock_command,mi_result;
  char isam_file_name[FN_REFLEN],llbuff[21],llbuff2[21];
  uchar head[20];
  gptr	buff;
  struct test_if_open_param open_param;
  IO_CACHE cache;
  File file;
  FILE *write_file;
  enum ha_extra_function extra_command;
  TREE tree;
  struct file_info file_info,*curr_file_info;
  DBUG_ENTER("examine_log");

  if ((file=my_open(file_name,O_RDONLY,MYF(MY_WME))) < 0)
    DBUG_RETURN(1);
  write_file=0;
  if (write_filename)
  {
    if (!(write_file=my_fopen(write_filename,O_WRONLY,MYF(MY_WME))))
    {
      my_close(file,MYF(0));
      DBUG_RETURN(1);
    }
  }

  init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0));
  bzero((gptr) com_count,sizeof(com_count));
  init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
	    (tree_element_free) file_info_free, NULL);
  VOID(init_key_cache(KEY_CACHE_SIZE));

  files_open=0; access_time=0;
  while (access_time++ != number_of_commands &&
	 !my_b_read(&cache,(byte*) head,9))
  {
    isamlog_filepos=my_b_tell(&cache)-9L;
    file_info.filenr= mi_uint2korr(head+1);
    isamlog_process=file_info.process=(long) mi_uint4korr(head+3);
    if (!opt_processes)
      file_info.process=0;
    result= mi_uint2korr(head+7);
    if ((curr_file_info=(struct file_info*) tree_search(&tree,&file_info)))
    {
      curr_file_info->accessed=access_time;
      if (update && curr_file_info->used && curr_file_info->closed)
      {
	if (reopen_closed_file(&tree,curr_file_info))
	{
	  command=sizeof(com_count)/sizeof(com_count[0][0])/3;
	  result=0;
	  goto com_err;
	}
      }
    }
    command=(uint) head[0];
    if (command < sizeof(com_count)/sizeof(com_count[0][0])/3 &&
	(!table_names[0] || (curr_file_info && curr_file_info->used)))
    {
      com_count[command][0]++;
      if (result)
	com_count[command][1]++;
    }
    switch ((enum myisam_log_commands) command) {
    case MI_LOG_OPEN:
      if (!table_names[0])
      {
	com_count[command][0]--;		/* Must be counted explicite */
	if (result)
	  com_count[command][1]--;
      }

      if (curr_file_info)
	printf("\nWarning: %s is opened with same process and filenumber\nMaybe you should use the -P option ?\n",
	       curr_file_info->show_name);
      if (my_b_read(&cache,(byte*) head,2))
	goto err;
      file_info.name=0;
      file_info.show_name=0;
      file_info.record=0;
      if (read_string(&cache,(gptr*) &file_info.name,
		      (uint) mi_uint2korr(head)))
	goto err;
      {
	uint i;
	char *pos,*to;

	/* Fix if old DOS files to new format */
	for (pos=file_info.name; (pos=strchr(pos,'\\')) ; pos++)
	  *pos= '/';

	pos=file_info.name;
	for (i=0 ; i < prefix_remove ; i++)
	{
	  char *next;
	  if (!(next=strchr(pos,'/')))
	    break;
	  pos=next+1;
	}
	to=isam_file_name;
	if (filepath)
	  to=convert_dirname(isam_file_name,filepath,NullS);
	strmov(to,pos);
	fn_ext(isam_file_name)[0]=0;	/* Remove extension */
      }
      open_param.name=file_info.name;
      open_param.max_id=0;
      VOID(tree_walk(&tree,(tree_walk_action) test_if_open,(void*) &open_param,
		     left_root_right));
      file_info.id=open_param.max_id+1;
      /*
       * In the line below +10 is added to accomodate '<' and '>' chars
       * plus '\0' at the end, so that there is place for 7 digits.
       * It is  improbable that same table can have that many entries in 
       * the table cache.
       * The additional space is needed for the sprintf commands two lines
       * below.
       */ 
      file_info.show_name=my_memdup(isam_file_name,
				    (uint) strlen(isam_file_name)+10,
				    MYF(MY_WME));
      if (file_info.id > 1)
	sprintf(strend(file_info.show_name),"<%d>",file_info.id);
      file_info.closed=1;
      file_info.accessed=access_time;
      file_info.used=1;
      if (table_names[0])
      {
	char **name;
	file_info.used=0;
	for (name=table_names ; *name ; name++)
	{
	  if (!strcmp(*name,isam_file_name))
	    file_info.used=1;			/* Update/log only this */
	}
      }
      if (update && file_info.used)
      {
	if (files_open >= max_files)
	{
	  if (close_some_file(&tree))
	    goto com_err;
	  files_open--;
	}
	if (!(file_info.isam= mi_open(isam_file_name,O_RDWR,
				      HA_OPEN_WAIT_IF_LOCKED)))
	  goto com_err;
	if (!(file_info.record=my_malloc(file_info.isam->s->base.reclength,
					 MYF(MY_WME))))
	  goto end;
	files_open++;
	file_info.closed=0;
	if (opt_myisam_with_debug)
	  file_info.isam->s->rnd= 0;
	else
	  file_info.isam->s->rnd= isamlog_process;
      }
      VOID(tree_insert(&tree,(gptr) &file_info,0));
      if (file_info.used)
      {
	if (verbose && !record_pos_file)
	  printf_log("%s: open -> %d",file_info.show_name, file_info.filenr);
	com_count[command][0]++;
	if (result)
	  com_count[command][1]++;
      }
      break;
    case MI_LOG_CLOSE:
      if (verbose && !record_pos_file &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
	printf_log("%s: %s -> %d",FILENAME(curr_file_info),
	       command_name[command],result);
      if (curr_file_info)
      {
	if (!curr_file_info->closed)
	  files_open--;
	VOID(tree_delete(&tree,(gptr) curr_file_info));
      }
      break;
    case MI_LOG_EXTRA:
      if (my_b_read(&cache,(byte*) head,1))
	goto err;
      extra_command=(enum ha_extra_function) head[0];
      if (verbose && !record_pos_file &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
	printf_log("%s: %s(%d) -> %d",FILENAME(curr_file_info),
		   command_name[command], (int) extra_command,result);
      if (update && curr_file_info && !curr_file_info->closed)
      {
	if (mi_extra(curr_file_info->isam, extra_command, 0) != (int) result)
	{
	  fflush(stdout);
	  VOID(fprintf(stderr,
		       "Warning: error %d, expected %d on command %s at %s\n",
		       my_errno,result,command_name[command],
		       llstr(isamlog_filepos,llbuff)));
	  fflush(stderr);
	}
      }
      break;
    case MI_LOG_DELETE:
      if (my_b_read(&cache,(byte*) head,8))
	goto err;
      filepos=mi_sizekorr(head);
      if (verbose && (!record_pos_file ||
		      ((record_pos == filepos || record_pos == NO_FILEPOS) &&
		       !cmp_filename(curr_file_info,record_pos_file))) &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
	printf_log("%s: %s at %ld -> %d",FILENAME(curr_file_info),
		   command_name[command],(long) filepos,result);
      if (update && curr_file_info && !curr_file_info->closed)
      {
	if (mi_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
	{
	  if (!recover)
	    goto com_err;
	  if (verbose)
	    printf_log("error: Didn't find row to delete with mi_rrnd");
	  com_count[command][2]++;		/* Mark error */
	}
	mi_result=mi_delete(curr_file_info->isam,curr_file_info->record);
	if ((mi_result == 0 && result) ||
	    (mi_result && (uint) my_errno != result))
	{
	  if (!recover)
	    goto com_err;
	  if (mi_result)
	    com_count[command][2]++;		/* Mark error */
	  if (verbose)
	    printf_log("error: Got result %d from mi_delete instead of %d",
		       mi_result, result);
	}
      }
      break;
    case MI_LOG_WRITE:
    case MI_LOG_UPDATE:
      if (my_b_read(&cache,(byte*) head,12))
	goto err;
      filepos=mi_sizekorr(head);
      length=mi_uint4korr(head+8);
      buff=0;
      if (read_string(&cache,&buff,(uint) length))
	goto err;
      if ((!record_pos_file ||
	  ((record_pos == filepos || record_pos == NO_FILEPOS) &&
	   !cmp_filename(curr_file_info,record_pos_file))) &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
      {
	if (write_file &&
	    (my_fwrite(write_file,buff,length,MYF(MY_WAIT_IF_FULL | MY_NABP))))
	  goto end;
	if (verbose)
	  printf_log("%s: %s at %ld, length=%ld -> %d",
		     FILENAME(curr_file_info),
		     command_name[command], filepos,length,result);
      }
      if (update && curr_file_info && !curr_file_info->closed)
      {
	if (curr_file_info->isam->s->base.blobs)
	  fix_blob_pointers(curr_file_info->isam,buff);
	if ((enum myisam_log_commands) command == MI_LOG_UPDATE)
	{
	  if (mi_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
	  {
	    if (!recover)
	    {
	      result=0;
	      goto com_err;
	    }
	    if (verbose)
	      printf_log("error: Didn't find row to update with mi_rrnd");
	    if (recover == 1 || result ||
		find_record_with_key(curr_file_info,buff))
	    {
	      com_count[command][2]++;		/* Mark error */
	      break;
	    }
	  }
	  mi_result=mi_update(curr_file_info->isam,curr_file_info->record,
			      buff);
	  if ((mi_result == 0 && result) ||
	      (mi_result && (uint) my_errno != result))
	  {
	    if (!recover)
	      goto com_err;
	    if (verbose)
	      printf_log("error: Got result %d from mi_update instead of %d",
			 mi_result, result);
	    if (mi_result)
	      com_count[command][2]++;		/* Mark error */
	  }
	}
	else
	{
	  mi_result=mi_write(curr_file_info->isam,buff);
	  if ((mi_result == 0 && result) ||
	      (mi_result && (uint) my_errno != result))
	  {
	    if (!recover)
	      goto com_err;
	    if (verbose)
	      printf_log("error: Got result %d from mi_write instead of %d",
			 mi_result, result);
	    if (mi_result)
	      com_count[command][2]++;		/* Mark error */
	  }
	  if (!recover && filepos != curr_file_info->isam->lastpos)
	  {
	    printf("error: Wrote at position: %s, should have been %s",
		   llstr(curr_file_info->isam->lastpos,llbuff),
		   llstr(filepos,llbuff2));
	    goto end;
	  }
	}
      }
      my_free(buff,MYF(0));
      break;
    case MI_LOG_LOCK:
      if (my_b_read(&cache,(byte*) head,sizeof(lock_command)))
	goto err;
      memcpy_fixed(&lock_command,head,sizeof(lock_command));
      if (verbose && !record_pos_file &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
	printf_log("%s: %s(%d) -> %d\n",FILENAME(curr_file_info),
		   command_name[command],lock_command,result);
      if (update && curr_file_info && !curr_file_info->closed)
      {
	if (mi_lock_database(curr_file_info->isam,lock_command) !=
	    (int) result)
	  goto com_err;
      }
      break;
    case MI_LOG_DELETE_ALL:
      if (verbose && !record_pos_file &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
	printf_log("%s: %s -> %d\n",FILENAME(curr_file_info),
		   command_name[command],result);
      break;
    default:
      fflush(stdout);
      VOID(fprintf(stderr,
		   "Error: found unknown command %d in logfile, aborted\n",
		   command));
      fflush(stderr);
      goto end;
    }
  }
  end_key_cache();
  delete_tree(&tree);
  VOID(end_io_cache(&cache));
  VOID(my_close(file,MYF(0)));
  if (write_file && my_fclose(write_file,MYF(MY_WME)))
    DBUG_RETURN(1);
  DBUG_RETURN(0);

 err:
  fflush(stdout);
  VOID(fprintf(stderr,"Got error %d when reading from logfile\n",my_errno));
  fflush(stderr);
  goto end;
 com_err:
  fflush(stdout);
  VOID(fprintf(stderr,"Got error %d, expected %d on command %s at %s\n",
	       my_errno,result,command_name[command],
	       llstr(isamlog_filepos,llbuff)));
  fflush(stderr);
 end:
  end_key_cache();
  delete_tree(&tree);
  VOID(end_io_cache(&cache));
  VOID(my_close(file,MYF(0)));
  if (write_file)
    VOID(my_fclose(write_file,MYF(MY_WME)));
  DBUG_RETURN(1);
}
Exemplo n.º 15
0
int mi_close(register MI_INFO *info)
{
  int error=0,flag;
  MYISAM_SHARE *share=info->s;
  DBUG_ENTER("mi_close");
  DBUG_PRINT("enter",("base: 0x%lx  reopen: %u  locks: %u",
		      (long) info, (uint) share->reopen,
                      (uint) share->tot_locks));

  mysql_mutex_lock(&THR_LOCK_myisam);
  if (info->lock_type == F_EXTRA_LCK)
    info->lock_type=F_UNLCK;			/* HA_EXTRA_NO_USER_CHANGE */

  if (info->lock_type != F_UNLCK)
  {
    if (mi_lock_database(info,F_UNLCK))
      error=my_errno;
  }
  mysql_mutex_lock(&share->intern_lock);

  if (share->options & HA_OPTION_READ_ONLY_DATA)
  {
    share->r_locks--;
    share->tot_locks--;
  }
  if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
  {
    if (end_io_cache(&info->rec_cache))
      error=my_errno;
    info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
  }
  flag= !--share->reopen;
  myisam_open_list=list_delete(myisam_open_list,&info->open_list);
  mysql_mutex_unlock(&share->intern_lock);

  my_free(mi_get_rec_buff_ptr(info, info->rec_buff));
  if (flag)
  {
    DBUG_EXECUTE_IF("crash_before_flush_keys",
                    if (share->kfile >= 0) abort(););
    if (share->kfile >= 0 &&
	flush_key_blocks(share->key_cache, share->kfile,
			 share->temporary ? FLUSH_IGNORE_CHANGED :
			 FLUSH_RELEASE))
      error=my_errno;
    if (share->kfile >= 0)
    {
      /*
        If we are crashed, we can safely flush the current state as it will
        not change the crashed state.
        We can NOT write the state in other cases as other threads
        may be using the file at this point
      */
      if (share->mode != O_RDONLY && mi_is_crashed(info))
	mi_state_info_write(share->kfile, &share->state, 1);
      /* Decrement open count must be last I/O on this file. */
      _mi_decrement_open_count(info);
      if (mysql_file_close(share->kfile, MYF(0)))
        error = my_errno;
    }
#ifdef HAVE_MMAP
    if (share->file_map)
      _mi_unmap_file(info);
#endif
    if (share->decode_trees)
    {
      my_free(share->decode_trees);
      my_free(share->decode_tables);
    }
    thr_lock_delete(&share->lock);
    mysql_mutex_destroy(&share->intern_lock);
    {
      int i,keys;
      keys = share->state.header.keys;
      mysql_rwlock_destroy(&share->mmap_lock);
      for(i=0; i<keys; i++) {
        mysql_rwlock_destroy(&share->key_root_lock[i]);
      }
    }
    my_free(info->s);
  }
Exemplo n.º 16
0
int mi_panic(enum ha_panic_function flag)
{
  int error=0;
  LIST *list_element,*next_open;
  MI_INFO *info;
  DBUG_ENTER("mi_panic");

  mysql_mutex_lock(&THR_LOCK_myisam);
  for (list_element=myisam_open_list ; list_element ; list_element=next_open)
  {
    next_open=list_element->next;		/* Save if close */
    info=(MI_INFO*) list_element->data;
    switch (flag) {
    case HA_PANIC_CLOSE:
      mysql_mutex_unlock(&THR_LOCK_myisam);     /* Not exactly right... */
      if (mi_close(info))
	error=my_errno;
      mysql_mutex_lock(&THR_LOCK_myisam);
      break;
    case HA_PANIC_WRITE:		/* Do this to free databases */
#ifdef CANT_OPEN_FILES_TWICE
      if (info->s->options & HA_OPTION_READ_ONLY_DATA)
	break;
#endif
      if (flush_key_blocks(info->s->key_cache, info->s->kfile, FLUSH_RELEASE))
	error=my_errno;
      if (info->opt_flag & WRITE_CACHE_USED)
	if (flush_io_cache(&info->rec_cache))
	  error=my_errno;
      if (info->opt_flag & READ_CACHE_USED)
      {
	if (flush_io_cache(&info->rec_cache))
	  error=my_errno;
	reinit_io_cache(&info->rec_cache,READ_CACHE,0,
		       (pbool) (info->lock_type != F_UNLCK),1);
      }
      if (info->lock_type != F_UNLCK && ! info->was_locked)
      {
	info->was_locked=info->lock_type;
	if (mi_lock_database(info,F_UNLCK))
	  error=my_errno;
      }
#ifdef CANT_OPEN_FILES_TWICE
      if (info->s->kfile >= 0 && mysql_file_close(info->s->kfile, MYF(0)))
	error = my_errno;
      if (info->dfile >= 0 && mysql_file_close(info->dfile, MYF(0)))
	error = my_errno;
      info->s->kfile=info->dfile= -1;	/* Files aren't open anymore */
      break;
#endif
    case HA_PANIC_READ:			/* Restore to before WRITE */
#ifdef CANT_OPEN_FILES_TWICE
      {					/* Open closed files */
	char name_buff[FN_REFLEN];
	if (info->s->kfile < 0)
          if ((info->s->kfile= mysql_file_open(mi_key_file_kfile,
                                               fn_format(name_buff,
                                                         info->filename, "",
                                                         N_NAME_IEXT, 4),
                                               info->mode, MYF(MY_WME))) < 0)
	    error = my_errno;
	if (info->dfile < 0)
	{
          if ((info->dfile= mysql_file_open(mi_key_file_dfile,
                                            fn_format(name_buff,
                                                      info->filename, "",
                                                      N_NAME_DEXT, 4),
                                            info->mode, MYF(MY_WME))) < 0)
	    error = my_errno;
	  info->rec_cache.file=info->dfile;
	}
      }
#endif
      if (info->was_locked)
      {
	if (mi_lock_database(info, info->was_locked))
	  error=my_errno;
	info->was_locked=0;
      }
      break;
    }
  }
  if (flag == HA_PANIC_CLOSE)
  {
    (void) mi_log(0);				/* Close log if neaded */
    ft_free_stopwords();
  }
  mysql_mutex_unlock(&THR_LOCK_myisam);
  if (!error)
    DBUG_RETURN(0);
  DBUG_RETURN(my_errno=error);
} /* mi_panic */