1 | /* Copyright (C) 2006 MySQL AB |
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 Street, Fifth Floor, Boston, MA 02111-1301 USA */ |
15 | |
16 | /* |
17 | Key cache assignments |
18 | */ |
19 | |
20 | #include "maria_def.h" |
21 | |
22 | /* |
23 | Assign pages of the index file for a table to a key cache |
24 | |
25 | SYNOPSIS |
26 | maria_assign_to_pagecache() |
27 | info open table |
28 | key_map map of indexes to assign to the key cache |
29 | pagecache_ptr pointer to the key cache handle |
30 | assign_lock Mutex to lock during assignment |
31 | |
32 | PREREQUESTS |
33 | One must have a READ lock or a WRITE lock on the table when calling |
34 | the function to ensure that there is no other writers to it. |
35 | |
36 | The caller must also ensure that one doesn't call this function from |
37 | two different threads with the same table. |
38 | |
39 | NOTES |
40 | At present pages for all indexes must be assigned to the same key cache. |
41 | In future only pages for indexes specified in the key_map parameter |
42 | of the table will be assigned to the specified key cache. |
43 | |
44 | RETURN VALUE |
45 | 0 If a success |
46 | # Error code |
47 | */ |
48 | |
49 | int maria_assign_to_pagecache(MARIA_HA *info, |
50 | ulonglong key_map __attribute__((unused)), |
51 | PAGECACHE *pagecache) |
52 | { |
53 | int error= 0; |
54 | MARIA_SHARE* share= info->s; |
55 | DBUG_ENTER("maria_assign_to_pagecache" ); |
56 | DBUG_PRINT("enter" , |
57 | ("old_pagecache_handle:%p new_pagecache_handle:%p" , |
58 | share->pagecache, pagecache)); |
59 | |
60 | /* |
61 | Skip operation if we didn't change key cache. This can happen if we |
62 | call this for all open instances of the same table |
63 | */ |
64 | if (share->pagecache == pagecache) |
65 | DBUG_RETURN(0); |
66 | |
67 | /* |
68 | First flush all blocks for the table in the old key cache. |
69 | This is to ensure that the disk is consistent with the data pages |
70 | in memory (which may not be the case if the table uses delayed_key_write) |
71 | |
72 | Note that some other read thread may still fill in the key cache with |
73 | new blocks during this call and after, but this doesn't matter as |
74 | all threads will start using the new key cache for their next call to |
75 | maria library and we know that there will not be any changed blocks |
76 | in the old key cache. |
77 | */ |
78 | |
79 | if (flush_pagecache_blocks(share->pagecache, &share->kfile, FLUSH_RELEASE)) |
80 | { |
81 | error= my_errno; |
82 | /* Mark that table must be checked */ |
83 | _ma_set_fatal_error(share, error); |
84 | } |
85 | |
86 | /* |
87 | Flush the new key cache for this file. This is needed to ensure |
88 | that there is no old blocks (with outdated data) left in the new key |
89 | cache from an earlier assign_to_keycache operation |
90 | |
91 | (This can never fail as there is never any not written data in the |
92 | new key cache) |
93 | */ |
94 | (void) flush_pagecache_blocks(pagecache, &share->kfile, FLUSH_RELEASE); |
95 | |
96 | /* |
97 | ensure that setting the key cache and changing the multi_pagecache |
98 | is done atomicly |
99 | */ |
100 | mysql_mutex_lock(&share->intern_lock); |
101 | /* |
102 | Tell all threads to use the new key cache |
103 | This should be seen at the lastes for the next call to an maria function. |
104 | */ |
105 | share->pagecache= pagecache; |
106 | |
107 | /* store the key cache in the global hash structure for future opens */ |
108 | if (multi_pagecache_set((uchar*) share->unique_file_name.str, |
109 | (uint)share->unique_file_name.length, |
110 | share->pagecache)) |
111 | error= my_errno; |
112 | mysql_mutex_unlock(&share->intern_lock); |
113 | DBUG_RETURN(error); |
114 | } |
115 | |
116 | |
117 | /* |
118 | Change all MARIA entries that uses one key cache to another key cache |
119 | |
120 | SYNOPSIS |
121 | maria_change_pagecache() |
122 | old_pagecache Old key cache |
123 | new_pagecache New key cache |
124 | |
125 | NOTES |
126 | This is used when we delete one key cache. |
127 | |
128 | To handle the case where some other threads tries to open an MARIA |
129 | table associated with the to-be-deleted key cache while this operation |
130 | is running, we have to call 'multi_pagecache_change()' from this |
131 | function while we have a lock on the MARIA table list structure. |
132 | |
133 | This is safe as long as it's only MARIA that is using this specific |
134 | key cache. |
135 | */ |
136 | |
137 | |
138 | void maria_change_pagecache(PAGECACHE *old_pagecache, |
139 | PAGECACHE *new_pagecache) |
140 | { |
141 | LIST *pos; |
142 | DBUG_ENTER("maria_change_pagecache" ); |
143 | |
144 | /* |
145 | Lock list to ensure that no one can close the table while we manipulate it |
146 | */ |
147 | mysql_mutex_lock(&THR_LOCK_maria); |
148 | for (pos=maria_open_list ; pos ; pos=pos->next) |
149 | { |
150 | MARIA_HA *info= (MARIA_HA*) pos->data; |
151 | MARIA_SHARE *share= info->s; |
152 | if (share->pagecache == old_pagecache) |
153 | maria_assign_to_pagecache(info, (ulonglong) ~0, new_pagecache); |
154 | } |
155 | |
156 | /* |
157 | We have to do the following call while we have the lock on the |
158 | MARIA list structure to ensure that another thread is not trying to |
159 | open a new table that will be associted with the old key cache |
160 | */ |
161 | multi_pagecache_change(old_pagecache, new_pagecache); |
162 | mysql_mutex_unlock(&THR_LOCK_maria); |
163 | DBUG_VOID_RETURN; |
164 | } |
165 | |