ma_extra.c 21.5 KB
Newer Older
1 2 3 4
/* 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
5
   the Free Software Foundation; version 2 of the License.
6 7 8 9 10 11 12 13 14 15 16 17 18 19

   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 */

#include "maria_def.h"
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
unknown's avatar
unknown committed
20
#include "ma_blockrec.h"
21

unknown's avatar
unknown committed
22 23
static void maria_extra_keyflag(MARIA_HA *info,
                                enum ha_extra_function function);
24

25 26
/**
   @brief Set options and buffers to optimize table handling
27

28 29 30 31 32 33 34
   @param  name             table's name
   @param  info             open table
   @param  function         operation
   @param  extra_arg        Pointer to extra argument (normally pointer to
                            ulong); used when function is one of:
                            HA_EXTRA_WRITE_CACHE
                            HA_EXTRA_CACHE
35

36 37 38
   @return Operation status
     @retval 0      ok
     @retval !=0    error
39 40
*/

unknown's avatar
unknown committed
41 42
int maria_extra(MARIA_HA *info, enum ha_extra_function function,
                void *extra_arg)
43
{
44
  int error= 0;
45
  ulong cache_size;
46 47
  MARIA_SHARE *share= info->s;
  my_bool block_records= share->data_file_type == BLOCK_RECORD;
48 49 50 51 52
  DBUG_ENTER("maria_extra");
  DBUG_PRINT("enter",("function: %d",(int) function));

  switch (function) {
  case HA_EXTRA_RESET_STATE:		/* Reset state (don't free buffers) */
53
    info->lastinx= ~0;			/* Detect index changes */
unknown's avatar
unknown committed
54
    info->last_search_keypage= info->cur_row.lastpos= HA_OFFSET_ERROR;
55
    info->page_changed= 1;
56 57 58 59 60 61 62 63 64 65 66 67
					/* Next/prev gives first/last */
    if (info->opt_flag & READ_CACHE_USED)
    {
      reinit_io_cache(&info->rec_cache,READ_CACHE,0,
		      (pbool) (info->lock_type != F_UNLCK),
		      (pbool) test(info->update & HA_STATE_ROW_CHANGED)
		      );
    }
    info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND |
		   HA_STATE_PREV_FOUND);
    break;
  case HA_EXTRA_CACHE:
unknown's avatar
unknown committed
68 69 70
    if (block_records)
      break;                                    /* Not supported */

71 72 73
    if (info->lock_type == F_UNLCK &&
	(share->options & HA_OPTION_PACK_RECORD))
    {
74 75
      error= 1;			/* Not possibly if not locked */
      my_errno= EACCES;
76 77 78 79 80 81 82 83 84 85 86
      break;
    }
    if (info->s->file_map) /* Don't use cache if mmap */
      break;
#if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
    if ((share->options & HA_OPTION_COMPRESS_RECORD))
    {
      pthread_mutex_lock(&share->intern_lock);
      if (_ma_memmap_file(info))
      {
	/* We don't nead MADV_SEQUENTIAL if small file */
87
	madvise((char*) share->file_map, share->state.state.data_file_length,
88 89 90 91 92 93 94 95 96 97 98
		share->state.state.data_file_length <= RECORD_CACHE_SIZE*16 ?
		MADV_RANDOM : MADV_SEQUENTIAL);
	pthread_mutex_unlock(&share->intern_lock);
	break;
      }
      pthread_mutex_unlock(&share->intern_lock);
    }
#endif
    if (info->opt_flag & WRITE_CACHE_USED)
    {
      info->opt_flag&= ~WRITE_CACHE_USED;
99
      if ((error= end_io_cache(&info->rec_cache)))
100 101 102 103 104 105 106
	break;
    }
    if (!(info->opt_flag &
	  (READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED)))
    {
      cache_size= (extra_arg ? *(ulong*) extra_arg :
		   my_default_record_cache_size);
unknown's avatar
unknown committed
107
      if (!(init_io_cache(&info->rec_cache, info->dfile.file,
108
			 (uint) min(share->state.state.data_file_length+1,
109 110 111 112
				    cache_size),
			  READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK),
			  MYF(share->write_flag & MY_WAIT_IF_FULL))))
      {
113 114
	info->opt_flag|= READ_CACHE_USED;
	info->update&=   ~HA_STATE_ROW_CHANGED;
115
      }
116
      if (share->non_transactional_concurrent_insert)
117
	info->rec_cache.end_of_file= info->state->data_file_length;
118 119 120 121 122
    }
    break;
  case HA_EXTRA_REINIT_CACHE:
    if (info->opt_flag & READ_CACHE_USED)
    {
unknown's avatar
unknown committed
123
      reinit_io_cache(&info->rec_cache, READ_CACHE, info->cur_row.nextpos,
124 125 126
		      (pbool) (info->lock_type != F_UNLCK),
		      (pbool) test(info->update & HA_STATE_ROW_CHANGED));
      info->update&= ~HA_STATE_ROW_CHANGED;
127
      if (share->non_transactional_concurrent_insert)
128
	info->rec_cache.end_of_file= info->state->data_file_length;
129 130 131 132 133
    }
    break;
  case HA_EXTRA_WRITE_CACHE:
    if (info->lock_type == F_UNLCK)
    {
134
      error= 1;                        	/* Not possibly if not locked */
135 136
      break;
    }
