LTP GCOV extension - code coverage report
Current view: directory - storage/maria - ma_close.c
Test: maria-unit-test.html
Date: 2009-03-04 Instrumented lines: 82
Code covered: 78.0 % Executed lines: 64

       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            3146 : {
      27            3146 :   int error=0,flag;
      28            3146 :   my_bool share_can_be_freed= FALSE;
      29            3146 :   MARIA_SHARE *share= info->s;
      30            3146 :   DBUG_ENTER("maria_close");
      31            3146 :   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            3146 :   DBUG_ASSERT(info->key_del_used == 0);
      37                 : 
      38            3146 :   pthread_mutex_lock(&THR_LOCK_maria);
      39            3146 :   if (info->lock_type == F_EXTRA_LCK)
      40              30 :     info->lock_type=F_UNLCK;                 /* HA_EXTRA_NO_USER_CHANGE */
      41                 : 
      42            3146 :   if (share->reopen == 1 && share->kfile.file >= 0)
      43            3146 :     _ma_decrement_open_count(info);
      44                 : 
      45            3146 :   if (info->lock_type != F_UNLCK)
      46                 :   {
      47            1235 :     if (maria_lock_database(info,F_UNLCK))
      48               0 :       error=my_errno;
      49                 :   }
      50            3146 :   pthread_mutex_lock(&share->close_lock);
      51            3146 :   pthread_mutex_lock(&share->intern_lock);
      52                 : 
      53            3146 :   if (share->options & HA_OPTION_READ_ONLY_DATA)
      54                 :   {
      55            1506 :     share->r_locks--;
      56            1506 :     share->tot_locks--;
      57                 :   }
      58            3146 :   if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
      59                 :   {
      60               2 :     if (end_io_cache(&info->rec_cache))
      61               0 :       error=my_errno;
      62               2 :     info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
      63                 :   }
      64            3146 :   flag= !--share->reopen;
      65            3146 :   maria_open_list=list_delete(maria_open_list,&info->open_list);
      66                 : 
      67            3146 :   my_free(info->rec_buff, MYF(MY_ALLOW_ZERO_PTR));
      68            3146 :   (*share->end)(info);
      69                 : 
      70            3146 :   if (flag)
      71                 :   {
      72                 :     /* Last close of file; Flush everything */
      73                 : 
      74                 :     /* Check that we don't have any dangling pointers from the transaction */
      75            3146 :     DBUG_ASSERT(share->in_trans == 0);
      76                 : 
      77            3146 :     if (share->kfile.file >= 0)
      78                 :     {
      79            3146 :       if ((*share->once_end)(share))
      80               0 :         error= my_errno;
      81            3146 :       if (flush_pagecache_blocks(share->pagecache, &share->kfile,
      82                 :                                  (share->temporary ?
      83                 :                                   FLUSH_IGNORE_CHANGED :
      84                 :                                   FLUSH_RELEASE)))
      85               0 :         error= my_errno;
      86                 : #ifdef HAVE_MMAP
      87            3146 :       if (share->file_map)
      88               0 :         _ma_unmap_file(info);
      89                 : #endif
      90                 :       /*
      91                 :         If we are crashed, we can safely flush the current state as it will
      92                 :         not change the crashed state.
      93                 :         We can NOT write the state in other cases as other threads
      94                 :         may be using the file at this point
      95                 :         IF using --external-locking, which does not apply to Maria.
      96                 :       */
      97            3146 :       if (((share->changed && share->base.born_transactional) ||
      98                 :            maria_is_crashed(info)))
      99                 :       {
     100                 :         /*
     101                 :           State must be written to file as it was not done at table's
     102                 :           unlocking.
     103                 :         */
     104             876 :         if (_ma_state_info_write(share, MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET))
     105               0 :           error= my_errno;
     106                 :       }
     107                 :       /*
     108                 :         File must be synced as it is going out of the maria_open_list and so
     109                 :         becoming unknown to future Checkpoints.
     110                 :       */
     111            3146 :       if (share->now_transactional && my_sync(share->kfile.file, MYF(MY_WME)))
     112               0 :         error= my_errno;
     113            3146 :       if (my_close(share->kfile.file, MYF(0)))
     114               0 :         error= my_errno;
     115                 :     }
     116                 : #ifdef THREAD
     117            3146 :     thr_lock_delete(&share->lock);
     118            3146 :     (void) pthread_mutex_destroy(&share->key_del_lock);
     119                 :     {
     120                 :       int i,keys;
     121            3146 :       keys = share->state.header.keys;
     122            3146 :       VOID(rwlock_destroy(&share->mmap_lock));
     123           11182 :       for(i=0; i<keys; i++) {
     124            8036 :         VOID(rwlock_destroy(&share->keyinfo[i].root_lock));
     125                 :       }
     126                 :     }
     127                 : #endif
     128            3146 :     DBUG_ASSERT(share->now_transactional == share->base.born_transactional);
     129                 :     /*
     130                 :       We assign -1 because checkpoint does not need to flush (in case we
     131                 :       have concurrent checkpoint if no then we do not need it here also)
     132                 :     */
     133            3146 :     share->kfile.file= -1;
     134                 : 
     135                 :     /*
     136                 :       Remember share->history for future opens
     137                 : 
     138                 :       We have to unlock share->intern_lock then lock it after
     139                 :       LOCK_trn_list (trnman_lock()) to avoid dead locks.
     140                 :     */
     141            3146 :     pthread_mutex_unlock(&share->intern_lock);
     142            3146 :     _ma_remove_not_visible_states_with_lock(share, TRUE);
     143            3146 :     pthread_mutex_lock(&share->intern_lock);
     144                 : 
     145            3146 :     if (share->in_checkpoint & MARIA_CHECKPOINT_LOOKS_AT_ME)
     146                 :     {
     147                 :       /* we cannot my_free() the share, Checkpoint would see a bad pointer */
     148               0 :       share->in_checkpoint|= MARIA_CHECKPOINT_SHOULD_FREE_ME;
     149                 :     }
     150                 :     else
     151            3146 :       share_can_be_freed= TRUE;
     152                 : 
     153            3146 :     if (share->state_history)
     154                 :     {
     155                 :       MARIA_STATE_HISTORY_CLOSED *history;
     156                 :       /*
     157                 :         Here we ignore the unlikely case that we don't have memory to
     158                 :         store the state. In the worst case what happens is that any transaction
     159                 :         that tries to access this table will get a wrong status information.
     160                 :       */
     161               0 :       if ((history= (MARIA_STATE_HISTORY_CLOSED *)
     162                 :            my_malloc(sizeof(*history), MYF(MY_WME))))
     163                 :       {
     164               0 :         history->create_rename_lsn= share->state.create_rename_lsn;
     165               0 :         history->state_history= share->state_history;
     166               0 :         if (my_hash_insert(&maria_stored_state, (uchar*) history))
     167               0 :           my_free(history, MYF(0));
     168                 :       }
     169                 :       /* Marker for concurrent checkpoint */
     170               0 :       share->state_history= 0;
     171                 :     }
     172                 :   }
     173            3146 :   pthread_mutex_unlock(&THR_LOCK_maria);
     174            3146 :   pthread_mutex_unlock(&share->intern_lock);
     175            3146 :   pthread_mutex_unlock(&share->close_lock);
     176            3146 :   if (share_can_be_freed)
     177                 :   {
     178            3146 :     (void) pthread_mutex_destroy(&share->intern_lock);
     179            3146 :     (void) pthread_mutex_destroy(&share->close_lock);
     180            3146 :     my_free((uchar *)share, MYF(0));
     181                 :     /*
     182                 :       If share cannot be freed, it's because checkpoint has previously
     183                 :       recorded to include this share in the checkpoint and so is soon going to
     184                 :       look at some of its content (share->in_checkpoint/id/last_version).
     185                 :     */
     186                 :   }
     187            3146 :   my_free(info->ftparser_param, MYF(MY_ALLOW_ZERO_PTR));
     188            3146 :   if (info->dfile.file >= 0)
     189                 :   {
     190                 :     /*
     191                 :       This is outside of mutex so would confuse a concurrent
     192                 :       Checkpoint. Fortunately in BLOCK_RECORD we close earlier under mutex.
     193                 :     */
     194             454 :     if (my_close(info->dfile.file, MYF(0)))
     195               0 :       error= my_errno;
     196                 :   }
     197                 : 
     198            3146 :   delete_dynamic(&info->pinned_pages);
     199            3146 :   my_free(info, MYF(0));
     200                 : 
     201            3146 :   if (error)
     202                 :   {
     203               0 :     DBUG_PRINT("error", ("Got error on close: %d", my_errno));
     204               0 :     DBUG_RETURN(my_errno= error);
     205                 :   }
     206            3146 :   DBUG_RETURN(0);
     207                 : } /* maria_close */

Generated by: LTP GCOV extension version 1.4