Exemplo n.º 1
0
my_off_t _mi_new(MI_INFO *info, MI_KEYDEF *keyinfo, int level)
{
  my_off_t pos;
  uchar buff[8];
  DBUG_ENTER("_mi_new");

  if ((pos= info->s->state.key_del[keyinfo->block_size_index]) ==
      HA_OFFSET_ERROR)
  {
    if (info->state->key_file_length >=
	info->s->base.max_key_file_length - keyinfo->block_length)
    {
      set_my_errno(HA_ERR_INDEX_FILE_FULL);
      DBUG_RETURN(HA_OFFSET_ERROR);
    }
    pos=info->state->key_file_length;
    info->state->key_file_length+= keyinfo->block_length;
  }
  else
  {
    if (!key_cache_read(info->s->key_cache,
                        keycache_thread_var(),
                        info->s->kfile, pos, level,
			buff,
			(uint) sizeof(buff),
			(uint) keyinfo->block_length,0))
      pos= HA_OFFSET_ERROR;
    else
      info->s->state.key_del[keyinfo->block_size_index]= mi_sizekorr(buff);
  }
  info->s->state.changed|= STATE_NOT_SORTED_PAGES;
  DBUG_PRINT("exit",("Pos: %ld",(long) pos));
  DBUG_RETURN(pos);
} /* _mi_new */
Exemplo n.º 2
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.º 3
0
my_off_t _ma_new(register MARIA_HA *info, int level,
                 MARIA_PINNED_PAGE **page_link)

{
  my_off_t pos;
  MARIA_SHARE *share= info->s;
  uint block_size= share->block_size;
  DBUG_ENTER("_ma_new");

  if (_ma_lock_key_del(info, 1))
  {
    mysql_mutex_lock(&share->intern_lock);
    pos= share->state.state.key_file_length;
    if (pos >= share->base.max_key_file_length - block_size)
    {
      my_errno=HA_ERR_INDEX_FILE_FULL;
      mysql_mutex_unlock(&share->intern_lock);
      DBUG_RETURN(HA_OFFSET_ERROR);
    }
    share->state.state.key_file_length+= block_size;
    /* Following is for not transactional tables */
    info->state->key_file_length= share->state.state.key_file_length;
    mysql_mutex_unlock(&share->intern_lock);
    (*page_link)->changed= 0;
    (*page_link)->write_lock= PAGECACHE_LOCK_WRITE;
  }
  else
  {
    uchar *buff;
    pos= share->key_del_current;                /* Protected */
    DBUG_ASSERT(share->pagecache->block_size == block_size);
    if (!(buff= pagecache_read(share->pagecache,
                               &share->kfile,
                               (pgcache_page_no_t) (pos / block_size), level,
                               0, share->page_type,
                               PAGECACHE_LOCK_WRITE, &(*page_link)->link)))
      pos= HA_OFFSET_ERROR;
    else
    {
      /*
        Next deleted page's number is in the header of the present page
        (single linked list):
      */
#ifndef DBUG_OFF
      my_off_t key_del_current;
#endif
      share->key_del_current= mi_sizekorr(buff+share->keypage_header);
#ifndef DBUG_OFF
      key_del_current= share->key_del_current;
      DBUG_ASSERT((key_del_current != 0) &&
                  ((key_del_current == HA_OFFSET_ERROR) ||
                   (key_del_current <=
                    (share->state.state.key_file_length - block_size))));
#endif
    }

    (*page_link)->unlock=     PAGECACHE_LOCK_WRITE_UNLOCK;
    (*page_link)->write_lock= PAGECACHE_LOCK_WRITE;
    /*
      We have to mark it changed as _ma_flush_pending_blocks() uses
      'changed' to know if we used the page cache or not
    */
    (*page_link)->changed= 1;
    push_dynamic(&info->pinned_pages, (void*) *page_link);
    *page_link= dynamic_element(&info->pinned_pages,
                                info->pinned_pages.elements-1,
                                MARIA_PINNED_PAGE *);
  }
  share->state.changed|= STATE_NOT_SORTED_PAGES;
  DBUG_PRINT("exit",("Pos: %ld",(long) pos));
  DBUG_RETURN(pos);
} /* _ma_new */