1/* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15
16/*
17 Preload indexes into key cache
18*/
19
20#include "myisamdef.h"
21
22
23/*
24 Preload pages of the index file for a table into the key cache
25
26 SYNOPSIS
27 mi_preload()
28 info open table
29 map map of indexes to preload into key cache
30 ignore_leaves only non-leaves pages are to be preloaded
31
32 RETURN VALUE
33 0 if a success. error code - otherwise.
34
35 NOTES.
36 At present pages for all indexes are preloaded.
37 In future only pages for indexes specified in the key_map parameter
38 of the table will be preloaded.
39*/
40
41int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
42{
43 uint i;
44 size_t length, block_length= 0;
45 uchar *buff= NULL;
46 MYISAM_SHARE* share= info->s;
47 uint keys= share->state.header.keys;
48 MI_KEYDEF *keyinfo= share->keyinfo;
49 my_off_t key_file_length= share->state.state.key_file_length;
50 my_off_t pos= share->base.keystart;
51 DBUG_ENTER("mi_preload");
52
53 if (!keys || !mi_is_any_key_active(key_map) || key_file_length == pos)
54 DBUG_RETURN(0);
55
56 /* Preload into a non initialized key cache should never happen. */
57 DBUG_ASSERT(share->key_cache->key_cache_inited);
58
59 block_length= keyinfo[0].block_length;
60
61 if (ignore_leaves)
62 {
63 /* Check whether all indexes use the same block size */
64 for (i= 1 ; i < keys ; i++)
65 {
66 if (keyinfo[i].block_length != block_length)
67 DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE);
68 }
69 }
70 else
71 block_length= (size_t)share->key_cache->param_block_size;
72
73 length= info->preload_buff_size/block_length * block_length;
74 set_if_bigger(length, block_length);
75
76 if (!(buff= (uchar *) my_malloc(length, MYF(MY_WME))))
77 DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM);
78
79 if (flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
80 FLUSH_RELEASE))
81 goto err;
82
83 do
84 {
85 /* Read the next block of index file into the preload buffer */
86 if ((my_off_t) length > (key_file_length-pos))
87 length= (size_t) (key_file_length-pos);
88 if (mysql_file_pread(share->kfile, (uchar*) buff, length, pos,
89 MYF(MY_FAE|MY_FNABP)))
90 goto err;
91
92 if (ignore_leaves)
93 {
94 uchar *end= buff+length;
95 do
96 {
97 if (mi_test_if_nod(buff))
98 {
99 if (key_cache_insert(share->key_cache,
100 share->kfile, pos, DFLT_INIT_HITS,
101 buff, (uint)block_length))
102 goto err;
103 }
104 pos+= block_length;
105 }
106 while ((buff+= block_length) != end);
107 buff= end-length;
108 }
109 else
110 {
111 if (key_cache_insert(share->key_cache,
112 share->kfile, pos, DFLT_INIT_HITS,
113 (uchar*) buff, (uint)length))
114 goto err;
115 pos+= length;
116 }
117 }
118 while (pos != key_file_length);
119
120 my_free(buff);
121 DBUG_RETURN(0);
122
123err:
124 my_free(buff);
125 DBUG_RETURN(my_errno= errno);
126}
127
128