00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00026 #include "fil0fil.h"
00027
00028 #include "mem0mem.h"
00029 #include "hash0hash.h"
00030 #include "os0file.h"
00031 #include "mach0data.h"
00032 #include "buf0buf.h"
00033 #include "buf0flu.h"
00034 #include "log0recv.h"
00035 #include "fsp0fsp.h"
00036 #include "srv0srv.h"
00037 #include "srv0start.h"
00038 #include "mtr0mtr.h"
00039 #include "mtr0log.h"
00040 #include "dict0dict.h"
00041 #include "page0page.h"
00042 #include "page0zip.h"
00043 #include "xtrabackup_api.h"
00044 #ifndef UNIV_HOTBACKUP
00045 # include "buf0lru.h"
00046 # include "ibuf0ibuf.h"
00047 # include "sync0sync.h"
00048 # include "os0sync.h"
00049 #else
00050 static ulint srv_data_read, srv_data_written;
00051 #endif
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00112 UNIV_INTERN const char* fil_path_to_mysql_datadir = ".";
00113
00115 UNIV_INTERN ulint fil_n_log_flushes = 0;
00116
00118 UNIV_INTERN ulint fil_n_pending_log_flushes = 0;
00120 UNIV_INTERN ulint fil_n_pending_tablespace_flushes = 0;
00121
00123 UNIV_INTERN fil_addr_t fil_addr_null = {FIL_NULL, 0};
00124
00125 #ifdef UNIV_PFS_MUTEX
00126
00127 UNIV_INTERN mysql_pfs_key_t fil_system_mutex_key;
00128 #endif
00129
00130 #ifdef UNIV_PFS_RWLOCK
00131
00132 UNIV_INTERN mysql_pfs_key_t fil_space_latch_key;
00133 #endif
00134
00136 struct fil_node_struct {
00137 fil_space_t* space;
00139 char* name;
00140 ibool open;
00141 os_file_t handle;
00142 ibool is_raw_disk;
00144 ulint size;
00147 ulint n_pending;
00151 ulint n_pending_flushes;
00155 ib_int64_t modification_counter;
00157 ib_int64_t flush_counter;
00160 UT_LIST_NODE_T(fil_node_t) chain;
00162 UT_LIST_NODE_T(fil_node_t) LRU;
00164 ulint magic_n;
00165 };
00166
00168 #define FIL_NODE_MAGIC_N 89389
00169
00171 struct fil_space_struct {
00172 char* name;
00174 ulint id;
00175 ib_int64_t tablespace_version;
00181 ibool mark;
00185 ibool stop_ios;
00189 ibool stop_ibuf_merges;
00192 ibool is_being_deleted;
00199 ulint purpose;
00201 UT_LIST_BASE_NODE_T(fil_node_t) chain;
00203 ulint size;
00207 ulint flags;
00208 ulint n_reserved_extents;
00211 ulint n_pending_flushes;
00214 ulint n_pending_ibuf_merges;
00220 hash_node_t hash;
00221 hash_node_t name_hash;
00222 #ifndef UNIV_HOTBACKUP
00223 rw_lock_t latch;
00225 #endif
00226 UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
00229 ibool is_in_unflushed_spaces;
00231 UT_LIST_NODE_T(fil_space_t) space_list;
00233 ulint magic_n;
00234 };
00235
00237 #define FIL_SPACE_MAGIC_N 89472
00238
00240 typedef struct fil_system_struct fil_system_t;
00241
00246 struct fil_system_struct {
00247 #ifndef UNIV_HOTBACKUP
00248 mutex_t mutex;
00249 #endif
00250 hash_table_t* spaces;
00253 hash_table_t* name_hash;
00255 UT_LIST_BASE_NODE_T(fil_node_t) LRU;
00266 UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
00272 ulint n_open;
00273 ulint max_n_open;
00275 ib_int64_t modification_counter;
00277 ulint max_assigned_id;
00283 ib_int64_t tablespace_version;
00291 UT_LIST_BASE_NODE_T(fil_space_t) space_list;
00293 ibool space_id_reuse_warned;
00294
00295
00296
00297 };
00298
00301 fil_system_t* fil_system = NULL;
00302
00303
00304
00311 static
00312 void
00313 fil_node_prepare_for_io(
00314
00315 fil_node_t* node,
00316 fil_system_t* system,
00317 fil_space_t* space);
00318
00321 static
00322 void
00323 fil_node_complete_io(
00324
00325 fil_node_t* node,
00326 fil_system_t* system,
00327 ulint type);
00330
00334 static
00335 ulint
00336 fil_get_space_id_for_table(
00337
00338 const char* name);
00340
00345 static
00346 ibool
00347 fil_space_free(
00348
00349 ulint id,
00350 ibool x_latched);
00351
00352
00358 UNIV_INLINE
00359 ulint
00360 fil_read(
00361
00362 ibool sync,
00363 ulint space_id,
00364 ulint zip_size,
00366 ulint block_offset,
00367 ulint byte_offset,
00369 ulint len,
00372 void* buf,
00374 void* message)
00376 {
00377 return(fil_io(OS_FILE_READ, sync, space_id, zip_size, block_offset,
00378 byte_offset, len, buf, message));
00379 }
00380
00381
00387 UNIV_INLINE
00388 ulint
00389 fil_write(
00390
00391 ibool sync,
00392 ulint space_id,
00393 ulint zip_size,
00395 ulint block_offset,
00396 ulint byte_offset,
00398 ulint len,
00401 void* buf,
00403 void* message)
00405 {
00406 return(fil_io(OS_FILE_WRITE, sync, space_id, zip_size, block_offset,
00407 byte_offset, len, buf, message));
00408 }
00409
00410
00412 UNIV_INLINE
00413 fil_space_t*
00414 fil_space_get_by_id(
00415
00416 ulint id)
00417 {
00418 fil_space_t* space;
00419
00420 ut_ad(mutex_own(&fil_system->mutex));
00421
00422 HASH_SEARCH(hash, fil_system->spaces, id,
00423 fil_space_t*, space,
00424 ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
00425 space->id == id);
00426
00427 return(space);
00428 }
00429
00430
00432 UNIV_INLINE
00433 fil_space_t*
00434 fil_space_get_by_name(
00435
00436 const char* name)
00437 {
00438 fil_space_t* space;
00439 ulint fold;
00440
00441 ut_ad(mutex_own(&fil_system->mutex));
00442
00443 fold = ut_fold_string(name);
00444
00445 HASH_SEARCH(name_hash, fil_system->name_hash, fold,
00446 fil_space_t*, space,
00447 ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
00448 !strcmp(name, space->name));
00449
00450 return(space);
00451 }
00452
00453 #ifndef UNIV_HOTBACKUP
00454
00458 UNIV_INTERN
00459 ib_int64_t
00460 fil_space_get_version(
00461
00462 ulint id)
00463 {
00464 fil_space_t* space;
00465 ib_int64_t version = -1;
00466
00467 ut_ad(fil_system);
00468
00469 mutex_enter(&fil_system->mutex);
00470
00471 space = fil_space_get_by_id(id);
00472
00473 if (space) {
00474 version = space->tablespace_version;
00475 }
00476
00477 mutex_exit(&fil_system->mutex);
00478
00479 return(version);
00480 }
00481
00482
00485 UNIV_INTERN
00486 rw_lock_t*
00487 fil_space_get_latch(
00488
00489 ulint id,
00490 ulint* flags)
00491 {
00492 fil_space_t* space;
00493
00494 ut_ad(fil_system);
00495
00496 mutex_enter(&fil_system->mutex);
00497
00498 space = fil_space_get_by_id(id);
00499
00500 ut_a(space);
00501
00502 if (flags) {
00503 *flags = space->flags;
00504 }
00505
00506 mutex_exit(&fil_system->mutex);
00507
00508 return(&(space->latch));
00509 }
00510
00511
00514 UNIV_INTERN
00515 ulint
00516 fil_space_get_type(
00517
00518 ulint id)
00519 {
00520 fil_space_t* space;
00521
00522 ut_ad(fil_system);
00523
00524 mutex_enter(&fil_system->mutex);
00525
00526 space = fil_space_get_by_id(id);
00527
00528 ut_a(space);
00529
00530 mutex_exit(&fil_system->mutex);
00531
00532 return(space->purpose);
00533 }
00534 #endif
00535
00536
00540 static
00541 ibool
00542 fil_space_is_flushed(
00543
00544 fil_space_t* space)
00545 {
00546 fil_node_t* node;
00547
00548 ut_ad(mutex_own(&fil_system->mutex));
00549
00550 node = UT_LIST_GET_FIRST(space->chain);
00551
00552 while (node) {
00553 if (node->modification_counter > node->flush_counter) {
00554
00555 return(FALSE);
00556 }
00557
00558 node = UT_LIST_GET_NEXT(chain, node);
00559 }
00560
00561 return(TRUE);
00562 }
00563
00564
00566 UNIV_INTERN
00567 void
00568 fil_node_create(
00569
00570 const char* name,
00571 ulint size,
00573 ulint id,
00574 ibool is_raw)
00576 {
00577 fil_node_t* node;
00578 fil_space_t* space;
00579
00580 ut_a(fil_system);
00581 ut_a(name);
00582
00583 mutex_enter(&fil_system->mutex);
00584
00585 node = static_cast<fil_node_t *>(mem_alloc(sizeof(fil_node_t)));
00586
00587 node->name = mem_strdup(name);
00588 node->open = FALSE;
00589
00590 ut_a(!is_raw || srv_start_raw_disk_in_use);
00591
00592 node->is_raw_disk = is_raw;
00593 node->size = size;
00594 node->magic_n = FIL_NODE_MAGIC_N;
00595 node->n_pending = 0;
00596 node->n_pending_flushes = 0;
00597
00598 node->modification_counter = 0;
00599 node->flush_counter = 0;
00600
00601 space = fil_space_get_by_id(id);
00602
00603 if (!space) {
00604 ut_print_timestamp(stderr);
00605 fprintf(stderr,
00606 " InnoDB: Error: Could not find tablespace %lu for\n"
00607 "InnoDB: file ", (ulong) id);
00608 ut_print_filename(stderr, name);
00609 fputs(" in the tablespace memory cache.\n", stderr);
00610 mem_free(node->name);
00611
00612 mem_free(node);
00613
00614 mutex_exit(&fil_system->mutex);
00615
00616 return;
00617 }
00618
00619 space->size += size;
00620
00621 node->space = space;
00622
00623 UT_LIST_ADD_LAST(chain, space->chain, node);
00624
00625 if (id < SRV_LOG_SPACE_FIRST_ID && fil_system->max_assigned_id < id) {
00626
00627 fil_system->max_assigned_id = id;
00628 }
00629
00630 mutex_exit(&fil_system->mutex);
00631 }
00632
00633
00636 static
00637 void
00638 fil_node_open_file(
00639
00640 fil_node_t* node,
00641 fil_system_t* system,
00642 fil_space_t* space)
00643 {
00644 uint64_t size_bytes;
00645 ulint size_low;
00646 ulint size_high;
00647 ibool ret;
00648 ibool success;
00649 byte* buf2;
00650 byte* page;
00651 ulint space_id;
00652 ulint flags;
00653
00654 ut_ad(mutex_own(&(system->mutex)));
00655 ut_a(node->n_pending == 0);
00656 ut_a(node->open == FALSE);
00657
00658 if (node->size == 0) {
00659
00660
00661
00662
00663
00664
00665
00666
00667 node->handle = os_file_create_simple_no_error_handling(
00668 innodb_file_data_key, node->name, OS_FILE_OPEN,
00669 OS_FILE_READ_ONLY, &success);
00670 if (!success) {
00671
00672 os_file_get_last_error(TRUE);
00673
00674 ut_print_timestamp(stderr);
00675
00676 fprintf(stderr,
00677 " InnoDB: Fatal error: cannot open %s\n."
00678 "InnoDB: Have you deleted .ibd files"
00679 " under a running mysqld server?\n",
00680 node->name);
00681 ut_a(0);
00682 }
00683
00684 os_file_get_size(node->handle, &size_low, &size_high);
00685
00686 size_bytes = (((uint64_t)size_high) << 32) + size_low;
00687 #ifdef UNIV_HOTBACKUP
00688 if (space->id == 0) {
00689 node->size = size_bytes / UNIV_PAGE_SIZE;
00690 os_file_close(node->handle);
00691 goto add_size;
00692 }
00693 #endif
00694 ut_a(space->purpose != FIL_LOG);
00695 ut_a(space->id != 0);
00696
00697 if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
00698 fprintf(stderr,
00699 "InnoDB: Error: the size of single-table"
00700 " tablespace file %s\n"
00701 "InnoDB: is only %lu %lu,"
00702 " should be at least %lu!\n",
00703 node->name,
00704 (ulong) size_high,
00705 (ulong) size_low,
00706 (ulong) (FIL_IBD_FILE_INITIAL_SIZE
00707 * UNIV_PAGE_SIZE));
00708
00709 ut_a(0);
00710 }
00711
00712
00713
00714 buf2 = static_cast<unsigned char *>(ut_malloc(2 * UNIV_PAGE_SIZE));
00715
00716
00717 page = static_cast<unsigned char *>(ut_align(buf2, UNIV_PAGE_SIZE));
00718
00719 success = os_file_read(node->handle, page, 0, 0,
00720 UNIV_PAGE_SIZE);
00721 space_id = fsp_header_get_space_id(page);
00722 flags = fsp_header_get_flags(page);
00723
00724 ut_free(buf2);
00725
00726
00727
00728 os_file_close(node->handle);
00729
00730 if (UNIV_UNLIKELY(space_id != space->id)) {
00731 fprintf(stderr,
00732 "InnoDB: Error: tablespace id is %lu"
00733 " in the data dictionary\n"
00734 "InnoDB: but in file %s it is %lu!\n",
00735 space->id, node->name, space_id);
00736
00737 ut_error;
00738 }
00739
00740 if (UNIV_UNLIKELY(space_id == ULINT_UNDEFINED
00741 || space_id == 0)) {
00742 fprintf(stderr,
00743 "InnoDB: Error: tablespace id %lu"
00744 " in file %s is not sensible\n",
00745 (ulong) space_id, node->name);
00746
00747 ut_error;
00748 }
00749
00750 if (UNIV_UNLIKELY(space->flags != flags)) {
00751 fprintf(stderr,
00752 "InnoDB: Error: table flags are %lx"
00753 " in the data dictionary\n"
00754 "InnoDB: but the flags in file %s are %lx!\n",
00755 space->flags, node->name, flags);
00756
00757 ut_error;
00758 }
00759
00760 if (size_bytes >= 1024 * 1024) {
00761
00762 size_bytes = ut_2pow_round(size_bytes, 1024 * 1024);
00763 }
00764
00765 if (!(flags & DICT_TF_ZSSIZE_MASK)) {
00766 node->size = (ulint)size_bytes / UNIV_PAGE_SIZE;
00767 } else {
00768 node->size = (ulint)
00769 (size_bytes
00770 / dict_table_flags_to_zip_size(flags));
00771 }
00772
00773 #ifdef UNIV_HOTBACKUP
00774 add_size:
00775 #endif
00776 space->size += node->size;
00777 }
00778
00779
00780
00781
00782
00783
00784
00785 if (space->purpose == FIL_LOG) {
00786 node->handle = os_file_create(innodb_file_log_key,
00787 node->name, OS_FILE_OPEN,
00788 OS_FILE_AIO, OS_LOG_FILE,
00789 &ret);
00790 } else if (node->is_raw_disk) {
00791 node->handle = os_file_create(innodb_file_data_key,
00792 node->name,
00793 OS_FILE_OPEN_RAW,
00794 OS_FILE_AIO, OS_DATA_FILE,
00795 &ret);
00796 } else {
00797 node->handle = os_file_create(innodb_file_data_key,
00798 node->name, OS_FILE_OPEN,
00799 OS_FILE_AIO, OS_DATA_FILE,
00800 &ret);
00801 }
00802
00803 ut_a(ret);
00804
00805 node->open = TRUE;
00806
00807 system->n_open++;
00808
00809 if (space->purpose == FIL_TABLESPACE && space->id != 0) {
00810
00811 UT_LIST_ADD_FIRST(LRU, system->LRU, node);
00812 }
00813 }
00814
00815
00817 static
00818 void
00819 fil_node_close_file(
00820
00821 fil_node_t* node,
00822 fil_system_t* system)
00823 {
00824 ibool ret;
00825
00826 ut_ad(node && system);
00827 ut_ad(mutex_own(&(system->mutex)));
00828 ut_a(node->open);
00829 ut_a(node->n_pending == 0);
00830 ut_a(node->n_pending_flushes == 0);
00831 ut_a(node->modification_counter == node->flush_counter);
00832
00833 ret = os_file_close(node->handle);
00834 ut_a(ret);
00835
00836
00837
00838 node->open = FALSE;
00839 ut_a(system->n_open > 0);
00840 system->n_open--;
00841
00842 if (node->space->purpose == FIL_TABLESPACE && node->space->id != 0) {
00843 ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
00844
00845
00846 UT_LIST_REMOVE(LRU, system->LRU, node);
00847 }
00848 }
00849
00850
00858 static
00859 ibool
00860 fil_try_to_close_file_in_LRU(
00861
00862 ibool print_info)
00864 {
00865 fil_node_t* node;
00866
00867 ut_ad(mutex_own(&fil_system->mutex));
00868
00869 node = UT_LIST_GET_LAST(fil_system->LRU);
00870
00871 if (print_info) {
00872 fprintf(stderr,
00873 "InnoDB: fil_sys open file LRU len %lu\n",
00874 (ulong) UT_LIST_GET_LEN(fil_system->LRU));
00875 }
00876
00877 while (node != NULL) {
00878 if (node->modification_counter == node->flush_counter
00879 && node->n_pending_flushes == 0) {
00880
00881 fil_node_close_file(node, fil_system);
00882
00883 return(TRUE);
00884 }
00885
00886 if (print_info && node->n_pending_flushes > 0) {
00887 fputs("InnoDB: cannot close file ", stderr);
00888 ut_print_filename(stderr, node->name);
00889 fprintf(stderr, ", because n_pending_flushes %lu\n",
00890 (ulong) node->n_pending_flushes);
00891 }
00892
00893 if (print_info
00894 && node->modification_counter != node->flush_counter) {
00895 fputs("InnoDB: cannot close file ", stderr);
00896 ut_print_filename(stderr, node->name);
00897 fprintf(stderr,
00898 ", because mod_count %ld != fl_count %ld\n",
00899 (long) node->modification_counter,
00900 (long) node->flush_counter);
00901 }
00902
00903 node = UT_LIST_GET_PREV(LRU, node);
00904 }
00905
00906 return(FALSE);
00907 }
00908
00909
00913 static
00914 void
00915 fil_mutex_enter_and_prepare_for_io(
00916
00917 ulint space_id)
00918 {
00919 fil_space_t* space;
00920 ibool success;
00921 ibool print_info = FALSE;
00922 ulint count = 0;
00923 ulint count2 = 0;
00924
00925 retry:
00926 mutex_enter(&fil_system->mutex);
00927
00928 if (space_id == 0 || space_id >= SRV_LOG_SPACE_FIRST_ID) {
00929
00930
00931
00932
00933
00934
00935 return;
00936 }
00937
00938 if (fil_system->n_open < fil_system->max_n_open) {
00939
00940 return;
00941 }
00942
00943 space = fil_space_get_by_id(space_id);
00944
00945 if (space != NULL && space->stop_ios) {
00946
00947
00948
00949 if (count2 > 20000) {
00950 fputs("InnoDB: Warning: tablespace ", stderr);
00951 ut_print_filename(stderr, space->name);
00952 fprintf(stderr,
00953 " has i/o ops stopped for a long time %lu\n",
00954 (ulong) count2);
00955 }
00956
00957 mutex_exit(&fil_system->mutex);
00958
00959 os_thread_sleep(20000);
00960
00961 count2++;
00962
00963 goto retry;
00964 }
00965
00966
00967
00968
00969
00970 if (!space || UT_LIST_GET_FIRST(space->chain)->open) {
00971
00972 return;
00973 }
00974
00975 if (count > 1) {
00976 print_info = TRUE;
00977 }
00978
00979
00980 close_more:
00981 success = fil_try_to_close_file_in_LRU(print_info);
00982
00983 if (success && fil_system->n_open >= fil_system->max_n_open) {
00984
00985 goto close_more;
00986 }
00987
00988 if (fil_system->n_open < fil_system->max_n_open) {
00989
00990
00991 return;
00992 }
00993
00994 if (count >= 2) {
00995 ut_print_timestamp(stderr);
00996 fprintf(stderr,
00997 " InnoDB: Warning: too many (%lu) files stay open"
00998 " while the maximum\n"
00999 "InnoDB: allowed value would be %lu.\n"
01000 "InnoDB: You may need to raise the value of"
01001 " innodb_open_files in\n"
01002 "InnoDB: my.cnf.\n",
01003 (ulong) fil_system->n_open,
01004 (ulong) fil_system->max_n_open);
01005
01006 return;
01007 }
01008
01009 mutex_exit(&fil_system->mutex);
01010
01011 #ifndef UNIV_HOTBACKUP
01012
01013
01014 os_aio_simulated_wake_handler_threads();
01015
01016 os_thread_sleep(20000);
01017 #endif
01018
01019
01020
01021 fil_flush_file_spaces(FIL_TABLESPACE);
01022
01023 count++;
01024
01025 goto retry;
01026 }
01027
01028
01030 static
01031 void
01032 fil_node_free(
01033
01034 fil_node_t* node,
01035 fil_system_t* system,
01036 fil_space_t* space)
01037 {
01038 ut_ad(node && system && space);
01039 ut_ad(mutex_own(&(system->mutex)));
01040 ut_a(node->magic_n == FIL_NODE_MAGIC_N);
01041 ut_a(node->n_pending == 0);
01042
01043 if (node->open) {
01044
01045
01046
01047 node->modification_counter = node->flush_counter;
01048
01049 if (space->is_in_unflushed_spaces
01050 && fil_space_is_flushed(space)) {
01051
01052 space->is_in_unflushed_spaces = FALSE;
01053
01054 UT_LIST_REMOVE(unflushed_spaces,
01055 system->unflushed_spaces,
01056 space);
01057 }
01058
01059 fil_node_close_file(node, system);
01060 }
01061
01062 space->size -= node->size;
01063
01064 UT_LIST_REMOVE(chain, space->chain, node);
01065
01066 mem_free(node->name);
01067 mem_free(node);
01068 }
01069
01070 #ifdef UNIV_LOG_ARCHIVE
01071
01074 UNIV_INTERN
01075 void
01076 fil_space_truncate_start(
01077
01078 ulint id,
01079 ulint trunc_len)
01082 {
01083 fil_node_t* node;
01084 fil_space_t* space;
01085
01086 mutex_enter(&fil_system->mutex);
01087
01088 space = fil_space_get_by_id(id);
01089
01090 ut_a(space);
01091
01092 while (trunc_len > 0) {
01093 node = UT_LIST_GET_FIRST(space->chain);
01094
01095 ut_a(node->size * UNIV_PAGE_SIZE <= trunc_len);
01096
01097 trunc_len -= node->size * UNIV_PAGE_SIZE;
01098
01099 fil_node_free(node, fil_system, space);
01100 }
01101
01102 mutex_exit(&fil_system->mutex);
01103 }
01104 #endif
01105
01106
01110 UNIV_INTERN
01111 ibool
01112 fil_space_create(
01113
01114 const char* name,
01115 ulint id,
01116 ulint flags,
01118 ulint purpose)
01119 {
01120 fil_space_t* space;
01121
01122
01123
01124
01125
01126
01127
01128 ut_a(flags != DICT_TF_COMPACT);
01129 ut_a(!(flags & (~0UL << DICT_TF_BITS)));
01130
01131 try_again:
01132
01133
01134
01135
01136 ut_a(fil_system);
01137 ut_a(name);
01138
01139 mutex_enter(&fil_system->mutex);
01140
01141 space = fil_space_get_by_name(name);
01142
01143 if (UNIV_LIKELY_NULL(space)) {
01144 ibool success;
01145 ulint namesake_id;
01146
01147 ut_print_timestamp(stderr);
01148 fprintf(stderr,
01149 " InnoDB: Warning: trying to init to the"
01150 " tablespace memory cache\n"
01151 "InnoDB: a tablespace %lu of name ", (ulong) id);
01152 ut_print_filename(stderr, name);
01153 fprintf(stderr, ",\n"
01154 "InnoDB: but a tablespace %lu of the same name\n"
01155 "InnoDB: already exists in the"
01156 " tablespace memory cache!\n",
01157 (ulong) space->id);
01158
01159 if (id == 0 || purpose != FIL_TABLESPACE) {
01160
01161 mutex_exit(&fil_system->mutex);
01162
01163 return(FALSE);
01164 }
01165
01166 fprintf(stderr,
01167 "InnoDB: We assume that InnoDB did a crash recovery,"
01168 " and you had\n"
01169 "InnoDB: an .ibd file for which the table"
01170 " did not exist in the\n"
01171 "InnoDB: InnoDB internal data dictionary in the"
01172 " ibdata files.\n"
01173 "InnoDB: We assume that you later removed the"
01174 " .ibd and .frm files,\n"
01175 "InnoDB: and are now trying to recreate the table."
01176 " We now remove the\n"
01177 "InnoDB: conflicting tablespace object"
01178 " from the memory cache and try\n"
01179 "InnoDB: the init again.\n");
01180
01181 namesake_id = space->id;
01182
01183 success = fil_space_free(namesake_id, FALSE);
01184 ut_a(success);
01185
01186 mutex_exit(&fil_system->mutex);
01187
01188 goto try_again;
01189 }
01190
01191 space = fil_space_get_by_id(id);
01192
01193 if (UNIV_LIKELY_NULL(space)) {
01194 fprintf(stderr,
01195 "InnoDB: Error: trying to add tablespace %lu"
01196 " of name ", (ulong) id);
01197 ut_print_filename(stderr, name);
01198 fprintf(stderr, "\n"
01199 "InnoDB: to the tablespace memory cache,"
01200 " but tablespace\n"
01201 "InnoDB: %lu of name ", (ulong) space->id);
01202 ut_print_filename(stderr, space->name);
01203 fputs(" already exists in the tablespace\n"
01204 "InnoDB: memory cache!\n", stderr);
01205
01206 mutex_exit(&fil_system->mutex);
01207
01208 return(FALSE);
01209 }
01210
01211 space = static_cast<fil_space_t *>(mem_alloc(sizeof(fil_space_t)));
01212
01213 space->name = mem_strdup(name);
01214 space->id = id;
01215
01216 fil_system->tablespace_version++;
01217 space->tablespace_version = fil_system->tablespace_version;
01218 space->mark = FALSE;
01219
01220 if (UNIV_LIKELY(purpose == FIL_TABLESPACE && !recv_recovery_on)
01221 && UNIV_UNLIKELY(id > fil_system->max_assigned_id)) {
01222 if (!fil_system->space_id_reuse_warned) {
01223 fil_system->space_id_reuse_warned = TRUE;
01224
01225 ut_print_timestamp(stderr);
01226 fprintf(stderr,
01227 " InnoDB: Warning: allocated tablespace %lu,"
01228 " old maximum was %lu\n",
01229 (ulong) id,
01230 (ulong) fil_system->max_assigned_id);
01231 }
01232
01233 fil_system->max_assigned_id = id;
01234 }
01235
01236 space->stop_ios = FALSE;
01237 space->stop_ibuf_merges = FALSE;
01238 space->is_being_deleted = FALSE;
01239 space->purpose = purpose;
01240 space->size = 0;
01241 space->flags = flags;
01242
01243 space->n_reserved_extents = 0;
01244
01245 space->n_pending_flushes = 0;
01246 space->n_pending_ibuf_merges = 0;
01247
01248 UT_LIST_INIT(space->chain);
01249 space->magic_n = FIL_SPACE_MAGIC_N;
01250
01251 rw_lock_create(fil_space_latch_key, &space->latch, SYNC_FSP);
01252
01253 HASH_INSERT(fil_space_t, hash, fil_system->spaces, id, space);
01254
01255 HASH_INSERT(fil_space_t, name_hash, fil_system->name_hash,
01256 ut_fold_string(name), space);
01257 space->is_in_unflushed_spaces = FALSE;
01258
01259 UT_LIST_ADD_LAST(space_list, fil_system->space_list, space);
01260
01261 mutex_exit(&fil_system->mutex);
01262
01263 return(TRUE);
01264 }
01265
01266
01271 UNIV_INTERN
01272 ibool
01273 fil_assign_new_space_id(
01274
01275 ulint* space_id)
01276 {
01277 ulint id;
01278 ibool success;
01279
01280 mutex_enter(&fil_system->mutex);
01281
01282 id = *space_id;
01283
01284 if (id < fil_system->max_assigned_id) {
01285 id = fil_system->max_assigned_id;
01286 }
01287
01288 id++;
01289
01290 if (id > (SRV_LOG_SPACE_FIRST_ID / 2) && (id % 1000000UL == 0)) {
01291 ut_print_timestamp(stderr);
01292 fprintf(stderr,
01293 "InnoDB: Warning: you are running out of new"
01294 " single-table tablespace id's.\n"
01295 "InnoDB: Current counter is %lu and it"
01296 " must not exceed %lu!\n"
01297 "InnoDB: To reset the counter to zero"
01298 " you have to dump all your tables and\n"
01299 "InnoDB: recreate the whole InnoDB installation.\n",
01300 (ulong) id,
01301 (ulong) SRV_LOG_SPACE_FIRST_ID);
01302 }
01303
01304 success = (id < SRV_LOG_SPACE_FIRST_ID);
01305
01306 if (success) {
01307 *space_id = fil_system->max_assigned_id = id;
01308 } else {
01309 ut_print_timestamp(stderr);
01310 fprintf(stderr,
01311 "InnoDB: You have run out of single-table"
01312 " tablespace id's!\n"
01313 "InnoDB: Current counter is %lu.\n"
01314 "InnoDB: To reset the counter to zero you"
01315 " have to dump all your tables and\n"
01316 "InnoDB: recreate the whole InnoDB installation.\n",
01317 (ulong) id);
01318 *space_id = ULINT_UNDEFINED;
01319 }
01320
01321 mutex_exit(&fil_system->mutex);
01322
01323 return(success);
01324 }
01325
01326
01331 static
01332 ibool
01333 fil_space_free(
01334
01335
01336 ulint id,
01337 ibool x_latched)
01338
01339 {
01340 fil_space_t* space;
01341 fil_space_t* tablespace;
01342 fil_node_t* fil_node;
01343
01344 ut_ad(mutex_own(&fil_system->mutex));
01345
01346 space = fil_space_get_by_id(id);
01347
01348 if (!space) {
01349 ut_print_timestamp(stderr);
01350 fprintf(stderr,
01351 " InnoDB: Error: trying to remove tablespace %lu"
01352 " from the cache but\n"
01353 "InnoDB: it is not there.\n", (ulong) id);
01354
01355 return(FALSE);
01356 }
01357
01358 HASH_DELETE(fil_space_t, hash, fil_system->spaces, id, space);
01359
01360 tablespace = fil_space_get_by_name(space->name);
01361 ut_a(tablespace);
01362 ut_a(space == tablespace);
01363
01364 HASH_DELETE(fil_space_t, name_hash, fil_system->name_hash,
01365 ut_fold_string(space->name), space);
01366
01367 if (space->is_in_unflushed_spaces) {
01368 space->is_in_unflushed_spaces = FALSE;
01369
01370 UT_LIST_REMOVE(unflushed_spaces, fil_system->unflushed_spaces,
01371 space);
01372 }
01373
01374 UT_LIST_REMOVE(space_list, fil_system->space_list, space);
01375
01376 ut_a(space->magic_n == FIL_SPACE_MAGIC_N);
01377 ut_a(0 == space->n_pending_flushes);
01378
01379 fil_node = UT_LIST_GET_FIRST(space->chain);
01380
01381 while (fil_node != NULL) {
01382 fil_node_free(fil_node, fil_system, space);
01383
01384 fil_node = UT_LIST_GET_FIRST(space->chain);
01385 }
01386
01387 ut_a(0 == UT_LIST_GET_LEN(space->chain));
01388
01389 if (x_latched) {
01390 rw_lock_x_unlock(&space->latch);
01391 }
01392
01393 rw_lock_free(&(space->latch));
01394
01395 mem_free(space->name);
01396 mem_free(space);
01397
01398 return(TRUE);
01399 }
01400
01401
01405 UNIV_INTERN
01406 ulint
01407 fil_space_get_size(
01408
01409 ulint id)
01410 {
01411 fil_node_t* node;
01412 fil_space_t* space;
01413 ulint size;
01414
01415 ut_ad(fil_system);
01416
01417 fil_mutex_enter_and_prepare_for_io(id);
01418
01419 space = fil_space_get_by_id(id);
01420
01421 if (space == NULL) {
01422 mutex_exit(&fil_system->mutex);
01423
01424 return(0);
01425 }
01426
01427 if (space->size == 0 && space->purpose == FIL_TABLESPACE) {
01428 ut_a(id != 0);
01429
01430 ut_a(1 == UT_LIST_GET_LEN(space->chain));
01431
01432 node = UT_LIST_GET_FIRST(space->chain);
01433
01434
01435
01436
01437
01438 fil_node_prepare_for_io(node, fil_system, space);
01439 fil_node_complete_io(node, fil_system, OS_FILE_READ);
01440 }
01441
01442 size = space->size;
01443
01444 mutex_exit(&fil_system->mutex);
01445
01446 return(size);
01447 }
01448
01449
01453 UNIV_INTERN
01454 ulint
01455 fil_space_get_flags(
01456
01457 ulint id)
01458 {
01459 fil_node_t* node;
01460 fil_space_t* space;
01461 ulint flags;
01462
01463 ut_ad(fil_system);
01464
01465 if (UNIV_UNLIKELY(!id)) {
01466 return(0);
01467 }
01468
01469 fil_mutex_enter_and_prepare_for_io(id);
01470
01471 space = fil_space_get_by_id(id);
01472
01473 if (space == NULL) {
01474 mutex_exit(&fil_system->mutex);
01475
01476 return(ULINT_UNDEFINED);
01477 }
01478
01479 if (space->size == 0 && space->purpose == FIL_TABLESPACE) {
01480 ut_a(id != 0);
01481
01482 ut_a(1 == UT_LIST_GET_LEN(space->chain));
01483
01484 node = UT_LIST_GET_FIRST(space->chain);
01485
01486
01487
01488
01489
01490 fil_node_prepare_for_io(node, fil_system, space);
01491 fil_node_complete_io(node, fil_system, OS_FILE_READ);
01492 }
01493
01494 flags = space->flags;
01495
01496 mutex_exit(&fil_system->mutex);
01497
01498 return(flags);
01499 }
01500
01501
01505 UNIV_INTERN
01506 ulint
01507 fil_space_get_zip_size(
01508
01509 ulint id)
01510 {
01511 ulint flags;
01512
01513 flags = fil_space_get_flags(id);
01514
01515 if (flags && flags != ULINT_UNDEFINED) {
01516
01517 return(dict_table_flags_to_zip_size(flags));
01518 }
01519
01520 return(flags);
01521 }
01522
01523
01527 UNIV_INTERN
01528 ibool
01529 fil_check_adress_in_tablespace(
01530
01531 ulint id,
01532 ulint page_no)
01533 {
01534 if (fil_space_get_size(id) > page_no) {
01535
01536 return(TRUE);
01537 }
01538
01539 return(FALSE);
01540 }
01541
01542
01544 UNIV_INTERN
01545 void
01546 fil_init(
01547
01548 ulint hash_size,
01549 ulint max_n_open)
01550 {
01551 ut_a(fil_system == NULL);
01552
01553 ut_a(hash_size > 0);
01554 ut_a(max_n_open > 0);
01555
01556 void *fil_system_ptr= mem_zalloc(sizeof(fil_system_t));
01557 fil_system = static_cast<fil_system_t *>(fil_system_ptr);
01558
01559 mutex_create(fil_system_mutex_key,
01560 &fil_system->mutex, SYNC_ANY_LATCH);
01561
01562 fil_system->spaces = hash_create(hash_size);
01563 fil_system->name_hash = hash_create(hash_size);
01564
01565 UT_LIST_INIT(fil_system->LRU);
01566
01567 fil_system->max_n_open = max_n_open;
01568 }
01569
01570
01576 UNIV_INTERN
01577 void
01578 fil_open_log_and_system_tablespace_files(void)
01579
01580 {
01581 fil_space_t* space;
01582 fil_node_t* node;
01583
01584 mutex_enter(&fil_system->mutex);
01585
01586 space = UT_LIST_GET_FIRST(fil_system->space_list);
01587
01588 while (space != NULL) {
01589 if (space->purpose != FIL_TABLESPACE || space->id == 0) {
01590 node = UT_LIST_GET_FIRST(space->chain);
01591
01592 while (node != NULL) {
01593 if (!node->open) {
01594 fil_node_open_file(node, fil_system,
01595 space);
01596 }
01597 if (fil_system->max_n_open
01598 < 10 + fil_system->n_open) {
01599 fprintf(stderr,
01600 "InnoDB: Warning: you must"
01601 " raise the value of"
01602 " innodb_open_files in\n"
01603 "InnoDB: my.cnf! Remember that"
01604 " InnoDB keeps all log files"
01605 " and all system\n"
01606 "InnoDB: tablespace files open"
01607 " for the whole time mysqld is"
01608 " running, and\n"
01609 "InnoDB: needs to open also"
01610 " some .ibd files if the"
01611 " file-per-table storage\n"
01612 "InnoDB: model is used."
01613 " Current open files %lu,"
01614 " max allowed"
01615 " open files %lu.\n",
01616 (ulong) fil_system->n_open,
01617 (ulong) fil_system->max_n_open);
01618 }
01619 node = UT_LIST_GET_NEXT(chain, node);
01620 }
01621 }
01622 space = UT_LIST_GET_NEXT(space_list, space);
01623 }
01624
01625 mutex_exit(&fil_system->mutex);
01626 }
01627
01628
01631 UNIV_INTERN
01632 void
01633 fil_close_all_files(void)
01634
01635 {
01636 fil_space_t* space;
01637
01638 mutex_enter(&fil_system->mutex);
01639
01640 space = UT_LIST_GET_FIRST(fil_system->space_list);
01641
01642 while (space != NULL) {
01643 fil_node_t* node;
01644 fil_space_t* prev_space = space;
01645
01646 for (node = UT_LIST_GET_FIRST(space->chain);
01647 node != NULL;
01648 node = UT_LIST_GET_NEXT(chain, node)) {
01649
01650 if (node->open) {
01651 fil_node_close_file(node, fil_system);
01652 }
01653 }
01654
01655 space = UT_LIST_GET_NEXT(space_list, space);
01656
01657 fil_space_free(prev_space->id, FALSE);
01658 }
01659
01660 mutex_exit(&fil_system->mutex);
01661 }
01662
01663
01666 UNIV_INTERN
01667 void
01668 fil_set_max_space_id_if_bigger(
01669
01670 ulint max_id)
01671 {
01672 if (max_id >= SRV_LOG_SPACE_FIRST_ID) {
01673 fprintf(stderr,
01674 "InnoDB: Fatal error: max tablespace id"
01675 " is too high, %lu\n", (ulong) max_id);
01676 ut_error;
01677 }
01678
01679 mutex_enter(&fil_system->mutex);
01680
01681 if (fil_system->max_assigned_id < max_id) {
01682
01683 fil_system->max_assigned_id = max_id;
01684 }
01685
01686 mutex_exit(&fil_system->mutex);
01687 }
01688
01689
01693 static
01694 ulint
01695 fil_write_lsn_and_arch_no_to_file(
01696
01697 ulint sum_of_sizes,
01699 ib_uint64_t lsn,
01700 ulint )
01702 {
01703 byte* buf1;
01704 byte* buf;
01705
01706 buf1 = static_cast<byte *>(mem_alloc(2 * UNIV_PAGE_SIZE));
01707 buf = static_cast<byte *>(ut_align(buf1, UNIV_PAGE_SIZE));
01708
01709 fil_read(TRUE, 0, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
01710
01711 mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN, lsn);
01712
01713 fil_write(TRUE, 0, 0, sum_of_sizes, 0, UNIV_PAGE_SIZE, buf, NULL);
01714
01715 mem_free(buf1);
01716
01717 return(DB_SUCCESS);
01718 }
01719
01720
01724 UNIV_INTERN
01725 ulint
01726 fil_write_flushed_lsn_to_data_files(
01727
01728 ib_uint64_t lsn,
01729 ulint arch_log_no)
01731 {
01732 fil_space_t* space;
01733 fil_node_t* node;
01734 ulint sum_of_sizes;
01735 ulint err;
01736
01737 mutex_enter(&fil_system->mutex);
01738
01739 space = UT_LIST_GET_FIRST(fil_system->space_list);
01740
01741 while (space) {
01742
01743
01744
01745
01746
01747
01748 if (space->purpose == FIL_TABLESPACE
01749 && space->id == 0) {
01750 sum_of_sizes = 0;
01751
01752 node = UT_LIST_GET_FIRST(space->chain);
01753 while (node) {
01754 mutex_exit(&fil_system->mutex);
01755
01756 err = fil_write_lsn_and_arch_no_to_file(
01757 sum_of_sizes, lsn, arch_log_no);
01758 if (err != DB_SUCCESS) {
01759
01760 return(err);
01761 }
01762
01763 mutex_enter(&fil_system->mutex);
01764
01765 sum_of_sizes += node->size;
01766 node = UT_LIST_GET_NEXT(chain, node);
01767 }
01768 }
01769 space = UT_LIST_GET_NEXT(space_list, space);
01770 }
01771
01772 mutex_exit(&fil_system->mutex);
01773
01774 return(DB_SUCCESS);
01775 }
01776
01777
01780 UNIV_INTERN
01781 void
01782 fil_read_flushed_lsn_and_arch_log_no(
01783
01784 os_file_t data_file,
01785 ibool one_read_already,
01788 #ifdef UNIV_LOG_ARCHIVE
01789 ulint* min_arch_log_no,
01790 ulint* max_arch_log_no,
01791 #endif
01792 ib_uint64_t* min_flushed_lsn,
01793 ib_uint64_t* max_flushed_lsn)
01794 {
01795 byte* buf;
01796 byte* buf2;
01797 ib_uint64_t flushed_lsn;
01798
01799 buf2 = static_cast<byte *>(ut_malloc(2 * UNIV_PAGE_SIZE));
01800
01801 buf = static_cast<byte *>(ut_align(buf2, UNIV_PAGE_SIZE));
01802
01803 os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE);
01804
01805 flushed_lsn = mach_read_from_8(buf + FIL_PAGE_FILE_FLUSH_LSN);
01806
01807 ut_free(buf2);
01808
01809 if (!one_read_already) {
01810 *min_flushed_lsn = flushed_lsn;
01811 *max_flushed_lsn = flushed_lsn;
01812 #ifdef UNIV_LOG_ARCHIVE
01813 *min_arch_log_no = arch_log_no;
01814 *max_arch_log_no = arch_log_no;
01815 #endif
01816 return;
01817 }
01818
01819 if (*min_flushed_lsn > flushed_lsn) {
01820 *min_flushed_lsn = flushed_lsn;
01821 }
01822 if (*max_flushed_lsn < flushed_lsn) {
01823 *max_flushed_lsn = flushed_lsn;
01824 }
01825 #ifdef UNIV_LOG_ARCHIVE
01826 if (*min_arch_log_no > arch_log_no) {
01827 *min_arch_log_no = arch_log_no;
01828 }
01829 if (*max_arch_log_no < arch_log_no) {
01830 *max_arch_log_no = arch_log_no;
01831 }
01832 #endif
01833 }
01834
01835
01836
01837 #ifndef UNIV_HOTBACKUP
01838
01842 UNIV_INTERN
01843 ibool
01844 fil_inc_pending_ibuf_merges(
01845
01846 ulint id)
01847 {
01848 fil_space_t* space;
01849
01850 mutex_enter(&fil_system->mutex);
01851
01852 space = fil_space_get_by_id(id);
01853
01854 if (space == NULL) {
01855 fprintf(stderr,
01856 "InnoDB: Error: trying to do ibuf merge to a"
01857 " dropped tablespace %lu\n",
01858 (ulong) id);
01859 }
01860
01861 if (space == NULL || space->stop_ibuf_merges) {
01862 mutex_exit(&fil_system->mutex);
01863
01864 return(TRUE);
01865 }
01866
01867 space->n_pending_ibuf_merges++;
01868
01869 mutex_exit(&fil_system->mutex);
01870
01871 return(FALSE);
01872 }
01873
01874
01876 UNIV_INTERN
01877 void
01878 fil_decr_pending_ibuf_merges(
01879
01880 ulint id)
01881 {
01882 fil_space_t* space;
01883
01884 mutex_enter(&fil_system->mutex);
01885
01886 space = fil_space_get_by_id(id);
01887
01888 if (space == NULL) {
01889 fprintf(stderr,
01890 "InnoDB: Error: decrementing ibuf merge of a"
01891 " dropped tablespace %lu\n",
01892 (ulong) id);
01893 }
01894
01895 if (space != NULL) {
01896 space->n_pending_ibuf_merges--;
01897 }
01898
01899 mutex_exit(&fil_system->mutex);
01900 }
01901 #endif
01902
01903
01905 static
01906 void
01907 fil_create_directory_for_tablename(
01908
01909 const char* name)
01911 {
01912 const char* namend;
01913 char* path;
01914 ulint len;
01915
01916 len = strlen(fil_path_to_mysql_datadir);
01917 namend = strchr(name, '/');
01918 ut_a(namend);
01919 path = static_cast<char *>(mem_alloc(len + (namend - name) + 2));
01920
01921 memcpy(path, fil_path_to_mysql_datadir, len);
01922 path[len] = '/';
01923 memcpy(path + len + 1, name, namend - name);
01924 path[len + (namend - name) + 1] = 0;
01925
01926 srv_normalize_path_for_win(path);
01927
01928 ut_a(os_file_create_directory(path, FALSE));
01929 mem_free(path);
01930 }
01931
01932 #ifndef UNIV_HOTBACKUP
01933
01935 static
01936 void
01937 fil_op_write_log(
01938
01939 ulint type,
01943 ulint space_id,
01944 ulint log_flags,
01946 ulint flags,
01949 const char* name,
01953 const char* new_name,
01956 mtr_t* mtr)
01957 {
01958 byte* log_ptr;
01959 ulint len;
01960
01961 log_ptr = mlog_open(mtr, 11 + 2 + 1);
01962
01963 if (!log_ptr) {
01964
01965
01966 return;
01967 }
01968
01969 log_ptr = mlog_write_initial_log_record_for_file_op(
01970 type, space_id, log_flags, log_ptr, mtr);
01971 if (type == MLOG_FILE_CREATE2) {
01972 mach_write_to_4(log_ptr, flags);
01973 log_ptr += 4;
01974 }
01975
01976
01977
01978 len = strlen(name) + 1;
01979
01980 mach_write_to_2(log_ptr, len);
01981 log_ptr += 2;
01982 mlog_close(mtr, log_ptr);
01983
01984 mlog_catenate_string(mtr, (byte*) name, len);
01985
01986 if (type == MLOG_FILE_RENAME) {
01987 len = strlen(new_name) + 1;
01988 log_ptr = mlog_open(mtr, 2 + len);
01989 ut_a(log_ptr);
01990 mach_write_to_2(log_ptr, len);
01991 log_ptr += 2;
01992 mlog_close(mtr, log_ptr);
01993
01994 mlog_catenate_string(mtr, (byte*) new_name, len);
01995 }
01996 }
01997 #endif
01998
01999
02013 UNIV_INTERN
02014 byte*
02015 fil_op_log_parse_or_replay(
02016
02017 byte* ptr,
02020 byte* end_ptr,
02021 ulint type,
02022 ulint space_id,
02025 ulint log_flags)
02027 {
02028 ulint name_len;
02029 ulint new_name_len;
02030 const char* name;
02031 const char* new_name = NULL;
02032 ulint flags = 0;
02033
02034 if (type == MLOG_FILE_CREATE2) {
02035 if (end_ptr < ptr + 4) {
02036
02037 return(NULL);
02038 }
02039
02040 flags = mach_read_from_4(ptr);
02041 ptr += 4;
02042 }
02043
02044 if (end_ptr < ptr + 2) {
02045
02046 return(NULL);
02047 }
02048
02049 name_len = mach_read_from_2(ptr);
02050
02051 ptr += 2;
02052
02053 if (end_ptr < ptr + name_len) {
02054
02055 return(NULL);
02056 }
02057
02058 name = (const char*) ptr;
02059
02060 ptr += name_len;
02061
02062 if (type == MLOG_FILE_RENAME) {
02063 if (end_ptr < ptr + 2) {
02064
02065 return(NULL);
02066 }
02067
02068 new_name_len = mach_read_from_2(ptr);
02069
02070 ptr += 2;
02071
02072 if (end_ptr < ptr + new_name_len) {
02073
02074 return(NULL);
02075 }
02076
02077 new_name = (const char*) ptr;
02078
02079 ptr += new_name_len;
02080 }
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091 if (!space_id) {
02092
02093 return(ptr);
02094 }
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104 switch (type) {
02105 case MLOG_FILE_DELETE:
02106 if (fil_tablespace_exists_in_mem(space_id)) {
02107 ut_a(fil_delete_tablespace(space_id));
02108 }
02109
02110 break;
02111
02112 case MLOG_FILE_RENAME:
02113
02114
02115
02116
02117
02118 if (fil_tablespace_exists_in_mem(space_id)) {
02119
02120
02121 fil_create_directory_for_tablename(new_name);
02122
02123
02124
02125
02126 if (fil_get_space_id_for_table(new_name)
02127 == ULINT_UNDEFINED) {
02128
02129
02130 if (!fil_rename_tablespace(NULL, space_id,
02131 new_name)) {
02132 ut_error;
02133 }
02134 }
02135 }
02136
02137 break;
02138
02139 case MLOG_FILE_CREATE:
02140 case MLOG_FILE_CREATE2:
02141 if (fil_tablespace_exists_in_mem(space_id)) {
02142
02143 } else if (fil_get_space_id_for_table(name)
02144 != ULINT_UNDEFINED) {
02145
02146 } else if (log_flags & MLOG_FILE_FLAG_TEMP) {
02147
02148 } else {
02149
02150
02151 fil_create_directory_for_tablename(name);
02152
02153 if (fil_create_new_single_table_tablespace(
02154 space_id, name, FALSE, flags,
02155 FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
02156 ut_error;
02157 }
02158 }
02159
02160 break;
02161
02162 default:
02163 ut_error;
02164 }
02165
02166 return(ptr);
02167 }
02168
02169
02173 UNIV_INTERN
02174 ibool
02175 fil_delete_tablespace(
02176
02177 ulint id)
02178 {
02179 ibool success;
02180 fil_space_t* space;
02181 fil_node_t* node;
02182 ulint count = 0;
02183 char* path;
02184
02185 ut_a(id != 0);
02186 stop_ibuf_merges:
02187 mutex_enter(&fil_system->mutex);
02188
02189 space = fil_space_get_by_id(id);
02190
02191 if (space != NULL) {
02192 space->stop_ibuf_merges = TRUE;
02193
02194 if (space->n_pending_ibuf_merges == 0) {
02195 mutex_exit(&fil_system->mutex);
02196
02197 count = 0;
02198
02199 goto try_again;
02200 } else {
02201 if (count > 5000) {
02202 ut_print_timestamp(stderr);
02203 fputs(" InnoDB: Warning: trying to"
02204 " delete tablespace ", stderr);
02205 ut_print_filename(stderr, space->name);
02206 fprintf(stderr, ",\n"
02207 "InnoDB: but there are %lu pending"
02208 " ibuf merges on it.\n"
02209 "InnoDB: Loop %lu.\n",
02210 (ulong) space->n_pending_ibuf_merges,
02211 (ulong) count);
02212 }
02213
02214 mutex_exit(&fil_system->mutex);
02215
02216 os_thread_sleep(20000);
02217 count++;
02218
02219 goto stop_ibuf_merges;
02220 }
02221 }
02222
02223 mutex_exit(&fil_system->mutex);
02224 count = 0;
02225
02226 try_again:
02227 mutex_enter(&fil_system->mutex);
02228
02229 space = fil_space_get_by_id(id);
02230
02231 if (space == NULL) {
02232 ut_print_timestamp(stderr);
02233 fprintf(stderr,
02234 " InnoDB: Error: cannot delete tablespace %lu\n"
02235 "InnoDB: because it is not found in the"
02236 " tablespace memory cache.\n",
02237 (ulong) id);
02238
02239 mutex_exit(&fil_system->mutex);
02240
02241 return(FALSE);
02242 }
02243
02244 ut_a(space);
02245 ut_a(space->n_pending_ibuf_merges == 0);
02246
02247 space->is_being_deleted = TRUE;
02248
02249 ut_a(UT_LIST_GET_LEN(space->chain) == 1);
02250 node = UT_LIST_GET_FIRST(space->chain);
02251
02252 if (space->n_pending_flushes > 0 || node->n_pending > 0) {
02253 if (count > 1000) {
02254 ut_print_timestamp(stderr);
02255 fputs(" InnoDB: Warning: trying to"
02256 " delete tablespace ", stderr);
02257 ut_print_filename(stderr, space->name);
02258 fprintf(stderr, ",\n"
02259 "InnoDB: but there are %lu flushes"
02260 " and %lu pending i/o's on it\n"
02261 "InnoDB: Loop %lu.\n",
02262 (ulong) space->n_pending_flushes,
02263 (ulong) node->n_pending,
02264 (ulong) count);
02265 }
02266 mutex_exit(&fil_system->mutex);
02267 os_thread_sleep(20000);
02268
02269 count++;
02270
02271 goto try_again;
02272 }
02273
02274 path = mem_strdup(space->name);
02275
02276 mutex_exit(&fil_system->mutex);
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288 rw_lock_x_lock(&space->latch);
02289
02290 #ifndef UNIV_HOTBACKUP
02291
02292
02293
02294
02295
02296
02297
02298 buf_LRU_invalidate_tablespace(id);
02299 #endif
02300
02301
02302 mutex_enter(&fil_system->mutex);
02303
02304 success = fil_space_free(id, TRUE);
02305
02306 mutex_exit(&fil_system->mutex);
02307
02308 if (success) {
02309 success = os_file_delete(path);
02310
02311 if (!success) {
02312 success = os_file_delete_if_exists(path);
02313 }
02314 } else {
02315 rw_lock_x_unlock(&space->latch);
02316 }
02317
02318 if (success) {
02319 #ifndef UNIV_HOTBACKUP
02320
02321
02322
02323
02324 mtr_t mtr;
02325
02326
02327
02328 mtr_start(&mtr);
02329
02330 fil_op_write_log(MLOG_FILE_DELETE, id, 0, 0, path, NULL, &mtr);
02331 mtr_commit(&mtr);
02332 #endif
02333 mem_free(path);
02334
02335 return(TRUE);
02336 }
02337
02338 mem_free(path);
02339
02340 return(FALSE);
02341 }
02342
02343
02346 UNIV_INTERN
02347 ibool
02348 fil_tablespace_is_being_deleted(
02349
02350 ulint id)
02351 {
02352 fil_space_t* space;
02353 ibool is_being_deleted;
02354
02355 mutex_enter(&fil_system->mutex);
02356
02357 space = fil_space_get_by_id(id);
02358
02359 ut_a(space != NULL);
02360
02361 is_being_deleted = space->is_being_deleted;
02362
02363 mutex_exit(&fil_system->mutex);
02364
02365 return(is_being_deleted);
02366 }
02367
02368 #ifndef UNIV_HOTBACKUP
02369
02378 UNIV_INTERN
02379 ibool
02380 fil_discard_tablespace(
02381
02382 ulint id)
02383 {
02384 ibool success;
02385
02386 success = fil_delete_tablespace(id);
02387
02388 if (!success) {
02389 fprintf(stderr,
02390 "InnoDB: Warning: cannot delete tablespace %lu"
02391 " in DISCARD TABLESPACE.\n"
02392 "InnoDB: But let us remove the"
02393 " insert buffer entries for this tablespace.\n",
02394 (ulong) id);
02395 }
02396
02397
02398
02399 ibuf_delete_for_discarded_space(id);
02400
02401 return(success);
02402 }
02403 #endif
02404
02405
02408 static
02409 ibool
02410 fil_rename_tablespace_in_mem(
02411
02412 fil_space_t* space,
02413 fil_node_t* node,
02414 const char* path)
02415 {
02416 fil_space_t* space2;
02417 const char* old_name = space->name;
02418
02419 ut_ad(mutex_own(&fil_system->mutex));
02420
02421 space2 = fil_space_get_by_name(old_name);
02422 if (space != space2) {
02423 fputs("InnoDB: Error: cannot find ", stderr);
02424 ut_print_filename(stderr, old_name);
02425 fputs(" in tablespace memory cache\n", stderr);
02426
02427 return(FALSE);
02428 }
02429
02430 space2 = fil_space_get_by_name(path);
02431 if (space2 != NULL) {
02432 fputs("InnoDB: Error: ", stderr);
02433 ut_print_filename(stderr, path);
02434 fputs(" is already in tablespace memory cache\n", stderr);
02435
02436 return(FALSE);
02437 }
02438
02439 HASH_DELETE(fil_space_t, name_hash, fil_system->name_hash,
02440 ut_fold_string(space->name), space);
02441 mem_free(space->name);
02442 mem_free(node->name);
02443
02444 space->name = mem_strdup(path);
02445 node->name = mem_strdup(path);
02446
02447 HASH_INSERT(fil_space_t, name_hash, fil_system->name_hash,
02448 ut_fold_string(path), space);
02449 return(TRUE);
02450 }
02451
02452
02456 static
02457 char*
02458 fil_make_ibd_name(
02459
02460 const char* name,
02462 ibool is_temp)
02463 {
02464 ulint namelen = strlen(name);
02465 ulint dirlen = strlen(fil_path_to_mysql_datadir);
02466 char* filename = static_cast<char *>(mem_alloc(namelen + dirlen + sizeof "/.ibd"));
02467
02468 if (is_temp) {
02469 memcpy(filename, name, namelen);
02470 memcpy(filename + namelen, ".ibd", sizeof ".ibd");
02471 } else {
02472 memcpy(filename, fil_path_to_mysql_datadir, dirlen);
02473 filename[dirlen] = '/';
02474
02475 memcpy(filename + dirlen + 1, name, namelen);
02476 memcpy(filename + dirlen + namelen + 1, ".ibd", sizeof ".ibd");
02477 }
02478
02479 srv_normalize_path_for_win(filename);
02480
02481 return(filename);
02482 }
02483
02484
02488 UNIV_INTERN
02489 ibool
02490 fil_rename_tablespace(
02491
02492 const char* old_name,
02496 ulint id,
02497 const char* new_name)
02500 {
02501 ibool success;
02502 fil_space_t* space;
02503 fil_node_t* node;
02504 ulint count = 0;
02505 char* path;
02506 ibool old_name_was_specified = TRUE;
02507 char* old_path;
02508
02509 ut_a(id != 0);
02510
02511 if (old_name == NULL) {
02512 old_name = "(name not specified)";
02513 old_name_was_specified = FALSE;
02514 }
02515 retry:
02516 count++;
02517
02518 if (count > 1000) {
02519 ut_print_timestamp(stderr);
02520 fputs(" InnoDB: Warning: problems renaming ", stderr);
02521 ut_print_filename(stderr, old_name);
02522 fputs(" to ", stderr);
02523 ut_print_filename(stderr, new_name);
02524 fprintf(stderr, ", %lu iterations\n", (ulong) count);
02525 }
02526
02527 mutex_enter(&fil_system->mutex);
02528
02529 space = fil_space_get_by_id(id);
02530
02531 if (space == NULL) {
02532 fprintf(stderr,
02533 "InnoDB: Error: cannot find space id %lu"
02534 " in the tablespace memory cache\n"
02535 "InnoDB: though the table ", (ulong) id);
02536 ut_print_filename(stderr, old_name);
02537 fputs(" in a rename operation should have that id\n", stderr);
02538 mutex_exit(&fil_system->mutex);
02539
02540 return(FALSE);
02541 }
02542
02543 if (count > 25000) {
02544 space->stop_ios = FALSE;
02545 mutex_exit(&fil_system->mutex);
02546
02547 return(FALSE);
02548 }
02549
02550
02551
02552
02553
02554 space->stop_ios = TRUE;
02555
02556 ut_a(UT_LIST_GET_LEN(space->chain) == 1);
02557 node = UT_LIST_GET_FIRST(space->chain);
02558
02559 if (node->n_pending > 0 || node->n_pending_flushes > 0) {
02560
02561
02562
02563 mutex_exit(&fil_system->mutex);
02564
02565 os_thread_sleep(20000);
02566
02567 goto retry;
02568
02569 } else if (node->modification_counter > node->flush_counter) {
02570
02571
02572 mutex_exit(&fil_system->mutex);
02573
02574 os_thread_sleep(20000);
02575
02576 fil_flush(id);
02577
02578 goto retry;
02579
02580 } else if (node->open) {
02581
02582
02583 fil_node_close_file(node, fil_system);
02584 }
02585
02586
02587
02588 if (old_name_was_specified) {
02589 old_path = fil_make_ibd_name(old_name, FALSE);
02590
02591 ut_a(strcmp(space->name, old_path) == 0);
02592 ut_a(strcmp(node->name, old_path) == 0);
02593 } else {
02594 old_path = mem_strdup(space->name);
02595 }
02596
02597
02598 path = fil_make_ibd_name(new_name, FALSE);
02599 success = fil_rename_tablespace_in_mem(space, node, path);
02600
02601 if (success) {
02602 success = os_file_rename(innodb_file_data_key, old_path, path);
02603
02604 if (!success) {
02605
02606
02607
02608 ut_a(fil_rename_tablespace_in_mem(space, node,
02609 old_path));
02610 }
02611 }
02612
02613 mem_free(path);
02614 mem_free(old_path);
02615
02616 space->stop_ios = FALSE;
02617
02618 mutex_exit(&fil_system->mutex);
02619
02620 #ifndef UNIV_HOTBACKUP
02621 if (success) {
02622 mtr_t mtr;
02623
02624 mtr_start(&mtr);
02625
02626 fil_op_write_log(MLOG_FILE_RENAME, id, 0, 0, old_name, new_name,
02627 &mtr);
02628 mtr_commit(&mtr);
02629 }
02630 #endif
02631 return(success);
02632 }
02633
02634
02641 UNIV_INTERN
02642 ulint
02643 fil_create_new_single_table_tablespace(
02644
02645 ulint space_id,
02646 const char* tablename,
02650 ibool is_temp,
02652 ulint flags,
02653 ulint size)
02656 {
02657 os_file_t file;
02658 ibool ret;
02659 ulint err;
02660 byte* buf2;
02661 byte* page;
02662 ibool success;
02663 char* path;
02664
02665 ut_a(space_id > 0);
02666 ut_a(space_id < SRV_LOG_SPACE_FIRST_ID);
02667 ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
02668
02669
02670
02671
02672
02673
02674 ut_a(flags != DICT_TF_COMPACT);
02675 ut_a(!(flags & (~0UL << DICT_TF_BITS)));
02676
02677 path = fil_make_ibd_name(tablename, is_temp);
02678
02679 file = os_file_create(innodb_file_data_key, path,
02680 OS_FILE_CREATE, OS_FILE_NORMAL,
02681 OS_DATA_FILE, &ret);
02682 if (ret == FALSE) {
02683 ut_print_timestamp(stderr);
02684 fputs(" InnoDB: Error creating file ", stderr);
02685 ut_print_filename(stderr, path);
02686 fputs(".\n", stderr);
02687
02688
02689
02690 err = os_file_get_last_error(TRUE);
02691
02692 if (err == OS_FILE_ALREADY_EXISTS) {
02693 fputs("InnoDB: The file already exists though"
02694 " the corresponding table did not\n"
02695 "InnoDB: exist in the InnoDB data dictionary."
02696 " Have you moved InnoDB\n"
02697 "InnoDB: .ibd files around without using the"
02698 " SQL commands\n"
02699 "InnoDB: DISCARD TABLESPACE and"
02700 " IMPORT TABLESPACE, or did\n"
02701 "InnoDB: mysqld crash in the middle of"
02702 " CREATE TABLE? You can\n"
02703 "InnoDB: resolve the problem by"
02704 " removing the file ", stderr);
02705 ut_print_filename(stderr, path);
02706 fputs("\n"
02707 "InnoDB: under the 'datadir' of MySQL.\n",
02708 stderr);
02709
02710 mem_free(path);
02711 return(DB_TABLESPACE_ALREADY_EXISTS);
02712 }
02713
02714 if (err == OS_FILE_DISK_FULL) {
02715
02716 mem_free(path);
02717 return(DB_OUT_OF_FILE_SPACE);
02718 }
02719
02720 mem_free(path);
02721 return(DB_ERROR);
02722 }
02723
02724 ret = os_file_set_size(path, file, size * UNIV_PAGE_SIZE, 0);
02725
02726 if (!ret) {
02727 err = DB_OUT_OF_FILE_SPACE;
02728 error_exit:
02729 os_file_close(file);
02730 error_exit2:
02731 os_file_delete(path);
02732
02733 mem_free(path);
02734 return(err);
02735 }
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748 buf2 = static_cast<byte *>(ut_malloc(3 * UNIV_PAGE_SIZE));
02749
02750 page = static_cast<byte *>(ut_align(buf2, UNIV_PAGE_SIZE));
02751
02752 memset(page, '\0', UNIV_PAGE_SIZE);
02753
02754 fsp_header_init_fields(page, space_id, flags);
02755 mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
02756
02757 if (!(flags & DICT_TF_ZSSIZE_MASK)) {
02758 buf_flush_init_for_writing(page, NULL, 0);
02759 ret = os_file_write(path, file, page, 0, 0, UNIV_PAGE_SIZE);
02760 } else {
02761 page_zip_des_t page_zip;
02762 ulint zip_size;
02763
02764 zip_size = ((PAGE_ZIP_MIN_SIZE >> 1)
02765 << ((flags & DICT_TF_ZSSIZE_MASK)
02766 >> DICT_TF_ZSSIZE_SHIFT));
02767
02768 page_zip_set_size(&page_zip, zip_size);
02769 page_zip.data = page + UNIV_PAGE_SIZE;
02770 #ifdef UNIV_DEBUG
02771 page_zip.m_start =
02772 #endif
02773 page_zip.m_end = page_zip.m_nonempty =
02774 page_zip.n_blobs = 0;
02775 buf_flush_init_for_writing(page, &page_zip, 0);
02776 ret = os_file_write(path, file, page_zip.data, 0, 0, zip_size);
02777 }
02778
02779 ut_free(buf2);
02780
02781 if (!ret) {
02782 fputs("InnoDB: Error: could not write the first page"
02783 " to tablespace ", stderr);
02784 ut_print_filename(stderr, path);
02785 putc('\n', stderr);
02786 err = DB_ERROR;
02787 goto error_exit;
02788 }
02789
02790 ret = os_file_flush(file);
02791
02792 if (!ret) {
02793 fputs("InnoDB: Error: file flush of tablespace ", stderr);
02794 ut_print_filename(stderr, path);
02795 fputs(" failed\n", stderr);
02796 err = DB_ERROR;
02797 goto error_exit;
02798 }
02799
02800 os_file_close(file);
02801
02802 success = fil_space_create(path, space_id, flags, FIL_TABLESPACE);
02803
02804 if (!success) {
02805 err = DB_ERROR;
02806 goto error_exit2;
02807 }
02808
02809 fil_node_create(path, size, space_id, FALSE);
02810
02811 #ifndef UNIV_HOTBACKUP
02812 {
02813 mtr_t mtr;
02814
02815 mtr_start(&mtr);
02816
02817 fil_op_write_log(flags
02818 ? MLOG_FILE_CREATE2
02819 : MLOG_FILE_CREATE,
02820 space_id,
02821 is_temp ? MLOG_FILE_FLAG_TEMP : 0,
02822 flags,
02823 tablename, NULL, &mtr);
02824
02825 mtr_commit(&mtr);
02826 }
02827 #endif
02828 mem_free(path);
02829 return(DB_SUCCESS);
02830 }
02831
02832 #ifndef UNIV_HOTBACKUP
02833
02843 UNIV_INTERN
02844 ibool
02845 fil_reset_too_high_lsns(
02846
02847 const char* name,
02849 ib_uint64_t current_lsn)
02852 {
02853 os_file_t file;
02854 char* filepath;
02855 byte* page;
02856 byte* buf2;
02857 ib_uint64_t flush_lsn;
02858 ulint space_id;
02859 ib_int64_t file_size;
02860 ib_int64_t offset;
02861 ulint zip_size;
02862 ibool success;
02863 page_zip_des_t page_zip;
02864
02865 filepath = fil_make_ibd_name(name, FALSE);
02866
02867 file = os_file_create_simple_no_error_handling(
02868 innodb_file_data_key, filepath, OS_FILE_OPEN,
02869 OS_FILE_READ_WRITE, &success);
02870 if (!success) {
02871
02872 os_file_get_last_error(TRUE);
02873
02874 ut_print_timestamp(stderr);
02875
02876 fputs(" InnoDB: Error: trying to open a table,"
02877 " but could not\n"
02878 "InnoDB: open the tablespace file ", stderr);
02879 ut_print_filename(stderr, filepath);
02880 fputs("!\n", stderr);
02881 mem_free(filepath);
02882
02883 return(FALSE);
02884 }
02885
02886
02887
02888 buf2 = static_cast<byte *>(ut_malloc(3 * UNIV_PAGE_SIZE));
02889
02890 page = static_cast<byte *>(ut_align(buf2, UNIV_PAGE_SIZE));
02891
02892 success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
02893 if (!success) {
02894
02895 goto func_exit;
02896 }
02897
02898
02899
02900 flush_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
02901
02902 if (current_lsn >= flush_lsn) {
02903
02904 success = TRUE;
02905
02906 goto func_exit;
02907 }
02908
02909 space_id = fsp_header_get_space_id(page);
02910 zip_size = fsp_header_get_zip_size(page);
02911
02912 page_zip_des_init(&page_zip);
02913 page_zip_set_size(&page_zip, zip_size);
02914 if (zip_size) {
02915 page_zip.data = page + UNIV_PAGE_SIZE;
02916 }
02917
02918 ut_print_timestamp(stderr);
02919 fprintf(stderr,
02920 " InnoDB: Flush lsn in the tablespace file %lu"
02921 " to be imported\n"
02922 "InnoDB: is %"PRIu64", which exceeds current"
02923 " system lsn %"PRIu64".\n"
02924 "InnoDB: We reset the lsn's in the file ",
02925 (ulong) space_id,
02926 flush_lsn, current_lsn);
02927 ut_print_filename(stderr, filepath);
02928 fputs(".\n", stderr);
02929
02930 ut_a(ut_is_2pow(zip_size));
02931 ut_a(zip_size <= UNIV_PAGE_SIZE);
02932
02933
02934
02935
02936 file_size = os_file_get_size_as_iblonglong(file);
02937
02938 for (offset = 0; offset < file_size;
02939 offset += zip_size ? zip_size : UNIV_PAGE_SIZE) {
02940 success = os_file_read(file, page,
02941 (ulint)(offset & 0xFFFFFFFFUL),
02942 (ulint)(offset >> 32),
02943 zip_size ? zip_size : UNIV_PAGE_SIZE);
02944 if (!success) {
02945
02946 goto func_exit;
02947 }
02948 if (mach_read_from_8(page + FIL_PAGE_LSN) > current_lsn) {
02949
02950
02951 if (zip_size) {
02952 memcpy(page_zip.data, page, zip_size);
02953 buf_flush_init_for_writing(
02954 page, &page_zip, current_lsn);
02955 success = os_file_write(
02956 filepath, file, page_zip.data,
02957 (ulint) offset & 0xFFFFFFFFUL,
02958 (ulint) (offset >> 32), zip_size);
02959 } else {
02960 buf_flush_init_for_writing(
02961 page, NULL, current_lsn);
02962 success = os_file_write(
02963 filepath, file, page,
02964 (ulint)(offset & 0xFFFFFFFFUL),
02965 (ulint)(offset >> 32),
02966 UNIV_PAGE_SIZE);
02967 }
02968
02969 if (!success) {
02970
02971 goto func_exit;
02972 }
02973 }
02974 }
02975
02976 success = os_file_flush(file);
02977 if (!success) {
02978
02979 goto func_exit;
02980 }
02981
02982
02983 success = os_file_read(file, page, 0, 0,
02984 zip_size ? zip_size : UNIV_PAGE_SIZE);
02985 if (!success) {
02986
02987 goto func_exit;
02988 }
02989
02990 mach_write_to_8(page + FIL_PAGE_FILE_FLUSH_LSN, current_lsn);
02991
02992 success = os_file_write(filepath, file, page, 0, 0,
02993 zip_size ? zip_size : UNIV_PAGE_SIZE);
02994 if (!success) {
02995
02996 goto func_exit;
02997 }
02998 success = os_file_flush(file);
02999 func_exit:
03000 os_file_close(file);
03001 ut_free(buf2);
03002 mem_free(filepath);
03003
03004 return(success);
03005 }
03006
03007
03017 UNIV_INTERN
03018 ibool
03019 fil_open_single_table_tablespace(
03020
03021 ibool check_space_id,
03028 ulint id,
03029 ulint flags,
03030 const char* name)
03032 {
03033 os_file_t file;
03034 char* filepath;
03035 ibool success;
03036 byte* buf2;
03037 byte* page;
03038 ulint space_id;
03039 ulint space_flags;
03040
03041 filepath = fil_make_ibd_name(name, FALSE);
03042
03043
03044
03045
03046
03047
03048
03049 ut_a(flags != DICT_TF_COMPACT);
03050 ut_a(!(flags & (~0UL << DICT_TF_BITS)));
03051
03052 file = os_file_create_simple_no_error_handling(
03053 innodb_file_data_key, filepath, OS_FILE_OPEN,
03054 OS_FILE_READ_ONLY, &success);
03055 if (!success) {
03056
03057 os_file_get_last_error(TRUE);
03058
03059 ut_print_timestamp(stderr);
03060
03061 fputs(" InnoDB: Error: trying to open a table,"
03062 " but could not\n"
03063 "InnoDB: open the tablespace file ", stderr);
03064 ut_print_filename(stderr, filepath);
03065 fputs("!\n"
03066 "InnoDB: Have you moved InnoDB .ibd files around"
03067 " without using the\n"
03068 "InnoDB: commands DISCARD TABLESPACE and"
03069 " IMPORT TABLESPACE?\n"
03070 "InnoDB: It is also possible that this is"
03071 " a temporary table #sql...,\n"
03072 "InnoDB: and MySQL removed the .ibd file for this.\n"
03073 "InnoDB: Please refer to\n"
03074 "InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n"
03075 "InnoDB: for how to resolve the issue.\n", stderr);
03076
03077 mem_free(filepath);
03078
03079 return(FALSE);
03080 }
03081
03082 if (!check_space_id) {
03083 space_id = id;
03084
03085 goto skip_check;
03086 }
03087
03088
03089
03090 buf2 = static_cast<byte *>(ut_malloc(2 * UNIV_PAGE_SIZE));
03091
03092 page = static_cast<byte *>(ut_align(buf2, UNIV_PAGE_SIZE));
03093
03094 success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
03095
03096
03097
03098 space_id = fsp_header_get_space_id(page);
03099 space_flags = fsp_header_get_flags(page);
03100
03101 ut_free(buf2);
03102
03103 if (UNIV_UNLIKELY(space_id != id
03104 || space_flags != (flags & ~(~0 << DICT_TF_BITS)))) {
03105 ut_print_timestamp(stderr);
03106
03107 fputs(" InnoDB: Error: tablespace id and flags in file ",
03108 stderr);
03109 ut_print_filename(stderr, filepath);
03110 fprintf(stderr, " are %lu and %lu, but in the InnoDB\n"
03111 "InnoDB: data dictionary they are %lu and %lu.\n"
03112 "InnoDB: Have you moved InnoDB .ibd files"
03113 " around without using the\n"
03114 "InnoDB: commands DISCARD TABLESPACE and"
03115 " IMPORT TABLESPACE?\n"
03116 "InnoDB: Please refer to\n"
03117 "InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n"
03118 "InnoDB: for how to resolve the issue.\n",
03119 (ulong) space_id, (ulong) space_flags,
03120 (ulong) id, (ulong) flags);
03121
03122 success = FALSE;
03123
03124 goto func_exit;
03125 }
03126
03127 skip_check:
03128 success = fil_space_create(filepath, space_id, flags, FIL_TABLESPACE);
03129
03130 if (!success) {
03131 goto func_exit;
03132 }
03133
03134
03135
03136
03137 fil_node_create(filepath, 0, space_id, FALSE);
03138 func_exit:
03139 os_file_close(file);
03140 mem_free(filepath);
03141
03142 return(success);
03143 }
03144 #endif
03145
03146 #ifdef UNIV_HOTBACKUP
03147
03151 static
03152 char*
03153 fil_make_ibbackup_old_name(
03154
03155 const char* name)
03156 {
03157 static const char suffix[] = "_ibbackup_old_vers_";
03158 ulint len = strlen(name);
03159 char* path = mem_alloc(len + (15 + sizeof suffix));
03160
03161 memcpy(path, name, len);
03162 memcpy(path + len, suffix, (sizeof suffix) - 1);
03163 ut_sprintf_timestamp_without_extra_chars(path + len + sizeof suffix);
03164 return(path);
03165 }
03166 #endif
03167
03168
03171 static
03172 void
03173 fil_load_single_table_tablespace(
03174
03175 const char* dbname,
03176 const char* filename)
03178 {
03179 os_file_t file;
03180 char* filepath;
03181 ibool success;
03182 byte* buf2;
03183 byte* page;
03184 ulint space_id;
03185 ulint flags;
03186 ulint size_low;
03187 ulint size_high;
03188 uint64_t size;
03189 #ifdef UNIV_HOTBACKUP
03190 fil_space_t* space;
03191 #endif
03192 filepath = static_cast<char *>(mem_alloc(strlen(dbname) + strlen(filename)
03193 + strlen(fil_path_to_mysql_datadir) + 3));
03194
03195 sprintf(filepath, "%s/%s/%s", fil_path_to_mysql_datadir, dbname,
03196 filename);
03197 srv_normalize_path_for_win(filepath);
03198 #ifdef __WIN__
03199 # ifndef UNIV_HOTBACKUP
03200
03201
03202
03203
03204
03205
03206 dict_casedn_str(filepath);
03207 # endif
03208 #endif
03209 file = os_file_create_simple_no_error_handling(
03210 innodb_file_data_key, filepath, OS_FILE_OPEN,
03211 OS_FILE_READ_ONLY, &success);
03212 if (!success) {
03213
03214 os_file_get_last_error(TRUE);
03215
03216 fprintf(stderr,
03217 "InnoDB: Error: could not open single-table tablespace"
03218 " file\n"
03219 "InnoDB: %s!\n"
03220 "InnoDB: We do not continue the crash recovery,"
03221 " because the table may become\n"
03222 "InnoDB: corrupt if we cannot apply the log records"
03223 " in the InnoDB log to it.\n"
03224 "InnoDB: To fix the problem and start mysqld:\n"
03225 "InnoDB: 1) If there is a permission problem"
03226 " in the file and mysqld cannot\n"
03227 "InnoDB: open the file, you should"
03228 " modify the permissions.\n"
03229 "InnoDB: 2) If the table is not needed, or you can"
03230 " restore it from a backup,\n"
03231 "InnoDB: then you can remove the .ibd file,"
03232 " and InnoDB will do a normal\n"
03233 "InnoDB: crash recovery and ignore that table.\n"
03234 "InnoDB: 3) If the file system or the"
03235 " disk is broken, and you cannot remove\n"
03236 "InnoDB: the .ibd file, you can set"
03237 " innodb_force_recovery > 0 in my.cnf\n"
03238 "InnoDB: and force InnoDB to continue crash"
03239 " recovery here.\n", filepath);
03240
03241 mem_free(filepath);
03242
03243 if (srv_force_recovery > 0) {
03244 fprintf(stderr,
03245 "InnoDB: innodb_force_recovery"
03246 " was set to %lu. Continuing crash recovery\n"
03247 "InnoDB: even though we cannot access"
03248 " the .ibd file of this table.\n",
03249 srv_force_recovery);
03250 return;
03251 }
03252
03253 exit(1);
03254 }
03255
03256 success = os_file_get_size(file, &size_low, &size_high);
03257
03258 if (!success) {
03259
03260 os_file_get_last_error(TRUE);
03261
03262 fprintf(stderr,
03263 "InnoDB: Error: could not measure the size"
03264 " of single-table tablespace file\n"
03265 "InnoDB: %s!\n"
03266 "InnoDB: We do not continue crash recovery,"
03267 " because the table will become\n"
03268 "InnoDB: corrupt if we cannot apply the log records"
03269 " in the InnoDB log to it.\n"
03270 "InnoDB: To fix the problem and start mysqld:\n"
03271 "InnoDB: 1) If there is a permission problem"
03272 " in the file and mysqld cannot\n"
03273 "InnoDB: access the file, you should"
03274 " modify the permissions.\n"
03275 "InnoDB: 2) If the table is not needed,"
03276 " or you can restore it from a backup,\n"
03277 "InnoDB: then you can remove the .ibd file,"
03278 " and InnoDB will do a normal\n"
03279 "InnoDB: crash recovery and ignore that table.\n"
03280 "InnoDB: 3) If the file system or the disk is broken,"
03281 " and you cannot remove\n"
03282 "InnoDB: the .ibd file, you can set"
03283 " innodb_force_recovery > 0 in my.cnf\n"
03284 "InnoDB: and force InnoDB to continue"
03285 " crash recovery here.\n", filepath);
03286
03287 os_file_close(file);
03288 mem_free(filepath);
03289
03290 if (srv_force_recovery > 0) {
03291 fprintf(stderr,
03292 "InnoDB: innodb_force_recovery"
03293 " was set to %lu. Continuing crash recovery\n"
03294 "InnoDB: even though we cannot access"
03295 " the .ibd file of this table.\n",
03296 srv_force_recovery);
03297 return;
03298 }
03299
03300 exit(1);
03301 }
03302
03303
03304
03305
03306
03307
03308
03309 size = (((ib_int64_t)size_high) << 32) + (ib_int64_t)size_low;
03310 #ifndef UNIV_HOTBACKUP
03311 if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
03312 fprintf(stderr,
03313 "InnoDB: Error: the size of single-table tablespace"
03314 " file %s\n"
03315 "InnoDB: is only %lu %lu, should be at least %lu!",
03316 filepath,
03317 (ulong) size_high,
03318 (ulong) size_low, (ulong) (4 * UNIV_PAGE_SIZE));
03319 os_file_close(file);
03320 mem_free(filepath);
03321
03322 return;
03323 }
03324 #endif
03325
03326
03327 buf2 = static_cast<byte *>(ut_malloc(2 * UNIV_PAGE_SIZE));
03328
03329 page = static_cast<byte *>(ut_align(buf2, UNIV_PAGE_SIZE));
03330
03331 if (size >= FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
03332 success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
03333
03334
03335
03336 space_id = fsp_header_get_space_id(page);
03337 flags = fsp_header_get_flags(page);
03338 } else {
03339 space_id = ULINT_UNDEFINED;
03340 flags = 0;
03341 }
03342
03343 #ifndef UNIV_HOTBACKUP
03344 if (space_id == ULINT_UNDEFINED || space_id == 0) {
03345 fprintf(stderr,
03346 "InnoDB: Error: tablespace id %lu in file %s"
03347 " is not sensible\n",
03348 (ulong) space_id,
03349 filepath);
03350 goto func_exit;
03351 }
03352 #else
03353 if (space_id == ULINT_UNDEFINED || space_id == 0) {
03354 char* new_path;
03355
03356 fprintf(stderr,
03357 "InnoDB: Renaming tablespace %s of id %lu,\n"
03358 "InnoDB: to %s_ibbackup_old_vers_<timestamp>\n"
03359 "InnoDB: because its size %" PRId64 " is too small"
03360 " (< 4 pages 16 kB each),\n"
03361 "InnoDB: or the space id in the file header"
03362 " is not sensible.\n"
03363 "InnoDB: This can happen in an ibbackup run,"
03364 " and is not dangerous.\n",
03365 filepath, space_id, filepath, size);
03366 os_file_close(file);
03367
03368 new_path = fil_make_ibbackup_old_name(filepath);
03369 ut_a(os_file_rename(innodb_file_data_key, filepath, new_path));
03370
03371 ut_free(buf2);
03372 mem_free(filepath);
03373 mem_free(new_path);
03374
03375 return;
03376 }
03377
03378
03379
03380
03381
03382
03383
03384
03385 mutex_enter(&fil_system->mutex);
03386
03387 space = fil_space_get_by_id(space_id);
03388
03389 if (space) {
03390 char* new_path;
03391
03392 fprintf(stderr,
03393 "InnoDB: Renaming tablespace %s of id %lu,\n"
03394 "InnoDB: to %s_ibbackup_old_vers_<timestamp>\n"
03395 "InnoDB: because space %s with the same id\n"
03396 "InnoDB: was scanned earlier. This can happen"
03397 " if you have renamed tables\n"
03398 "InnoDB: during an ibbackup run.\n",
03399 filepath, space_id, filepath,
03400 space->name);
03401 os_file_close(file);
03402
03403 new_path = fil_make_ibbackup_old_name(filepath);
03404
03405 mutex_exit(&fil_system->mutex);
03406
03407 ut_a(os_file_rename(innodb_file_data_key, filepath, new_path));
03408
03409 ut_free(buf2);
03410 mem_free(filepath);
03411 mem_free(new_path);
03412
03413 return;
03414 }
03415 mutex_exit(&fil_system->mutex);
03416 #endif
03417 success = fil_space_create(filepath, space_id, flags, FIL_TABLESPACE);
03418
03419 if (!success) {
03420
03421 if (srv_force_recovery > 0) {
03422 fprintf(stderr,
03423 "InnoDB: innodb_force_recovery"
03424 " was set to %lu. Continuing crash recovery\n"
03425 "InnoDB: even though the tablespace creation"
03426 " of this table failed.\n",
03427 srv_force_recovery);
03428 goto func_exit;
03429 }
03430
03431 exit(1);
03432 }
03433
03434
03435
03436
03437
03438 fil_node_create(filepath, 0, space_id, FALSE);
03439 func_exit:
03440 os_file_close(file);
03441 ut_free(buf2);
03442 mem_free(filepath);
03443 }
03444
03445
03451 int
03452 fil_file_readdir_next_file(
03453
03454 ulint* err,
03456 const char* dirname,
03457 os_file_dir_t dir,
03458 os_file_stat_t* info)
03459 {
03460 ulint i;
03461 int ret;
03462
03463 for (i = 0; i < 100; i++) {
03464 ret = os_file_readdir_next_file(dirname, dir, info);
03465
03466 if (ret != -1) {
03467
03468 return(ret);
03469 }
03470
03471 fprintf(stderr,
03472 "InnoDB: Error: os_file_readdir_next_file()"
03473 " returned -1 in\n"
03474 "InnoDB: directory %s\n"
03475 "InnoDB: Crash recovery may have failed"
03476 " for some .ibd files!\n", dirname);
03477
03478 *err = DB_ERROR;
03479 }
03480
03481 return(-1);
03482 }
03483
03484
03492 UNIV_INTERN
03493 ulint
03494 fil_load_single_table_tablespaces(void)
03495
03496 {
03497 int ret;
03498 char* dbpath = NULL;
03499 ulint dbpath_len = 100;
03500 os_file_dir_t dir;
03501 os_file_dir_t dbdir;
03502 os_file_stat_t dbinfo;
03503 os_file_stat_t fileinfo;
03504 ulint err = DB_SUCCESS;
03505
03506
03507
03508 dir = os_file_opendir(fil_path_to_mysql_datadir, TRUE);
03509
03510 if (dir == NULL) {
03511
03512 return(DB_ERROR);
03513 }
03514
03515 dbpath = static_cast<char *>(mem_alloc(dbpath_len));
03516
03517
03518
03519
03520 ret = fil_file_readdir_next_file(&err, fil_path_to_mysql_datadir, dir,
03521 &dbinfo);
03522 while (ret == 0) {
03523 ulint len;
03524
03525
03526 if (dbinfo.type == OS_FILE_TYPE_FILE
03527 || dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
03528
03529 goto next_datadir_item;
03530 }
03531
03532
03533
03534
03535 len = strlen(fil_path_to_mysql_datadir)
03536 + strlen (dbinfo.name) + 2;
03537 if (len > dbpath_len) {
03538 dbpath_len = len;
03539
03540 if (dbpath) {
03541 mem_free(dbpath);
03542 }
03543
03544 dbpath = static_cast<char *>(mem_alloc(dbpath_len));
03545 }
03546 sprintf(dbpath, "%s/%s", fil_path_to_mysql_datadir,
03547 dbinfo.name);
03548 srv_normalize_path_for_win(dbpath);
03549
03550 dbdir = os_file_opendir(dbpath, FALSE);
03551
03552 if (dbdir != NULL) {
03553
03554
03555
03556
03557
03558 ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
03559 &fileinfo);
03560 while (ret == 0) {
03561
03562
03563
03564 if (fileinfo.type == OS_FILE_TYPE_DIR) {
03565
03566 goto next_file_item;
03567 }
03568
03569
03570 if (strlen(fileinfo.name) > 4
03571 && 0 == strcmp(fileinfo.name
03572 + strlen(fileinfo.name) - 4,
03573 ".ibd")) {
03574
03575
03576 fil_load_single_table_tablespace(
03577 dbinfo.name, fileinfo.name);
03578 }
03579 next_file_item:
03580 ret = fil_file_readdir_next_file(&err,
03581 dbpath, dbdir,
03582 &fileinfo);
03583 }
03584
03585 if (0 != os_file_closedir(dbdir)) {
03586 fputs("InnoDB: Warning: could not"
03587 " close database directory ", stderr);
03588 ut_print_filename(stderr, dbpath);
03589 putc('\n', stderr);
03590
03591 err = DB_ERROR;
03592 }
03593 }
03594
03595 next_datadir_item:
03596 ret = fil_file_readdir_next_file(&err,
03597 fil_path_to_mysql_datadir,
03598 dir, &dbinfo);
03599 }
03600
03601 mem_free(dbpath);
03602
03603 if (0 != os_file_closedir(dir)) {
03604 fprintf(stderr,
03605 "InnoDB: Error: could not close MySQL datadir\n");
03606
03607 return(DB_ERROR);
03608 }
03609
03610 return(err);
03611 }
03612
03613
03617 UNIV_INTERN
03618 ibool
03619 fil_tablespace_deleted_or_being_deleted_in_mem(
03620
03621 ulint id,
03622 ib_int64_t version)
03625 {
03626 fil_space_t* space;
03627
03628 ut_ad(fil_system);
03629
03630 mutex_enter(&fil_system->mutex);
03631
03632 space = fil_space_get_by_id(id);
03633
03634 if (space == NULL || space->is_being_deleted) {
03635 mutex_exit(&fil_system->mutex);
03636
03637 return(TRUE);
03638 }
03639
03640 if (version != ((ib_int64_t)-1)
03641 && space->tablespace_version != version) {
03642 mutex_exit(&fil_system->mutex);
03643
03644 return(TRUE);
03645 }
03646
03647 mutex_exit(&fil_system->mutex);
03648
03649 return(FALSE);
03650 }
03651
03652
03655 UNIV_INTERN
03656 ibool
03657 fil_tablespace_exists_in_mem(
03658
03659 ulint id)
03660 {
03661 fil_space_t* space;
03662
03663 ut_ad(fil_system);
03664
03665 mutex_enter(&fil_system->mutex);
03666
03667 space = fil_space_get_by_id(id);
03668
03669 mutex_exit(&fil_system->mutex);
03670
03671 return(space != NULL);
03672 }
03673
03674
03679 UNIV_INTERN
03680 ibool
03681 fil_space_for_table_exists_in_mem(
03682
03683 ulint id,
03684 const char* name,
03687 ibool is_temp,
03689 ibool mark_space,
03695 ibool print_error_if_does_not_exist)
03700 {
03701 fil_space_t* tablespace;
03702 fil_space_t* space;
03703 char* path;
03704
03705 ut_ad(fil_system);
03706
03707 mutex_enter(&fil_system->mutex);
03708
03709 path = fil_make_ibd_name(name, is_temp);
03710
03711
03712
03713 space = fil_space_get_by_id(id);
03714
03715
03716
03717
03718 tablespace = fil_space_get_by_name(path);
03719 if (space && space == tablespace) {
03720
03721
03722 if (mark_space) {
03723 space->mark = TRUE;
03724 }
03725
03726 mem_free(path);
03727 mutex_exit(&fil_system->mutex);
03728
03729 return(TRUE);
03730 }
03731
03732 if (!print_error_if_does_not_exist) {
03733
03734 mem_free(path);
03735 mutex_exit(&fil_system->mutex);
03736
03737 return(FALSE);
03738 }
03739
03740 if (space == NULL) {
03741 if (tablespace == NULL) {
03742 ut_print_timestamp(stderr);
03743 fputs(" InnoDB: Error: table ", stderr);
03744 ut_print_filename(stderr, name);
03745 fprintf(stderr, "\n"
03746 "InnoDB: in InnoDB data dictionary"
03747 " has tablespace id %lu,\n"
03748 "InnoDB: but tablespace with that id"
03749 " or name does not exist. Have\n"
03750 "InnoDB: you deleted or moved .ibd files?\n"
03751 "InnoDB: This may also be a table created with"
03752 " CREATE TEMPORARY TABLE\n"
03753 "InnoDB: whose .ibd and .frm files"
03754 " MySQL automatically removed, but the\n"
03755 "InnoDB: table still exists in the"
03756 " InnoDB internal data dictionary.\n",
03757 (ulong) id);
03758 } else {
03759 ut_print_timestamp(stderr);
03760 fputs(" InnoDB: Error: table ", stderr);
03761 ut_print_filename(stderr, name);
03762 fprintf(stderr, "\n"
03763 "InnoDB: in InnoDB data dictionary has"
03764 " tablespace id %lu,\n"
03765 "InnoDB: but a tablespace with that id"
03766 " does not exist. There is\n"
03767 "InnoDB: a tablespace of name %s and id %lu,"
03768 " though. Have\n"
03769 "InnoDB: you deleted or moved .ibd files?\n",
03770 (ulong) id, tablespace->name,
03771 (ulong) tablespace->id);
03772 }
03773 error_exit:
03774 fputs("InnoDB: Please refer to\n"
03775 "InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n"
03776 "InnoDB: for how to resolve the issue.\n", stderr);
03777
03778 mem_free(path);
03779 mutex_exit(&fil_system->mutex);
03780
03781 return(FALSE);
03782 }
03783
03784 if (0 != strcmp(space->name, path)) {
03785 ut_print_timestamp(stderr);
03786 fputs(" InnoDB: Error: table ", stderr);
03787 ut_print_filename(stderr, name);
03788 fprintf(stderr, "\n"
03789 "InnoDB: in InnoDB data dictionary has"
03790 " tablespace id %lu,\n"
03791 "InnoDB: but the tablespace with that id"
03792 " has name %s.\n"
03793 "InnoDB: Have you deleted or moved .ibd files?\n",
03794 (ulong) id, space->name);
03795
03796 if (tablespace != NULL) {
03797 fputs("InnoDB: There is a tablespace"
03798 " with the right name\n"
03799 "InnoDB: ", stderr);
03800 ut_print_filename(stderr, tablespace->name);
03801 fprintf(stderr, ", but its id is %lu.\n",
03802 (ulong) tablespace->id);
03803 }
03804
03805 goto error_exit;
03806 }
03807
03808 mem_free(path);
03809 mutex_exit(&fil_system->mutex);
03810
03811 return(FALSE);
03812 }
03813
03814
03818 static
03819 ulint
03820 fil_get_space_id_for_table(
03821
03822 const char* name)
03824 {
03825 fil_space_t* tablespace;
03826 ulint id = ULINT_UNDEFINED;
03827 char* path;
03828
03829 ut_ad(fil_system);
03830
03831 mutex_enter(&fil_system->mutex);
03832
03833 path = fil_make_ibd_name(name, FALSE);
03834
03835
03836
03837
03838 tablespace = fil_space_get_by_name(path);
03839
03840 if (tablespace) {
03841 id = tablespace->id;
03842 }
03843
03844 mem_free(path);
03845
03846 mutex_exit(&fil_system->mutex);
03847
03848 return(id);
03849 }
03850
03851
03856 UNIV_INTERN
03857 ibool
03858 fil_extend_space_to_desired_size(
03859
03860 ulint* actual_size,
03863 ulint space_id,
03864 ulint size_after_extend)
03867 {
03868 fil_node_t* node;
03869 fil_space_t* space;
03870 byte* buf2;
03871 byte* buf;
03872 ulint buf_size;
03873 ulint start_page_no;
03874 ulint file_start_page_no;
03875 ulint offset_high;
03876 ulint offset_low;
03877 ulint page_size;
03878 ibool success = TRUE;
03879
03880 fil_mutex_enter_and_prepare_for_io(space_id);
03881
03882 space = fil_space_get_by_id(space_id);
03883 ut_a(space);
03884
03885 if (space->size >= size_after_extend) {
03886
03887
03888 *actual_size = space->size;
03889
03890 mutex_exit(&fil_system->mutex);
03891
03892 return(TRUE);
03893 }
03894
03895 page_size = dict_table_flags_to_zip_size(space->flags);
03896 if (!page_size) {
03897 page_size = UNIV_PAGE_SIZE;
03898 }
03899
03900 node = UT_LIST_GET_LAST(space->chain);
03901
03902 fil_node_prepare_for_io(node, fil_system, space);
03903
03904 start_page_no = space->size;
03905 file_start_page_no = space->size - node->size;
03906
03907
03908 buf_size = ut_min(64, size_after_extend - start_page_no) * page_size;
03909 buf2 = static_cast<byte *>(mem_alloc(buf_size + page_size));
03910 buf = static_cast<byte *>(ut_align(buf2, page_size));
03911
03912 memset(buf, 0, buf_size);
03913
03914 while (start_page_no < size_after_extend) {
03915 ulint n_pages = ut_min(buf_size / page_size,
03916 size_after_extend - start_page_no);
03917
03918 offset_high = (start_page_no - file_start_page_no)
03919 / (4096 * ((1024 * 1024) / page_size));
03920 offset_low = ((start_page_no - file_start_page_no)
03921 % (4096 * ((1024 * 1024) / page_size)))
03922 * page_size;
03923 #ifdef UNIV_HOTBACKUP
03924 success = os_file_write(node->name, node->handle, buf,
03925 offset_low, offset_high,
03926 page_size * n_pages);
03927 #else
03928 success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC,
03929 node->name, node->handle, buf,
03930 offset_low, offset_high,
03931 page_size * n_pages,
03932 NULL, NULL);
03933 #endif
03934 if (success) {
03935 node->size += n_pages;
03936 space->size += n_pages;
03937
03938 os_has_said_disk_full = FALSE;
03939 } else {
03940
03941
03942
03943 n_pages = ((ulint)
03944 (os_file_get_size_as_iblonglong(
03945 node->handle)
03946 / page_size)) - node->size;
03947
03948 node->size += n_pages;
03949 space->size += n_pages;
03950
03951 break;
03952 }
03953
03954 start_page_no += n_pages;
03955 }
03956
03957 mem_free(buf2);
03958
03959 fil_node_complete_io(node, fil_system, OS_FILE_WRITE);
03960
03961 *actual_size = space->size;
03962
03963 #ifndef UNIV_HOTBACKUP
03964 if (space_id == 0) {
03965 ulint pages_per_mb = (1024 * 1024) / page_size;
03966
03967
03968
03969
03970 srv_data_file_sizes[srv_n_data_files - 1]
03971 = (node->size / pages_per_mb) * pages_per_mb;
03972 }
03973 #endif
03974
03975
03976
03977
03978 mutex_exit(&fil_system->mutex);
03979
03980 fil_flush(space_id);
03981
03982 return(success);
03983 }
03984
03985 #ifdef UNIV_HOTBACKUP
03986
03991 UNIV_INTERN
03992 void
03993 fil_extend_tablespaces_to_stored_len(void)
03994
03995 {
03996 fil_space_t* space;
03997 byte* buf;
03998 ulint actual_size;
03999 ulint size_in_header;
04000 ulint error;
04001 ibool success;
04002
04003 buf = mem_alloc(UNIV_PAGE_SIZE);
04004
04005 mutex_enter(&fil_system->mutex);
04006
04007 space = UT_LIST_GET_FIRST(fil_system->space_list);
04008
04009 while (space) {
04010 ut_a(space->purpose == FIL_TABLESPACE);
04011
04012 mutex_exit(&fil_system->mutex);
04013
04014
04015 error = fil_read(TRUE, space->id,
04016 dict_table_flags_to_zip_size(space->flags),
04017 0, 0, UNIV_PAGE_SIZE, buf, NULL);
04018 ut_a(error == DB_SUCCESS);
04019
04020 size_in_header = fsp_get_size_low(buf);
04021
04022 success = fil_extend_space_to_desired_size(
04023 &actual_size, space->id, size_in_header);
04024 if (!success) {
04025 fprintf(stderr,
04026 "InnoDB: Error: could not extend the"
04027 " tablespace of %s\n"
04028 "InnoDB: to the size stored in header,"
04029 " %lu pages;\n"
04030 "InnoDB: size after extension %lu pages\n"
04031 "InnoDB: Check that you have free disk space"
04032 " and retry!\n",
04033 space->name, size_in_header, actual_size);
04034 exit(1);
04035 }
04036
04037 mutex_enter(&fil_system->mutex);
04038
04039 space = UT_LIST_GET_NEXT(space_list, space);
04040 }
04041
04042 mutex_exit(&fil_system->mutex);
04043
04044 mem_free(buf);
04045 }
04046 #endif
04047
04048
04049
04050
04053 UNIV_INTERN
04054 ibool
04055 fil_space_reserve_free_extents(
04056
04057 ulint id,
04058 ulint n_free_now,
04059 ulint n_to_reserve)
04060 {
04061 fil_space_t* space;
04062 ibool success;
04063
04064 ut_ad(fil_system);
04065
04066 mutex_enter(&fil_system->mutex);
04067
04068 space = fil_space_get_by_id(id);
04069
04070 ut_a(space);
04071
04072 if (space->n_reserved_extents + n_to_reserve > n_free_now) {
04073 success = FALSE;
04074 } else {
04075 space->n_reserved_extents += n_to_reserve;
04076 success = TRUE;
04077 }
04078
04079 mutex_exit(&fil_system->mutex);
04080
04081 return(success);
04082 }
04083
04084
04086 UNIV_INTERN
04087 void
04088 fil_space_release_free_extents(
04089
04090 ulint id,
04091 ulint n_reserved)
04092 {
04093 fil_space_t* space;
04094
04095 ut_ad(fil_system);
04096
04097 mutex_enter(&fil_system->mutex);
04098
04099 space = fil_space_get_by_id(id);
04100
04101 ut_a(space);
04102 ut_a(space->n_reserved_extents >= n_reserved);
04103
04104 space->n_reserved_extents -= n_reserved;
04105
04106 mutex_exit(&fil_system->mutex);
04107 }
04108
04109
04112 UNIV_INTERN
04113 ulint
04114 fil_space_get_n_reserved_extents(
04115
04116 ulint id)
04117 {
04118 fil_space_t* space;
04119 ulint n;
04120
04121 ut_ad(fil_system);
04122
04123 mutex_enter(&fil_system->mutex);
04124
04125 space = fil_space_get_by_id(id);
04126
04127 ut_a(space);
04128
04129 n = space->n_reserved_extents;
04130
04131 mutex_exit(&fil_system->mutex);
04132
04133 return(n);
04134 }
04135
04136
04137
04138
04145 static
04146 void
04147 fil_node_prepare_for_io(
04148
04149 fil_node_t* node,
04150 fil_system_t* system,
04151 fil_space_t* space)
04152 {
04153 ut_ad(node && system && space);
04154 ut_ad(mutex_own(&(system->mutex)));
04155
04156 if (system->n_open > system->max_n_open + 5) {
04157 ut_print_timestamp(stderr);
04158 fprintf(stderr,
04159 " InnoDB: Warning: open files %lu"
04160 " exceeds the limit %lu\n",
04161 (ulong) system->n_open,
04162 (ulong) system->max_n_open);
04163 }
04164
04165 if (node->open == FALSE) {
04166
04167 ut_a(node->n_pending == 0);
04168
04169 fil_node_open_file(node, system, space);
04170 }
04171
04172 if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE
04173 && space->id != 0) {
04174
04175
04176 ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
04177
04178 UT_LIST_REMOVE(LRU, system->LRU, node);
04179 }
04180
04181 node->n_pending++;
04182 }
04183
04184
04187 static
04188 void
04189 fil_node_complete_io(
04190
04191 fil_node_t* node,
04192 fil_system_t* system,
04193 ulint type)
04196 {
04197 ut_ad(node);
04198 ut_ad(system);
04199 ut_ad(mutex_own(&(system->mutex)));
04200
04201 ut_a(node->n_pending > 0);
04202
04203 node->n_pending--;
04204
04205 if (type == OS_FILE_WRITE) {
04206 system->modification_counter++;
04207 node->modification_counter = system->modification_counter;
04208
04209 if (!node->space->is_in_unflushed_spaces) {
04210
04211 node->space->is_in_unflushed_spaces = TRUE;
04212 UT_LIST_ADD_FIRST(unflushed_spaces,
04213 system->unflushed_spaces,
04214 node->space);
04215 }
04216 }
04217
04218 if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE
04219 && node->space->id != 0) {
04220
04221 UT_LIST_ADD_FIRST(LRU, system->LRU, node);
04222 }
04223 }
04224
04225
04227 static
04228 void
04229 fil_report_invalid_page_access(
04230
04231 ulint block_offset,
04232 ulint space_id,
04233 const char* space_name,
04234 ulint byte_offset,
04235 ulint len,
04236 ulint type)
04237 {
04238 fprintf(stderr,
04239 "InnoDB: Error: trying to access page number %lu"
04240 " in space %lu,\n"
04241 "InnoDB: space name %s,\n"
04242 "InnoDB: which is outside the tablespace bounds.\n"
04243 "InnoDB: Byte offset %lu, len %lu, i/o type %lu.\n"
04244 "InnoDB: If you get this error at mysqld startup,"
04245 " please check that\n"
04246 "InnoDB: your my.cnf matches the ibdata files"
04247 " that you have in the\n"
04248 "InnoDB: MySQL server.\n",
04249 (ulong) block_offset, (ulong) space_id, space_name,
04250 (ulong) byte_offset, (ulong) len, (ulong) type);
04251 }
04252
04253
04257 UNIV_INTERN
04258 ulint
04259 fil_io(
04260
04261 ulint type,
04270 ibool sync,
04271 ulint space_id,
04272 ulint zip_size,
04274 ulint block_offset,
04275 ulint byte_offset,
04278 ulint len,
04281 void* buf,
04284 void* message)
04286 {
04287 ulint mode;
04288 fil_space_t* space;
04289 fil_node_t* node;
04290 ulint offset_high;
04291 ulint offset_low;
04292 ibool ret;
04293 ulint is_log;
04294 ulint wake_later;
04295
04296 is_log = type & OS_FILE_LOG;
04297 type = type & ~OS_FILE_LOG;
04298
04299 wake_later = type & OS_AIO_SIMULATED_WAKE_LATER;
04300 type = type & ~OS_AIO_SIMULATED_WAKE_LATER;
04301
04302 ut_ad(byte_offset < UNIV_PAGE_SIZE);
04303 ut_ad(!zip_size || !byte_offset);
04304 ut_ad(ut_is_2pow(zip_size));
04305 ut_ad(buf);
04306 ut_ad(len > 0);
04307 ut_ad(fil_validate());
04308 #ifndef UNIV_HOTBACKUP
04309 # ifndef UNIV_LOG_DEBUG
04310
04311 ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE)
04312 || !ibuf_bitmap_page(zip_size, block_offset)
04313 || sync || is_log);
04314 ut_ad(!ibuf_inside() || is_log || (type == OS_FILE_WRITE)
04315 || ibuf_page(space_id, zip_size, block_offset, NULL));
04316 # endif
04317 if (sync) {
04318 mode = OS_AIO_SYNC;
04319 } else if (is_log) {
04320 mode = OS_AIO_LOG;
04321 } else if (type == OS_FILE_READ
04322 && !recv_no_ibuf_operations
04323 && ibuf_page(space_id, zip_size, block_offset, NULL)) {
04324 mode = OS_AIO_IBUF;
04325 } else {
04326 mode = OS_AIO_NORMAL;
04327 }
04328 #else
04329 ut_a(sync);
04330 mode = OS_AIO_SYNC;
04331 #endif
04332
04333 if (type == OS_FILE_READ) {
04334 srv_data_read+= len;
04335 } else if (type == OS_FILE_WRITE) {
04336 srv_data_written+= len;
04337 }
04338
04339
04340
04341
04342 fil_mutex_enter_and_prepare_for_io(space_id);
04343
04344 space = fil_space_get_by_id(space_id);
04345
04346 if (!space) {
04347 mutex_exit(&fil_system->mutex);
04348
04349 ut_print_timestamp(stderr);
04350 fprintf(stderr,
04351 " InnoDB: Error: trying to do i/o"
04352 " to a tablespace which does not exist.\n"
04353 "InnoDB: i/o type %lu, space id %lu,"
04354 " page no. %lu, i/o length %lu bytes\n",
04355 (ulong) type, (ulong) space_id, (ulong) block_offset,
04356 (ulong) len);
04357
04358 return(DB_TABLESPACE_DELETED);
04359 }
04360
04361 ut_ad((mode != OS_AIO_IBUF) || (space->purpose == FIL_TABLESPACE));
04362
04363 node = UT_LIST_GET_FIRST(space->chain);
04364
04365 for (;;) {
04366 if (UNIV_UNLIKELY(node == NULL)) {
04367 fil_report_invalid_page_access(
04368 block_offset, space_id, space->name,
04369 byte_offset, len, type);
04370
04371 ut_error;
04372 }
04373
04374 if (space->id != 0 && node->size == 0) {
04375
04376
04377
04378 break;
04379 }
04380
04381 if (node->size > block_offset) {
04382
04383 break;
04384 } else {
04385 block_offset -= node->size;
04386 node = UT_LIST_GET_NEXT(chain, node);
04387 }
04388 }
04389
04390
04391 fil_node_prepare_for_io(node, fil_system, space);
04392
04393
04394
04395 if (UNIV_UNLIKELY(node->size <= block_offset)
04396 && space->id != 0 && space->purpose == FIL_TABLESPACE) {
04397
04398 fil_report_invalid_page_access(
04399 block_offset, space_id, space->name, byte_offset,
04400 len, type);
04401
04402 ut_error;
04403 }
04404
04405
04406 mutex_exit(&fil_system->mutex);
04407
04408
04409
04410 if (!zip_size) {
04411 offset_high = (block_offset >> (32 - UNIV_PAGE_SIZE_SHIFT));
04412 offset_low = ((block_offset << UNIV_PAGE_SIZE_SHIFT)
04413 & 0xFFFFFFFFUL) + byte_offset;
04414
04415 ut_a(node->size - block_offset
04416 >= ((byte_offset + len + (UNIV_PAGE_SIZE - 1))
04417 / UNIV_PAGE_SIZE));
04418 } else {
04419 ulint zip_size_shift;
04420 switch (zip_size) {
04421 case 1024: zip_size_shift = 10; break;
04422 case 2048: zip_size_shift = 11; break;
04423 case 4096: zip_size_shift = 12; break;
04424 case 8192: zip_size_shift = 13; break;
04425 case 16384: zip_size_shift = 14; break;
04426 default: ut_error;
04427 }
04428 offset_high = block_offset >> (32 - zip_size_shift);
04429 offset_low = (block_offset << zip_size_shift & 0xFFFFFFFFUL)
04430 + byte_offset;
04431 ut_a(node->size - block_offset
04432 >= (len + (zip_size - 1)) / zip_size);
04433 }
04434
04435
04436
04437 ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
04438 ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
04439
04440 #ifdef UNIV_HOTBACKUP
04441
04442 if (type == OS_FILE_READ) {
04443 ret = os_file_read(node->handle, buf, offset_low, offset_high,
04444 len);
04445 } else {
04446 ret = os_file_write(node->name, node->handle, buf,
04447 offset_low, offset_high, len);
04448 }
04449 #else
04450
04451 ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
04452 offset_low, offset_high, len, node, message);
04453 #endif
04454 ut_a(ret);
04455
04456 if (mode == OS_AIO_SYNC) {
04457
04458
04459
04460 mutex_enter(&fil_system->mutex);
04461
04462 fil_node_complete_io(node, fil_system, type);
04463
04464 mutex_exit(&fil_system->mutex);
04465
04466 ut_ad(fil_validate());
04467 }
04468
04469 return(DB_SUCCESS);
04470 }
04471
04472
04474 UNIV_INTERN
04475 bool
04476 fil_is_exist(
04477
04478 ulint space_id,
04479 ulint block_offset)
04480 {
04481 fil_space_t* space;
04482 fil_node_t* node;
04483
04484
04485
04486
04487 fil_mutex_enter_and_prepare_for_io(space_id);
04488
04489 space = fil_space_get_by_id(space_id);
04490
04491 if (!space) {
04492 mutex_exit(&fil_system->mutex);
04493 return(false);
04494 }
04495
04496 node = UT_LIST_GET_FIRST(space->chain);
04497
04498 for (;;) {
04499 if (UNIV_UNLIKELY(node == NULL)) {
04500 mutex_exit(&fil_system->mutex);
04501 return(false);
04502 }
04503
04504 if (space->id != 0 && node->size == 0) {
04505
04506
04507
04508 break;
04509 }
04510
04511 if (node->size > block_offset) {
04512
04513 break;
04514 } else {
04515 block_offset -= node->size;
04516 node = UT_LIST_GET_NEXT(chain, node);
04517 }
04518 }
04519
04520
04521 fil_node_prepare_for_io(node, fil_system, space);
04522 fil_node_complete_io(node, fil_system, OS_FILE_READ);
04523
04524
04525
04526 if (UNIV_UNLIKELY(node->size <= block_offset)
04527 && space->id != 0 && space->purpose == FIL_TABLESPACE) {
04528 mutex_exit(&fil_system->mutex);
04529 return(false);
04530 }
04531
04532 mutex_exit(&fil_system->mutex);
04533 return(true);
04534 }
04535
04536 #ifndef UNIV_HOTBACKUP
04537
04542 UNIV_INTERN
04543 void
04544 fil_aio_wait(
04545
04546 ulint segment)
04548 {
04549 ibool ret;
04550 fil_node_t* fil_node;
04551 void* message;
04552 ulint type;
04553
04554 ut_ad(fil_validate());
04555
04556 if (srv_use_native_aio) {
04557 srv_set_io_thread_op_info(segment, "native aio handle");
04558 #ifdef WIN_ASYNC_IO
04559 ret = os_aio_windows_handle(segment, 0, &fil_node,
04560 &message, &type);
04561 #elif defined(LINUX_NATIVE_AIO)
04562 ret = os_aio_linux_handle(segment, &fil_node,
04563 &message, &type);
04564 #else
04565 ret = 0;
04566 ut_error;
04567 #endif
04568 } else {
04569 srv_set_io_thread_op_info(segment, "simulated aio handle");
04570
04571 ret = os_aio_simulated_handle(segment, &fil_node,
04572 &message, &type);
04573 }
04574
04575 ut_a(ret);
04576
04577 srv_set_io_thread_op_info(segment, "complete io for fil node");
04578
04579 mutex_enter(&fil_system->mutex);
04580
04581 fil_node_complete_io(fil_node, fil_system, type);
04582
04583 mutex_exit(&fil_system->mutex);
04584
04585 ut_ad(fil_validate());
04586
04587
04588
04589
04590
04591
04592
04593 if (fil_node->space->purpose == FIL_TABLESPACE) {
04594 srv_set_io_thread_op_info(segment, "complete io for buf page");
04595 buf_page_io_complete(static_cast<buf_page_t *>(message));
04596 } else {
04597 srv_set_io_thread_op_info(segment, "complete io for log");
04598 log_io_complete(static_cast<log_group_t *>(message));
04599 }
04600 }
04601 #endif
04602
04603
04606 UNIV_INTERN
04607 void
04608 fil_flush(
04609
04610 ulint space_id)
04612 {
04613 fil_space_t* space;
04614 fil_node_t* node;
04615 os_file_t file;
04616 ib_int64_t old_mod_counter;
04617
04618 mutex_enter(&fil_system->mutex);
04619
04620 space = fil_space_get_by_id(space_id);
04621
04622 if (!space || space->is_being_deleted) {
04623 mutex_exit(&fil_system->mutex);
04624
04625 return;
04626 }
04627
04628 space->n_pending_flushes++;
04630 node = UT_LIST_GET_FIRST(space->chain);
04631
04632 while (node) {
04633 if (node->modification_counter > node->flush_counter) {
04634 ut_a(node->open);
04635
04636
04637
04638 old_mod_counter = node->modification_counter;
04639
04640 if (space->purpose == FIL_TABLESPACE) {
04641 fil_n_pending_tablespace_flushes++;
04642 } else {
04643 fil_n_pending_log_flushes++;
04644 fil_n_log_flushes++;
04645 }
04646 #ifdef __WIN__
04647 if (node->is_raw_disk) {
04648
04649 goto skip_flush;
04650 }
04651 #endif
04652 retry:
04653 if (node->n_pending_flushes > 0) {
04654
04655
04656
04657
04658
04659 mutex_exit(&fil_system->mutex);
04660
04661 os_thread_sleep(20000);
04662
04663 mutex_enter(&fil_system->mutex);
04664
04665 if (node->flush_counter >= old_mod_counter) {
04666
04667 goto skip_flush;
04668 }
04669
04670 goto retry;
04671 }
04672
04673 ut_a(node->open);
04674 file = node->handle;
04675 node->n_pending_flushes++;
04676
04677 mutex_exit(&fil_system->mutex);
04678
04679
04680
04681
04682 os_file_flush(file);
04683
04684 mutex_enter(&fil_system->mutex);
04685
04686 node->n_pending_flushes--;
04687 skip_flush:
04688 if (node->flush_counter < old_mod_counter) {
04689 node->flush_counter = old_mod_counter;
04690
04691 if (space->is_in_unflushed_spaces
04692 && fil_space_is_flushed(space)) {
04693
04694 space->is_in_unflushed_spaces = FALSE;
04695
04696 UT_LIST_REMOVE(
04697 unflushed_spaces,
04698 fil_system->unflushed_spaces,
04699 space);
04700 }
04701 }
04702
04703 if (space->purpose == FIL_TABLESPACE) {
04704 fil_n_pending_tablespace_flushes--;
04705 } else {
04706 fil_n_pending_log_flushes--;
04707 }
04708 }
04709
04710 node = UT_LIST_GET_NEXT(chain, node);
04711 }
04712
04713 space->n_pending_flushes--;
04714
04715 mutex_exit(&fil_system->mutex);
04716 }
04717
04718
04721 UNIV_INTERN
04722 void
04723 fil_flush_file_spaces(
04724
04725 ulint purpose)
04726 {
04727 fil_space_t* space;
04728 ulint* space_ids;
04729 ulint n_space_ids;
04730 ulint i;
04731
04732 mutex_enter(&fil_system->mutex);
04733
04734 n_space_ids = UT_LIST_GET_LEN(fil_system->unflushed_spaces);
04735 if (n_space_ids == 0) {
04736
04737 mutex_exit(&fil_system->mutex);
04738 return;
04739 }
04740
04741
04742
04743
04744
04745 space_ids = static_cast<unsigned long *>(mem_alloc(n_space_ids * sizeof *space_ids));
04746
04747 n_space_ids = 0;
04748
04749 for (space = UT_LIST_GET_FIRST(fil_system->unflushed_spaces);
04750 space;
04751 space = UT_LIST_GET_NEXT(unflushed_spaces, space)) {
04752
04753 if (space->purpose == purpose && !space->is_being_deleted) {
04754
04755 space_ids[n_space_ids++] = space->id;
04756 }
04757 }
04758
04759 mutex_exit(&fil_system->mutex);
04760
04761
04762
04763 for (i = 0; i < n_space_ids; i++) {
04764
04765 fil_flush(space_ids[i]);
04766 }
04767
04768 mem_free(space_ids);
04769 }
04770
04771
04774 UNIV_INTERN
04775 ibool
04776 fil_validate(void)
04777
04778 {
04779 fil_space_t* space;
04780 fil_node_t* fil_node;
04781 ulint n_open = 0;
04782 ulint i;
04783
04784 mutex_enter(&fil_system->mutex);
04785
04786
04787
04788 for (i = 0; i < hash_get_n_cells(fil_system->spaces); i++) {
04789
04790 space = static_cast<fil_space_t *>(HASH_GET_FIRST(fil_system->spaces, i));
04791
04792 while (space != NULL) {
04793 UT_LIST_VALIDATE(chain, fil_node_t, space->chain,
04794 ut_a(ut_list_node_313->open
04795 || !ut_list_node_313->n_pending));
04796
04797 fil_node = UT_LIST_GET_FIRST(space->chain);
04798
04799 while (fil_node != NULL) {
04800 if (fil_node->n_pending > 0) {
04801 ut_a(fil_node->open);
04802 }
04803
04804 if (fil_node->open) {
04805 n_open++;
04806 }
04807 fil_node = UT_LIST_GET_NEXT(chain, fil_node);
04808 }
04809 space = static_cast<fil_space_t *>(HASH_GET_NEXT(hash, space));
04810 }
04811 }
04812
04813 ut_a(fil_system->n_open == n_open);
04814
04815 UT_LIST_VALIDATE(LRU, fil_node_t, fil_system->LRU, (void) 0);
04816
04817 fil_node = UT_LIST_GET_FIRST(fil_system->LRU);
04818
04819 while (fil_node != NULL) {
04820 ut_a(fil_node->n_pending == 0);
04821 ut_a(fil_node->open);
04822 ut_a(fil_node->space->purpose == FIL_TABLESPACE);
04823 ut_a(fil_node->space->id != 0);
04824
04825 fil_node = UT_LIST_GET_NEXT(LRU, fil_node);
04826 }
04827
04828 mutex_exit(&fil_system->mutex);
04829
04830 return(TRUE);
04831 }
04832
04833
04836 UNIV_INTERN
04837 ibool
04838 fil_addr_is_null(
04839
04840 fil_addr_t addr)
04841 {
04842 return(addr.page == FIL_NULL);
04843 }
04844
04845
04848 UNIV_INTERN
04849 ulint
04850 fil_page_get_prev(
04851
04852 const byte* page)
04853 {
04854 return(mach_read_from_4(page + FIL_PAGE_PREV));
04855 }
04856
04857
04860 UNIV_INTERN
04861 ulint
04862 fil_page_get_next(
04863
04864 const byte* page)
04865 {
04866 return(mach_read_from_4(page + FIL_PAGE_NEXT));
04867 }
04868
04869
04871 UNIV_INTERN
04872 void
04873 fil_page_set_type(
04874
04875 byte* page,
04876 ulint type)
04877 {
04878 ut_ad(page);
04879
04880 mach_write_to_2(page + FIL_PAGE_TYPE, type);
04881 }
04882
04883
04887 UNIV_INTERN
04888 ulint
04889 fil_page_get_type(
04890
04891 const byte* page)
04892 {
04893 ut_ad(page);
04894
04895 return(mach_read_from_2(page + FIL_PAGE_TYPE));
04896 }
04897
04898
04900 UNIV_INTERN
04901 void
04902 fil_close(void)
04903
04904 {
04905 #ifndef UNIV_HOTBACKUP
04906
04907 ut_ad(fil_system->mutex.magic_n == 0);
04908 #endif
04909
04910 hash_table_free(fil_system->spaces);
04911
04912 hash_table_free(fil_system->name_hash);
04913
04914 ut_a(UT_LIST_GET_LEN(fil_system->LRU) == 0);
04915 ut_a(UT_LIST_GET_LEN(fil_system->unflushed_spaces) == 0);
04916 ut_a(UT_LIST_GET_LEN(fil_system->space_list) == 0);
04917
04918 mem_free(fil_system);
04919
04920 fil_system = NULL;
04921 }