unknown's avatar
unknown committed
137 138
    if (block_records)
      break;                            /* Not supported */
139 140 141 142 143 144

    cache_size= (extra_arg ? *(ulong*) extra_arg :
		 my_default_record_cache_size);
    if (!(info->opt_flag &
	  (READ_CACHE_USED | WRITE_CACHE_USED | OPT_NO_ROWS)) &&
	!share->state.header.uniques)
unknown's avatar
unknown committed
145
      if (!(init_io_cache(&info->rec_cache, info->dfile.file, cache_size,
146
                          WRITE_CACHE, info->state->data_file_length,
147 148 149
			  (pbool) (info->lock_type != F_UNLCK),
			  MYF(share->write_flag & MY_WAIT_IF_FULL))))
      {
150 151 152 153
	info->opt_flag|= WRITE_CACHE_USED;
	info->update&=   ~(HA_STATE_ROW_CHANGED |
                           HA_STATE_WRITE_AT_END |
                           HA_STATE_EXTEND_BLOCK);
154 155 156 157 158 159 160 161 162 163
      }
    break;
  case HA_EXTRA_PREPARE_FOR_UPDATE:
    if (info->s->data_file_type != DYNAMIC_RECORD)
      break;
    /* Remove read/write cache if dynamic rows */
  case HA_EXTRA_NO_CACHE:
    if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
    {
      info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
164
      error= end_io_cache(&info->rec_cache);
165 166 167 168
      /* Sergei will insert full text index caching here */
    }
#if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
    if (info->opt_flag & MEMMAP_USED)
169 170
      madvise((char*) share->file_map, share->state.state.data_file_length,
              MADV_RANDOM);
171 172 173 174 175
#endif
    break;
  case HA_EXTRA_FLUSH_CACHE:
    if (info->opt_flag & WRITE_CACHE_USED)
    {
176
      if ((error= flush_io_cache(&info->rec_cache)))
177
      {
Michael Widenius's avatar
Michael Widenius committed
178 179
        /* Fatal error found */
        _ma_set_fatal_error(share, HA_ERR_CRASHED);
180 181 182 183 184 185 186 187 188 189 190
      }
    }
    break;
  case HA_EXTRA_NO_READCHECK:
    info->opt_flag&= ~READ_CHECK_USED;		/* No readcheck */
    break;
  case HA_EXTRA_READCHECK:
    info->opt_flag|= READ_CHECK_USED;
    break;
  case HA_EXTRA_KEYREAD:			/* Read only keys to record */
  case HA_EXTRA_REMEMBER_POS:
191
    info->opt_flag|= REMEMBER_OLD_POS;
Michael Widenius's avatar
Michael Widenius committed
192 193
    bmove(info->last_key.data + share->base.max_key_length*2,
	  info->last_key.data,
194
          info->last_key.data_length + info->last_key.ref_length);
