MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
fil0fil.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************/
26 #include "fil0fil.h"
27 
28 #include <debug_sync.h>
29 #include <my_dbug.h>
30 
31 #include "mem0mem.h"
32 #include "hash0hash.h"
33 #include "os0file.h"
34 #include "mach0data.h"
35 #include "buf0buf.h"
36 #include "buf0flu.h"
37 #include "log0recv.h"
38 #include "fsp0fsp.h"
39 #include "srv0srv.h"
40 #include "srv0start.h"
41 #include "mtr0mtr.h"
42 #include "mtr0log.h"
43 #include "dict0dict.h"
44 #include "page0page.h"
45 #include "page0zip.h"
46 #include "trx0sys.h"
47 #include "row0mysql.h"
48 #ifndef UNIV_HOTBACKUP
49 # include "buf0lru.h"
50 # include "ibuf0ibuf.h"
51 # include "sync0sync.h"
52 # include "os0sync.h"
53 #else /* !UNIV_HOTBACKUP */
54 # include "srv0srv.h"
55 static ulint srv_data_read, srv_data_written;
56 #endif /* !UNIV_HOTBACKUP */
57 
58 /*
59  IMPLEMENTATION OF THE TABLESPACE MEMORY CACHE
60  =============================================
61 
62 The tablespace cache is responsible for providing fast read/write access to
63 tablespaces and logs of the database. File creation and deletion is done
64 in other modules which know more of the logic of the operation, however.
65 
66 A tablespace consists of a chain of files. The size of the files does not
67 have to be divisible by the database block size, because we may just leave
68 the last incomplete block unused. When a new file is appended to the
69 tablespace, the maximum size of the file is also specified. At the moment,
70 we think that it is best to extend the file to its maximum size already at
71 the creation of the file, because then we can avoid dynamically extending
72 the file when more space is needed for the tablespace.
73 
74 A block's position in the tablespace is specified with a 32-bit unsigned
75 integer. The files in the chain are thought to be catenated, and the block
76 corresponding to an address n is the nth block in the catenated file (where
77 the first block is named the 0th block, and the incomplete block fragments
78 at the end of files are not taken into account). A tablespace can be extended
79 by appending a new file at the end of the chain.
80 
81 Our tablespace concept is similar to the one of Oracle.
82 
83 To acquire more speed in disk transfers, a technique called disk striping is
84 sometimes used. This means that logical block addresses are divided in a
85 round-robin fashion across several disks. Windows NT supports disk striping,
86 so there we do not need to support it in the database. Disk striping is
87 implemented in hardware in RAID disks. We conclude that it is not necessary
88 to implement it in the database. Oracle 7 does not support disk striping,
89 either.
90 
91 Another trick used at some database sites is replacing tablespace files by
92 raw disks, that is, the whole physical disk drive, or a partition of it, is
93 opened as a single file, and it is accessed through byte offsets calculated
94 from the start of the disk or the partition. This is recommended in some
95 books on database tuning to achieve more speed in i/o. Using raw disk
96 certainly prevents the OS from fragmenting disk space, but it is not clear
97 if it really adds speed. We measured on the Pentium 100 MHz + NT + NTFS file
98 system + EIDE Conner disk only a negligible difference in speed when reading
99 from a file, versus reading from a raw disk.
100 
101 To have fast access to a tablespace or a log file, we put the data structures
102 to a hash table. Each tablespace and log file is given an unique 32-bit
103 identifier.
104 
105 Some operating systems do not support many open files at the same time,
106 though NT seems to tolerate at least 900 open files. Therefore, we put the
107 open files in an LRU-list. If we need to open another file, we may close the
108 file at the end of the LRU-list. When an i/o-operation is pending on a file,
109 the file cannot be closed. We take the file nodes with pending i/o-operations
110 out of the LRU-list and keep a count of pending operations. When an operation
111 completes, we decrement the count and return the file node to the LRU-list if
112 the count drops to zero. */
113 
117 UNIV_INTERN const char* fil_path_to_mysql_datadir = ".";
118 
120 UNIV_INTERN ulint fil_n_log_flushes = 0;
121 
123 UNIV_INTERN ulint fil_n_pending_log_flushes = 0;
125 UNIV_INTERN ulint fil_n_pending_tablespace_flushes = 0;
126 
128 UNIV_INTERN ulint fil_n_file_opened = 0;
129 
131 UNIV_INTERN fil_addr_t fil_addr_null = {FIL_NULL, 0};
132 
133 #ifdef UNIV_PFS_MUTEX
134 /* Key to register fil_system_mutex with performance schema */
135 UNIV_INTERN mysql_pfs_key_t fil_system_mutex_key;
136 #endif /* UNIV_PFS_MUTEX */
137 
138 #ifdef UNIV_PFS_RWLOCK
139 /* Key to register file space latch with performance schema */
140 UNIV_INTERN mysql_pfs_key_t fil_space_latch_key;
141 #endif /* UNIV_PFS_RWLOCK */
142 
144 struct fil_node_t {
147  char* name;
148  ibool open;
152  ibool is_raw_disk;
154  ulint size;
157  ulint n_pending;
161  ulint n_pending_flushes;
165  ibool being_extended;
170  ib_int64_t flush_counter;
173  UT_LIST_NODE_T(fil_node_t) chain;
177  ulint magic_n;
178 };
179 
181 #define FIL_NODE_MAGIC_N 89389
182 
184 struct fil_space_t {
185  char* name;
187  ulint id;
188  ib_int64_t tablespace_version;
194  ibool mark;
198  ibool stop_ios;
202  ibool stop_new_ops;
214  ulint purpose;
216  UT_LIST_BASE_NODE_T(fil_node_t) chain;
218  ulint size;
222  ulint flags;
225  ulint n_reserved_extents;
231  ulint n_pending_ops;
238  hash_node_t hash;
239  hash_node_t name_hash;
240 #ifndef UNIV_HOTBACKUP
241  rw_lock_t latch;
243 #endif /* !UNIV_HOTBACKUP */
244  UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
247  bool is_in_unflushed_spaces;
250  UT_LIST_NODE_T(fil_space_t) space_list;
252  ulint magic_n;
253 };
254 
256 #define FIL_SPACE_MAGIC_N 89472
257 
261 struct fil_system_t {
262 #ifndef UNIV_HOTBACKUP
264 #endif /* !UNIV_HOTBACKUP */
265  hash_table_t* spaces;
268  hash_table_t* name_hash;
270  UT_LIST_BASE_NODE_T(fil_node_t) LRU;
281  UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
287  ulint n_open;
288  ulint max_n_open;
292  ulint max_assigned_id;
298  ib_int64_t tablespace_version;
306  UT_LIST_BASE_NODE_T(fil_space_t) space_list;
308  ibool space_id_reuse_warned;
309  /* !< TRUE if fil_space_create()
310  has issued a warning about
311  potential space_id reuse */
312 };
313 
316 static fil_system_t* fil_system = NULL;
317 
319 # define fil_is_user_tablespace_id(i) ((i) > srv_undo_tablespaces_open)
320 
322 #ifndef __WIN__
323 # define fil_buffering_disabled(s) \
324  ((s)->purpose == FIL_TABLESPACE \
325  && srv_unix_file_flush_method \
326  == SRV_UNIX_O_DIRECT_NO_FSYNC)
327 #else /* __WIN__ */
328 # define fil_buffering_disabled(s) (0)
329 #endif /* __WIN__ */
330 
331 #ifdef UNIV_DEBUG
332 
333 # define FIL_VALIDATE_SKIP 17
334 
335 /******************************************************************/
338 static
339 ibool
340 fil_validate_skip(void)
341 /*===================*/
342 {
345  static int fil_validate_count = FIL_VALIDATE_SKIP;
346 
347  /* There is a race condition below, but it does not matter,
348  because this call is only for heuristic purposes. We want to
349  reduce the call frequency of the costly fil_validate() check
350  in debug builds. */
351  if (--fil_validate_count > 0) {
352  return(TRUE);
353  }
354 
355  fil_validate_count = FIL_VALIDATE_SKIP;
356  return(fil_validate());
357 }
358 #endif /* UNIV_DEBUG */
359 
360 /********************************************************************/
363 UNIV_INLINE
364 ibool
366 /*=====================*/
367  const fil_space_t* space)
368 {
369  return(space->purpose == FIL_TABLESPACE
370  && fil_is_user_tablespace_id(space->id));
371 }
372 
373 /********************************************************************/
381 static
382 bool
383 fil_node_prepare_for_io(
384 /*====================*/
385  fil_node_t* node,
386  fil_system_t* system,
387  fil_space_t* space);
388 /********************************************************************/
391 static
392 void
393 fil_node_complete_io(
394 /*=================*/
395  fil_node_t* node,
396  fil_system_t* system,
397  ulint type);
400 /*******************************************************************/
405 static
406 ibool
407 fil_space_free(
408 /*===========*/
409  ulint id, /* in: space id */
410  ibool x_latched); /* in: TRUE if caller has space->latch
411  in X mode */
412 /********************************************************************/
418 UNIV_INLINE
419 dberr_t
421 /*=====*/
422  bool sync,
423  ulint space_id,
424  ulint zip_size,
426  ulint block_offset,
427  ulint byte_offset,
429  ulint len,
432  void* buf,
434  void* message)
436 {
437  return(fil_io(OS_FILE_READ, sync, space_id, zip_size, block_offset,
438  byte_offset, len, buf, message));
439 }
440 
441 /********************************************************************/
447 UNIV_INLINE
448 dberr_t
450 /*======*/
451  bool sync,
452  ulint space_id,
453  ulint zip_size,
455  ulint block_offset,
456  ulint byte_offset,
458  ulint len,
461  void* buf,
463  void* message)
465 {
467 
468  return(fil_io(OS_FILE_WRITE, sync, space_id, zip_size, block_offset,
469  byte_offset, len, buf, message));
470 }
471 
472 /*******************************************************************/
474 UNIV_INLINE
477 /*================*/
478  ulint id)
479 {
481 
482  ut_ad(mutex_own(&fil_system->mutex));
483 
484  HASH_SEARCH(hash, fil_system->spaces, id,
485  fil_space_t*, space,
486  ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
487  space->id == id);
488 
489  return(space);
490 }
491 
492 /*******************************************************************/
494 UNIV_INLINE
497 /*==================*/
498  const char* name)
499 {
501  ulint fold;
502 
503  ut_ad(mutex_own(&fil_system->mutex));
504 
505  fold = ut_fold_string(name);
506 
507  HASH_SEARCH(name_hash, fil_system->name_hash, fold,
508  fil_space_t*, space,
509  ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
510  !strcmp(name, space->name));
511 
512  return(space);
513 }
514 
515 #ifndef UNIV_HOTBACKUP
516 /*******************************************************************/
520 UNIV_INTERN
521 ib_int64_t
523 /*==================*/
524  ulint id)
525 {
527  ib_int64_t version = -1;
528 
529  ut_ad(fil_system);
530 
531  mutex_enter(&fil_system->mutex);
532 
533  space = fil_space_get_by_id(id);
534 
535  if (space) {
536  version = space->tablespace_version;
537  }
538 
539  mutex_exit(&fil_system->mutex);
540 
541  return(version);
542 }
543 
544 /*******************************************************************/
547 UNIV_INTERN
548 rw_lock_t*
550 /*================*/
551  ulint id,
552  ulint* flags)
553 {
555 
556  ut_ad(fil_system);
557 
558  mutex_enter(&fil_system->mutex);
559 
560  space = fil_space_get_by_id(id);
561 
562  ut_a(space);
563 
564  if (flags) {
565  *flags = space->flags;
566  }
567 
568  mutex_exit(&fil_system->mutex);
569 
570  return(&(space->latch));
571 }
572 
573 /*******************************************************************/
576 UNIV_INTERN
577 ulint
579 /*===============*/
580  ulint id)
581 {
583 
584  ut_ad(fil_system);
585 
586  mutex_enter(&fil_system->mutex);
587 
588  space = fil_space_get_by_id(id);
589 
590  ut_a(space);
591 
592  mutex_exit(&fil_system->mutex);
593 
594  return(space->purpose);
595 }
596 #endif /* !UNIV_HOTBACKUP */
597 
598 /**********************************************************************/
602 static
603 bool
604 fil_space_is_flushed(
605 /*=================*/
606  fil_space_t* space)
607 {
608  fil_node_t* node;
609 
610  ut_ad(mutex_own(&fil_system->mutex));
611 
612  node = UT_LIST_GET_FIRST(space->chain);
613 
614  while (node) {
615  if (node->modification_counter > node->flush_counter) {
616 
617  ut_ad(!fil_buffering_disabled(space));
618  return(false);
619  }
620 
621  node = UT_LIST_GET_NEXT(chain, node);
622  }
623 
624  return(true);
625 }
626 
627 /*******************************************************************/
630 UNIV_INTERN
631 char*
633 /*============*/
634  const char* name,
635  ulint size,
637  ulint id,
638  ibool is_raw)
640 {
641  fil_node_t* node;
643 
644  ut_a(fil_system);
645  ut_a(name);
646 
647  mutex_enter(&fil_system->mutex);
648 
649  node = static_cast<fil_node_t*>(mem_zalloc(sizeof(fil_node_t)));
650 
651  node->name = mem_strdup(name);
652 
653  ut_a(!is_raw || srv_start_raw_disk_in_use);
654 
655  node->sync_event = os_event_create();
656  node->is_raw_disk = is_raw;
657  node->size = size;
658  node->magic_n = FIL_NODE_MAGIC_N;
659 
660  space = fil_space_get_by_id(id);
661 
662  if (!space) {
663  ut_print_timestamp(stderr);
664  fprintf(stderr,
665  " InnoDB: Error: Could not find tablespace %lu for\n"
666  "InnoDB: file ", (ulong) id);
667  ut_print_filename(stderr, name);
668  fputs(" in the tablespace memory cache.\n", stderr);
669  mem_free(node->name);
670 
671  mem_free(node);
672 
673  mutex_exit(&fil_system->mutex);
674 
675  return(NULL);
676  }
677 
678  space->size += size;
679 
680  node->space = space;
681 
682  UT_LIST_ADD_LAST(chain, space->chain, node);
683 
684  if (id < SRV_LOG_SPACE_FIRST_ID && fil_system->max_assigned_id < id) {
685 
686  fil_system->max_assigned_id = id;
687  }
688 
689  mutex_exit(&fil_system->mutex);
690 
691  return(node->name);
692 }
693 
694 /********************************************************************/
698 static
699 bool
700 fil_node_open_file(
701 /*===============*/
702  fil_node_t* node,
703  fil_system_t* system,
704  fil_space_t* space)
705 {
706  os_offset_t size_bytes;
707  ibool ret;
708  ibool success;
709  byte* buf2;
710  byte* page;
711  ulint space_id;
712  ulint flags;
713  ulint page_size;
714 
715  ut_ad(mutex_own(&(system->mutex)));
716  ut_a(node->n_pending == 0);
717  ut_a(node->open == FALSE);
718 
719  if (node->size == 0) {
720  /* It must be a single-table tablespace and we do not know the
721  size of the file yet. First we open the file in the normal
722  mode, no async I/O here, for simplicity. Then do some checks,
723  and close the file again.
724  NOTE that we could not use the simple file read function
725  os_file_read() in Windows to read from a file opened for
726  async I/O! */
727 
728  node->handle = os_file_create_simple_no_error_handling(
729  innodb_file_data_key, node->name, OS_FILE_OPEN,
730  OS_FILE_READ_ONLY, &success);
731  if (!success) {
732  /* The following call prints an error message */
734 
735  ut_print_timestamp(stderr);
736 
737  ib_logf(IB_LOG_LEVEL_WARN, "InnoDB: Error: cannot "
738  "open %s\n. InnoDB: Have you deleted .ibd "
739  "files under a running mysqld server?\n",
740  node->name);
741 
742  return(false);
743  }
744 
745  size_bytes = os_file_get_size(node->handle);
746  ut_a(size_bytes != (os_offset_t) -1);
747 #ifdef UNIV_HOTBACKUP
748  if (space->id == 0) {
749  node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
750  os_file_close(node->handle);
751  goto add_size;
752  }
753 #endif /* UNIV_HOTBACKUP */
754  ut_a(space->purpose != FIL_LOG);
756 
757  if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
758  fprintf(stderr,
759  "InnoDB: Error: the size of single-table"
760  " tablespace file %s\n"
761  "InnoDB: is only "UINT64PF","
762  " should be at least %lu!\n",
763  node->name,
764  size_bytes,
766  * UNIV_PAGE_SIZE));
767 
768  ut_a(0);
769  }
770 
771  /* Read the first page of the tablespace */
772 
773  buf2 = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE));
774  /* Align the memory for file i/o if we might have O_DIRECT
775  set */
776  page = static_cast<byte*>(ut_align(buf2, UNIV_PAGE_SIZE));
777 
778  success = os_file_read(node->handle, page, 0, UNIV_PAGE_SIZE);
779  space_id = fsp_header_get_space_id(page);
780  flags = fsp_header_get_flags(page);
781  page_size = fsp_flags_get_page_size(flags);
782 
783  ut_free(buf2);
784 
785  /* Close the file now that we have read the space id from it */
786 
787  os_file_close(node->handle);
788 
789  if (UNIV_UNLIKELY(space_id != space->id)) {
790  fprintf(stderr,
791  "InnoDB: Error: tablespace id is %lu"
792  " in the data dictionary\n"
793  "InnoDB: but in file %s it is %lu!\n",
794  space->id, node->name, space_id);
795 
796  ut_error;
797  }
798 
799  if (UNIV_UNLIKELY(space_id == ULINT_UNDEFINED
800  || space_id == 0)) {
801  fprintf(stderr,
802  "InnoDB: Error: tablespace id %lu"
803  " in file %s is not sensible\n",
804  (ulong) space_id, node->name);
805 
806  ut_error;
807  }
808 
809  if (UNIV_UNLIKELY(fsp_flags_get_page_size(space->flags)
810  != page_size)) {
811  fprintf(stderr,
812  "InnoDB: Error: tablespace file %s"
813  " has page size 0x%lx\n"
814  "InnoDB: but the data dictionary"
815  " expects page size 0x%lx!\n",
816  node->name, flags,
818 
819  ut_error;
820  }
821 
822  if (UNIV_UNLIKELY(space->flags != flags)) {
823  fprintf(stderr,
824  "InnoDB: Error: table flags are 0x%lx"
825  " in the data dictionary\n"
826  "InnoDB: but the flags in file %s are 0x%lx!\n",
827  space->flags, node->name, flags);
828 
829  ut_error;
830  }
831 
832  if (size_bytes >= 1024 * 1024) {
833  /* Truncate the size to whole megabytes. */
834  size_bytes = ut_2pow_round(size_bytes, 1024 * 1024);
835  }
836 
837  if (!fsp_flags_is_compressed(flags)) {
838  node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
839  } else {
840  node->size = (ulint)
841  (size_bytes
842  / fsp_flags_get_zip_size(flags));
843  }
844 
845 #ifdef UNIV_HOTBACKUP
846 add_size:
847 #endif /* UNIV_HOTBACKUP */
848  space->size += node->size;
849  }
850 
851  /* printf("Opening file %s\n", node->name); */
852 
853  /* Open the file for reading and writing, in Windows normally in the
854  unbuffered async I/O mode, though global variables may make
855  os_file_create() to fall back to the normal file I/O mode. */
856 
857  if (space->purpose == FIL_LOG) {
858  node->handle = os_file_create(innodb_file_log_key,
859  node->name, OS_FILE_OPEN,
860  OS_FILE_AIO, OS_LOG_FILE,
861  &ret);
862  } else if (node->is_raw_disk) {
863  node->handle = os_file_create(innodb_file_data_key,
864  node->name,
866  OS_FILE_AIO, OS_DATA_FILE,
867  &ret);
868  } else {
869  node->handle = os_file_create(innodb_file_data_key,
870  node->name, OS_FILE_OPEN,
871  OS_FILE_AIO, OS_DATA_FILE,
872  &ret);
873  }
874 
875  ut_a(ret);
876 
877  node->open = TRUE;
878 
879  system->n_open++;
881 
882  if (fil_space_belongs_in_lru(space)) {
883 
884  /* Put the node to the LRU list */
885  UT_LIST_ADD_FIRST(LRU, system->LRU, node);
886  }
887 
888  return(true);
889 }
890 
891 /**********************************************************************/
893 static
894 void
895 fil_node_close_file(
896 /*================*/
897  fil_node_t* node,
898  fil_system_t* system)
899 {
900  ibool ret;
901 
902  ut_ad(node && system);
903  ut_ad(mutex_own(&(system->mutex)));
904  ut_a(node->open);
905  ut_a(node->n_pending == 0);
906  ut_a(node->n_pending_flushes == 0);
907  ut_a(!node->being_extended);
908 #ifndef UNIV_HOTBACKUP
910  || srv_fast_shutdown == 2);
911 #endif /* !UNIV_HOTBACKUP */
912 
913  ret = os_file_close(node->handle);
914  ut_a(ret);
915 
916  /* printf("Closing file %s\n", node->name); */
917 
918  node->open = FALSE;
919  ut_a(system->n_open > 0);
920  system->n_open--;
922 
923  if (fil_space_belongs_in_lru(node->space)) {
924 
925  ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
926 
927  /* The node is in the LRU list, remove it */
928  UT_LIST_REMOVE(LRU, system->LRU, node);
929  }
930 }
931 
932 /********************************************************************/
940 static
941 ibool
942 fil_try_to_close_file_in_LRU(
943 /*=========================*/
944  ibool print_info)
946 {
947  fil_node_t* node;
948 
949  ut_ad(mutex_own(&fil_system->mutex));
950 
951  if (print_info) {
952  fprintf(stderr,
953  "InnoDB: fil_sys open file LRU len %lu\n",
954  (ulong) UT_LIST_GET_LEN(fil_system->LRU));
955  }
956 
957  for (node = UT_LIST_GET_LAST(fil_system->LRU);
958  node != NULL;
959  node = UT_LIST_GET_PREV(LRU, node)) {
960 
961  if (node->modification_counter == node->flush_counter
962  && node->n_pending_flushes == 0
963  && !node->being_extended) {
964 
965  fil_node_close_file(node, fil_system);
966 
967  return(TRUE);
968  }
969 
970  if (!print_info) {
971  continue;
972  }
973 
974  if (node->n_pending_flushes > 0) {
975  fputs("InnoDB: cannot close file ", stderr);
976  ut_print_filename(stderr, node->name);
977  fprintf(stderr, ", because n_pending_flushes %lu\n",
978  (ulong) node->n_pending_flushes);
979  }
980 
981  if (node->modification_counter != node->flush_counter) {
982  fputs("InnoDB: cannot close file ", stderr);
983  ut_print_filename(stderr, node->name);
984  fprintf(stderr,
985  ", because mod_count %ld != fl_count %ld\n",
986  (long) node->modification_counter,
987  (long) node->flush_counter);
988 
989  }
990 
991  if (node->being_extended) {
992  fputs("InnoDB: cannot close file ", stderr);
993  ut_print_filename(stderr, node->name);
994  fprintf(stderr, ", because it is being extended\n");
995  }
996  }
997 
998  return(FALSE);
999 }
1000 
1001 /*******************************************************************/
1005 static
1006 void
1007 fil_mutex_enter_and_prepare_for_io(
1008 /*===============================*/
1009  ulint space_id)
1010 {
1011  fil_space_t* space;
1012  ibool success;
1013  ibool print_info = FALSE;
1014  ulint count = 0;
1015  ulint count2 = 0;
1016 
1017 retry:
1018  mutex_enter(&fil_system->mutex);
1019 
1020  if (space_id == 0 || space_id >= SRV_LOG_SPACE_FIRST_ID) {
1021  /* We keep log files and system tablespace files always open;
1022  this is important in preventing deadlocks in this module, as
1023  a page read completion often performs another read from the
1024  insert buffer. The insert buffer is in tablespace 0, and we
1025  cannot end up waiting in this function. */
1026 
1027  return;
1028  }
1029 
1030  space = fil_space_get_by_id(space_id);
1031 
1032  if (space != NULL && space->stop_ios) {
1033  /* We are going to do a rename file and want to stop new i/o's
1034  for a while */
1035 
1036  if (count2 > 20000) {
1037  fputs("InnoDB: Warning: tablespace ", stderr);
1038  ut_print_filename(stderr, space->name);
1039  fprintf(stderr,
1040  " has i/o ops stopped for a long time %lu\n",
1041  (ulong) count2);
1042  }
1043 
1044  mutex_exit(&fil_system->mutex);
1045 
1046 #ifndef UNIV_HOTBACKUP
1047 
1048  /* Wake the i/o-handler threads to make sure pending
1049  i/o's are performed */
1051 
1052  /* The sleep here is just to give IO helper threads a
1053  bit of time to do some work. It is not required that
1054  all IO related to the tablespace being renamed must
1055  be flushed here as we do fil_flush() in
1056  fil_rename_tablespace() as well. */
1057  os_thread_sleep(20000);
1058 
1059 #endif /* UNIV_HOTBACKUP */
1060 
1061  /* Flush tablespaces so that we can close modified
1062  files in the LRU list */
1064 
1065  os_thread_sleep(20000);
1066 
1067  count2++;
1068 
1069  goto retry;
1070  }
1071 
1072  if (fil_system->n_open < fil_system->max_n_open) {
1073 
1074  return;
1075  }
1076 
1077  /* If the file is already open, no need to do anything; if the space
1078  does not exist, we handle the situation in the function which called
1079  this function */
1080 
1081  if (!space || UT_LIST_GET_FIRST(space->chain)->open) {
1082 
1083  return;
1084  }
1085 
1086  if (count > 1) {
1087  print_info = TRUE;
1088  }
1089 
1090  /* Too many files are open, try to close some */
1091 close_more:
1092  success = fil_try_to_close_file_in_LRU(print_info);
1093 
1094  if (success && fil_system->n_open >= fil_system->max_n_open) {
1095 
1096  goto close_more;
1097  }
1098 
1099  if (fil_system->n_open < fil_system->max_n_open) {
1100  /* Ok */
1101 
1102  return;
1103  }
1104 
1105  if (count >= 2) {
1106  ut_print_timestamp(stderr);
1107  fprintf(stderr,
1108  " InnoDB: Warning: too many (%lu) files stay open"
1109  " while the maximum\n"
1110  "InnoDB: allowed value would be %lu.\n"
1111  "InnoDB: You may need to raise the value of"
1112  " innodb_open_files in\n"
1113  "InnoDB: my.cnf.\n",
1114  (ulong) fil_system->n_open,
1115  (ulong) fil_system->max_n_open);
1116 
1117  return;
1118  }
1119 
1120  mutex_exit(&fil_system->mutex);
1121 
1122 #ifndef UNIV_HOTBACKUP
1123  /* Wake the i/o-handler threads to make sure pending i/o's are
1124  performed */
1126 
1127  os_thread_sleep(20000);
1128 #endif
1129  /* Flush tablespaces so that we can close modified files in the LRU
1130  list */
1131 
1133 
1134  count++;
1135 
1136  goto retry;
1137 }
1138 
1139 /*******************************************************************/
1141 static
1142 void
1143 fil_node_free(
1144 /*==========*/
1145  fil_node_t* node,
1146  fil_system_t* system,
1147  fil_space_t* space)
1148 {
1149  ut_ad(node && system && space);
1150  ut_ad(mutex_own(&(system->mutex)));
1151  ut_a(node->magic_n == FIL_NODE_MAGIC_N);
1152  ut_a(node->n_pending == 0);
1153  ut_a(!node->being_extended);
1154 
1155  if (node->open) {
1156  /* We fool the assertion in fil_node_close_file() to think
1157  there are no unflushed modifications in the file */
1158 
1159  node->modification_counter = node->flush_counter;
1160  os_event_set(node->sync_event);
1161 
1162  if (fil_buffering_disabled(space)) {
1163 
1164  ut_ad(!space->is_in_unflushed_spaces);
1165  ut_ad(fil_space_is_flushed(space));
1166 
1167  } else if (space->is_in_unflushed_spaces
1168  && fil_space_is_flushed(space)) {
1169 
1170  space->is_in_unflushed_spaces = false;
1171 
1172  UT_LIST_REMOVE(unflushed_spaces,
1173  system->unflushed_spaces,
1174  space);
1175  }
1176 
1177  fil_node_close_file(node, system);
1178  }
1179 
1180  space->size -= node->size;
1181 
1182  UT_LIST_REMOVE(chain, space->chain, node);
1183 
1184  os_event_free(node->sync_event);
1185  mem_free(node->name);
1186  mem_free(node);
1187 }
1188 
1189 #ifdef UNIV_LOG_ARCHIVE
1190 /****************************************************************/
1193 UNIV_INTERN
1194 void
1195 fil_space_truncate_start(
1196 /*=====================*/
1197  ulint id,
1198  ulint trunc_len)
1201 {
1202  fil_node_t* node;
1203  fil_space_t* space;
1204 
1205  mutex_enter(&fil_system->mutex);
1206 
1207  space = fil_space_get_by_id(id);
1208 
1209  ut_a(space);
1210 
1211  while (trunc_len > 0) {
1212  node = UT_LIST_GET_FIRST(space->chain);
1213 
1214  ut_a(node->size * UNIV_PAGE_SIZE <= trunc_len);
1215 
1216  trunc_len -= node->size * UNIV_PAGE_SIZE;
1217 
1218  fil_node_free(node, fil_system, space);
1219  }
1220 
1221  mutex_exit(&fil_system->mutex);
1222 }
1223 #endif /* UNIV_LOG_ARCHIVE */
1224 
1225 /*******************************************************************/
1229 UNIV_INTERN
1230 ibool
1232 /*=============*/
1233  const char* name,
1234  ulint id,
1235  ulint flags,
1236  ulint purpose)
1237 {
1238  fil_space_t* space;
1239 
1240  DBUG_EXECUTE_IF("fil_space_create_failure", return(false););
1241 
1242  ut_a(fil_system);
1243  ut_a(fsp_flags_is_valid(flags));
1244 
1245  /* Look for a matching tablespace and if found free it. */
1246  do {
1247  mutex_enter(&fil_system->mutex);
1248 
1249  space = fil_space_get_by_name(name);
1250 
1251  if (space != 0) {
1252  ib_logf(IB_LOG_LEVEL_WARN,
1253  "Tablespace '%s' exists in the cache "
1254  "with id %lu != %lu",
1255  name, (ulong) space->id, (ulong) id);
1256 
1257  if (id == 0 || purpose != FIL_TABLESPACE) {
1258 
1259  mutex_exit(&fil_system->mutex);
1260 
1261  return(FALSE);
1262  }
1263 
1264  ib_logf(IB_LOG_LEVEL_WARN,
1265  "Freeing existing tablespace '%s' entry "
1266  "from the cache with id %lu",
1267  name, (ulong) id);
1268 
1269  ibool success = fil_space_free(space->id, FALSE);
1270  ut_a(success);
1271 
1272  mutex_exit(&fil_system->mutex);
1273  }
1274 
1275  } while (space != 0);
1276 
1277  space = fil_space_get_by_id(id);
1278 
1279  if (space != 0) {
1280  ib_logf(IB_LOG_LEVEL_ERROR,
1281  "Trying to add tablespace '%s' with id %lu "
1282  "to the tablespace memory cache, but tablespace '%s' "
1283  "with id %lu already exists in the cache!",
1284  name, (ulong) id, space->name, (ulong) space->id);
1285 
1286  mutex_exit(&fil_system->mutex);
1287 
1288  return(FALSE);
1289  }
1290 
1291  space = static_cast<fil_space_t*>(mem_zalloc(sizeof(*space)));
1292 
1293  space->name = mem_strdup(name);
1294  space->id = id;
1295 
1296  fil_system->tablespace_version++;
1297  space->tablespace_version = fil_system->tablespace_version;
1298  space->mark = FALSE;
1299 
1300  if (purpose == FIL_TABLESPACE && !recv_recovery_on
1301  && id > fil_system->max_assigned_id) {
1302 
1303  if (!fil_system->space_id_reuse_warned) {
1304  fil_system->space_id_reuse_warned = TRUE;
1305 
1306  ib_logf(IB_LOG_LEVEL_WARN,
1307  "Allocated tablespace %lu, old maximum "
1308  "was %lu",
1309  (ulong) id,
1310  (ulong) fil_system->max_assigned_id);
1311  }
1312 
1313  fil_system->max_assigned_id = id;
1314  }
1315 
1316  space->purpose = purpose;
1317  space->flags = flags;
1318 
1319  space->magic_n = FIL_SPACE_MAGIC_N;
1320 
1321  rw_lock_create(fil_space_latch_key, &space->latch, SYNC_FSP);
1322 
1323  HASH_INSERT(fil_space_t, hash, fil_system->spaces, id, space);
1324 
1325  HASH_INSERT(fil_space_t, name_hash, fil_system->name_hash,
1326  ut_fold_string(name), space);
1327  space->is_in_unflushed_spaces = false;
1328 
1329  UT_LIST_ADD_LAST(space_list, fil_system->space_list, space);
1330 
1331  mutex_exit(&fil_system->mutex);
1332 
1333  return(TRUE);
1334 }
1335 
1336 /*******************************************************************/
1341 UNIV_INTERN
1342 ibool
1344 /*====================*/
1345  ulint* space_id)
1346 {
1347  ulint id;
1348  ibool success;
1349 
1350  mutex_enter(&fil_system->mutex);
1351 
1352  id = *space_id;
1353 
1354  if (id < fil_system->max_assigned_id) {
1355  id = fil_system->max_assigned_id;
1356  }
1357 
1358  id++;
1359 
1360  if (id > (SRV_LOG_SPACE_FIRST_ID / 2) && (id % 1000000UL == 0)) {
1361  ut_print_timestamp(stderr);
1362  fprintf(stderr,
1363  "InnoDB: Warning: you are running out of new"
1364  " single-table tablespace id's.\n"
1365  "InnoDB: Current counter is %lu and it"
1366  " must not exceed %lu!\n"
1367  "InnoDB: To reset the counter to zero"
1368  " you have to dump all your tables and\n"
1369  "InnoDB: recreate the whole InnoDB installation.\n",
1370  (ulong) id,
1371  (ulong) SRV_LOG_SPACE_FIRST_ID);
1372  }
1373 
1374  success = (id < SRV_LOG_SPACE_FIRST_ID);
1375 
1376  if (success) {
1377  *space_id = fil_system->max_assigned_id = id;
1378  } else {
1379  ut_print_timestamp(stderr);
1380  fprintf(stderr,
1381  "InnoDB: You have run out of single-table"
1382  " tablespace id's!\n"
1383  "InnoDB: Current counter is %lu.\n"
1384  "InnoDB: To reset the counter to zero you"
1385  " have to dump all your tables and\n"
1386  "InnoDB: recreate the whole InnoDB installation.\n",
1387  (ulong) id);
1388  *space_id = ULINT_UNDEFINED;
1389  }
1390 
1391  mutex_exit(&fil_system->mutex);
1392 
1393  return(success);
1394 }
1395 
1396 /*******************************************************************/
1401 static
1402 ibool
1403 fil_space_free(
1404 /*===========*/
1405  /* out: TRUE if success */
1406  ulint id, /* in: space id */
1407  ibool x_latched) /* in: TRUE if caller has space->latch
1408  in X mode */
1409 {
1410  fil_space_t* space;
1411  fil_space_t* fnamespace;
1412 
1413  ut_ad(mutex_own(&fil_system->mutex));
1414 
1415  space = fil_space_get_by_id(id);
1416 
1417  if (!space) {
1418  ut_print_timestamp(stderr);
1419  fprintf(stderr,
1420  " InnoDB: Error: trying to remove tablespace %lu"
1421  " from the cache but\n"
1422  "InnoDB: it is not there.\n", (ulong) id);
1423 
1424  return(FALSE);
1425  }
1426 
1427  HASH_DELETE(fil_space_t, hash, fil_system->spaces, id, space);
1428 
1429  fnamespace = fil_space_get_by_name(space->name);
1430  ut_a(fnamespace);
1431  ut_a(space == fnamespace);
1432 
1433  HASH_DELETE(fil_space_t, name_hash, fil_system->name_hash,
1434  ut_fold_string(space->name), space);
1435 
1436  if (space->is_in_unflushed_spaces) {
1437 
1438  ut_ad(!fil_buffering_disabled(space));
1439  space->is_in_unflushed_spaces = false;
1440 
1441  UT_LIST_REMOVE(unflushed_spaces, fil_system->unflushed_spaces,
1442  space);
1443  }
1444 
1445  UT_LIST_REMOVE(space_list, fil_system->space_list, space);
1446 
1447  ut_a(space->magic_n == FIL_SPACE_MAGIC_N);
1448  ut_a(0 == space->n_pending_flushes);
1449 
1450  for (fil_node_t* fil_node = UT_LIST_GET_FIRST(space->chain);
1451  fil_node != NULL;
1452  fil_node = UT_LIST_GET_FIRST(space->chain)) {
1453 
1454  fil_node_free(fil_node, fil_system, space);
1455  }
1456 
1457  ut_a(0 == UT_LIST_GET_LEN(space->chain));
1458 
1459  if (x_latched) {
1460  rw_lock_x_unlock(&space->latch);
1461  }
1462 
1463  rw_lock_free(&(space->latch));
1464 
1465  mem_free(space->name);
1466  mem_free(space);
1467 
1468  return(TRUE);
1469 }
1470 
1471 /*******************************************************************/
1475 UNIV_INLINE
1476 fil_space_t*
1478 /*================*/
1479  ulint id)
1480 {
1481  fil_space_t* space;
1482  fil_node_t* node;
1483 
1484  ut_ad(fil_system);
1485 
1486  space = fil_space_get_by_id(id);
1487  if (space == NULL) {
1488  return(NULL);
1489  }
1490 
1491  if (space->size == 0 && space->purpose == FIL_TABLESPACE) {
1492  ut_a(id != 0);
1493 
1494  mutex_exit(&fil_system->mutex);
1495 
1496  /* It is possible that the space gets evicted at this point
1497  before the fil_mutex_enter_and_prepare_for_io() acquires
1498  the fil_system->mutex. Check for this after completing the
1499  call to fil_mutex_enter_and_prepare_for_io(). */
1500  fil_mutex_enter_and_prepare_for_io(id);
1501 
1502  /* We are still holding the fil_system->mutex. Check if
1503  the space is still in memory cache. */
1504  space = fil_space_get_by_id(id);
1505  if (space == NULL) {
1506  return(NULL);
1507  }
1508 
1509  /* The following code must change when InnoDB supports
1510  multiple datafiles per tablespace. */
1511  ut_a(1 == UT_LIST_GET_LEN(space->chain));
1512 
1513  node = UT_LIST_GET_FIRST(space->chain);
1514 
1515  /* It must be a single-table tablespace and we have not opened
1516  the file yet; the following calls will open it and update the
1517  size fields */
1518 
1519  if (!fil_node_prepare_for_io(node, fil_system, space)) {
1520  /* The single-table tablespace can't be opened,
1521  because the ibd file is missing. */
1522  return(NULL);
1523  }
1524  fil_node_complete_io(node, fil_system, OS_FILE_READ);
1525  }
1526 
1527  return(space);
1528 }
1529 
1530 /*******************************************************************/
1536 UNIV_INTERN
1537 char*
1539 /*=====================*/
1540  ulint id)
1541 {
1542  fil_space_t* space;
1543  fil_node_t* node;
1544  char* path;
1545 
1546  ut_ad(fil_system);
1547  ut_a(id);
1548 
1549  fil_mutex_enter_and_prepare_for_io(id);
1550 
1551  space = fil_space_get_space(id);
1552 
1553  if (space == NULL) {
1554  mutex_exit(&fil_system->mutex);
1555 
1556  return(NULL);
1557  }
1558 
1559  ut_ad(mutex_own(&fil_system->mutex));
1560 
1561  node = UT_LIST_GET_FIRST(space->chain);
1562 
1563  path = mem_strdup(node->name);
1564 
1565  mutex_exit(&fil_system->mutex);
1566 
1567  return(path);
1568 }
1569 
1570 /*******************************************************************/
1574 UNIV_INTERN
1575 ulint
1577 /*===============*/
1578  ulint id)
1579 {
1580  fil_space_t* space;
1581  ulint size;
1582 
1583  ut_ad(fil_system);
1584  mutex_enter(&fil_system->mutex);
1585 
1586  space = fil_space_get_space(id);
1587 
1588  size = space ? space->size : 0;
1589 
1590  mutex_exit(&fil_system->mutex);
1591 
1592  return(size);
1593 }
1594 
1595 /*******************************************************************/
1599 UNIV_INTERN
1600 ulint
1602 /*================*/
1603  ulint id)
1604 {
1605  fil_space_t* space;
1606  ulint flags;
1607 
1608  ut_ad(fil_system);
1609 
1610  if (!id) {
1611  return(0);
1612  }
1613 
1614  mutex_enter(&fil_system->mutex);
1615 
1616  space = fil_space_get_space(id);
1617 
1618  if (space == NULL) {
1619  mutex_exit(&fil_system->mutex);
1620 
1621  return(ULINT_UNDEFINED);
1622  }
1623 
1624  flags = space->flags;
1625 
1626  mutex_exit(&fil_system->mutex);
1627 
1628  return(flags);
1629 }
1630 
1631 /*******************************************************************/
1635 UNIV_INTERN
1636 ulint
1638 /*===================*/
1639  ulint id)
1640 {
1641  ulint flags;
1642 
1643  flags = fil_space_get_flags(id);
1644 
1645  if (flags && flags != ULINT_UNDEFINED) {
1646 
1647  return(fsp_flags_get_zip_size(flags));
1648  }
1649 
1650  return(flags);
1651 }
1652 
1653 /*******************************************************************/
1657 UNIV_INTERN
1658 ibool
1660 /*===========================*/
1661  ulint id,
1662  ulint page_no)
1663 {
1664  if (fil_space_get_size(id) > page_no) {
1665 
1666  return(TRUE);
1667  }
1668 
1669  return(FALSE);
1670 }
1671 
1672 /****************************************************************/
1674 UNIV_INTERN
1675 void
1677 /*=====*/
1678  ulint hash_size,
1679  ulint max_n_open)
1680 {
1681  ut_a(fil_system == NULL);
1682 
1683  ut_a(hash_size > 0);
1684  ut_a(max_n_open > 0);
1685 
1686  fil_system = static_cast<fil_system_t*>(
1687  mem_zalloc(sizeof(fil_system_t)));
1688 
1689  mutex_create(fil_system_mutex_key,
1690  &fil_system->mutex, SYNC_ANY_LATCH);
1691 
1692  fil_system->spaces = hash_create(hash_size);
1693  fil_system->name_hash = hash_create(hash_size);
1694 
1695  UT_LIST_INIT(fil_system->LRU);
1696 
1697  fil_system->max_n_open = max_n_open;
1698 }
1699 
1700 /*******************************************************************/
1706 UNIV_INTERN
1707 void
1709 /*==========================================*/
1710 {
1711  fil_space_t* space;
1712 
1713  mutex_enter(&fil_system->mutex);
1714 
1715  for (space = UT_LIST_GET_FIRST(fil_system->space_list);
1716  space != NULL;
1717  space = UT_LIST_GET_NEXT(space_list, space)) {
1718 
1719  fil_node_t* node;
1720 
1721  if (fil_space_belongs_in_lru(space)) {
1722 
1723  continue;
1724  }
1725 
1726  for (node = UT_LIST_GET_FIRST(space->chain);
1727  node != NULL;
1728  node = UT_LIST_GET_NEXT(chain, node)) {
1729 
1730  if (!node->open) {
1731  if (!fil_node_open_file(node, fil_system,
1732  space)) {
1733  /* This func is called during server's
1734  startup. If some file of log or system
1735  tablespace is missing, the server
1736  can't start successfully. So we should
1737  assert for it. */
1738  ut_a(0);
1739  }
1740  }
1741 
1742  if (fil_system->max_n_open < 10 + fil_system->n_open) {
1743 
1744  fprintf(stderr,
1745  "InnoDB: Warning: you must"
1746  " raise the value of"
1747  " innodb_open_files in\n"
1748  "InnoDB: my.cnf! Remember that"
1749  " InnoDB keeps all log files"
1750  " and all system\n"
1751  "InnoDB: tablespace files open"
1752  " for the whole time mysqld is"
1753  " running, and\n"
1754  "InnoDB: needs to open also"
1755  " some .ibd files if the"
1756  " file-per-table storage\n"
1757  "InnoDB: model is used."
1758  " Current open files %lu,"
1759  " max allowed"
1760  " open files %lu.\n",
1761  (ulong) fil_system->n_open,
1762  (ulong) fil_system->max_n_open);
1763  }
1764  }
1765  }
1766 
1767  mutex_exit(&fil_system->mutex);
1768 }
1769 
1770 /*******************************************************************/
1773 UNIV_INTERN
1774 void
1776 /*=====================*/
1777 {
1778  fil_space_t* space;
1779 
1780  mutex_enter(&fil_system->mutex);
1781 
1782  space = UT_LIST_GET_FIRST(fil_system->space_list);
1783 
1784  while (space != NULL) {
1785  fil_node_t* node;
1786  fil_space_t* prev_space = space;
1787 
1788  for (node = UT_LIST_GET_FIRST(space->chain);
1789  node != NULL;
1790  node = UT_LIST_GET_NEXT(chain, node)) {
1791 
1792  if (node->open) {
1793  fil_node_close_file(node, fil_system);
1794  }
1795  }
1796 
1797  space = UT_LIST_GET_NEXT(space_list, space);
1798 
1799  fil_space_free(prev_space->id, FALSE);
1800  }
1801 
1802  mutex_exit(&fil_system->mutex);
1803 }
1804 
1805 /*******************************************************************/
1808 UNIV_INTERN
1809 void
1811 /*================*/
1812  bool free)
1813 {
1814  fil_space_t* space;
1815 
1816  mutex_enter(&fil_system->mutex);
1817 
1818  space = UT_LIST_GET_FIRST(fil_system->space_list);
1819 
1820  while (space != NULL) {
1821  fil_node_t* node;
1822  fil_space_t* prev_space = space;
1823 
1824  if (space->purpose != FIL_LOG) {
1825  space = UT_LIST_GET_NEXT(space_list, space);
1826  continue;
1827  }
1828 
1829  for (node = UT_LIST_GET_FIRST(space->chain);
1830  node != NULL;
1831  node = UT_LIST_GET_NEXT(chain, node)) {
1832 
1833  if (node->open) {
1834  fil_node_close_file(node, fil_system);
1835  }
1836  }
1837 
1838  space = UT_LIST_GET_NEXT(space_list, space);
1839 
1840  if (free) {
1841  fil_space_free(prev_space->id, FALSE);
1842  }
1843  }
1844 
1845  mutex_exit(&fil_system->mutex);
1846 }
1847 
1848 /*******************************************************************/
1851 UNIV_INTERN
1852 void
1854 /*===========================*/
1855  ulint max_id)
1856 {
1857  if (max_id >= SRV_LOG_SPACE_FIRST_ID) {
1858  fprintf(stderr,
1859  "InnoDB: Fatal error: max tablespace id"
1860  " is too high, %lu\n", (ulong) max_id);
1861  ut_error;
1862  }
1863 
1864  mutex_enter(&fil_system->mutex);
1865 
1866  if (fil_system->max_assigned_id < max_id) {
1867 
1868  fil_system->max_assigned_id = max_id;
1869  }
1870 
1871  mutex_exit(&fil_system->mutex);
1872 }
1873 
1874 /****************************************************************/
1878 static __attribute__((warn_unused_result))
1879 dberr_t
1880 fil_write_lsn_and_arch_no_to_file(
1881 /*==============================*/
1882  ulint space,
1883  ulint sum_of_sizes,
1885  lsn_t lsn,
1886  ulint arch_log_no __attribute__((unused)))
1888 {
1889  byte* buf1;
1890  byte* buf;
1891  dberr_t err;
1892 
1893  buf1 = static_cast<byte*>(mem_alloc(2 * UNIV_PAGE_SIZE));
1894  buf = static_cast<byte*>(ut_align(buf1, UNIV_PAGE_SIZE));
1895 
1896  err = fil_read(TRUE, space, 0, sum_of_sizes, 0,
1897  UNIV_PAGE_SIZE, buf, NULL);
1898  if (err == DB_SUCCESS) {
1900 
1901  err = fil_write(TRUE, space, 0, sum_of_sizes, 0,
1902  UNIV_PAGE_SIZE, buf, NULL);
1903  }
1904 
1905  mem_free(buf1);
1906 
1907  return(err);
1908 }
1909 
1910 /****************************************************************/
1914 UNIV_INTERN
1915 dberr_t
1917 /*================================*/
1918  lsn_t lsn,
1919  ulint arch_log_no)
1920 {
1921  fil_space_t* space;
1922  fil_node_t* node;
1923  dberr_t err;
1924 
1925  mutex_enter(&fil_system->mutex);
1926 
1927  for (space = UT_LIST_GET_FIRST(fil_system->space_list);
1928  space != NULL;
1929  space = UT_LIST_GET_NEXT(space_list, space)) {
1930 
1931  /* We only write the lsn to all existing data files which have
1932  been open during the lifetime of the mysqld process; they are
1933  represented by the space objects in the tablespace memory
1934  cache. Note that all data files in the system tablespace 0
1935  and the UNDO log tablespaces (if separate) are always open. */
1936 
1937  if (space->purpose == FIL_TABLESPACE
1938  && !fil_is_user_tablespace_id(space->id)) {
1939  ulint sum_of_sizes = 0;
1940 
1941  for (node = UT_LIST_GET_FIRST(space->chain);
1942  node != NULL;
1943  node = UT_LIST_GET_NEXT(chain, node)) {
1944 
1945  mutex_exit(&fil_system->mutex);
1946 
1947  err = fil_write_lsn_and_arch_no_to_file(
1948  space->id, sum_of_sizes, lsn,
1949  arch_log_no);
1950 
1951  if (err != DB_SUCCESS) {
1952 
1953  return(err);
1954  }
1955 
1956  mutex_enter(&fil_system->mutex);
1957 
1958  sum_of_sizes += node->size;
1959  }
1960  }
1961  }
1962 
1963  mutex_exit(&fil_system->mutex);
1964 
1965  return(DB_SUCCESS);
1966 }
1967 
1968 /*******************************************************************/
1973 static __attribute__((warn_unused_result))
1974 const char*
1975 fil_check_first_page(
1976 /*=================*/
1977  const page_t* page)
1978 {
1979  ulint space_id;
1980  ulint flags;
1981 
1983  return(NULL);
1984  }
1985 
1986  space_id = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page);
1987  flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
1988 
1989  if (UNIV_PAGE_SIZE != fsp_flags_get_page_size(flags)) {
1990  return("innodb-page-size mismatch");
1991  }
1992 
1993  if (!space_id && !flags) {
1994  ulint nonzero_bytes = UNIV_PAGE_SIZE;
1995  const byte* b = page;
1996 
1997  while (!*b && --nonzero_bytes) {
1998  b++;
1999  }
2000 
2001  if (!nonzero_bytes) {
2002  return("space header page consists of zero bytes");
2003  }
2004  }
2005 
2007  false, page, fsp_flags_get_zip_size(flags))) {
2008  return("checksum mismatch");
2009  }
2010 
2011  if (page_get_space_id(page) == space_id
2012  && page_get_page_no(page) == 0) {
2013  return(NULL);
2014  }
2015 
2016  return("inconsistent data in space header");
2017 }
2018 
2019 /*******************************************************************/
2024 UNIV_INTERN
2025 const char*
2027 /*================*/
2028  os_file_t data_file,
2029  ibool one_read_already,
2032  ulint* flags,
2033  ulint* space_id,
2034 #ifdef UNIV_LOG_ARCHIVE
2035  ulint* min_arch_log_no,
2037  ulint* max_arch_log_no,
2039 #endif /* UNIV_LOG_ARCHIVE */
2040  lsn_t* min_flushed_lsn,
2042  lsn_t* max_flushed_lsn)
2044 {
2045  byte* buf;
2046  byte* page;
2047  lsn_t flushed_lsn;
2048  const char* check_msg = NULL;
2049 
2050  buf = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE));
2051 
2052  /* Align the memory for a possible read from a raw device */
2053 
2054  page = static_cast<byte*>(ut_align(buf, UNIV_PAGE_SIZE));
2055 
2056  os_file_read(data_file, page, 0, UNIV_PAGE_SIZE);
2057 
2058  *flags = fsp_header_get_flags(page);
2059 
2060  *space_id = fsp_header_get_space_id(page);
2061 
2062  flushed_lsn = mach_read_from_8(page + FIL_PAGE_FILE_FLUSH_LSN);
2063 
2064  if (!one_read_already) {
2065  check_msg = fil_check_first_page(page);
2066  }
2067 
2068  ut_free(buf);
2069 
2070  if (check_msg) {
2071  return(check_msg);
2072  }
2073 
2074  if (!one_read_already) {
2075  *min_flushed_lsn = flushed_lsn;
2076  *max_flushed_lsn = flushed_lsn;
2077 #ifdef UNIV_LOG_ARCHIVE
2078  *min_arch_log_no = arch_log_no;
2079  *max_arch_log_no = arch_log_no;
2080 #endif /* UNIV_LOG_ARCHIVE */
2081  return(NULL);
2082  }
2083 
2084  if (*min_flushed_lsn > flushed_lsn) {
2085  *min_flushed_lsn = flushed_lsn;
2086  }
2087  if (*max_flushed_lsn < flushed_lsn) {
2088  *max_flushed_lsn = flushed_lsn;
2089  }
2090 #ifdef UNIV_LOG_ARCHIVE
2091  if (*min_arch_log_no > arch_log_no) {
2092  *min_arch_log_no = arch_log_no;
2093  }
2094  if (*max_arch_log_no < arch_log_no) {
2095  *max_arch_log_no = arch_log_no;
2096  }
2097 #endif /* UNIV_LOG_ARCHIVE */
2098 
2099  return(NULL);
2100 }
2101 
2102 /*================ SINGLE-TABLE TABLESPACES ==========================*/
2103 
2104 #ifndef UNIV_HOTBACKUP
2105 /*******************************************************************/
2108 UNIV_INTERN
2109 ibool
2111 /*================*/
2112  ulint id)
2113 {
2114  fil_space_t* space;
2115 
2116  mutex_enter(&fil_system->mutex);
2117 
2118  space = fil_space_get_by_id(id);
2119 
2120  if (space == NULL) {
2121  fprintf(stderr,
2122  "InnoDB: Error: trying to do an operation on a"
2123  " dropped tablespace %lu\n",
2124  (ulong) id);
2125  }
2126 
2127  if (space == NULL || space->stop_new_ops) {
2128  mutex_exit(&fil_system->mutex);
2129 
2130  return(TRUE);
2131  }
2132 
2133  space->n_pending_ops++;
2134 
2135  mutex_exit(&fil_system->mutex);
2136 
2137  return(FALSE);
2138 }
2139 
2140 /*******************************************************************/
2142 UNIV_INTERN
2143 void
2145 /*=================*/
2146  ulint id)
2147 {
2148  fil_space_t* space;
2149 
2150  mutex_enter(&fil_system->mutex);
2151 
2152  space = fil_space_get_by_id(id);
2153 
2154  if (space == NULL) {
2155  fprintf(stderr,
2156  "InnoDB: Error: decrementing pending operation"
2157  " of a dropped tablespace %lu\n",
2158  (ulong) id);
2159  }
2160 
2161  if (space != NULL) {
2162  space->n_pending_ops--;
2163  }
2164 
2165  mutex_exit(&fil_system->mutex);
2166 }
2167 #endif /* !UNIV_HOTBACKUP */
2168 
2169 /********************************************************/
2171 static
2172 void
2173 fil_create_directory_for_tablename(
2174 /*===============================*/
2175  const char* name)
2177 {
2178  const char* namend;
2179  char* path;
2180  ulint len;
2181 
2182  len = strlen(fil_path_to_mysql_datadir);
2183  namend = strchr(name, '/');
2184  ut_a(namend);
2185  path = static_cast<char*>(mem_alloc(len + (namend - name) + 2));
2186 
2187  memcpy(path, fil_path_to_mysql_datadir, len);
2188  path[len] = '/';
2189  memcpy(path + len + 1, name, namend - name);
2190  path[len + (namend - name) + 1] = 0;
2191 
2193 
2194  ut_a(os_file_create_directory(path, FALSE));
2195  mem_free(path);
2196 }
2197 
2198 #ifndef UNIV_HOTBACKUP
2199 /********************************************************/
2201 static
2202 void
2203 fil_op_write_log(
2204 /*=============*/
2205  ulint type,
2209  ulint space_id,
2210  ulint log_flags,
2212  ulint flags,
2215  const char* name,
2219  const char* new_name,
2222  mtr_t* mtr)
2223 {
2224  byte* log_ptr;
2225  ulint len;
2226 
2227  log_ptr = mlog_open(mtr, 11 + 2 + 1);
2228 
2229  if (!log_ptr) {
2230  /* Logging in mtr is switched off during crash recovery:
2231  in that case mlog_open returns NULL */
2232  return;
2233  }
2234 
2236  type, space_id, log_flags, log_ptr, mtr);
2237  if (type == MLOG_FILE_CREATE2) {
2238  mach_write_to_4(log_ptr, flags);
2239  log_ptr += 4;
2240  }
2241  /* Let us store the strings as null-terminated for easier readability
2242  and handling */
2243 
2244  len = strlen(name) + 1;
2245 
2246  mach_write_to_2(log_ptr, len);
2247  log_ptr += 2;
2248  mlog_close(mtr, log_ptr);
2249 
2250  mlog_catenate_string(mtr, (byte*) name, len);
2251 
2252  if (type == MLOG_FILE_RENAME) {
2253  len = strlen(new_name) + 1;
2254  log_ptr = mlog_open(mtr, 2 + len);
2255  ut_a(log_ptr);
2256  mach_write_to_2(log_ptr, len);
2257  log_ptr += 2;
2258  mlog_close(mtr, log_ptr);
2259 
2260  mlog_catenate_string(mtr, (byte*) new_name, len);
2261  }
2262 }
2263 #endif
2264 
2265 /*******************************************************************/
2285 UNIV_INTERN
2286 byte*
2288 /*=======================*/
2289  byte* ptr,
2292  byte* end_ptr,
2293  ulint type,
2294  ulint space_id,
2297  ulint log_flags)
2299 {
2300  ulint name_len;
2301  ulint new_name_len;
2302  const char* name;
2303  const char* new_name = NULL;
2304  ulint flags = 0;
2305 
2306  if (type == MLOG_FILE_CREATE2) {
2307  if (end_ptr < ptr + 4) {
2308 
2309  return(NULL);
2310  }
2311 
2312  flags = mach_read_from_4(ptr);
2313  ptr += 4;
2314  }
2315 
2316  if (end_ptr < ptr + 2) {
2317 
2318  return(NULL);
2319  }
2320 
2321  name_len = mach_read_from_2(ptr);
2322 
2323  ptr += 2;
2324 
2325  if (end_ptr < ptr + name_len) {
2326 
2327  return(NULL);
2328  }
2329 
2330  name = (const char*) ptr;
2331 
2332  ptr += name_len;
2333 
2334  if (type == MLOG_FILE_RENAME) {
2335  if (end_ptr < ptr + 2) {
2336 
2337  return(NULL);
2338  }
2339 
2340  new_name_len = mach_read_from_2(ptr);
2341 
2342  ptr += 2;
2343 
2344  if (end_ptr < ptr + new_name_len) {
2345 
2346  return(NULL);
2347  }
2348 
2349  new_name = (const char*) ptr;
2350 
2351  ptr += new_name_len;
2352  }
2353 
2354  /* We managed to parse a full log record body */
2355  /*
2356  printf("Parsed log rec of type %lu space %lu\n"
2357  "name %s\n", type, space_id, name);
2358 
2359  if (type == MLOG_FILE_RENAME) {
2360  printf("new name %s\n", new_name);
2361  }
2362  */
2363  if (!space_id) {
2364  return(ptr);
2365  }
2366 
2367  /* Let us try to perform the file operation, if sensible. Note that
2368  ibbackup has at this stage already read in all space id info to the
2369  fil0fil.cc data structures.
2370 
2371  NOTE that our algorithm is not guaranteed to work correctly if there
2372  were renames of tables during the backup. See ibbackup code for more
2373  on the problem. */
2374 
2375  switch (type) {
2376  case MLOG_FILE_DELETE:
2377  if (fil_tablespace_exists_in_mem(space_id)) {
2379  space_id, BUF_REMOVE_FLUSH_NO_WRITE);
2380  ut_a(err == DB_SUCCESS);
2381  }
2382 
2383  break;
2384 
2385  case MLOG_FILE_RENAME:
2386  /* We do the rename based on space id, not old file name;
2387  this should guarantee that after the log replay each .ibd file
2388  has the correct name for the latest log sequence number; the
2389  proof is left as an exercise :) */
2390 
2391  if (fil_tablespace_exists_in_mem(space_id)) {
2392  /* Create the database directory for the new name, if
2393  it does not exist yet */
2394  fil_create_directory_for_tablename(new_name);
2395 
2396  /* Rename the table if there is not yet a tablespace
2397  with the same name */
2398 
2399  if (fil_get_space_id_for_table(new_name)
2400  == ULINT_UNDEFINED) {
2401  /* We do not care about the old name, that
2402  is why we pass NULL as the first argument. */
2403  if (!fil_rename_tablespace(NULL, space_id,
2404  new_name, NULL)) {
2405  ut_error;
2406  }
2407  }
2408  }
2409 
2410  break;
2411 
2412  case MLOG_FILE_CREATE:
2413  case MLOG_FILE_CREATE2:
2414  if (fil_tablespace_exists_in_mem(space_id)) {
2415  /* Do nothing */
2416  } else if (fil_get_space_id_for_table(name)
2417  != ULINT_UNDEFINED) {
2418  /* Do nothing */
2419  } else if (log_flags & MLOG_FILE_FLAG_TEMP) {
2420  /* Temporary table, do nothing */
2421  } else {
2422  const char* path = NULL;
2423 
2424  /* Create the database directory for name, if it does
2425  not exist yet */
2426  fil_create_directory_for_tablename(name);
2427 
2429  space_id, name, path, flags,
2431  FIL_IBD_FILE_INITIAL_SIZE) != DB_SUCCESS) {
2432  ut_error;
2433  }
2434  }
2435 
2436  break;
2437 
2438  default:
2439  ut_error;
2440  }
2441 
2442  return(ptr);
2443 }
2444 
2445 /*******************************************************************/
2449 static
2450 char*
2451 fil_make_cfg_name(
2452 /*==============*/
2453  const char* filepath)
2454 {
2455  char* cfg_name;
2456 
2457  /* Create a temporary file path by replacing the .ibd suffix
2458  with .cfg. */
2459 
2460  ut_ad(strlen(filepath) > 4);
2461 
2462  cfg_name = mem_strdup(filepath);
2463  ut_snprintf(cfg_name + strlen(cfg_name) - 3, 4, "cfg");
2464  return(cfg_name);
2465 }
2466 
2467 /*******************************************************************/
2470 static
2471 ulint
2472 fil_ibuf_check_pending_ops(
2473 /*=======================*/
2474  fil_space_t* space,
2475  ulint count)
2476 {
2477  ut_ad(mutex_own(&fil_system->mutex));
2478 
2479  if (space != 0 && space->n_pending_ops != 0) {
2480 
2481  if (count > 5000) {
2482  ib_logf(IB_LOG_LEVEL_WARN,
2483  "Trying to close/delete tablespace "
2484  "'%s' but there are %lu pending change "
2485  "buffer merges on it.",
2486  space->name,
2487  (ulong) space->n_pending_ops);
2488  }
2489 
2490  return(count + 1);
2491  }
2492 
2493  return(0);
2494 }
2495 
2496 /*******************************************************************/
2499 static
2500 ulint
2501 fil_check_pending_io(
2502 /*=================*/
2503  fil_space_t* space,
2504  fil_node_t** node,
2505  ulint count)
2506 {
2507  ut_ad(mutex_own(&fil_system->mutex));
2508  ut_a(space->n_pending_ops == 0);
2509 
2510  /* The following code must change when InnoDB supports
2511  multiple datafiles per tablespace. */
2512  ut_a(UT_LIST_GET_LEN(space->chain) == 1);
2513 
2514  *node = UT_LIST_GET_FIRST(space->chain);
2515 
2516  if (space->n_pending_flushes > 0 || (*node)->n_pending > 0) {
2517 
2518  ut_a(!(*node)->being_extended);
2519 
2520  if (count > 1000) {
2521  ib_logf(IB_LOG_LEVEL_WARN,
2522  "Trying to close/delete tablespace '%s' "
2523  "but there are %lu flushes "
2524  " and %lu pending i/o's on it.",
2525  space->name,
2526  (ulong) space->n_pending_flushes,
2527  (ulong) (*node)->n_pending);
2528  }
2529 
2530  return(count + 1);
2531  }
2532 
2533  return(0);
2534 }
2535 
2536 /*******************************************************************/
2539 static
2540 dberr_t
2541 fil_check_pending_operations(
2542 /*=========================*/
2543  ulint id,
2544  fil_space_t** space,
2545  char** path)
2546 {
2547  ulint count = 0;
2548 
2549  ut_a(id != TRX_SYS_SPACE);
2550  ut_ad(space);
2551 
2552  *space = 0;
2553 
2554  mutex_enter(&fil_system->mutex);
2555  fil_space_t* sp = fil_space_get_by_id(id);
2556  if (sp) {
2557  sp->stop_new_ops = TRUE;
2558  }
2559  mutex_exit(&fil_system->mutex);
2560 
2561  /* Check for pending change buffer merges. */
2562 
2563  do {
2564  mutex_enter(&fil_system->mutex);
2565 
2566  sp = fil_space_get_by_id(id);
2567 
2568  count = fil_ibuf_check_pending_ops(sp, count);
2569 
2570  mutex_exit(&fil_system->mutex);
2571 
2572  if (count > 0) {
2573  os_thread_sleep(20000);
2574  }
2575 
2576  } while (count > 0);
2577 
2578  /* Check for pending IO. */
2579 
2580  *path = 0;
2581 
2582  do {
2583  mutex_enter(&fil_system->mutex);
2584 
2585  sp = fil_space_get_by_id(id);
2586 
2587  if (sp == NULL) {
2588  mutex_exit(&fil_system->mutex);
2589  return(DB_TABLESPACE_NOT_FOUND);
2590  }
2591 
2592  fil_node_t* node;
2593 
2594  count = fil_check_pending_io(sp, &node, count);
2595 
2596  if (count == 0) {
2597  *path = mem_strdup(node->name);
2598  }
2599 
2600  mutex_exit(&fil_system->mutex);
2601 
2602  if (count > 0) {
2603  os_thread_sleep(20000);
2604  }
2605 
2606  } while (count > 0);
2607 
2608  ut_ad(sp);
2609 
2610  *space = sp;
2611  return(DB_SUCCESS);
2612 }
2613 
2614 /*******************************************************************/
2618 UNIV_INTERN
2619 dberr_t
2621 /*=================*/
2622  trx_t* trx,
2623  ulint id)
2624 {
2625  char* path = 0;
2626  fil_space_t* space = 0;
2627 
2628  ut_a(id != TRX_SYS_SPACE);
2629 
2630  dberr_t err = fil_check_pending_operations(id, &space, &path);
2631 
2632  if (err != DB_SUCCESS) {
2633  return(err);
2634  }
2635 
2636  ut_a(space);
2637  ut_a(path != 0);
2638 
2639  rw_lock_x_lock(&space->latch);
2640 
2641 #ifndef UNIV_HOTBACKUP
2642  /* Invalidate in the buffer pool all pages belonging to the
2643  tablespace. Since we have set space->stop_new_ops = TRUE, readahead
2644  or ibuf merge can no longer read more pages of this tablespace to the
2645  buffer pool. Thus we can clean the tablespace out of the buffer pool
2646  completely and permanently. The flag stop_new_ops also prevents
2647  fil_flush() from being applied to this tablespace. */
2648 
2650 #endif
2651  mutex_enter(&fil_system->mutex);
2652 
2653  /* If the free is successful, the X lock will be released before
2654  the space memory data structure is freed. */
2655 
2656  if (!fil_space_free(id, TRUE)) {
2657  rw_lock_x_unlock(&space->latch);
2658  err = DB_TABLESPACE_NOT_FOUND;
2659  } else {
2660  err = DB_SUCCESS;
2661  }
2662 
2663  mutex_exit(&fil_system->mutex);
2664 
2665  /* If it is a delete then also delete any generated files, otherwise
2666  when we drop the database the remove directory will fail. */
2667 
2668  char* cfg_name = fil_make_cfg_name(path);
2669 
2670  os_file_delete_if_exists(innodb_file_data_key, cfg_name);
2671 
2672  mem_free(path);
2673  mem_free(cfg_name);
2674 
2675  return(err);
2676 }
2677 
2678 /*******************************************************************/
2682 UNIV_INTERN
2683 dberr_t
2685 /*==================*/
2686  ulint id,
2687  buf_remove_t buf_remove)
2690 {
2691  char* path = 0;
2692  fil_space_t* space = 0;
2693 
2694  ut_a(id != TRX_SYS_SPACE);
2695 
2696  dberr_t err = fil_check_pending_operations(id, &space, &path);
2697 
2698  if (err != DB_SUCCESS) {
2699 
2700  ib_logf(IB_LOG_LEVEL_ERROR,
2701  "Cannot delete tablespace %lu because it is not "
2702  "found in the tablespace memory cache.",
2703  (ulong) id);
2704 
2705  return(err);
2706  }
2707 
2708  ut_a(space);
2709  ut_a(path != 0);
2710 
2711  /* Important: We rely on the data dictionary mutex to ensure
2712  that a race is not possible here. It should serialize the tablespace
2713  drop/free. We acquire an X latch only to avoid a race condition
2714  when accessing the tablespace instance via:
2715 
2716  fsp_get_available_space_in_free_extents().
2717 
2718  There our main motivation is to reduce the contention on the
2719  dictionary mutex. */
2720 
2721  rw_lock_x_lock(&space->latch);
2722 
2723 #ifndef UNIV_HOTBACKUP
2724  /* IMPORTANT: Because we have set space::stop_new_ops there
2725  can't be any new ibuf merges, reads or flushes. We are here
2726  because node::n_pending was zero above. However, it is still
2727  possible to have pending read and write requests:
2728 
2729  A read request can happen because the reader thread has
2730  gone through the ::stop_new_ops check in buf_page_init_for_read()
2731  before the flag was set and has not yet incremented ::n_pending
2732  when we checked it above.
2733 
2734  A write request can be issued any time because we don't check
2735  the ::stop_new_ops flag when queueing a block for write.
2736 
2737  We deal with pending write requests in the following function
2738  where we'd minimally evict all dirty pages belonging to this
2739  space from the flush_list. Not that if a block is IO-fixed
2740  we'll wait for IO to complete.
2741 
2742  To deal with potential read requests by checking the
2743  ::stop_new_ops flag in fil_io() */
2744 
2745  buf_LRU_flush_or_remove_pages(id, buf_remove, 0);
2746 
2747 #endif /* !UNIV_HOTBACKUP */
2748 
2749  /* If it is a delete then also delete any generated files, otherwise
2750  when we drop the database the remove directory will fail. */
2751  {
2752  char* cfg_name = fil_make_cfg_name(path);
2753  os_file_delete_if_exists(innodb_file_data_key, cfg_name);
2754  mem_free(cfg_name);
2755  }
2756 
2757  /* Delete the link file pointing to the ibd file we are deleting. */
2758  if (FSP_FLAGS_HAS_DATA_DIR(space->flags)) {
2759  fil_delete_link_file(space->name);
2760  }
2761 
2762  mutex_enter(&fil_system->mutex);
2763 
2764  /* Double check the sanity of pending ops after reacquiring
2765  the fil_system::mutex. */
2766  if (fil_space_get_by_id(id)) {
2767  ut_a(space->n_pending_ops == 0);
2768  ut_a(UT_LIST_GET_LEN(space->chain) == 1);
2769  fil_node_t* node = UT_LIST_GET_FIRST(space->chain);
2770  ut_a(node->n_pending == 0);
2771  }
2772 
2773  if (!fil_space_free(id, TRUE)) {
2774  err = DB_TABLESPACE_NOT_FOUND;
2775  }
2776 
2777  mutex_exit(&fil_system->mutex);
2778 
2779  if (err != DB_SUCCESS) {
2780  rw_lock_x_unlock(&space->latch);
2781  } else if (!os_file_delete(innodb_file_data_key, path)
2782  && !os_file_delete_if_exists(innodb_file_data_key, path)) {
2783 
2784  /* Note: This is because we have removed the
2785  tablespace instance from the cache. */
2786 
2787  err = DB_IO_ERROR;
2788  }
2789 
2790  if (err == DB_SUCCESS) {
2791 #ifndef UNIV_HOTBACKUP
2792  /* Write a log record about the deletion of the .ibd
2793  file, so that ibbackup can replay it in the
2794  --apply-log phase. We use a dummy mtr and the familiar
2795  log write mechanism. */
2796  mtr_t mtr;
2797 
2798  /* When replaying the operation in ibbackup, do not try
2799  to write any log record */
2800  mtr_start(&mtr);
2801 
2802  fil_op_write_log(MLOG_FILE_DELETE, id, 0, 0, path, NULL, &mtr);
2803  mtr_commit(&mtr);
2804 #endif
2805  err = DB_SUCCESS;
2806  }
2807 
2808  mem_free(path);
2809 
2810  return(err);
2811 }
2812 
2813 /*******************************************************************/
2816 UNIV_INTERN
2817 ibool
2819 /*============================*/
2820  ulint id)
2821 {
2822  fil_space_t* space;
2823  ibool is_being_deleted;
2824 
2825  mutex_enter(&fil_system->mutex);
2826 
2827  space = fil_space_get_by_id(id);
2828 
2829  ut_a(space != NULL);
2830 
2831  is_being_deleted = space->stop_new_ops;
2832 
2833  mutex_exit(&fil_system->mutex);
2834 
2835  return(is_being_deleted);
2836 }
2837 
2838 #ifndef UNIV_HOTBACKUP
2839 /*******************************************************************/
2850 UNIV_INTERN
2851 dberr_t
2853 /*===================*/
2854  ulint id)
2855 {
2856  dberr_t err;
2857 
2858  switch (err = fil_delete_tablespace(id, BUF_REMOVE_ALL_NO_WRITE)) {
2859  case DB_SUCCESS:
2860  break;
2861 
2862  case DB_IO_ERROR:
2863  ib_logf(IB_LOG_LEVEL_WARN,
2864  "While deleting tablespace %lu in DISCARD TABLESPACE."
2865  " File rename/delete failed: %s",
2866  (ulong) id, ut_strerr(err));
2867  break;
2868 
2869  case DB_TABLESPACE_NOT_FOUND:
2870  ib_logf(IB_LOG_LEVEL_WARN,
2871  "Cannot delete tablespace %lu in DISCARD "
2872  "TABLESPACE. %s",
2873  (ulong) id, ut_strerr(err));
2874  break;
2875 
2876  default:
2877  ut_error;
2878  }
2879 
2880  /* Remove all insert buffer entries for the tablespace */
2881 
2883 
2884  return(err);
2885 }
2886 #endif /* !UNIV_HOTBACKUP */
2887 
2888 /*******************************************************************/
2891 static
2892 ibool
2893 fil_rename_tablespace_in_mem(
2894 /*=========================*/
2895  fil_space_t* space,
2896  fil_node_t* node,
2897  const char* new_name,
2898  const char* new_path)
2899 {
2900  fil_space_t* space2;
2901  const char* old_name = space->name;
2902 
2903  ut_ad(mutex_own(&fil_system->mutex));
2904 
2905  space2 = fil_space_get_by_name(old_name);
2906  if (space != space2) {
2907  fputs("InnoDB: Error: cannot find ", stderr);
2908  ut_print_filename(stderr, old_name);
2909  fputs(" in tablespace memory cache\n", stderr);
2910 
2911  return(FALSE);
2912  }
2913 
2914  space2 = fil_space_get_by_name(new_name);
2915  if (space2 != NULL) {
2916  fputs("InnoDB: Error: ", stderr);
2917  ut_print_filename(stderr, new_name);
2918  fputs(" is already in tablespace memory cache\n", stderr);
2919 
2920  return(FALSE);
2921  }
2922 
2923  HASH_DELETE(fil_space_t, name_hash, fil_system->name_hash,
2924  ut_fold_string(space->name), space);
2925  mem_free(space->name);
2926  mem_free(node->name);
2927 
2928  space->name = mem_strdup(new_name);
2929  node->name = mem_strdup(new_path);
2930 
2931  HASH_INSERT(fil_space_t, name_hash, fil_system->name_hash,
2932  ut_fold_string(new_name), space);
2933  return(TRUE);
2934 }
2935 
2936 /*******************************************************************/
2940 UNIV_INTERN
2941 char*
2943 /*==============*/
2944  const char* name,
2945  bool is_full_path)
2946 {
2947  char* filename;
2948  ulint namelen = strlen(name);
2949  ulint dirlen = strlen(fil_path_to_mysql_datadir);
2950  ulint pathlen = dirlen + namelen + sizeof "/.ibd";
2951 
2952  filename = static_cast<char*>(mem_alloc(pathlen));
2953 
2954  if (is_full_path) {
2955  memcpy(filename, name, namelen);
2956  memcpy(filename + namelen, ".ibd", sizeof ".ibd");
2957  } else {
2958  ut_snprintf(filename, pathlen, "%s/%s.ibd",
2960 
2961  }
2962 
2963  srv_normalize_path_for_win(filename);
2964 
2965  return(filename);
2966 }
2967 
2968 /*******************************************************************/
2972 UNIV_INTERN
2973 char*
2975 /*==============*/
2976  const char* name)
2977 {
2978  char* filename;
2979  ulint namelen = strlen(name);
2980  ulint dirlen = strlen(fil_path_to_mysql_datadir);
2981  ulint pathlen = dirlen + namelen + sizeof "/.isl";
2982 
2983  filename = static_cast<char*>(mem_alloc(pathlen));
2984 
2985  ut_snprintf(filename, pathlen, "%s/%s.isl",
2987 
2988  srv_normalize_path_for_win(filename);
2989 
2990  return(filename);
2991 }
2992 
2993 /*******************************************************************/
2997 UNIV_INTERN
2998 ibool
3000 /*==================*/
3001  const char* old_name_in,
3006  ulint id,
3007  const char* new_name,
3010  const char* new_path_in)
3014 {
3015  ibool success;
3016  fil_space_t* space;
3017  fil_node_t* node;
3018  ulint count = 0;
3019  char* new_path;
3020  char* old_name;
3021  char* old_path;
3022  const char* not_given = "(name not specified)";
3023 
3024  ut_a(id != 0);
3025 
3026 retry:
3027  count++;
3028 
3029  if (!(count % 1000)) {
3030  ut_print_timestamp(stderr);
3031  fputs(" InnoDB: Warning: problems renaming ", stderr);
3032  ut_print_filename(stderr,
3033  old_name_in ? old_name_in : not_given);
3034  fputs(" to ", stderr);
3035  ut_print_filename(stderr, new_name);
3036  fprintf(stderr, ", %lu iterations\n", (ulong) count);
3037  }
3038 
3039  mutex_enter(&fil_system->mutex);
3040 
3041  space = fil_space_get_by_id(id);
3042 
3043  DBUG_EXECUTE_IF("fil_rename_tablespace_failure_1", space = NULL; );
3044 
3045  if (space == NULL) {
3046  ib_logf(IB_LOG_LEVEL_ERROR,
3047  "Cannot find space id %lu in the tablespace "
3048  "memory cache, though the table '%s' in a "
3049  "rename operation should have that id.",
3050  (ulong) id, old_name_in ? old_name_in : not_given);
3051  mutex_exit(&fil_system->mutex);
3052 
3053  return(FALSE);
3054  }
3055 
3056  if (count > 25000) {
3057  space->stop_ios = FALSE;
3058  mutex_exit(&fil_system->mutex);
3059 
3060  return(FALSE);
3061  }
3062 
3063  /* We temporarily close the .ibd file because we do not trust that
3064  operating systems can rename an open file. For the closing we have to
3065  wait until there are no pending i/o's or flushes on the file. */
3066 
3067  space->stop_ios = TRUE;
3068 
3069  /* The following code must change when InnoDB supports
3070  multiple datafiles per tablespace. */
3071  ut_a(UT_LIST_GET_LEN(space->chain) == 1);
3072  node = UT_LIST_GET_FIRST(space->chain);
3073 
3074  if (node->n_pending > 0
3075  || node->n_pending_flushes > 0
3076  || node->being_extended) {
3077  /* There are pending i/o's or flushes or the file is
3078  currently being extended, sleep for a while and
3079  retry */
3080 
3081  mutex_exit(&fil_system->mutex);
3082 
3083  os_thread_sleep(20000);
3084 
3085  goto retry;
3086 
3087  } else if (node->modification_counter > node->flush_counter) {
3088  /* Flush the space */
3089 
3090  mutex_exit(&fil_system->mutex);
3091 
3092  os_thread_sleep(20000);
3093 
3094  fil_flush(id);
3095 
3096  goto retry;
3097 
3098  } else if (node->open) {
3099  /* Close the file */
3100 
3101  fil_node_close_file(node, fil_system);
3102  }
3103 
3104  /* Check that the old name in the space is right */
3105 
3106  if (old_name_in) {
3107  old_name = mem_strdup(old_name_in);
3108  ut_a(strcmp(space->name, old_name) == 0);
3109  } else {
3110  old_name = mem_strdup(space->name);
3111  }
3112  old_path = mem_strdup(node->name);
3113 
3114  /* Rename the tablespace and the node in the memory cache */
3115  new_path = new_path_in ? mem_strdup(new_path_in)
3116  : fil_make_ibd_name(new_name, false);
3117 
3118  success = fil_rename_tablespace_in_mem(
3119  space, node, new_name, new_path);
3120 
3121  if (success) {
3122 
3123  DBUG_EXECUTE_IF("fil_rename_tablespace_failure_2",
3124  goto skip_second_rename; );
3125 
3126  success = os_file_rename(
3127  innodb_file_data_key, old_path, new_path);
3128 
3129  DBUG_EXECUTE_IF("fil_rename_tablespace_failure_2",
3130 skip_second_rename:
3131  success = FALSE; );
3132 
3133  if (!success) {
3134  /* We have to revert the changes we made
3135  to the tablespace memory cache */
3136 
3137  ut_a(fil_rename_tablespace_in_mem(
3138  space, node, old_name, old_path));
3139  }
3140  }
3141 
3142  space->stop_ios = FALSE;
3143 
3144  mutex_exit(&fil_system->mutex);
3145 
3146 #ifndef UNIV_HOTBACKUP
3147  if (success && !recv_recovery_on) {
3148  mtr_t mtr;
3149 
3150  mtr_start(&mtr);
3151 
3152  fil_op_write_log(MLOG_FILE_RENAME, id, 0, 0, old_name, new_name,
3153  &mtr);
3154  mtr_commit(&mtr);
3155  }
3156 #endif /* !UNIV_HOTBACKUP */
3157 
3158  mem_free(new_path);
3159  mem_free(old_path);
3160  mem_free(old_name);
3161 
3162  return(success);
3163 }
3164 
3165 /*******************************************************************/
3170 UNIV_INTERN
3171 dberr_t
3173 /*=================*/
3174  const char* tablename,
3175  const char* filepath)
3176 {
3177  os_file_t file;
3178  ibool success;
3179  dberr_t err = DB_SUCCESS;
3180  char* link_filepath;
3181  char* prev_filepath = fil_read_link_file(tablename);
3182 
3184 
3185  if (prev_filepath) {
3186  /* Truncate will call this with an existing
3187  link file which contains the same filepath. */
3188  if (0 == strcmp(prev_filepath, filepath)) {
3189  mem_free(prev_filepath);
3190  return(DB_SUCCESS);
3191  }
3192  mem_free(prev_filepath);
3193  }
3194 
3195  link_filepath = fil_make_isl_name(tablename);
3196 
3197  file = os_file_create_simple_no_error_handling(
3198  innodb_file_data_key, link_filepath,
3199  OS_FILE_CREATE, OS_FILE_READ_WRITE, &success);
3200 
3201  if (!success) {
3202  /* The following call will print an error message */
3203  ulint error = os_file_get_last_error(true);
3204 
3205  ut_print_timestamp(stderr);
3206  fputs(" InnoDB: Cannot create file ", stderr);
3207  ut_print_filename(stderr, link_filepath);
3208  fputs(".\n", stderr);
3209 
3210  if (error == OS_FILE_ALREADY_EXISTS) {
3211  fputs("InnoDB: The link file: ", stderr);
3212  ut_print_filename(stderr, filepath);
3213  fputs(" already exists.\n", stderr);
3214  err = DB_TABLESPACE_EXISTS;
3215 
3216  } else if (error == OS_FILE_DISK_FULL) {
3217  err = DB_OUT_OF_FILE_SPACE;
3218 
3219  } else {
3220  err = DB_ERROR;
3221  }
3222 
3223  /* file is not open, no need to close it. */
3224  mem_free(link_filepath);
3225  return(err);
3226  }
3227 
3228  if (!os_file_write(link_filepath, file, filepath, 0,
3229  strlen(filepath))) {
3230  err = DB_ERROR;
3231  }
3232 
3233  /* Close the file, we only need it at startup */
3234  os_file_close(file);
3235 
3236  mem_free(link_filepath);
3237 
3238  return(err);
3239 }
3240 
3241 /*******************************************************************/
3243 UNIV_INTERN
3244 void
3246 /*=================*/
3247  const char* tablename)
3248 {
3249  char* link_filepath = fil_make_isl_name(tablename);
3250 
3251  os_file_delete_if_exists(innodb_file_data_key, link_filepath);
3252 
3253  mem_free(link_filepath);
3254 }
3255 
3256 /*******************************************************************/
3263 UNIV_INTERN
3264 char*
3266 /*===============*/
3267  const char* name)
3268 {
3269  char* filepath = NULL;
3270  char* link_filepath;
3271  FILE* file = NULL;
3272 
3273  /* The .isl file is in the 'normal' tablespace location. */
3274  link_filepath = fil_make_isl_name(name);
3275 
3276  file = fopen(link_filepath, "r+b");
3277 
3278  mem_free(link_filepath);
3279 
3280  if (file) {
3281  filepath = static_cast<char*>(mem_alloc(OS_FILE_MAX_PATH));
3282 
3283  os_file_read_string(file, filepath, OS_FILE_MAX_PATH);
3284  fclose(file);
3285 
3286  if (strlen(filepath)) {
3287  /* Trim whitespace from end of filepath */
3288  ulint lastch = strlen(filepath) - 1;
3289  while (lastch > 4 && filepath[lastch] <= 0x20) {
3290  filepath[lastch--] = 0x00;
3291  }
3292  srv_normalize_path_for_win(filepath);
3293  }
3294  }
3295 
3296  return(filepath);
3297 }
3298 
3299 /*******************************************************************/
3302 UNIV_INTERN
3303 ibool
3305 /*===============*/
3306  const char* tablename,
3307  char** remote_filepath,
3308  os_file_t* remote_file)
3310 {
3311  ibool success;
3312 
3313  *remote_filepath = fil_read_link_file(tablename);
3314  if (*remote_filepath == NULL) {
3315  return(FALSE);
3316  }
3317 
3318  /* The filepath provided is different from what was
3319  found in the link file. */
3320  *remote_file = os_file_create_simple_no_error_handling(
3321  innodb_file_data_key, *remote_filepath,
3322  OS_FILE_OPEN, OS_FILE_READ_ONLY,
3323  &success);
3324 
3325  if (!success) {
3326  char* link_filepath = fil_make_isl_name(tablename);
3327 
3328  /* The following call prints an error message */
3329  os_file_get_last_error(true);
3330 
3331  ib_logf(IB_LOG_LEVEL_ERROR,
3332  "A link file was found named '%s' "
3333  "but the linked tablespace '%s' "
3334  "could not be opened.",
3335  link_filepath, *remote_filepath);
3336 
3337  mem_free(link_filepath);
3338  mem_free(*remote_filepath);
3339  *remote_filepath = NULL;
3340  }
3341 
3342  return(success);
3343 }
3344 
3345 /*******************************************************************/
3353 UNIV_INTERN
3354 dberr_t
3356 /*===================================*/
3357  ulint space_id,
3358  const char* tablename,
3361  const char* dir_path,
3362  ulint flags,
3363  ulint flags2,
3364  ulint size)
3367 {
3368  os_file_t file;
3369  ibool ret;
3370  dberr_t err;
3371  byte* buf2;
3372  byte* page;
3373  char* path;
3374  ibool success;
3375  /* TRUE if a table is created with CREATE TEMPORARY TABLE */
3376  bool is_temp = !!(flags2 & DICT_TF2_TEMPORARY);
3377  bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags);
3378 
3379  ut_a(space_id > 0);
3381  ut_a(space_id < SRV_LOG_SPACE_FIRST_ID);
3383  ut_a(fsp_flags_is_valid(flags));
3384 
3385  if (is_temp) {
3386  /* Temporary table filepath */
3387  ut_ad(dir_path);
3388  path = fil_make_ibd_name(dir_path, true);
3389  } else if (has_data_dir) {
3390  ut_ad(dir_path);
3391  path = os_file_make_remote_pathname(dir_path, tablename, "ibd");
3392 
3393  /* Since this tablespace file will be created in a
3394  remote directory, let's create the subdirectories
3395  in the path, if they are not there already. */
3396  success = os_file_create_subdirs_if_needed(path);
3397  if (!success) {
3398  err = DB_ERROR;
3399  goto error_exit_3;
3400  }
3401  } else {
3402  path = fil_make_ibd_name(tablename, false);
3403  }
3404 
3405  file = os_file_create(
3406  innodb_file_data_key, path,
3408  OS_FILE_NORMAL,
3409  OS_DATA_FILE,
3410  &ret);
3411 
3412  if (ret == FALSE) {
3413  /* The following call will print an error message */
3414  ulint error = os_file_get_last_error(true);
3415 
3416  ib_logf(IB_LOG_LEVEL_ERROR,
3417  "Cannot create file '%s'\n", path);
3418 
3419  if (error == OS_FILE_ALREADY_EXISTS) {
3420  ib_logf(IB_LOG_LEVEL_ERROR,
3421  "The file '%s' already exists though the "
3422  "corresponding table did not exist "
3423  "in the InnoDB data dictionary. "
3424  "Have you moved InnoDB .ibd files "
3425  "around without using the SQL commands "
3426  "DISCARD TABLESPACE and IMPORT TABLESPACE, "
3427  "or did mysqld crash in the middle of "
3428  "CREATE TABLE? "
3429  "You can resolve the problem by removing "
3430  "the file '%s' under the 'datadir' of MySQL.",
3431  path, path);
3432 
3433  err = DB_TABLESPACE_EXISTS;
3434  goto error_exit_3;
3435  }
3436 
3437  if (error == OS_FILE_DISK_FULL) {
3438  err = DB_OUT_OF_FILE_SPACE;
3439  goto error_exit_3;
3440  }
3441 
3442  err = DB_ERROR;
3443  goto error_exit_3;
3444  }
3445 
3446  ret = os_file_set_size(path, file, size * UNIV_PAGE_SIZE);
3447 
3448  if (!ret) {
3449  err = DB_OUT_OF_FILE_SPACE;
3450  goto error_exit_2;
3451  }
3452 
3453  /* printf("Creating tablespace %s id %lu\n", path, space_id); */
3454 
3455  /* We have to write the space id to the file immediately and flush the
3456  file to disk. This is because in crash recovery we must be aware what
3457  tablespaces exist and what are their space id's, so that we can apply
3458  the log records to the right file. It may take quite a while until
3459  buffer pool flush algorithms write anything to the file and flush it to
3460  disk. If we would not write here anything, the file would be filled
3461  with zeros from the call of os_file_set_size(), until a buffer pool
3462  flush would write to it. */
3463 
3464  buf2 = static_cast<byte*>(ut_malloc(3 * UNIV_PAGE_SIZE));
3465  /* Align the memory for file i/o if we might have O_DIRECT set */
3466  page = static_cast<byte*>(ut_align(buf2, UNIV_PAGE_SIZE));
3467 
3468  memset(page, '\0', UNIV_PAGE_SIZE);
3469 
3470  /* Add the UNIV_PAGE_SIZE to the table flags and write them to the
3471  tablespace header. */
3472  flags = fsp_flags_set_page_size(flags, UNIV_PAGE_SIZE);
3473  fsp_header_init_fields(page, space_id, flags);
3475 
3476  if (!(fsp_flags_is_compressed(flags))) {
3477  buf_flush_init_for_writing(page, NULL, 0);
3478  ret = os_file_write(path, file, page, 0, UNIV_PAGE_SIZE);
3479  } else {
3480  page_zip_des_t page_zip;
3481  ulint zip_size;
3482 
3483  zip_size = fsp_flags_get_zip_size(flags);
3484 
3485  page_zip_set_size(&page_zip, zip_size);
3486  page_zip.data = page + UNIV_PAGE_SIZE;
3487 #ifdef UNIV_DEBUG
3488  page_zip.m_start =
3489 #endif /* UNIV_DEBUG */
3490  page_zip.m_end = page_zip.m_nonempty =
3491  page_zip.n_blobs = 0;
3492  buf_flush_init_for_writing(page, &page_zip, 0);
3493  ret = os_file_write(path, file, page_zip.data, 0, zip_size);
3494  }
3495 
3496  ut_free(buf2);
3497 
3498  if (!ret) {
3499  ib_logf(IB_LOG_LEVEL_ERROR,
3500  "Could not write the first page to tablespace "
3501  "'%s'", path);
3502 
3503  err = DB_ERROR;
3504  goto error_exit_2;
3505  }
3506 
3507  ret = os_file_flush(file);
3508 
3509  if (!ret) {
3510  ib_logf(IB_LOG_LEVEL_ERROR,
3511  "File flush of tablespace '%s' failed", path);
3512  err = DB_ERROR;
3513  goto error_exit_2;
3514  }
3515 
3516  if (has_data_dir) {
3517  /* Now that the IBD file is created, make the ISL file. */
3518  err = fil_create_link_file(tablename, path);
3519  if (err != DB_SUCCESS) {
3520  goto error_exit_2;
3521  }
3522  }
3523 
3524  success = fil_space_create(tablename, space_id, flags, FIL_TABLESPACE);
3525  if (!success || !fil_node_create(path, size, space_id, FALSE)) {
3526  err = DB_ERROR;
3527  goto error_exit_1;
3528  }
3529 
3530 #ifndef UNIV_HOTBACKUP
3531  {
3532  mtr_t mtr;
3533  ulint mlog_file_flag = 0;
3534 
3535  if (is_temp) {
3536  mlog_file_flag |= MLOG_FILE_FLAG_TEMP;
3537  }
3538 
3539  mtr_start(&mtr);
3540 
3541  fil_op_write_log(flags
3543  : MLOG_FILE_CREATE,
3544  space_id, mlog_file_flag, flags,
3545  tablename, NULL, &mtr);
3546 
3547  mtr_commit(&mtr);
3548  }
3549 #endif
3550  err = DB_SUCCESS;
3551 
3552  /* Error code is set. Cleanup the various variables used.
3553  These labels reflect the order in which variables are assigned or
3554  actions are done. */
3555 error_exit_1:
3556  if (has_data_dir && err != DB_SUCCESS) {
3557  fil_delete_link_file(tablename);
3558  }
3559 error_exit_2:
3560  os_file_close(file);
3561  if (err != DB_SUCCESS) {
3562  os_file_delete(innodb_file_data_key, path);
3563  }
3564 error_exit_3:
3565  mem_free(path);
3566 
3567  return(err);
3568 }
3569 
3570 #ifndef UNIV_HOTBACKUP
3571 /********************************************************************/
3573 static
3574 void
3575 fil_report_bad_tablespace(
3576 /*======================*/
3577  const char* filepath,
3578  const char* check_msg,
3579  ulint found_id,
3580  ulint found_flags,
3581  ulint expected_id,
3582  ulint expected_flags)
3583 {
3584  if (check_msg) {
3585  ib_logf(IB_LOG_LEVEL_ERROR,
3586  "Error %s in file '%s',"
3587  "tablespace id=%lu, flags=%lu. "
3588  "Please refer to "
3589  REFMAN "innodb-troubleshooting-datadict.html "
3590  "for how to resolve the issue.",
3591  check_msg, filepath,
3592  (ulong) expected_id, (ulong) expected_flags);
3593  return;
3594  }
3595 
3596  ib_logf(IB_LOG_LEVEL_ERROR,
3597  "In file '%s', tablespace id and flags are %lu and %lu, "
3598  "but in the InnoDB data dictionary they are %lu and %lu. "
3599  "Have you moved InnoDB .ibd files around without using the "
3600  "commands DISCARD TABLESPACE and IMPORT TABLESPACE? "
3601  "Please refer to "
3602  REFMAN "innodb-troubleshooting-datadict.html "
3603  "for how to resolve the issue.",
3604  filepath, (ulong) found_id, (ulong) found_flags,
3605  (ulong) expected_id, (ulong) expected_flags);
3606 }
3607 
3609  ibool success;
3610  const char* check_msg;
3611  ibool valid;
3613  char* filepath;
3614  lsn_t lsn;
3615  ulint id;
3616  ulint flags;
3617 #ifdef UNIV_LOG_ARCHIVE
3618  ulint arch_log_no;
3619 #endif /* UNIV_LOG_ARCHIVE */
3620 };
3621 
3622 /********************************************************************/
3644 UNIV_INTERN
3645 dberr_t
3647 /*=============================*/
3648  bool validate,
3649  bool fix_dict,
3650  ulint id,
3651  ulint flags,
3652  const char* tablename,
3654  const char* path_in)
3655 {
3656  dberr_t err = DB_SUCCESS;
3657  bool dict_filepath_same_as_default = false;
3658  bool link_file_found = false;
3659  bool link_file_is_bad = false;
3660  fsp_open_info def;
3661  fsp_open_info dict;
3662  fsp_open_info remote;
3663  ulint tablespaces_found = 0;
3664  ulint valid_tablespaces_found = 0;
3665 
3666 #ifdef UNIV_SYNC_DEBUG
3667  ut_ad(!fix_dict || rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
3668 #endif /* UNIV_SYNC_DEBUG */
3669  ut_ad(!fix_dict || mutex_own(&(dict_sys->mutex)));
3670 
3671  if (!fsp_flags_is_valid(flags)) {
3672  return(DB_CORRUPTION);
3673  }
3674 
3675  /* If the tablespace was relocated, we do not
3676  compare the DATA_DIR flag */
3677  ulint mod_flags = flags & ~FSP_FLAGS_MASK_DATA_DIR;
3678 
3679  memset(&def, 0, sizeof(def));
3680  memset(&dict, 0, sizeof(dict));
3681  memset(&remote, 0, sizeof(remote));
3682 
3683  /* Discover the correct filepath. We will always look for an ibd
3684  in the default location. If it is remote, it should not be here. */
3685  def.filepath = fil_make_ibd_name(tablename, false);
3686 
3687  /* The path_in was read from SYS_DATAFILES. */
3688  if (path_in) {
3689  if (strcmp(def.filepath, path_in)) {
3690  dict.filepath = mem_strdup(path_in);
3691  /* possibility of multiple files. */
3692  validate = true;
3693  } else {
3694  dict_filepath_same_as_default = true;
3695  }
3696  }
3697 
3698  link_file_found = fil_open_linked_file(
3699  tablename, &remote.filepath, &remote.file);
3700  remote.success = link_file_found;
3701  if (remote.success) {
3702  /* possibility of multiple files. */
3703  validate = true;
3704  tablespaces_found++;
3705 
3706  /* A link file was found. MySQL does not allow a DATA
3707  DIRECTORY to be be the same as the default filepath. */
3708  ut_a(strcmp(def.filepath, remote.filepath));
3709 
3710  /* If there was a filepath found in SYS_DATAFILES,
3711  we hope it was the same as this remote.filepath found
3712  in the ISL file. */
3713  if (dict.filepath
3714  && (0 == strcmp(dict.filepath, remote.filepath))) {
3715  remote.success = FALSE;
3716  os_file_close(remote.file);
3717  mem_free(remote.filepath);
3718  remote.filepath = NULL;
3719  tablespaces_found--;
3720  }
3721  }
3722 
3723  /* Attempt to open the tablespace at other possible filepaths. */
3724  if (dict.filepath) {
3725  dict.file = os_file_create_simple_no_error_handling(
3726  innodb_file_data_key, dict.filepath, OS_FILE_OPEN,
3727  OS_FILE_READ_ONLY, &dict.success);
3728  if (dict.success) {
3729  /* possibility of multiple files. */
3730  validate = true;
3731  tablespaces_found++;
3732  }
3733  }
3734 
3735  /* Always look for a file at the default location. */
3736  ut_a(def.filepath);
3737  def.file = os_file_create_simple_no_error_handling(
3738  innodb_file_data_key, def.filepath, OS_FILE_OPEN,
3739  OS_FILE_READ_ONLY, &def.success);
3740  if (def.success) {
3741  tablespaces_found++;
3742  }
3743 
3744  /* We have now checked all possible tablespace locations and
3745  have a count of how many we found. If things are normal, we
3746  only found 1. */
3747  if (!validate && tablespaces_found == 1) {
3748  goto skip_validate;
3749  }
3750 
3751  /* Read the first page of the datadir tablespace, if found. */
3752  if (def.success) {
3754  def.file, FALSE, &def.flags, &def.id,
3755 #ifdef UNIV_LOG_ARCHIVE
3756  &space_arch_log_no, &space_arch_log_no,
3757 #endif /* UNIV_LOG_ARCHIVE */
3758  &def.lsn, &def.lsn);
3759  def.valid = !def.check_msg;
3760 
3761  /* Validate this single-table-tablespace with SYS_TABLES,
3762  but do not compare the DATA_DIR flag, in case the
3763  tablespace was relocated. */
3764  if (def.valid && def.id == id
3765  && (def.flags & ~FSP_FLAGS_MASK_DATA_DIR) == mod_flags) {
3766  valid_tablespaces_found++;
3767  } else {
3768  def.valid = false;
3769  /* Do not use this tablespace. */
3770  fil_report_bad_tablespace(
3771  def.filepath, def.check_msg, def.id,
3772  def.flags, id, flags);
3773  }
3774  }
3775 
3776  /* Read the first page of the remote tablespace */
3777  if (remote.success) {
3778  remote.check_msg = fil_read_first_page(
3779  remote.file, FALSE, &remote.flags, &remote.id,
3780 #ifdef UNIV_LOG_ARCHIVE
3781  &remote.arch_log_no, &remote.arch_log_no,
3782 #endif /* UNIV_LOG_ARCHIVE */
3783  &remote.lsn, &remote.lsn);
3784  remote.valid = !remote.check_msg;
3785 
3786  /* Validate this single-table-tablespace with SYS_TABLES,
3787  but do not compare the DATA_DIR flag, in case the
3788  tablespace was relocated. */
3789  if (remote.valid && remote.id == id
3790  && (remote.flags & ~FSP_FLAGS_MASK_DATA_DIR) == mod_flags) {
3791  valid_tablespaces_found++;
3792  } else {
3793  remote.valid = false;
3794  /* Do not use this linked tablespace. */
3795  fil_report_bad_tablespace(
3796  remote.filepath, remote.check_msg, remote.id,
3797  remote.flags, id, flags);
3798  link_file_is_bad = true;
3799  }
3800  }
3801 
3802  /* Read the first page of the datadir tablespace, if found. */
3803  if (dict.success) {
3805  dict.file, FALSE, &dict.flags, &dict.id,
3806 #ifdef UNIV_LOG_ARCHIVE
3807  &dict.arch_log_no, &dict.arch_log_no,
3808 #endif /* UNIV_LOG_ARCHIVE */
3809  &dict.lsn, &dict.lsn);
3810  dict.valid = !dict.check_msg;
3811 
3812  /* Validate this single-table-tablespace with SYS_TABLES,
3813  but do not compare the DATA_DIR flag, in case the
3814  tablespace was relocated. */
3815  if (dict.valid && dict.id == id
3816  && (dict.flags & ~FSP_FLAGS_MASK_DATA_DIR) == mod_flags) {
3817  valid_tablespaces_found++;
3818  } else {
3819  dict.valid = false;
3820  /* Do not use this tablespace. */
3821  fil_report_bad_tablespace(
3822  dict.filepath, dict.check_msg, dict.id,
3823  dict.flags, id, flags);
3824  }
3825  }
3826 
3827  /* Make sense of these three possible locations.
3828  First, bail out if no tablespace files were found. */
3829  if (valid_tablespaces_found == 0) {
3830  /* The following call prints an error message */
3831  os_file_get_last_error(true);
3832 
3833  ib_logf(IB_LOG_LEVEL_ERROR,
3834  "Could not find a valid tablespace file for '%s'. "
3835  "See " REFMAN "innodb-troubleshooting-datadict.html "
3836  "for how to resolve the issue.",
3837  tablename);
3838 
3839  err = DB_CORRUPTION;
3840 
3841  goto cleanup_and_exit;
3842  }
3843 
3844  /* Do not open any tablespaces if more than one tablespace with
3845  the correct space ID and flags were found. */
3846  if (tablespaces_found > 1) {
3847  ib_logf(IB_LOG_LEVEL_ERROR,
3848  "A tablespace for %s has been found in "
3849  "multiple places;", tablename);
3850  if (def.success) {
3851  ib_logf(IB_LOG_LEVEL_ERROR,
3852  "Default location; %s, LSN=" LSN_PF
3853  ", Space ID=%lu, Flags=%lu",
3854  def.filepath, def.lsn,
3855  (ulong) def.id, (ulong) def.flags);
3856  }
3857  if (remote.success) {
3858  ib_logf(IB_LOG_LEVEL_ERROR,
3859  "Remote location; %s, LSN=" LSN_PF
3860  ", Space ID=%lu, Flags=%lu",
3861  remote.filepath, remote.lsn,
3862  (ulong) remote.id, (ulong) remote.flags);
3863  }
3864  if (dict.success) {
3865  ib_logf(IB_LOG_LEVEL_ERROR,
3866  "Dictionary location; %s, LSN=" LSN_PF
3867  ", Space ID=%lu, Flags=%lu",
3868  dict.filepath, dict.lsn,
3869  (ulong) dict.id, (ulong) dict.flags);
3870  }
3871 
3872  /* Force-recovery will allow some tablespaces to be
3873  skipped by REDO if there was more than one file found.
3874  Unlike during the REDO phase of recovery, we now know
3875  if the tablespace is valid according to the dictionary,
3876  which was not available then. So if we did not force
3877  recovery and there is only one good tablespace, ignore
3878  any bad tablespaces. */
3879  if (valid_tablespaces_found > 1 || srv_force_recovery > 0) {
3880  ib_logf(IB_LOG_LEVEL_ERROR,
3881  "Will not open the tablespace for '%s'",
3882  tablename);
3883 
3884  if (def.success != def.valid
3885  || dict.success != dict.valid
3886  || remote.success != remote.valid) {
3887  err = DB_CORRUPTION;
3888  } else {
3889  err = DB_ERROR;
3890  }
3891  goto cleanup_and_exit;
3892  }
3893 
3894  /* There is only one valid tablespace found and we did
3895  not use srv_force_recovery during REDO. Use this one
3896  tablespace and clean up invalid tablespace pointers */
3897  if (def.success && !def.valid) {
3898  def.success = false;
3899  os_file_close(def.file);
3900  tablespaces_found--;
3901  }
3902  if (dict.success && !dict.valid) {
3903  dict.success = false;
3904  os_file_close(dict.file);
3905  /* Leave dict.filepath so that SYS_DATAFILES
3906  can be corrected below. */
3907  tablespaces_found--;
3908  }
3909  if (remote.success && !remote.valid) {
3910  remote.success = false;
3911  os_file_close(remote.file);
3912  mem_free(remote.filepath);
3913  remote.filepath = NULL;
3914  tablespaces_found--;
3915  }
3916  }
3917 
3918  /* At this point, there should be only one filepath. */
3919  ut_a(tablespaces_found == 1);
3920  ut_a(valid_tablespaces_found == 1);
3921 
3922  /* Only fix the dictionary at startup when there is only one thread.
3923  Calls to dict_load_table() can be done while holding other latches. */
3924  if (!fix_dict) {
3925  goto skip_validate;
3926  }
3927 
3928  /* We may need to change what is stored in SYS_DATAFILES or
3929  SYS_TABLESPACES or adjust the link file.
3930  Since a failure to update SYS_TABLESPACES or SYS_DATAFILES does
3931  not prevent opening and using the single_table_tablespace either
3932  this time or the next, we do not check the return code or fail
3933  to open the tablespace. But dict_update_filepath() will issue a
3934  warning to the log. */
3935  if (dict.filepath) {
3936  if (remote.success) {
3937  dict_update_filepath(id, remote.filepath);
3938  } else if (def.success) {
3939  dict_update_filepath(id, def.filepath);
3940  if (link_file_is_bad) {
3941  fil_delete_link_file(tablename);
3942  }
3943  } else if (!link_file_found || link_file_is_bad) {
3944  ut_ad(dict.success);
3945  /* Fix the link file if we got our filepath
3946  from the dictionary but a link file did not
3947  exist or it did not point to a valid file. */
3948  fil_delete_link_file(tablename);
3949  fil_create_link_file(tablename, dict.filepath);
3950  }
3951 
3952  } else if (remote.success && dict_filepath_same_as_default) {
3953  dict_update_filepath(id, remote.filepath);
3954 
3955  } else if (remote.success && path_in == NULL) {
3956  /* SYS_DATAFILES record for this space ID was not found. */
3958  id, tablename, remote.filepath, flags);
3959  }
3960 
3961 skip_validate:
3962  if (err != DB_SUCCESS) {
3963  ; // Don't load the tablespace into the cache
3964  } else if (!fil_space_create(tablename, id, flags, FIL_TABLESPACE)) {
3965  err = DB_ERROR;
3966  } else {
3967  /* We do not measure the size of the file, that is why
3968  we pass the 0 below */
3969 
3970  if (!fil_node_create(remote.success ? remote.filepath :
3971  dict.success ? dict.filepath :
3972  def.filepath, 0, id, FALSE)) {
3973  err = DB_ERROR;
3974  }
3975  }
3976 
3977 cleanup_and_exit:
3978  if (remote.success) {
3979  os_file_close(remote.file);
3980  }
3981  if (remote.filepath) {
3982  mem_free(remote.filepath);
3983  }
3984  if (dict.success) {
3985  os_file_close(dict.file);
3986  }
3987  if (dict.filepath) {
3988  mem_free(dict.filepath);
3989  }
3990  if (def.success) {
3991  os_file_close(def.file);
3992  }
3993  mem_free(def.filepath);
3994 
3995  return(err);
3996 }
3997 #endif /* !UNIV_HOTBACKUP */
3998 
3999 #ifdef UNIV_HOTBACKUP
4000 /*******************************************************************/
4004 static
4005 char*
4006 fil_make_ibbackup_old_name(
4007 /*=======================*/
4008  const char* name)
4009 {
4010  static const char suffix[] = "_ibbackup_old_vers_";
4011  char* path;
4012  ulint len = strlen(name);
4013 
4014  path = static_cast<char*>(mem_alloc(len + (15 + sizeof suffix)));
4015 
4016  memcpy(path, name, len);
4017  memcpy(path + len, suffix, (sizeof suffix) - 1);
4018  ut_sprintf_timestamp_without_extra_chars(
4019  path + len + ((sizeof suffix) - 1));
4020  return(path);
4021 }
4022 #endif /* UNIV_HOTBACKUP */
4023 
4024 /********************************************************************/
4028 static
4029 void
4030 fil_validate_single_table_tablespace(
4031 /*=================================*/
4032  const char* tablename,
4033  fsp_open_info* fsp)
4034 {
4035  if (const char* check_msg = fil_read_first_page(
4036  fsp->file, FALSE, &fsp->flags, &fsp->id,
4037 #ifdef UNIV_LOG_ARCHIVE
4038  &fsp->arch_log_no, &fsp->arch_log_no,
4039 #endif /* UNIV_LOG_ARCHIVE */
4040  &fsp->lsn, &fsp->lsn)) {
4041  ib_logf(IB_LOG_LEVEL_ERROR,
4042  "%s in tablespace %s (table %s)",
4043  check_msg, fsp->filepath, tablename);
4044  fsp->success = FALSE;
4045  return;
4046  }
4047 
4048  if (fsp->id == ULINT_UNDEFINED || fsp->id == 0) {
4049  ib_logf(IB_LOG_LEVEL_ERROR,
4050  "Tablespace is not sensible;"
4051  " Table: %s Space ID: %lu Filepath: %s\n",
4052  tablename, (ulong) fsp->id, fsp->filepath);
4053  fsp->success = FALSE;
4054  return;
4055  }
4056 
4057  mutex_enter(&fil_system->mutex);
4058  fil_space_t* space = fil_space_get_by_id(fsp->id);
4059  mutex_exit(&fil_system->mutex);
4060  if (space != NULL) {
4061  char* prev_filepath = fil_space_get_first_path(fsp->id);
4062 
4063  ib_logf(IB_LOG_LEVEL_ERROR,
4064  "Attempted to open a previously opened tablespace. "
4065  "Previous tablespace %s uses space ID: %lu at "
4066  "filepath: %s. Cannot open tablespace %s which uses "
4067  "space ID: %lu at filepath: %s",
4068  space->name, (ulong) space->id, prev_filepath,
4069  tablename, (ulong) fsp->id, fsp->filepath);
4070 
4071  mem_free(prev_filepath);
4072  fsp->success = FALSE;
4073  return;
4074  }
4075 
4076  fsp->success = TRUE;
4077 }
4078 
4079 
4080 /********************************************************************/
4083 static
4084 void
4085 fil_load_single_table_tablespace(
4086 /*=============================*/
4087  const char* dbname,
4088  const char* filename)
4090 {
4091  char* tablename;
4092  ulint tablename_len;
4093  ulint dbname_len = strlen(dbname);
4094  ulint filename_len = strlen(filename);
4095  fsp_open_info def;
4096  fsp_open_info remote;
4097  os_offset_t size;
4098 #ifdef UNIV_HOTBACKUP
4099  fil_space_t* space;
4100 #endif
4101 
4102  memset(&def, 0, sizeof(def));
4103  memset(&remote, 0, sizeof(remote));
4104 
4105  /* The caller assured that the extension is ".ibd" or ".isl". */
4106  ut_ad(0 == memcmp(filename + filename_len - 4, ".ibd", 4)
4107  || 0 == memcmp(filename + filename_len - 4, ".isl", 4));
4108 
4109  /* Build up the tablename in the standard form database/table. */
4110  tablename = static_cast<char*>(
4111  mem_alloc(dbname_len + filename_len + 2));
4112  sprintf(tablename, "%s/%s", dbname, filename);
4113  tablename_len = strlen(tablename) - strlen(".ibd");
4114  tablename[tablename_len] = '\0';
4115 
4116  /* There may be both .ibd and .isl file in the directory.
4117  And it is possible that the .isl file refers to a different
4118  .ibd file. If so, we open and compare them the first time
4119  one of them is sent to this function. So if this table has
4120  already been loaded, there is nothing to do.*/
4121  mutex_enter(&fil_system->mutex);
4122  if (fil_space_get_by_name(tablename)) {
4123  mem_free(tablename);
4124  mutex_exit(&fil_system->mutex);
4125  return;
4126  }
4127  mutex_exit(&fil_system->mutex);
4128 
4129  /* Build up the filepath of the .ibd tablespace in the datadir.
4130  This must be freed independent of def.success. */
4131  def.filepath = fil_make_ibd_name(tablename, false);
4132 
4133 #ifdef __WIN__
4134 # ifndef UNIV_HOTBACKUP
4135  /* If lower_case_table_names is 0 or 2, then MySQL allows database
4136  directory names with upper case letters. On Windows, all table and
4137  database names in InnoDB are internally always in lower case. Put the
4138  file path to lower case, so that we are consistent with InnoDB's
4139  internal data dictionary. */
4140 
4142 # endif /* !UNIV_HOTBACKUP */
4143 #endif
4144 
4145  /* Check for a link file which locates a remote tablespace. */
4146  remote.success = fil_open_linked_file(
4147  tablename, &remote.filepath, &remote.file);
4148 
4149  /* Read the first page of the remote tablespace */
4150  if (remote.success) {
4151  fil_validate_single_table_tablespace(tablename, &remote);
4152  if (!remote.success) {
4153  os_file_close(remote.file);
4154  mem_free(remote.filepath);
4155  }
4156  }
4157 
4158 
4159  /* Try to open the tablespace in the datadir. */
4160  def.file = os_file_create_simple_no_error_handling(
4161  innodb_file_data_key, def.filepath, OS_FILE_OPEN,
4162  OS_FILE_READ_ONLY, &def.success);
4163 
4164  /* Read the first page of the remote tablespace */
4165  if (def.success) {
4166  fil_validate_single_table_tablespace(tablename, &def);
4167  if (!def.success) {
4168  os_file_close(def.file);
4169  }
4170  }
4171 
4172  if (!def.success && !remote.success) {
4173  /* The following call prints an error message */
4174  os_file_get_last_error(true);
4175  fprintf(stderr,
4176  "InnoDB: Error: could not open single-table"
4177  " tablespace file %s\n", def.filepath);
4178 
4179  if (!strncmp(filename,
4180  tmp_file_prefix, tmp_file_prefix_length)) {
4181  /* Ignore errors for #sql tablespaces. */
4182  mem_free(tablename);
4183  if (remote.filepath) {
4184  mem_free(remote.filepath);
4185  }
4186  if (def.filepath) {
4187  mem_free(def.filepath);
4188  }
4189  return;
4190  }
4191 no_good_file:
4192  fprintf(stderr,
4193  "InnoDB: We do not continue the crash recovery,"
4194  " because the table may become\n"
4195  "InnoDB: corrupt if we cannot apply the log"
4196  " records in the InnoDB log to it.\n"
4197  "InnoDB: To fix the problem and start mysqld:\n"
4198  "InnoDB: 1) If there is a permission problem"
4199  " in the file and mysqld cannot\n"
4200  "InnoDB: open the file, you should"
4201  " modify the permissions.\n"
4202  "InnoDB: 2) If the table is not needed, or you"
4203  " can restore it from a backup,\n"
4204  "InnoDB: then you can remove the .ibd file,"
4205  " and InnoDB will do a normal\n"
4206  "InnoDB: crash recovery and ignore that table.\n"
4207  "InnoDB: 3) If the file system or the"
4208  " disk is broken, and you cannot remove\n"
4209  "InnoDB: the .ibd file, you can set"
4210  " innodb_force_recovery > 0 in my.cnf\n"
4211  "InnoDB: and force InnoDB to continue crash"
4212  " recovery here.\n");
4213 will_not_choose:
4214  mem_free(tablename);
4215  if (remote.filepath) {
4216  mem_free(remote.filepath);
4217  }
4218  if (def.filepath) {
4219  mem_free(def.filepath);
4220  }
4221 
4222  if (srv_force_recovery > 0) {
4223  ib_logf(IB_LOG_LEVEL_INFO,
4224  "innodb_force_recovery was set to %lu. "
4225  "Continuing crash recovery even though we "
4226  "cannot access the .ibd file of this table.",
4228  return;
4229  }
4230 
4231  exit(1);
4232  }
4233 
4234  if (def.success && remote.success) {
4235  ib_logf(IB_LOG_LEVEL_ERROR,
4236  "Tablespaces for %s have been found in two places;\n"
4237  "Location 1: SpaceID: %lu LSN: %lu File: %s\n"
4238  "Location 2: SpaceID: %lu LSN: %lu File: %s\n"
4239  "You must delete one of them.",
4240  tablename, (ulong) def.id, (ulong) def.lsn,
4241  def.filepath, (ulong) remote.id, (ulong) remote.lsn,
4242  remote.filepath);
4243 
4244  def.success = FALSE;
4245  os_file_close(def.file);
4246  os_file_close(remote.file);
4247  goto will_not_choose;
4248  }
4249 
4250  /* At this point, only one tablespace is open */
4251  ut_a(def.success == !remote.success);
4252 
4253  fsp_open_info* fsp = def.success ? &def : &remote;
4254 
4255  /* Get and test the file size. */
4256  size = os_file_get_size(fsp->file);
4257 
4258  if (size == (os_offset_t) -1) {
4259  /* The following call prints an error message */
4260  os_file_get_last_error(true);
4261 
4262  ib_logf(IB_LOG_LEVEL_ERROR,
4263  "could not measure the size of single-table "
4264  "tablespace file %s", fsp->filepath);
4265 
4266  os_file_close(fsp->file);
4267  goto no_good_file;
4268  }
4269 
4270  /* Every .ibd file is created >= 4 pages in size. Smaller files
4271  cannot be ok. */
4272  ulong minimum_size = FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE;
4273  if (size < minimum_size) {
4274 #ifndef UNIV_HOTBACKUP
4275  ib_logf(IB_LOG_LEVEL_ERROR,
4276  "The size of single-table tablespace file %s "
4277  "is only " UINT64PF ", should be at least %lu!",
4278  fsp->filepath, size, minimum_size);
4279  os_file_close(fsp->file);
4280  goto no_good_file;
4281 #else
4282  fsp->id = ULINT_UNDEFINED;
4283  fsp->flags = 0;
4284 #endif /* !UNIV_HOTBACKUP */
4285  }
4286 
4287 #ifdef UNIV_HOTBACKUP
4288  if (fsp->id == ULINT_UNDEFINED || fsp->id == 0) {
4289  char* new_path;
4290 
4291  fprintf(stderr,
4292  "InnoDB: Renaming tablespace %s of id %lu,\n"
4293  "InnoDB: to %s_ibbackup_old_vers_<timestamp>\n"
4294  "InnoDB: because its size %" PRId64 " is too small"
4295  " (< 4 pages 16 kB each),\n"
4296  "InnoDB: or the space id in the file header"
4297  " is not sensible.\n"
4298  "InnoDB: This can happen in an ibbackup run,"
4299  " and is not dangerous.\n",
4300  fsp->filepath, fsp->id, fsp->filepath, size);
4301  os_file_close(fsp->file);
4302 
4303  new_path = fil_make_ibbackup_old_name(fsp->filepath);
4304 
4305  bool success = os_file_rename(
4306  innodb_file_data_key, fsp->filepath, new_path);
4307 
4308  ut_a(success);
4309 
4310  mem_free(new_path);
4311 
4312  goto func_exit_after_close;
4313  }
4314 
4315  /* A backup may contain the same space several times, if the space got
4316  renamed at a sensitive time. Since it is enough to have one version of
4317  the space, we rename the file if a space with the same space id
4318  already exists in the tablespace memory cache. We rather rename the
4319  file than delete it, because if there is a bug, we do not want to
4320  destroy valuable data. */
4321 
4322  mutex_enter(&fil_system->mutex);
4323 
4324  space = fil_space_get_by_id(fsp->id);
4325 
4326  if (space) {
4327  char* new_path;
4328 
4329  fprintf(stderr,
4330  "InnoDB: Renaming tablespace %s of id %lu,\n"
4331  "InnoDB: to %s_ibbackup_old_vers_<timestamp>\n"
4332  "InnoDB: because space %s with the same id\n"
4333  "InnoDB: was scanned earlier. This can happen"
4334  " if you have renamed tables\n"
4335  "InnoDB: during an ibbackup run.\n",
4336  fsp->filepath, fsp->id, fsp->filepath,
4337  space->name);
4338  os_file_close(fsp->file);
4339 
4340  new_path = fil_make_ibbackup_old_name(fsp->filepath);
4341 
4342  mutex_exit(&fil_system->mutex);
4343 
4344  bool success = os_file_rename(
4345  innodb_file_data_key, fsp->filepath, new_path);
4346 
4347  ut_a(success);
4348 
4349  mem_free(new_path);
4350 
4351  goto func_exit_after_close;
4352  }
4353  mutex_exit(&fil_system->mutex);
4354 #endif /* UNIV_HOTBACKUP */
4355  ibool file_space_create_success = fil_space_create(
4356  tablename, fsp->id, fsp->flags, FIL_TABLESPACE);
4357 
4358  if (!file_space_create_success) {
4359  if (srv_force_recovery > 0) {
4360  fprintf(stderr,
4361  "InnoDB: innodb_force_recovery was set"
4362  " to %lu. Continuing crash recovery\n"
4363  "InnoDB: even though the tablespace"
4364  " creation of this table failed.\n",
4366  goto func_exit;
4367  }
4368 
4369  /* Exit here with a core dump, stack, etc. */
4370  ut_a(file_space_create_success);
4371  }
4372 
4373  /* We do not use the size information we have about the file, because
4374  the rounding formula for extents and pages is somewhat complex; we
4375  let fil_node_open() do that task. */
4376 
4377  if (!fil_node_create(fsp->filepath, 0, fsp->id, FALSE)) {
4378  ut_error;
4379  }
4380 
4381 func_exit:
4382  os_file_close(fsp->file);
4383 
4384 #ifdef UNIV_HOTBACKUP
4385 func_exit_after_close:
4386 #else
4387  ut_ad(!mutex_own(&fil_system->mutex));
4388 #endif
4389  mem_free(tablename);
4390  if (remote.success) {
4391  mem_free(remote.filepath);
4392  }
4393  mem_free(def.filepath);
4394 }
4395 
4396 /***********************************************************************/
4402 static
4403 int
4404 fil_file_readdir_next_file(
4405 /*=======================*/
4406  dberr_t* err,
4408  const char* dirname,
4409  os_file_dir_t dir,
4410  os_file_stat_t* info)
4412 {
4413  for (ulint i = 0; i < 100; i++) {
4414  int ret = os_file_readdir_next_file(dirname, dir, info);
4415 
4416  if (ret != -1) {
4417 
4418  return(ret);
4419  }
4420 
4421  ib_logf(IB_LOG_LEVEL_ERROR,
4422  "os_file_readdir_next_file() returned -1 in "
4423  "directory %s, crash recovery may have failed "
4424  "for some .ibd files!", dirname);
4425 
4426  *err = DB_ERROR;
4427  }
4428 
4429  return(-1);
4430 }
4431 
4432 /********************************************************************/
4440 UNIV_INTERN
4441 dberr_t
4443 /*===================================*/
4444 {
4445  int ret;
4446  char* dbpath = NULL;
4447  ulint dbpath_len = 100;
4448  os_file_dir_t dir;
4449  os_file_dir_t dbdir;
4450  os_file_stat_t dbinfo;
4452  dberr_t err = DB_SUCCESS;
4453 
4454  /* The datadir of MySQL is always the default directory of mysqld */
4455 
4457 
4458  if (dir == NULL) {
4459 
4460  return(DB_ERROR);
4461  }
4462 
4463  dbpath = static_cast<char*>(mem_alloc(dbpath_len));
4464 
4465  /* Scan all directories under the datadir. They are the database
4466  directories of MySQL. */
4467 
4468  ret = fil_file_readdir_next_file(&err, fil_path_to_mysql_datadir, dir,
4469  &dbinfo);
4470  while (ret == 0) {
4471  ulint len;
4472  /* printf("Looking at %s in datadir\n", dbinfo.name); */
4473 
4474  if (dbinfo.type == OS_FILE_TYPE_FILE
4475  || dbinfo.type == OS_FILE_TYPE_UNKNOWN) {
4476 
4477  goto next_datadir_item;
4478  }
4479 
4480  /* We found a symlink or a directory; try opening it to see
4481  if a symlink is a directory */
4482 
4483  len = strlen(fil_path_to_mysql_datadir)
4484  + strlen (dbinfo.name) + 2;
4485  if (len > dbpath_len) {
4486  dbpath_len = len;
4487 
4488  if (dbpath) {
4489  mem_free(dbpath);
4490  }
4491 
4492  dbpath = static_cast<char*>(mem_alloc(dbpath_len));
4493  }
4494  ut_snprintf(dbpath, dbpath_len,
4495  "%s/%s", fil_path_to_mysql_datadir, dbinfo.name);
4497 
4498  dbdir = os_file_opendir(dbpath, FALSE);
4499 
4500  if (dbdir != NULL) {
4501 
4502  /* We found a database directory; loop through it,
4503  looking for possible .ibd files in it */
4504 
4505  ret = fil_file_readdir_next_file(&err, dbpath, dbdir,
4506  &fileinfo);
4507  while (ret == 0) {
4508 
4509  if (fileinfo.type == OS_FILE_TYPE_DIR) {
4510 
4511  goto next_file_item;
4512  }
4513 
4514  /* We found a symlink or a file */
4515  if (strlen(fileinfo.name) > 4
4516  && (0 == strcmp(fileinfo.name
4517  + strlen(fileinfo.name) - 4,
4518  ".ibd")
4519  || 0 == strcmp(fileinfo.name
4520  + strlen(fileinfo.name) - 4,
4521  ".isl"))) {
4522  /* The name ends in .ibd or .isl;
4523  try opening the file */
4524  fil_load_single_table_tablespace(
4525  dbinfo.name, fileinfo.name);
4526  }
4527 next_file_item:
4528  ret = fil_file_readdir_next_file(&err,
4529  dbpath, dbdir,
4530  &fileinfo);
4531  }
4532 
4533  if (0 != os_file_closedir(dbdir)) {
4534  fputs("InnoDB: Warning: could not"
4535  " close database directory ", stderr);
4536  ut_print_filename(stderr, dbpath);
4537  putc('\n', stderr);
4538 
4539  err = DB_ERROR;
4540  }
4541  }
4542 
4543 next_datadir_item:
4544  ret = fil_file_readdir_next_file(&err,
4546  dir, &dbinfo);
4547  }
4548 
4549  mem_free(dbpath);
4550 
4551  if (0 != os_file_closedir(dir)) {
4552  fprintf(stderr,
4553  "InnoDB: Error: could not close MySQL datadir\n");
4554 
4555  return(DB_ERROR);
4556  }
4557 
4558  return(err);
4559 }
4560 
4561 /*******************************************************************/
4565 UNIV_INTERN
4566 ibool
4568 /*===========================================*/
4569  ulint id,
4570  ib_int64_t version)
4573 {
4574  fil_space_t* space;
4575 
4576  ut_ad(fil_system);
4577 
4578  mutex_enter(&fil_system->mutex);
4579 
4580  space = fil_space_get_by_id(id);
4581 
4582  if (space == NULL || space->stop_new_ops) {
4583  mutex_exit(&fil_system->mutex);
4584 
4585  return(TRUE);
4586  }
4587 
4588  if (version != ((ib_int64_t)-1)
4589  && space->tablespace_version != version) {
4590  mutex_exit(&fil_system->mutex);
4591 
4592  return(TRUE);
4593  }
4594 
4595  mutex_exit(&fil_system->mutex);
4596 
4597  return(FALSE);
4598 }
4599 
4600 /*******************************************************************/
4603 UNIV_INTERN
4604 ibool
4606 /*=========================*/
4607  ulint id)
4608 {
4609  fil_space_t* space;
4610 
4611  ut_ad(fil_system);
4612 
4613  mutex_enter(&fil_system->mutex);
4614 
4615  space = fil_space_get_by_id(id);
4616 
4617  mutex_exit(&fil_system->mutex);
4618 
4619  return(space != NULL);
4620 }
4621 
4622 /*******************************************************************/
4624 static
4625 void
4626 fil_report_missing_tablespace(
4627 /*===========================*/
4628  const char* name,
4629  ulint space_id)
4630 {
4631  char index_name[MAX_FULL_NAME_LEN + 1];
4632 
4633  innobase_format_name(index_name, sizeof(index_name), name, TRUE);
4634 
4635  ib_logf(IB_LOG_LEVEL_ERROR,
4636  "Table %s in the InnoDB data dictionary has tablespace id %lu, "
4637  "but tablespace with that id or name does not exist. Have "
4638  "you deleted or moved .ibd files? This may also be a table "
4639  "created with CREATE TEMPORARY TABLE whose .ibd and .frm "
4640  "files MySQL automatically removed, but the table still "
4641  "exists in the InnoDB internal data dictionary.",
4642  name, space_id);
4643 }
4644 
4645 /*******************************************************************/
4650 UNIV_INTERN
4651 ibool
4653 /*==============================*/
4654  ulint id,
4655  const char* name,
4659  ibool mark_space,
4665  ibool print_error_if_does_not_exist,
4670  bool adjust_space,
4672  mem_heap_t* heap,
4673  table_id_t table_id)
4674 {
4675  fil_space_t* fnamespace;
4676  fil_space_t* space;
4677 
4678  ut_ad(fil_system);
4679 
4680  mutex_enter(&fil_system->mutex);
4681 
4682  /* Look if there is a space with the same id */
4683 
4684  space = fil_space_get_by_id(id);
4685 
4686  /* Look if there is a space with the same name; the name is the
4687  directory path from the datadir to the file */
4688 
4689  fnamespace = fil_space_get_by_name(name);
4690  if (space && space == fnamespace) {
4691  /* Found */
4692 
4693  if (mark_space) {
4694  space->mark = TRUE;
4695  }
4696 
4697  mutex_exit(&fil_system->mutex);
4698 
4699  return(TRUE);
4700  }
4701 
4702  /* Info from "fnamespace" comes from the ibd file itself, it can
4703  be different from data obtained from System tables since it is
4704  not transactional. If adjust_space is set, and the mismatching
4705  space are between a user table and its temp table, we shall
4706  adjust the ibd file name according to system table info */
4707  if (adjust_space
4708  && space != NULL
4710  && !row_is_mysql_tmp_table_name(name)) {
4711 
4712  mutex_exit(&fil_system->mutex);
4713 
4714  DBUG_EXECUTE_IF("ib_crash_before_adjust_fil_space",
4715  DBUG_SUICIDE(););
4716 
4717  if (fnamespace) {
4718  char* tmp_name;
4719 
4720  tmp_name = dict_mem_create_temporary_tablename(
4721  heap, name, table_id);
4722 
4723  fil_rename_tablespace(fnamespace->name, fnamespace->id,
4724  tmp_name, NULL);
4725  }
4726 
4727  DBUG_EXECUTE_IF("ib_crash_after_adjust_one_fil_space",
4728  DBUG_SUICIDE(););
4729 
4730  fil_rename_tablespace(space->name, id, name, NULL);
4731 
4732  DBUG_EXECUTE_IF("ib_crash_after_adjust_fil_space",
4733  DBUG_SUICIDE(););
4734 
4735  mutex_enter(&fil_system->mutex);
4736  fnamespace = fil_space_get_by_name(name);
4737  ut_ad(space == fnamespace);
4738  mutex_exit(&fil_system->mutex);
4739 
4740  return(TRUE);
4741  }
4742 
4743  if (!print_error_if_does_not_exist) {
4744 
4745  mutex_exit(&fil_system->mutex);
4746 
4747  return(FALSE);
4748  }
4749 
4750  if (space == NULL) {
4751  if (fnamespace == NULL) {
4752  if (print_error_if_does_not_exist) {
4753  fil_report_missing_tablespace(name, id);
4754  }
4755  } else {
4756  ut_print_timestamp(stderr);
4757  fputs(" InnoDB: Error: table ", stderr);
4758  ut_print_filename(stderr, name);
4759  fprintf(stderr, "\n"
4760  "InnoDB: in InnoDB data dictionary has"
4761  " tablespace id %lu,\n"
4762  "InnoDB: but a tablespace with that id"
4763  " does not exist. There is\n"
4764  "InnoDB: a tablespace of name %s and id %lu,"
4765  " though. Have\n"
4766  "InnoDB: you deleted or moved .ibd files?\n",
4767  (ulong) id, fnamespace->name,
4768  (ulong) fnamespace->id);
4769  }
4770 error_exit:
4771  fputs("InnoDB: Please refer to\n"
4772  "InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n"
4773  "InnoDB: for how to resolve the issue.\n", stderr);
4774 
4775  mutex_exit(&fil_system->mutex);
4776 
4777  return(FALSE);
4778  }
4779 
4780  if (0 != strcmp(space->name, name)) {
4781  ut_print_timestamp(stderr);
4782  fputs(" InnoDB: Error: table ", stderr);
4783  ut_print_filename(stderr, name);
4784  fprintf(stderr, "\n"
4785  "InnoDB: in InnoDB data dictionary has"
4786  " tablespace id %lu,\n"
4787  "InnoDB: but the tablespace with that id"
4788  " has name %s.\n"
4789  "InnoDB: Have you deleted or moved .ibd files?\n",
4790  (ulong) id, space->name);
4791 
4792  if (fnamespace != NULL) {
4793  fputs("InnoDB: There is a tablespace"
4794  " with the right name\n"
4795  "InnoDB: ", stderr);
4796  ut_print_filename(stderr, fnamespace->name);
4797  fprintf(stderr, ", but its id is %lu.\n",
4798  (ulong) fnamespace->id);
4799  }
4800 
4801  goto error_exit;
4802  }
4803 
4804  mutex_exit(&fil_system->mutex);
4805 
4806  return(FALSE);
4807 }
4808 
4809 /*******************************************************************/
4813 UNIV_INTERN
4814 ulint
4816 /*=======================*/
4817  const char* tablename)
4819 {
4820  fil_space_t* fnamespace;
4821  ulint id = ULINT_UNDEFINED;
4822 
4823  ut_ad(fil_system);
4824 
4825  mutex_enter(&fil_system->mutex);
4826 
4827  /* Look if there is a space with the same name. */
4828 
4829  fnamespace = fil_space_get_by_name(tablename);
4830 
4831  if (fnamespace) {
4832  id = fnamespace->id;
4833  }
4834 
4835  mutex_exit(&fil_system->mutex);
4836 
4837  return(id);
4838 }
4839 
4840 /**********************************************************************/
4845 UNIV_INTERN
4846 ibool
4848 /*=============================*/
4849  ulint* actual_size,
4852  ulint space_id,
4853  ulint size_after_extend)
4856 {
4857  fil_node_t* node;
4858  fil_space_t* space;
4859  byte* buf2;
4860  byte* buf;
4861  ulint buf_size;
4862  ulint start_page_no;
4863  ulint file_start_page_no;
4864  ulint page_size;
4865  ulint pages_added;
4866  ibool success;
4867 
4869 
4870 retry:
4871  pages_added = 0;
4872  success = TRUE;
4873 
4874  fil_mutex_enter_and_prepare_for_io(space_id);
4875 
4876  space = fil_space_get_by_id(space_id);
4877  ut_a(space);
4878 
4879  if (space->size >= size_after_extend) {
4880  /* Space already big enough */
4881 
4882  *actual_size = space->size;
4883 
4884  mutex_exit(&fil_system->mutex);
4885 
4886  return(TRUE);
4887  }
4888 
4889  page_size = fsp_flags_get_zip_size(space->flags);
4890  if (!page_size) {
4891  page_size = UNIV_PAGE_SIZE;
4892  }
4893 
4894  node = UT_LIST_GET_LAST(space->chain);
4895 
4896  if (!node->being_extended) {
4897  /* Mark this node as undergoing extension. This flag
4898  is used by other threads to wait for the extension
4899  opereation to finish. */
4900  node->being_extended = TRUE;
4901  } else {
4902  /* Another thread is currently extending the file. Wait
4903  for it to finish.
4904  It'd have been better to use event driven mechanism but
4905  the entire module is peppered with polling stuff. */
4906  mutex_exit(&fil_system->mutex);
4907  os_thread_sleep(100000);
4908  goto retry;
4909  }
4910 
4911  if (!fil_node_prepare_for_io(node, fil_system, space)) {
4912  /* The tablespace data file, such as .ibd file, is missing */
4913  node->being_extended = false;
4914  mutex_exit(&fil_system->mutex);
4915 
4916  return(false);
4917  }
4918 
4919  /* At this point it is safe to release fil_system mutex. No
4920  other thread can rename, delete or close the file because
4921  we have set the node->being_extended flag. */
4922  mutex_exit(&fil_system->mutex);
4923 
4924  start_page_no = space->size;
4925  file_start_page_no = space->size - node->size;
4926 
4927  /* Extend at most 64 pages at a time */
4928  buf_size = ut_min(64, size_after_extend - start_page_no) * page_size;
4929  buf2 = static_cast<byte*>(mem_alloc(buf_size + page_size));
4930  buf = static_cast<byte*>(ut_align(buf2, page_size));
4931 
4932  memset(buf, 0, buf_size);
4933 
4934  while (start_page_no < size_after_extend) {
4935  ulint n_pages
4936  = ut_min(buf_size / page_size,
4937  size_after_extend - start_page_no);
4938 
4940  = ((os_offset_t) (start_page_no - file_start_page_no))
4941  * page_size;
4942 #ifdef UNIV_HOTBACKUP
4943  success = os_file_write(node->name, node->handle, buf,
4944  offset, page_size * n_pages);
4945 #else
4946  success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC,
4947  node->name, node->handle, buf,
4948  offset, page_size * n_pages,
4949  NULL, NULL);
4950 #endif /* UNIV_HOTBACKUP */
4951  if (success) {
4952  os_has_said_disk_full = FALSE;
4953  } else {
4954  /* Let us measure the size of the file to determine
4955  how much we were able to extend it */
4956  os_offset_t size;
4957 
4958  size = os_file_get_size(node->handle);
4959  ut_a(size != (os_offset_t) -1);
4960 
4961  n_pages = ((ulint) (size / page_size))
4962  - node->size - pages_added;
4963 
4964  pages_added += n_pages;
4965  break;
4966  }
4967 
4968  start_page_no += n_pages;
4969  pages_added += n_pages;
4970  }
4971 
4972  mem_free(buf2);
4973 
4974  mutex_enter(&fil_system->mutex);
4975 
4976  ut_a(node->being_extended);
4977 
4978  space->size += pages_added;
4979  node->size += pages_added;
4980  node->being_extended = FALSE;
4981 
4982  fil_node_complete_io(node, fil_system, OS_FILE_WRITE);
4983 
4984  *actual_size = space->size;
4985 
4986 #ifndef UNIV_HOTBACKUP
4987  if (space_id == 0) {
4988  ulint pages_per_mb = (1024 * 1024) / page_size;
4989 
4990  /* Keep the last data file size info up to date, rounded to
4991  full megabytes */
4992 
4993  srv_data_file_sizes[srv_n_data_files - 1]
4994  = (node->size / pages_per_mb) * pages_per_mb;
4995  }
4996 #endif /* !UNIV_HOTBACKUP */
4997 
4998  /*
4999  printf("Extended %s to %lu, actual size %lu pages\n", space->name,
5000  size_after_extend, *actual_size); */
5001  mutex_exit(&fil_system->mutex);
5002 
5003  fil_flush(space_id);
5004 
5005  return(success);
5006 }
5007 
5008 #ifdef UNIV_HOTBACKUP
5009 /********************************************************************/
5014 UNIV_INTERN
5015 void
5016 fil_extend_tablespaces_to_stored_len(void)
5017 /*======================================*/
5018 {
5019  fil_space_t* space;
5020  byte* buf;
5021  ulint actual_size;
5022  ulint size_in_header;
5023  dberr_t error;
5024  ibool success;
5025 
5026  buf = mem_alloc(UNIV_PAGE_SIZE);
5027 
5028  mutex_enter(&fil_system->mutex);
5029 
5030  space = UT_LIST_GET_FIRST(fil_system->space_list);
5031 
5032  while (space) {
5033  ut_a(space->purpose == FIL_TABLESPACE);
5034 
5035  mutex_exit(&fil_system->mutex); /* no need to protect with a
5036  mutex, because this is a
5037  single-threaded operation */
5038  error = fil_read(TRUE, space->id,
5039  fsp_flags_get_zip_size(space->flags),
5040  0, 0, UNIV_PAGE_SIZE, buf, NULL);
5041  ut_a(error == DB_SUCCESS);
5042 
5043  size_in_header = fsp_get_size_low(buf);
5044 
5046  &actual_size, space->id, size_in_header);
5047  if (!success) {
5048  fprintf(stderr,
5049  "InnoDB: Error: could not extend the"
5050  " tablespace of %s\n"
5051  "InnoDB: to the size stored in header,"
5052  " %lu pages;\n"
5053  "InnoDB: size after extension %lu pages\n"
5054  "InnoDB: Check that you have free disk space"
5055  " and retry!\n",
5056  space->name, size_in_header, actual_size);
5057  ut_a(success);
5058  }
5059 
5060  mutex_enter(&fil_system->mutex);
5061 
5062  space = UT_LIST_GET_NEXT(space_list, space);
5063  }
5064 
5065  mutex_exit(&fil_system->mutex);
5066 
5067  mem_free(buf);
5068 }
5069 #endif
5070 
5071 /*========== RESERVE FREE EXTENTS (for a B-tree split, for example) ===*/
5072 
5073 /*******************************************************************/
5076 UNIV_INTERN
5077 ibool
5079 /*===========================*/
5080  ulint id,
5081  ulint n_free_now,
5082  ulint n_to_reserve)
5083 {
5084  fil_space_t* space;
5085  ibool success;
5086 
5087  ut_ad(fil_system);
5088 
5089  mutex_enter(&fil_system->mutex);
5090 
5091  space = fil_space_get_by_id(id);
5092 
5093  ut_a(space);
5094 
5095  if (space->n_reserved_extents + n_to_reserve > n_free_now) {
5096  success = FALSE;
5097  } else {
5098  space->n_reserved_extents += n_to_reserve;
5099  success = TRUE;
5100  }
5101 
5102  mutex_exit(&fil_system->mutex);
5103 
5104  return(success);
5105 }
5106 
5107 /*******************************************************************/
5109 UNIV_INTERN
5110 void
5112 /*===========================*/
5113  ulint id,
5114  ulint n_reserved)
5115 {
5116  fil_space_t* space;
5117 
5118  ut_ad(fil_system);
5119 
5120  mutex_enter(&fil_system->mutex);
5121 
5122  space = fil_space_get_by_id(id);
5123 
5124  ut_a(space);
5125  ut_a(space->n_reserved_extents >= n_reserved);
5126 
5127  space->n_reserved_extents -= n_reserved;
5128 
5129  mutex_exit(&fil_system->mutex);
5130 }
5131 
5132 /*******************************************************************/
5135 UNIV_INTERN
5136 ulint
5138 /*=============================*/
5139  ulint id)
5140 {
5141  fil_space_t* space;
5142  ulint n;
5143 
5144  ut_ad(fil_system);
5145 
5146  mutex_enter(&fil_system->mutex);
5147 
5148  space = fil_space_get_by_id(id);
5149 
5150  ut_a(space);
5151 
5152  n = space->n_reserved_extents;
5153 
5154  mutex_exit(&fil_system->mutex);
5155 
5156  return(n);
5157 }
5158 
5159 /*============================ FILE I/O ================================*/
5160 
5161 /********************************************************************/
5169 static
5170 bool
5171 fil_node_prepare_for_io(
5172 /*====================*/
5173  fil_node_t* node,
5174  fil_system_t* system,
5175  fil_space_t* space)
5176 {
5177  ut_ad(node && system && space);
5178  ut_ad(mutex_own(&(system->mutex)));
5179 
5180  if (system->n_open > system->max_n_open + 5) {
5181  ut_print_timestamp(stderr);
5182  fprintf(stderr,
5183  " InnoDB: Warning: open files %lu"
5184  " exceeds the limit %lu\n",
5185  (ulong) system->n_open,
5186  (ulong) system->max_n_open);
5187  }
5188 
5189  if (node->open == FALSE) {
5190  /* File is closed: open it */
5191  ut_a(node->n_pending == 0);
5192 
5193  if (!fil_node_open_file(node, system, space)) {
5194  return(false);
5195  }
5196  }
5197 
5198  if (node->n_pending == 0 && fil_space_belongs_in_lru(space)) {
5199  /* The node is in the LRU list, remove it */
5200 
5201  ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
5202 
5203  UT_LIST_REMOVE(LRU, system->LRU, node);
5204  }
5205 
5206  node->n_pending++;
5207 
5208  return(true);
5209 }
5210 
5211 /********************************************************************/
5214 static
5215 void
5216 fil_node_complete_io(
5217 /*=================*/
5218  fil_node_t* node,
5219  fil_system_t* system,
5220  ulint type)
5223 {
5224  ut_ad(node);
5225  ut_ad(system);
5226  ut_ad(mutex_own(&(system->mutex)));
5227 
5228  ut_a(node->n_pending > 0);
5229 
5230  node->n_pending--;
5231 
5232  if (type == OS_FILE_WRITE) {
5234  system->modification_counter++;
5236 
5237  if (fil_buffering_disabled(node->space)) {
5238 
5239  /* We don't need to keep track of unflushed
5240  changes as user has explicitly disabled
5241  buffering. */
5243  node->flush_counter = node->modification_counter;
5244 
5245  } else if (!node->space->is_in_unflushed_spaces) {
5246 
5247  node->space->is_in_unflushed_spaces = true;
5248  UT_LIST_ADD_FIRST(unflushed_spaces,
5249  system->unflushed_spaces,
5250  node->space);
5251  }
5252  }
5253 
5254  if (node->n_pending == 0 && fil_space_belongs_in_lru(node->space)) {
5255 
5256  /* The node must be put back to the LRU list */
5257  UT_LIST_ADD_FIRST(LRU, system->LRU, node);
5258  }
5259 }
5260 
5261 /********************************************************************/
5263 static
5264 void
5265 fil_report_invalid_page_access(
5266 /*===========================*/
5267  ulint block_offset,
5268  ulint space_id,
5269  const char* space_name,
5270  ulint byte_offset,
5271  ulint len,
5272  ulint type)
5273 {
5274  fprintf(stderr,
5275  "InnoDB: Error: trying to access page number %lu"
5276  " in space %lu,\n"
5277  "InnoDB: space name %s,\n"
5278  "InnoDB: which is outside the tablespace bounds.\n"
5279  "InnoDB: Byte offset %lu, len %lu, i/o type %lu.\n"
5280  "InnoDB: If you get this error at mysqld startup,"
5281  " please check that\n"
5282  "InnoDB: your my.cnf matches the ibdata files"
5283  " that you have in the\n"
5284  "InnoDB: MySQL server.\n",
5285  (ulong) block_offset, (ulong) space_id, space_name,
5286  (ulong) byte_offset, (ulong) len, (ulong) type);
5287 }
5288 
5289 /********************************************************************/
5293 UNIV_INTERN
5294 dberr_t
5296 /*===*/
5297  ulint type,
5306  bool sync,
5307  ulint space_id,
5308  ulint zip_size,
5310  ulint block_offset,
5311  ulint byte_offset,
5314  ulint len,
5317  void* buf,
5320  void* message)
5322 {
5323  ulint mode;
5324  fil_space_t* space;
5325  fil_node_t* node;
5326  ibool ret;
5327  ulint is_log;
5328  ulint wake_later;
5330  ibool ignore_nonexistent_pages;
5331 
5332  is_log = type & OS_FILE_LOG;
5333  type = type & ~OS_FILE_LOG;
5334 
5335  wake_later = type & OS_AIO_SIMULATED_WAKE_LATER;
5336  type = type & ~OS_AIO_SIMULATED_WAKE_LATER;
5337 
5338  ignore_nonexistent_pages = type & BUF_READ_IGNORE_NONEXISTENT_PAGES;
5339  type &= ~BUF_READ_IGNORE_NONEXISTENT_PAGES;
5340 
5341  ut_ad(byte_offset < UNIV_PAGE_SIZE);
5342  ut_ad(!zip_size || !byte_offset);
5343  ut_ad(ut_is_2pow(zip_size));
5344  ut_ad(buf);
5345  ut_ad(len > 0);
5346  ut_ad(UNIV_PAGE_SIZE == (ulong)(1 << UNIV_PAGE_SIZE_SHIFT));
5347 #if (1 << UNIV_PAGE_SIZE_SHIFT_MAX) != UNIV_PAGE_SIZE_MAX
5348 # error "(1 << UNIV_PAGE_SIZE_SHIFT_MAX) != UNIV_PAGE_SIZE_MAX"
5349 #endif
5350 #if (1 << UNIV_PAGE_SIZE_SHIFT_MIN) != UNIV_PAGE_SIZE_MIN
5351 # error "(1 << UNIV_PAGE_SIZE_SHIFT_MIN) != UNIV_PAGE_SIZE_MIN"
5352 #endif
5353  ut_ad(fil_validate_skip());
5354 #ifndef UNIV_HOTBACKUP
5355 # ifndef UNIV_LOG_DEBUG
5356  /* ibuf bitmap pages must be read in the sync aio mode: */
5358  || type == OS_FILE_WRITE
5359  || !ibuf_bitmap_page(zip_size, block_offset)
5360  || sync
5361  || is_log);
5362 # endif /* UNIV_LOG_DEBUG */
5363  if (sync) {
5364  mode = OS_AIO_SYNC;
5365  } else if (is_log) {
5366  mode = OS_AIO_LOG;
5367  } else if (type == OS_FILE_READ
5369  && ibuf_page(space_id, zip_size, block_offset, NULL)) {
5370  mode = OS_AIO_IBUF;
5371  } else {
5372  mode = OS_AIO_NORMAL;
5373  }
5374 #else /* !UNIV_HOTBACKUP */
5375  ut_a(sync);
5376  mode = OS_AIO_SYNC;
5377 #endif /* !UNIV_HOTBACKUP */
5378 
5379  if (type == OS_FILE_READ) {
5380  srv_stats.data_read.add(len);
5381  } else if (type == OS_FILE_WRITE) {
5383  srv_stats.data_written.add(len);
5384  }
5385 
5386  /* Reserve the fil_system mutex and make sure that we can open at
5387  least one file while holding it, if the file is not already open */
5388 
5389  fil_mutex_enter_and_prepare_for_io(space_id);
5390 
5391  space = fil_space_get_by_id(space_id);
5392 
5393  /* If we are deleting a tablespace we don't allow any read
5394  operations on that. However, we do allow write operations. */
5395  if (space == 0 || (type == OS_FILE_READ && space->stop_new_ops)) {
5396  mutex_exit(&fil_system->mutex);
5397 
5398  ib_logf(IB_LOG_LEVEL_ERROR,
5399  "Trying to do i/o to a tablespace which does "
5400  "not exist. i/o type %lu, space id %lu, "
5401  "page no. %lu, i/o length %lu bytes",
5402  (ulong) type, (ulong) space_id, (ulong) block_offset,
5403  (ulong) len);
5404 
5405  return(DB_TABLESPACE_DELETED);
5406  }
5407 
5408  ut_ad(mode != OS_AIO_IBUF || space->purpose == FIL_TABLESPACE);
5409 
5410  node = UT_LIST_GET_FIRST(space->chain);
5411 
5412  for (;;) {
5413  if (node == NULL) {
5414  if (ignore_nonexistent_pages) {
5415  mutex_exit(&fil_system->mutex);
5416  return(DB_ERROR);
5417  }
5418 
5419  fil_report_invalid_page_access(
5420  block_offset, space_id, space->name,
5421  byte_offset, len, type);
5422 
5423  ut_error;
5424 
5425  } else if (fil_is_user_tablespace_id(space->id)
5426  && node->size == 0) {
5427 
5428  /* We do not know the size of a single-table tablespace
5429  before we open the file */
5430  break;
5431  } else if (node->size > block_offset) {
5432  /* Found! */
5433  break;
5434  } else {
5435  block_offset -= node->size;
5436  node = UT_LIST_GET_NEXT(chain, node);
5437  }
5438  }
5439 
5440  /* Open file if closed */
5441  if (!fil_node_prepare_for_io(node, fil_system, space)) {
5442  if (space->purpose == FIL_TABLESPACE
5443  && fil_is_user_tablespace_id(space->id)) {
5444  mutex_exit(&fil_system->mutex);
5445 
5446  ib_logf(IB_LOG_LEVEL_ERROR,
5447  "Trying to do i/o to a tablespace which "
5448  "exists without .ibd data file. "
5449  "i/o type %lu, space id %lu, page no %lu, "
5450  "i/o length %lu bytes",
5451  (ulong) type, (ulong) space_id,
5452  (ulong) block_offset, (ulong) len);
5453 
5454  return(DB_TABLESPACE_DELETED);
5455  }
5456 
5457  /* The tablespace is for log. Currently, we just assert here
5458  to prevent handling errors along the way fil_io returns.
5459  Also, if the log files are missing, it would be hard to
5460  promise the server can continue running. */
5461  ut_a(0);
5462  }
5463 
5464  /* Check that at least the start offset is within the bounds of a
5465  single-table tablespace, including rollback tablespaces. */
5466  if (UNIV_UNLIKELY(node->size <= block_offset)
5467  && space->id != 0 && space->purpose == FIL_TABLESPACE) {
5468 
5469  fil_report_invalid_page_access(
5470  block_offset, space_id, space->name, byte_offset,
5471  len, type);
5472 
5473  ut_error;
5474  }
5475 
5476  /* Now we have made the changes in the data structures of fil_system */
5477  mutex_exit(&fil_system->mutex);
5478 
5479  /* Calculate the low 32 bits and the high 32 bits of the file offset */
5480 
5481  if (!zip_size) {
5482  offset = ((os_offset_t) block_offset << UNIV_PAGE_SIZE_SHIFT)
5483  + byte_offset;
5484 
5485  ut_a(node->size - block_offset
5486  >= ((byte_offset + len + (UNIV_PAGE_SIZE - 1))
5487  / UNIV_PAGE_SIZE));
5488  } else {
5489  ulint zip_size_shift;
5490  switch (zip_size) {
5491  case 1024: zip_size_shift = 10; break;
5492  case 2048: zip_size_shift = 11; break;
5493  case 4096: zip_size_shift = 12; break;
5494  case 8192: zip_size_shift = 13; break;
5495  case 16384: zip_size_shift = 14; break;
5496  default: ut_error;
5497  }
5498  offset = ((os_offset_t) block_offset << zip_size_shift)
5499  + byte_offset;
5500  ut_a(node->size - block_offset
5501  >= (len + (zip_size - 1)) / zip_size);
5502  }
5503 
5504  /* Do aio */
5505 
5506  ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
5507  ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
5508 
5509 #ifdef UNIV_HOTBACKUP
5510  /* In ibbackup do normal i/o, not aio */
5511  if (type == OS_FILE_READ) {
5512  ret = os_file_read(node->handle, buf, offset, len);
5513  } else {
5515  ret = os_file_write(node->name, node->handle, buf,
5516  offset, len);
5517  }
5518 #else
5519  /* Queue the aio request */
5520  ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
5521  offset, len, node, message);
5522 #endif /* UNIV_HOTBACKUP */
5523  ut_a(ret);
5524 
5525  if (mode == OS_AIO_SYNC) {
5526  /* The i/o operation is already completed when we return from
5527  os_aio: */
5528 
5529  mutex_enter(&fil_system->mutex);
5530 
5531  fil_node_complete_io(node, fil_system, type);
5532 
5533  mutex_exit(&fil_system->mutex);
5534 
5535  ut_ad(fil_validate_skip());
5536  }
5537 
5538  return(DB_SUCCESS);
5539 }
5540 
5541 #ifndef UNIV_HOTBACKUP
5542 /**********************************************************************/
5547 UNIV_INTERN
5548 void
5550 /*=========*/
5551  ulint segment)
5553 {
5554  ibool ret;
5555  fil_node_t* fil_node;
5556  void* message;
5557  ulint type;
5558 
5559  ut_ad(fil_validate_skip());
5560 
5561  if (srv_use_native_aio) {
5562  srv_set_io_thread_op_info(segment, "native aio handle");
5563 #ifdef WIN_ASYNC_IO
5564  ret = os_aio_windows_handle(
5565  segment, 0, &fil_node, &message, &type);
5566 #elif defined(LINUX_NATIVE_AIO)
5567  ret = os_aio_linux_handle(
5568  segment, &fil_node, &message, &type);
5569 #else
5570  ut_error;
5571  ret = 0; /* Eliminate compiler warning */
5572 #endif /* WIN_ASYNC_IO */
5573  } else {
5574  srv_set_io_thread_op_info(segment, "simulated aio handle");
5575 
5577  segment, &fil_node, &message, &type);
5578  }
5579 
5580  ut_a(ret);
5581  if (fil_node == NULL) {
5583  return;
5584  }
5585 
5586  srv_set_io_thread_op_info(segment, "complete io for fil node");
5587 
5588  mutex_enter(&fil_system->mutex);
5589 
5590  fil_node_complete_io(fil_node, fil_system, type);
5591 
5592  mutex_exit(&fil_system->mutex);
5593 
5594  ut_ad(fil_validate_skip());
5595 
5596  /* Do the i/o handling */
5597  /* IMPORTANT: since i/o handling for reads will read also the insert
5598  buffer in tablespace 0, you have to be very careful not to introduce
5599  deadlocks in the i/o system. We keep tablespace 0 data files always
5600  open, and use a special i/o thread to serve insert buffer requests. */
5601 
5602  if (fil_node->space->purpose == FIL_TABLESPACE) {
5603  srv_set_io_thread_op_info(segment, "complete io for buf page");
5604  buf_page_io_complete(static_cast<buf_page_t*>(message));
5605  } else {
5606  srv_set_io_thread_op_info(segment, "complete io for log");
5607  log_io_complete(static_cast<log_group_t*>(message));
5608  }
5609 }
5610 #endif /* UNIV_HOTBACKUP */
5611 
5612 /**********************************************************************/
5615 UNIV_INTERN
5616 void
5618 /*======*/
5619  ulint space_id)
5621 {
5622  fil_space_t* space;
5623  fil_node_t* node;
5624  os_file_t file;
5625 
5626 
5627  mutex_enter(&fil_system->mutex);
5628 
5629  space = fil_space_get_by_id(space_id);
5630 
5631  if (!space || space->stop_new_ops) {
5632  mutex_exit(&fil_system->mutex);
5633 
5634  return;
5635  }
5636 
5637  if (fil_buffering_disabled(space)) {
5638 
5639  /* No need to flush. User has explicitly disabled
5640  buffering. */
5641  ut_ad(!space->is_in_unflushed_spaces);
5642  ut_ad(fil_space_is_flushed(space));
5643  ut_ad(space->n_pending_flushes == 0);
5644 
5645 #ifdef UNIV_DEBUG
5646  for (node = UT_LIST_GET_FIRST(space->chain);
5647  node != NULL;
5648  node = UT_LIST_GET_NEXT(chain, node)) {
5650  == node->flush_counter);
5651  ut_ad(node->n_pending_flushes == 0);
5652  }
5653 #endif /* UNIV_DEBUG */
5654 
5655  mutex_exit(&fil_system->mutex);
5656  return;
5657  }
5658 
5659  space->n_pending_flushes++;
5661  for (node = UT_LIST_GET_FIRST(space->chain);
5662  node != NULL;
5663  node = UT_LIST_GET_NEXT(chain, node)) {
5664 
5665  ib_int64_t old_mod_counter = node->modification_counter;;
5666 
5667  if (old_mod_counter <= node->flush_counter) {
5668  continue;
5669  }
5670 
5671  ut_a(node->open);
5672 
5673  if (space->purpose == FIL_TABLESPACE) {
5675  } else {
5678  }
5679 #ifdef __WIN__
5680  if (node->is_raw_disk) {
5681 
5682  goto skip_flush;
5683  }
5684 #endif /* __WIN__ */
5685 retry:
5686  if (node->n_pending_flushes > 0) {
5687  /* We want to avoid calling os_file_flush() on
5688  the file twice at the same time, because we do
5689  not know what bugs OS's may contain in file
5690  i/o */
5691 
5692  ib_int64_t sig_count =
5693  os_event_reset(node->sync_event);
5694 
5695  mutex_exit(&fil_system->mutex);
5696 
5697  os_event_wait_low(node->sync_event, sig_count);
5698 
5699  mutex_enter(&fil_system->mutex);
5700 
5701  if (node->flush_counter >= old_mod_counter) {
5702 
5703  goto skip_flush;
5704  }
5705 
5706  goto retry;
5707  }
5708 
5709  ut_a(node->open);
5710  file = node->handle;
5711  node->n_pending_flushes++;
5712 
5713  mutex_exit(&fil_system->mutex);
5714 
5715  os_file_flush(file);
5716 
5717  mutex_enter(&fil_system->mutex);
5718 
5719  os_event_set(node->sync_event);
5720 
5721  node->n_pending_flushes--;
5722 skip_flush:
5723  if (node->flush_counter < old_mod_counter) {
5724  node->flush_counter = old_mod_counter;
5725 
5726  if (space->is_in_unflushed_spaces
5727  && fil_space_is_flushed(space)) {
5728 
5729  space->is_in_unflushed_spaces = false;
5730 
5732  unflushed_spaces,
5733  fil_system->unflushed_spaces,
5734  space);
5735  }
5736  }
5737 
5738  if (space->purpose == FIL_TABLESPACE) {
5740  } else {
5742  }
5743  }
5744 
5745  space->n_pending_flushes--;
5746 
5747  mutex_exit(&fil_system->mutex);
5748 }
5749 
5750 /**********************************************************************/
5753 UNIV_INTERN
5754 void
5756 /*==================*/
5757  ulint purpose)
5758 {
5759  fil_space_t* space;
5760  ulint* space_ids;
5761  ulint n_space_ids;
5762  ulint i;
5763 
5764  mutex_enter(&fil_system->mutex);
5765 
5766  n_space_ids = UT_LIST_GET_LEN(fil_system->unflushed_spaces);
5767  if (n_space_ids == 0) {
5768 
5769  mutex_exit(&fil_system->mutex);
5770  return;
5771  }
5772 
5773  /* Assemble a list of space ids to flush. Previously, we
5774  traversed fil_system->unflushed_spaces and called UT_LIST_GET_NEXT()
5775  on a space that was just removed from the list by fil_flush().
5776  Thus, the space could be dropped and the memory overwritten. */
5777  space_ids = static_cast<ulint*>(
5778  mem_alloc(n_space_ids * sizeof *space_ids));
5779 
5780  n_space_ids = 0;
5781 
5782  for (space = UT_LIST_GET_FIRST(fil_system->unflushed_spaces);
5783  space;
5784  space = UT_LIST_GET_NEXT(unflushed_spaces, space)) {
5785 
5786  if (space->purpose == purpose && !space->stop_new_ops) {
5787 
5788  space_ids[n_space_ids++] = space->id;
5789  }
5790  }
5791 
5792  mutex_exit(&fil_system->mutex);
5793 
5794  /* Flush the spaces. It will not hurt to call fil_flush() on
5795  a non-existing space id. */
5796  for (i = 0; i < n_space_ids; i++) {
5797 
5798  fil_flush(space_ids[i]);
5799  }
5800 
5801  mem_free(space_ids);
5802 }
5803 
5805 struct Check {
5806  void operator()(const fil_node_t* elem)
5807  {
5808  ut_a(elem->open || !elem->n_pending);
5809  }
5810 };
5811 
5812 /******************************************************************/
5815 UNIV_INTERN
5816 ibool
5818 /*==============*/
5819 {
5820  fil_space_t* space;
5821  fil_node_t* fil_node;
5822  ulint n_open = 0;
5823  ulint i;
5824 
5825  mutex_enter(&fil_system->mutex);
5826 
5827  /* Look for spaces in the hash table */
5828 
5829  for (i = 0; i < hash_get_n_cells(fil_system->spaces); i++) {
5830 
5831  for (space = static_cast<fil_space_t*>(
5832  HASH_GET_FIRST(fil_system->spaces, i));
5833  space != 0;
5834  space = static_cast<fil_space_t*>(
5835  HASH_GET_NEXT(hash, space))) {
5836 
5838  chain, fil_node_t, space->chain, Check());
5839 
5840  for (fil_node = UT_LIST_GET_FIRST(space->chain);
5841  fil_node != 0;
5842  fil_node = UT_LIST_GET_NEXT(chain, fil_node)) {
5843 
5844  if (fil_node->n_pending > 0) {
5845  ut_a(fil_node->open);
5846  }
5847 
5848  if (fil_node->open) {
5849  n_open++;
5850  }
5851  }
5852  }
5853  }
5854 
5855  ut_a(fil_system->n_open == n_open);
5856 
5857  UT_LIST_CHECK(LRU, fil_node_t, fil_system->LRU);
5858 
5859  for (fil_node = UT_LIST_GET_FIRST(fil_system->LRU);
5860  fil_node != 0;
5861  fil_node = UT_LIST_GET_NEXT(LRU, fil_node)) {
5862 
5863  ut_a(fil_node->n_pending == 0);
5864  ut_a(!fil_node->being_extended);
5865  ut_a(fil_node->open);
5866  ut_a(fil_space_belongs_in_lru(fil_node->space));
5867  }
5868 
5869  mutex_exit(&fil_system->mutex);
5870 
5871  return(TRUE);
5872 }
5873 
5874 /********************************************************************/
5877 UNIV_INTERN
5878 ibool
5880 /*=============*/
5881  fil_addr_t addr)
5882 {
5883  return(addr.page == FIL_NULL);
5884 }
5885 
5886 /********************************************************************/
5889 UNIV_INTERN
5890 ulint
5892 /*==============*/
5893  const byte* page)
5894 {
5895  return(mach_read_from_4(page + FIL_PAGE_PREV));
5896 }
5897 
5898 /********************************************************************/
5901 UNIV_INTERN
5902 ulint
5904 /*==============*/
5905  const byte* page)
5906 {
5907  return(mach_read_from_4(page + FIL_PAGE_NEXT));
5908 }
5909 
5910 /*********************************************************************/
5912 UNIV_INTERN
5913 void
5915 /*==============*/
5916  byte* page,
5917  ulint type)
5918 {
5919  ut_ad(page);
5920 
5921  mach_write_to_2(page + FIL_PAGE_TYPE, type);
5922 }
5923 
5924 /*********************************************************************/
5928 UNIV_INTERN
5929 ulint
5931 /*==============*/
5932  const byte* page)
5933 {
5934  ut_ad(page);
5935 
5936  return(mach_read_from_2(page + FIL_PAGE_TYPE));
5937 }
5938 
5939 /****************************************************************/
5941 UNIV_INTERN
5942 void
5944 /*===========*/
5945 {
5946 #ifndef UNIV_HOTBACKUP
5947  /* The mutex should already have been freed. */
5948  ut_ad(fil_system->mutex.magic_n == 0);
5949 #endif /* !UNIV_HOTBACKUP */
5950 
5951  hash_table_free(fil_system->spaces);
5952 
5953  hash_table_free(fil_system->name_hash);
5954 
5955  ut_a(UT_LIST_GET_LEN(fil_system->LRU) == 0);
5956  ut_a(UT_LIST_GET_LEN(fil_system->unflushed_spaces) == 0);
5957  ut_a(UT_LIST_GET_LEN(fil_system->space_list) == 0);
5958 
5959  mem_free(fil_system);
5960 
5961  fil_system = NULL;
5962 }
5963 
5964 /********************************************************************/
5966 static
5967 void
5968 fil_buf_block_init(
5969 /*===============*/
5970  buf_block_t* block,
5971  byte* frame)
5972 {
5973  UNIV_MEM_DESC(frame, UNIV_PAGE_SIZE);
5974 
5975  block->frame = frame;
5976 
5977  block->page.io_fix = BUF_IO_NONE;
5978  /* There are assertions that check for this. */
5979  block->page.buf_fix_count = 1;
5981 
5982  page_zip_des_init(&block->page.zip);
5983 }
5984 
5987  const char* filepath;
5991  ulint page_size;
5992  ulint n_io_buffers;
5994  byte* io_buffer;
5995 };
5996 
5997 /********************************************************************/
6009 static
6010 dberr_t
6011 fil_iterate(
6012 /*========*/
6013  const fil_iterator_t& iter,
6014  buf_block_t* block,
6015  PageCallback& callback)
6016 {
6018  ulint page_no = 0;
6019  ulint space_id = callback.get_space_id();
6020  ulint n_bytes = iter.n_io_buffers * iter.page_size;
6021 
6023 
6024  /* TODO: For compressed tables we do a lot of useless
6025  copying for non-index pages. Unfortunately, it is
6026  required by buf_zip_decompress() */
6027 
6028  for (offset = iter.start; offset < iter.end; offset += n_bytes) {
6029 
6030  byte* io_buffer = iter.io_buffer;
6031 
6032  block->frame = io_buffer;
6033 
6034  if (callback.get_zip_size() > 0) {
6035  page_zip_des_init(&block->page.zip);
6036  page_zip_set_size(&block->page.zip, iter.page_size);
6037  block->page.zip.data = block->frame + UNIV_PAGE_SIZE;
6038  ut_d(block->page.zip.m_external = true);
6039  ut_ad(iter.page_size == callback.get_zip_size());
6040 
6041  /* Zip IO is done in the compressed page buffer. */
6042  io_buffer = block->page.zip.data;
6043  } else {
6044  io_buffer = iter.io_buffer;
6045  }
6046 
6047  /* We have to read the exact number of bytes. Otherwise the
6048  InnoDB IO functions croak on failed reads. */
6049 
6050  n_bytes = static_cast<ulint>(
6051  ut_min(static_cast<os_offset_t>(n_bytes),
6052  iter.end - offset));
6053 
6054  ut_ad(n_bytes > 0);
6055  ut_ad(!(n_bytes % iter.page_size));
6056 
6057  if (!os_file_read(iter.file, io_buffer, offset,
6058  (ulint) n_bytes)) {
6059 
6060  ib_logf(IB_LOG_LEVEL_ERROR, "os_file_read() failed");
6061 
6062  return(DB_IO_ERROR);
6063  }
6064 
6065  bool updated = false;
6066  os_offset_t page_off = offset;
6067  ulint n_pages_read = (ulint) n_bytes / iter.page_size;
6068 
6069  for (ulint i = 0; i < n_pages_read; ++i) {
6070 
6071  buf_block_set_file_page(block, space_id, page_no++);
6072 
6073  dberr_t err;
6074 
6075  if ((err = callback(page_off, block)) != DB_SUCCESS) {
6076 
6077  return(err);
6078 
6079  } else if (!updated) {
6080  updated = buf_block_get_state(block)
6082  }
6083 
6086 
6087  page_off += iter.page_size;
6088  block->frame += iter.page_size;
6089  }
6090 
6091  /* A page was updated in the set, write back to disk. */
6092  if (updated
6093  && !os_file_write(
6094  iter.filepath, iter.file, io_buffer,
6095  offset, (ulint) n_bytes)) {
6096 
6097  ib_logf(IB_LOG_LEVEL_ERROR, "os_file_write() failed");
6098 
6099  return(DB_IO_ERROR);
6100  }
6101  }
6102 
6103  return(DB_SUCCESS);
6104 }
6105 
6106 /********************************************************************/
6112 UNIV_INTERN
6113 dberr_t
6115 /*===================*/
6117  ulint n_io_buffers,
6118  PageCallback& callback)
6119 {
6120  dberr_t err;
6121  os_file_t file;
6122  char* filepath;
6123 
6124  ut_a(n_io_buffers > 0);
6126 
6127  DBUG_EXECUTE_IF("ib_import_trigger_corruption_1",
6128  return(DB_CORRUPTION););
6129 
6130  if (DICT_TF_HAS_DATA_DIR(table->flags)) {
6131  dict_get_and_save_data_dir_path(table, false);
6132  ut_a(table->data_dir_path);
6133 
6134  filepath = os_file_make_remote_pathname(
6135  table->data_dir_path, table->name, "ibd");
6136  } else {
6137  filepath = fil_make_ibd_name(table->name, false);
6138  }
6139 
6140  {
6141  ibool success;
6142 
6143  file = os_file_create_simple_no_error_handling(
6144  innodb_file_data_key, filepath,
6145  OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
6146 
6147  DBUG_EXECUTE_IF("fil_tablespace_iterate_failure",
6148  {
6149  static bool once;
6150 
6151  if (!once || ut_rnd_interval(0, 10) == 5) {
6152  once = true;
6153  success = FALSE;
6154  os_file_close(file);
6155  }
6156  });
6157 
6158  if (!success) {
6159  /* The following call prints an error message */
6160  os_file_get_last_error(true);
6161 
6162  ib_logf(IB_LOG_LEVEL_ERROR,
6163  "Trying to import a tablespace, but could not "
6164  "open the tablespace file %s", filepath);
6165 
6166  mem_free(filepath);
6167 
6168  return(DB_TABLESPACE_NOT_FOUND);
6169 
6170  } else {
6171  err = DB_SUCCESS;
6172  }
6173  }
6174 
6175  callback.set_file(filepath, file);
6176 
6177  os_offset_t file_size = os_file_get_size(file);
6178  ut_a(file_size != (os_offset_t) -1);
6179 
6180  /* The block we will use for every physical page */
6182 
6183  memset(&block, 0x0, sizeof(block));
6184 
6185  /* Allocate a page to read in the tablespace header, so that we
6186  can determine the page size and zip_size (if it is compressed).
6187  We allocate an extra page in case it is a compressed table. One
6188  page is to ensure alignement. */
6189 
6190  void* page_ptr = mem_alloc(3 * UNIV_PAGE_SIZE);
6191  byte* page = static_cast<byte*>(ut_align(page_ptr, UNIV_PAGE_SIZE));
6192 
6193  fil_buf_block_init(&block, page);
6194 
6195  /* Read the first page and determine the page and zip size. */
6196 
6197  if (!os_file_read(file, page, 0, UNIV_PAGE_SIZE)) {
6198 
6199  err = DB_IO_ERROR;
6200 
6201  } else if ((err = callback.init(file_size, &block)) == DB_SUCCESS) {
6202  fil_iterator_t iter;
6203 
6204  iter.file = file;
6205  iter.start = 0;
6206  iter.end = file_size;
6207  iter.filepath = filepath;
6208  iter.file_size = file_size;
6209  iter.n_io_buffers = n_io_buffers;
6210  iter.page_size = callback.get_page_size();
6211 
6212  /* Compressed pages can't be optimised for block IO for now.
6213  We do the IMPORT page by page. */
6214 
6215  if (callback.get_zip_size() > 0) {
6216  iter.n_io_buffers = 1;
6217  ut_a(iter.page_size == callback.get_zip_size());
6218  }
6219 
6222  void* io_buffer = mem_alloc(
6223  (2 + iter.n_io_buffers) * UNIV_PAGE_SIZE);
6224 
6225  iter.io_buffer = static_cast<byte*>(
6226  ut_align(io_buffer, UNIV_PAGE_SIZE));
6227 
6228  err = fil_iterate(iter, &block, callback);
6229 
6230  mem_free(io_buffer);
6231  }
6232 
6233  if (err == DB_SUCCESS) {
6234 
6235  ib_logf(IB_LOG_LEVEL_INFO, "Sync to disk");
6236 
6237  if (!os_file_flush(file)) {
6238  ib_logf(IB_LOG_LEVEL_INFO, "os_file_flush() failed!");
6239  err = DB_IO_ERROR;
6240  } else {
6241  ib_logf(IB_LOG_LEVEL_INFO, "Sync to disk - done!");
6242  }
6243  }
6244 
6245  os_file_close(file);
6246 
6247  mem_free(page_ptr);
6248  mem_free(filepath);
6249 
6250  return(err);
6251 }
6252 
6256 dberr_t
6257 PageCallback::set_zip_size(const buf_frame_t* page) UNIV_NOTHROW
6258 {
6259  m_zip_size = fsp_header_get_zip_size(page);
6260 
6261  if (!ut_is_2pow(m_zip_size) || m_zip_size > UNIV_ZIP_SIZE_MAX) {
6262  return(DB_CORRUPTION);
6263  }
6264 
6265  return(DB_SUCCESS);
6266 }
6267 
6268 /********************************************************************/
6271 UNIV_INTERN
6272 void
6274 /*============*/
6275  const char* ibd_name)
6277 {
6278  /* Force a delete of any stale .ibd files that are lying around. */
6279 
6280  ib_logf(IB_LOG_LEVEL_INFO, "Deleting %s", ibd_name);
6281 
6282  os_file_delete_if_exists(innodb_file_data_key, ibd_name);
6283 
6284  char* cfg_name = fil_make_cfg_name(ibd_name);
6285 
6286  os_file_delete_if_exists(innodb_file_data_key, cfg_name);
6287 
6288  mem_free(cfg_name);
6289 }
6290 
6296 UNIV_INTERN
6297 dberr_t
6299 /*================*/
6300  space_name_list_t& space_name_list)
6302 {
6303  fil_space_t* space;
6304  dberr_t err = DB_SUCCESS;
6305 
6306  mutex_enter(&fil_system->mutex);
6307 
6308  for (space = UT_LIST_GET_FIRST(fil_system->space_list);
6309  space != NULL;
6310  space = UT_LIST_GET_NEXT(space_list, space)) {
6311 
6312  if (space->purpose == FIL_TABLESPACE) {
6313  ulint len;
6314  char* name;
6315 
6316  len = strlen(space->name);
6317  name = new(std::nothrow) char[len + 1];
6318 
6319  if (name == 0) {
6320  /* Caller to free elements allocated so far. */
6321  err = DB_OUT_OF_MEMORY;
6322  break;
6323  }
6324 
6325  memcpy(name, space->name, len);
6326  name[len] = 0;
6327 
6328  space_name_list.push_back(name);
6329  }
6330  }
6331 
6332  mutex_exit(&fil_system->mutex);
6333 
6334  return(err);
6335 }
6336 
6337 /****************************************************************/
6339 UNIV_INTERN
6340 void
6342 /*===============*/
6343  ulint old_space_id,
6345  const char* old_name,
6346  ulint new_space_id,
6348  const char* new_name,
6349  const char* tmp_name,
6351  mtr_t* mtr)
6352 {
6353  if (old_space_id != TRX_SYS_SPACE) {
6354  fil_op_write_log(MLOG_FILE_RENAME, old_space_id,
6355  0, 0, old_name, tmp_name, mtr);
6356  }
6357 
6358  if (new_space_id != TRX_SYS_SPACE) {
6359  fil_op_write_log(MLOG_FILE_RENAME, new_space_id,
6360  0, 0, new_name, old_name, mtr);
6361  }
6362 }