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