195 196
    info->save_update=	info->update;
    info->save_lastinx= info->lastinx;
unknown's avatar
unknown committed
197
    info->save_lastpos= info->cur_row.lastpos;
198 199
    info->save_lastkey_data_length= info->last_key.data_length;
    info->save_lastkey_ref_length= info->last_key.ref_length;
200 201 202 203
    if (function == HA_EXTRA_REMEMBER_POS)
      break;
    /* fall through */
  case HA_EXTRA_KEYREAD_CHANGE_POS:
204
    info->opt_flag|= KEY_READ_USED;
205 206 207 208 209 210
    info->read_record= _ma_read_key_record;
    break;
  case HA_EXTRA_NO_KEYREAD:
  case HA_EXTRA_RESTORE_POS:
    if (info->opt_flag & REMEMBER_OLD_POS)
    {
Michael Widenius's avatar
Michael Widenius committed
211 212
      bmove(info->last_key.data,
	    info->last_key.data + share->base.max_key_length*2,
213
	    info->save_lastkey_data_length + info->save_lastkey_ref_length);
214 215
      info->update=	info->save_update | HA_STATE_WRITTEN;
      info->lastinx=	info->save_lastinx;
216
      info->cur_row.lastpos= info->save_lastpos;
217 218 219
      info->last_key.data_length= info->save_lastkey_data_length;
      info->last_key.ref_length= info->save_lastkey_ref_length;
      info->last_key.flag= 0;
220 221 222 223 224 225 226 227
    }
    info->read_record=	share->read_record;
    info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
    break;
  case HA_EXTRA_NO_USER_CHANGE: /* Database is somehow locked agains changes */
    info->lock_type= F_EXTRA_LCK; /* Simulate as locked */
    break;
  case HA_EXTRA_WAIT_LOCK:
228
    info->lock_wait= 0;
229 230
    break;
  case HA_EXTRA_NO_WAIT_LOCK:
231
    info->lock_wait= MY_SHORT_WAIT;
232 233
    break;
  case HA_EXTRA_NO_KEYS:
unknown's avatar
unknown committed
234 235
    /* we're going to modify pieces of the state, stall Checkpoint */
    pthread_mutex_lock(&share->intern_lock);
236 237
    if (info->lock_type == F_UNLCK)
    {
unknown's avatar
unknown committed
238
      pthread_mutex_unlock(&share->intern_lock);
239
      error= 1;					/* Not possibly if not lock */
240 241 242 243
      break;
    }
    if (maria_is_any_key_active(share->state.key_map))
    {
244
      MARIA_KEYDEF *key= share->keyinfo;
245
      uint i;
246
      for (i =0 ; i < share->base.keys ; i++,key++)
247 248 249 250 251 252 253 254 255 256
      {
        if (!(key->flag & HA_NOSAME) && info->s->base.auto_key != i+1)
        {
          maria_clear_key_active(share->state.key_map, i);
          info->update|= HA_STATE_CHANGED;
        }
      }

      if (!share->changed)
      {
257
	share->changed= 1;			/* Update on close */
258
	share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED;
259 260
	if (!share->global_changed)
	{
261
	  share->global_changed= 1;
262 263 264
	  share->state.open_count++;
	}
      }
265 266
      if (!share->now_transactional)
        share->state.state= *info->state;
unknown's avatar
unknown committed
267 268 269 270 271 272 273
      /*
        That state write to disk must be done, even for transactional tables;
        indeed the table's share is going to be lost (there was a
        HA_EXTRA_FORCE_REOPEN before, which set share->last_version to
        0), and so the only way it leaves information (share->state.key_map)
        for the posterity is by writing it to disk.
      */
unknown's avatar
unknown committed
274
      DBUG_ASSERT(!maria_in_recovery);
275 276 277
      error= _ma_state_info_write(share,
                                  MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET |
                                  MA_STATE_INFO_WRITE_FULL_INFO);
278
    }
