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 #ifndef UNIV_HOTBACKUP
00044 # include "buf0lru.h"
00045 # include "ibuf0ibuf.h"
00046 # include "sync0sync.h"
00047 # include "os0sync.h"
00048 #else
00049 static ulint srv_data_read, srv_data_written;
00050 #endif
00051
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
00111 UNIV_INTERN const char* fil_path_to_mysql_datadir = ".";
00112
00114 UNIV_INTERN ulint fil_n_log_flushes = 0;
00115
00117 UNIV_INTERN ulint fil_n_pending_log_flushes = 0;
00119 UNIV_INTERN ulint fil_n_pending_tablespace_flushes = 0;
00120
00122 UNIV_INTERN fil_addr_t fil_addr_null = {FIL_NULL, 0};
00123
00124 #ifdef UNIV_PFS_MUTEX
00125
00126 UNIV_INTERN mysql_pfs_key_t fil_system_mutex_key;
00127 #endif
00128
00129 #ifdef UNIV_PFS_RWLOCK
00130
00131 UNIV_INTERN mysql_pfs_key_t fil_space_latch_key;
00132 #endif
00133
00135 struct fil_node_struct {
00136 fil_space_t* space;
00138 char* name;
00139 ibool open;
00140 os_file_t handle;
00141 ibool is_raw_disk;
00143 ulint size;
00146 ulint n_pending;
00150 ulint n_pending_flushes;
00154 ib_int64_t modification_counter;
00156 ib_int64_t flush_counter;
00159 UT_LIST_NODE_T(fil_node_t) chain;
00161 UT_LIST_NODE_T(fil_node_t) LRU;
00163 ulint magic_n;
00164 };
00165
00167 #define FIL_NODE_MAGIC_N 89389
00168
00170 struct fil_space_struct {
00171 char* name;
00173 ulint id;
00174 ib_int64_t tablespace_version;
00180 ibool mark;
00184 ibool stop_ios;
00188 ibool stop_ibuf_merges;
00191 ibool is_being_deleted;
00198 ulint purpose;
00200 UT_LIST_BASE_NODE_T(fil_node_t) chain;
00202 ulint size;
00206 ulint flags;
00207 ulint n_reserved_extents;
00210 ulint n_pending_flushes;
00213 ulint n_pending_ibuf_merges;
00219 hash_node_t hash;
00220 hash_node_t name_hash;
00221 #ifndef UNIV_HOTBACKUP
00222 rw_lock_t latch;
00224 #endif
00225 UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
00228 ibool is_in_unflushed_spaces;
00230 UT_LIST_NODE_T(fil_space_t) space_list;
00232 ulint magic_n;
00233 };
00234
00236 #define FIL_SPACE_MAGIC_N 89472
00237
00239 typedef struct fil_system_struct fil_system_t;
00240
00245 struct fil_system_struct {
00246 #ifndef UNIV_HOTBACKUP
00247 mutex_t mutex;
00248 #endif
00249 hash_table_t* spaces;
00252 hash_table_t* name_hash;
00254 UT_LIST_BASE_NODE_T(fil_node_t) LRU;
00265 UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
00271 ulint n_open;
00272 ulint max_n_open;
00274 ib_int64_t modification_counter;
00276 ulint max_assigned_id;
00282 ib_int64_t tablespace_version;
00290 UT_LIST_BASE_NODE_T(fil_space_t) space_list;
00292 ibool space_id_reuse_warned;
00293
00294
00295
00296 };
00297
00300 static fil_system_t* fil_system = NULL;
00301
00302
00303
00310 static
00311 void
00312 fil_node_prepare_for_io(
00313
00314 fil_node_t* node,
00315 fil_system_t* system,
00316 fil_space_t* space);
00317
00320 static
00321 void
00322 fil_node_complete_io(
00323
00324 fil_node_t* node,
00325 fil_system_t* system,
00326 ulint type);
00329
00333 static
00334 ulint
00335 fil_get_space_id_for_table(
00336
00337 const char* name);
00339
00344 static
00345 ibool
00346 fil_space_free(
00347
00348 ulint id,
00349 ibool x_latched);
00350
00351
00357 UNIV_INLINE
00358 ulint
00359 fil_read(
00360
00361 ibool sync,
00362 ulint space_id,
00363 ulint zip_size,
00365 ulint block_offset,
00366 ulint byte_offset,
00368 ulint len,
00371 void* buf,
00373 void* message)
00375 {
00376 return(fil_io(OS_FILE_READ, sync, space_id, zip_size, block_offset,
00377 byte_offset, len, buf, message));
00378 }
00379
00380
00386 UNIV_INLINE
00387 ulint
00388 fil_write(
00389
00390 ibool sync,
00391 ulint space_id,
00392 ulint zip_size,
00394 ulint block_offset,
00395 ulint byte_offset,
00397 ulint len,
00400 void* buf,
00402 void* message)
00404 {
00405 return(fil_io(OS_FILE_WRITE, sync, space_id, zip_size, block_offset,
00406 byte_offset, len, buf, message));
00407 }
00408
00409
00411 UNIV_INLINE
00412 fil_space_t*
00413 fil_space_get_by_id(
00414
00415 ulint id)
00416 {
00417 fil_space_t* space;
00418
00419 ut_ad(mutex_own(&fil_system->mutex));
00420
00421 HASH_SEARCH(hash, fil_system->spaces, id,
00422 fil_space_t*, space,
00423 ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
00424 space->id == id);
00425
00426 return(space);
00427 }
00428
00429
00431 UNIV_INLINE
00432 fil_space_t*
00433 fil_space_get_by_name(
00434
00435 const char* name)
00436 {
00437 fil_space_t* space;
00438 ulint fold;
00439
00440 ut_ad(mutex_own(&fil_system->mutex));
00441
00442 fold = ut_fold_string(name);
00443
00444 HASH_SEARCH(name_hash, fil_system->name_hash, fold,
00445 fil_space_t*, space,
00446 ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
00447 !strcmp(name, space->name));
00448
00449 return(space);
00450 }
00451
00452 #ifndef UNIV_HOTBACKUP
00453
00457 UNIV_INTERN
00458 ib_int64_t
00459 fil_space_get_version(
00460
00461 ulint id)
00462 {
00463 fil_space_t* space;
00464 ib_int64_t version = -1;
00465
00466 ut_ad(fil_system);
00467
00468 mutex_enter(&fil_system->mutex);
00469
00470 space = fil_space_get_by_id(id);
00471
00472 if (space) {
00473 version = space->tablespace_version;
00474 }
00475
00476 mutex_exit(&fil_system->mutex);
00477
00478 return(version);
00479 }
00480
00481
00484 UNIV_INTERN
00485 rw_lock_t*
00486 fil_space_get_latch(
00487
00488 ulint id,
00489 ulint* flags)
00490 {
00491 fil_space_t* space;
00492
00493 ut_ad(fil_system);
00494
00495 mutex_enter(&fil_system->mutex);
00496
00497 space = fil_space_get_by_id(id);
00498
00499 ut_a(space);
00500
00501 if (flags) {
00502 *flags = space->flags;
00503 }
00504
00505 mutex_exit(&fil_system->mutex);
00506
00507 return(&(space->latch));
00508 }
00509
00510
00513 UNIV_INTERN
00514 ulint
00515 fil_space_get_type(
00516
00517 ulint id)
00518 {
00519 fil_space_t* space;
00520
00521 ut_ad(fil_system);
00522
00523 mutex_enter(&fil_system->mutex);
00524
00525 space = fil_space_get_by_id(id);
00526
00527 ut_a(space);
00528
00529 mutex_exit(&fil_system->mutex);
00530
00531 return(space->purpose);
00532 }
00533 #endif
00534
00535
00539 static
00540 ibool
00541 fil_space_is_flushed(
00542
00543 fil_space_t* space)
00544 {
00545 fil_node_t* node;
00546
00547 ut_ad(mutex_own(&fil_system->mutex));
00548
00549 node = UT_LIST_GET_FIRST(space->chain);
00550
00551 while (node) {
00552 if (node->modification_counter > node->flush_counter) {
00553
00554 return(FALSE);
00555 }
00556
00557 node = UT_LIST_GET_NEXT(chain, node);
00558 }
00559
00560 return(TRUE);
00561 }
00562
00563
00565 UNIV_INTERN
00566 void
00567 fil_node_create(
00568
00569 const char* name,
00570 ulint size,
00572 ulint id,
00573 ibool is_raw)
00575 {
00576 fil_node_t* node;
00577 fil_space_t* space;
00578
00579 ut_a(fil_system);
00580 ut_a(name);
00581
00582 mutex_enter(&fil_system->mutex);
00583
00584 node = static_cast<fil_node_t *>(mem_alloc(sizeof(fil_node_t)));
00585
00586 node->name = mem_strdup(name);
00587 node->open = FALSE;
00588
00589 ut_a(!is_raw || srv_start_raw_disk_in_use);
00590
00591 node->is_raw_disk = is_raw;
00592 node->size = size;
00593 node->magic_n = FIL_NODE_MAGIC_N;
00594 node->n_pending = 0;
00595 node->n_pending_flushes = 0;
00596
00597 node->modification_counter = 0;
00598 node->flush_counter = 0;
00599
00600 space = fil_space_get_by_id(id);
00601
00602 if (!space) {
00603 ut_print_timestamp(stderr);
00604 fprintf(stderr,
00605 " InnoDB: Error: Could not find tablespace %lu for\n"
00606 "InnoDB: file ", (ulong) id);
00607 ut_print_filename(stderr, name);
00608 fputs(" in the tablespace memory cache.\n", stderr);
00609 mem_free(node->name);
00610
00611 mem_free(node);
00612
00613 mutex_exit(&fil_system->mutex);
00614
00615 return;
00616 }
00617
00618 space->size += size;
00619
00620 node->space = space;
00621
00622 UT_LIST_ADD_LAST(chain, space->chain, node);
00623
00624 if (id < SRV_LOG_SPACE_FIRST_ID && fil_system->max_assigned_id < id) {
00625
00626 fil_system->max_assigned_id = id;
00627 }
00628
00629 mutex_exit(&fil_system->mutex);
00630 }
00631
00632
00635 static
00636 void
00637 fil_node_open_file(
00638
00639 fil_node_t* node,
00640 fil_system_t* system,
00641 fil_space_t* space)
00642 {
00643 ib_int64_t size_bytes;
00644 ulint size_low;
00645 ulint size_high;
00646 ibool ret;
00647 ibool success;
00648 byte* buf2;
00649 byte* page;
00650 ulint space_id;
00651 ulint flags;
00652
00653 ut_ad(mutex_own(&(system->mutex)));
00654 ut_a(node->n_pending == 0);
00655 ut_a(node->open == FALSE);
00656
00657 if (node->size == 0) {
00658
00659
00660
00661
00662
00663
00664
00665
00666 node->handle = os_file_create_simple_no_error_handling(
00667 innodb_file_data_key, node->name, OS_FILE_OPEN,
00668 OS_FILE_READ_ONLY, &success);
00669 if (!success) {
00670
00671 os_file_get_last_error(TRUE);
00672
00673 ut_print_timestamp(stderr);
00674
00675 fprintf(stderr,
00676 " InnoDB: Fatal error: cannot open %s\n."
00677 "InnoDB: Have you deleted .ibd files"
00678 " under a running mysqld server?\n",
00679 node->name);
00680 ut_a(0);
00681 }
00682
00683 os_file_get_size(node->handle, &size_low, &size_high);
00684
00685 size_bytes = (((ib_int64_t)size_high) << 32)
00686 + (ib_int64_t)size_low;
00687 #ifdef UNIV_HOTBACKUP
00688 if (space->id == 0) {
00689 node->size = (ulint) (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 ib_int64_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 static
03452 int
03453 fil_file_readdir_next_file(
03454
03455 ulint* err,
03457 const char* dirname,
03458 os_file_dir_t dir,
03459 os_file_stat_t* info)
03460 {
03461 ulint i;
03462 int ret;
03463
03464 for (i = 0; i < 100; i++) {
03465 ret = os_file_readdir_next_file(dirname, dir, info);
03466
03467 if (ret != -1) {
03468
03469 return(ret);
03470 }
03471
03472 fprintf(stderr,
03473 "InnoDB: Error: os_file_readdir_next_file()"
03474 " returned -1 in\n"
03475 "InnoDB: directory %s\n"
03476 "InnoDB: Crash recovery may have failed"
03477 " for some .ibd files!\n", dirname);
03478
03479 *err = DB_ERROR;
03480 }
03481
03482 return(-1);
03483 }
03484
03485
03493 UNIV_INTERN
03494 ulint
03495 fil_load_single_table_tablespaces(void)
03496
03497 {
03498 int ret;
03499 char* dbpath = NULL;
03500 ulint dbpath_len = 100;
03501 os_file_dir_t dir;
03502 os_file_dir_t dbdir;
03503 os_file_stat_t dbinfo;
03504 os_file_stat_t fileinfo;
03505 ulint err = DB_SUCCESS;
03506
03507
03508
03509 dir = os_file_opendir(fil_path_to_mysql_datadir, TRUE);
03510
03511 if (dir == NULL) {
03512
03513 return(DB_ERROR);
03514 }
03515
03516 dbpath = static_cast<char *>(mem_alloc(dbpath_len));
03517
03518
03519
03520
03521 ret = fil_file_readdir_next_file(&err, fil_path_to_mysql_datadir, dir,
03522 &dbinfo);
03523 while (ret == 0) {
03524 ulint len;
03525
03526
03527 if (dbinfo.type == OS_FILE_TYPE_FILE
03528 || dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
03529
03530 goto next_datadir_item;
03531 }
03532
03533
03534
03535
03536 len = strlen(fil_path_to_mysql_datadir)
03537 + strlen (dbinfo.name) + 2;
03538 if (len > dbpath_len) {
03539 dbpath_len = len;
03540
03541 if (dbpath) {
03542 mem_free(dbpath);
03543 }
03544
03545 dbpath = static_cast<char *>(mem_alloc(dbpath_len));
03546 }
03547 sprintf(dbpath, "%s/%s", fil_path_to_mysql_datadir,
03548 dbinfo.name);
03549 srv_normalize_path_for_win(dbpath);
03550
03551 dbdir = os_file_opendir(dbpath, FALSE);
03552
03553 if (dbdir != NULL) {
03554
03555
03556
03557
03558
03559 ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
03560 &fileinfo);
03561 while (ret == 0) {
03562
03563
03564
03565 if (fileinfo.type == OS_FILE_TYPE_DIR) {
03566
03567 goto next_file_item;
03568 }
03569
03570
03571 if (strlen(fileinfo.name) > 4
03572 && 0 == strcmp(fileinfo.name
03573 + strlen(fileinfo.name) - 4,
03574 ".ibd")) {
03575
03576
03577 fil_load_single_table_tablespace(
03578 dbinfo.name, fileinfo.name);
03579 }
03580 next_file_item:
03581 ret = fil_file_readdir_next_file(&err,
03582 dbpath, dbdir,
03583 &fileinfo);
03584 }
03585
03586 if (0 != os_file_closedir(dbdir)) {
03587 fputs("InnoDB: Warning: could not"
03588 " close database directory ", stderr);
03589 ut_print_filename(stderr, dbpath);
03590 putc('\n', stderr);
03591
03592 err = DB_ERROR;
03593 }
03594 }
03595
03596 next_datadir_item:
03597 ret = fil_file_readdir_next_file(&err,
03598 fil_path_to_mysql_datadir,
03599 dir, &dbinfo);
03600 }
03601
03602 mem_free(dbpath);
03603
03604 if (0 != os_file_closedir(dir)) {
03605 fprintf(stderr,
03606 "InnoDB: Error: could not close MySQL datadir\n");
03607
03608 return(DB_ERROR);
03609 }
03610
03611 return(err);
03612 }
03613
03614
03618 UNIV_INTERN
03619 ibool
03620 fil_tablespace_deleted_or_being_deleted_in_mem(
03621
03622 ulint id,
03623 ib_int64_t version)
03626 {
03627 fil_space_t* space;
03628
03629 ut_ad(fil_system);
03630
03631 mutex_enter(&fil_system->mutex);
03632
03633 space = fil_space_get_by_id(id);
03634
03635 if (space == NULL || space->is_being_deleted) {
03636 mutex_exit(&fil_system->mutex);
03637
03638 return(TRUE);
03639 }
03640
03641 if (version != ((ib_int64_t)-1)
03642 && space->tablespace_version != version) {
03643 mutex_exit(&fil_system->mutex);
03644
03645 return(TRUE);
03646 }
03647
03648 mutex_exit(&fil_system->mutex);
03649
03650 return(FALSE);
03651 }
03652
03653
03656 UNIV_INTERN
03657 ibool
03658 fil_tablespace_exists_in_mem(
03659
03660 ulint id)
03661 {
03662 fil_space_t* space;
03663
03664 ut_ad(fil_system);
03665
03666 mutex_enter(&fil_system->mutex);
03667
03668 space = fil_space_get_by_id(id);
03669
03670 mutex_exit(&fil_system->mutex);
03671
03672 return(space != NULL);
03673 }
03674
03675
03680 UNIV_INTERN
03681 ibool
03682 fil_space_for_table_exists_in_mem(
03683
03684 ulint id,
03685 const char* name,
03688 ibool is_temp,
03690 ibool mark_space,
03696 ibool print_error_if_does_not_exist)
03701 {
03702 fil_space_t* tablespace;
03703 fil_space_t* space;
03704 char* path;
03705
03706 ut_ad(fil_system);
03707
03708 mutex_enter(&fil_system->mutex);
03709
03710 path = fil_make_ibd_name(name, is_temp);
03711
03712
03713
03714 space = fil_space_get_by_id(id);
03715
03716
03717
03718
03719 tablespace = fil_space_get_by_name(path);
03720 if (space && space == tablespace) {
03721
03722
03723 if (mark_space) {
03724 space->mark = TRUE;
03725 }
03726
03727 mem_free(path);
03728 mutex_exit(&fil_system->mutex);
03729
03730 return(TRUE);
03731 }
03732
03733 if (!print_error_if_does_not_exist) {
03734
03735 mem_free(path);
03736 mutex_exit(&fil_system->mutex);
03737
03738 return(FALSE);
03739 }
03740
03741 if (space == NULL) {
03742 if (tablespace == NULL) {
03743 ut_print_timestamp(stderr);
03744 fputs(" InnoDB: Error: table ", stderr);
03745 ut_print_filename(stderr, name);
03746 fprintf(stderr, "\n"
03747 "InnoDB: in InnoDB data dictionary"
03748 " has tablespace id %lu,\n"
03749 "InnoDB: but tablespace with that id"
03750 " or name does not exist. Have\n"
03751 "InnoDB: you deleted or moved .ibd files?\n"
03752 "InnoDB: This may also be a table created with"
03753 " CREATE TEMPORARY TABLE\n"
03754 "InnoDB: whose .ibd and .frm files"
03755 " MySQL automatically removed, but the\n"
03756 "InnoDB: table still exists in the"
03757 " InnoDB internal data dictionary.\n",
03758 (ulong) id);
03759 } else {
03760 ut_print_timestamp(stderr);
03761 fputs(" InnoDB: Error: table ", stderr);
03762 ut_print_filename(stderr, name);
03763 fprintf(stderr, "\n"
03764 "InnoDB: in InnoDB data dictionary has"
03765 " tablespace id %lu,\n"
03766 "InnoDB: but a tablespace with that id"
03767 " does not exist. There is\n"
03768 "InnoDB: a tablespace of name %s and id %lu,"
03769 " though. Have\n"
03770 "InnoDB: you deleted or moved .ibd files?\n",
03771 (ulong) id, tablespace->name,
03772 (ulong) tablespace->id);
03773 }
03774 error_exit:
03775 fputs("InnoDB: Please refer to\n"
03776 "InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n"
03777 "InnoDB: for how to resolve the issue.\n", stderr);
03778
03779 mem_free(path);
03780 mutex_exit(&fil_system->mutex);
03781
03782 return(FALSE);
03783 }
03784
03785 if (0 != strcmp(space->name, path)) {
03786 ut_print_timestamp(stderr);
03787 fputs(" InnoDB: Error: table ", stderr);
03788 ut_print_filename(stderr, name);
03789 fprintf(stderr, "\n"
03790 "InnoDB: in InnoDB data dictionary has"
03791 " tablespace id %lu,\n"
03792 "InnoDB: but the tablespace with that id"
03793 " has name %s.\n"
03794 "InnoDB: Have you deleted or moved .ibd files?\n",
03795 (ulong) id, space->name);
03796
03797 if (tablespace != NULL) {
03798 fputs("InnoDB: There is a tablespace"
03799 " with the right name\n"
03800 "InnoDB: ", stderr);
03801 ut_print_filename(stderr, tablespace->name);
03802 fprintf(stderr, ", but its id is %lu.\n",
03803 (ulong) tablespace->id);
03804 }
03805
03806 goto error_exit;
03807 }
03808
03809 mem_free(path);
03810 mutex_exit(&fil_system->mutex);
03811
03812 return(FALSE);
03813 }
03814
03815
03819 static
03820 ulint
03821 fil_get_space_id_for_table(
03822
03823 const char* name)
03825 {
03826 fil_space_t* tablespace;
03827 ulint id = ULINT_UNDEFINED;
03828 char* path;
03829
03830 ut_ad(fil_system);
03831
03832 mutex_enter(&fil_system->mutex);
03833
03834 path = fil_make_ibd_name(name, FALSE);
03835
03836
03837
03838
03839 tablespace = fil_space_get_by_name(path);
03840
03841 if (tablespace) {
03842 id = tablespace->id;
03843 }
03844
03845 mem_free(path);
03846
03847 mutex_exit(&fil_system->mutex);
03848
03849 return(id);
03850 }
03851
03852
03857 UNIV_INTERN
03858 ibool
03859 fil_extend_space_to_desired_size(
03860
03861 ulint* actual_size,
03864 ulint space_id,
03865 ulint size_after_extend)
03868 {
03869 fil_node_t* node;
03870 fil_space_t* space;
03871 byte* buf2;
03872 byte* buf;
03873 ulint buf_size;
03874 ulint start_page_no;
03875 ulint file_start_page_no;
03876 ulint offset_high;
03877 ulint offset_low;
03878 ulint page_size;
03879 ibool success = TRUE;
03880
03881 fil_mutex_enter_and_prepare_for_io(space_id);
03882
03883 space = fil_space_get_by_id(space_id);
03884 ut_a(space);
03885
03886 if (space->size >= size_after_extend) {
03887
03888
03889 *actual_size = space->size;
03890
03891 mutex_exit(&fil_system->mutex);
03892
03893 return(TRUE);
03894 }
03895
03896 page_size = dict_table_flags_to_zip_size(space->flags);
03897 if (!page_size) {
03898 page_size = UNIV_PAGE_SIZE;
03899 }
03900
03901 node = UT_LIST_GET_LAST(space->chain);
03902
03903 fil_node_prepare_for_io(node, fil_system, space);
03904
03905 start_page_no = space->size;
03906 file_start_page_no = space->size - node->size;
03907
03908
03909 buf_size = ut_min(64, size_after_extend - start_page_no) * page_size;
03910 buf2 = static_cast<byte *>(mem_alloc(buf_size + page_size));
03911 buf = static_cast<byte *>(ut_align(buf2, page_size));
03912
03913 memset(buf, 0, buf_size);
03914
03915 while (start_page_no < size_after_extend) {
03916 ulint n_pages = ut_min(buf_size / page_size,
03917 size_after_extend - start_page_no);
03918
03919 offset_high = (start_page_no - file_start_page_no)
03920 / (4096 * ((1024 * 1024) / page_size));
03921 offset_low = ((start_page_no - file_start_page_no)
03922 % (4096 * ((1024 * 1024) / page_size)))
03923 * page_size;
03924 #ifdef UNIV_HOTBACKUP
03925 success = os_file_write(node->name, node->handle, buf,
03926 offset_low, offset_high,
03927 page_size * n_pages);
03928 #else
03929 success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC,
03930 node->name, node->handle, buf,
03931 offset_low, offset_high,
03932 page_size * n_pages,
03933 NULL, NULL);
03934 #endif
03935 if (success) {
03936 node->size += n_pages;
03937 space->size += n_pages;
03938
03939 os_has_said_disk_full = FALSE;
03940 } else {
03941
03942
03943
03944 n_pages = ((ulint)
03945 (os_file_get_size_as_iblonglong(
03946 node->handle)
03947 / page_size)) - node->size;
03948
03949 node->size += n_pages;
03950 space->size += n_pages;
03951
03952 break;
03953 }
03954
03955 start_page_no += n_pages;
03956 }
03957
03958 mem_free(buf2);
03959
03960 fil_node_complete_io(node, fil_system, OS_FILE_WRITE);
03961
03962 *actual_size = space->size;
03963
03964 #ifndef UNIV_HOTBACKUP
03965 if (space_id == 0) {
03966 ulint pages_per_mb = (1024 * 1024) / page_size;
03967
03968
03969
03970
03971 srv_data_file_sizes[srv_n_data_files - 1]
03972 = (node->size / pages_per_mb) * pages_per_mb;
03973 }
03974 #endif
03975
03976
03977
03978
03979 mutex_exit(&fil_system->mutex);
03980
03981 fil_flush(space_id);
03982
03983 return(success);
03984 }
03985
03986 #ifdef UNIV_HOTBACKUP
03987
03992 UNIV_INTERN
03993 void
03994 fil_extend_tablespaces_to_stored_len(void)
03995
03996 {
03997 fil_space_t* space;
03998 byte* buf;
03999 ulint actual_size;
04000 ulint size_in_header;
04001 ulint error;
04002 ibool success;
04003
04004 buf = mem_alloc(UNIV_PAGE_SIZE);
04005
04006 mutex_enter(&fil_system->mutex);
04007
04008 space = UT_LIST_GET_FIRST(fil_system->space_list);
04009
04010 while (space) {
04011 ut_a(space->purpose == FIL_TABLESPACE);
04012
04013 mutex_exit(&fil_system->mutex);
04014
04015
04016 error = fil_read(TRUE, space->id,
04017 dict_table_flags_to_zip_size(space->flags),
04018 0, 0, UNIV_PAGE_SIZE, buf, NULL);
04019 ut_a(error == DB_SUCCESS);
04020
04021 size_in_header = fsp_get_size_low(buf);
04022
04023 success = fil_extend_space_to_desired_size(
04024 &actual_size, space->id, size_in_header);
04025 if (!success) {
04026 fprintf(stderr,
04027 "InnoDB: Error: could not extend the"
04028 " tablespace of %s\n"
04029 "InnoDB: to the size stored in header,"
04030 " %lu pages;\n"
04031 "InnoDB: size after extension %lu pages\n"
04032 "InnoDB: Check that you have free disk space"
04033 " and retry!\n",
04034 space->name, size_in_header, actual_size);
04035 exit(1);
04036 }
04037
04038 mutex_enter(&fil_system->mutex);
04039
04040 space = UT_LIST_GET_NEXT(space_list, space);
04041 }
04042
04043 mutex_exit(&fil_system->mutex);
04044
04045 mem_free(buf);
04046 }
04047 #endif
04048
04049
04050
04051
04054 UNIV_INTERN
04055 ibool
04056 fil_space_reserve_free_extents(
04057
04058 ulint id,
04059 ulint n_free_now,
04060 ulint n_to_reserve)
04061 {
04062 fil_space_t* space;
04063 ibool success;
04064
04065 ut_ad(fil_system);
04066
04067 mutex_enter(&fil_system->mutex);
04068
04069 space = fil_space_get_by_id(id);
04070
04071 ut_a(space);
04072
04073 if (space->n_reserved_extents + n_to_reserve > n_free_now) {
04074 success = FALSE;
04075 } else {
04076 space->n_reserved_extents += n_to_reserve;
04077 success = TRUE;
04078 }
04079
04080 mutex_exit(&fil_system->mutex);
04081
04082 return(success);
04083 }
04084
04085
04087 UNIV_INTERN
04088 void
04089 fil_space_release_free_extents(
04090
04091 ulint id,
04092 ulint n_reserved)
04093 {
04094 fil_space_t* space;
04095
04096 ut_ad(fil_system);
04097
04098 mutex_enter(&fil_system->mutex);
04099
04100 space = fil_space_get_by_id(id);
04101
04102 ut_a(space);
04103 ut_a(space->n_reserved_extents >= n_reserved);
04104
04105 space->n_reserved_extents -= n_reserved;
04106
04107 mutex_exit(&fil_system->mutex);
04108 }
04109
04110
04113 UNIV_INTERN
04114 ulint
04115 fil_space_get_n_reserved_extents(
04116
04117 ulint id)
04118 {
04119 fil_space_t* space;
04120 ulint n;
04121
04122 ut_ad(fil_system);
04123
04124 mutex_enter(&fil_system->mutex);
04125
04126 space = fil_space_get_by_id(id);
04127
04128 ut_a(space);
04129
04130 n = space->n_reserved_extents;
04131
04132 mutex_exit(&fil_system->mutex);
04133
04134 return(n);
04135 }
04136
04137
04138
04139
04146 static
04147 void
04148 fil_node_prepare_for_io(
04149
04150 fil_node_t* node,
04151 fil_system_t* system,
04152 fil_space_t* space)
04153 {
04154 ut_ad(node && system && space);
04155 ut_ad(mutex_own(&(system->mutex)));
04156
04157 if (system->n_open > system->max_n_open + 5) {
04158 ut_print_timestamp(stderr);
04159 fprintf(stderr,
04160 " InnoDB: Warning: open files %lu"
04161 " exceeds the limit %lu\n",
04162 (ulong) system->n_open,
04163 (ulong) system->max_n_open);
04164 }
04165
04166 if (node->open == FALSE) {
04167
04168 ut_a(node->n_pending == 0);
04169
04170 fil_node_open_file(node, system, space);
04171 }
04172
04173 if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE
04174 && space->id != 0) {
04175
04176
04177 ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
04178
04179 UT_LIST_REMOVE(LRU, system->LRU, node);
04180 }
04181
04182 node->n_pending++;
04183 }
04184
04185
04188 static
04189 void
04190 fil_node_complete_io(
04191
04192 fil_node_t* node,
04193 fil_system_t* system,
04194 ulint type)
04197 {
04198 ut_ad(node);
04199 ut_ad(system);
04200 ut_ad(mutex_own(&(system->mutex)));
04201
04202 ut_a(node->n_pending > 0);
04203
04204 node->n_pending--;
04205
04206 if (type == OS_FILE_WRITE) {
04207 system->modification_counter++;
04208 node->modification_counter = system->modification_counter;
04209
04210 if (!node->space->is_in_unflushed_spaces) {
04211
04212 node->space->is_in_unflushed_spaces = TRUE;
04213 UT_LIST_ADD_FIRST(unflushed_spaces,
04214 system->unflushed_spaces,
04215 node->space);
04216 }
04217 }
04218
04219 if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE
04220 && node->space->id != 0) {
04221
04222 UT_LIST_ADD_FIRST(LRU, system->LRU, node);
04223 }
04224 }
04225
04226
04228 static
04229 void
04230 fil_report_invalid_page_access(
04231
04232 ulint block_offset,
04233 ulint space_id,
04234 const char* space_name,
04235 ulint byte_offset,
04236 ulint len,
04237 ulint type)
04238 {
04239 fprintf(stderr,
04240 "InnoDB: Error: trying to access page number %lu"
04241 " in space %lu,\n"
04242 "InnoDB: space name %s,\n"
04243 "InnoDB: which is outside the tablespace bounds.\n"
04244 "InnoDB: Byte offset %lu, len %lu, i/o type %lu.\n"
04245 "InnoDB: If you get this error at mysqld startup,"
04246 " please check that\n"
04247 "InnoDB: your my.cnf matches the ibdata files"
04248 " that you have in the\n"
04249 "InnoDB: MySQL server.\n",
04250 (ulong) block_offset, (ulong) space_id, space_name,
04251 (ulong) byte_offset, (ulong) len, (ulong) type);
04252 }
04253
04254
04258 UNIV_INTERN
04259 ulint
04260 fil_io(
04261
04262 ulint type,
04271 ibool sync,
04272 ulint space_id,
04273 ulint zip_size,
04275 ulint block_offset,
04276 ulint byte_offset,
04279 ulint len,
04282 void* buf,
04285 void* message)
04287 {
04288 ulint mode;
04289 fil_space_t* space;
04290 fil_node_t* node;
04291 ulint offset_high;
04292 ulint offset_low;
04293 ibool ret;
04294 ulint is_log;
04295 ulint wake_later;
04296
04297 is_log = type & OS_FILE_LOG;
04298 type = type & ~OS_FILE_LOG;
04299
04300 wake_later = type & OS_AIO_SIMULATED_WAKE_LATER;
04301 type = type & ~OS_AIO_SIMULATED_WAKE_LATER;
04302
04303 ut_ad(byte_offset < UNIV_PAGE_SIZE);
04304 ut_ad(!zip_size || !byte_offset);
04305 ut_ad(ut_is_2pow(zip_size));
04306 ut_ad(buf);
04307 ut_ad(len > 0);
04308 #if (1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE
04309 # error "(1 << UNIV_PAGE_SIZE_SHIFT) != UNIV_PAGE_SIZE"
04310 #endif
04311 ut_ad(fil_validate());
04312 #ifndef UNIV_HOTBACKUP
04313 # ifndef UNIV_LOG_DEBUG
04314
04315 ut_ad(recv_no_ibuf_operations || (type == OS_FILE_WRITE)
04316 || !ibuf_bitmap_page(zip_size, block_offset)
04317 || sync || is_log);
04318 ut_ad(!ibuf_inside() || is_log || (type == OS_FILE_WRITE)
04319 || ibuf_page(space_id, zip_size, block_offset, NULL));
04320 # endif
04321 if (sync) {
04322 mode = OS_AIO_SYNC;
04323 } else if (is_log) {
04324 mode = OS_AIO_LOG;
04325 } else if (type == OS_FILE_READ
04326 && !recv_no_ibuf_operations
04327 && ibuf_page(space_id, zip_size, block_offset, NULL)) {
04328 mode = OS_AIO_IBUF;
04329 } else {
04330 mode = OS_AIO_NORMAL;
04331 }
04332 #else
04333 ut_a(sync);
04334 mode = OS_AIO_SYNC;
04335 #endif
04336
04337 if (type == OS_FILE_READ) {
04338 srv_data_read+= len;
04339 } else if (type == OS_FILE_WRITE) {
04340 srv_data_written+= len;
04341 }
04342
04343
04344
04345
04346 fil_mutex_enter_and_prepare_for_io(space_id);
04347
04348 space = fil_space_get_by_id(space_id);
04349
04350 if (!space) {
04351 mutex_exit(&fil_system->mutex);
04352
04353 ut_print_timestamp(stderr);
04354 fprintf(stderr,
04355 " InnoDB: Error: trying to do i/o"
04356 " to a tablespace which does not exist.\n"
04357 "InnoDB: i/o type %lu, space id %lu,"
04358 " page no. %lu, i/o length %lu bytes\n",
04359 (ulong) type, (ulong) space_id, (ulong) block_offset,
04360 (ulong) len);
04361
04362 return(DB_TABLESPACE_DELETED);
04363 }
04364
04365 ut_ad((mode != OS_AIO_IBUF) || (space->purpose == FIL_TABLESPACE));
04366
04367 node = UT_LIST_GET_FIRST(space->chain);
04368
04369 for (;;) {
04370 if (UNIV_UNLIKELY(node == NULL)) {
04371 fil_report_invalid_page_access(
04372 block_offset, space_id, space->name,
04373 byte_offset, len, type);
04374
04375 ut_error;
04376 }
04377
04378 if (space->id != 0 && node->size == 0) {
04379
04380
04381
04382 break;
04383 }
04384
04385 if (node->size > block_offset) {
04386
04387 break;
04388 } else {
04389 block_offset -= node->size;
04390 node = UT_LIST_GET_NEXT(chain, node);
04391 }
04392 }
04393
04394
04395 fil_node_prepare_for_io(node, fil_system, space);
04396
04397
04398
04399 if (UNIV_UNLIKELY(node->size <= block_offset)
04400 && space->id != 0 && space->purpose == FIL_TABLESPACE) {
04401
04402 fil_report_invalid_page_access(
04403 block_offset, space_id, space->name, byte_offset,
04404 len, type);
04405
04406 ut_error;
04407 }
04408
04409
04410 mutex_exit(&fil_system->mutex);
04411
04412
04413
04414 if (!zip_size) {
04415 offset_high = (block_offset >> (32 - UNIV_PAGE_SIZE_SHIFT));
04416 offset_low = ((block_offset << UNIV_PAGE_SIZE_SHIFT)
04417 & 0xFFFFFFFFUL) + byte_offset;
04418
04419 ut_a(node->size - block_offset
04420 >= ((byte_offset + len + (UNIV_PAGE_SIZE - 1))
04421 / UNIV_PAGE_SIZE));
04422 } else {
04423 ulint zip_size_shift;
04424 switch (zip_size) {
04425 case 1024: zip_size_shift = 10; break;
04426 case 2048: zip_size_shift = 11; break;
04427 case 4096: zip_size_shift = 12; break;
04428 case 8192: zip_size_shift = 13; break;
04429 case 16384: zip_size_shift = 14; break;
04430 default: ut_error;
04431 }
04432 offset_high = block_offset >> (32 - zip_size_shift);
04433 offset_low = (block_offset << zip_size_shift & 0xFFFFFFFFUL)
04434 + byte_offset;
04435 ut_a(node->size - block_offset
04436 >= (len + (zip_size - 1)) / zip_size);
04437 }
04438
04439
04440
04441 ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
04442 ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
04443
04444 #ifdef UNIV_HOTBACKUP
04445
04446 if (type == OS_FILE_READ) {
04447 ret = os_file_read(node->handle, buf, offset_low, offset_high,
04448 len);
04449 } else {
04450 ret = os_file_write(node->name, node->handle, buf,
04451 offset_low, offset_high, len);
04452 }
04453 #else
04454
04455 ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
04456 offset_low, offset_high, len, node, message);
04457 #endif
04458 ut_a(ret);
04459
04460 if (mode == OS_AIO_SYNC) {
04461
04462
04463
04464 mutex_enter(&fil_system->mutex);
04465
04466 fil_node_complete_io(node, fil_system, type);
04467
04468 mutex_exit(&fil_system->mutex);
04469
04470 ut_ad(fil_validate());
04471 }
04472
04473 return(DB_SUCCESS);
04474 }
04475
04476 #ifndef UNIV_HOTBACKUP
04477
04482 UNIV_INTERN
04483 void
04484 fil_aio_wait(
04485
04486 ulint segment)
04488 {
04489 ibool ret;
04490 fil_node_t* fil_node;
04491 void* message;
04492 ulint type;
04493
04494 ut_ad(fil_validate());
04495
04496 if (srv_use_native_aio) {
04497 srv_set_io_thread_op_info(segment, "native aio handle");
04498 #ifdef WIN_ASYNC_IO
04499 ret = os_aio_windows_handle(segment, 0, &fil_node,
04500 &message, &type);
04501 #elif defined(LINUX_NATIVE_AIO)
04502 ret = os_aio_linux_handle(segment, &fil_node,
04503 &message, &type);
04504 #else
04505 ret = 0;
04506 ut_error;
04507 #endif
04508 } else {
04509 srv_set_io_thread_op_info(segment, "simulated aio handle");
04510
04511 ret = os_aio_simulated_handle(segment, &fil_node,
04512 &message, &type);
04513 }
04514
04515 ut_a(ret);
04516
04517 srv_set_io_thread_op_info(segment, "complete io for fil node");
04518
04519 mutex_enter(&fil_system->mutex);
04520
04521 fil_node_complete_io(fil_node, fil_system, type);
04522
04523 mutex_exit(&fil_system->mutex);
04524
04525 ut_ad(fil_validate());
04526
04527
04528
04529
04530
04531
04532
04533 if (fil_node->space->purpose == FIL_TABLESPACE) {
04534 srv_set_io_thread_op_info(segment, "complete io for buf page");
04535 buf_page_io_complete(static_cast<buf_page_t *>(message));
04536 } else {
04537 srv_set_io_thread_op_info(segment, "complete io for log");
04538 log_io_complete(static_cast<log_group_t *>(message));
04539 }
04540 }
04541 #endif
04542
04543
04546 UNIV_INTERN
04547 void
04548 fil_flush(
04549
04550 ulint space_id)
04552 {
04553 fil_space_t* space;
04554 fil_node_t* node;
04555 os_file_t file;
04556 ib_int64_t old_mod_counter;
04557
04558 mutex_enter(&fil_system->mutex);
04559
04560 space = fil_space_get_by_id(space_id);
04561
04562 if (!space || space->is_being_deleted) {
04563 mutex_exit(&fil_system->mutex);
04564
04565 return;
04566 }
04567
04568 space->n_pending_flushes++;
04570 node = UT_LIST_GET_FIRST(space->chain);
04571
04572 while (node) {
04573 if (node->modification_counter > node->flush_counter) {
04574 ut_a(node->open);
04575
04576
04577
04578 old_mod_counter = node->modification_counter;
04579
04580 if (space->purpose == FIL_TABLESPACE) {
04581 fil_n_pending_tablespace_flushes++;
04582 } else {
04583 fil_n_pending_log_flushes++;
04584 fil_n_log_flushes++;
04585 }
04586 #ifdef __WIN__
04587 if (node->is_raw_disk) {
04588
04589 goto skip_flush;
04590 }
04591 #endif
04592 retry:
04593 if (node->n_pending_flushes > 0) {
04594
04595
04596
04597
04598
04599 mutex_exit(&fil_system->mutex);
04600
04601 os_thread_sleep(20000);
04602
04603 mutex_enter(&fil_system->mutex);
04604
04605 if (node->flush_counter >= old_mod_counter) {
04606
04607 goto skip_flush;
04608 }
04609
04610 goto retry;
04611 }
04612
04613 ut_a(node->open);
04614 file = node->handle;
04615 node->n_pending_flushes++;
04616
04617 mutex_exit(&fil_system->mutex);
04618
04619
04620
04621
04622 os_file_flush(file);
04623
04624 mutex_enter(&fil_system->mutex);
04625
04626 node->n_pending_flushes--;
04627 skip_flush:
04628 if (node->flush_counter < old_mod_counter) {
04629 node->flush_counter = old_mod_counter;
04630
04631 if (space->is_in_unflushed_spaces
04632 && fil_space_is_flushed(space)) {
04633
04634 space->is_in_unflushed_spaces = FALSE;
04635
04636 UT_LIST_REMOVE(
04637 unflushed_spaces,
04638 fil_system->unflushed_spaces,
04639 space);
04640 }
04641 }
04642
04643 if (space->purpose == FIL_TABLESPACE) {
04644 fil_n_pending_tablespace_flushes--;
04645 } else {
04646 fil_n_pending_log_flushes--;
04647 }
04648 }
04649
04650 node = UT_LIST_GET_NEXT(chain, node);
04651 }
04652
04653 space->n_pending_flushes--;
04654
04655 mutex_exit(&fil_system->mutex);
04656 }
04657
04658
04661 UNIV_INTERN
04662 void
04663 fil_flush_file_spaces(
04664
04665 ulint purpose)
04666 {
04667 fil_space_t* space;
04668 ulint* space_ids;
04669 ulint n_space_ids;
04670 ulint i;
04671
04672 mutex_enter(&fil_system->mutex);
04673
04674 n_space_ids = UT_LIST_GET_LEN(fil_system->unflushed_spaces);
04675 if (n_space_ids == 0) {
04676
04677 mutex_exit(&fil_system->mutex);
04678 return;
04679 }
04680
04681
04682
04683
04684
04685 space_ids = static_cast<unsigned long *>(mem_alloc(n_space_ids * sizeof *space_ids));
04686
04687 n_space_ids = 0;
04688
04689 for (space = UT_LIST_GET_FIRST(fil_system->unflushed_spaces);
04690 space;
04691 space = UT_LIST_GET_NEXT(unflushed_spaces, space)) {
04692
04693 if (space->purpose == purpose && !space->is_being_deleted) {
04694
04695 space_ids[n_space_ids++] = space->id;
04696 }
04697 }
04698
04699 mutex_exit(&fil_system->mutex);
04700
04701
04702
04703 for (i = 0; i < n_space_ids; i++) {
04704
04705 fil_flush(space_ids[i]);
04706 }
04707
04708 mem_free(space_ids);
04709 }
04710
04711
04714 UNIV_INTERN
04715 ibool
04716 fil_validate(void)
04717
04718 {
04719 fil_space_t* space;
04720 fil_node_t* fil_node;
04721 ulint n_open = 0;
04722 ulint i;
04723
04724 mutex_enter(&fil_system->mutex);
04725
04726
04727
04728 for (i = 0; i < hash_get_n_cells(fil_system->spaces); i++) {
04729
04730 space = static_cast<fil_space_t *>(HASH_GET_FIRST(fil_system->spaces, i));
04731
04732 while (space != NULL) {
04733 UT_LIST_VALIDATE(chain, fil_node_t, space->chain,
04734 ut_a(ut_list_node_313->open
04735 || !ut_list_node_313->n_pending));
04736
04737 fil_node = UT_LIST_GET_FIRST(space->chain);
04738
04739 while (fil_node != NULL) {
04740 if (fil_node->n_pending > 0) {
04741 ut_a(fil_node->open);
04742 }
04743
04744 if (fil_node->open) {
04745 n_open++;
04746 }
04747 fil_node = UT_LIST_GET_NEXT(chain, fil_node);
04748 }
04749 space = static_cast<fil_space_t *>(HASH_GET_NEXT(hash, space));
04750 }
04751 }
04752
04753 ut_a(fil_system->n_open == n_open);
04754
04755 UT_LIST_VALIDATE(LRU, fil_node_t, fil_system->LRU, (void) 0);
04756
04757 fil_node = UT_LIST_GET_FIRST(fil_system->LRU);
04758
04759 while (fil_node != NULL) {
04760 ut_a(fil_node->n_pending == 0);
04761 ut_a(fil_node->open);
04762 ut_a(fil_node->space->purpose == FIL_TABLESPACE);
04763 ut_a(fil_node->space->id != 0);
04764
04765 fil_node = UT_LIST_GET_NEXT(LRU, fil_node);
04766 }
04767
04768 mutex_exit(&fil_system->mutex);
04769
04770 return(TRUE);
04771 }
04772
04773
04776 UNIV_INTERN
04777 ibool
04778 fil_addr_is_null(
04779
04780 fil_addr_t addr)
04781 {
04782 return(addr.page == FIL_NULL);
04783 }
04784
04785
04788 UNIV_INTERN
04789 ulint
04790 fil_page_get_prev(
04791
04792 const byte* page)
04793 {
04794 return(mach_read_from_4(page + FIL_PAGE_PREV));
04795 }
04796
04797
04800 UNIV_INTERN
04801 ulint
04802 fil_page_get_next(
04803
04804 const byte* page)
04805 {
04806 return(mach_read_from_4(page + FIL_PAGE_NEXT));
04807 }
04808
04809
04811 UNIV_INTERN
04812 void
04813 fil_page_set_type(
04814
04815 byte* page,
04816 ulint type)
04817 {
04818 ut_ad(page);
04819
04820 mach_write_to_2(page + FIL_PAGE_TYPE, type);
04821 }
04822
04823
04827 UNIV_INTERN
04828 ulint
04829 fil_page_get_type(
04830
04831 const byte* page)
04832 {
04833 ut_ad(page);
04834
04835 return(mach_read_from_2(page + FIL_PAGE_TYPE));
04836 }
04837
04838
04840 UNIV_INTERN
04841 void
04842 fil_close(void)
04843
04844 {
04845 #ifndef UNIV_HOTBACKUP
04846
04847 ut_ad(fil_system->mutex.magic_n == 0);
04848 #endif
04849
04850 hash_table_free(fil_system->spaces);
04851
04852 hash_table_free(fil_system->name_hash);
04853
04854 ut_a(UT_LIST_GET_LEN(fil_system->LRU) == 0);
04855 ut_a(UT_LIST_GET_LEN(fil_system->unflushed_spaces) == 0);
04856 ut_a(UT_LIST_GET_LEN(fil_system->space_list) == 0);
04857
04858 mem_free(fil_system);
04859
04860 fil_system = NULL;
04861 }