LTP GCOV extension - code coverage report
Current view: directory - storage/maria - ma_delete_all.c
Test: maria-unit-test.html
Date: 2009-03-04 Instrumented lines: 53
Code covered: 34.0 % Executed lines: 18

       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                 : /* Remove all rows from a MARIA table */
      17                 : /* This clears the status information and truncates files */
      18                 : 
      19                 : #include "maria_def.h"
      20                 : #include "trnman.h"
      21                 : 
      22                 : /**
      23                 :    @brief deletes all rows from a table
      24                 : 
      25                 :    @param  info             Maria handler
      26                 : 
      27                 :    @note It is important that this function does not rely on the state
      28                 :    information, as it may be called by ma_apply_undo_bulk_insert() on an
      29                 :    inconsistent table left by a crash.
      30                 : 
      31                 :    @return Operation status
      32                 :      @retval 0      ok
      33                 :      @retval 1      error
      34                 : */
      35                 : 
      36                 : int maria_delete_all_rows(MARIA_HA *info)
      37               0 : {
      38               0 :   MARIA_SHARE *share= info->s;
      39                 :   my_bool log_record;
      40                 :   LSN lsn;
      41               0 :   DBUG_ENTER("maria_delete_all_rows");
      42                 : 
      43               0 :   if (share->options & HA_OPTION_READ_ONLY_DATA)
      44                 :   {
      45               0 :     DBUG_RETURN(my_errno=EACCES);
      46                 :   }
      47                 :   /**
      48                 :      @todo LOCK take X-lock on table here.
      49                 :      When we have versioning, if some other thread is looking at this table,
      50                 :      we cannot shrink the file like this.
      51                 :   */
      52               0 :   if (_ma_readinfo(info,F_WRLCK,1))
      53               0 :     DBUG_RETURN(my_errno);
      54               0 :   log_record= share->now_transactional && !share->temporary;
      55               0 :   if (_ma_mark_file_changed(info))
      56               0 :     goto err;
      57                 : 
      58               0 :   if (log_record)
      59                 :   {
      60                 :     /*
      61                 :       This record will be used by Recovery to finish the deletion if it
      62                 :       crashed. We force it to have a complete history in the log.
      63                 :     */
      64                 :     LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 1];
      65                 :     uchar log_data[FILEID_STORE_SIZE];
      66               0 :     log_array[TRANSLOG_INTERNAL_PARTS + 0].str=    log_data;
      67               0 :     log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
      68               0 :     if (unlikely(translog_write_record(&lsn, LOGREC_REDO_DELETE_ALL,
      69                 :                                        info->trn, info, 0,
      70                 :                                        sizeof(log_array)/sizeof(log_array[0]),
      71                 :                                        log_array, log_data, NULL) ||
      72                 :                  translog_flush(lsn)))
      73                 :       goto err;
      74                 :     /*
      75                 :       If we fail in this function after this point, log and table will be
      76                 :       inconsistent.
      77                 :     */
      78                 :   }
      79                 :   else
      80                 :   {
      81                 :     /* Other branch called function below when writing log record, in hook */
      82               0 :     _ma_reset_status(info);
      83                 :   }
      84                 :   /* Remove old history as the table is now empty for everyone */
      85               0 :   _ma_reset_state(info);
      86                 : 
      87                 :   /*
      88                 :     If we are using delayed keys or if the user has done changes to the tables
      89                 :     since it was locked then there may be key blocks in the page cache. Or
      90                 :     there may be data blocks there. We need to throw them away or they may
      91                 :     re-enter the emptied table or another table later.
      92                 :   */
      93                 : 
      94                 : #ifdef HAVE_MMAP
      95               0 :   if (share->file_map)
      96               0 :     _ma_unmap_file(info);
      97                 : #endif
      98                 : 
      99               0 :   if (_ma_flush_table_files(info, MARIA_FLUSH_DATA|MARIA_FLUSH_INDEX,
     100                 :                             FLUSH_IGNORE_CHANGED, FLUSH_IGNORE_CHANGED) ||
     101                 :       my_chsize(info->dfile.file, 0, 0, MYF(MY_WME)) ||
     102                 :       my_chsize(share->kfile.file, share->base.keystart, 0, MYF(MY_WME)))
     103                 :     goto err;
     104                 : 
     105               0 :   if (_ma_initialize_data_file(share, info->dfile.file))
     106               0 :     goto err;
     107                 : 
     108               0 :   if (log_record)
     109                 :   {
     110                 :     /*
     111                 :       Because LOGREC_REDO_DELETE_ALL does not operate on pages, it has the
     112                 :       following problem:
     113                 :       delete_all; inserts (redo_insert); all pages get flushed; checkpoint:
     114                 :       the dirty pages list will be empty. In recovery, delete_all is executed,
     115                 :       but redo_insert are skipped (dirty pages list is empty).
     116                 :       To avoid this, we need to set skip_redo_lsn now, and thus need to sync
     117                 :       files.
     118                 :       Also fixes the problem of:
     119                 :       bulk insert; insert; delete_all; crash:
     120                 :       "bulk insert" is skipped (no REDOs), so if "insert" would not be skipped
     121                 :       (if we didn't update skip_redo_lsn below) then "insert" would be tried
     122                 :       and fail, saying that it sees that the first page has to be created
     123                 :       though the inserted row has rownr>0.
     124                 :     */
     125                 :     my_bool error= _ma_state_info_write(share,
     126                 :                                         MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET |
     127                 :                                         MA_STATE_INFO_WRITE_LOCK) ||
     128                 :       _ma_update_state_lsns(share, lsn, trnman_get_min_trid(), FALSE, FALSE) ||
     129               0 :       _ma_sync_table_files(info);
     130               0 :     info->trn->rec_lsn= LSN_IMPOSSIBLE;
     131               0 :     if (error)
     132               0 :       goto err;
     133                 :   }
     134                 : 
     135               0 :   VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
     136                 : #ifdef HAVE_MMAP
     137                 :   /* Map again */
     138               0 :   if (share->file_map)
     139               0 :     _ma_dynmap_file(info, (my_off_t) 0);
     140                 : #endif
     141                 :   allow_break();                        /* Allow SIGHUP & SIGINT */
     142               0 :   DBUG_RETURN(0);
     143                 : 
     144               0 : err:
     145                 :   {
     146               0 :     int save_errno=my_errno;
     147               0 :     VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
     148               0 :     info->update|=HA_STATE_WRITTEN;  /* Buffer changed */
     149                 :     allow_break();                      /* Allow SIGHUP & SIGINT */
     150               0 :     DBUG_RETURN(my_errno=save_errno);
     151                 :   }
     152                 : } /* maria_delete_all_rows */
     153                 : 
     154                 : 
     155                 : /*
     156                 :   Reset status information
     157                 : 
     158                 :   SYNOPSIS
     159                 :     _ma_reset_status()
     160                 :     maria       Maria handler
     161                 : 
     162                 :   DESCRIPTION
     163                 :     Resets data and index file information as if the file would be empty
     164                 :     Files are not touched.
     165                 : */
     166                 : 
     167                 : void _ma_reset_status(MARIA_HA *info)
     168              45 : {
     169              45 :   MARIA_SHARE *share= info->s;
     170              45 :   MARIA_STATE_INFO *state= &share->state;
     171                 :   uint i;
     172              45 :   DBUG_ENTER("_ma_reset_status");
     173                 : 
     174              45 :   state->split= 0;
     175              45 :   state->state.records= state->state.del= 0;
     176              45 :   state->changed=  0;                            /* File is optimized */
     177              45 :   state->dellink= HA_OFFSET_ERROR;
     178              45 :   state->sortkey=  (ushort) ~0;
     179              45 :   state->state.key_file_length= share->base.keystart;
     180              45 :   state->state.data_file_length= 0;
     181              45 :   state->state.empty= state->state.key_empty= 0;
     182              45 :   state->state.checksum= 0;
     183                 : 
     184              45 :   *info->state= state->state;
     185                 : 
     186                 :   /* Drop the delete key chain. */
     187              45 :   state->key_del= HA_OFFSET_ERROR;
     188                 :   /* Clear all keys */
     189             165 :   for (i=0 ; i < share->base.keys ; i++)
     190             120 :     state->key_root[i]= HA_OFFSET_ERROR;
     191              45 :   DBUG_VOID_RETURN;
     192                 : }

Generated by: LTP GCOV extension version 1.4