unknown's avatar
unknown committed
279
    pthread_mutex_unlock(&share->intern_lock);
280 281
    break;
  case HA_EXTRA_FORCE_REOPEN:
unknown's avatar
unknown committed
282
    /*
283 284
      MySQL uses this case after it has closed all other instances
      of this table.
unknown's avatar
unknown committed
285 286 287
      We however do a flush here for additional safety.
    */
    /** @todo consider porting these flush-es to MyISAM */
288
    DBUG_ASSERT(share->reopen == 1);
unknown's avatar
unknown committed
289
    error= _ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
290 291 292 293
                                 FLUSH_FORCE_WRITE, FLUSH_FORCE_WRITE);
    if (!error && share->changed)
    {
      pthread_mutex_lock(&share->intern_lock);
294 295 296
      error= _ma_state_info_write(share,
                                  MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET|
                                  MA_STATE_INFO_WRITE_FULL_INFO);
297 298
      pthread_mutex_unlock(&share->intern_lock);
    }
299
    pthread_mutex_lock(&THR_LOCK_maria);
unknown's avatar
unknown committed
300
    pthread_mutex_lock(&share->intern_lock); /* protect against Checkpoint */
Michael Widenius's avatar
Michael Widenius committed
301 302
    /* Safety against assert in checkpoint */
    share->bitmap.changed_not_flushed= 0;
unknown's avatar
unknown committed
303
    /* this makes the share not be re-used next time the table is opened */
304
    share->last_version= 0L;			/* Impossible version */
unknown's avatar
unknown committed
305
    pthread_mutex_unlock(&share->intern_lock);
306 307
    pthread_mutex_unlock(&THR_LOCK_maria);
    break;
308
  case HA_EXTRA_PREPARE_FOR_DROP:
309 310 311 312
    /* Signals about intent to delete this table */
    share->deleting= TRUE;
    share->global_changed= FALSE;     /* force writing changed flag */
    /* To force repair if reopened */
313 314 315
    share->state.open_count= 1;
    share->changed= 1;
    _ma_mark_file_changed_now(share);
316
    /* Fall trough */
317
  case HA_EXTRA_PREPARE_FOR_RENAME:
unknown's avatar
unknown committed
318 319
  {
    my_bool do_flush= test(function != HA_EXTRA_PREPARE_FOR_DROP);
320
    my_bool save_global_changed;
321
    enum flush_type type;
322
    /*
unknown's avatar
unknown committed
323
      This share, to have last_version=0, needs to save all its data/index
unknown's avatar
unknown committed
324 325 326
      blocks to disk if this is not for a DROP TABLE. Otherwise they would be
      invisible to future openers; and they could even go to disk late and
      cancel the work of future openers.
327
    */
unknown's avatar
unknown committed
328 329 330 331 332 333 334
    if (info->lock_type != F_UNLCK && !info->was_locked)
    {
      info->was_locked= info->lock_type;
      if (maria_lock_database(info, F_UNLCK))
        error= my_errno;
      info->lock_type= F_UNLCK;
    }
335 336 337 338 339 340 341
    /*
      We don't need to call _mi_decrement_open_count() if we are
      dropping the table, as the files will be removed anyway. If we
      are aborted before the files is removed, it's better to not
      call it as in that case the automatic repair on open will add
      the missing index entries
    */
unknown's avatar
unknown committed
342
    pthread_mutex_lock(&share->intern_lock);
343
    if (share->kfile.file >= 0 && function != HA_EXTRA_PREPARE_FOR_DROP)
344
      _ma_decrement_open_count(info, 0);
345 346 347 348
    if (info->trn)
    {
      _ma_remove_table_from_trnman(share, info->trn);
      /* Ensure we don't point to the deleted data in trn */
349
      info->state= info->state_start= &share->state.state;
350 351
    }

352
    type= do_flush ? FLUSH_RELEASE : FLUSH_IGNORE_CHANGED;
353 354
    save_global_changed= share->global_changed;
    share->global_changed= 1;                 /* Don't increment open count */
Michael Widenius's avatar
Michael Widenius committed
355
    pthread_mutex_unlock(&share->intern_lock);
unknown's avatar
unknown committed
356 357
    if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
                              type, type))
