~jlukas79/+junk/mysql-server

« back to all changes in this revision

Viewing changes to storage/maria/ma_close.c

manual merge 6.0-main --> 6.0-bka-review

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "maria_def.h"
 
24
 
 
25
int maria_close(register MARIA_HA *info)
 
26
{
 
27
  int error=0,flag;
 
28
  my_bool share_can_be_freed= FALSE;
 
29
  MARIA_SHARE *share= info->s;
 
30
  DBUG_ENTER("maria_close");
 
31
  DBUG_PRINT("enter",("base: 0x%lx  reopen: %u  locks: %u",
 
32
                      (long) info, (uint) share->reopen,
 
33
                      (uint) share->tot_locks));
 
34
 
 
35
  /* Check that we have unlocked key delete-links properly */
 
36
  DBUG_ASSERT(info->used_key_del == 0);
 
37
 
 
38
  pthread_mutex_lock(&THR_LOCK_maria);
 
39
  if (info->lock_type == F_EXTRA_LCK)
 
40
    info->lock_type=F_UNLCK;                    /* HA_EXTRA_NO_USER_CHANGE */
 
41
 
 
42
  if (share->reopen == 1 && share->kfile.file >= 0)
 
43
    _ma_decrement_open_count(info);
 
44
 
 
45
  if (info->lock_type != F_UNLCK)
 
46
  {
 
47
    if (maria_lock_database(info,F_UNLCK))
 
48
      error=my_errno;
 
49
  }
 
50
  pthread_mutex_lock(&share->intern_lock);
 
51
 
 
52
  if (share->options & HA_OPTION_READ_ONLY_DATA)
 
53
  {
 
54
    share->r_locks--;
 
55
    share->tot_locks--;
 
56
  }
 
57
  if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
 
58
  {
 
59
    if (end_io_cache(&info->rec_cache))
 
60
      error=my_errno;
 
61
    info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
 
62
  }
 
63
  flag= !--share->reopen;
 
64
  maria_open_list=list_delete(maria_open_list,&info->open_list);
 
65
 
 
66
  my_free(info->rec_buff, MYF(MY_ALLOW_ZERO_PTR));
 
67
  (*share->end)(info);
 
68
 
 
69
  if (flag)
 
70
  {
 
71
    /* Last close of file; Flush everything */
 
72
    if (share->kfile.file >= 0)
 
73
    {
 
74
      if ((*share->once_end)(share))
 
75
        error= my_errno;
 
76
      if (flush_pagecache_blocks(share->pagecache, &share->kfile,
 
77
                                 (share->temporary ?
 
78
                                  FLUSH_IGNORE_CHANGED :
 
79
                                  FLUSH_RELEASE)))
 
80
        error= my_errno;
 
81
#ifdef HAVE_MMAP
 
82
      if (share->file_map)
 
83
        _ma_unmap_file(info);
 
84
#endif
 
85
      /*
 
86
        If we are crashed, we can safely flush the current state as it will
 
87
        not change the crashed state.
 
88
        We can NOT write the state in other cases as other threads
 
89
        may be using the file at this point
 
90
        IF using --external-locking, which does not apply to Maria.
 
91
      */
 
92
      if (((share->changed && share->base.born_transactional) ||
 
93
           maria_is_crashed(info)))
 
94
      {
 
95
        /*
 
96
          State must be written to file as it was not done at table's
 
97
          unlocking.
 
98
        */
 
99
        if (_ma_state_info_write(share, 1))
 
100
          error= my_errno;
 
101
      }
 
102
      /*
 
103
        File must be synced as it is going out of the maria_open_list and so
 
104
        becoming unknown to future Checkpoints.
 
105
      */
 
106
      if (!share->temporary && my_sync(share->kfile.file, MYF(MY_WME)))
 
107
        error= my_errno;
 
108
      if (my_close(share->kfile.file, MYF(0)))
 
109
        error= my_errno;
 
110
    }
 
111
#ifdef THREAD
 
112
    thr_lock_delete(&share->lock);
 
113
    {
 
114
      int i,keys;
 
115
      keys = share->state.header.keys;
 
116
      (void)(rwlock_destroy(&share->mmap_lock));
 
117
      for(i=0; i<keys; i++) {
 
118
        (void)(rwlock_destroy(&share->keyinfo[i].root_lock));
 
119
      }
 
120
    }
 
121
#endif
 
122
    DBUG_ASSERT(share->now_transactional == share->base.born_transactional);
 
123
    if (share->in_checkpoint == MARIA_CHECKPOINT_LOOKS_AT_ME)
 
124
    {
 
125
      share->kfile.file= -1; /* because Checkpoint does not need to flush */
 
126
      /* we cannot my_free() the share, Checkpoint would see a bad pointer */
 
127
      share->in_checkpoint|= MARIA_CHECKPOINT_SHOULD_FREE_ME;
 
128
    }
 
129
    else
 
130
      share_can_be_freed= TRUE;
 
131
 
 
132
    /* Remember share->history for future opens */
 
133
    share->state_history= _ma_remove_not_visible_states(share->state_history,
 
134
                                                        1, 0);
 
135
    if (share->state_history)
 
136
    {
 
137
      MARIA_STATE_HISTORY_CLOSED *history;
 
138
      /*
 
139
        Here we ignore the unlikely case that we don't have memory to
 
140
        store the case. In the worst case what happens is that any transaction
 
141
        that tries to access this table will get a wrong status information.
 
142
      */
 
143
      if ((history= (MARIA_STATE_HISTORY_CLOSED *)
 
144
           my_malloc(sizeof(*history), MYF(MY_WME))))
 
145
      {
 
146
        history->create_rename_lsn= share->state.create_rename_lsn;
 
147
        history->state_history= share->state_history;
 
148
        if (my_hash_insert(&maria_stored_state, (uchar*) history))
 
149
          my_free(history, MYF(0));
 
150
      }
 
151
    }
 
152
  }
 
153
  pthread_mutex_unlock(&THR_LOCK_maria);
 
154
  pthread_mutex_unlock(&share->intern_lock);
 
155
  if (share_can_be_freed)
 
156
  {
 
157
    (void)(pthread_mutex_destroy(&share->intern_lock));
 
158
    my_free((uchar *)share, MYF(0));
 
159
  }
 
160
  if (info->ftparser_param)
 
161
  {
 
162
    my_free((uchar*)info->ftparser_param, MYF(0));
 
163
    info->ftparser_param= 0;
 
164
  }
 
165
  if (info->dfile.file >= 0)
 
166
  {
 
167
    /*
 
168
      This is outside of mutex so would confuse a concurrent
 
169
      Checkpoint. Fortunately in BLOCK_RECORD we close earlier under mutex.
 
170
    */
 
171
    if (my_close(info->dfile.file, MYF(0)))
 
172
      error= my_errno;
 
173
  }
 
174
 
 
175
  delete_dynamic(&info->pinned_pages);
 
176
  my_free(info, MYF(0));
 
177
 
 
178
  if (error)
 
179
  {
 
180
    DBUG_PRINT("error", ("Got error on close: %d", my_errno));
 
181
    DBUG_RETURN(my_errno= error);
 
182
  }
 
183
  DBUG_RETURN(0);
 
184
} /* maria_close */