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 | |
41 | int 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 | |
123 | err: |
124 | my_free(buff); |
125 | DBUG_RETURN(my_errno= errno); |
126 | } |
127 | |
128 | |