358 359
    {
      error=my_errno;
360
      share->changed= 1;
361
    }
Michael Widenius's avatar
Michael Widenius committed
362
    pthread_mutex_lock(&share->intern_lock);
363
    share->global_changed= save_global_changed;
364 365 366
    if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
    {
      info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
unknown's avatar
unknown committed
367 368
      if (end_io_cache(&info->rec_cache))
        error= 1;
369
    }
unknown's avatar
unknown committed
370
    if (share->kfile.file >= 0)
371
    {
unknown's avatar
unknown committed
372 373
      if (do_flush)
      {
374
        /* Save the state so that others can find it from disk. */
375 376 377 378
        if ((share->changed &&
             _ma_state_info_write(share,
                                  MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET |
                                  MA_STATE_INFO_WRITE_FULL_INFO)) ||
unknown's avatar
unknown committed
379 380 381 382 383 384 385
            my_sync(share->kfile.file, MYF(0)))
          error= my_errno;
      }
      else
      {
        /* be sure that state is not tried for write as file may be closed */
        share->changed= 0;
386 387
        share->global_changed= 0;
        share->state.open_count= 0;
unknown's avatar
unknown committed
388
      }
389
    }
unknown's avatar
unknown committed
390 391 392
    if (share->data_file_type == BLOCK_RECORD &&
        share->bitmap.file.file >= 0)
    {
Michael Widenius's avatar
Michael Widenius committed
393 394
      DBUG_ASSERT(share->bitmap.non_flushable == 0 &&
                  share->bitmap.changed == 0);
unknown's avatar
unknown committed
395 396
      if (do_flush && my_sync(share->bitmap.file.file, MYF(0)))
        error= my_errno;
Michael Widenius's avatar
Michael Widenius committed
397
      share->bitmap.changed_not_flushed= 0;
398
    }
Michael Widenius's avatar
Michael Widenius committed
399
    /* last_version must be protected by intern_lock; See collect_tables() */
unknown's avatar
unknown committed
400
    share->last_version= 0L;			/* Impossible version */
unknown's avatar
unknown committed
401
    pthread_mutex_unlock(&share->intern_lock);
402
    break;
unknown's avatar
unknown committed
403
  }
404 405 406 407 408 409 410 411 412 413
  case HA_EXTRA_PREPARE_FOR_FORCED_CLOSE:
    if (info->trn)
    {
      pthread_mutex_lock(&share->intern_lock);
      _ma_remove_table_from_trnman(share, info->trn);
      /* Ensure we don't point to the deleted data in trn */
      info->state= info->state_start= &share->state.state;
      pthread_mutex_unlock(&share->intern_lock);    
    }
    break;
414 415
  case HA_EXTRA_FLUSH:
    if (!share->temporary)
unknown's avatar
unknown committed
416 417
      error= _ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
                                   FLUSH_KEEP, FLUSH_KEEP);
418

419
    _ma_decrement_open_count(info, 1);
420 421
    if (share->not_flushed)
    {
422
      share->not_flushed= 0;
423
      if (_ma_sync_table_files(info))
424 425 426
	error= my_errno;
      if (error)
      {
Michael Widenius's avatar
Michael Widenius committed
427
	/* Fatal error found */
428
	share->changed= 1;
Michael Widenius's avatar
Michael Widenius committed
429
        _ma_set_fatal_error(share, HA_ERR_CRASHED);
430 431 432 433
      }
    }
    break;
  case HA_EXTRA_NORMAL:				/* Theese isn't in use */
434
    info->quick_mode= 0;
435 436
    break;
  case HA_EXTRA_QUICK:
437
    info->quick_mode= 1;
438 439 440 441 442 443 444 445 446 447 448 449 450 451
    break;
  case HA_EXTRA_NO_ROWS:
    if (!share->state.header.uniques)
      info->opt_flag|= OPT_NO_ROWS;
    break;
  case HA_EXTRA_PRELOAD_BUFFER_SIZE:
    info->preload_buff_size= *((ulong *) extra_arg);
    break;
  case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
  case HA_EXTRA_CHANGE_KEY_TO_DUP:
    maria_extra_keyflag(info, function);
    break;
  case HA_EXTRA_MMAP:
