1 | /* Copyright (c) 2003-2008 MySQL AB, 2009 Sun Microsystems, Inc. |
2 | Use is subject to license terms. |
3 | |
4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by |
6 | the Free Software Foundation; version 2 of the License. |
7 | |
8 | This program is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | GNU General Public License for more details. |
12 | |
13 | You should have received a copy of the GNU General Public License |
14 | along with this program; if not, write to the Free Software |
15 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
16 | |
17 | /* |
18 | Key cache assignments |
19 | */ |
20 | |
21 | #include "myisamdef.h" |
22 | |
23 | /* |
24 | Assign pages of the index file for a table to a key cache |
25 | |
26 | SYNOPSIS |
27 | mi_assign_to_key_cache() |
28 | info open table |
29 | key_map map of indexes to assign to the key cache |
30 | key_cache_ptr pointer to the key cache handle |
31 | assign_lock Mutex to lock during assignment |
32 | |
33 | PREREQUESTS |
34 | One must have a READ lock or a WRITE lock on the table when calling |
35 | the function to ensure that there is no other writers to it. |
36 | |
37 | The caller must also ensure that one doesn't call this function from |
38 | two different threads with the same table. |
39 | |
40 | NOTES |
41 | At present pages for all indexes must be assigned to the same key cache. |
42 | In future only pages for indexes specified in the key_map parameter |
43 | of the table will be assigned to the specified key cache. |
44 | |
45 | RETURN VALUE |
46 | 0 If a success |
47 | # Error code |
48 | */ |
49 | |
50 | int mi_assign_to_key_cache(MI_INFO *info, |
51 | ulonglong key_map __attribute__((unused)), |
52 | KEY_CACHE *new_key_cache) |
53 | { |
54 | int error= 0; |
55 | MYISAM_SHARE* share= info->s; |
56 | KEY_CACHE *old_key_cache= share->key_cache; |
57 | DBUG_ENTER("mi_assign_to_key_cache" ); |
58 | DBUG_PRINT("enter" ,("old_key_cache_handle: %p new_key_cache_handle: %p" , |
59 | old_key_cache, new_key_cache)); |
60 | |
61 | /* |
62 | Skip operation if we didn't change key cache. This can happen if we |
63 | call this for all open instances of the same table |
64 | */ |
65 | if (old_key_cache == new_key_cache) |
66 | DBUG_RETURN(0); |
67 | |
68 | /* |
69 | First flush all blocks for the table in the old key cache. |
70 | This is to ensure that the disk is consistent with the data pages |
71 | in memory (which may not be the case if the table uses delayed_key_write) |
72 | |
73 | Note that some other read thread may still fill in the key cache with |
74 | new blocks during this call and after, but this doesn't matter as |
75 | all threads will start using the new key cache for their next call to |
76 | myisam library and we know that there will not be any changed blocks |
77 | in the old key cache. |
78 | */ |
79 | |
80 | pthread_mutex_lock(&old_key_cache->op_lock); |
81 | DEBUG_SYNC_C("assign_key_cache_op_lock" ); |
82 | if (flush_key_blocks(old_key_cache, share->kfile, &share->dirty_part_map, |
83 | FLUSH_RELEASE)) |
84 | { |
85 | error= my_errno; |
86 | mi_print_error(info->s, HA_ERR_CRASHED); |
87 | mi_mark_crashed(info); /* Mark that table must be checked */ |
88 | } |
89 | pthread_mutex_unlock(&old_key_cache->op_lock); |
90 | DEBUG_SYNC_C("assign_key_cache_op_unlock" ); |
91 | |
92 | /* |
93 | Flush the new key cache for this file. This is needed to ensure |
94 | that there is no old blocks (with outdated data) left in the new key |
95 | cache from an earlier assign_to_keycache operation |
96 | |
97 | (This can never fail as there is never any not written data in the |
98 | new key cache) |
99 | */ |
100 | (void) flush_key_blocks(new_key_cache, share->kfile, &share->dirty_part_map, |
101 | FLUSH_RELEASE); |
102 | |
103 | /* |
104 | ensure that setting the key cache and changing the multi_key_cache |
105 | is done atomicly |
106 | */ |
107 | mysql_mutex_lock(&share->intern_lock); |
108 | /* |
109 | Tell all threads to use the new key cache |
110 | This should be seen at the lastes for the next call to an myisam function. |
111 | */ |
112 | share->key_cache= new_key_cache; |
113 | share->dirty_part_map= 0; |
114 | |
115 | /* store the key cache in the global hash structure for future opens */ |
116 | if (multi_key_cache_set((uchar*) share->unique_file_name, |
117 | share->unique_name_length, |
118 | new_key_cache)) |
119 | error= my_errno; |
120 | mysql_mutex_unlock(&share->intern_lock); |
121 | DBUG_RETURN(error); |
122 | } |
123 | |
124 | |
125 | /* |
126 | Change all MyISAM entries that uses one key cache to another key cache |
127 | |
128 | SYNOPSIS |
129 | mi_change_key_cache() |
130 | old_key_cache Old key cache |
131 | new_key_cache New key cache |
132 | |
133 | NOTES |
134 | This is used when we delete one key cache. |
135 | |
136 | To handle the case where some other threads tries to open an MyISAM |
137 | table associated with the to-be-deleted key cache while this operation |
138 | is running, we have to call 'multi_key_cache_change()' from this |
139 | function while we have a lock on the MyISAM table list structure. |
140 | |
141 | This is safe as long as it's only MyISAM that is using this specific |
142 | key cache. |
143 | */ |
144 | |
145 | |
146 | void mi_change_key_cache(KEY_CACHE *old_key_cache, |
147 | KEY_CACHE *new_key_cache) |
148 | { |
149 | LIST *pos; |
150 | DBUG_ENTER("mi_change_key_cache" ); |
151 | |
152 | /* |
153 | Lock list to ensure that no one can close the table while we manipulate it |
154 | */ |
155 | mysql_mutex_lock(&THR_LOCK_myisam); |
156 | for (pos=myisam_open_list ; pos ; pos=pos->next) |
157 | { |
158 | MI_INFO *info= (MI_INFO*) pos->data; |
159 | MYISAM_SHARE *share= info->s; |
160 | if (share->key_cache == old_key_cache) |
161 | mi_assign_to_key_cache(info, (ulonglong) ~0, new_key_cache); |
162 | } |
163 | |
164 | /* |
165 | We have to do the following call while we have the lock on the |
166 | MyISAM list structure to ensure that another thread is not trying to |
167 | open a new table that will be associted with the old key cache |
168 | */ |
169 | multi_key_cache_change(old_key_cache, new_key_cache); |
170 | mysql_mutex_unlock(&THR_LOCK_myisam); |
171 | DBUG_VOID_RETURN; |
172 | } |
173 | |