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-1335  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 "ftdefs.h"
24 
mi_close(register MI_INFO * info)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   ftparser_call_deinitializer(info);
64 
65   if (flag)
66   {
67     DBUG_EXECUTE_IF("crash_before_flush_keys",
68                     if (share->kfile >= 0) DBUG_SUICIDE(););
69     if (share->kfile >= 0 &&
70 	flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
71                          share->deleting ? FLUSH_IGNORE_CHANGED : FLUSH_RELEASE))
72       error=my_errno;
73     if (share->kfile >= 0)
74     {
75       /*
76         If we are crashed, we can safely flush the current state as it will
77         not change the crashed state.
78         We can NOT write the state in other cases as other threads
79         may be using the file at this point IF using --external-locking.
80 
81         Also, write the state if a temporary table is not being dropped
82         (the server might want to reopen it, and mi_lock_database() only
83         writes the state for non-temp ones)
84       */
85       if (share->mode != O_RDONLY &&
86           (mi_is_crashed(info) || (share->temporary && !share->deleting)))
87 	mi_state_info_write(share->kfile, &share->state, 1);
88       /* Decrement open count must be last I/O on this file. */
89       _mi_decrement_open_count(info);
90       if (mysql_file_close(share->kfile, MYF(0)))
91         error = my_errno;
92     }
93 #ifdef HAVE_MMAP
94     if (share->file_map)
95     {
96       if (share->options & HA_OPTION_COMPRESS_RECORD)
97         _mi_unmap_file(info);
98       else
99         mi_munmap_file(info);
100     }
101 #endif
102     if (share->decode_trees)
103     {
104       my_free(share->decode_trees);
105       my_free(share->decode_tables);
106     }
107     thr_lock_delete(&share->lock);
108     mysql_mutex_destroy(&share->intern_lock);
109     {
110       int i,keys;
111       keys = share->state.header.keys;
112       mysql_rwlock_destroy(&share->mmap_lock);
113       for(i=0; i<keys; i++) {
114         mysql_rwlock_destroy(&share->key_root_lock[i]);
115       }
116     }
117     my_free(info->s);
118   }
119   if (info->open_list.data)
120     mysql_mutex_unlock(&THR_LOCK_myisam);
121   if (info->ftparser_param)
122   {
123     my_free(info->ftparser_param);
124     info->ftparser_param= 0;
125   }
126   if (info->dfile >= 0 && mysql_file_close(info->dfile, MYF(0)))
127     error = my_errno;
128 
129   myisam_log_command(MI_LOG_CLOSE,info,NULL,0,error);
130   my_free(info);
131 
132   if (error)
133   {
134     DBUG_RETURN(my_errno=error);
135   }
136   DBUG_RETURN(0);
137 } /* mi_close */
138