#ifdef HAVE_MMAP
unknown's avatar
unknown committed
452 453
    if (block_records)
      break;                                    /* Not supported */
454
    pthread_mutex_lock(&share->intern_lock);
455
    /*
456 457 458 459 460
      Memory map the data file if it is not already mapped. It is safe
      to memory map a file while other threads are using file I/O on it.
      Assigning a new address to a function pointer is an atomic
      operation. intern_lock prevents that two or more mappings are done
      at the same time.
461
    */
462
    if (!share->file_map)
463 464 465 466 467 468 469 470
    {
      if (_ma_dynmap_file(info, share->state.state.data_file_length))
      {
        DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
        error= my_errno= errno;
      }
      else
      {
471
        share->file_read=  _ma_mmap_pread;
472 473 474 475 476 477
        share->file_write= _ma_mmap_pwrite;
      }
    }
    pthread_mutex_unlock(&share->intern_lock);
#endif
    break;
478 479 480 481 482
  case HA_EXTRA_MARK_AS_LOG_TABLE:
    pthread_mutex_lock(&share->intern_lock);
    share->is_log_table= TRUE;
    pthread_mutex_unlock(&share->intern_lock);
    break;
483 484 485 486 487 488 489 490 491
  case HA_EXTRA_KEY_CACHE:
  case HA_EXTRA_NO_KEY_CACHE:
  default:
    break;
  }
  DBUG_RETURN(error);
} /* maria_extra */


492 493 494 495 496 497 498 499
void ma_set_index_cond_func(MARIA_HA *info, index_cond_func_t func,
                            void *func_arg)
{
  info->index_cond_func= func;
  info->index_cond_func_arg= func_arg;
}


500
/*
unknown's avatar
unknown committed
501 502 503 504 505
  Start/Stop Inserting Duplicates Into a Table, WL#1648.
*/

static void maria_extra_keyflag(MARIA_HA *info,
                                enum ha_extra_function function)
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
{
  uint  idx;

  for (idx= 0; idx< info->s->base.keys; idx++)
  {
    switch (function) {
    case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
      info->s->keyinfo[idx].flag|= HA_NOSAME;
      break;
    case HA_EXTRA_CHANGE_KEY_TO_DUP:
      info->s->keyinfo[idx].flag&= ~(HA_NOSAME);
      break;
    default:
      break;
    }
  }
}
523 524 525 526 527


int maria_reset(MARIA_HA *info)
{
  int error= 0;
528
  MARIA_SHARE *share= info->s;
529 530 531 532 533 534 535 536 537 538 539 540 541
  DBUG_ENTER("maria_reset");
  /*
    Free buffers and reset the following flags:
    EXTRA_CACHE, EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK

    If the row buffer cache is large (for dynamic tables), reduce it
    to save memory.
  */
  if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
  {
    info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
    error= end_io_cache(&info->rec_cache);
  }
542 543 544 545
  /* Free memory used for keeping blobs */
  if (share->base.blobs)
  {
    if (info->rec_buff_size > share->base.default_rec_buff_size)
unknown's avatar
unknown committed
546 547 548 549 550
    {
      info->rec_buff_size= 1;                 /* Force realloc */
      _ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size,
                       share->base.default_rec_buff_size);
    }
551 552 553 554 555 556 557
    if (info->blob_buff_size > MARIA_SMALL_BLOB_BUFFER)
    {
      info->blob_buff_size= 1;                 /* Force realloc */
      _ma_alloc_buffer(&info->blob_buff, &info->blob_buff_size,
                       MARIA_SMALL_BLOB_BUFFER);
    }
  }
558 559
#if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
  if (info->opt_flag & MEMMAP_USED)
560 561
    madvise((char*) share->file_map, share->state.state.data_file_length,
            MADV_RANDOM);
562 563
#endif
  info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
