/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/* Remove all rows from a MARIA table */
/* This clears the status information and truncates files */

#include "maria_def.h"

int maria_delete_all_rows(MARIA_HA *info)
{
  uint i;
  MARIA_SHARE *share=info->s;
  MARIA_STATE_INFO *state=&share->state;
  DBUG_ENTER("maria_delete_all_rows");

  if (share->options & HA_OPTION_READ_ONLY_DATA)
  {
    DBUG_RETURN(my_errno=EACCES);
  }
  /* LOCK TODO take X-lock on table here */
  if (_ma_readinfo(info,F_WRLCK,1))
    DBUG_RETURN(my_errno);
  if (_ma_mark_file_changed(info))
    goto err;

  info->state->records=info->state->del=state->split=0;
  state->changed= 0;                            /* File is optimized */
  state->dellink = HA_OFFSET_ERROR;
  state->sortkey=  (ushort) ~0;
  info->state->key_file_length=share->base.keystart;
  info->state->data_file_length=0;
  info->state->empty=info->state->key_empty=0;
  info->state->checksum=0;

  state->key_del= HA_OFFSET_ERROR;
  for (i=0 ; i < share->base.keys ; i++)
    state->key_root[i]= HA_OFFSET_ERROR;

  /*
    If we are using delayed keys or if the user has done changes to the tables
    since it was locked then there may be key blocks in the key cache
  */
  flush_pagecache_blocks(share->pagecache, &share->kfile,
                         FLUSH_IGNORE_CHANGED);
  /*
    RECOVERY TODO Log the two chsize and header modifications and force the
    log. So that if crash between the two chsize, we finish the work at
    Recovery. For this scenario:
    "TRUNCATE TABLE t1; DROP TABLE t1; RENAME TABLE t2 to t1; crash;"
    Recovery mustn't truncate the new t1, so the log records of TRUNCATE
    should be applied only if t1 exists and its ZeroDirtyPagesLSN is smaller
    than the records'. See more comments below.
  */
  if (my_chsize(info->dfile.file, 0, 0, MYF(MY_WME)) ||
      my_chsize(share->kfile.file, share->base.keystart, 0, MYF(MY_WME))  )
    goto err;

  if (_ma_initialize_data_file(info->dfile.file, info->s))
    goto err;

  /*
    RECOVERY TODO Consider updating ZeroDirtyPagesLSN here. It is
    not a necessity (it is one only in RENAME commands) but an optional
    optimization which will allow some REDO skipping at Recovery.
  */
  VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
#ifdef HAVE_MMAP
  /* Resize mmaped area */
  rw_wrlock(&info->s->mmap_lock);
  _ma_remap_file(info, (my_off_t)0);
  rw_unlock(&info->s->mmap_lock);
#endif
  /*
    RECOVERY TODO Until we have the TRUNCATE log record and take it into
    account for log-low-water-mark calculation and use it in Recovery, we need
    to sync.
  */
  if (_ma_sync_table_files(info))
    goto err;
  allow_break();			/* Allow SIGHUP & SIGINT */
  DBUG_RETURN(0);

err:
  {
    int save_errno=my_errno;
    /* RECOVERY TODO log the header modifications */
    VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
    info->update|=HA_STATE_WRITTEN;	/* Buffer changed */
    /* RECOVERY TODO until we log above we have to sync */
    if (_ma_sync_table_files(info) && !save_errno)
      save_errno= my_errno;
    allow_break();			/* Allow SIGHUP & SIGINT */
    DBUG_RETURN(my_errno=save_errno);
  }
} /* maria_delete */
