summaryrefslogtreecommitdiff
path: root/storage/xtradb/srv/srv0srv.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/xtradb/srv/srv0srv.c')
-rw-r--r--storage/xtradb/srv/srv0srv.c4251
1 files changed, 0 insertions, 4251 deletions
diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c
deleted file mode 100644
index 478fc0505bc..00000000000
--- a/storage/xtradb/srv/srv0srv.c
+++ /dev/null
@@ -1,4251 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2008, 2009 Google Inc.
-Copyright (c) 2009, Percona Inc.
-
-Portions of this file contain modifications contributed and copyrighted by
-Google, Inc. Those modifications are gratefully acknowledged and are described
-briefly in the InnoDB documentation. The contributions by Google are
-incorporated with their permission, and subject to the conditions contained in
-the file COPYING.Google.
-
-Portions of this file contain modifications contributed and copyrighted
-by Percona Inc.. Those modifications are
-gratefully acknowledged and are described briefly in the InnoDB
-documentation. The contributions by Percona Inc. are incorporated with
-their permission, and subject to the conditions contained in the file
-COPYING.Percona.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file srv/srv0srv.c
-The database server main program
-
-NOTE: SQL Server 7 uses something which the documentation
-calls user mode scheduled threads (UMS threads). One such
-thread is usually allocated per processor. Win32
-documentation does not know any UMS threads, which suggests
-that the concept is internal to SQL Server 7. It may mean that
-SQL Server 7 does all the scheduling of threads itself, even
-in i/o waits. We should maybe modify InnoDB to use the same
-technique, because thread switches within NT may be too slow.
-
-SQL Server 7 also mentions fibers, which are cooperatively
-scheduled threads. They can boost performance by 5 %,
-according to the Delaney and Soukup's book.
-
-Windows 2000 will have something called thread pooling
-(see msdn website), which we could possibly use.
-
-Another possibility could be to use some very fast user space
-thread library. This might confuse NT though.
-
-Created 10/8/1995 Heikki Tuuri
-*******************************************************/
-
-/* Dummy comment */
-#include "m_string.h" /* for my_sys.h */
-#include "my_sys.h" /* DEBUG_SYNC_C */
-#include "srv0srv.h"
-
-#include "ut0mem.h"
-#include "ut0ut.h"
-#include "os0proc.h"
-#include "mem0mem.h"
-#include "mem0pool.h"
-#include "sync0sync.h"
-#include "que0que.h"
-#include "log0online.h"
-#include "log0recv.h"
-#include "pars0pars.h"
-#include "usr0sess.h"
-#include "lock0lock.h"
-#include "trx0purge.h"
-#include "ibuf0ibuf.h"
-#include "buf0flu.h"
-#include "buf0lru.h"
-#include "btr0sea.h"
-#include "dict0load.h"
-#include "dict0boot.h"
-#include "srv0start.h"
-#include "row0mysql.h"
-#include "ha_prototypes.h"
-#include "trx0i_s.h"
-#include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
-#include "read0read.h"
-#include "mysql/plugin.h"
-#include "mysql/service_thd_wait.h"
-
-/* prototypes of new functions added to ha_innodb.cc for kill_idle_transaction */
-ibool innobase_thd_is_idle(const void* thd);
-ib_int64_t innobase_thd_get_start_time(const void* thd);
-void innobase_thd_kill(ulong thd_id);
-ulong innobase_thd_get_thread_id(const void* thd);
-
-/* prototypes for new functions added to ha_innodb.cc */
-ibool innobase_get_slow_log();
-
-/* The following counter is incremented whenever there is some user activity
-in the server */
-UNIV_INTERN ulint srv_activity_count = 0;
-
-/* The following is the maximum allowed duration of a lock wait. */
-UNIV_INTERN ulint srv_fatal_semaphore_wait_threshold = 600;
-
-/**/
-UNIV_INTERN long long srv_kill_idle_transaction = 0;
-
-/* How much data manipulation language (DML) statements need to be delayed,
-in microseconds, in order to reduce the lagging of the purge thread. */
-UNIV_INTERN ulint srv_dml_needed_delay = 0;
-
-UNIV_INTERN ibool srv_lock_timeout_active = FALSE;
-UNIV_INTERN ibool srv_monitor_active = FALSE;
-UNIV_INTERN ibool srv_error_monitor_active = FALSE;
-
-UNIV_INTERN const char* srv_main_thread_op_info = "";
-
-/** Prefix used by MySQL to indicate pre-5.1 table name encoding */
-UNIV_INTERN const char srv_mysql50_table_name_prefix[9] = "#mysql50#";
-
-/* Server parameters which are read from the initfile */
-
-/* The following three are dir paths which are catenated before file
-names, where the file name itself may also contain a path */
-
-UNIV_INTERN char* srv_data_home = NULL;
-#ifdef UNIV_LOG_ARCHIVE
-UNIV_INTERN char* srv_arch_dir = NULL;
-#endif /* UNIV_LOG_ARCHIVE */
-
-/** store to its own file each table created by an user; data
-dictionary tables are in the system tablespace 0 */
-UNIV_INTERN my_bool srv_file_per_table;
-/** The file format to use on new *.ibd files. */
-UNIV_INTERN ulint srv_file_format = 0;
-/** Whether to check file format during startup. A value of
-DICT_TF_FORMAT_MAX + 1 means no checking ie. FALSE. The default is to
-set it to the highest format we support. */
-UNIV_INTERN ulint srv_max_file_format_at_startup = DICT_TF_FORMAT_MAX;
-
-#if DICT_TF_FORMAT_51
-# error "DICT_TF_FORMAT_51 must be 0!"
-#endif
-/** Place locks to records only i.e. do not use next-key locking except
-on duplicate key checking and foreign key checking */
-UNIV_INTERN ibool srv_locks_unsafe_for_binlog = FALSE;
-
-/* If this flag is TRUE, then we will use the native aio of the
-OS (provided we compiled Innobase with it in), otherwise we will
-use simulated aio we build below with threads.
-Currently we support native aio on windows and linux */
-UNIV_INTERN my_bool srv_use_native_aio = TRUE;
-
-#ifdef __WIN__
-/* Windows native condition variables. We use runtime loading / function
-pointers, because they are not available on Windows Server 2003 and
-Windows XP/2000.
-
-We use condition for events on Windows if possible, even if os_event
-resembles Windows kernel event object well API-wise. The reason is
-performance, kernel objects are heavyweights and WaitForSingleObject() is a
-performance killer causing calling thread to context switch. Besides, Innodb
-is preallocating large number (often millions) of os_events. With kernel event
-objects it takes a big chunk out of non-paged pool, which is better suited
-for tasks like IO than for storing idle event objects. */
-UNIV_INTERN ibool srv_use_native_conditions = FALSE;
-#endif /* __WIN__ */
-
-UNIV_INTERN ulint srv_n_data_files = 0;
-UNIV_INTERN char** srv_data_file_names = NULL;
-/* size in database pages */
-UNIV_INTERN ulint* srv_data_file_sizes = NULL;
-
-UNIV_INTERN char* srv_doublewrite_file = NULL;
-
-UNIV_INTERN ibool srv_recovery_stats = FALSE;
-
-UNIV_INTERN my_bool srv_track_changed_pages = FALSE;
-
-UNIV_INTERN ib_uint64_t srv_max_bitmap_file_size = 100 * 1024 * 1024;
-
-UNIV_INTERN ulonglong srv_max_changed_pages = 0;
-
-/** When TRUE, fake change transcations take S rather than X row locks.
- When FALSE, row locks are not taken at all. */
-UNIV_INTERN my_bool srv_fake_changes_locks = TRUE;
-
-/* if TRUE, then we auto-extend the last data file */
-UNIV_INTERN ibool srv_auto_extend_last_data_file = FALSE;
-/* if != 0, this tells the max size auto-extending may increase the
-last data file size */
-UNIV_INTERN ulint srv_last_file_size_max = 0;
-/* If the last data file is auto-extended, we add this
-many pages to it at a time */
-UNIV_INTERN ulong srv_auto_extend_increment = 8;
-UNIV_INTERN ulint* srv_data_file_is_raw_partition = NULL;
-
-/* If the following is TRUE we do not allow inserts etc. This protects
-the user from forgetting the 'newraw' keyword to my.cnf */
-
-UNIV_INTERN ibool srv_created_new_raw = FALSE;
-
-UNIV_INTERN char** srv_log_group_home_dirs = NULL;
-
-UNIV_INTERN ulint srv_n_log_groups = ULINT_MAX;
-UNIV_INTERN ulint srv_n_log_files = ULINT_MAX;
-/* size in database pages */
-UNIV_INTERN ulint srv_log_file_size = ULINT_MAX;
-/* size in database pages */
-UNIV_INTERN ulint srv_log_buffer_size = ULINT_MAX;
-//UNIV_INTERN ulong srv_flush_log_at_trx_commit = 1;
-UNIV_INTERN char srv_use_global_flush_log_at_trx_commit = TRUE;
-
-/* Try to flush dirty pages so as to avoid IO bursts at
-the checkpoints. */
-UNIV_INTERN char srv_adaptive_flushing = TRUE;
-
-UNIV_INTERN ulong srv_show_locks_held = 10;
-UNIV_INTERN ulong srv_show_verbose_locks = 0;
-
-/** Maximum number of times allowed to conditionally acquire
-mutex before switching to blocking wait on the mutex */
-#define MAX_MUTEX_NOWAIT 20
-
-/** Check whether the number of failed nonblocking mutex
-acquisition attempts exceeds maximum allowed value. If so,
-srv_printf_innodb_monitor() will request mutex acquisition
-with mutex_enter(), which will wait until it gets the mutex. */
-#define MUTEX_NOWAIT(mutex_skipped) ((mutex_skipped) < MAX_MUTEX_NOWAIT)
-
-/** The sort order table of the MySQL latin1_swedish_ci character set
-collation */
-UNIV_INTERN const byte* srv_latin1_ordering;
-
-/* use os/external memory allocator */
-UNIV_INTERN my_bool srv_use_sys_malloc = TRUE;
-/* requested size in kilobytes */
-UNIV_INTERN ulint srv_buf_pool_size = ULINT_MAX;
-/* force virtual page preallocation (prefault) */
-UNIV_INTERN my_bool srv_buf_pool_populate = FALSE;
-/* requested number of buffer pool instances */
-UNIV_INTERN ulint srv_buf_pool_instances = 1;
-/* previously requested size */
-UNIV_INTERN ulint srv_buf_pool_old_size;
-/* current size in kilobytes */
-UNIV_INTERN ulint srv_buf_pool_curr_size = 0;
-/* size in bytes */
-UNIV_INTERN ulint srv_mem_pool_size = ULINT_MAX;
-UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX;
-
-/* This parameter is deprecated. Use srv_n_io_[read|write]_threads
-instead. */
-UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX;
-UNIV_INTERN ulint srv_n_read_io_threads = ULINT_MAX;
-UNIV_INTERN ulint srv_n_write_io_threads = ULINT_MAX;
-
-/* Switch to enable random read ahead. */
-UNIV_INTERN my_bool srv_random_read_ahead = FALSE;
-
-/* The universal page size of the database */
-UNIV_INTERN ulint srv_page_size_shift = 0;
-UNIV_INTERN ulint srv_page_size = 0;
-
-/* The log block size */
-UNIV_INTERN ulint srv_log_block_size = 0;
-
-/* User settable value of the number of pages that must be present
-in the buffer cache and accessed sequentially for InnoDB to trigger a
-readahead request. */
-UNIV_INTERN ulong srv_read_ahead_threshold = 56;
-
-#ifdef UNIV_LOG_ARCHIVE
-UNIV_INTERN ibool srv_log_archive_on = FALSE;
-UNIV_INTERN ibool srv_archive_recovery = 0;
-UNIV_INTERN ib_uint64_t srv_archive_recovery_limit_lsn;
-#endif /* UNIV_LOG_ARCHIVE */
-
-/* This parameter is used to throttle the number of insert buffers that are
-merged in a batch. By increasing this parameter on a faster disk you can
-possibly reduce the number of I/O operations performed to complete the
-merge operation. The value of this parameter is used as is by the
-background loop when the system is idle (low load), on a busy system
-the parameter is scaled down by a factor of 4, this is to avoid putting
-a heavier load on the I/O sub system. */
-
-UNIV_INTERN ulong srv_insert_buffer_batch_size = 20;
-
-UNIV_INTERN char* srv_file_flush_method_str = NULL;
-UNIV_INTERN ulint srv_unix_file_flush_method = SRV_UNIX_FSYNC;
-UNIV_INTERN ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
-
-UNIV_INTERN ulint srv_max_n_open_files = 300;
-
-/* Number of IO operations per second the server can do */
-UNIV_INTERN ulong srv_io_capacity = 200;
-
-/* The InnoDB main thread tries to keep the ratio of modified pages
-in the buffer pool to all database pages in the buffer pool smaller than
-the following number. But it is not guaranteed that the value stays below
-that during a time of heavy update/insert activity. */
-
-UNIV_INTERN ulong srv_max_buf_pool_modified_pct = 75;
-
-/* the number of purge threads to use from the worker pool (currently 0 or 1).*/
-UNIV_INTERN ulong srv_n_purge_threads = 0;
-
-/* the number of pages to purge in one batch */
-UNIV_INTERN ulong srv_purge_batch_size = 20;
-
-/* the number of rollback segments to use */
-UNIV_INTERN ulong srv_rollback_segments = TRX_SYS_N_RSEGS;
-
-/* Internal setting for "innodb_stats_method". Decides how InnoDB treats
-NULL value when collecting statistics. By default, it is set to
-SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */
-UNIV_INTERN ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL;
-
-/** Time in seconds between automatic buffer pool dumps */
-UNIV_INTERN uint srv_auto_lru_dump = 0;
-
-/** Whether startup should be blocked until buffer pool is fully restored */
-UNIV_INTERN ibool srv_blocking_lru_restore;
-
-/* structure to pass status variables to MySQL */
-UNIV_INTERN export_struc export_vars;
-
-/* If the following is != 0 we do not allow inserts etc. This protects
-the user from forgetting the innodb_force_recovery keyword to my.cnf */
-
-UNIV_INTERN ulint srv_force_recovery = 0;
-/*-----------------------*/
-/* We are prepared for a situation that we have this many threads waiting for
-a semaphore inside InnoDB. innobase_start_or_create_for_mysql() sets the
-value. */
-
-UNIV_INTERN ulint srv_max_n_threads = 0;
-
-/* The following controls how many threads we let inside InnoDB concurrently:
-threads waiting for locks are not counted into the number because otherwise
-we could get a deadlock. MySQL creates a thread for each user session, and
-semaphore contention and convoy problems can occur withput this restriction.
-Value 10 should be good if there are less than 4 processors + 4 disks in the
-computer. Bigger computers need bigger values. Value 0 will disable the
-concurrency check. */
-
-UNIV_INTERN ibool srv_thread_concurrency_timer_based = FALSE;
-UNIV_INTERN ulong srv_thread_concurrency = 0;
-
-/* this mutex protects srv_conc data structures */
-UNIV_INTERN os_fast_mutex_t srv_conc_mutex;
-/* number of transactions that have declared_to_be_inside_innodb set.
-It used to be a non-error for this value to drop below zero temporarily.
-This is no longer true. We'll, however, keep the lint datatype to add
-assertions to catch any corner cases that we may have missed. */
-UNIV_INTERN lint srv_conc_n_threads = 0;
-/* number of OS threads waiting in the FIFO for a permission to enter
-InnoDB */
-UNIV_INTERN ulint srv_conc_n_waiting_threads = 0;
-
-/* print all user-level transactions deadlocks to mysqld stderr */
-UNIV_INTERN my_bool srv_print_all_deadlocks = FALSE;
-
-/* Produce a stacktrace on long semaphore wait */
-UNIV_INTERN my_bool srv_use_stacktrace = FALSE;
-
-typedef struct srv_conc_slot_struct srv_conc_slot_t;
-struct srv_conc_slot_struct{
- os_event_t event; /*!< event to wait */
- ibool reserved; /*!< TRUE if slot
- reserved */
- ibool wait_ended; /*!< TRUE when another
- thread has already set
- the event and the
- thread in this slot is
- free to proceed; but
- reserved may still be
- TRUE at that point */
- UT_LIST_NODE_T(srv_conc_slot_t) srv_conc_queue; /*!< queue node */
-};
-
-/* queue of threads waiting to get in */
-UNIV_INTERN UT_LIST_BASE_NODE_T(srv_conc_slot_t) srv_conc_queue;
-/* array of wait slots */
-UNIV_INTERN srv_conc_slot_t* srv_conc_slots;
-
-/* Number of times a thread is allowed to enter InnoDB within the same
-SQL query after it has once got the ticket at srv_conc_enter_innodb */
-#define SRV_FREE_TICKETS_TO_ENTER srv_n_free_tickets_to_enter
-#define SRV_THREAD_SLEEP_DELAY srv_thread_sleep_delay
-/*-----------------------*/
-/* If the following is set to 1 then we do not run purge and insert buffer
-merge to completion before shutdown. If it is set to 2, do not even flush the
-buffer pool to data files at the shutdown: we effectively 'crash'
-InnoDB (but lose no committed transactions). */
-UNIV_INTERN ulint srv_fast_shutdown = 0;
-
-/* Generate a innodb_status.<pid> file */
-UNIV_INTERN ibool srv_innodb_status = FALSE;
-
-/* When estimating number of different key values in an index, sample
-this many index pages */
-UNIV_INTERN unsigned long long srv_stats_sample_pages = 8;
-UNIV_INTERN ulint srv_stats_auto_update = 1;
-UNIV_INTERN ulint srv_stats_update_need_lock = 1;
-UNIV_INTERN ibool srv_use_sys_stats_table = FALSE;
-#ifdef UNIV_DEBUG
-UNIV_INTERN ulong srv_sys_stats_root_page = 0;
-#endif
-
-UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE;
-UNIV_INTERN ibool srv_use_atomic_writes = FALSE;
-#ifdef HAVE_POSIX_FALLOCATE
-UNIV_INTERN ibool srv_use_posix_fallocate = FALSE;
-#endif
-
-UNIV_INTERN ibool srv_use_checksums = TRUE;
-UNIV_INTERN ibool srv_fast_checksum = FALSE;
-
-UNIV_INTERN ulong srv_replication_delay = 0;
-
-UNIV_INTERN long long srv_ibuf_max_size = 0;
-UNIV_INTERN ulong srv_ibuf_active_contract = 0; /* 0:disable 1:enable */
-UNIV_INTERN ulong srv_ibuf_accel_rate = 100;
-#define PCT_IBUF_IO(pct) ((ulint) (srv_io_capacity * srv_ibuf_accel_rate * ((double) pct / 10000.0)))
-
-UNIV_INTERN ulint srv_checkpoint_age_target = 0;
-UNIV_INTERN ulong srv_flush_neighbor_pages = 1; /* 0:disable 1:area 2:contiguous */
-
-UNIV_INTERN ulint srv_deprecated_enable_unsafe_group_commit = 0;
-UNIV_INTERN ulong srv_read_ahead = 3; /* 1: random 2: linear 3: Both */
-UNIV_INTERN ulong srv_adaptive_flushing_method = 0; /* 0: native 1: estimate 2: keep_average */
-
-UNIV_INTERN ulong srv_expand_import = 0; /* 0:disable 1:enable */
-UNIV_INTERN ulong srv_pass_corrupt_table = 0; /* 0:disable 1:enable */
-
-UNIV_INTERN ulint srv_dict_size_limit = 0;
-/*-------------------------------------------*/
-UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
-UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
-UNIV_INTERN ulong srv_thread_sleep_delay = 10000;
-UNIV_INTERN ulong srv_spin_wait_delay = 6;
-UNIV_INTERN ibool srv_priority_boost = TRUE;
-
-#ifdef UNIV_DEBUG
-UNIV_INTERN ibool srv_print_thread_releases = FALSE;
-UNIV_INTERN ibool srv_print_lock_waits = FALSE;
-UNIV_INTERN ibool srv_print_buf_io = FALSE;
-UNIV_INTERN ibool srv_print_log_io = FALSE;
-UNIV_INTERN ibool srv_print_latch_waits = FALSE;
-#endif /* UNIV_DEBUG */
-
-static ulint srv_n_rows_inserted_old = 0;
-static ulint srv_n_rows_updated_old = 0;
-static ulint srv_n_rows_deleted_old = 0;
-static ulint srv_n_rows_read_old = 0;
-
-/* Ensure counters are on separate cache lines */
-
-#define CACHE_LINE_SIZE 64
-#define CACHE_ALIGNED __attribute__ ((aligned (CACHE_LINE_SIZE)))
-
-UNIV_INTERN byte
-counters_pad_start[CACHE_LINE_SIZE] __attribute__((unused)) = {0};
-
-UNIV_INTERN ulint srv_n_rows_inserted CACHE_ALIGNED = 0;
-UNIV_INTERN ulint srv_n_rows_updated CACHE_ALIGNED = 0;
-UNIV_INTERN ulint srv_n_rows_deleted CACHE_ALIGNED = 0;
-UNIV_INTERN ulint srv_n_rows_read CACHE_ALIGNED = 0;
-
-UNIV_INTERN ulint srv_read_views_memory CACHE_ALIGNED = 0;
-UNIV_INTERN ulint srv_descriptors_memory CACHE_ALIGNED = 0;
-
-UNIV_INTERN ulint srv_n_lock_deadlock_count CACHE_ALIGNED = 0;
-UNIV_INTERN ulint srv_n_lock_wait_count CACHE_ALIGNED = 0;
-UNIV_INTERN ulint srv_n_lock_wait_current_count CACHE_ALIGNED = 0;
-UNIV_INTERN ib_int64_t srv_n_lock_wait_time CACHE_ALIGNED = 0;
-UNIV_INTERN ulint srv_n_lock_max_wait_time CACHE_ALIGNED = 0;
-
-UNIV_INTERN ulint srv_truncated_status_writes CACHE_ALIGNED = 0;
-
-/* variable counts amount of data read in total (in bytes) */
-UNIV_INTERN ulint srv_data_read CACHE_ALIGNED = 0;
-
-/* here we count the amount of data written in total (in bytes) */
-UNIV_INTERN ulint srv_data_written CACHE_ALIGNED = 0;
-
-/* the number of the log write requests done */
-UNIV_INTERN ulint srv_log_write_requests CACHE_ALIGNED = 0;
-
-/* the number of physical writes to the log performed */
-UNIV_INTERN ulint srv_log_writes CACHE_ALIGNED = 0;
-
-/* amount of data written to the log files in bytes */
-UNIV_INTERN ulint srv_os_log_written CACHE_ALIGNED = 0;
-
-/* amount of writes being done to the log files */
-UNIV_INTERN ulint srv_os_log_pending_writes CACHE_ALIGNED = 0;
-
-/* we increase this counter, when there we don't have enough space in the
-log buffer and have to flush it */
-UNIV_INTERN ulint srv_log_waits CACHE_ALIGNED = 0;
-
-/* this variable counts the amount of times, when the doublewrite buffer
-was flushed */
-UNIV_INTERN ulint srv_dblwr_writes CACHE_ALIGNED = 0;
-
-/* here we store the number of pages that have been flushed to the
-doublewrite buffer */
-UNIV_INTERN ulint srv_dblwr_pages_written CACHE_ALIGNED = 0;
-
-/* in this variable we store the number of write requests issued */
-UNIV_INTERN ulint srv_buf_pool_write_requests CACHE_ALIGNED = 0;
-
-/* here we store the number of times when we had to wait for a free page
-in the buffer pool. It happens when the buffer pool is full and we need
-to make a flush, in order to be able to read or create a page. */
-UNIV_INTERN ulint srv_buf_pool_wait_free CACHE_ALIGNED = 0;
-
-/** Number of buffer pool reads that led to the
-reading of a disk page */
-UNIV_INTERN ulint srv_buf_pool_reads CACHE_ALIGNED = 0;
-
-/* variable to count the number of pages that were written from buffer
-pool to the disk */
-UNIV_INTERN ulint srv_buf_pool_flushed CACHE_ALIGNED = 0;
-
-/* variable to count the number of LRU flushed pages */
-UNIV_INTERN ulint buf_lru_flush_page_count CACHE_ALIGNED = 0;
-
-UNIV_INTERN byte
-counters_pad_end[CACHE_LINE_SIZE] __attribute__((unused)) = {0};
-
-/*
- Set the following to 0 if you want InnoDB to write messages on
- stderr on startup/shutdown
-*/
-UNIV_INTERN ibool srv_print_verbose_log = TRUE;
-UNIV_INTERN ibool srv_print_innodb_monitor = FALSE;
-UNIV_INTERN ibool srv_print_innodb_lock_monitor = FALSE;
-UNIV_INTERN ibool srv_print_innodb_tablespace_monitor = FALSE;
-UNIV_INTERN ibool srv_print_innodb_table_monitor = FALSE;
-
-/* Array of English strings describing the current state of an
-i/o handler thread */
-
-UNIV_INTERN const char* srv_io_thread_op_info[SRV_MAX_N_IO_THREADS];
-UNIV_INTERN const char* srv_io_thread_function[SRV_MAX_N_IO_THREADS];
-
-UNIV_INTERN time_t srv_last_monitor_time;
-
-UNIV_INTERN mutex_t srv_innodb_monitor_mutex;
-
-/* Mutex for locking srv_monitor_file */
-UNIV_INTERN mutex_t srv_monitor_file_mutex;
-
-#ifdef UNIV_PFS_MUTEX
-/* Key to register kernel_mutex with performance schema */
-UNIV_INTERN mysql_pfs_key_t kernel_mutex_key;
-/* Key to register srv_innodb_monitor_mutex with performance schema */
-UNIV_INTERN mysql_pfs_key_t srv_innodb_monitor_mutex_key;
-/* Key to register srv_monitor_file_mutex with performance schema */
-UNIV_INTERN mysql_pfs_key_t srv_monitor_file_mutex_key;
-/* Key to register srv_dict_tmpfile_mutex with performance schema */
-UNIV_INTERN mysql_pfs_key_t srv_dict_tmpfile_mutex_key;
-/* Key to register the mutex with performance schema */
-UNIV_INTERN mysql_pfs_key_t srv_misc_tmpfile_mutex_key;
-#endif /* UNIV_PFS_MUTEX */
-
-/* Temporary file for innodb monitor output */
-UNIV_INTERN FILE* srv_monitor_file;
-/* Mutex for locking srv_dict_tmpfile.
-This mutex has a very high rank; threads reserving it should not
-be holding any InnoDB latches. */
-UNIV_INTERN mutex_t srv_dict_tmpfile_mutex;
-/* Temporary file for output from the data dictionary */
-UNIV_INTERN FILE* srv_dict_tmpfile;
-/* Mutex for locking srv_misc_tmpfile.
-This mutex has a very low rank; threads reserving it should not
-acquire any further latches or sleep before releasing this one. */
-UNIV_INTERN mutex_t srv_misc_tmpfile_mutex;
-/* Temporary file for miscellanous diagnostic output */
-UNIV_INTERN FILE* srv_misc_tmpfile;
-
-UNIV_INTERN ulint srv_main_thread_process_no = 0;
-UNIV_INTERN ulint srv_main_thread_id = 0;
-
-/* The following count work done by srv_master_thread. */
-
-/* Iterations by the 'once per second' loop. */
-static ulint srv_main_1_second_loops = 0;
-/* Calls to sleep by the 'once per second' loop. */
-static ulint srv_main_sleeps = 0;
-/* Iterations by the 'once per 10 seconds' loop. */
-static ulint srv_main_10_second_loops = 0;
-/* Iterations of the loop bounded by the 'background_loop' label. */
-static ulint srv_main_background_loops = 0;
-/* Iterations of the loop bounded by the 'flush_loop' label. */
-static ulint srv_main_flush_loops = 0;
-/* Log writes involving flush. */
-static ulint srv_log_writes_and_flush = 0;
-
-/* This is only ever touched by the master thread. It records the
-time when the last flush of log file has happened. The master
-thread ensures that we flush the log files at least once per
-second. */
-static time_t srv_last_log_flush_time;
-
-/* The master thread performs various tasks based on the current
-state of IO activity and the level of IO utilization is past
-intervals. Following macros define thresholds for these conditions. */
-#define SRV_PEND_IO_THRESHOLD (PCT_IO(3))
-#define SRV_RECENT_IO_ACTIVITY (PCT_IO(5))
-#define SRV_PAST_IO_ACTIVITY (PCT_IO(200))
-
-/*
- IMPLEMENTATION OF THE SERVER MAIN PROGRAM
- =========================================
-
-There is the following analogue between this database
-server and an operating system kernel:
-
-DB concept equivalent OS concept
----------- ---------------------
-transaction -- process;
-
-query thread -- thread;
-
-lock -- semaphore;
-
-transaction set to
-the rollback state -- kill signal delivered to a process;
-
-kernel -- kernel;
-
-query thread execution:
-(a) without kernel mutex
-reserved -- process executing in user mode;
-(b) with kernel mutex reserved
- -- process executing in kernel mode;
-
-The server is controlled by a master thread which runs at
-a priority higher than normal, that is, higher than user threads.
-It sleeps most of the time, and wakes up, say, every 300 milliseconds,
-to check whether there is anything happening in the server which
-requires intervention of the master thread. Such situations may be,
-for example, when flushing of dirty blocks is needed in the buffer
-pool or old version of database rows have to be cleaned away.
-
-The threads which we call user threads serve the queries of
-the clients and input from the console of the server.
-They run at normal priority. The server may have several
-communications endpoints. A dedicated set of user threads waits
-at each of these endpoints ready to receive a client request.
-Each request is taken by a single user thread, which then starts
-processing and, when the result is ready, sends it to the client
-and returns to wait at the same endpoint the thread started from.
-
-So, we do not have dedicated communication threads listening at
-the endpoints and dealing the jobs to dedicated worker threads.
-Our architecture saves one thread swithch per request, compared
-to the solution with dedicated communication threads
-which amounts to 15 microseconds on 100 MHz Pentium
-running NT. If the client
-is communicating over a network, this saving is negligible, but
-if the client resides in the same machine, maybe in an SMP machine
-on a different processor from the server thread, the saving
-can be important as the threads can communicate over shared
-memory with an overhead of a few microseconds.
-
-We may later implement a dedicated communication thread solution
-for those endpoints which communicate over a network.
-
-Our solution with user threads has two problems: for each endpoint
-there has to be a number of listening threads. If there are many
-communication endpoints, it may be difficult to set the right number
-of concurrent threads in the system, as many of the threads
-may always be waiting at less busy endpoints. Another problem
-is queuing of the messages, as the server internally does not
-offer any queue for jobs.
-
-Another group of user threads is intended for splitting the
-queries and processing them in parallel. Let us call these
-parallel communication threads. These threads are waiting for
-parallelized tasks, suspended on event semaphores.
-
-A single user thread waits for input from the console,
-like a command to shut the database.
-
-Utility threads are a different group of threads which takes
-care of the buffer pool flushing and other, mainly background
-operations, in the server.
-Some of these utility threads always run at a lower than normal
-priority, so that they are always in background. Some of them
-may dynamically boost their priority by the pri_adjust function,
-even to higher than normal priority, if their task becomes urgent.
-The running of utilities is controlled by high- and low-water marks
-of urgency. The urgency may be measured by the number of dirty blocks
-in the buffer pool, in the case of the flush thread, for example.
-When the high-water mark is exceeded, an utility starts running, until
-the urgency drops under the low-water mark. Then the utility thread
-suspend itself to wait for an event. The master thread is
-responsible of signaling this event when the utility thread is
-again needed.
-
-For each individual type of utility, some threads always remain
-at lower than normal priority. This is because pri_adjust is implemented
-so that the threads at normal or higher priority control their
-share of running time by calling sleep. Thus, if the load of the
-system sudenly drops, these threads cannot necessarily utilize
-the system fully. The background priority threads make up for this,
-starting to run when the load drops.
-
-When there is no activity in the system, also the master thread
-suspends itself to wait for an event making
-the server totally silent. The responsibility to signal this
-event is on the user thread which again receives a message
-from a client.
-
-There is still one complication in our server design. If a
-background utility thread obtains a resource (e.g., mutex) needed by a user
-thread, and there is also some other user activity in the system,
-the user thread may have to wait indefinitely long for the
-resource, as the OS does not schedule a background thread if
-there is some other runnable user thread. This problem is called
-priority inversion in real-time programming.
-
-One solution to the priority inversion problem would be to
-keep record of which thread owns which resource and
-in the above case boost the priority of the background thread
-so that it will be scheduled and it can release the resource.
-This solution is called priority inheritance in real-time programming.
-A drawback of this solution is that the overhead of acquiring a mutex
-increases slightly, maybe 0.2 microseconds on a 100 MHz Pentium, because
-the thread has to call os_thread_get_curr_id.
-This may be compared to 0.5 microsecond overhead for a mutex lock-unlock
-pair. Note that the thread
-cannot store the information in the resource, say mutex, itself,
-because competing threads could wipe out the information if it is
-stored before acquiring the mutex, and if it stored afterwards,
-the information is outdated for the time of one machine instruction,
-at least. (To be precise, the information could be stored to
-lock_word in mutex if the machine supports atomic swap.)
-
-The above solution with priority inheritance may become actual in the
-future, but at the moment we plan to implement a more coarse solution,
-which could be called a global priority inheritance. If a thread
-has to wait for a long time, say 300 milliseconds, for a resource,
-we just guess that it may be waiting for a resource owned by a background
-thread, and boost the priority of all runnable background threads
-to the normal level. The background threads then themselves adjust
-their fixed priority back to background after releasing all resources
-they had (or, at some fixed points in their program code).
-
-What is the performance of the global priority inheritance solution?
-We may weigh the length of the wait time 300 milliseconds, during
-which the system processes some other thread
-to the cost of boosting the priority of each runnable background
-thread, rescheduling it, and lowering the priority again.
-On 100 MHz Pentium + NT this overhead may be of the order 100
-microseconds per thread. So, if the number of runnable background
-threads is not very big, say < 100, the cost is tolerable.
-Utility threads probably will access resources used by
-user threads not very often, so collisions of user threads
-to preempted utility threads should not happen very often.
-
-The thread table contains
-information of the current status of each thread existing in the system,
-and also the event semaphores used in suspending the master thread
-and utility and parallel communication threads when they have nothing to do.
-The thread table can be seen as an analogue to the process table
-in a traditional Unix implementation.
-
-The thread table is also used in the global priority inheritance
-scheme. This brings in one additional complication: threads accessing
-the thread table must have at least normal fixed priority,
-because the priority inheritance solution does not work if a background
-thread is preempted while possessing the mutex protecting the thread table.
-So, if a thread accesses the thread table, its priority has to be
-boosted at least to normal. This priority requirement can be seen similar to
-the privileged mode used when processing the kernel calls in traditional
-Unix.*/
-
-/* Thread slot in the thread table */
-struct srv_slot_struct{
- unsigned type:1; /*!< thread type: user, utility etc. */
- unsigned in_use:1; /*!< TRUE if this slot is in use */
- unsigned suspended:1; /*!< TRUE if the thread is waiting
- for the event of this slot */
- ib_time_t suspend_time; /*!< time when the thread was
- suspended */
- os_event_t event; /*!< event used in suspending the
- thread when it has nothing to do */
- que_thr_t* thr; /*!< suspended query thread (only
- used for MySQL threads) */
-};
-
-/* Table for MySQL threads where they will be suspended to wait for locks */
-UNIV_INTERN srv_slot_t* srv_mysql_table = NULL;
-
-UNIV_INTERN os_event_t srv_timeout_event;
-
-UNIV_INTERN os_event_t srv_monitor_event;
-
-UNIV_INTERN os_event_t srv_error_event;
-
-UNIV_INTERN os_event_t srv_lock_timeout_thread_event;
-
-UNIV_INTERN os_event_t srv_shutdown_event;
-
-UNIV_INTERN os_event_t srv_checkpoint_completed_event;
-
-UNIV_INTERN os_event_t srv_redo_log_thread_finished_event;
-
-UNIV_INTERN srv_sys_t* srv_sys = NULL;
-
-/* padding to prevent other memory update hotspots from residing on
-the same memory cache line */
-UNIV_INTERN byte srv_pad1[64];
-/* mutex protecting the server, trx structs, query threads, and lock table */
-UNIV_INTERN mutex_t* kernel_mutex_temp;
-/* padding to prevent other memory update hotspots from residing on
-the same memory cache line */
-UNIV_INTERN byte srv_pad2[64];
-
-#if 0
-/* The following three values measure the urgency of the jobs of
-buffer, version, and insert threads. They may vary from 0 - 1000.
-The server mutex protects all these variables. The low-water values
-tell that the server can acquiesce the utility when the value
-drops below this low-water mark. */
-
-static ulint srv_meter[SRV_MASTER + 1];
-static ulint srv_meter_low_water[SRV_MASTER + 1];
-static ulint srv_meter_high_water[SRV_MASTER + 1];
-static ulint srv_meter_high_water2[SRV_MASTER + 1];
-static ulint srv_meter_foreground[SRV_MASTER + 1];
-#endif
-
-/* The following values give info about the activity going on in
-the database. They are protected by the server mutex. The arrays
-are indexed by the type of the thread. */
-
-UNIV_INTERN ulint srv_n_threads_active[SRV_MASTER + 1];
-UNIV_INTERN ulint srv_n_threads[SRV_MASTER + 1];
-
-/*********************************************************************//**
-Asynchronous purge thread.
-@return a dummy parameter */
-UNIV_INTERN
-os_thread_ret_t
-srv_purge_thread(
-/*=============*/
- void* arg __attribute__((unused))); /*!< in: a dummy parameter
- required by os_thread_create */
-
-/***********************************************************************
-Prints counters for work done by srv_master_thread. */
-static
-void
-srv_print_master_thread_info(
-/*=========================*/
- FILE *file) /* in: output stream */
-{
- fprintf(file, "srv_master_thread loops: %lu 1_second, %lu sleeps, "
- "%lu 10_second, %lu background, %lu flush\n",
- srv_main_1_second_loops, srv_main_sleeps,
- srv_main_10_second_loops, srv_main_background_loops,
- srv_main_flush_loops);
- fprintf(file, "srv_master_thread log flush and writes: %lu\n",
- srv_log_writes_and_flush);
-}
-
-/*********************************************************************//**
-Sets the info describing an i/o thread current state. */
-UNIV_INTERN
-void
-srv_set_io_thread_op_info(
-/*======================*/
- ulint i, /*!< in: the 'segment' of the i/o thread */
- const char* str) /*!< in: constant char string describing the
- state */
-{
- ut_a(i < SRV_MAX_N_IO_THREADS);
-
- srv_io_thread_op_info[i] = str;
-}
-
-/*********************************************************************//**
-Accessor function to get pointer to n'th slot in the server thread
-table.
-@return pointer to the slot */
-static
-srv_slot_t*
-srv_table_get_nth_slot(
-/*===================*/
- ulint index) /*!< in: index of the slot */
-{
- ut_ad(mutex_own(&kernel_mutex));
- ut_a(index < OS_THREAD_MAX_N);
-
- return(srv_sys->threads + index);
-}
-
-/*********************************************************************//**
-Gets the number of threads in the system.
-@return sum of srv_n_threads[] */
-UNIV_INTERN
-ulint
-srv_get_n_threads(void)
-/*===================*/
-{
- ulint i;
- ulint n_threads = 0;
-
- mutex_enter(&kernel_mutex);
-
- for (i = 0; i < SRV_MASTER + 1; i++) {
-
- n_threads += srv_n_threads[i];
- }
-
- mutex_exit(&kernel_mutex);
-
- return(n_threads);
-}
-
-#ifdef UNIV_DEBUG
-/*********************************************************************//**
-Validates the type of a thread table slot.
-@return TRUE if ok */
-static
-ibool
-srv_thread_type_validate(
-/*=====================*/
- enum srv_thread_type type) /*!< in: thread type */
-{
- switch (type) {
- case SRV_WORKER:
- case SRV_MASTER:
- return(TRUE);
- }
- ut_error;
- return(FALSE);
-}
-#endif /* UNIV_DEBUG */
-
-/*********************************************************************//**
-Gets the type of a thread table slot.
-@return thread type */
-static
-enum srv_thread_type
-srv_slot_get_type(
-/*==============*/
- const srv_slot_t* slot) /*!< in: thread slot */
-{
- enum srv_thread_type type = (enum srv_thread_type) slot->type;
- ut_ad(srv_thread_type_validate(type));
- return(type);
-}
-
-/*********************************************************************//**
-Reserves a slot in the thread table for the current thread.
-NOTE! The server mutex has to be reserved by the caller!
-@return reserved slot */
-static
-srv_slot_t*
-srv_table_reserve_slot(
-/*===================*/
- enum srv_thread_type type) /*!< in: type of the thread */
-{
- srv_slot_t* slot;
- ulint i;
-
- ut_ad(srv_thread_type_validate(type));
- ut_ad(mutex_own(&kernel_mutex));
-
- i = 0;
- slot = srv_table_get_nth_slot(i);
-
- while (slot->in_use) {
- i++;
- slot = srv_table_get_nth_slot(i);
- }
-
- slot->in_use = TRUE;
- slot->suspended = FALSE;
- slot->type = type;
- ut_ad(srv_slot_get_type(slot) == type);
-
- return(slot);
-}
-
-/*********************************************************************//**
-Suspends the calling thread to wait for the event in its thread slot.
-NOTE! The server mutex has to be reserved by the caller! */
-static
-void
-srv_suspend_thread(
-/*===============*/
- srv_slot_t* slot) /*!< in/out: thread slot */
-{
- enum srv_thread_type type;
-
- ut_ad(mutex_own(&kernel_mutex));
- ut_ad(slot->in_use);
- ut_ad(!slot->suspended);
-
- if (srv_print_thread_releases) {
- fprintf(stderr,
- "Suspending thread %lu to slot %lu\n",
- (ulong) os_thread_get_curr_id(),
- (ulong) (slot - srv_sys->threads));
- }
-
- type = srv_slot_get_type(slot);
-
- slot->suspended = TRUE;
-
- ut_ad(srv_n_threads_active[type] > 0);
-
- srv_n_threads_active[type]--;
-
- os_event_reset(slot->event);
-}
-
-/*********************************************************************//**
-Releases threads of the type given from suspension in the thread table.
-NOTE! The server mutex has to be reserved by the caller!
-@return number of threads released: this may be less than n if not
-enough threads were suspended at the moment */
-UNIV_INTERN
-ulint
-srv_release_threads(
-/*================*/
- enum srv_thread_type type, /*!< in: thread type */
- ulint n) /*!< in: number of threads to release */
-{
- srv_slot_t* slot;
- ulint i;
- ulint count = 0;
-
- ut_ad(srv_thread_type_validate(type));
- ut_ad(n > 0);
- ut_ad(mutex_own(&kernel_mutex));
-
- for (i = 0; i < OS_THREAD_MAX_N; i++) {
-
- slot = srv_table_get_nth_slot(i);
-
- if (slot->in_use && slot->suspended
- && srv_slot_get_type(slot) == type) {
-
- slot->suspended = FALSE;
-
- srv_n_threads_active[type]++;
-
- os_event_set(slot->event);
-
- if (srv_print_thread_releases) {
- fprintf(stderr,
- "Releasing thread type %lu"
- " from slot %lu\n",
- (ulong) type, (ulong) i);
- }
-
- count++;
-
- if (count == n) {
- break;
- }
- }
- }
-
- return(count);
-}
-
-/*********************************************************************//**
-Check whether thread type has reserved a slot. Return the first slot that
-is found. This works because we currently have only 1 thread of each type.
-@return slot number or ULINT_UNDEFINED if not found*/
-UNIV_INTERN
-ulint
-srv_thread_has_reserved_slot(
-/*=========================*/
- enum srv_thread_type type) /*!< in: thread type to check */
-{
- ulint i;
- ulint slot_no = ULINT_UNDEFINED;
-
- ut_ad(srv_thread_type_validate(type));
- mutex_enter(&kernel_mutex);
-
- for (i = 0; i < OS_THREAD_MAX_N; i++) {
- srv_slot_t* slot;
-
- slot = srv_table_get_nth_slot(i);
-
- if (slot->in_use && slot->type == type) {
- slot_no = i;
- break;
- }
- }
-
- mutex_exit(&kernel_mutex);
-
- return(slot_no);
-}
-
-/*********************************************************************//**
-Initializes the server. */
-UNIV_INTERN
-void
-srv_init(void)
-/*==========*/
-{
- srv_conc_slot_t* conc_slot;
- srv_slot_t* slot;
- ulint i;
-
- srv_sys = mem_alloc(sizeof(srv_sys_t));
-
- kernel_mutex_temp = mem_alloc(sizeof(mutex_t));
- mutex_create(kernel_mutex_key, &kernel_mutex, SYNC_KERNEL);
-
- mutex_create(srv_innodb_monitor_mutex_key,
- &srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
-
- srv_sys->threads = mem_zalloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
-
- for (i = 0; i < OS_THREAD_MAX_N; i++) {
- slot = srv_sys->threads + i;
- slot->event = os_event_create(NULL);
- ut_a(slot->event);
- }
-
- srv_mysql_table = mem_zalloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
-
- for (i = 0; i < OS_THREAD_MAX_N; i++) {
- slot = srv_mysql_table + i;
- slot->event = os_event_create(NULL);
- ut_a(slot->event);
- }
-
- srv_error_event = os_event_create(NULL);
-
- srv_timeout_event = os_event_create(NULL);
-
- srv_monitor_event = os_event_create(NULL);
-
- srv_lock_timeout_thread_event = os_event_create(NULL);
- srv_shutdown_event = os_event_create(NULL);
-
- srv_checkpoint_completed_event = os_event_create(NULL);
- srv_redo_log_thread_finished_event = os_event_create(NULL);
-
- for (i = 0; i < SRV_MASTER + 1; i++) {
- srv_n_threads_active[i] = 0;
- srv_n_threads[i] = 0;
-#if 0
- srv_meter[i] = 30;
- srv_meter_low_water[i] = 50;
- srv_meter_high_water[i] = 100;
- srv_meter_high_water2[i] = 200;
- srv_meter_foreground[i] = 250;
-#endif
- }
-
- UT_LIST_INIT(srv_sys->tasks);
-
- /* Create dummy indexes for infimum and supremum records */
-
- dict_ind_init();
-
- /* Init the server concurrency restriction data structures */
-
- os_fast_mutex_init(&srv_conc_mutex);
-
- UT_LIST_INIT(srv_conc_queue);
-
- srv_conc_slots = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_conc_slot_t));
-
- for (i = 0; i < OS_THREAD_MAX_N; i++) {
- conc_slot = srv_conc_slots + i;
- conc_slot->reserved = FALSE;
- conc_slot->event = os_event_create(NULL);
- ut_a(conc_slot->event);
- }
-
- /* Initialize some INFORMATION SCHEMA internal structures */
- trx_i_s_cache_init(trx_i_s_cache);
-}
-
-/*********************************************************************//**
-Frees the data structures created in srv_init(). */
-UNIV_INTERN
-void
-srv_free(void)
-/*==========*/
-{
- os_fast_mutex_free(&srv_conc_mutex);
- mem_free(srv_conc_slots);
- srv_conc_slots = NULL;
-
- mem_free(srv_sys->threads);
- mem_free(srv_sys);
- srv_sys = NULL;
-
- mem_free(kernel_mutex_temp);
- kernel_mutex_temp = NULL;
- mem_free(srv_mysql_table);
- srv_mysql_table = NULL;
-
- trx_i_s_cache_free(trx_i_s_cache);
-}
-
-/*********************************************************************//**
-Initializes the synchronization primitives, memory system, and the thread
-local storage. */
-UNIV_INTERN
-void
-srv_general_init(void)
-/*==================*/
-{
- ut_mem_init();
- /* Reset the system variables in the recovery module. */
- recv_sys_var_init();
- os_sync_init();
- sync_init();
- mem_init(srv_mem_pool_size);
-}
-
-/*======================= InnoDB Server FIFO queue =======================*/
-
-/* Maximum allowable purge history length. <=0 means 'infinite'. */
-UNIV_INTERN ulong srv_max_purge_lag = 0;
-
-/*********************************************************************//**
-Puts an OS thread to wait if there are too many concurrent threads
-(>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
-
-#ifdef HAVE_ATOMIC_BUILTINS
-static void
-enter_innodb_with_tickets(trx_t* trx)
-{
- trx->declared_to_be_inside_innodb = TRUE;
- trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
- return;
-}
-
-static void
-srv_conc_enter_innodb_timer_based(trx_t* trx)
-{
- lint conc_n_threads;
- ibool has_yielded = FALSE;
- ulint has_slept = 0;
-
- if (trx->declared_to_be_inside_innodb) {
- ut_print_timestamp(stderr);
- fputs(
-" InnoDB: Error: trying to declare trx to enter InnoDB, but\n"
-"InnoDB: it already is declared.\n", stderr);
- trx_print(stderr, trx, 0);
- putc('\n', stderr);
- }
-retry:
- if (srv_conc_n_threads < (lint) srv_thread_concurrency) {
- conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1);
- if (conc_n_threads <= (lint) srv_thread_concurrency) {
- enter_innodb_with_tickets(trx);
- return;
- }
- (void) os_atomic_increment_lint(&srv_conc_n_threads, -1);
- }
- if (!has_yielded)
- {
- has_yielded = TRUE;
- os_thread_yield();
- goto retry;
- }
-
- ut_ad(!trx->has_search_latch);
-
- if (NULL != UT_LIST_GET_FIRST(trx->trx_locks)) {
-
- conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1);
- enter_innodb_with_tickets(trx);
- return;
- }
- if (has_slept < 2)
- {
- trx->op_info = "sleeping before entering InnoDB";
- os_thread_sleep(10000);
- trx->op_info = "";
- has_slept++;
- }
- conc_n_threads = os_atomic_increment_lint(&srv_conc_n_threads, 1);
- enter_innodb_with_tickets(trx);
- return;
-}
-
-static void
-srv_conc_exit_innodb_timer_based(trx_t* trx)
-{
- (void) os_atomic_increment_lint(&srv_conc_n_threads, -1);
- trx->declared_to_be_inside_innodb = FALSE;
- trx->n_tickets_to_enter_innodb = 0;
- return;
-}
-#endif
-
-UNIV_INTERN
-void
-srv_conc_enter_innodb(
-/*==================*/
- trx_t* trx) /*!< in: transaction object associated with the
- thread */
-{
- ibool has_slept = FALSE;
- srv_conc_slot_t* slot = NULL;
- ulint i;
- ib_uint64_t start_time = 0L;
- ib_uint64_t finish_time = 0L;
- ulint sec;
- ulint ms;
-
- ut_ad(!trx->has_search_latch);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(!btr_search_own_any());
- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
-#endif /* UNIV_SYNC_DEBUG */
-
- if (trx->mysql_thd != NULL
- && thd_is_replication_slave_thread(trx->mysql_thd)) {
-
- UT_WAIT_FOR(srv_conc_n_threads
- < (lint)srv_thread_concurrency,
- srv_replication_delay * 1000);
-
- return;
- }
-
- /* If trx has 'free tickets' to enter the engine left, then use one
- such ticket */
-
- if (trx->n_tickets_to_enter_innodb > 0) {
- trx->n_tickets_to_enter_innodb--;
-
- return;
- }
-
-#ifdef HAVE_ATOMIC_BUILTINS
- if (srv_thread_concurrency_timer_based) {
- srv_conc_enter_innodb_timer_based(trx);
- return;
- }
-#endif
-
- os_fast_mutex_lock(&srv_conc_mutex);
-retry:
- if (trx->declared_to_be_inside_innodb) {
- ut_print_timestamp(stderr);
- fputs(" InnoDB: Error: trying to declare trx"
- " to enter InnoDB, but\n"
- "InnoDB: it already is declared.\n", stderr);
- trx_print(stderr, trx, 0);
- putc('\n', stderr);
- os_fast_mutex_unlock(&srv_conc_mutex);
-
- return;
- }
-
- ut_ad(srv_conc_n_threads >= 0);
-
- if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
-
- srv_conc_n_threads++;
- trx->declared_to_be_inside_innodb = TRUE;
- trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
-
- os_fast_mutex_unlock(&srv_conc_mutex);
-
- return;
- }
-
- /* If the transaction is not holding resources, let it sleep
- for SRV_THREAD_SLEEP_DELAY microseconds, and try again then */
-
- ut_ad(!trx->has_search_latch);
-
- if (!has_slept
- && NULL == UT_LIST_GET_FIRST(trx->trx_locks)) {
-
- has_slept = TRUE; /* We let it sleep only once to avoid
- starvation */
-
- srv_conc_n_waiting_threads++;
-
- os_fast_mutex_unlock(&srv_conc_mutex);
-
- trx->op_info = "sleeping before joining InnoDB queue";
-
- /* Peter Zaitsev suggested that we take the sleep away
- altogether. But the sleep may be good in pathological
- situations of lots of thread switches. Simply put some
- threads aside for a while to reduce the number of thread
- switches. */
- if (SRV_THREAD_SLEEP_DELAY > 0) {
- os_thread_sleep(SRV_THREAD_SLEEP_DELAY);
- trx->innodb_que_wait_timer += SRV_THREAD_SLEEP_DELAY;
- }
-
- trx->op_info = "";
-
- os_fast_mutex_lock(&srv_conc_mutex);
-
- srv_conc_n_waiting_threads--;
-
- goto retry;
- }
-
- /* Too many threads inside: put the current thread to a queue */
-
- for (i = 0; i < OS_THREAD_MAX_N; i++) {
- slot = srv_conc_slots + i;
-
- if (!slot->reserved) {
-
- break;
- }
- }
-
- if (i == OS_THREAD_MAX_N) {
- /* Could not find a free wait slot, we must let the
- thread enter */
-
- srv_conc_n_threads++;
- trx->declared_to_be_inside_innodb = TRUE;
- trx->n_tickets_to_enter_innodb = 0;
-
- os_fast_mutex_unlock(&srv_conc_mutex);
-
- return;
- }
-
- /* No-op for XtraDB. */
- trx_search_latch_release_if_reserved(trx);
-
- /* Add to the queue */
- slot->reserved = TRUE;
- slot->wait_ended = FALSE;
-
- UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot);
-
- os_event_reset(slot->event);
-
- srv_conc_n_waiting_threads++;
-
- os_fast_mutex_unlock(&srv_conc_mutex);
-
- /* Go to wait for the event; when a thread leaves InnoDB it will
- release this thread */
-
- ut_ad(!trx->has_search_latch);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(!btr_search_own_any());
- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
-#endif /* UNIV_SYNC_DEBUG */
-
- if (UNIV_UNLIKELY(trx->take_stats)) {
- ut_usectime(&sec, &ms);
- start_time = (ib_uint64_t)sec * 1000000 + ms;
- } else {
- start_time = 0;
- }
-
- trx->op_info = "waiting in InnoDB queue";
-
- thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK);
- os_event_wait(slot->event);
- thd_wait_end(trx->mysql_thd);
-
- trx->op_info = "";
-
- if (UNIV_UNLIKELY(start_time != 0)) {
- ut_usectime(&sec, &ms);
- finish_time = (ib_uint64_t)sec * 1000000 + ms;
- trx->innodb_que_wait_timer += (ulint)(finish_time - start_time);
- }
-
- os_fast_mutex_lock(&srv_conc_mutex);
-
- srv_conc_n_waiting_threads--;
-
- /* NOTE that the thread which released this thread already
- incremented the thread counter on behalf of this thread */
-
- slot->reserved = FALSE;
-
- UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot);
-
- trx->declared_to_be_inside_innodb = TRUE;
- trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
-
- os_fast_mutex_unlock(&srv_conc_mutex);
-}
-
-/*********************************************************************//**
-This lets a thread enter InnoDB regardless of the number of threads inside
-InnoDB. This must be called when a thread ends a lock wait. */
-UNIV_INTERN
-void
-srv_conc_force_enter_innodb(
-/*========================*/
- trx_t* trx) /*!< in: transaction object associated with the
- thread */
-{
- ut_ad(!trx->has_search_latch);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(!btr_search_own_any());
- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
-#endif /* UNIV_SYNC_DEBUG */
-
- if (UNIV_LIKELY(!srv_thread_concurrency)) {
-
- return;
- }
-
- ut_ad(srv_conc_n_threads >= 0);
-#ifdef HAVE_ATOMIC_BUILTINS
- if (srv_thread_concurrency_timer_based) {
- (void) os_atomic_increment_lint(&srv_conc_n_threads, 1);
- trx->declared_to_be_inside_innodb = TRUE;
- trx->n_tickets_to_enter_innodb = 1;
- return;
- }
-#endif
-
- os_fast_mutex_lock(&srv_conc_mutex);
-
- srv_conc_n_threads++;
- trx->declared_to_be_inside_innodb = TRUE;
- trx->n_tickets_to_enter_innodb = 1;
-
- os_fast_mutex_unlock(&srv_conc_mutex);
-}
-
-/*********************************************************************//**
-This must be called when a thread exits InnoDB in a lock wait or at the
-end of an SQL statement. */
-UNIV_INTERN
-void
-srv_conc_force_exit_innodb(
-/*=======================*/
- trx_t* trx) /*!< in: transaction object associated with the
- thread */
-{
- srv_conc_slot_t* slot = NULL;
-
- if (trx->mysql_thd != NULL
- && thd_is_replication_slave_thread(trx->mysql_thd)) {
-
- return;
- }
-
- if (trx->declared_to_be_inside_innodb == FALSE) {
-
- return;
- }
-
-#ifdef HAVE_ATOMIC_BUILTINS
- if (srv_thread_concurrency_timer_based) {
- srv_conc_exit_innodb_timer_based(trx);
- return;
- }
-#endif
-
- os_fast_mutex_lock(&srv_conc_mutex);
-
- ut_ad(srv_conc_n_threads > 0);
- srv_conc_n_threads--;
- trx->declared_to_be_inside_innodb = FALSE;
- trx->n_tickets_to_enter_innodb = 0;
-
- if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
- /* Look for a slot where a thread is waiting and no other
- thread has yet released the thread */
-
- slot = UT_LIST_GET_FIRST(srv_conc_queue);
-
- while (slot && slot->wait_ended == TRUE) {
- slot = UT_LIST_GET_NEXT(srv_conc_queue, slot);
- }
-
- if (slot != NULL) {
- slot->wait_ended = TRUE;
-
- /* We increment the count on behalf of the released
- thread */
-
- srv_conc_n_threads++;
- }
- }
-
- os_fast_mutex_unlock(&srv_conc_mutex);
-
- if (slot != NULL) {
- os_event_set(slot->event);
- }
-
- ut_ad(!trx->has_search_latch);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(!btr_search_own_any());
- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
-#endif /* UNIV_SYNC_DEBUG */
-}
-
-/*********************************************************************//**
-This must be called when a thread exits InnoDB. */
-UNIV_INTERN
-void
-srv_conc_exit_innodb(
-/*=================*/
- trx_t* trx) /*!< in: transaction object associated with the
- thread */
-{
- ut_ad(!trx->has_search_latch);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(!btr_search_own_any());
- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
-#endif /* UNIV_SYNC_DEBUG */
-
- if (trx->n_tickets_to_enter_innodb > 0) {
- /* We will pretend the thread is still inside InnoDB though it
- now leaves the InnoDB engine. In this way we save
- a lot of semaphore operations. srv_conc_force_exit_innodb is
- used to declare the thread definitely outside InnoDB. It
- should be called when there is a lock wait or an SQL statement
- ends. */
-
- return;
- }
-
- srv_conc_force_exit_innodb(trx);
-}
-
-/*========================================================================*/
-
-/*********************************************************************//**
-Normalizes init parameter values to use units we use inside InnoDB.
-@return DB_SUCCESS or error code */
-static
-ulint
-srv_normalize_init_values(void)
-/*===========================*/
-{
- ulint n;
- ulint i;
-
- n = srv_n_data_files;
-
- for (i = 0; i < n; i++) {
- srv_data_file_sizes[i] = srv_data_file_sizes[i]
- * ((1024 * 1024) / UNIV_PAGE_SIZE);
- }
-
- srv_last_file_size_max = srv_last_file_size_max
- * ((1024 * 1024) / UNIV_PAGE_SIZE);
-
- srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE;
-
- srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
-
- srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
-
- return(DB_SUCCESS);
-}
-
-/*********************************************************************//**
-Boots the InnoDB server.
-@return DB_SUCCESS or error code */
-UNIV_INTERN
-ulint
-srv_boot(void)
-/*==========*/
-{
- ulint err;
-
- /* Transform the init parameter values given by MySQL to
- use units we use inside InnoDB: */
-
- err = srv_normalize_init_values();
-
- if (err != DB_SUCCESS) {
- return(err);
- }
-
- /* Initialize synchronization primitives, memory management, and thread
- local storage */
-
- srv_general_init();
-
- /* Initialize this module */
-
- srv_init();
-
- return(DB_SUCCESS);
-}
-
-/*********************************************************************//**
-Reserves a slot in the thread table for the current MySQL OS thread.
-NOTE! The kernel mutex has to be reserved by the caller!
-@return reserved slot */
-static
-srv_slot_t*
-srv_table_reserve_slot_for_mysql(void)
-/*==================================*/
-{
- srv_slot_t* slot;
- ulint i;
-
- ut_ad(mutex_own(&kernel_mutex));
-
- i = 0;
- slot = srv_mysql_table + i;
-
- while (slot->in_use) {
- i++;
-
- if (UNIV_UNLIKELY(i >= OS_THREAD_MAX_N)) {
-
- ut_print_timestamp(stderr);
-
- fprintf(stderr,
- " InnoDB: There appear to be %lu MySQL"
- " threads currently waiting\n"
- "InnoDB: inside InnoDB, which is the"
- " upper limit. Cannot continue operation.\n"
- "InnoDB: We intentionally generate"
- " a seg fault to print a stack trace\n"
- "InnoDB: on Linux. But first we print"
- " a list of waiting threads.\n", (ulong) i);
-
- for (i = 0; i < OS_THREAD_MAX_N; i++) {
-
- slot = srv_mysql_table + i;
-
- fprintf(stderr,
- "Slot %lu: thread type %lu,"
- " in use %lu, susp %lu, time %lu\n",
- (ulong) i,
- (ulong) slot->type,
- (ulong) slot->in_use,
- (ulong) slot->suspended,
- (ulong) difftime(ut_time(),
- slot->suspend_time));
- }
-
- ut_error;
- }
-
- slot = srv_mysql_table + i;
- }
-
- ut_a(slot->in_use == FALSE);
-
- slot->in_use = TRUE;
-
- return(slot);
-}
-
-/***************************************************************//**
-Puts a MySQL OS thread to wait for a lock to be released. If an error
-occurs during the wait trx->error_state associated with thr is
-!= DB_SUCCESS when we return. DB_LOCK_WAIT_TIMEOUT and DB_DEADLOCK
-are possible errors. DB_DEADLOCK is returned if selective deadlock
-resolution chose this transaction as a victim. */
-UNIV_INTERN
-void
-srv_suspend_mysql_thread(
-/*=====================*/
- que_thr_t* thr) /*!< in: query thread associated with the MySQL
- OS thread */
-{
- srv_slot_t* slot;
- os_event_t event;
- double wait_time;
- trx_t* trx;
- ulint had_dict_lock;
- ibool was_declared_inside_innodb = FALSE;
- ib_int64_t start_time = 0;
- ib_int64_t finish_time;
- ulint diff_time;
- ulint sec;
- ulint ms;
- ulong lock_wait_timeout;
-
- ut_ad(!mutex_own(&kernel_mutex));
-
- trx = thr_get_trx(thr);
-
- if (trx->mysql_thd != 0) {
- DEBUG_SYNC_C("srv_suspend_mysql_thread_enter");
- }
-
- os_event_set(srv_lock_timeout_thread_event);
-
- mutex_enter(&kernel_mutex);
-
- trx->error_state = DB_SUCCESS;
-
- if (thr->state == QUE_THR_RUNNING) {
-
- ut_ad(thr->is_active == TRUE);
-
- /* The lock has already been released or this transaction
- was chosen as a deadlock victim: no need to suspend */
-
- if (trx->was_chosen_as_deadlock_victim) {
-
- trx->error_state = DB_DEADLOCK;
- trx->was_chosen_as_deadlock_victim = FALSE;
- }
-
- mutex_exit(&kernel_mutex);
-
- return;
- }
-
- ut_ad(thr->is_active == FALSE);
-
- slot = srv_table_reserve_slot_for_mysql();
-
- event = slot->event;
-
- slot->thr = thr;
-
- os_event_reset(event);
-
- slot->suspend_time = ut_time();
-
- if (thr->lock_state == QUE_THR_LOCK_ROW) {
- srv_n_lock_wait_count++;
- srv_n_lock_wait_current_count++;
-
- if (ut_usectime(&sec, &ms) == -1) {
- start_time = -1;
- } else {
- start_time = (ib_int64_t) sec * 1000000 + ms;
- }
- }
- /* Wake the lock timeout monitor thread, if it is suspended */
-
- os_event_set(srv_lock_timeout_thread_event);
-
- mutex_exit(&kernel_mutex);
-
- had_dict_lock = trx->dict_operation_lock_mode;
-
- switch (had_dict_lock) {
- case RW_S_LATCH:
- /* Release foreign key check latch */
- row_mysql_unfreeze_data_dictionary(trx);
- break;
- case RW_X_LATCH:
- /* There should never be a lock wait when the
- dictionary latch is reserved in X mode. Dictionary
- transactions should only acquire locks on dictionary
- tables, not other tables. All access to dictionary
- tables should be covered by dictionary
- transactions. */
- ut_print_timestamp(stderr);
- fputs(" InnoDB: Error: dict X latch held in "
- "srv_suspend_mysql_thread\n", stderr);
- /* This should never occur. This incorrect handling
- was added in the early development of
- ha_innobase::add_index() in InnoDB Plugin 1.0. */
- /* Release fast index creation latch */
- row_mysql_unlock_data_dictionary(trx);
- break;
- }
-
- ut_a(trx->dict_operation_lock_mode == 0);
-
- if (trx->declared_to_be_inside_innodb) {
-
- was_declared_inside_innodb = TRUE;
-
- /* We must declare this OS thread to exit InnoDB, since a
- possible other thread holding a lock which this thread waits
- for must be allowed to enter, sooner or later */
-
- srv_conc_force_exit_innodb(trx);
- }
-
- /* Suspend this thread and wait for the event. */
-
- thd_wait_begin(trx->mysql_thd, THD_WAIT_ROW_LOCK);
- os_event_wait(event);
- thd_wait_end(trx->mysql_thd);
-
- ut_ad(!trx->has_search_latch);
-#ifdef UNIV_SYNC_DEBUG
- ut_ad(!btr_search_own_any());
- ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
-#endif /* UNIV_SYNC_DEBUG */
-
- if (was_declared_inside_innodb) {
-
- /* Return back inside InnoDB */
-
- srv_conc_force_enter_innodb(trx);
- }
-
- /* After resuming, reacquire the data dictionary latch if
- necessary. */
-
- switch (had_dict_lock) {
- case RW_S_LATCH:
- row_mysql_freeze_data_dictionary(trx);
- break;
- case RW_X_LATCH:
- /* This should never occur. This incorrect handling
- was added in the early development of
- ha_innobase::add_index() in InnoDB Plugin 1.0. */
- row_mysql_lock_data_dictionary(trx);
- break;
- }
-
- mutex_enter(&kernel_mutex);
-
- /* Release the slot for others to use */
-
- slot->in_use = FALSE;
-
- wait_time = ut_difftime(ut_time(), slot->suspend_time);
-
- if (thr->lock_state == QUE_THR_LOCK_ROW) {
- if (ut_usectime(&sec, &ms) == -1) {
- finish_time = -1;
- } else {
- finish_time = (ib_int64_t) sec * 1000000 + ms;
- }
-
- diff_time = (finish_time > start_time) ?
- (ulint) (finish_time - start_time) : 0;
-
- srv_n_lock_wait_current_count--;
- srv_n_lock_wait_time = srv_n_lock_wait_time + diff_time;
- if (diff_time > srv_n_lock_max_wait_time &&
- /* only update the variable if we successfully
- retrieved the start and finish times. See Bug#36819. */
- start_time != -1 && finish_time != -1) {
- srv_n_lock_max_wait_time = diff_time;
- }
-
- /* Record the lock wait time for this thread */
- thd_set_lock_wait_time(trx->mysql_thd, diff_time);
- }
-
- if (trx->was_chosen_as_deadlock_victim) {
-
- trx->error_state = DB_DEADLOCK;
- trx->was_chosen_as_deadlock_victim = FALSE;
- }
-
- mutex_exit(&kernel_mutex);
-
- /* InnoDB system transactions (such as the purge, and
- incomplete transactions that are being rolled back after crash
- recovery) will use the global value of
- innodb_lock_wait_timeout, because trx->mysql_thd == NULL. */
- lock_wait_timeout = thd_lock_wait_timeout(trx->mysql_thd);
-
- if (lock_wait_timeout < 100000000
- && wait_time > (double) lock_wait_timeout) {
-
- trx->error_state = DB_LOCK_WAIT_TIMEOUT;
- }
-
- if (trx_is_interrupted(trx)) {
-
- trx->error_state = DB_INTERRUPTED;
- }
-}
-
-/********************************************************************//**
-Releases a MySQL OS thread waiting for a lock to be released, if the
-thread is already suspended. */
-UNIV_INTERN
-void
-srv_release_mysql_thread_if_suspended(
-/*==================================*/
- que_thr_t* thr) /*!< in: query thread associated with the
- MySQL OS thread */
-{
- srv_slot_t* slot;
- ulint i;
-
- ut_ad(mutex_own(&kernel_mutex));
-
- for (i = 0; i < OS_THREAD_MAX_N; i++) {
-
- slot = srv_mysql_table + i;
-
- if (slot->in_use && slot->thr == thr) {
- /* Found */
-
- os_event_set(slot->event);
-
- return;
- }
- }
-
- /* not found */
-}
-
-/******************************************************************//**
-Refreshes the values used to calculate per-second averages. */
-static
-void
-srv_refresh_innodb_monitor_stats(void)
-/*==================================*/
-{
- mutex_enter(&srv_innodb_monitor_mutex);
-
- srv_last_monitor_time = time(NULL);
-
- os_aio_refresh_stats();
-
- btr_cur_n_sea_old = btr_cur_n_sea;
- btr_cur_n_non_sea_old = btr_cur_n_non_sea;
-
- log_refresh_stats();
-
- buf_refresh_io_stats_all();
-
- srv_n_rows_inserted_old = srv_n_rows_inserted;
- srv_n_rows_updated_old = srv_n_rows_updated;
- srv_n_rows_deleted_old = srv_n_rows_deleted;
- srv_n_rows_read_old = srv_n_rows_read;
-
- mutex_exit(&srv_innodb_monitor_mutex);
-}
-
-/******************************************************************//**
-Outputs to a file the output of the InnoDB Monitor.
-@return FALSE if not all information printed
-due to failure to obtain necessary mutex */
-UNIV_INTERN
-ibool
-srv_printf_innodb_monitor(
-/*======================*/
- FILE* file, /*!< in: output stream */
- ibool nowait, /*!< in: whether to wait for kernel mutex */
- ulint* trx_start, /*!< out: file position of the start of
- the list of active transactions */
- ulint* trx_end) /*!< out: file position of the end of
- the list of active transactions */
-{
- double time_elapsed;
- time_t current_time;
- ulint n_reserved;
- ibool ret;
-
- ulong btr_search_sys_constant;
- ulong btr_search_sys_variable;
- ulint lock_sys_subtotal;
- ulint recv_sys_subtotal;
-
- ulint i;
- trx_t* trx;
-
- mutex_enter(&srv_innodb_monitor_mutex);
-
- current_time = time(NULL);
-
- /* We add 0.001 seconds to time_elapsed to prevent division
- by zero if two users happen to call SHOW INNODB STATUS at the same
- time */
-
- time_elapsed = difftime(current_time, srv_last_monitor_time)
- + 0.001;
-
- srv_last_monitor_time = time(NULL);
-
- fputs("\n=====================================\n", file);
-
- ut_print_timestamp(file);
- fprintf(file,
- " INNODB MONITOR OUTPUT\n"
- "=====================================\n"
- "Per second averages calculated from the last %lu seconds\n",
- (ulong)time_elapsed);
-
- fputs("-----------------\n"
- "BACKGROUND THREAD\n"
- "-----------------\n", file);
- srv_print_master_thread_info(file);
-
- fputs("----------\n"
- "SEMAPHORES\n"
- "----------\n", file);
- sync_print(file);
-
- /* Conceptually, srv_innodb_monitor_mutex has a very high latching
- order level in sync0sync.h, while dict_foreign_err_mutex has a very
- low level 135. Therefore we can reserve the latter mutex here without
- a danger of a deadlock of threads. */
-
- mutex_enter(&dict_foreign_err_mutex);
-
- if (ftell(dict_foreign_err_file) != 0L) {
- fputs("------------------------\n"
- "LATEST FOREIGN KEY ERROR\n"
- "------------------------\n", file);
- ut_copy_file(file, dict_foreign_err_file);
- }
-
- mutex_exit(&dict_foreign_err_mutex);
-
- fputs("--------\n"
- "FILE I/O\n"
- "--------\n", file);
- os_aio_print(file);
-
- fputs("-------------------------------------\n"
- "INSERT BUFFER AND ADAPTIVE HASH INDEX\n"
- "-------------------------------------\n", file);
- ibuf_print(file);
-
- for (i = 0; i < btr_search_index_num; i++) {
- ha_print_info(file, btr_search_sys->hash_tables[i]);
- }
-
- fprintf(file,
- "%.2f hash searches/s, %.2f non-hash searches/s\n",
- (btr_cur_n_sea - btr_cur_n_sea_old)
- / time_elapsed,
- (btr_cur_n_non_sea - btr_cur_n_non_sea_old)
- / time_elapsed);
- btr_cur_n_sea_old = btr_cur_n_sea;
- btr_cur_n_non_sea_old = btr_cur_n_non_sea;
-
- fputs("---\n"
- "LOG\n"
- "---\n", file);
- log_print(file);
-
- fputs("----------------------\n"
- "BUFFER POOL AND MEMORY\n"
- "----------------------\n", file);
- fprintf(file,
- "Total memory allocated " ULINTPF
- "; in additional pool allocated " ULINTPF "\n",
- ut_total_allocated_memory,
- mem_pool_get_reserved(mem_comm_pool));
- fprintf(file,
- "Total memory allocated by read views " ULINTPF "\n",
- srv_read_views_memory);
-
- /* Calculate AHI constant and variable memory allocations */
-
- btr_search_sys_constant = 0;
- btr_search_sys_variable = 0;
-
- ut_ad(btr_search_sys->hash_tables);
-
- for (i = 0; i < btr_search_index_num; i++) {
- hash_table_t* ht = btr_search_sys->hash_tables[i];
-
- ut_ad(ht);
- ut_ad(ht->heap);
-
- /* Multiple mutexes/heaps are currently never used for adaptive
- hash index tables. */
- ut_ad(!ht->n_mutexes);
- ut_ad(!ht->heaps);
-
- btr_search_sys_variable += mem_heap_get_size(ht->heap);
- btr_search_sys_constant += ht->n_cells * sizeof(hash_cell_t);
- }
-
- lock_sys_subtotal = 0;
- if (trx_sys) {
- mutex_enter(&kernel_mutex);
- trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
- while (trx) {
- lock_sys_subtotal += ((trx->lock_heap) ? mem_heap_get_size(trx->lock_heap) : 0);
- trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
- }
- mutex_exit(&kernel_mutex);
- }
-
- recv_sys_subtotal = ((recv_sys && recv_sys->addr_hash)
- ? mem_heap_get_size(recv_sys->heap) : 0);
-
- fprintf(file,
- "Internal hash tables (constant factor + variable factor)\n"
- " Adaptive hash index %lu \t(%lu + %lu)\n"
- " Page hash %lu (buffer pool 0 only)\n"
- " Dictionary cache %lu \t(%lu + %lu)\n"
- " File system %lu \t(%lu + %lu)\n"
- " Lock system %lu \t(%lu + %lu)\n"
- " Recovery system %lu \t(%lu + %lu)\n",
-
- btr_search_sys_constant + btr_search_sys_variable,
- btr_search_sys_constant,
- btr_search_sys_variable,
-
- (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t)),
-
- (ulong) (dict_sys ? ((dict_sys->table_hash->n_cells
- + dict_sys->table_id_hash->n_cells
- ) * sizeof(hash_cell_t)
- + dict_sys->size) : 0),
- (ulong) (dict_sys ? ((dict_sys->table_hash->n_cells
- + dict_sys->table_id_hash->n_cells
- ) * sizeof(hash_cell_t)) : 0),
- (ulong) (dict_sys ? (dict_sys->size) : 0),
-
- (ulong) (fil_system_hash_cells() * sizeof(hash_cell_t)
- + fil_system_hash_nodes()),
- (ulong) (fil_system_hash_cells() * sizeof(hash_cell_t)),
- (ulong) fil_system_hash_nodes(),
-
- (ulong) ((lock_sys ? (lock_sys->rec_hash->n_cells * sizeof(hash_cell_t)) : 0)
- + lock_sys_subtotal),
- (ulong) (lock_sys ? (lock_sys->rec_hash->n_cells * sizeof(hash_cell_t)) : 0),
- (ulong) lock_sys_subtotal,
-
- (ulong) (((recv_sys && recv_sys->addr_hash)
- ? (recv_sys->addr_hash->n_cells * sizeof(hash_cell_t)) : 0)
- + recv_sys_subtotal),
- (ulong) ((recv_sys && recv_sys->addr_hash)
- ? (recv_sys->addr_hash->n_cells * sizeof(hash_cell_t)) : 0),
- (ulong) recv_sys_subtotal);
-
- fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
- dict_sys->size);
-
- buf_print_io(file);
-
- fputs("--------------\n"
- "ROW OPERATIONS\n"
- "--------------\n", file);
- fprintf(file, "%ld queries inside InnoDB, %lu queries in queue\n",
- (long) srv_conc_n_threads,
- (ulong) srv_conc_n_waiting_threads);
-
- mutex_enter(&kernel_mutex);
-
- fprintf(file, "%lu read views open inside InnoDB\n",
- UT_LIST_GET_LEN(trx_sys->view_list));
-
- fprintf(file, "%lu transactions active inside InnoDB\n",
- UT_LIST_GET_LEN(trx_sys->trx_list));
-
- fprintf(file, "%lu out of %lu descriptors used\n",
- trx_sys->descr_n_used, trx_sys->descr_n_max);
-
- if (UT_LIST_GET_LEN(trx_sys->view_list)) {
- read_view_t* view = UT_LIST_GET_LAST(trx_sys->view_list);
-
- if (view) {
- fprintf(file, "---OLDEST VIEW---\n");
- read_view_print(file, view);
- fprintf(file, "-----------------\n");
- }
- }
-
- mutex_exit(&kernel_mutex);
-
- n_reserved = fil_space_get_n_reserved_extents(0);
- if (n_reserved > 0) {
- fprintf(file,
- "%lu tablespace extents now reserved for"
- " B-tree split operations\n",
- (ulong) n_reserved);
- }
-
-#ifdef UNIV_LINUX
- fprintf(file, "Main thread process no. %lu, id %lu, state: %s\n",
- (ulong) srv_main_thread_process_no,
- (ulong) srv_main_thread_id,
- srv_main_thread_op_info);
-#else
- fprintf(file, "Main thread id %lu, state: %s\n",
- (ulong) srv_main_thread_id,
- srv_main_thread_op_info);
-#endif
- fprintf(file,
- "Number of rows inserted " ULINTPF
- ", updated " ULINTPF ", deleted " ULINTPF
- ", read " ULINTPF "\n",
- srv_n_rows_inserted,
- srv_n_rows_updated,
- srv_n_rows_deleted,
- srv_n_rows_read);
- fprintf(file,
- "%.2f inserts/s, %.2f updates/s,"
- " %.2f deletes/s, %.2f reads/s\n",
- (srv_n_rows_inserted - srv_n_rows_inserted_old)
- / time_elapsed,
- (srv_n_rows_updated - srv_n_rows_updated_old)
- / time_elapsed,
- (srv_n_rows_deleted - srv_n_rows_deleted_old)
- / time_elapsed,
- (srv_n_rows_read - srv_n_rows_read_old)
- / time_elapsed);
-
- srv_n_rows_inserted_old = srv_n_rows_inserted;
- srv_n_rows_updated_old = srv_n_rows_updated;
- srv_n_rows_deleted_old = srv_n_rows_deleted;
- srv_n_rows_read_old = srv_n_rows_read;
-
- /* Only if lock_print_info_summary proceeds correctly,
- before we call the lock_print_info_all_transactions
- to print all the lock information. */
- ret = lock_print_info_summary(file, nowait);
-
- if (ret) {
- if (trx_start) {
- long t = ftell(file);
- if (t < 0) {
- *trx_start = ULINT_UNDEFINED;
- } else {
- *trx_start = (ulint) t;
- }
- }
- lock_print_info_all_transactions(file);
- if (trx_end) {
- long t = ftell(file);
- if (t < 0) {
- *trx_end = ULINT_UNDEFINED;
- } else {
- *trx_end = (ulint) t;
- }
- }
- }
-
- fputs("----------------------------\n"
- "END OF INNODB MONITOR OUTPUT\n"
- "============================\n", file);
- mutex_exit(&srv_innodb_monitor_mutex);
- fflush(file);
-
- return(ret);
-}
-
-/******************************************************************//**
-Function to pass InnoDB status variables to MySQL */
-UNIV_INTERN
-void
-srv_export_innodb_status(void)
-/*==========================*/
-{
- buf_pool_stat_t stat;
- buf_pools_list_size_t buf_pools_list_size;
- ulint LRU_len;
- ulint free_len;
- ulint flush_list_len;
- ulint mem_adaptive_hash, mem_dictionary;
- read_view_t* oldest_view;
- ulint i;
-
- buf_get_total_stat(&stat);
- buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len);
- buf_get_total_list_size_in_bytes(&buf_pools_list_size);
-
- mem_adaptive_hash = 0;
-
- ut_ad(btr_search_sys->hash_tables);
-
- for (i = 0; i < btr_search_index_num; i++) {
- hash_table_t* ht = btr_search_sys->hash_tables[i];
-
- ut_ad(ht);
- ut_ad(ht->heap);
- /* Multiple mutexes/heaps are currently never used for adaptive
- hash index tables. */
- ut_ad(!ht->n_mutexes);
- ut_ad(!ht->heaps);
-
- mem_adaptive_hash += mem_heap_get_size(ht->heap);
- mem_adaptive_hash += ht->n_cells * sizeof(hash_cell_t);
- }
-
- mem_dictionary = (dict_sys ? ((dict_sys->table_hash->n_cells
- + dict_sys->table_id_hash->n_cells
- ) * sizeof(hash_cell_t)
- + dict_sys->size) : 0);
-
- mutex_enter(&srv_innodb_monitor_mutex);
-
- export_vars.innodb_adaptive_hash_cells = 0;
- export_vars.innodb_adaptive_hash_heap_buffers = 0;
- for (i = 0; i < btr_search_index_num; i++) {
- hash_table_t* table = btr_search_sys->hash_tables[i];
-
- export_vars.innodb_adaptive_hash_cells
- += hash_get_n_cells(table);
- export_vars.innodb_adaptive_hash_heap_buffers
- += (UT_LIST_GET_LEN(table->heap->base) - 1);
- }
- export_vars.innodb_adaptive_hash_hash_searches
- = btr_cur_n_sea;
- export_vars.innodb_adaptive_hash_non_hash_searches
- = btr_cur_n_non_sea;
- export_vars.innodb_background_log_sync
- = srv_log_writes_and_flush;
- export_vars.innodb_data_pending_reads
- = os_n_pending_reads;
- export_vars.innodb_data_pending_writes
- = os_n_pending_writes;
- export_vars.innodb_data_pending_fsyncs
- = fil_n_pending_log_flushes
- + fil_n_pending_tablespace_flushes;
- export_vars.innodb_data_fsyncs = os_n_fsyncs;
- export_vars.innodb_data_read = srv_data_read;
- export_vars.innodb_data_reads = os_n_file_reads;
- export_vars.innodb_data_writes = os_n_file_writes;
- export_vars.innodb_data_written = srv_data_written;
- export_vars.innodb_dict_tables= (dict_sys ? UT_LIST_GET_LEN(dict_sys->table_LRU) : 0);
- export_vars.innodb_buffer_pool_read_requests = stat.n_page_gets;
- export_vars.innodb_buffer_pool_write_requests
- = srv_buf_pool_write_requests;
- export_vars.innodb_buffer_pool_wait_free = srv_buf_pool_wait_free;
- export_vars.innodb_buffer_pool_pages_flushed = srv_buf_pool_flushed;
- export_vars.innodb_buffer_pool_pages_LRU_flushed = buf_lru_flush_page_count;
- export_vars.innodb_buffer_pool_reads = srv_buf_pool_reads;
- export_vars.innodb_buffer_pool_read_ahead_rnd
- = stat.n_ra_pages_read_rnd;
- export_vars.innodb_buffer_pool_read_ahead
- = stat.n_ra_pages_read;
- export_vars.innodb_buffer_pool_read_ahead_evicted
- = stat.n_ra_pages_evicted;
- export_vars.innodb_buffer_pool_pages_data = LRU_len;
- export_vars.innodb_buffer_pool_bytes_data =
- buf_pools_list_size.LRU_bytes
- + buf_pools_list_size.unzip_LRU_bytes;
- export_vars.innodb_buffer_pool_pages_dirty = flush_list_len;
- export_vars.innodb_buffer_pool_bytes_dirty =
- buf_pools_list_size.flush_list_bytes;
- export_vars.innodb_buffer_pool_pages_free = free_len;
- export_vars.innodb_deadlocks = srv_n_lock_deadlock_count;
-#ifdef UNIV_DEBUG
- export_vars.innodb_buffer_pool_pages_latched
- = buf_get_latched_pages_number();
-#endif /* UNIV_DEBUG */
- export_vars.innodb_buffer_pool_pages_total = buf_pool_get_n_pages();
-
- export_vars.innodb_buffer_pool_pages_misc
- = buf_pool_get_n_pages() - LRU_len - free_len;
-
- export_vars.innodb_buffer_pool_pages_made_young
- = stat.n_pages_made_young;
- export_vars.innodb_buffer_pool_pages_made_not_young
- = stat.n_pages_not_made_young;
- export_vars.innodb_buffer_pool_pages_old = 0;
- for (i = 0; i < srv_buf_pool_instances; i++) {
- buf_pool_t* buf_pool = buf_pool_from_array(i);
- export_vars.innodb_buffer_pool_pages_old
- += buf_pool->LRU_old_len;
- }
- export_vars.innodb_checkpoint_age
- = (log_sys->lsn - log_sys->last_checkpoint_lsn);
- export_vars.innodb_checkpoint_max_age
- = log_sys->max_checkpoint_age;
- export_vars.innodb_checkpoint_target_age
- = srv_checkpoint_age_target
- ? ut_min(log_sys->max_checkpoint_age_async, srv_checkpoint_age_target)
- : log_sys->max_checkpoint_age_async;
- export_vars.innodb_history_list_length
- = trx_sys->rseg_history_len;
- ibuf_export_ibuf_status(
- &export_vars.innodb_ibuf_size,
- &export_vars.innodb_ibuf_free_list,
- &export_vars.innodb_ibuf_segment_size,
- &export_vars.innodb_ibuf_merges,
- &export_vars.innodb_ibuf_merged_inserts,
- &export_vars.innodb_ibuf_merged_delete_marks,
- &export_vars.innodb_ibuf_merged_deletes,
- &export_vars.innodb_ibuf_discarded_inserts,
- &export_vars.innodb_ibuf_discarded_delete_marks,
- &export_vars.innodb_ibuf_discarded_deletes);
- export_vars.innodb_lsn_current
- = log_sys->lsn;
- export_vars.innodb_lsn_flushed
- = log_sys->flushed_to_disk_lsn;
- export_vars.innodb_lsn_last_checkpoint
- = log_sys->last_checkpoint_lsn;
- export_vars.innodb_master_thread_1_second_loops
- = srv_main_1_second_loops;
- export_vars.innodb_master_thread_10_second_loops
- = srv_main_10_second_loops;
- export_vars.innodb_master_thread_background_loops
- = srv_main_background_loops;
- export_vars.innodb_master_thread_main_flush_loops
- = srv_main_flush_loops;
- export_vars.innodb_master_thread_sleeps
- = srv_main_sleeps;
- export_vars.innodb_max_trx_id
- = trx_sys->max_trx_id;
- export_vars.innodb_mem_adaptive_hash
- = mem_adaptive_hash;
- export_vars.innodb_mem_dictionary
- = mem_dictionary;
- export_vars.innodb_mem_total
- = ut_total_allocated_memory;
- export_vars.innodb_mutex_os_waits
- = mutex_os_wait_count;
- export_vars.innodb_mutex_spin_rounds
- = mutex_spin_round_count;
- export_vars.innodb_mutex_spin_waits
- = mutex_spin_wait_count;
- export_vars.innodb_s_lock_os_waits
- = rw_s_os_wait_count;
- export_vars.innodb_s_lock_spin_rounds
- = rw_s_spin_round_count;
- export_vars.innodb_s_lock_spin_waits
- = rw_s_spin_wait_count;
- export_vars.innodb_x_lock_os_waits
- = rw_x_os_wait_count;
- export_vars.innodb_x_lock_spin_rounds
- = rw_x_spin_round_count;
- export_vars.innodb_x_lock_spin_waits
- = rw_x_spin_wait_count;
-
- oldest_view = UT_LIST_GET_LAST(trx_sys->view_list);
- export_vars.innodb_oldest_view_low_limit_trx_id
- = oldest_view ? oldest_view->low_limit_id : 0;
-
- export_vars.innodb_purge_trx_id
- = purge_sys->purge_trx_no;
- export_vars.innodb_purge_undo_no
- = purge_sys->purge_undo_no;
- export_vars.innodb_current_row_locks
- = lock_sys->rec_num;
-
-#ifdef HAVE_ATOMIC_BUILTINS
- export_vars.innodb_have_atomic_builtins = 1;
-#else
- export_vars.innodb_have_atomic_builtins = 0;
-#endif
- export_vars.innodb_page_size = UNIV_PAGE_SIZE;
- export_vars.innodb_log_waits = srv_log_waits;
- export_vars.innodb_os_log_written = srv_os_log_written;
- export_vars.innodb_os_log_fsyncs = fil_n_log_flushes;
- export_vars.innodb_os_log_pending_fsyncs = fil_n_pending_log_flushes;
- export_vars.innodb_os_log_pending_writes = srv_os_log_pending_writes;
- export_vars.innodb_log_write_requests = srv_log_write_requests;
- export_vars.innodb_log_writes = srv_log_writes;
- export_vars.innodb_dblwr_pages_written = srv_dblwr_pages_written;
- export_vars.innodb_dblwr_writes = srv_dblwr_writes;
- export_vars.innodb_pages_created = stat.n_pages_created;
- export_vars.innodb_pages_read = stat.n_pages_read;
- export_vars.innodb_pages_written = stat.n_pages_written;
- export_vars.innodb_row_lock_waits = srv_n_lock_wait_count;
- export_vars.innodb_row_lock_current_waits
- = srv_n_lock_wait_current_count;
- export_vars.innodb_row_lock_time = srv_n_lock_wait_time / 1000;
- if (srv_n_lock_wait_count > 0) {
- export_vars.innodb_row_lock_time_avg = (ulint)
- (srv_n_lock_wait_time / 1000 / srv_n_lock_wait_count);
- } else {
- export_vars.innodb_row_lock_time_avg = 0;
- }
- export_vars.innodb_row_lock_time_max
- = srv_n_lock_max_wait_time / 1000;
- export_vars.innodb_rows_read = srv_n_rows_read;
- export_vars.innodb_rows_inserted = srv_n_rows_inserted;
- export_vars.innodb_rows_updated = srv_n_rows_updated;
- export_vars.innodb_rows_deleted = srv_n_rows_deleted;
- export_vars.innodb_truncated_status_writes = srv_truncated_status_writes;
- export_vars.innodb_read_views_memory = srv_read_views_memory;
- export_vars.innodb_descriptors_memory = srv_descriptors_memory;
-
-#ifdef UNIV_DEBUG
- {
- trx_id_t done_trx_no;
- trx_id_t up_limit_id;
-
- rw_lock_s_lock(&purge_sys->latch);
- done_trx_no = purge_sys->done_trx_no;
- up_limit_id = purge_sys->view
- ? purge_sys->view->up_limit_id
- : 0;
- rw_lock_s_unlock(&purge_sys->latch);
-
- if (trx_sys->max_trx_id < done_trx_no) {
- export_vars.innodb_purge_trx_id_age = 0;
- } else {
- export_vars.innodb_purge_trx_id_age =
- trx_sys->max_trx_id - done_trx_no;
- }
-
- if (!up_limit_id
- || trx_sys->max_trx_id < up_limit_id) {
- export_vars.innodb_purge_view_trx_id_age = 0;
- } else {
- export_vars.innodb_purge_view_trx_id_age =
- trx_sys->max_trx_id - up_limit_id;
- }
- }
-#endif /* UNIV_DEBUG */
-
- mutex_exit(&srv_innodb_monitor_mutex);
-}
-
-/*********************************************************************//**
-A thread which prints the info output by various InnoDB monitors.
-@return a dummy parameter */
-UNIV_INTERN
-os_thread_ret_t
-srv_monitor_thread(
-/*===============*/
- void* arg __attribute__((unused)))
- /*!< in: a dummy parameter required by
- os_thread_create */
-{
- ib_int64_t sig_count;
- double time_elapsed;
- time_t current_time;
- time_t last_table_monitor_time;
- time_t last_tablespace_monitor_time;
- time_t last_monitor_time;
- ulint mutex_skipped;
- ibool last_srv_print_monitor;
-
-#ifdef UNIV_DEBUG_THREAD_CREATION
- fprintf(stderr, "Lock timeout thread starts, id %lu\n",
- os_thread_pf(os_thread_get_curr_id()));
-#endif
-
-#ifdef UNIV_PFS_THREAD
- pfs_register_thread(srv_monitor_thread_key);
-#endif
-
- UT_NOT_USED(arg);
- srv_last_monitor_time = ut_time();
- last_table_monitor_time = ut_time();
- last_tablespace_monitor_time = ut_time();
- last_monitor_time = ut_time();
- mutex_skipped = 0;
- last_srv_print_monitor = srv_print_innodb_monitor;
-loop:
- srv_monitor_active = TRUE;
-
- /* Wake up every 5 seconds to see if we need to print
- monitor information or if signalled at shutdown. */
-
- sig_count = os_event_reset(srv_monitor_event);
-
- os_event_wait_time_low(srv_monitor_event, 5000000, sig_count);
-
- current_time = ut_time();
-
- time_elapsed = difftime(current_time, last_monitor_time);
-
- if (time_elapsed > 15) {
- last_monitor_time = ut_time();
-
- if (srv_print_innodb_monitor) {
- /* Reset mutex_skipped counter everytime
- srv_print_innodb_monitor changes. This is to
- ensure we will not be blocked by kernel_mutex
- for short duration information printing,
- such as requested by sync_array_print_long_waits() */
- if (!last_srv_print_monitor) {
- mutex_skipped = 0;
- last_srv_print_monitor = TRUE;
- }
-
- if (!srv_printf_innodb_monitor(stderr,
- MUTEX_NOWAIT(mutex_skipped),
- NULL, NULL)) {
- mutex_skipped++;
- } else {
- /* Reset the counter */
- mutex_skipped = 0;
- }
- } else {
- last_srv_print_monitor = FALSE;
- }
-
-
- if (srv_innodb_status) {
- mutex_enter(&srv_monitor_file_mutex);
- rewind(srv_monitor_file);
- if (!srv_printf_innodb_monitor(srv_monitor_file,
- MUTEX_NOWAIT(mutex_skipped),
- NULL, NULL)) {
- mutex_skipped++;
- } else {
- mutex_skipped = 0;
- }
-
- os_file_set_eof(srv_monitor_file);
- mutex_exit(&srv_monitor_file_mutex);
- }
-
- if (srv_print_innodb_tablespace_monitor
- && difftime(current_time,
- last_tablespace_monitor_time) > 60) {
- last_tablespace_monitor_time = ut_time();
-
- fputs("========================"
- "========================\n",
- stderr);
-
- ut_print_timestamp(stderr);
-
- fputs(" INNODB TABLESPACE MONITOR OUTPUT\n"
- "========================"
- "========================\n",
- stderr);
-
- fsp_print(0);
- fputs("Validating tablespace\n", stderr);
- fsp_validate(0);
- fputs("Validation ok\n"
- "---------------------------------------\n"
- "END OF INNODB TABLESPACE MONITOR OUTPUT\n"
- "=======================================\n",
- stderr);
- }
-
- if (srv_print_innodb_table_monitor
- && difftime(current_time, last_table_monitor_time) > 60) {
-
- last_table_monitor_time = ut_time();
-
- fputs("===========================================\n",
- stderr);
-
- ut_print_timestamp(stderr);
-
- fputs(" INNODB TABLE MONITOR OUTPUT\n"
- "===========================================\n",
- stderr);
- dict_print();
-
- fputs("-----------------------------------\n"
- "END OF INNODB TABLE MONITOR OUTPUT\n"
- "==================================\n",
- stderr);
- }
- }
-
- if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
- goto exit_func;
- }
-
- if (srv_print_innodb_monitor
- || srv_print_innodb_lock_monitor
- || srv_print_innodb_tablespace_monitor
- || srv_print_innodb_table_monitor) {
- goto loop;
- }
-
- srv_monitor_active = FALSE;
-
- goto loop;
-
-exit_func:
- srv_monitor_active = FALSE;
-
- /* We count the number of threads in os_thread_exit(). A created
- thread should always use that to exit and not use return() to exit. */
-
- os_thread_exit(NULL);
-
- OS_THREAD_DUMMY_RETURN;
-}
-
-/*********************************************************************//**
-A thread which wakes up threads whose lock wait may have lasted too long.
-@return a dummy parameter */
-UNIV_INTERN
-os_thread_ret_t
-srv_lock_timeout_thread(
-/*====================*/
- void* arg __attribute__((unused)))
- /* in: a dummy parameter required by
- os_thread_create */
-{
- srv_slot_t* slot;
- ibool some_waits;
- double wait_time;
- ulint i;
- ib_int64_t sig_count;
-
-#ifdef UNIV_PFS_THREAD
- pfs_register_thread(srv_lock_timeout_thread_key);
-#endif
-
-loop:
-
- /* When someone is waiting for a lock, we wake up every second
- and check if a timeout has passed for a lock wait */
-
- sig_count = os_event_reset(srv_timeout_event);
-
- os_event_wait_time_low(srv_timeout_event, 1000000, sig_count);
-
- srv_lock_timeout_active = TRUE;
-
- mutex_enter(&kernel_mutex);
-
- some_waits = FALSE;
-
- /* Check of all slots if a thread is waiting there, and if it
- has exceeded the time limit */
-
- for (i = 0; i < OS_THREAD_MAX_N; i++) {
-
- slot = srv_mysql_table + i;
-
- if (slot->in_use) {
- trx_t* trx;
- ulong lock_wait_timeout;
-
- some_waits = TRUE;
-
- wait_time = ut_difftime(ut_time(), slot->suspend_time);
-
- trx = thr_get_trx(slot->thr);
- lock_wait_timeout = thd_lock_wait_timeout(
- trx->mysql_thd);
-
- if (trx_is_interrupted(trx)
- || (lock_wait_timeout < 100000000
- && (wait_time > (double) lock_wait_timeout
- || wait_time < 0))) {
-
- /* Timeout exceeded or a wrap-around in system
- time counter: cancel the lock request queued
- by the transaction and release possible
- other transactions waiting behind; it is
- possible that the lock has already been
- granted: in that case do nothing */
-
- if (trx->wait_lock) {
- lock_cancel_waiting_and_release(
- trx->wait_lock);
- }
- }
- }
- }
-
- os_event_reset(srv_lock_timeout_thread_event);
-
- mutex_exit(&kernel_mutex);
-
- if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
- goto exit_func;
- }
-
- if (some_waits) {
- goto loop;
- }
-
- srv_lock_timeout_active = FALSE;
-
-#if 0
- /* The following synchronisation is disabled, since
- the InnoDB monitor output is to be updated every 15 seconds. */
- os_event_wait(srv_lock_timeout_thread_event);
-#endif
- goto loop;
-
-exit_func:
- srv_lock_timeout_active = FALSE;
-
- /* We count the number of threads in os_thread_exit(). A created
- thread should always use that to exit and not use return() to exit. */
-
- os_thread_exit(NULL);
-
- OS_THREAD_DUMMY_RETURN;
-}
-
-/*********************************************************************//**
-A thread which prints warnings about semaphore waits which have lasted
-too long. These can be used to track bugs which cause hangs.
-@return a dummy parameter */
-UNIV_INTERN
-os_thread_ret_t
-srv_error_monitor_thread(
-/*=====================*/
- void* arg __attribute__((unused)))
- /*!< in: a dummy parameter required by
- os_thread_create */
-{
- /* number of successive fatal timeouts observed */
- ulint fatal_cnt = 0;
- ib_uint64_t old_lsn;
- ib_uint64_t new_lsn;
- ib_int64_t sig_count;
- /* longest waiting thread for a semaphore */
- os_thread_id_t waiter = os_thread_get_curr_id();
- os_thread_id_t old_waiter = waiter;
- /* the semaphore that is being waited for */
- const void* sema = NULL;
- const void* old_sema = NULL;
-
- old_lsn = srv_start_lsn;
-
-#ifdef UNIV_DEBUG_THREAD_CREATION
- fprintf(stderr, "Error monitor thread starts, id %lu\n",
- os_thread_pf(os_thread_get_curr_id()));
-#endif
-
-#ifdef UNIV_PFS_THREAD
- pfs_register_thread(srv_error_monitor_thread_key);
-#endif
-
-loop:
- srv_error_monitor_active = TRUE;
-
- /* Try to track a strange bug reported by Harald Fuchs and others,
- where the lsn seems to decrease at times */
-
- new_lsn = log_get_lsn();
-
- if (new_lsn < old_lsn) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: old log sequence number %llu"
- " was greater\n"
- "InnoDB: than the new log sequence number %llu!\n"
- "InnoDB: Please submit a bug report"
- " to http://bugs.mysql.com\n",
- old_lsn, new_lsn);
- ut_ad(0);
- }
-
- old_lsn = new_lsn;
-
- if (difftime(time(NULL), srv_last_monitor_time) > 60) {
- /* We referesh InnoDB Monitor values so that averages are
- printed from at most 60 last seconds */
-
- srv_refresh_innodb_monitor_stats();
- }
-
- /* Update the statistics collected for deciding LRU
- eviction policy. */
- buf_LRU_stat_update();
-
- /* Update the statistics collected for flush rate policy. */
- buf_flush_stat_update();
-
- /* In case mutex_exit is not a memory barrier, it is
- theoretically possible some threads are left waiting though
- the semaphore is already released. Wake up those threads: */
-
- sync_arr_wake_threads_if_sema_free();
-
- if (sync_array_print_long_waits(&waiter, &sema)
- && sema == old_sema && os_thread_eq(waiter, old_waiter)) {
- fatal_cnt++;
- if (fatal_cnt > 10) {
-
- fprintf(stderr,
- "InnoDB: Error: semaphore wait has lasted"
- " > %lu seconds\n"
- "InnoDB: We intentionally crash the server,"
- " because it appears to be hung.\n",
- (ulong) srv_fatal_semaphore_wait_threshold);
-
- ut_error;
- }
- } else {
- fatal_cnt = 0;
- old_waiter = waiter;
- old_sema = sema;
- }
-
- if (srv_kill_idle_transaction && trx_sys) {
- trx_t* trx;
- time_t now;
-rescan_idle:
- now = time(NULL);
- mutex_enter(&kernel_mutex);
- trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
- while (trx) {
- if (trx->state == TRX_ACTIVE
- && trx->mysql_thd
- && innobase_thd_is_idle(trx->mysql_thd)) {
- ib_int64_t start_time = innobase_thd_get_start_time(trx->mysql_thd);
- ulong thd_id = innobase_thd_get_thread_id(trx->mysql_thd);
-
- if (trx->last_stmt_start != start_time) {
- trx->idle_start = now;
- trx->last_stmt_start = start_time;
- } else if (difftime(now, trx->idle_start)
- > srv_kill_idle_transaction) {
- /* kill the session */
- mutex_exit(&kernel_mutex);
- innobase_thd_kill(thd_id);
- goto rescan_idle;
- }
- }
- trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
- }
- mutex_exit(&kernel_mutex);
- }
-
- /* Flush stderr so that a database user gets the output
- to possible MySQL error file */
-
- fflush(stderr);
-
- sig_count = os_event_reset(srv_error_event);
-
- os_event_wait_time_low(srv_error_event, 1000000, sig_count);
-
- if (srv_shutdown_state < SRV_SHUTDOWN_CLEANUP) {
-
- goto loop;
- }
-
- srv_error_monitor_active = FALSE;
-
- /* We count the number of threads in os_thread_exit(). A created
- thread should always use that to exit and not use return() to exit. */
-
- os_thread_exit(NULL);
-
- OS_THREAD_DUMMY_RETURN;
-}
-
-/*********************************************************************//**
-A thread which restores the buffer pool from a dump file on startup and does
-periodic buffer pool dumps.
-@return a dummy parameter */
-UNIV_INTERN
-os_thread_ret_t
-srv_LRU_dump_restore_thread(
-/*====================*/
- void* arg __attribute__((unused)))
- /*!< in: a dummy parameter required by
- os_thread_create */
-{
- uint auto_lru_dump;
- time_t last_dump_time;
- time_t time_elapsed;
-
-#ifdef UNIV_DEBUG_THREAD_CREATION
- fprintf(stderr, "The LRU dump/restore thread has started, id %lu\n",
- os_thread_pf(os_thread_get_curr_id()));
-#endif
-
- /* If srv_blocking_lru_restore is TRUE, restore will be done
- synchronously on startup. */
- if (srv_auto_lru_dump && !srv_blocking_lru_restore)
- buf_LRU_file_restore();
-
- last_dump_time = time(NULL);
-
-loop:
- os_event_wait_time_low(srv_shutdown_event, 5000000, 0);
-
- if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
- goto exit_func;
- }
-
- time_elapsed = time(NULL) - last_dump_time;
- auto_lru_dump = srv_auto_lru_dump;
- if (auto_lru_dump > 0 && (time_t) auto_lru_dump < time_elapsed) {
- last_dump_time = time(NULL);
- buf_LRU_file_dump();
- }
-
- goto loop;
-exit_func:
- /* We count the number of threads in os_thread_exit(). A created
- thread should always use that to exit and not use return() to exit. */
-
- os_thread_exit(NULL);
-
- OS_THREAD_DUMMY_RETURN;
-}
-
-/**********************************************************************//**
-Check whether any background thread is active. If so return the thread
-type
-@return ULINT_UNDEFINED if all are suspended or have exited, thread
-type if any are still active. */
-UNIV_INTERN
-ulint
-srv_get_active_thread_type(void)
-/*============================*/
-{
- ulint i;
- ibool ret = ULINT_UNDEFINED;
-
- mutex_enter(&kernel_mutex);
-
- for (i = 0; i <= SRV_MASTER; ++i) {
- if (srv_n_threads_active[i] != 0) {
- ret = i;
- break;
- }
- }
-
- mutex_exit(&kernel_mutex);
-
- return(ret);
-}
-
-/*********************************************************************//**
-This function prints progress message every 60 seconds during server
-shutdown, for any activities that master thread is pending on. */
-static
-void
-srv_shutdown_print_master_pending(
-/*==============================*/
- ib_time_t* last_print_time, /*!< last time the function
- print the message */
- ulint n_tables_to_drop, /*!< number of tables to
- be dropped */
- ulint n_bytes_merged, /*!< number of change buffer
- just merged */
- ulint n_pages_flushed) /*!< number of pages flushed */
-{
- ib_time_t current_time;
- double time_elapsed;
-
- current_time = ut_time();
- time_elapsed = ut_difftime(current_time, *last_print_time);
-
- if (time_elapsed > 60) {
- *last_print_time = ut_time();
-
- if (n_tables_to_drop) {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Waiting for "
- "%lu table(s) to be dropped\n",
- (ulong) n_tables_to_drop);
- }
-
- /* Check change buffer merge, we only wait for change buffer
- merge if it is a slow shutdown */
- if (!srv_fast_shutdown && n_bytes_merged) {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Waiting for change "
- "buffer merge to complete\n"
- " InnoDB: number of bytes of change buffer "
- "just merged: %lu\n",
- n_bytes_merged);
- }
-
- if (n_pages_flushed) {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Waiting for "
- "%lu pages to be flushed\n",
- (ulong) n_pages_flushed);
- }
- }
-}
-
-/******************************************************************//**
-A thread which follows the redo log and outputs the changed page bitmap.
-@return a dummy value */
-os_thread_ret_t
-srv_redo_log_follow_thread(
-/*=======================*/
- void* arg __attribute__((unused))) /*!< in: a dummy parameter
- required by
- os_thread_create */
-{
-#ifdef UNIV_DEBUG_THREAD_CREATION
- fprintf(stderr, "Redo log follower thread starts, id %lu\n",
- os_thread_pf(os_thread_get_curr_id()));
-#endif
-
-#ifdef UNIV_PFS_THREAD
- pfs_register_thread(srv_log_tracking_thread_key);
-#endif
-
- my_thread_init();
-
- do {
- os_event_wait(srv_checkpoint_completed_event);
- os_event_reset(srv_checkpoint_completed_event);
-
-#ifdef UNIV_DEBUG
- if (!srv_track_changed_pages) {
- continue;
- }
-#endif
-
- if (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE) {
- if (!log_online_follow_redo_log()) {
- /* TODO: sync with I_S log tracking status? */
- fprintf(stderr,
- "InnoDB: Error: log tracking bitmap "
- "write failed, stopping log tracking "
- "thread!\n");
- break;
- }
- }
-
- } while (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE);
-
- srv_track_changed_pages = FALSE;
- log_online_read_shutdown();
- os_event_set(srv_redo_log_thread_finished_event);
-
- my_thread_end();
- os_thread_exit(NULL);
-
- OS_THREAD_DUMMY_RETURN;
-}
-
-/*******************************************************************//**
-Tells the InnoDB server that there has been activity in the database
-and wakes up the master thread if it is suspended (not sleeping). Used
-in the MySQL interface. Note that there is a small chance that the master
-thread stays suspended (we do not protect our operation with the
-srv_sys_t->mutex, for performance reasons). */
-UNIV_INTERN
-void
-srv_active_wake_master_thread(void)
-/*===============================*/
-{
- srv_activity_count++;
-
- if (srv_n_threads_active[SRV_MASTER] == 0) {
-
- mutex_enter(&kernel_mutex);
-
- srv_release_threads(SRV_MASTER, 1);
-
- mutex_exit(&kernel_mutex);
- }
-}
-
-/*******************************************************************//**
-Tells the purge thread that there has been activity in the database
-and wakes up the purge thread if it is suspended (not sleeping). Note
-that there is a small chance that the purge thread stays suspended
-(we do not protect our operation with the kernel mutex, for
-performace reasons). */
-UNIV_INTERN
-void
-srv_wake_purge_thread_if_not_active(void)
-/*=====================================*/
-{
- ut_ad(!mutex_own(&kernel_mutex));
-
- if (srv_n_purge_threads > 0
- && srv_n_threads_active[SRV_WORKER] == 0) {
-
- mutex_enter(&kernel_mutex);
-
- srv_release_threads(SRV_WORKER, 1);
-
- mutex_exit(&kernel_mutex);
- }
-}
-
-/*******************************************************************//**
-Wakes up the master thread if it is suspended or being suspended. */
-UNIV_INTERN
-void
-srv_wake_master_thread(void)
-/*========================*/
-{
- srv_activity_count++;
-
- mutex_enter(&kernel_mutex);
-
- srv_release_threads(SRV_MASTER, 1);
-
- mutex_exit(&kernel_mutex);
-}
-
-/*******************************************************************//**
-Wakes up the purge thread if it's not already awake. */
-UNIV_INTERN
-void
-srv_wake_purge_thread(void)
-/*=======================*/
-{
- ut_ad(!mutex_own(&kernel_mutex));
-
- if (srv_n_purge_threads > 0) {
-
- mutex_enter(&kernel_mutex);
-
- srv_release_threads(SRV_WORKER, 1);
-
- mutex_exit(&kernel_mutex);
- }
-}
-
-/**********************************************************************
-The master thread is tasked to ensure that flush of log file happens
-once every second in the background. This is to ensure that not more
-than one second of trxs are lost in case of crash when
-innodb_flush_logs_at_trx_commit != 1 */
-static
-void
-srv_sync_log_buffer_in_background(void)
-/*===================================*/
-{
- time_t current_time = time(NULL);
-
- srv_main_thread_op_info = "flushing log";
- if (difftime(current_time, srv_last_log_flush_time) >= 1) {
- log_buffer_sync_in_background(TRUE);
- srv_last_log_flush_time = current_time;
- srv_log_writes_and_flush++;
- }
-}
-
-/********************************************************************//**
-Do a full purge, reconfigure the purge sub-system if a dynamic
-change is detected. */
-static
-void
-srv_master_do_purge(void)
-/*=====================*/
-{
- ulint n_pages_purged;
-
- ut_ad(!mutex_own(&kernel_mutex));
-
- ut_a(srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0));
-
- do {
- /* Check for shutdown and change in purge config. */
- if (srv_fast_shutdown && srv_shutdown_state > 0) {
- /* Nothing to purge. */
- n_pages_purged = 0;
- } else {
- n_pages_purged = trx_purge(srv_purge_batch_size);
- }
-
- srv_sync_log_buffer_in_background();
-
- } while (n_pages_purged > 0);
-}
-
-/*********************************************************************//**
-The master thread controlling the server.
-@return a dummy parameter */
-UNIV_INTERN
-os_thread_ret_t
-srv_master_thread(
-/*==============*/
- void* arg __attribute__((unused)))
- /*!< in: a dummy parameter required by
- os_thread_create */
-{
- buf_pool_stat_t buf_stat;
- srv_slot_t* slot;
- ulint old_activity_count;
- ulint n_pages_purged = 0;
- ulint n_bytes_merged;
- ulint n_pages_flushed;
- ulint n_pages_flushed_prev = 0;
- ulint n_bytes_archived;
- ulint n_tables_to_drop;
- ulint n_ios;
- ulint n_ios_old;
- ulint n_ios_very_old;
- ulint n_pend_ios;
- ulint next_itr_time;
- ulint prev_adaptive_flushing_method = ULINT_UNDEFINED;
- ulint inner_loop = 0;
- ibool skip_sleep = FALSE;
- ulint i;
- struct t_prev_flush_info_struct {
- ulint count;
- unsigned space:32;
- unsigned offset:32;
- ib_uint64_t oldest_modification;
- } prev_flush_info[MAX_BUFFER_POOLS];
-
- ib_uint64_t lsn_old;
-
- ib_uint64_t oldest_lsn;
- ib_time_t last_print_time;
-
-#ifdef UNIV_DEBUG_THREAD_CREATION
- fprintf(stderr, "Master thread starts, id %lu\n",
- os_thread_pf(os_thread_get_curr_id()));
-#endif
-
-#ifdef UNIV_PFS_THREAD
- pfs_register_thread(srv_master_thread_key);
-#endif
-
- srv_main_thread_process_no = os_proc_get_number();
- srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
-
- memset(&prev_flush_info, 0, sizeof(prev_flush_info));
- mutex_enter(&kernel_mutex);
-
- slot = srv_table_reserve_slot(SRV_MASTER);
-
- srv_n_threads_active[SRV_MASTER]++;
-
- mutex_exit(&kernel_mutex);
-
- mutex_enter(&(log_sys->mutex));
- lsn_old = log_sys->lsn;
- mutex_exit(&(log_sys->mutex));
-
- last_print_time = ut_time();
-
-loop:
- /*****************************************************************/
- /* ---- When there is database activity by users, we cycle in this
- loop */
-
- srv_main_thread_op_info = "reserving kernel mutex";
-
- buf_get_total_stat(&buf_stat);
- n_ios_very_old = log_sys->n_log_ios + buf_stat.n_pages_read
- + buf_stat.n_pages_written;
- n_pages_flushed= 0;
-
- mutex_enter(&kernel_mutex);
-
- /* Store the user activity counter at the start of this loop */
- old_activity_count = srv_activity_count;
-
- mutex_exit(&kernel_mutex);
-
- if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
-
- goto suspend_thread;
- }
-
- /* ---- We run the following loop approximately once per second
- when there is database activity */
-
- srv_last_log_flush_time = time(NULL);
-
- /* Sleep for 1 second on entrying the for loop below the first time. */
- next_itr_time = ut_time_ms() + 1000;
-
- skip_sleep = FALSE;
-
- for (i = 0; i < 10; i++) {
- ulint cur_time = ut_time_ms();
-
-#ifdef UNIV_DEBUG
- if (btr_cur_limit_optimistic_insert_debug
- && srv_n_purge_threads == 0) {
- /* If btr_cur_limit_optimistic_insert_debug is enabled
- and no purge_threads, purge opportunity is increased
- by x100 (1purge/100msec), to speed up debug scripts
- which should wait for purged. */
- next_itr_time -= 900;
-
- srv_main_thread_op_info = "master purging";
-
- srv_master_do_purge();
-
- if (srv_fast_shutdown && srv_shutdown_state > 0) {
-
- goto background_loop;
- }
- }
-#endif /* UNIV_DEBUG */
-
- n_pages_flushed = 0; /* initialize */
-
- /* ALTER TABLE in MySQL requires on Unix that the table handler
- can drop tables lazily after there no longer are SELECT
- queries to them. */
-
- srv_main_thread_op_info = "doing background drop tables";
-
- row_drop_tables_for_mysql_in_background();
-
- srv_main_thread_op_info = "";
-
- if (srv_fast_shutdown && srv_shutdown_state > 0) {
-
- goto background_loop;
- }
-
- buf_get_total_stat(&buf_stat);
-
- n_ios_old = log_sys->n_log_ios + buf_stat.n_pages_read
- + buf_stat.n_pages_written;
-
- srv_main_thread_op_info = "sleeping";
- srv_main_1_second_loops++;
-
- if (!skip_sleep) {
- if (next_itr_time > cur_time
- && srv_shutdown_state == SRV_SHUTDOWN_NONE) {
-
- /* Get sleep interval in micro seconds. We use
- ut_min() to avoid long sleep in case of
- wrap around. */
- os_event_wait_time_low(srv_shutdown_event,
- ut_min(1000000,
- (next_itr_time - cur_time)
- * 1000),
- 0);
- srv_main_sleeps++;
-
- /*
- mutex_enter(&(log_sys->mutex));
- oldest_lsn = buf_pool_get_oldest_modification();
- ib_uint64_t lsn = log_sys->lsn;
- mutex_exit(&(log_sys->mutex));
-
- if(oldest_lsn)
- fprintf(stderr,
- "InnoDB flush: age pct: %lu, lsn progress: %lu\n",
- (lsn - oldest_lsn) * 100 / log_sys->max_checkpoint_age,
- lsn - lsn_old);
- */
- }
-
- /* Each iteration should happen at 1 second interval. */
- next_itr_time = ut_time_ms() + 1000;
- } /* if (!skip_sleep) */
-
- skip_sleep = FALSE;
-
- /* Flush logs if needed */
- srv_sync_log_buffer_in_background();
-
- srv_main_thread_op_info = "making checkpoint";
- log_free_check();
-
- /* If i/os during one second sleep were less than 5% of
- capacity, we assume that there is free disk i/o capacity
- available, and it makes sense to do an insert buffer merge. */
-
- buf_get_total_stat(&buf_stat);
- n_pend_ios = buf_get_n_pending_ios()
- + log_sys->n_pending_writes;
- n_ios = log_sys->n_log_ios + buf_stat.n_pages_read
- + buf_stat.n_pages_written;
- if (n_pend_ios < SRV_PEND_IO_THRESHOLD
- && (n_ios - n_ios_old < SRV_RECENT_IO_ACTIVITY)) {
- srv_main_thread_op_info = "doing insert buffer merge";
- ibuf_contract_for_n_pages(FALSE, PCT_IBUF_IO(5));
-
- /* Flush logs if needed */
- srv_sync_log_buffer_in_background();
- }
-
- if (UNIV_UNLIKELY(buf_get_modified_ratio_pct()
- > srv_max_buf_pool_modified_pct)) {
-
- /* Try to keep the number of modified pages in the
- buffer pool under the limit wished by the user */
-
- srv_main_thread_op_info =
- "flushing buffer pool pages";
- n_pages_flushed = buf_flush_list(
- PCT_IO(100), IB_ULONGLONG_MAX);
-
- mutex_enter(&(log_sys->mutex));
- lsn_old = log_sys->lsn;
- mutex_exit(&(log_sys->mutex));
- prev_adaptive_flushing_method = ULINT_UNDEFINED;
- } else if (srv_adaptive_flushing && srv_adaptive_flushing_method == 0) {
-
- /* Try to keep the rate of flushing of dirty
- pages such that redo log generation does not
- produce bursts of IO at checkpoint time. */
- ulint n_flush = buf_flush_get_desired_flush_rate();
-
- if (n_flush) {
- srv_main_thread_op_info =
- "flushing buffer pool pages";
- n_flush = ut_min(PCT_IO(100), n_flush);
- n_pages_flushed =
- buf_flush_list(
- n_flush,
- IB_ULONGLONG_MAX);
- }
-
- mutex_enter(&(log_sys->mutex));
- lsn_old = log_sys->lsn;
- mutex_exit(&(log_sys->mutex));
- prev_adaptive_flushing_method = ULINT_UNDEFINED;
- } else if (srv_adaptive_flushing && srv_adaptive_flushing_method == 1) {
-
- /* Try to keep modified age not to exceed
- max_checkpoint_age * 7/8 line */
-
- mutex_enter(&(log_sys->mutex));
-
- oldest_lsn = buf_pool_get_oldest_modification();
- if (oldest_lsn == 0) {
- lsn_old = log_sys->lsn;
- mutex_exit(&(log_sys->mutex));
-
- } else {
- if ((log_sys->lsn - oldest_lsn)
- > (log_sys->max_checkpoint_age) - ((log_sys->max_checkpoint_age) / 8)) {
- /* LOG_POOL_PREFLUSH_RATIO_ASYNC is exceeded. */
- /* We should not flush from here. */
- lsn_old = log_sys->lsn;
- mutex_exit(&(log_sys->mutex));
- } else if ((log_sys->lsn - oldest_lsn)
- > (log_sys->max_checkpoint_age)/4 ) {
-
- /* defence line (max_checkpoint_age * 1/2) */
- ib_uint64_t lsn = log_sys->lsn;
-
- ib_uint64_t level, bpl;
- buf_page_t* bpage;
- ulint j;
-
- mutex_exit(&(log_sys->mutex));
-
- bpl = 0;
-
- for (j = 0; j < srv_buf_pool_instances; j++) {
- buf_pool_t* buf_pool;
- ulint n_blocks;
-
- buf_pool = buf_pool_from_array(j);
-
- buf_flush_list_mutex_enter(buf_pool);
- level = 0;
- n_blocks = 0;
- bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
-
- while (bpage != NULL) {
- ib_uint64_t oldest_modification = bpage->oldest_modification;
- if (oldest_modification != 0) {
- level += log_sys->max_checkpoint_age
- - (lsn - oldest_modification);
- }
- bpage = UT_LIST_GET_NEXT(flush_list, bpage);
- n_blocks++;
- }
- buf_flush_list_mutex_exit(buf_pool);
-
- if (level) {
- bpl += ((ib_uint64_t) n_blocks * n_blocks
- * (lsn - lsn_old)) / level;
- }
-
- }
-
- if (!srv_use_doublewrite_buf) {
- /* flush is faster than when doublewrite */
- bpl = (bpl * 7) / 8;
- }
-
- if (bpl) {
-retry_flush_batch:
- n_pages_flushed = buf_flush_list(bpl,
- oldest_lsn + (lsn - lsn_old));
- if (n_pages_flushed == ULINT_UNDEFINED) {
- os_thread_sleep(5000);
- goto retry_flush_batch;
- }
- }
-
- lsn_old = lsn;
- /*
- fprintf(stderr,
- "InnoDB flush: age pct: %lu, lsn progress: %lu, blocks to flush:%llu\n",
- (lsn - oldest_lsn) * 100 / log_sys->max_checkpoint_age,
- lsn - lsn_old, bpl);
- */
- } else {
- lsn_old = log_sys->lsn;
- mutex_exit(&(log_sys->mutex));
- }
- }
- prev_adaptive_flushing_method = 1;
- } else if (srv_adaptive_flushing && srv_adaptive_flushing_method == 2) {
- buf_pool_t* buf_pool;
- buf_page_t* bpage;
- ib_uint64_t lsn;
- ulint j;
-
- mutex_enter(&(log_sys->mutex));
- oldest_lsn = buf_pool_get_oldest_modification();
- lsn = log_sys->lsn;
- mutex_exit(&(log_sys->mutex));
-
- /* upper loop/sec. (x10) */
- next_itr_time -= 900; /* 1000 - 900 == 100 */
- inner_loop++;
- if (inner_loop < 10) {
- i--;
- } else {
- inner_loop = 0;
- }
-
- if (prev_adaptive_flushing_method == 2) {
- lint n_flush;
- lint blocks_sum;
- ulint new_blocks_sum, flushed_blocks_sum;
-
- blocks_sum = new_blocks_sum = flushed_blocks_sum = 0;
-
- /* prev_flush_info[j] should be the previous loop's */
- for (j = 0; j < srv_buf_pool_instances; j++) {
- lint blocks_num, new_blocks_num = 0;
- lint flushed_blocks_num;
-
- buf_pool = buf_pool_from_array(j);
- buf_flush_list_mutex_enter(buf_pool);
-
- blocks_num = UT_LIST_GET_LEN(buf_pool->flush_list);
- bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
-
- while (bpage != NULL) {
- if (prev_flush_info[j].space == bpage->space
- && prev_flush_info[j].offset == bpage->offset
- && prev_flush_info[j].oldest_modification
- == bpage->oldest_modification) {
- break;
- }
- bpage = UT_LIST_GET_NEXT(flush_list, bpage);
- new_blocks_num++;
- }
-
- flushed_blocks_num = new_blocks_num + prev_flush_info[j].count
- - blocks_num;
- if (flushed_blocks_num < 0) {
- flushed_blocks_num = 0;
- }
-
- bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
-
- prev_flush_info[j].count = UT_LIST_GET_LEN(buf_pool->flush_list);
- if (bpage) {
- prev_flush_info[j].space = bpage->space;
- prev_flush_info[j].offset = bpage->offset;
- prev_flush_info[j].oldest_modification = bpage->oldest_modification;
- buf_flush_list_mutex_exit(buf_pool);
- } else {
- buf_flush_list_mutex_exit(buf_pool);
- prev_flush_info[j].space = 0;
- prev_flush_info[j].offset = 0;
- prev_flush_info[j].oldest_modification = 0;
- }
-
- new_blocks_sum += new_blocks_num;
- flushed_blocks_sum += flushed_blocks_num;
- blocks_sum += blocks_num;
- }
-
- n_flush = (lint) (blocks_sum * (lsn - lsn_old) / log_sys->max_modified_age_async);
- if ((ulint) flushed_blocks_sum > n_pages_flushed_prev) {
- n_flush -= (flushed_blocks_sum - n_pages_flushed_prev);
- }
-
- if (n_flush > 0) {
- n_flush++;
- n_pages_flushed = buf_flush_list(n_flush, oldest_lsn + (lsn - lsn_old));
- } else {
- n_pages_flushed = 0;
- }
- } else {
- /* store previous first pages of the flush_list */
- for (j = 0; j < srv_buf_pool_instances; j++) {
- buf_pool = buf_pool_from_array(j);
- buf_flush_list_mutex_enter(buf_pool);
-
- bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
-
- prev_flush_info[j].count = UT_LIST_GET_LEN(buf_pool->flush_list);
- if (bpage) {
- prev_flush_info[j].space = bpage->space;
- prev_flush_info[j].offset = bpage->offset;
- prev_flush_info[j].oldest_modification = bpage->oldest_modification;
- buf_flush_list_mutex_exit(buf_pool);
- } else {
- buf_flush_list_mutex_exit(buf_pool);
- prev_flush_info[j].space = 0;
- prev_flush_info[j].offset = 0;
- prev_flush_info[j].oldest_modification = 0;
- }
- }
- n_pages_flushed = 0;
- }
-
- lsn_old = lsn;
- prev_adaptive_flushing_method = 2;
- } else {
- mutex_enter(&(log_sys->mutex));
- lsn_old = log_sys->lsn;
- mutex_exit(&(log_sys->mutex));
- prev_adaptive_flushing_method = ULINT_UNDEFINED;
- }
-
- if (n_pages_flushed == ULINT_UNDEFINED) {
- n_pages_flushed_prev = 0;
- } else {
- n_pages_flushed_prev = n_pages_flushed;
- }
-
- if (srv_activity_count == old_activity_count) {
-
- /* There is no user activity at the moment, go to
- the background loop */
-
- goto background_loop;
- }
- }
-
- /* ---- We perform the following code approximately once per
- 10 seconds when there is database activity */
-
-#ifdef MEM_PERIODIC_CHECK
- /* Check magic numbers of every allocated mem block once in 10
- seconds */
- mem_validate_all_blocks();
-#endif
- /* If i/os during the 10 second period were less than 200% of
- capacity, we assume that there is free disk i/o capacity
- available, and it makes sense to flush srv_io_capacity pages.
-
- Note that this is done regardless of the fraction of dirty
- pages relative to the max requested by the user. The one second
- loop above requests writes for that case. The writes done here
- are not required, and may be disabled. */
-
- buf_get_total_stat(&buf_stat);
- n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
- n_ios = log_sys->n_log_ios + buf_stat.n_pages_read
- + buf_stat.n_pages_written;
-
- srv_main_10_second_loops++;
- if (n_pend_ios < SRV_PEND_IO_THRESHOLD
- && (n_ios - n_ios_very_old < SRV_PAST_IO_ACTIVITY)) {
-
- srv_main_thread_op_info = "flushing buffer pool pages";
- buf_flush_list(PCT_IO(100), IB_ULONGLONG_MAX);
-
- /* Flush logs if needed */
- srv_sync_log_buffer_in_background();
- }
-
- /* We run a batch of insert buffer merge every 10 seconds,
- even if the server were active */
-
- srv_main_thread_op_info = "doing insert buffer merge";
- ibuf_contract_for_n_pages(FALSE, PCT_IBUF_IO(5));
-
- /* Flush logs if needed */
- srv_sync_log_buffer_in_background();
-
- if (srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0)) {
- srv_main_thread_op_info = "master purging";
-
- srv_master_do_purge();
-
- if (srv_fast_shutdown && srv_shutdown_state > 0) {
-
- goto background_loop;
- }
- }
-
- srv_main_thread_op_info = "flushing buffer pool pages";
-
- /* Flush a few oldest pages to make a new checkpoint younger */
-
- if (buf_get_modified_ratio_pct() > 70) {
-
- /* If there are lots of modified pages in the buffer pool
- (> 70 %), we assume we can afford reserving the disk(s) for
- the time it requires to flush 100 pages */
-
- n_pages_flushed = buf_flush_list(
- PCT_IO(100), IB_ULONGLONG_MAX);
- } else {
- /* Otherwise, we only flush a small number of pages so that
- we do not unnecessarily use much disk i/o capacity from
- other work */
-
- n_pages_flushed = buf_flush_list(
- PCT_IO(10), IB_ULONGLONG_MAX);
- }
-
- srv_main_thread_op_info = "making checkpoint";
-
- /* Make a new checkpoint about once in 10 seconds */
-
- log_checkpoint(TRUE, FALSE, TRUE);
-
- srv_main_thread_op_info = "reserving kernel mutex";
-
- mutex_enter(&kernel_mutex);
-
- /* ---- When there is database activity, we jump from here back to
- the start of loop */
-
- if (srv_activity_count != old_activity_count) {
- mutex_exit(&kernel_mutex);
- goto loop;
- }
-
- mutex_exit(&kernel_mutex);
-
- /* If the database is quiet, we enter the background loop */
-
- /*****************************************************************/
-background_loop:
- /* ---- In this loop we run background operations when the server
- is quiet from user activity. Also in the case of a shutdown, we
- loop here, flushing the buffer pool to the data files. */
-
- /* The server has been quiet for a while: start running background
- operations */
- srv_main_background_loops++;
- srv_main_thread_op_info = "doing background drop tables";
-
- n_tables_to_drop = row_drop_tables_for_mysql_in_background();
-
- if (n_tables_to_drop > 0) {
- /* Do not monopolize the CPU even if there are tables waiting
- in the background drop queue. (It is essentially a bug if
- MySQL tries to drop a table while there are still open handles
- to it and we had to put it to the background drop queue.) */
-
- if (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
- os_thread_sleep(100000);
- }
- }
-
- if (srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0)) {
- srv_main_thread_op_info = "master purging";
-
- srv_master_do_purge();
- }
-
- srv_main_thread_op_info = "reserving kernel mutex";
-
- mutex_enter(&kernel_mutex);
- if (srv_activity_count != old_activity_count) {
- mutex_exit(&kernel_mutex);
- goto loop;
- }
- mutex_exit(&kernel_mutex);
-
- srv_main_thread_op_info = "doing insert buffer merge";
-
- if (srv_fast_shutdown && srv_shutdown_state > 0) {
- n_bytes_merged = 0;
- } else {
- /* This should do an amount of IO similar to the number of
- dirty pages that will be flushed in the call to
- buf_flush_list below. Otherwise, the system favors
- clean pages over cleanup throughput. */
- n_bytes_merged = ibuf_contract_for_n_pages(FALSE,
- PCT_IBUF_IO(100));
- }
-
- srv_main_thread_op_info = "reserving kernel mutex";
-
- mutex_enter(&kernel_mutex);
- if (srv_activity_count != old_activity_count) {
- mutex_exit(&kernel_mutex);
- goto loop;
- }
- mutex_exit(&kernel_mutex);
-
-flush_loop:
- srv_main_thread_op_info = "flushing buffer pool pages";
- srv_main_flush_loops++;
- if (srv_fast_shutdown < 2 || srv_shutdown_state == SRV_SHUTDOWN_NONE) {
- n_pages_flushed = buf_flush_list(
- PCT_IO(100), IB_ULONGLONG_MAX);
- } else {
- /* In the fastest shutdown we do not flush the buffer pool
- to data files: we set n_pages_flushed to 0 artificially. */
- ut_ad(srv_fast_shutdown == 2);
- ut_ad(srv_shutdown_state > 0);
-
- n_pages_flushed = 0;
-
- DBUG_PRINT("master", ("doing very fast shutdown"));
- }
-
- srv_main_thread_op_info = "reserving kernel mutex";
-
- mutex_enter(&kernel_mutex);
- if (srv_activity_count != old_activity_count) {
- mutex_exit(&kernel_mutex);
- goto loop;
- }
- mutex_exit(&kernel_mutex);
-
- srv_main_thread_op_info = "waiting for buffer pool flush to end";
- buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
-
- /* Flush logs if needed */
- srv_sync_log_buffer_in_background();
-
- srv_main_thread_op_info = "making checkpoint";
-
- log_checkpoint(TRUE, FALSE, TRUE);
-
- if (!(srv_fast_shutdown == 2 && srv_shutdown_state > 0)
- && (buf_get_modified_ratio_pct()
- > srv_max_buf_pool_modified_pct)) {
-
- /* If the server is doing a very fast shutdown, then
- we will not come here. */
-
- /* Try to keep the number of modified pages in the
- buffer pool under the limit wished by the user */
-
- goto flush_loop;
- }
-
- srv_main_thread_op_info = "reserving kernel mutex";
-
- mutex_enter(&kernel_mutex);
- if (srv_activity_count != old_activity_count) {
- mutex_exit(&kernel_mutex);
- goto loop;
- }
- mutex_exit(&kernel_mutex);
- /*
- srv_main_thread_op_info = "archiving log (if log archive is on)";
-
- log_archive_do(FALSE, &n_bytes_archived);
- */
- n_bytes_archived = 0;
-
- /* Print progress message every 60 seconds during shutdown */
- if (srv_shutdown_state > 0 && srv_print_verbose_log) {
- srv_shutdown_print_master_pending(&last_print_time,
- n_tables_to_drop,
- n_bytes_merged,
- n_pages_flushed);
- }
-
- /* Keep looping in the background loop if still work to do */
-
- if (srv_fast_shutdown && srv_shutdown_state > 0) {
- if (n_tables_to_drop + n_pages_flushed
- + n_bytes_archived != 0) {
-
- /* If we are doing a fast shutdown (= the default)
- we do not do purge or insert buffer merge. But we
- flush the buffer pool completely to disk.
- In a 'very fast' shutdown we do not flush the buffer
- pool to data files: we have set n_pages_flushed to
- 0 artificially. */
-
- goto background_loop;
- }
- } else if (n_tables_to_drop
- + n_pages_purged + n_bytes_merged + n_pages_flushed
- + n_bytes_archived != 0) {
-
- /* In a 'slow' shutdown we run purge and the insert buffer
- merge to completion */
-
- goto background_loop;
- }
-
- /* There is no work for background operations either: suspend
- master thread to wait for more server activity */
-
-suspend_thread:
- srv_main_thread_op_info = "suspending";
-
- mutex_enter(&kernel_mutex);
-
- if (row_get_background_drop_list_len_low() > 0) {
- mutex_exit(&kernel_mutex);
-
- goto loop;
- }
-
- srv_suspend_thread(slot);
-
- mutex_exit(&kernel_mutex);
-
- /* DO NOT CHANGE THIS STRING. innobase_start_or_create_for_mysql()
- waits for database activity to die down when converting < 4.1.x
- databases, and relies on this string being exactly as it is. InnoDB
- manual also mentions this string in several places. */
- srv_main_thread_op_info = "waiting for server activity";
-
- os_event_wait(slot->event);
-
- if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- os_thread_exit(NULL);
- }
-
- /* When there is user activity, InnoDB will set the event and the
- main thread goes back to loop. */
-
- goto loop;
-}
-
-/*********************************************************************//**
-Asynchronous purge thread.
-@return a dummy parameter */
-UNIV_INTERN
-os_thread_ret_t
-srv_purge_thread(
-/*=============*/
- void* arg __attribute__((unused))) /*!< in: a dummy parameter
- required by os_thread_create */
-{
- srv_slot_t* slot;
- ulint retries = 0;
- ulint n_total_purged = ULINT_UNDEFINED;
- ulint next_itr_time;
- ib_int64_t sig_count;
-
- ut_a(srv_n_purge_threads == 1);
-
-#ifdef UNIV_PFS_THREAD
- pfs_register_thread(srv_purge_thread_key);
-#endif /* UNIV_PFS_THREAD */
-
-#ifdef UNIV_DEBUG_THREAD_CREATION
- fprintf(stderr, "InnoDB: Purge thread running, id %lu\n",
- os_thread_pf(os_thread_get_curr_id()));
-#endif /* UNIV_DEBUG_THREAD_CREATION */
-
- mutex_enter(&kernel_mutex);
-
- slot = srv_table_reserve_slot(SRV_WORKER);
-
- ++srv_n_threads_active[SRV_WORKER];
-
- mutex_exit(&kernel_mutex);
-
- next_itr_time = ut_time_ms();
-
- while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
-
- ulint n_pages_purged = 0;
- ulint cur_time;
-
- /* If there are very few records to purge or the last
- purge didn't purge any records then wait for activity.
- We peek at the history len without holding any mutex
- because in the worst case we will end up waiting for
- the next purge event. */
- if (trx_sys->rseg_history_len < srv_purge_batch_size
- || (n_total_purged == 0
- && retries >= TRX_SYS_N_RSEGS)) {
-
- mutex_enter(&kernel_mutex);
-
- srv_suspend_thread(slot);
-
- mutex_exit(&kernel_mutex);
-
- os_event_wait(slot->event);
-
- retries = 0;
- }
-
- /* Check for shutdown and whether we should do purge at all. */
- if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND
- || srv_shutdown_state != 0
- || srv_fast_shutdown) {
-
- break;
- }
-
- if (n_total_purged == 0 && retries <= TRX_SYS_N_RSEGS) {
- ++retries;
- } else if (n_total_purged > 0) {
- retries = 0;
- n_total_purged = 0;
- }
-
- /* Purge until there are no more records to purge and there is
- no change in configuration or server state. */
- do {
- n_pages_purged = trx_purge(srv_purge_batch_size);
-
- n_total_purged += n_pages_purged;
-
- } while (n_pages_purged > 0 && !srv_fast_shutdown);
-
- srv_sync_log_buffer_in_background();
-
- cur_time = ut_time_ms();
- sig_count = os_event_reset(srv_shutdown_event);
- if (next_itr_time > cur_time) {
- os_event_wait_time_low(srv_shutdown_event,
- ut_min(1000000,
- (next_itr_time - cur_time)
- * 1000),
- sig_count);
- next_itr_time = ut_time_ms() + 1000;
- } else {
- next_itr_time = cur_time + 1000;
- }
- }
-
- mutex_enter(&kernel_mutex);
-
- /* Decrement the active count. */
- srv_suspend_thread(slot);
-
- slot->in_use = FALSE;
-
- mutex_exit(&kernel_mutex);
-
-#ifdef UNIV_DEBUG_THREAD_CREATION
- fprintf(stderr, "InnoDB: Purge thread exiting, id %lu\n",
- os_thread_pf(os_thread_get_curr_id()));
-#endif /* UNIV_DEBUG_THREAD_CREATION */
-
- /* We count the number of threads in os_thread_exit(). A created
- thread should always use that to exit and not use return() to exit. */
- os_thread_exit(NULL);
-
- OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
-}
-
-/**********************************************************************//**
-Enqueues a task to server task queue and releases a worker thread, if there
-is a suspended one. */
-UNIV_INTERN
-void
-srv_que_task_enqueue_low(
-/*=====================*/
- que_thr_t* thr) /*!< in: query thread */
-{
- ut_ad(thr);
-
- mutex_enter(&kernel_mutex);
-
- UT_LIST_ADD_LAST(queue, srv_sys->tasks, thr);
-
- srv_release_threads(SRV_WORKER, 1);
-
- mutex_exit(&kernel_mutex);
-}