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