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