| 1 | /* Copyright (c) 2000, 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 | /* close a isam-database */ |
| 17 | /* |
| 18 | TODO: |
| 19 | We need to have a separate mutex on the closed file to allow other threads |
| 20 | to open other files during the time we flush the cache and close this file |
| 21 | */ |
| 22 | |
| 23 | #include "myisamdef.h" |
| 24 | |
| 25 | int mi_close(register MI_INFO *info) |
| 26 | { |
| 27 | int error=0,flag; |
| 28 | MYISAM_SHARE *share=info->s; |
| 29 | DBUG_ENTER("mi_close" ); |
| 30 | DBUG_PRINT("enter" ,("base: %p reopen: %u locks: %u" , |
| 31 | info, (uint) share->reopen, |
| 32 | (uint) share->tot_locks)); |
| 33 | |
| 34 | if (info->open_list.data) |
| 35 | mysql_mutex_lock(&THR_LOCK_myisam); |
| 36 | if (info->lock_type == F_EXTRA_LCK) |
| 37 | info->lock_type=F_UNLCK; /* HA_EXTRA_NO_USER_CHANGE */ |
| 38 | |
| 39 | if (info->lock_type != F_UNLCK) |
| 40 | { |
| 41 | if (mi_lock_database(info,F_UNLCK)) |
| 42 | error=my_errno; |
| 43 | } |
| 44 | mysql_mutex_lock(&share->intern_lock); |
| 45 | |
| 46 | if (share->options & HA_OPTION_READ_ONLY_DATA) |
| 47 | { |
| 48 | share->r_locks--; |
| 49 | share->tot_locks--; |
| 50 | } |
| 51 | if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)) |
| 52 | { |
| 53 | if (end_io_cache(&info->rec_cache)) |
| 54 | error=my_errno; |
| 55 | info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED); |
| 56 | } |
| 57 | flag= !--share->reopen; |
| 58 | if (info->open_list.data) |
| 59 | myisam_open_list= list_delete(myisam_open_list, &info->open_list); |
| 60 | mysql_mutex_unlock(&share->intern_lock); |
| 61 | |
| 62 | my_free(mi_get_rec_buff_ptr(info, info->rec_buff)); |
| 63 | if (flag) |
| 64 | { |
| 65 | DBUG_EXECUTE_IF("crash_before_flush_keys" , |
| 66 | if (share->kfile >= 0) DBUG_SUICIDE();); |
| 67 | if (share->kfile >= 0 && |
| 68 | flush_key_blocks(share->key_cache, share->kfile, |
| 69 | &share->dirty_part_map, |
| 70 | ((share->temporary || share->deleting) ? |
| 71 | FLUSH_IGNORE_CHANGED : |
| 72 | FLUSH_RELEASE))) |
| 73 | error=my_errno; |
| 74 | if (share->kfile >= 0) |
| 75 | { |
| 76 | /* |
| 77 | If we are crashed, we can safely flush the current state as it will |
| 78 | not change the crashed state. |
| 79 | We can NOT write the state in other cases as other threads |
| 80 | may be using the file at this point |
| 81 | IF using --external-locking. |
| 82 | */ |
| 83 | if (share->mode != O_RDONLY && mi_is_crashed(info)) |
| 84 | mi_state_info_write(share->kfile, &share->state, 1); |
| 85 | /* Decrement open count must be last I/O on this file. */ |
| 86 | _mi_decrement_open_count(info); |
| 87 | if (mysql_file_close(share->kfile, MYF(0))) |
| 88 | error = my_errno; |
| 89 | } |
| 90 | #ifdef HAVE_MMAP |
| 91 | if (share->file_map) |
| 92 | { |
| 93 | if (share->options & HA_OPTION_COMPRESS_RECORD) |
| 94 | _mi_unmap_file(info); |
| 95 | else |
| 96 | mi_munmap_file(info); |
| 97 | } |
| 98 | #endif |
| 99 | if (share->decode_trees) |
| 100 | { |
| 101 | my_free(share->decode_trees); |
| 102 | my_free(share->decode_tables); |
| 103 | } |
| 104 | thr_lock_delete(&share->lock); |
| 105 | mysql_mutex_destroy(&share->intern_lock); |
| 106 | { |
| 107 | int i,keys; |
| 108 | keys = share->state.header.keys; |
| 109 | mysql_rwlock_destroy(&share->mmap_lock); |
| 110 | for(i=0; i<keys; i++) { |
| 111 | mysql_rwlock_destroy(&share->key_root_lock[i]); |
| 112 | } |
| 113 | } |
| 114 | my_free(info->s); |
| 115 | } |
| 116 | if (info->open_list.data) |
| 117 | mysql_mutex_unlock(&THR_LOCK_myisam); |
| 118 | if (info->ftparser_param) |
| 119 | { |
| 120 | my_free(info->ftparser_param); |
| 121 | info->ftparser_param= 0; |
| 122 | } |
| 123 | if (info->dfile >= 0 && mysql_file_close(info->dfile, MYF(0))) |
| 124 | error = my_errno; |
| 125 | |
| 126 | myisam_log_command(MI_LOG_CLOSE,info,NULL,0,error); |
| 127 | my_free(info); |
| 128 | |
| 129 | if (error) |
| 130 | { |
| 131 | DBUG_RETURN(my_errno=error); |
| 132 | } |
| 133 | DBUG_RETURN(0); |
| 134 | } /* mi_close */ |
| 135 | |