564
  info->quick_mode= 0;
565
  info->lastinx= ~0;			/* detect index changes */
unknown's avatar
unknown committed
566
  info->last_search_keypage= info->cur_row.lastpos= HA_OFFSET_ERROR;
567 568 569 570 571
  info->page_changed= 1;
  info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND |
                 HA_STATE_PREV_FOUND);
  DBUG_RETURN(error);
}
572 573 574 575


int _ma_sync_table_files(const MARIA_HA *info)
{
unknown's avatar
unknown committed
576 577
  return (my_sync(info->dfile.file, MYF(MY_WME)) ||
          my_sync(info->s->kfile.file, MYF(MY_WME)));
578
}
unknown's avatar
unknown committed
579

Michael Widenius's avatar
Michael Widenius committed
580 581 582 583 584 585
uint _ma_file_callback_to_id(void *callback_data)
{
  MARIA_SHARE *share= (MARIA_SHARE*) callback_data;
  return share ? share->id : 0;
}

unknown's avatar
unknown committed
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613

/**
   @brief flushes the data and/or index file of a table

   This is useful when one wants to read a table using OS syscalls (like
   my_copy()) and first wants to be sure that MySQL-level caches go down to
   the OS so that OS syscalls can see all data. It can flush rec_cache,
   bitmap, pagecache of data file, pagecache of index file.

   @param  info                table
   @param  flush_data_or_index one or two of these flags:
                               MARIA_FLUSH_DATA, MARIA_FLUSH_INDEX
   @param  flush_type_for_data
   @param  flush_type_for_index

   @note does not sync files (@see _ma_sync_table_files()).
   @note Progressively this function will be used in all places where we flush
   the index but not the data file (probable bugs).

   @return Operation status
     @retval 0      OK
     @retval 1      Error
*/

int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index,
                          enum flush_type flush_type_for_data,
                          enum flush_type flush_type_for_index)
{
614
  int error= 0;
unknown's avatar
unknown committed
615
  MARIA_SHARE *share= info->s;
616 617
  DBUG_ENTER("_ma_flush_table_files");

unknown's avatar
unknown committed
618 619 620
  /* flush data file first because it's more critical */
  if (flush_data_or_index & MARIA_FLUSH_DATA)
  {
unknown's avatar
unknown committed
621
    if ((info->opt_flag & WRITE_CACHE_USED) &&
622
        flush_type_for_data != FLUSH_IGNORE_CHANGED &&
unknown's avatar
unknown committed
623
        flush_io_cache(&info->rec_cache))
624
      error= 1;
unknown's avatar
unknown committed
625 626
    if (share->data_file_type == BLOCK_RECORD)
    {
627 628 629 630 631 632
      if (flush_type_for_data != FLUSH_IGNORE_CHANGED)
      {
        if (_ma_bitmap_flush(share))
          error= 1;
      }
      else
633 634 635
      {
        pthread_mutex_lock(&share->bitmap.bitmap_lock);
        share->bitmap.changed= 0;
Michael Widenius's avatar
Michael Widenius committed
636
        share->bitmap.changed_not_flushed= 0;
637 638
        pthread_mutex_unlock(&share->bitmap.bitmap_lock);
      }
639 640 641
      if (flush_pagecache_blocks(share->pagecache, &info->dfile,
                                 flush_type_for_data))
        error= 1;
unknown's avatar
unknown committed
642 643 644 645 646
    }
  }
  if ((flush_data_or_index & MARIA_FLUSH_INDEX) &&
      flush_pagecache_blocks(share->pagecache, &share->kfile,
                             flush_type_for_index))
647 648
    error= 1;
  if (!error)
649
    DBUG_RETURN(0);
650

Michael Widenius's avatar
Michael Widenius committed
651
  _ma_set_fatal_error(info->s, HA_ERR_CRASHED);
652
  DBUG_RETURN(1);
unknown's avatar
unknown committed
653
}
654

655 656 657 658 659 660

my_bool ma_killed_standalone(MARIA_HA *info __attribute__((unused)))
{
  return 0;
}