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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
15
16#include "maria_def.h"
17#ifdef HAVE_SYS_MMAN_H
18#include <sys/mman.h>
19#endif
20#include "ma_blockrec.h"
21
22static void maria_extra_keyflag(MARIA_HA *info,
23 enum ha_extra_function function);
24
25/**
26 @brief Set options and buffers to optimize table handling
27
28 @param name table's name
29 @param info open table
30 @param function operation
31 @param extra_arg Pointer to extra argument (normally pointer to
32 ulong); used when function is one of:
33 HA_EXTRA_WRITE_CACHE
34 HA_EXTRA_CACHE
35
36 @return Operation status
37 @retval 0 ok
38 @retval !=0 error
39*/
40
41int maria_extra(MARIA_HA *info, enum ha_extra_function function,
42 void *extra_arg)
43{
44 int error= 0;
45 ulong cache_size;
46 MARIA_SHARE *share= info->s;
47 my_bool block_records= share->data_file_type == BLOCK_RECORD;
48 DBUG_ENTER("maria_extra");
49 DBUG_PRINT("enter",("function: %d",(int) function));
50
51 switch (function) {
52 case HA_EXTRA_RESET_STATE: /* Reset state (don't free buffers) */
53 info->lastinx= ~0; /* Detect index changes */
54 info->last_search_keypage= info->cur_row.lastpos= HA_OFFSET_ERROR;
55 info->page_changed= 1;
56 /* Next/prev gives first/last */
57 if (info->opt_flag & READ_CACHE_USED)
58 {
59 reinit_io_cache(&info->rec_cache,READ_CACHE,0,
60 (pbool) (info->lock_type != F_UNLCK),
61 (pbool) MY_TEST(info->update & HA_STATE_ROW_CHANGED)
62 );
63 }
64 info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND |
65 HA_STATE_PREV_FOUND);
66 break;
67 case HA_EXTRA_CACHE:
68 if (block_records)
69 break; /* Not supported */
70
71 if (info->lock_type == F_UNLCK &&
72 (share->options & HA_OPTION_PACK_RECORD))
73 {
74 error= 1; /* Not possibly if not locked */
75 my_errno= EACCES;
76 break;
77 }
78 if (info->s->file_map) /* Don't use cache if mmap */
79 break;
80#if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
81 if ((share->options & HA_OPTION_COMPRESS_RECORD))
82 {
83 mysql_mutex_lock(&share->intern_lock);
84 if (_ma_memmap_file(info))
85 {
86 /* We don't nead MADV_SEQUENTIAL if small file */
87 madvise((char*) share->file_map, share->state.state.data_file_length,
88 share->state.state.data_file_length <= RECORD_CACHE_SIZE*16 ?
89 MADV_RANDOM : MADV_SEQUENTIAL);
90 mysql_mutex_unlock(&share->intern_lock);
91 break;
92 }
93 mysql_mutex_unlock(&share->intern_lock);
94 }
95#endif
96 if (info->opt_flag & WRITE_CACHE_USED)
97 {
98 info->opt_flag&= ~WRITE_CACHE_USED;
99 if ((error= end_io_cache(&info->rec_cache)))
100 break;
101 }
102 if (!(info->opt_flag &
103 (READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED)))
104 {
105 cache_size= (extra_arg ? *(ulong*) extra_arg :
106 my_default_record_cache_size);
107 if (!(init_io_cache(&info->rec_cache, info->dfile.file,
108 (uint) MY_MIN(share->state.state.data_file_length+1,
109 cache_size),
110 READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK),
111 MYF(share->write_flag & MY_WAIT_IF_FULL))))
112 {
113 info->opt_flag|= READ_CACHE_USED;
114 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 break;
120 case HA_EXTRA_REINIT_CACHE:
121 if (info->opt_flag & READ_CACHE_USED)
122 {
123 reinit_io_cache(&info->rec_cache, READ_CACHE, info->cur_row.nextpos,
124 (pbool) (info->lock_type != F_UNLCK),
125 (pbool) MY_TEST(info->update & HA_STATE_ROW_CHANGED));
126 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 break;
131 case HA_EXTRA_WRITE_CACHE:
132 if (info->lock_type == F_UNLCK)
133 {
134 error= 1; /* Not possibly if not locked */
135 break;
136 }
137 if (block_records)
138 break; /* Not supported */
139
140 cache_size= (extra_arg ? *(ulong*) extra_arg :
141 my_default_record_cache_size);
142 if (!(info->opt_flag &
143 (READ_CACHE_USED | WRITE_CACHE_USED | OPT_NO_ROWS)) &&
144 !share->state.header.uniques)
145 if (!(init_io_cache(&info->rec_cache, info->dfile.file, cache_size,
146 WRITE_CACHE, info->state->data_file_length,
147 (pbool) (info->lock_type != F_UNLCK),
148 MYF(share->write_flag & MY_WAIT_IF_FULL))))
149 {
150 info->opt_flag|= WRITE_CACHE_USED;
151 info->update&= ~(HA_STATE_ROW_CHANGED |
152 HA_STATE_WRITE_AT_END |
153 HA_STATE_EXTEND_BLOCK);
154 }
155 break;
156 case HA_EXTRA_PREPARE_FOR_UPDATE:
157 if (info->s->data_file_type != DYNAMIC_RECORD)
158 break;
159 /* Remove read/write cache if dynamic rows */
160 /* fall through */
161 case HA_EXTRA_NO_CACHE:
162 if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
163 {
164 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
165 error= end_io_cache(&info->rec_cache);
166 /* Sergei will insert full text index caching here */
167 }
168#if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
169 if (info->opt_flag & MEMMAP_USED)
170 madvise((char*) share->file_map, share->state.state.data_file_length,
171 MADV_RANDOM);
172#endif
173 break;
174 case HA_EXTRA_FLUSH_CACHE:
175 if (info->opt_flag & WRITE_CACHE_USED)
176 {
177 if ((error= flush_io_cache(&info->rec_cache)))
178 {
179 /* Fatal error found */
180 _ma_set_fatal_error(share, HA_ERR_CRASHED);
181 }
182 }
183 break;
184 case HA_EXTRA_NO_READCHECK:
185 info->opt_flag&= ~READ_CHECK_USED; /* No readcheck */
186 break;
187 case HA_EXTRA_READCHECK:
188 info->opt_flag|= READ_CHECK_USED;
189 break;
190 case HA_EXTRA_KEYREAD: /* Read only keys to record */
191 case HA_EXTRA_REMEMBER_POS:
192 info->opt_flag|= REMEMBER_OLD_POS;
193 bmove(info->last_key.data + share->base.max_key_length*2,
194 info->last_key.data,
195 info->last_key.data_length + info->last_key.ref_length);
196 info->save_update= info->update;
197 info->save_lastinx= info->lastinx;
198 info->save_lastpos= info->cur_row.lastpos;
199 info->save_lastkey_data_length= info->last_key.data_length;
200 info->save_lastkey_ref_length= info->last_key.ref_length;
201 if (function == HA_EXTRA_REMEMBER_POS)
202 break;
203 /* fall through */
204 case HA_EXTRA_KEYREAD_CHANGE_POS:
205 info->opt_flag|= KEY_READ_USED;
206 info->read_record= _ma_read_key_record;
207 break;
208 case HA_EXTRA_NO_KEYREAD:
209 case HA_EXTRA_RESTORE_POS:
210 if (info->opt_flag & REMEMBER_OLD_POS)
211 {
212 bmove(info->last_key.data,
213 info->last_key.data + share->base.max_key_length*2,
214 info->save_lastkey_data_length + info->save_lastkey_ref_length);
215 info->update= info->save_update | HA_STATE_WRITTEN;
216 info->lastinx= info->save_lastinx;
217 info->cur_row.lastpos= info->save_lastpos;
218 info->last_key.data_length= info->save_lastkey_data_length;
219 info->last_key.ref_length= info->save_lastkey_ref_length;
220 info->last_key.flag= 0;
221 }
222 info->read_record= share->read_record;
223 info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
224 break;
225 case HA_EXTRA_NO_USER_CHANGE: /* Database is somehow locked agains changes */
226 info->lock_type= F_EXTRA_LCK; /* Simulate as locked */
227 break;
228 case HA_EXTRA_WAIT_LOCK:
229 info->lock_wait= 0;
230 break;
231 case HA_EXTRA_NO_WAIT_LOCK:
232 info->lock_wait= MY_SHORT_WAIT;
233 break;
234 case HA_EXTRA_NO_KEYS:
235 /* we're going to modify pieces of the state, stall Checkpoint */
236 mysql_mutex_lock(&share->intern_lock);
237 if (info->lock_type == F_UNLCK)
238 {
239 mysql_mutex_unlock(&share->intern_lock);
240 error= 1; /* Not possibly if not lock */
241 break;
242 }
243 if (maria_is_any_key_active(share->state.key_map))
244 {
245 MARIA_KEYDEF *key= share->keyinfo;
246 uint i;
247 for (i =0 ; i < share->base.keys ; i++,key++)
248 {
249 if (!(key->flag & HA_NOSAME) && info->s->base.auto_key != i+1)
250 {
251 maria_clear_key_active(share->state.key_map, i);
252 info->update|= HA_STATE_CHANGED;
253 }
254 }
255
256 if (!share->changed)
257 {
258 share->changed= 1; /* Update on close */
259 share->state.changed|= STATE_CHANGED | STATE_NOT_ANALYZED;
260 if (!share->global_changed)
261 {
262 share->global_changed= 1;
263 share->state.open_count++;
264 }
265 }
266 if (!share->now_transactional)
267 share->state.state= *info->state;
268 /*
269 That state write to disk must be done, even for transactional tables;
270 indeed the table's share is going to be lost (there was a
271 HA_EXTRA_FORCE_REOPEN before, which set share->last_version to
272 0), and so the only way it leaves information (share->state.key_map)
273 for the posterity is by writing it to disk.
274 */
275 DBUG_ASSERT(!maria_in_recovery);
276 error= _ma_state_info_write(share,
277 MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET |
278 MA_STATE_INFO_WRITE_FULL_INFO);
279 }
280 mysql_mutex_unlock(&share->intern_lock);
281 break;
282 case HA_EXTRA_FORCE_REOPEN:
283 /*
284 MySQL uses this case after it has closed all other instances
285 of this table.
286 We however do a flush here for additional safety.
287 */
288 /** @todo consider porting these flush-es to MyISAM */
289 DBUG_ASSERT(share->reopen == 1);
290 error= _ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
291 FLUSH_FORCE_WRITE, FLUSH_FORCE_WRITE);
292 if (!error && share->changed)
293 {
294 mysql_mutex_lock(&share->intern_lock);
295 error= _ma_state_info_write(share,
296 MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET|
297 MA_STATE_INFO_WRITE_FULL_INFO);
298 mysql_mutex_unlock(&share->intern_lock);
299 }
300 mysql_mutex_lock(&THR_LOCK_maria);
301 mysql_mutex_lock(&share->intern_lock); /* protect against Checkpoint */
302 /* Safety against assert in checkpoint */
303 share->bitmap.changed_not_flushed= 0;
304 /* this makes the share not be re-used next time the table is opened */
305 share->last_version= 0L; /* Impossible version */
306 mysql_mutex_unlock(&share->intern_lock);
307 mysql_mutex_unlock(&THR_LOCK_maria);
308 break;
309 case HA_EXTRA_PREPARE_FOR_DROP:
310 /* Signals about intent to delete this table */
311 share->deleting= TRUE;
312 share->global_changed= FALSE; /* force writing changed flag */
313 /* To force repair if reopened */
314 share->state.open_count= 1;
315 share->changed= 1;
316 _ma_mark_file_changed_now(share);
317 /* fall through */
318 case HA_EXTRA_PREPARE_FOR_RENAME:
319 {
320 my_bool do_flush= MY_TEST(function != HA_EXTRA_PREPARE_FOR_DROP);
321 my_bool save_global_changed;
322 enum flush_type type;
323 DBUG_ASSERT(!share->temporary);
324 /*
325 This share, to have last_version=0, needs to save all its data/index
326 blocks to disk if this is not for a DROP TABLE. Otherwise they would be
327 invisible to future openers; and they could even go to disk late and
328 cancel the work of future openers.
329 */
330 if (info->lock_type != F_UNLCK && !info->was_locked)
331 {
332 info->was_locked= info->lock_type;
333 if (maria_lock_database(info, F_UNLCK))
334 error= my_errno;
335 info->lock_type= F_UNLCK;
336 }
337 /*
338 We don't need to call _mi_decrement_open_count() if we are
339 dropping the table, as the files will be removed anyway. If we
340 are aborted before the files is removed, it's better to not
341 call it as in that case the automatic repair on open will add
342 the missing index entries
343 */
344 mysql_mutex_lock(&share->intern_lock);
345 if (share->kfile.file >= 0 && function != HA_EXTRA_PREPARE_FOR_DROP)
346 _ma_decrement_open_count(info, 0);
347 if (info->trn)
348 {
349 _ma_remove_table_from_trnman(share, info->trn);
350 /* Ensure we don't point to the deleted data in trn */
351 info->state= info->state_start= &share->state.state;
352 }
353 /* Remove history for table */
354 _ma_reset_state(info);
355
356 type= do_flush ? FLUSH_RELEASE : FLUSH_IGNORE_CHANGED;
357 save_global_changed= share->global_changed;
358 share->global_changed= 1; /* Don't increment open count */
359 mysql_mutex_unlock(&share->intern_lock);
360 if (_ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
361 type, type))
362 {
363 error=my_errno;
364 share->changed= 1;
365 }
366 mysql_mutex_lock(&share->intern_lock);
367 share->global_changed= save_global_changed;
368 if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
369 {
370 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
371 if (end_io_cache(&info->rec_cache))
372 error= 1;
373 }
374 if (share->kfile.file >= 0)
375 {
376 if (do_flush)
377 {
378 /* Save the state so that others can find it from disk. */
379 if ((share->changed &&
380 _ma_state_info_write(share,
381 MA_STATE_INFO_WRITE_DONT_MOVE_OFFSET |
382 MA_STATE_INFO_WRITE_FULL_INFO)) ||
383 mysql_file_sync(share->kfile.file, MYF(0)))
384 error= my_errno;
385 }
386 else
387 {
388 /* be sure that state is not tried for write as file may be closed */
389 share->changed= 0;
390 share->global_changed= 0;
391 share->state.open_count= 0;
392 }
393 }
394 if (share->data_file_type == BLOCK_RECORD &&
395 share->bitmap.file.file >= 0)
396 {
397 DBUG_ASSERT(share->bitmap.non_flushable == 0 &&
398 share->bitmap.changed == 0);
399 if (do_flush && my_sync(share->bitmap.file.file, MYF(0)))
400 error= my_errno;
401 share->bitmap.changed_not_flushed= 0;
402 }
403 /* last_version must be protected by intern_lock; See collect_tables() */
404 share->last_version= 0L; /* Impossible version */
405 mysql_mutex_unlock(&share->intern_lock);
406 break;
407 }
408 case HA_EXTRA_PREPARE_FOR_FORCED_CLOSE:
409 if (info->trn)
410 {
411 mysql_mutex_lock(&share->intern_lock);
412 _ma_remove_table_from_trnman(share, info->trn);
413 /* Ensure we don't point to the deleted data in trn */
414 info->state= info->state_start= &share->state.state;
415 mysql_mutex_unlock(&share->intern_lock);
416 }
417 break;
418 case HA_EXTRA_FLUSH:
419 if (!share->temporary)
420 error= _ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
421 FLUSH_KEEP, FLUSH_KEEP);
422
423 _ma_decrement_open_count(info, 1);
424 if (share->not_flushed)
425 {
426 share->not_flushed= 0;
427 if (_ma_sync_table_files(info))
428 error= my_errno;
429 if (error)
430 {
431 /* Fatal error found */
432 share->changed= 1;
433 _ma_set_fatal_error(share, HA_ERR_CRASHED);
434 }
435 }
436 break;
437 case HA_EXTRA_NORMAL: /* Theese isn't in use */
438 info->quick_mode= 0;
439 break;
440 case HA_EXTRA_QUICK:
441 info->quick_mode= 1;
442 break;
443 case HA_EXTRA_NO_ROWS:
444 if (!share->state.header.uniques)
445 info->opt_flag|= OPT_NO_ROWS;
446 break;
447 case HA_EXTRA_PRELOAD_BUFFER_SIZE:
448 info->preload_buff_size= *((ulong *) extra_arg);
449 break;
450 case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
451 case HA_EXTRA_CHANGE_KEY_TO_DUP:
452 maria_extra_keyflag(info, function);
453 break;
454 case HA_EXTRA_MMAP:
455#ifdef HAVE_MMAP
456 if (block_records)
457 break; /* Not supported */
458 mysql_mutex_lock(&share->intern_lock);
459 /*
460 Memory map the data file if it is not already mapped. It is safe
461 to memory map a file while other threads are using file I/O on it.
462 Assigning a new address to a function pointer is an atomic
463 operation. intern_lock prevents that two or more mappings are done
464 at the same time.
465 */
466 if (!share->file_map)
467 {
468 if (_ma_dynmap_file(info, share->state.state.data_file_length))
469 {
470 DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
471 error= my_errno= errno;
472 }
473 else
474 {
475 share->file_read= _ma_mmap_pread;
476 share->file_write= _ma_mmap_pwrite;
477 }
478 }
479 mysql_mutex_unlock(&share->intern_lock);
480#endif
481 break;
482 case HA_EXTRA_MARK_AS_LOG_TABLE:
483 mysql_mutex_lock(&share->intern_lock);
484 share->is_log_table= TRUE;
485 mysql_mutex_unlock(&share->intern_lock);
486 break;
487 case HA_EXTRA_KEY_CACHE:
488 case HA_EXTRA_NO_KEY_CACHE:
489 default:
490 break;
491 }
492 DBUG_RETURN(error);
493} /* maria_extra */
494
495
496void ma_set_index_cond_func(MARIA_HA *info, index_cond_func_t func,
497 void *func_arg)
498{
499 info->index_cond_func= func;
500 info->index_cond_func_arg= func_arg;
501}
502
503
504/*
505 Start/Stop Inserting Duplicates Into a Table, WL#1648.
506*/
507
508static void maria_extra_keyflag(MARIA_HA *info,
509 enum ha_extra_function function)
510{
511 uint idx;
512
513 for (idx= 0; idx< info->s->base.keys; idx++)
514 {
515 switch (function) {
516 case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
517 info->s->keyinfo[idx].flag|= HA_NOSAME;
518 break;
519 case HA_EXTRA_CHANGE_KEY_TO_DUP:
520 info->s->keyinfo[idx].flag&= ~(HA_NOSAME);
521 break;
522 default:
523 break;
524 }
525 }
526}
527
528
529int maria_reset(MARIA_HA *info)
530{
531 int error= 0;
532 MARIA_SHARE *share= info->s;
533 DBUG_ENTER("maria_reset");
534 /*
535 Free buffers and reset the following flags:
536 EXTRA_CACHE, EXTRA_WRITE_CACHE, EXTRA_KEYREAD, EXTRA_QUICK
537
538 If the row buffer cache is large (for dynamic tables), reduce it
539 to save memory.
540 */
541 if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
542 {
543 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
544 error= end_io_cache(&info->rec_cache);
545 }
546 /* Free memory used for keeping blobs */
547 if (share->base.blobs)
548 {
549 if (info->rec_buff_size > share->base.default_rec_buff_size)
550 {
551 info->rec_buff_size= 1; /* Force realloc */
552 _ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size,
553 share->base.default_rec_buff_size);
554 }
555 if (info->blob_buff_size > MARIA_SMALL_BLOB_BUFFER)
556 {
557 info->blob_buff_size= 1; /* Force realloc */
558 _ma_alloc_buffer(&info->blob_buff, &info->blob_buff_size,
559 MARIA_SMALL_BLOB_BUFFER);
560 }
561 }
562#if defined(HAVE_MMAP) && defined(HAVE_MADVISE)
563 if (info->opt_flag & MEMMAP_USED)
564 madvise((char*) share->file_map, share->state.state.data_file_length,
565 MADV_RANDOM);
566#endif
567 info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
568 info->quick_mode= 0;
569 info->lastinx= ~0; /* detect index changes */
570 info->last_search_keypage= info->cur_row.lastpos= HA_OFFSET_ERROR;
571 info->page_changed= 1;
572 info->update= ((info->update & HA_STATE_CHANGED) | HA_STATE_NEXT_FOUND |
573 HA_STATE_PREV_FOUND);
574 DBUG_RETURN(error);
575}
576
577
578int _ma_sync_table_files(const MARIA_HA *info)
579{
580 return (mysql_file_sync(info->dfile.file, MYF(MY_WME)) ||
581 mysql_file_sync(info->s->kfile.file, MYF(MY_WME)));
582}
583
584uint _ma_file_callback_to_id(void *callback_data)
585{
586 MARIA_SHARE *share= (MARIA_SHARE*) callback_data;
587 return share ? share->id : 0;
588}
589
590
591/**
592 @brief flushes the data and/or index file of a table
593
594 This is useful when one wants to read a table using OS syscalls (like
595 my_copy()) and first wants to be sure that MySQL-level caches go down to
596 the OS so that OS syscalls can see all data. It can flush rec_cache,
597 bitmap, pagecache of data file, pagecache of index file.
598
599 @param info table
600 @param flush_data_or_index one or two of these flags:
601 MARIA_FLUSH_DATA, MARIA_FLUSH_INDEX
602 @param flush_type_for_data
603 @param flush_type_for_index
604
605 @note does not sync files (@see _ma_sync_table_files()).
606 @note Progressively this function will be used in all places where we flush
607 the index but not the data file (probable bugs).
608
609 @return Operation status
610 @retval 0 OK
611 @retval 1 Error
612*/
613
614int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index,
615 enum flush_type flush_type_for_data,
616 enum flush_type flush_type_for_index)
617{
618 int error= 0;
619 MARIA_SHARE *share= info->s;
620 DBUG_ENTER("_ma_flush_table_files");
621
622 /* flush data file first because it's more critical */
623 if (flush_data_or_index & MARIA_FLUSH_DATA)
624 {
625 if ((info->opt_flag & WRITE_CACHE_USED) &&
626 flush_type_for_data != FLUSH_IGNORE_CHANGED &&
627 flush_io_cache(&info->rec_cache))
628 error= 1;
629 if (share->data_file_type == BLOCK_RECORD)
630 {
631 if (flush_type_for_data != FLUSH_IGNORE_CHANGED)
632 {
633 if (_ma_bitmap_flush(share))
634 error= 1;
635 }
636 else
637 {
638 mysql_mutex_lock(&share->bitmap.bitmap_lock);
639 share->bitmap.changed= 0;
640 share->bitmap.changed_not_flushed= 0;
641 mysql_mutex_unlock(&share->bitmap.bitmap_lock);
642 }
643 if (flush_pagecache_blocks(share->pagecache, &info->dfile,
644 flush_type_for_data))
645 error= 1;
646 }
647 }
648 if ((flush_data_or_index & MARIA_FLUSH_INDEX) &&
649 flush_pagecache_blocks(share->pagecache, &share->kfile,
650 flush_type_for_index))
651 error= 1;
652 if (!error)
653 DBUG_RETURN(0);
654
655 _ma_set_fatal_error(info->s, HA_ERR_CRASHED);
656 DBUG_RETURN(1);
657}
658
659
660my_bool ma_killed_standalone(MARIA_HA *info __attribute__((unused)))
661{
662 return 0;
663}
664