mi_preload.c 3.56 KB
Newer Older
1
/* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
unknown's avatar
unknown committed
2 3 4

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
6 7 8 9 10 11 12 13

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
unknown's avatar
unknown committed
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

/*
  Preload indexes into key cache
*/

#include "myisamdef.h"


/*
  Preload pages of the index file for a table into the key cache

  SYNOPSIS
    mi_preload()
      info          open table
      map           map of indexes to preload into key cache 
      ignore_leaves only non-leaves pages are to be preloaded

  RETURN VALUE
    0 if a success. error code - otherwise.

  NOTES.
    At present pages for all indexes are preloaded.
    In future only pages for indexes specified in the key_map parameter
    of the table will be preloaded.
*/

int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
{
  uint i;
unknown's avatar
unknown committed
44
  ulong length, block_length= 0;
unknown's avatar
unknown committed
45 46 47 48 49 50
  uchar *buff= NULL;
  MYISAM_SHARE* share= info->s;
  uint keys= share->state.header.keys;
  MI_KEYDEF *keyinfo= share->keyinfo;
  my_off_t key_file_length= share->state.state.key_file_length;
  my_off_t pos= share->base.keystart;
unknown's avatar
unknown committed
51
  DBUG_ENTER("mi_preload");
unknown's avatar
unknown committed
52

53
  if (!keys || !mi_is_any_key_active(key_map) || key_file_length == pos)
unknown's avatar
unknown committed
54
    DBUG_RETURN(0);
unknown's avatar
unknown committed
55

56 57 58
  /* Preload into a non initialized key cache should never happen. */
  DBUG_ASSERT(share->key_cache->key_cache_inited);

unknown's avatar
unknown committed
59 60
  block_length= keyinfo[0].block_length;

61
  if (ignore_leaves)
unknown's avatar
unknown committed
62
  {
63 64 65 66 67 68
    /* Check whether all indexes use the same block size */
    for (i= 1 ; i < keys ; i++)
    {
      if (keyinfo[i].block_length != block_length)
        DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE);
    }
69 70
  }
  else
71
    block_length= share->key_cache->param_block_size;
72

unknown's avatar
unknown committed
73 74 75 76
  length= info->preload_buff_size/block_length * block_length;
  set_if_bigger(length, block_length);

  if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME))))
unknown's avatar
unknown committed
77
    DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM);
unknown's avatar
unknown committed
78

79 80
  if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
                       FLUSH_RELEASE))
unknown's avatar
unknown committed
81
    goto err;
unknown's avatar
unknown committed
82

unknown's avatar
unknown committed
83 84 85
  do
  {
    /* Read the next block of index file into the preload buffer */
unknown's avatar
unknown committed
86 87
    if ((my_off_t) length > (key_file_length-pos))
      length= (ulong) (key_file_length-pos);
Marc Alff's avatar
Marc Alff committed
88 89
    if (mysql_file_pread(share->kfile, (uchar*) buff, length, pos,
                         MYF(MY_FAE|MY_FNABP)))
unknown's avatar
unknown committed
90
      goto err;
unknown's avatar
unknown committed
91

unknown's avatar
unknown committed
92 93 94 95 96 97 98
    if (ignore_leaves)
    {
      uchar *end= buff+length;
      do
      {
        if (mi_test_if_nod(buff))
        {
unknown's avatar
unknown committed
99
          if (key_cache_insert(share->key_cache,
unknown's avatar
unknown committed
100
                               share->kfile, pos, DFLT_INIT_HITS,
101
                              (uchar*) buff, block_length))
unknown's avatar
unknown committed
102 103 104 105 106 107 108 109 110
	    goto err;
	}
        pos+= block_length;
      }
      while ((buff+= block_length) != end);
      buff= end-length;
    }
    else
    {
unknown's avatar
unknown committed
111
      if (key_cache_insert(share->key_cache,
112
                           share->kfile, pos, DFLT_INIT_HITS,
113
                           (uchar*) buff, length))
unknown's avatar
unknown committed
114 115 116 117 118 119
	goto err;
      pos+= length;
    }
  }
  while (pos != key_file_length);

120
  my_free(buff);
unknown's avatar
unknown committed
121
  DBUG_RETURN(0);
unknown's avatar
unknown committed
122 123

err:
124
  my_free(buff);
unknown's avatar
unknown committed
125
  DBUG_RETURN(my_errno= errno);
unknown's avatar
unknown committed
126 127
}