| 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 | |