Drizzled Public API Documentation

srv0srv.cc
00001 /*****************************************************************************
00002 
00003 Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
00004 Copyright (C) 2008, 2009 Google Inc.
00005 Copyright (C) 2009, Percona Inc.
00006 
00007 Portions of this file contain modifications contributed and copyrighted by
00008 Google, Inc. Those modifications are gratefully acknowledged and are described
00009 briefly in the InnoDB documentation. The contributions by Google are
00010 incorporated with their permission, and subject to the conditions contained in
00011 the file COPYING.Google.
00012 
00013 Portions of this file contain modifications contributed and copyrighted
00014 by Percona Inc.. Those modifications are
00015 gratefully acknowledged and are described briefly in the InnoDB
00016 documentation. The contributions by Percona Inc. are incorporated with
00017 their permission, and subject to the conditions contained in the file
00018 COPYING.Percona.
00019 
00020 This program is free software; you can redistribute it and/or modify it under
00021 the terms of the GNU General Public License as published by the Free Software
00022 Foundation; version 2 of the License.
00023 
00024 This program is distributed in the hope that it will be useful, but WITHOUT
00025 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00026 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00027 
00028 You should have received a copy of the GNU General Public License along with
00029 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00030 St, Fifth Floor, Boston, MA 02110-1301 USA
00031 
00032 *****************************************************************************/
00033 
00034 /**************************************************/
00060 /* Dummy comment */
00061 #include "srv0srv.h"
00062 
00063 #include <drizzled/error.h>
00064 #include <drizzled/errmsg_print.h>
00065 
00066 #include "ut0mem.h"
00067 #include "ut0ut.h"
00068 #include "os0proc.h"
00069 #include "mem0mem.h"
00070 #include "mem0pool.h"
00071 #include "sync0sync.h"
00072 #include "thr0loc.h"
00073 #include "que0que.h"
00074 #include "log0recv.h"
00075 #include "pars0pars.h"
00076 #include "usr0sess.h"
00077 #include "lock0lock.h"
00078 #include "trx0purge.h"
00079 #include "ibuf0ibuf.h"
00080 #include "buf0flu.h"
00081 #include "buf0lru.h"
00082 #include "btr0sea.h"
00083 #include "dict0load.h"
00084 #include "dict0boot.h"
00085 #include "srv0start.h"
00086 #include "row0mysql.h"
00087 #include "ha_prototypes.h"
00088 #include "trx0i_s.h"
00089 #include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
00090 
00091 /* This is set to TRUE if the MySQL user has set it in MySQL; currently
00092 affects only FOREIGN KEY definition parsing */
00093 UNIV_INTERN ibool srv_lower_case_table_names  = FALSE;
00094 
00095 /* The following counter is incremented whenever there is some user activity
00096 in the server */
00097 UNIV_INTERN ulint srv_activity_count  = 0;
00098 
00099 /* The following is the maximum allowed duration of a lock wait. */
00100 UNIV_INTERN ulint srv_fatal_semaphore_wait_threshold = 600;
00101 
00102 /* How much data manipulation language (DML) statements need to be delayed,
00103 in microseconds, in order to reduce the lagging of the purge thread. */
00104 UNIV_INTERN ulint srv_dml_needed_delay = 0;
00105 
00106 UNIV_INTERN ibool srv_lock_timeout_active = FALSE;
00107 UNIV_INTERN ibool srv_monitor_active = FALSE;
00108 UNIV_INTERN ibool srv_error_monitor_active = FALSE;
00109 
00110 UNIV_INTERN const char* srv_main_thread_op_info = "";
00111 
00112 /* Server parameters which are read from the initfile */
00113 
00114 /* The following three are dir paths which are catenated before file
00115 names, where the file name itself may also contain a path */
00116 
00117 UNIV_INTERN char* srv_data_home = NULL;
00118 #ifdef UNIV_LOG_ARCHIVE
00119 UNIV_INTERN char* srv_arch_dir  = NULL;
00120 #endif /* UNIV_LOG_ARCHIVE */
00121 
00124 UNIV_INTERN my_bool srv_file_per_table;
00126 UNIV_INTERN ulint srv_file_format = 0;
00130 UNIV_INTERN ulint srv_max_file_format_at_startup = DICT_TF_FORMAT_MAX;
00131 
00132 #if DICT_TF_FORMAT_51
00133 # error "DICT_TF_FORMAT_51 must be 0!"
00134 #endif
00135 
00137 UNIV_INTERN ibool srv_locks_unsafe_for_binlog = FALSE;
00138 
00139 /* If this flag is TRUE, then we will use the native aio of the
00140 OS (provided we compiled Innobase with it in), otherwise we will
00141 use simulated aio we build below with threads.
00142 Currently we support native aio on windows and linux */
00143 UNIV_INTERN my_bool srv_use_native_aio = TRUE;
00144 
00145 #ifdef __WIN__
00146 /* Windows native condition variables. We use runtime loading / function
00147 pointers, because they are not available on Windows Server 2003 and
00148 Windows XP/2000.
00149 
00150 We use condition for events on Windows if possible, even if os_event
00151 resembles Windows kernel event object well API-wise. The reason is
00152 performance, kernel objects are heavyweights and WaitForSingleObject() is a
00153 performance killer causing calling thread to context switch. Besides, Innodb
00154 is preallocating large number (often millions) of os_events. With kernel event
00155 objects it takes a big chunk out of non-paged pool, which is better suited
00156 for tasks like IO than for storing idle event objects. */
00157 UNIV_INTERN ibool srv_use_native_conditions = FALSE;
00158 #endif /* __WIN__ */
00159 
00160 UNIV_INTERN ulint srv_n_data_files = 0;
00161 UNIV_INTERN char**  srv_data_file_names = NULL;
00162 /* size in database pages */
00163 UNIV_INTERN ulint*  srv_data_file_sizes = NULL;
00164 
00165 /* if TRUE, then we auto-extend the last data file */
00166 UNIV_INTERN ibool srv_auto_extend_last_data_file  = FALSE;
00167 /* if != 0, this tells the max size auto-extending may increase the
00168 last data file size */
00169 UNIV_INTERN ulint srv_last_file_size_max  = 0;
00170 /* If the last data file is auto-extended, we add this
00171 many pages to it at a time */
00172 UNIV_INTERN unsigned int srv_auto_extend_increment = 8;
00173 UNIV_INTERN ulint*  srv_data_file_is_raw_partition = NULL;
00174 
00175 /* If the following is TRUE we do not allow inserts etc. This protects
00176 the user from forgetting the 'newraw' keyword to my.cnf */
00177 
00178 UNIV_INTERN ibool srv_created_new_raw = FALSE;
00179 
00180 UNIV_INTERN char**  srv_log_group_home_dirs = NULL;
00181 
00182 UNIV_INTERN ulint srv_n_log_groups  = ULINT_MAX;
00183 UNIV_INTERN ulint srv_n_log_files   = ULINT_MAX;
00184 /* size in database pages */
00185 UNIV_INTERN ulint srv_log_file_size = ULINT_MAX;
00186 /* size in database pages */
00187 UNIV_INTERN ulint srv_log_buffer_size = ULINT_MAX;
00188 UNIV_INTERN ulong srv_flush_log_at_trx_commit = 1;
00189 
00190 /* Try to flush dirty pages so as to avoid IO bursts at
00191 the checkpoints. */
00192 UNIV_INTERN bool  srv_adaptive_flushing = TRUE;
00193 
00196 #define MAX_MUTEX_NOWAIT  20
00197 
00202 #define MUTEX_NOWAIT(mutex_skipped) ((mutex_skipped) < MAX_MUTEX_NOWAIT)
00203 
00206 #if defined(BUILD_DRIZZLE)
00207 const byte  srv_latin1_ordering[256]  /* The sort order table of the latin1
00208           character set. The following table is
00209           the MySQL order as of Feb 10th, 2002 */
00210 = {
00211   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
00212 , 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
00213 , 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
00214 , 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
00215 , 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
00216 , 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F
00217 , 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37
00218 , 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
00219 , 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47
00220 , 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F
00221 , 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
00222 , 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
00223 , 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47
00224 , 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F
00225 , 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57
00226 , 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F
00227 , 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87
00228 , 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F
00229 , 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97
00230 , 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F
00231 , 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7
00232 , 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF
00233 , 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7
00234 , 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF
00235 , 0x41, 0x41, 0x41, 0x41, 0x5C, 0x5B, 0x5C, 0x43
00236 , 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49
00237 , 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x5D, 0xD7
00238 , 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xDF
00239 , 0x41, 0x41, 0x41, 0x41, 0x5C, 0x5B, 0x5C, 0x43
00240 , 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49
00241 , 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x5D, 0xF7
00242 , 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xFF
00243 };
00244 #else
00245 UNIV_INTERN const byte*        srv_latin1_ordering;
00246 #endif /* BUILD_DRIZZLE */
00247 
00248 
00249 /* use os/external memory allocator */
00250 UNIV_INTERN my_bool srv_use_sys_malloc  = TRUE;
00251 /* requested size in kilobytes */
00252 UNIV_INTERN ulint srv_buf_pool_size = ULINT_MAX;
00253 /* requested number of buffer pool instances */
00254 UNIV_INTERN ulint       srv_buf_pool_instances  = 1;
00255 /* previously requested size */
00256 UNIV_INTERN ulint srv_buf_pool_old_size;
00257 /* current size in kilobytes */
00258 UNIV_INTERN ulint srv_buf_pool_curr_size  = 0;
00259 /* size in bytes */
00260 UNIV_INTERN ulint srv_mem_pool_size = ULINT_MAX;
00261 UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX;
00262 
00263 /* This parameter is deprecated. Use srv_n_io_[read|write]_threads
00264 instead. */
00265 UNIV_INTERN ulint srv_n_file_io_threads = ULINT_MAX;
00266 UNIV_INTERN ulint srv_n_read_io_threads = ULINT_MAX;
00267 UNIV_INTERN ulint srv_n_write_io_threads  = ULINT_MAX;
00268 
00269 /* The universal page size of the database */
00270 UNIV_INTERN ulint srv_page_size_shift = 0;
00271 UNIV_INTERN ulint srv_page_size   = 0;
00272 
00273 /* The log block size */
00274 UNIV_INTERN uint32_t  srv_log_block_size  = 0;
00275 
00276 /* User settable value of the number of pages that must be present
00277 in the buffer cache and accessed sequentially for InnoDB to trigger a
00278 readahead request. */
00279 UNIV_INTERN ulong srv_read_ahead_threshold  = 56;
00280 
00281 #ifdef UNIV_LOG_ARCHIVE
00282 UNIV_INTERN ibool   srv_log_archive_on  = FALSE;
00283 UNIV_INTERN ibool   srv_archive_recovery  = 0;
00284 UNIV_INTERN ib_uint64_t srv_archive_recovery_limit_lsn;
00285 #endif /* UNIV_LOG_ARCHIVE */
00286 
00287 /* This parameter is used to throttle the number of insert buffers that are
00288 merged in a batch. By increasing this parameter on a faster disk you can
00289 possibly reduce the number of I/O operations performed to complete the
00290 merge operation. The value of this parameter is used as is by the
00291 background loop when the system is idle (low load), on a busy system
00292 the parameter is scaled down by a factor of 4, this is to avoid putting
00293 a heavier load on the I/O sub system. */
00294 
00295 UNIV_INTERN ulong srv_insert_buffer_batch_size = 20;
00296 
00297 UNIV_INTERN char* srv_file_flush_method_str = NULL;
00298 UNIV_INTERN ulint srv_unix_file_flush_method = SRV_UNIX_FSYNC;
00299 UNIV_INTERN ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
00300 
00301 UNIV_INTERN ulint srv_max_n_open_files    = 300;
00302 
00303 /* Number of IO operations per second the server can do */
00304 UNIV_INTERN ulong srv_io_capacity         = 200;
00305 
00306 /* The InnoDB main thread tries to keep the ratio of modified pages
00307 in the buffer pool to all database pages in the buffer pool smaller than
00308 the following number. But it is not guaranteed that the value stays below
00309 that during a time of heavy update/insert activity. */
00310 
00311 UNIV_INTERN ulong srv_max_buf_pool_modified_pct = 75;
00312 
00313 /* the number of purge threads to use from the worker pool (currently 0 or 1).*/
00314 UNIV_INTERN ulong srv_n_purge_threads = 0;
00315 
00316 /* the number of records to purge in one batch */
00317 UNIV_INTERN ulong srv_purge_batch_size = 20;
00318 
00319 /* variable counts amount of data read in total (in bytes) */
00320 UNIV_INTERN ulint srv_data_read = 0;
00321 
00322 /* here we count the amount of data written in total (in bytes) */
00323 UNIV_INTERN ulint srv_data_written = 0;
00324 
00325 /* the number of the log write requests done */
00326 UNIV_INTERN ulint srv_log_write_requests = 0;
00327 
00328 /* the number of physical writes to the log performed */
00329 UNIV_INTERN ulint srv_log_writes = 0;
00330 
00331 /* amount of data written to the log files in bytes */
00332 UNIV_INTERN ulint srv_os_log_written = 0;
00333 
00334 /* amount of writes being done to the log files */
00335 UNIV_INTERN ulint srv_os_log_pending_writes = 0;
00336 
00337 /* we increase this counter, when there we don't have enough space in the
00338 log buffer and have to flush it */
00339 UNIV_INTERN ulint srv_log_waits = 0;
00340 
00341 /* this variable counts the amount of times, when the doublewrite buffer
00342 was flushed */
00343 UNIV_INTERN ulint srv_dblwr_writes = 0;
00344 
00345 /* here we store the number of pages that have been flushed to the
00346 doublewrite buffer */
00347 UNIV_INTERN ulint srv_dblwr_pages_written = 0;
00348 
00349 /* in this variable we store the number of write requests issued */
00350 UNIV_INTERN ulint srv_buf_pool_write_requests = 0;
00351 
00352 /* here we store the number of times when we had to wait for a free page
00353 in the buffer pool. It happens when the buffer pool is full and we need
00354 to make a flush, in order to be able to read or create a page. */
00355 UNIV_INTERN ulint srv_buf_pool_wait_free = 0;
00356 
00357 /* variable to count the number of pages that were written from buffer
00358 pool to the disk */
00359 UNIV_INTERN ulint srv_buf_pool_flushed = 0;
00360 
00363 UNIV_INTERN ulint srv_buf_pool_reads = 0;
00364 
00366 UNIV_INTERN uint srv_auto_lru_dump = 0;
00367 
00368 /* structure to pass status variables to MySQL */
00369 UNIV_INTERN export_struc export_vars;
00370 
00371 /* If the following is != 0 we do not allow inserts etc. This protects
00372 the user from forgetting the innodb_force_recovery keyword to my.cnf */
00373 
00374 UNIV_INTERN ulint srv_force_recovery  = 0;
00375 /*-----------------------*/
00376 /* We are prepared for a situation that we have this many threads waiting for
00377 a semaphore inside InnoDB. innobase_start_or_create_for_mysql() sets the
00378 value. */
00379 
00380 UNIV_INTERN ulint srv_max_n_threads = 0;
00381 
00382 /* The following controls how many threads we let inside InnoDB concurrently:
00383 threads waiting for locks are not counted into the number because otherwise
00384 we could get a deadlock. MySQL creates a thread for each user session, and
00385 semaphore contention and convoy problems can occur withput this restriction.
00386 Value 10 should be good if there are less than 4 processors + 4 disks in the
00387 computer. Bigger computers need bigger values. Value 0 will disable the
00388 concurrency check. */
00389 
00390 UNIV_INTERN ulong srv_thread_concurrency  = 0;
00391 
00392 /* this mutex protects srv_conc data structures */
00393 UNIV_INTERN os_fast_mutex_t srv_conc_mutex;
00394 /* number of transactions that have declared_to_be_inside_innodb set.
00395 It used to be a non-error for this value to drop below zero temporarily.
00396 This is no longer true. We'll, however, keep the lint datatype to add
00397 assertions to catch any corner cases that we may have missed. */
00398 UNIV_INTERN lint  srv_conc_n_threads  = 0;
00399 /* number of OS threads waiting in the FIFO for a permission to enter
00400 InnoDB */
00401 UNIV_INTERN ulint srv_conc_n_waiting_threads = 0;
00402 
00403 typedef struct srv_conc_slot_struct srv_conc_slot_t;
00404 struct srv_conc_slot_struct{
00405   os_event_t      event;    
00406   ibool       reserved; 
00408   ibool       wait_ended; 
00415   UT_LIST_NODE_T(srv_conc_slot_t) srv_conc_queue; 
00416 };
00417 
00418 /* queue of threads waiting to get in */
00419 UNIV_INTERN UT_LIST_BASE_NODE_T(srv_conc_slot_t)  srv_conc_queue;
00420 /* array of wait slots */
00421 UNIV_INTERN srv_conc_slot_t* srv_conc_slots;
00422 
00423 /* Number of times a thread is allowed to enter InnoDB within the same
00424 SQL query after it has once got the ticket at srv_conc_enter_innodb */
00425 #define SRV_FREE_TICKETS_TO_ENTER srv_n_free_tickets_to_enter
00426 #define SRV_THREAD_SLEEP_DELAY srv_thread_sleep_delay
00427 /*-----------------------*/
00428 /* If the following is set to 1 then we do not run purge and insert buffer
00429 merge to completion before shutdown. If it is set to 2, do not even flush the
00430 buffer pool to data files at the shutdown: we effectively 'crash'
00431 InnoDB (but lose no committed transactions). */
00432 UNIV_INTERN ulint srv_fast_shutdown = 0;
00433 
00434 /* Generate a innodb_status.<pid> file */
00435 UNIV_INTERN ibool srv_innodb_status = FALSE;
00436 
00437 /* When estimating number of different key values in an index, sample
00438 this many index pages */
00439 UNIV_INTERN ib_uint64_t srv_stats_sample_pages = 8;
00440 
00441 UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE;
00442 UNIV_INTERN ibool srv_use_checksums = TRUE;
00443 
00444 UNIV_INTERN ulong srv_replication_delay   = 0;
00445 
00446 UNIV_INTERN uint64_t  srv_ibuf_max_size = 0;
00447 UNIV_INTERN uint32_t  srv_ibuf_active_contract = 0;
00448 UNIV_INTERN uint32_t  srv_ibuf_accel_rate = 100;
00449 
00450 #define PCT_IBUF_IO(pct) (srv_io_capacity * srv_ibuf_accel_rate \
00451         * (pct / 10000.0))
00452 
00453 UNIV_INTERN uint32_t  srv_checkpoint_age_target = 0;
00454 UNIV_INTERN uint32_t  srv_flush_neighbor_pages = 1;
00455 
00456 UNIV_INTERN uint32_t  srv_read_ahead = 3; /* 1: random, 2: linear, 3: both */
00457 UNIV_INTERN uint32_t  srv_adaptive_flushing_method = 0; /* 0: native,
00458                    1: estimate,
00459                    2: keep_average */
00460 
00461 UNIV_INTERN ibool srv_read_only = FALSE;
00462 UNIV_INTERN ibool srv_fake_write = FALSE;
00463 UNIV_INTERN ibool srv_apply_log_only = FALSE;
00464 
00465 /*-------------------------------------------*/
00466 UNIV_INTERN ulong srv_n_spin_wait_rounds  = 30;
00467 UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
00468 UNIV_INTERN ulong srv_thread_sleep_delay = 10000;
00469 UNIV_INTERN ulong srv_spin_wait_delay = 6;
00470 UNIV_INTERN ibool srv_priority_boost  = TRUE;
00471 
00472 #ifdef UNIV_DEBUG
00473 UNIV_INTERN ibool srv_print_thread_releases = FALSE;
00474 UNIV_INTERN ibool srv_print_lock_waits    = FALSE;
00475 UNIV_INTERN ibool srv_print_buf_io    = FALSE;
00476 UNIV_INTERN ibool srv_print_log_io    = FALSE;
00477 UNIV_INTERN ibool srv_print_latch_waits   = FALSE;
00478 #endif /* UNIV_DEBUG */
00479 
00480 UNIV_INTERN ulint   srv_n_rows_inserted   = 0;
00481 UNIV_INTERN ulint   srv_n_rows_updated    = 0;
00482 UNIV_INTERN ulint   srv_n_rows_deleted    = 0;
00483 UNIV_INTERN ulint   srv_n_rows_read     = 0;
00484 
00485 static ulint  srv_n_rows_inserted_old   = 0;
00486 static ulint  srv_n_rows_updated_old    = 0;
00487 static ulint  srv_n_rows_deleted_old    = 0;
00488 static ulint  srv_n_rows_read_old   = 0;
00489 
00490 UNIV_INTERN ulint   srv_n_lock_wait_count   = 0;
00491 UNIV_INTERN ulint   srv_n_lock_wait_current_count = 0;
00492 UNIV_INTERN ib_int64_t  srv_n_lock_wait_time    = 0;
00493 UNIV_INTERN ulint   srv_n_lock_max_wait_time  = 0;
00494 
00495 UNIV_INTERN ulint   srv_truncated_status_writes = 0;
00496 
00497 /*
00498   Set the following to 0 if you want InnoDB to write messages on
00499   stderr on startup/shutdown
00500 */
00501 UNIV_INTERN ibool srv_print_verbose_log   = TRUE;
00502 UNIV_INTERN ibool srv_print_innodb_monitor  = FALSE;
00503 UNIV_INTERN ibool srv_print_innodb_lock_monitor = FALSE;
00504 UNIV_INTERN ibool srv_print_innodb_tablespace_monitor = FALSE;
00505 UNIV_INTERN ibool srv_print_innodb_table_monitor = FALSE;
00506 
00507 /* Array of English strings describing the current state of an
00508 i/o handler thread */
00509 
00510 UNIV_INTERN const char* srv_io_thread_op_info[SRV_MAX_N_IO_THREADS];
00511 UNIV_INTERN const char* srv_io_thread_function[SRV_MAX_N_IO_THREADS];
00512 
00513 UNIV_INTERN time_t  srv_last_monitor_time;
00514 
00515 UNIV_INTERN mutex_t srv_innodb_monitor_mutex;
00516 
00517 /* Mutex for locking srv_monitor_file */
00518 UNIV_INTERN mutex_t srv_monitor_file_mutex;
00519 
00520 #ifdef UNIV_PFS_MUTEX
00521 /* Key to register kernel_mutex with performance schema */
00522 UNIV_INTERN mysql_pfs_key_t kernel_mutex_key;
00523 /* Key to protect writing the commit_id to the sys header */
00524 UNIV_INTERN mysql_pfs_key_t     commit_id_mutex_key;
00525 /* Key to register srv_innodb_monitor_mutex with performance schema */
00526 UNIV_INTERN mysql_pfs_key_t srv_innodb_monitor_mutex_key;
00527 /* Key to register srv_monitor_file_mutex with performance schema */
00528 UNIV_INTERN mysql_pfs_key_t srv_monitor_file_mutex_key;
00529 /* Key to register srv_dict_tmpfile_mutex with performance schema */
00530 UNIV_INTERN mysql_pfs_key_t srv_dict_tmpfile_mutex_key;
00531 /* Key to register the mutex with performance schema */
00532 UNIV_INTERN mysql_pfs_key_t srv_misc_tmpfile_mutex_key;
00533 #endif /* UNIV_PFS_MUTEX */
00534 
00535 /* Temporary file for innodb monitor output */
00536 UNIV_INTERN FILE* srv_monitor_file;
00537 /* Mutex for locking srv_dict_tmpfile.
00538 This mutex has a very high rank; threads reserving it should not
00539 be holding any InnoDB latches. */
00540 UNIV_INTERN mutex_t srv_dict_tmpfile_mutex;
00541 /* Temporary file for output from the data dictionary */
00542 UNIV_INTERN FILE* srv_dict_tmpfile;
00543 /* Mutex for locking srv_misc_tmpfile.
00544 This mutex has a very low rank; threads reserving it should not
00545 acquire any further latches or sleep before releasing this one. */
00546 UNIV_INTERN mutex_t srv_misc_tmpfile_mutex;
00547 /* Temporary file for miscellanous diagnostic output */
00548 UNIV_INTERN FILE* srv_misc_tmpfile;
00549 
00550 UNIV_INTERN ulint srv_main_thread_process_no  = 0;
00551 UNIV_INTERN ulint srv_main_thread_id    = 0;
00552 
00553 /* The following count work done by srv_master_thread. */
00554 
00555 /* Iterations by the 'once per second' loop. */
00556 static ulint   srv_main_1_second_loops    = 0;
00557 /* Calls to sleep by the 'once per second' loop. */
00558 static ulint   srv_main_sleeps      = 0;
00559 /* Iterations by the 'once per 10 seconds' loop. */
00560 static ulint   srv_main_10_second_loops   = 0;
00561 /* Iterations of the loop bounded by the 'background_loop' label. */
00562 static ulint   srv_main_background_loops  = 0;
00563 /* Iterations of the loop bounded by the 'flush_loop' label. */
00564 static ulint   srv_main_flush_loops   = 0;
00565 /* Log writes involving flush. */
00566 static ulint   srv_log_writes_and_flush   = 0;
00567 
00568 /* This is only ever touched by the master thread. It records the
00569 time when the last flush of log file has happened. The master
00570 thread ensures that we flush the log files at least once per
00571 second. */
00572 static time_t srv_last_log_flush_time;
00573 
00574 /* The master thread performs various tasks based on the current
00575 state of IO activity and the level of IO utilization is past
00576 intervals. Following macros define thresholds for these conditions. */
00577 #define SRV_PEND_IO_THRESHOLD (PCT_IO(3))
00578 #define SRV_RECENT_IO_ACTIVITY  (PCT_IO(5))
00579 #define SRV_PAST_IO_ACTIVITY  (PCT_IO(200))
00580 
00581 /*
00582   IMPLEMENTATION OF THE SERVER MAIN PROGRAM
00583   =========================================
00584 
00585 There is the following analogue between this database
00586 server and an operating system kernel:
00587 
00588 DB concept      equivalent OS concept
00589 ----------      ---------------------
00590 transaction   --  process;
00591 
00592 query thread    --  thread;
00593 
00594 lock      --  semaphore;
00595 
00596 transaction set to
00597 the rollback state  --  kill signal delivered to a process;
00598 
00599 kernel      --  kernel;
00600 
00601 query thread execution:
00602 (a) without kernel mutex
00603 reserved    --  process executing in user mode;
00604 (b) with kernel mutex reserved
00605       --  process executing in kernel mode;
00606 
00607 The server is controlled by a master thread which runs at
00608 a priority higher than normal, that is, higher than user threads.
00609 It sleeps most of the time, and wakes up, say, every 300 milliseconds,
00610 to check whether there is anything happening in the server which
00611 requires intervention of the master thread. Such situations may be,
00612 for example, when flushing of dirty blocks is needed in the buffer
00613 pool or old version of database rows have to be cleaned away.
00614 
00615 The threads which we call user threads serve the queries of
00616 the clients and input from the console of the server.
00617 They run at normal priority. The server may have several
00618 communications endpoints. A dedicated set of user threads waits
00619 at each of these endpoints ready to receive a client request.
00620 Each request is taken by a single user thread, which then starts
00621 processing and, when the result is ready, sends it to the client
00622 and returns to wait at the same endpoint the thread started from.
00623 
00624 So, we do not have dedicated communication threads listening at
00625 the endpoints and dealing the jobs to dedicated worker threads.
00626 Our architecture saves one thread swithch per request, compared
00627 to the solution with dedicated communication threads
00628 which amounts to 15 microseconds on 100 MHz Pentium
00629 running NT. If the client
00630 is communicating over a network, this saving is negligible, but
00631 if the client resides in the same machine, maybe in an SMP machine
00632 on a different processor from the server thread, the saving
00633 can be important as the threads can communicate over shared
00634 memory with an overhead of a few microseconds.
00635 
00636 We may later implement a dedicated communication thread solution
00637 for those endpoints which communicate over a network.
00638 
00639 Our solution with user threads has two problems: for each endpoint
00640 there has to be a number of listening threads. If there are many
00641 communication endpoints, it may be difficult to set the right number
00642 of concurrent threads in the system, as many of the threads
00643 may always be waiting at less busy endpoints. Another problem
00644 is queuing of the messages, as the server internally does not
00645 offer any queue for jobs.
00646 
00647 Another group of user threads is intended for splitting the
00648 queries and processing them in parallel. Let us call these
00649 parallel communication threads. These threads are waiting for
00650 parallelized tasks, suspended on event semaphores.
00651 
00652 A single user thread waits for input from the console,
00653 like a command to shut the database.
00654 
00655 Utility threads are a different group of threads which takes
00656 care of the buffer pool flushing and other, mainly background
00657 operations, in the server.
00658 Some of these utility threads always run at a lower than normal
00659 priority, so that they are always in background. Some of them
00660 may dynamically boost their priority by the pri_adjust function,
00661 even to higher than normal priority, if their task becomes urgent.
00662 The running of utilities is controlled by high- and low-water marks
00663 of urgency. The urgency may be measured by the number of dirty blocks
00664 in the buffer pool, in the case of the flush thread, for example.
00665 When the high-water mark is exceeded, an utility starts running, until
00666 the urgency drops under the low-water mark. Then the utility thread
00667 suspend itself to wait for an event. The master thread is
00668 responsible of signaling this event when the utility thread is
00669 again needed.
00670 
00671 For each individual type of utility, some threads always remain
00672 at lower than normal priority. This is because pri_adjust is implemented
00673 so that the threads at normal or higher priority control their
00674 share of running time by calling sleep. Thus, if the load of the
00675 system sudenly drops, these threads cannot necessarily utilize
00676 the system fully. The background priority threads make up for this,
00677 starting to run when the load drops.
00678 
00679 When there is no activity in the system, also the master thread
00680 suspends itself to wait for an event making
00681 the server totally silent. The responsibility to signal this
00682 event is on the user thread which again receives a message
00683 from a client.
00684 
00685 There is still one complication in our server design. If a
00686 background utility thread obtains a resource (e.g., mutex) needed by a user
00687 thread, and there is also some other user activity in the system,
00688 the user thread may have to wait indefinitely long for the
00689 resource, as the OS does not schedule a background thread if
00690 there is some other runnable user thread. This problem is called
00691 priority inversion in real-time programming.
00692 
00693 One solution to the priority inversion problem would be to
00694 keep record of which thread owns which resource and
00695 in the above case boost the priority of the background thread
00696 so that it will be scheduled and it can release the resource.
00697 This solution is called priority inheritance in real-time programming.
00698 A drawback of this solution is that the overhead of acquiring a mutex
00699 increases slightly, maybe 0.2 microseconds on a 100 MHz Pentium, because
00700 the thread has to call os_thread_get_curr_id.
00701 This may be compared to 0.5 microsecond overhead for a mutex lock-unlock
00702 pair. Note that the thread
00703 cannot store the information in the resource, say mutex, itself,
00704 because competing threads could wipe out the information if it is
00705 stored before acquiring the mutex, and if it stored afterwards,
00706 the information is outdated for the time of one machine instruction,
00707 at least. (To be precise, the information could be stored to
00708 lock_word in mutex if the machine supports atomic swap.)
00709 
00710 The above solution with priority inheritance may become actual in the
00711 future, but at the moment we plan to implement a more coarse solution,
00712 which could be called a global priority inheritance. If a thread
00713 has to wait for a long time, say 300 milliseconds, for a resource,
00714 we just guess that it may be waiting for a resource owned by a background
00715 thread, and boost the the priority of all runnable background threads
00716 to the normal level. The background threads then themselves adjust
00717 their fixed priority back to background after releasing all resources
00718 they had (or, at some fixed points in their program code).
00719 
00720 What is the performance of the global priority inheritance solution?
00721 We may weigh the length of the wait time 300 milliseconds, during
00722 which the system processes some other thread
00723 to the cost of boosting the priority of each runnable background
00724 thread, rescheduling it, and lowering the priority again.
00725 On 100 MHz Pentium + NT this overhead may be of the order 100
00726 microseconds per thread. So, if the number of runnable background
00727 threads is not very big, say < 100, the cost is tolerable.
00728 Utility threads probably will access resources used by
00729 user threads not very often, so collisions of user threads
00730 to preempted utility threads should not happen very often.
00731 
00732 The thread table contains
00733 information of the current status of each thread existing in the system,
00734 and also the event semaphores used in suspending the master thread
00735 and utility and parallel communication threads when they have nothing to do.
00736 The thread table can be seen as an analogue to the process table
00737 in a traditional Unix implementation.
00738 
00739 The thread table is also used in the global priority inheritance
00740 scheme. This brings in one additional complication: threads accessing
00741 the thread table must have at least normal fixed priority,
00742 because the priority inheritance solution does not work if a background
00743 thread is preempted while possessing the mutex protecting the thread table.
00744 So, if a thread accesses the thread table, its priority has to be
00745 boosted at least to normal. This priority requirement can be seen similar to
00746 the privileged mode used when processing the kernel calls in traditional
00747 Unix.*/
00748 
00749 /* Thread slot in the thread table */
00750 struct srv_slot_struct{
00751   os_thread_id_t  id;   
00752   os_thread_t handle;   
00753   unsigned  type:3;   
00754   unsigned  in_use:1; 
00755   unsigned  suspended:1;  
00757   ib_time_t suspend_time; 
00759   os_event_t  event;    
00761   que_thr_t*  thr;    
00763 };
00764 
00765 /* Table for MySQL threads where they will be suspended to wait for locks */
00766 UNIV_INTERN srv_slot_t* srv_mysql_table = NULL;
00767 
00768 UNIV_INTERN os_event_t  srv_timeout_event;
00769 
00770 UNIV_INTERN os_event_t  srv_monitor_event;
00771 
00772 UNIV_INTERN os_event_t  srv_error_event;
00773 
00774 UNIV_INTERN os_event_t  srv_lock_timeout_thread_event;
00775 
00776 UNIV_INTERN srv_sys_t*  srv_sys = NULL;
00777 
00778 /* padding to prevent other memory update hotspots from residing on
00779 the same memory cache line */
00780 UNIV_INTERN byte  srv_pad1[64];
00781 /* mutex protecting the server, trx structs, query threads, and lock table */
00782 UNIV_INTERN mutex_t*  kernel_mutex_temp;
00783 /* mutex protecting the sys header for writing the commit id */
00784 UNIV_INTERN mutex_t*    commit_id_mutex_temp;
00785 
00786 /* padding to prevent other memory update hotspots from residing on
00787 the same memory cache line */
00788 UNIV_INTERN byte  srv_pad2[64];
00789 
00790 #if 0
00791 /* The following three values measure the urgency of the jobs of
00792 buffer, version, and insert threads. They may vary from 0 - 1000.
00793 The server mutex protects all these variables. The low-water values
00794 tell that the server can acquiesce the utility when the value
00795 drops below this low-water mark. */
00796 
00797 static ulint  srv_meter[SRV_MASTER + 1];
00798 static ulint  srv_meter_low_water[SRV_MASTER + 1];
00799 static ulint  srv_meter_high_water[SRV_MASTER + 1];
00800 static ulint  srv_meter_high_water2[SRV_MASTER + 1];
00801 static ulint  srv_meter_foreground[SRV_MASTER + 1];
00802 #endif
00803 
00804 /***********************************************************************
00805 Prints counters for work done by srv_master_thread. */
00806 static
00807 void
00808 srv_print_master_thread_info(
00809 /*=========================*/
00810   FILE  *file)    /* in: output stream */
00811 {
00812   fprintf(file, "srv_master_thread loops: %lu 1_second, %lu sleeps, "
00813     "%lu 10_second, %lu background, %lu flush\n",
00814     srv_main_1_second_loops, srv_main_sleeps,
00815     srv_main_10_second_loops, srv_main_background_loops,
00816     srv_main_flush_loops);
00817   fprintf(file, "srv_master_thread log flush and writes: %lu\n",
00818           srv_log_writes_and_flush);
00819 }
00820 
00821 /* The following values give info about the activity going on in
00822 the database. They are protected by the server mutex. The arrays
00823 are indexed by the type of the thread. */
00824 
00825 UNIV_INTERN ulint srv_n_threads_active[SRV_MASTER + 1];
00826 UNIV_INTERN ulint srv_n_threads[SRV_MASTER + 1];
00827 
00828 /*********************************************************************/
00830 UNIV_INTERN
00831 void
00832 srv_set_io_thread_op_info(
00833 /*======================*/
00834   ulint   i,  
00835   const char* str)  
00837 {
00838   ut_a(i < SRV_MAX_N_IO_THREADS);
00839 
00840   srv_io_thread_op_info[i] = str;
00841 }
00842 
00843 /*********************************************************************/
00847 static
00848 srv_slot_t*
00849 srv_table_get_nth_slot(
00850 /*===================*/
00851   ulint index)    
00852 {
00853   ut_a(index < OS_THREAD_MAX_N);
00854 
00855   return(srv_sys->threads + index);
00856 }
00857 
00858 /*********************************************************************/
00861 UNIV_INTERN
00862 ulint
00863 srv_get_n_threads(void)
00864 /*===================*/
00865 {
00866   ulint i;
00867   ulint n_threads = 0;
00868 
00869   mutex_enter(&kernel_mutex);
00870 
00871   for (i = SRV_COM; i < SRV_MASTER + 1; i++) {
00872 
00873     n_threads += srv_n_threads[i];
00874   }
00875 
00876   mutex_exit(&kernel_mutex);
00877 
00878   return(n_threads);
00879 }
00880 
00881 /*********************************************************************/
00886 static
00887 ulint
00888 srv_table_reserve_slot(
00889 /*===================*/
00890   enum srv_thread_type  type) 
00891 {
00892   srv_slot_t* slot;
00893   ulint   i;
00894 
00895   ut_a(type > 0);
00896   ut_a(type <= SRV_MASTER);
00897 
00898   i = 0;
00899   slot = srv_table_get_nth_slot(i);
00900 
00901   while (slot->in_use) {
00902     i++;
00903     slot = srv_table_get_nth_slot(i);
00904   }
00905 
00906   ut_a(slot->in_use == FALSE);
00907 
00908   slot->in_use = TRUE;
00909   slot->suspended = FALSE;
00910   slot->type = type;
00911   slot->id = os_thread_get_curr_id();
00912   slot->handle = os_thread_get_curr();
00913 
00914   thr_local_create();
00915 
00916   thr_local_set_slot_no(os_thread_get_curr_id(), i);
00917 
00918   return(i);
00919 }
00920 
00921 /*********************************************************************/
00925 static
00926 os_event_t
00927 srv_suspend_thread(void)
00928 /*====================*/
00929 {
00930   srv_slot_t*   slot;
00931   os_event_t    event;
00932   ulint     slot_no;
00933   enum srv_thread_type  type;
00934 
00935   ut_ad(mutex_own(&kernel_mutex));
00936 
00937   slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
00938 
00939   if (srv_print_thread_releases) {
00940     fprintf(stderr,
00941       "Suspending thread %lu to slot %lu\n",
00942       (ulong) os_thread_get_curr_id(), (ulong) slot_no);
00943   }
00944 
00945   slot = srv_table_get_nth_slot(slot_no);
00946 
00947         type = static_cast<srv_thread_type>(slot->type);
00948 
00949   ut_ad(type >= SRV_WORKER);
00950   ut_ad(type <= SRV_MASTER);
00951 
00952   event = slot->event;
00953 
00954   slot->suspended = TRUE;
00955 
00956   ut_ad(srv_n_threads_active[type] > 0);
00957 
00958   srv_n_threads_active[type]--;
00959 
00960   os_event_reset(event);
00961 
00962   return(event);
00963 }
00964 
00965 /*********************************************************************/
00970 UNIV_INTERN
00971 ulint
00972 srv_release_threads(
00973 /*================*/
00974   enum srv_thread_type  type, 
00975   ulint     n)  
00976 {
00977   srv_slot_t* slot;
00978   ulint   i;
00979   ulint   count = 0;
00980 
00981   ut_ad(type >= SRV_WORKER);
00982   ut_ad(type <= SRV_MASTER);
00983   ut_ad(n > 0);
00984   ut_ad(mutex_own(&kernel_mutex));
00985 
00986   for (i = 0; i < OS_THREAD_MAX_N; i++) {
00987 
00988     slot = srv_table_get_nth_slot(i);
00989 
00990                 if (slot->in_use &&
00991                     (static_cast<srv_thread_type>(slot->type) == type) &&
00992                     slot->suspended) {
00993 
00994       slot->suspended = FALSE;
00995 
00996       srv_n_threads_active[type]++;
00997 
00998       os_event_set(slot->event);
00999 
01000       if (srv_print_thread_releases) {
01001         fprintf(stderr,
01002           "Releasing thread %lu type %lu"
01003           " from slot %lu\n",
01004           (ulong) slot->id, (ulong) type,
01005           (ulong) i);
01006       }
01007 
01008       count++;
01009 
01010       if (count == n) {
01011         break;
01012       }
01013     }
01014   }
01015 
01016   return(count);
01017 }
01018 
01019 /*********************************************************************/
01022 UNIV_INTERN
01023 enum srv_thread_type
01024 srv_get_thread_type(void)
01025 /*=====================*/
01026 {
01027   ulint     slot_no;
01028   srv_slot_t*   slot;
01029   enum srv_thread_type  type;
01030 
01031   mutex_enter(&kernel_mutex);
01032 
01033   slot_no = thr_local_get_slot_no(os_thread_get_curr_id());
01034 
01035   slot = srv_table_get_nth_slot(slot_no);
01036 
01037         type = static_cast<srv_thread_type>(slot->type);
01038 
01039   ut_ad(type >= SRV_WORKER);
01040   ut_ad(type <= SRV_MASTER);
01041 
01042   mutex_exit(&kernel_mutex);
01043 
01044   return(type);
01045 }
01046 
01047 /*********************************************************************/
01049 UNIV_INTERN
01050 void
01051 srv_init(void)
01052 /*==========*/
01053 {
01054   srv_conc_slot_t*  conc_slot;
01055   srv_slot_t*   slot;
01056   ulint     i;
01057 
01058         srv_sys = static_cast<srv_sys_t *>(mem_alloc(sizeof(srv_sys_t)));
01059 
01060         kernel_mutex_temp = static_cast<ib_mutex_t *>(mem_alloc(sizeof(mutex_t)));
01061   mutex_create(kernel_mutex_key, &kernel_mutex, SYNC_KERNEL);
01062 
01063   commit_id_mutex_temp = static_cast<ib_mutex_t *>(mem_alloc(sizeof(mutex_t)));
01064   mutex_create(commit_id_mutex_key, &commit_id_mutex, SYNC_COMMIT_ID_LOCK);
01065 
01066   mutex_create(srv_innodb_monitor_mutex_key,
01067          &srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
01068 
01069         srv_sys->threads = static_cast<srv_table_t *>(mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t)));
01070 
01071   for (i = 0; i < OS_THREAD_MAX_N; i++) {
01072     slot = srv_table_get_nth_slot(i);
01073     slot->in_use = FALSE;
01074     slot->type=0; /* Avoid purify errors */
01075     slot->event = os_event_create(NULL);
01076     ut_a(slot->event);
01077   }
01078 
01079         srv_mysql_table = static_cast<srv_slot_t *>(mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t)));
01080 
01081   for (i = 0; i < OS_THREAD_MAX_N; i++) {
01082     slot = srv_mysql_table + i;
01083     slot->in_use = FALSE;
01084     slot->type = 0;
01085     slot->event = os_event_create(NULL);
01086     ut_a(slot->event);
01087   }
01088 
01089   srv_error_event = os_event_create(NULL);
01090 
01091   srv_timeout_event = os_event_create(NULL);
01092 
01093   srv_monitor_event = os_event_create(NULL);
01094 
01095   srv_lock_timeout_thread_event = os_event_create(NULL);
01096 
01097   for (i = 0; i < SRV_MASTER + 1; i++) {
01098     srv_n_threads_active[i] = 0;
01099     srv_n_threads[i] = 0;
01100 #if 0
01101     srv_meter[i] = 30;
01102     srv_meter_low_water[i] = 50;
01103     srv_meter_high_water[i] = 100;
01104     srv_meter_high_water2[i] = 200;
01105     srv_meter_foreground[i] = 250;
01106 #endif
01107   }
01108 
01109   UT_LIST_INIT(srv_sys->tasks);
01110 
01111   /* Create dummy indexes for infimum and supremum records */
01112 
01113   dict_ind_init();
01114 
01115   /* Init the server concurrency restriction data structures */
01116 
01117   os_fast_mutex_init(&srv_conc_mutex);
01118 
01119   UT_LIST_INIT(srv_conc_queue);
01120 
01121         srv_conc_slots = static_cast<srv_conc_slot_t *>(mem_alloc(OS_THREAD_MAX_N * sizeof(srv_conc_slot_t)));
01122 
01123   for (i = 0; i < OS_THREAD_MAX_N; i++) {
01124     conc_slot = srv_conc_slots + i;
01125     conc_slot->reserved = FALSE;
01126     conc_slot->event = os_event_create(NULL);
01127     ut_a(conc_slot->event);
01128   }
01129 
01130   /* Initialize some INFORMATION SCHEMA internal structures */
01131   trx_i_s_cache_init(trx_i_s_cache);
01132 }
01133 
01134 /*********************************************************************/
01136 UNIV_INTERN
01137 void
01138 srv_free(void)
01139 /*==========*/
01140 {
01141   os_fast_mutex_free(&srv_conc_mutex);
01142   mem_free(srv_conc_slots);
01143   srv_conc_slots = NULL;
01144 
01145   mem_free(srv_sys->threads);
01146   mem_free(srv_sys);
01147   srv_sys = NULL;
01148 
01149   mem_free(kernel_mutex_temp);
01150   kernel_mutex_temp = NULL;
01151   mem_free(srv_mysql_table);
01152   srv_mysql_table = NULL;
01153 
01154   mem_free(commit_id_mutex_temp);
01155   commit_id_mutex_temp = NULL;
01156 
01157   trx_i_s_cache_free(trx_i_s_cache);
01158 }
01159 
01160 /*********************************************************************/
01163 UNIV_INTERN
01164 void
01165 srv_general_init(void)
01166 /*==================*/
01167 {
01168   ut_mem_init();
01169   /* Reset the system variables in the recovery module. */
01170   recv_sys_var_init();
01171   os_sync_init();
01172   sync_init();
01173   mem_init(srv_mem_pool_size);
01174   thr_local_init();
01175 }
01176 
01177 /*======================= InnoDB Server FIFO queue =======================*/
01178 
01179 /* Maximum allowable purge history length.  <=0 means 'infinite'. */
01180 UNIV_INTERN ulong srv_max_purge_lag   = 0;
01181 
01182 /*********************************************************************/
01185 UNIV_INTERN
01186 void
01187 srv_conc_enter_innodb(
01188 /*==================*/
01189   trx_t*  trx)  
01191 {
01192   ibool     has_slept = FALSE;
01193   srv_conc_slot_t*  slot    = NULL;
01194   ulint     i;
01195 
01196   if (trx->mysql_thd != NULL
01197       && thd_is_replication_slave_thread(trx->mysql_thd)) {
01198 
01199     UT_WAIT_FOR(srv_conc_n_threads
01200           < (lint)srv_thread_concurrency,
01201           srv_replication_delay * 1000);
01202 
01203     return;
01204   }
01205 
01206   /* If trx has 'free tickets' to enter the engine left, then use one
01207   such ticket */
01208 
01209   if (trx->n_tickets_to_enter_innodb > 0) {
01210     trx->n_tickets_to_enter_innodb--;
01211 
01212     return;
01213   }
01214 
01215   os_fast_mutex_lock(&srv_conc_mutex);
01216 retry:
01217   if (trx->declared_to_be_inside_innodb) {
01218     ut_print_timestamp(stderr);
01219     fputs("  InnoDB: Error: trying to declare trx"
01220           " to enter InnoDB, but\n"
01221           "InnoDB: it already is declared.\n", stderr);
01222     trx_print(stderr, trx, 0);
01223     putc('\n', stderr);
01224     os_fast_mutex_unlock(&srv_conc_mutex);
01225 
01226     return;
01227   }
01228 
01229   ut_ad(srv_conc_n_threads >= 0);
01230 
01231   if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
01232 
01233     srv_conc_n_threads++;
01234     trx->declared_to_be_inside_innodb = TRUE;
01235     trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
01236 
01237     os_fast_mutex_unlock(&srv_conc_mutex);
01238 
01239     return;
01240   }
01241 
01242   /* If the transaction is not holding resources, let it sleep
01243   for SRV_THREAD_SLEEP_DELAY microseconds, and try again then */
01244 
01245   if (!has_slept && !trx->has_search_latch
01246       && NULL == UT_LIST_GET_FIRST(trx->trx_locks)) {
01247 
01248     has_slept = TRUE; /* We let it sleep only once to avoid
01249           starvation */
01250 
01251     srv_conc_n_waiting_threads++;
01252 
01253     os_fast_mutex_unlock(&srv_conc_mutex);
01254 
01255     trx->op_info = "sleeping before joining InnoDB queue";
01256 
01257     /* Peter Zaitsev suggested that we take the sleep away
01258     altogether. But the sleep may be good in pathological
01259     situations of lots of thread switches. Simply put some
01260     threads aside for a while to reduce the number of thread
01261     switches. */
01262     if (SRV_THREAD_SLEEP_DELAY > 0) {
01263       os_thread_sleep(SRV_THREAD_SLEEP_DELAY);
01264     }
01265 
01266     trx->op_info = "";
01267 
01268     os_fast_mutex_lock(&srv_conc_mutex);
01269 
01270     srv_conc_n_waiting_threads--;
01271 
01272     goto retry;
01273   }
01274 
01275   /* Too many threads inside: put the current thread to a queue */
01276 
01277   for (i = 0; i < OS_THREAD_MAX_N; i++) {
01278     slot = srv_conc_slots + i;
01279 
01280     if (!slot->reserved) {
01281 
01282       break;
01283     }
01284   }
01285 
01286   if (i == OS_THREAD_MAX_N) {
01287     /* Could not find a free wait slot, we must let the
01288     thread enter */
01289 
01290     srv_conc_n_threads++;
01291     trx->declared_to_be_inside_innodb = TRUE;
01292     trx->n_tickets_to_enter_innodb = 0;
01293 
01294     os_fast_mutex_unlock(&srv_conc_mutex);
01295 
01296     return;
01297   }
01298 
01299   /* Release possible search system latch this thread has */
01300   if (trx->has_search_latch) {
01301     trx_search_latch_release_if_reserved(trx);
01302   }
01303 
01304   /* Add to the queue */
01305   slot->reserved = TRUE;
01306   slot->wait_ended = FALSE;
01307 
01308   UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot);
01309 
01310   os_event_reset(slot->event);
01311 
01312   srv_conc_n_waiting_threads++;
01313 
01314   os_fast_mutex_unlock(&srv_conc_mutex);
01315 
01316   /* Go to wait for the event; when a thread leaves InnoDB it will
01317   release this thread */
01318 
01319   trx->op_info = "waiting in InnoDB queue";
01320 
01321   os_event_wait(slot->event);
01322 
01323   trx->op_info = "";
01324 
01325   os_fast_mutex_lock(&srv_conc_mutex);
01326 
01327   srv_conc_n_waiting_threads--;
01328 
01329   /* NOTE that the thread which released this thread already
01330   incremented the thread counter on behalf of this thread */
01331 
01332   slot->reserved = FALSE;
01333 
01334   UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot);
01335 
01336   trx->declared_to_be_inside_innodb = TRUE;
01337   trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
01338 
01339   os_fast_mutex_unlock(&srv_conc_mutex);
01340 }
01341 
01342 /*********************************************************************/
01345 UNIV_INTERN
01346 void
01347 srv_conc_force_enter_innodb(
01348 /*========================*/
01349   trx_t*  trx)  
01351 {
01352   if (UNIV_LIKELY(!srv_thread_concurrency)) {
01353 
01354     return;
01355   }
01356 
01357   ut_ad(srv_conc_n_threads >= 0);
01358 
01359   os_fast_mutex_lock(&srv_conc_mutex);
01360 
01361   srv_conc_n_threads++;
01362   trx->declared_to_be_inside_innodb = TRUE;
01363   trx->n_tickets_to_enter_innodb = 1;
01364 
01365   os_fast_mutex_unlock(&srv_conc_mutex);
01366 }
01367 
01368 /*********************************************************************/
01371 UNIV_INTERN
01372 void
01373 srv_conc_force_exit_innodb(
01374 /*=======================*/
01375   trx_t*  trx)  
01377 {
01378   srv_conc_slot_t*  slot  = NULL;
01379 
01380   if (trx->mysql_thd != NULL
01381       && thd_is_replication_slave_thread(trx->mysql_thd)) {
01382 
01383     return;
01384   }
01385 
01386   if (trx->declared_to_be_inside_innodb == FALSE) {
01387 
01388     return;
01389   }
01390 
01391   os_fast_mutex_lock(&srv_conc_mutex);
01392 
01393   ut_ad(srv_conc_n_threads > 0);
01394   srv_conc_n_threads--;
01395   trx->declared_to_be_inside_innodb = FALSE;
01396   trx->n_tickets_to_enter_innodb = 0;
01397 
01398   if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
01399     /* Look for a slot where a thread is waiting and no other
01400     thread has yet released the thread */
01401 
01402     slot = UT_LIST_GET_FIRST(srv_conc_queue);
01403 
01404     while (slot && slot->wait_ended == TRUE) {
01405       slot = UT_LIST_GET_NEXT(srv_conc_queue, slot);
01406     }
01407 
01408     if (slot != NULL) {
01409       slot->wait_ended = TRUE;
01410 
01411       /* We increment the count on behalf of the released
01412       thread */
01413 
01414       srv_conc_n_threads++;
01415     }
01416   }
01417 
01418   os_fast_mutex_unlock(&srv_conc_mutex);
01419 
01420   if (slot != NULL) {
01421     os_event_set(slot->event);
01422   }
01423 }
01424 
01425 /*********************************************************************/
01427 UNIV_INTERN
01428 void
01429 srv_conc_exit_innodb(
01430 /*=================*/
01431   trx_t*  trx)  
01433 {
01434   if (trx->n_tickets_to_enter_innodb > 0) {
01435     /* We will pretend the thread is still inside InnoDB though it
01436     now leaves the InnoDB engine. In this way we save
01437     a lot of semaphore operations. srv_conc_force_exit_innodb is
01438     used to declare the thread definitely outside InnoDB. It
01439     should be called when there is a lock wait or an SQL statement
01440     ends. */
01441 
01442     return;
01443   }
01444 
01445   srv_conc_force_exit_innodb(trx);
01446 }
01447 
01448 /*========================================================================*/
01449 
01450 /*********************************************************************/
01453 static
01454 ulint
01455 srv_normalize_init_values(void)
01456 /*===========================*/
01457 {
01458   ulint n;
01459   ulint i;
01460 
01461   n = srv_n_data_files;
01462 
01463   for (i = 0; i < n; i++) {
01464     srv_data_file_sizes[i] = srv_data_file_sizes[i]
01465       * ((1024 * 1024) / UNIV_PAGE_SIZE);
01466   }
01467 
01468   srv_last_file_size_max = srv_last_file_size_max
01469     * ((1024 * 1024) / UNIV_PAGE_SIZE);
01470 
01471   srv_log_file_size = srv_log_file_size / UNIV_PAGE_SIZE;
01472 
01473   srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
01474 
01475   srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
01476 
01477   return(DB_SUCCESS);
01478 }
01479 
01480 /*********************************************************************/
01483 UNIV_INTERN
01484 ulint
01485 srv_boot(void)
01486 /*==========*/
01487 {
01488   ulint err;
01489 
01490   /* Transform the init parameter values given by MySQL to
01491   use units we use inside InnoDB: */
01492 
01493   err = srv_normalize_init_values();
01494 
01495   if (err != DB_SUCCESS) {
01496     return(err);
01497   }
01498 
01499   /* Initialize synchronization primitives, memory management, and thread
01500   local storage */
01501 
01502   srv_general_init();
01503 
01504   /* Initialize this module */
01505 
01506   srv_init();
01507 
01508   return(DB_SUCCESS);
01509 }
01510 
01511 /*********************************************************************/
01515 static
01516 srv_slot_t*
01517 srv_table_reserve_slot_for_mysql(void)
01518 /*==================================*/
01519 {
01520   srv_slot_t* slot;
01521   ulint   i;
01522 
01523   ut_ad(mutex_own(&kernel_mutex));
01524 
01525   i = 0;
01526   slot = srv_mysql_table + i;
01527 
01528   while (slot->in_use) {
01529     i++;
01530 
01531     if (i >= OS_THREAD_MAX_N) {
01532 
01533       ut_print_timestamp(stderr);
01534 
01535       fprintf(stderr,
01536         "  InnoDB: There appear to be %lu MySQL"
01537         " threads currently waiting\n"
01538         "InnoDB: inside InnoDB, which is the"
01539         " upper limit. Cannot continue operation.\n"
01540         "InnoDB: We intentionally generate"
01541         " a seg fault to print a stack trace\n"
01542         "InnoDB: on Linux. But first we print"
01543         " a list of waiting threads.\n", (ulong) i);
01544 
01545       for (i = 0; i < OS_THREAD_MAX_N; i++) {
01546 
01547         slot = srv_mysql_table + i;
01548 
01549         fprintf(stderr,
01550           "Slot %lu: thread id %lu, type %lu,"
01551           " in use %lu, susp %lu, time %lu\n",
01552           (ulong) i,
01553           (ulong) os_thread_pf(slot->id),
01554           (ulong) slot->type,
01555           (ulong) slot->in_use,
01556           (ulong) slot->suspended,
01557           (ulong) difftime(ut_time(),
01558                slot->suspend_time));
01559       }
01560 
01561       ut_error;
01562     }
01563 
01564     slot = srv_mysql_table + i;
01565   }
01566 
01567   ut_a(slot->in_use == FALSE);
01568 
01569   slot->in_use = TRUE;
01570   slot->id = os_thread_get_curr_id();
01571   slot->handle = os_thread_get_curr();
01572 
01573   return(slot);
01574 }
01575 
01576 /***************************************************************/
01582 UNIV_INTERN
01583 void
01584 srv_suspend_mysql_thread(
01585 /*=====================*/
01586   que_thr_t*  thr)  
01588 {
01589   srv_slot_t* slot;
01590   os_event_t  event;
01591   double    wait_time;
01592   trx_t*    trx;
01593   ulint   had_dict_lock;
01594   ibool   was_declared_inside_innodb  = FALSE;
01595   ib_int64_t  start_time      = 0;
01596   ib_int64_t  finish_time;
01597   ulint   diff_time;
01598   ulint   sec;
01599   ulint   ms;
01600   ulong   lock_wait_timeout;
01601 
01602   ut_ad(!mutex_own(&kernel_mutex));
01603 
01604   trx = thr_get_trx(thr);
01605 
01606   os_event_set(srv_lock_timeout_thread_event);
01607 
01608   mutex_enter(&kernel_mutex);
01609 
01610   trx->error_state = DB_SUCCESS;
01611 
01612   if (thr->state == QUE_THR_RUNNING) {
01613 
01614     ut_ad(thr->is_active == TRUE);
01615 
01616     /* The lock has already been released or this transaction
01617     was chosen as a deadlock victim: no need to suspend */
01618 
01619     if (trx->was_chosen_as_deadlock_victim) {
01620 
01621       trx->error_state = DB_DEADLOCK;
01622       trx->was_chosen_as_deadlock_victim = FALSE;
01623     }
01624 
01625     mutex_exit(&kernel_mutex);
01626 
01627     return;
01628   }
01629 
01630   ut_ad(thr->is_active == FALSE);
01631 
01632   slot = srv_table_reserve_slot_for_mysql();
01633 
01634   event = slot->event;
01635 
01636   slot->thr = thr;
01637 
01638   os_event_reset(event);
01639 
01640   slot->suspend_time = ut_time();
01641 
01642   if (thr->lock_state == QUE_THR_LOCK_ROW) {
01643     srv_n_lock_wait_count++;
01644     srv_n_lock_wait_current_count++;
01645 
01646     if (ut_usectime(&sec, &ms) == -1) {
01647       start_time = -1;
01648     } else {
01649       start_time = (ib_int64_t) sec * 1000000 + ms;
01650     }
01651   }
01652   /* Wake the lock timeout monitor thread, if it is suspended */
01653 
01654   os_event_set(srv_lock_timeout_thread_event);
01655 
01656   mutex_exit(&kernel_mutex);
01657 
01658   if (trx->declared_to_be_inside_innodb) {
01659 
01660     was_declared_inside_innodb = TRUE;
01661 
01662     /* We must declare this OS thread to exit InnoDB, since a
01663     possible other thread holding a lock which this thread waits
01664     for must be allowed to enter, sooner or later */
01665 
01666     srv_conc_force_exit_innodb(trx);
01667   }
01668 
01669   had_dict_lock = trx->dict_operation_lock_mode;
01670 
01671   switch (had_dict_lock) {
01672   case RW_S_LATCH:
01673     /* Release foreign key check latch */
01674     row_mysql_unfreeze_data_dictionary(trx);
01675     break;
01676   case RW_X_LATCH:
01677     /* There should never be a lock wait when the
01678     dictionary latch is reserved in X mode.  Dictionary
01679     transactions should only acquire locks on dictionary
01680     tables, not other tables. All access to dictionary
01681     tables should be covered by dictionary
01682     transactions. */
01683     ut_print_timestamp(stderr);
01684     fputs("  InnoDB: Error: dict X latch held in "
01685           "srv_suspend_mysql_thread\n", stderr);
01686     /* This should never occur. This incorrect handling
01687     was added in the early development of
01688     ha_innobase::add_index() in InnoDB Plugin 1.0. */
01689     /* Release fast index creation latch */
01690     row_mysql_unlock_data_dictionary(trx);
01691     break;
01692   }
01693 
01694   ut_a(trx->dict_operation_lock_mode == 0);
01695 
01696   /* Suspend this thread and wait for the event. */
01697 
01698   os_event_wait(event);
01699 
01700   /* After resuming, reacquire the data dictionary latch if
01701   necessary. */
01702 
01703   switch (had_dict_lock) {
01704   case RW_S_LATCH:
01705     row_mysql_freeze_data_dictionary(trx);
01706     break;
01707   case RW_X_LATCH:
01708     /* This should never occur. This incorrect handling
01709     was added in the early development of
01710     ha_innobase::add_index() in InnoDB Plugin 1.0. */
01711     row_mysql_lock_data_dictionary(trx);
01712     break;
01713   }
01714 
01715   if (was_declared_inside_innodb) {
01716 
01717     /* Return back inside InnoDB */
01718 
01719     srv_conc_force_enter_innodb(trx);
01720   }
01721 
01722   mutex_enter(&kernel_mutex);
01723 
01724   /* Release the slot for others to use */
01725 
01726   slot->in_use = FALSE;
01727 
01728   wait_time = ut_difftime(ut_time(), slot->suspend_time);
01729 
01730   if (thr->lock_state == QUE_THR_LOCK_ROW) {
01731     if (ut_usectime(&sec, &ms) == -1) {
01732       finish_time = -1;
01733     } else {
01734       finish_time = (ib_int64_t) sec * 1000000 + ms;
01735     }
01736 
01737     diff_time = (ulint) (finish_time - start_time);
01738 
01739     srv_n_lock_wait_current_count--;
01740     srv_n_lock_wait_time = srv_n_lock_wait_time + diff_time;
01741     if (diff_time > srv_n_lock_max_wait_time &&
01742         /* only update the variable if we successfully
01743         retrieved the start and finish times. See Bug#36819. */
01744         start_time != -1 && finish_time != -1) {
01745       srv_n_lock_max_wait_time = diff_time;
01746     }
01747 
01748     /* Record the lock wait time for this thread */
01749     thd_set_lock_wait_time(trx->mysql_thd, diff_time);
01750   }
01751 
01752   if (trx->was_chosen_as_deadlock_victim) {
01753 
01754     trx->error_state = DB_DEADLOCK;
01755     trx->was_chosen_as_deadlock_victim = FALSE;
01756   }
01757 
01758   mutex_exit(&kernel_mutex);
01759 
01760   /* InnoDB system transactions (such as the purge, and
01761   incomplete transactions that are being rolled back after crash
01762   recovery) will use the global value of
01763   innodb_lock_wait_timeout, because trx->mysql_thd == NULL. */
01764   lock_wait_timeout = thd_lock_wait_timeout(trx->mysql_thd);
01765 
01766   if (lock_wait_timeout < 100000000
01767       && wait_time > (double) lock_wait_timeout) {
01768 
01769     trx->error_state = DB_LOCK_WAIT_TIMEOUT;
01770   }
01771 
01772   if (trx_is_interrupted(trx)) {
01773 
01774     trx->error_state = DB_INTERRUPTED;
01775   }
01776 }
01777 
01778 /********************************************************************/
01781 UNIV_INTERN
01782 void
01783 srv_release_mysql_thread_if_suspended(
01784 /*==================================*/
01785   que_thr_t*  thr)  
01787 {
01788   srv_slot_t* slot;
01789   ulint   i;
01790 
01791   ut_ad(mutex_own(&kernel_mutex));
01792 
01793   for (i = 0; i < OS_THREAD_MAX_N; i++) {
01794 
01795     slot = srv_mysql_table + i;
01796 
01797     if (slot->in_use && slot->thr == thr) {
01798       /* Found */
01799 
01800       os_event_set(slot->event);
01801 
01802       return;
01803     }
01804   }
01805 
01806   /* not found */
01807 }
01808 
01809 /******************************************************************/
01811 static
01812 void
01813 srv_refresh_innodb_monitor_stats(void)
01814 /*==================================*/
01815 {
01816   mutex_enter(&srv_innodb_monitor_mutex);
01817 
01818   srv_last_monitor_time = time(NULL);
01819 
01820   os_aio_refresh_stats();
01821 
01822   btr_cur_n_sea_old = btr_cur_n_sea;
01823   btr_cur_n_non_sea_old = btr_cur_n_non_sea;
01824 
01825   log_refresh_stats();
01826 
01827   buf_refresh_io_stats_all();
01828 
01829   srv_n_rows_inserted_old = srv_n_rows_inserted;
01830   srv_n_rows_updated_old = srv_n_rows_updated;
01831   srv_n_rows_deleted_old = srv_n_rows_deleted;
01832   srv_n_rows_read_old = srv_n_rows_read;
01833 
01834   mutex_exit(&srv_innodb_monitor_mutex);
01835 }
01836 
01837 /******************************************************************/
01841 UNIV_INTERN
01842 ibool
01843 srv_printf_innodb_monitor(
01844 /*======================*/
01845   FILE* file,   
01846   ibool nowait,   
01847   ulint*  trx_start,  
01849   ulint*  trx_end)  
01851 {
01852   double  time_elapsed;
01853   time_t  current_time;
01854   ulint n_reserved;
01855   ibool ret;
01856 
01857   mutex_enter(&srv_innodb_monitor_mutex);
01858 
01859   current_time = time(NULL);
01860 
01861   /* We add 0.001 seconds to time_elapsed to prevent division
01862   by zero if two users happen to call SHOW INNODB STATUS at the same
01863   time */
01864 
01865   time_elapsed = difftime(current_time, srv_last_monitor_time)
01866     + 0.001;
01867 
01868   srv_last_monitor_time = time(NULL);
01869 
01870   fputs("\n=====================================\n", file);
01871 
01872   ut_print_timestamp(file);
01873   fprintf(file,
01874     " INNODB MONITOR OUTPUT\n"
01875     "=====================================\n"
01876     "Per second averages calculated from the last %lu seconds\n",
01877     (ulong)time_elapsed);
01878 
01879   fputs("-----------------\n"
01880         "BACKGROUND THREAD\n"
01881         "-----------------\n", file);
01882   srv_print_master_thread_info(file);
01883 
01884   fputs("----------\n"
01885         "SEMAPHORES\n"
01886         "----------\n", file);
01887   sync_print(file);
01888 
01889   /* Conceptually, srv_innodb_monitor_mutex has a very high latching
01890   order level in sync0sync.h, while dict_foreign_err_mutex has a very
01891   low level 135. Therefore we can reserve the latter mutex here without
01892   a danger of a deadlock of threads. */
01893 
01894   mutex_enter(&dict_foreign_err_mutex);
01895 
01896   if (ftell(dict_foreign_err_file) != 0L) {
01897     fputs("------------------------\n"
01898           "LATEST FOREIGN KEY ERROR\n"
01899           "------------------------\n", file);
01900     ut_copy_file(file, dict_foreign_err_file);
01901   }
01902 
01903   mutex_exit(&dict_foreign_err_mutex);
01904 
01905   /* Only if lock_print_info_summary proceeds correctly,
01906   before we call the lock_print_info_all_transactions
01907   to print all the lock information. */
01908   ret = lock_print_info_summary(file, nowait);
01909 
01910   if (ret) {
01911     if (trx_start) {
01912       long  t = ftell(file);
01913       if (t < 0) {
01914         *trx_start = ULINT_UNDEFINED;
01915       } else {
01916         *trx_start = (ulint) t;
01917       }
01918     }
01919     lock_print_info_all_transactions(file);
01920     if (trx_end) {
01921       long  t = ftell(file);
01922       if (t < 0) {
01923         *trx_end = ULINT_UNDEFINED;
01924       } else {
01925         *trx_end = (ulint) t;
01926       }
01927     }
01928   }
01929 
01930   fputs("--------\n"
01931         "FILE I/O\n"
01932         "--------\n", file);
01933   os_aio_print(file);
01934 
01935   fputs("-------------------------------------\n"
01936         "INSERT BUFFER AND ADAPTIVE HASH INDEX\n"
01937         "-------------------------------------\n", file);
01938   ibuf_print(file);
01939 
01940   ha_print_info(file, btr_search_sys->hash_index);
01941 
01942   fprintf(file,
01943     "%.2f hash searches/s, %.2f non-hash searches/s\n",
01944     (btr_cur_n_sea - btr_cur_n_sea_old)
01945     / time_elapsed,
01946     (btr_cur_n_non_sea - btr_cur_n_non_sea_old)
01947     / time_elapsed);
01948   btr_cur_n_sea_old = btr_cur_n_sea;
01949   btr_cur_n_non_sea_old = btr_cur_n_non_sea;
01950 
01951   fputs("---\n"
01952         "LOG\n"
01953         "---\n", file);
01954   log_print(file);
01955 
01956   fputs("----------------------\n"
01957         "BUFFER POOL AND MEMORY\n"
01958         "----------------------\n", file);
01959   fprintf(file,
01960     "Total memory allocated " ULINTPF
01961     "; in additional pool allocated " ULINTPF "\n",
01962     ut_total_allocated_memory,
01963     mem_pool_get_reserved(mem_comm_pool));
01964   fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
01965     dict_sys->size);
01966 
01967   buf_print_io(file);
01968 
01969   fputs("--------------\n"
01970         "ROW OPERATIONS\n"
01971         "--------------\n", file);
01972   fprintf(file, "%ld queries inside InnoDB, %lu queries in queue\n",
01973     (long) srv_conc_n_threads,
01974     (ulong) srv_conc_n_waiting_threads);
01975 
01976   fprintf(file, "%lu read views open inside InnoDB\n",
01977     static_cast<ulint>(UT_LIST_GET_LEN(trx_sys->view_list)));
01978 
01979   n_reserved = fil_space_get_n_reserved_extents(0);
01980   if (n_reserved > 0) {
01981     fprintf(file,
01982       "%lu tablespace extents now reserved for"
01983       " B-tree split operations\n",
01984       (ulong) n_reserved);
01985   }
01986 
01987 #ifdef UNIV_LINUX
01988   fprintf(file, "Main thread process no. %lu, id %lu, state: %s\n",
01989     (ulong) srv_main_thread_process_no,
01990     (ulong) srv_main_thread_id,
01991     srv_main_thread_op_info);
01992 #else
01993   fprintf(file, "Main thread id %lu, state: %s\n",
01994     (ulong) srv_main_thread_id,
01995     srv_main_thread_op_info);
01996 #endif
01997   fprintf(file,
01998     "Number of rows inserted " ULINTPF
01999     ", updated " ULINTPF ", deleted " ULINTPF
02000     ", read " ULINTPF "\n",
02001     srv_n_rows_inserted,
02002     srv_n_rows_updated,
02003     srv_n_rows_deleted,
02004     srv_n_rows_read);
02005   fprintf(file,
02006     "%.2f inserts/s, %.2f updates/s,"
02007     " %.2f deletes/s, %.2f reads/s\n",
02008     (srv_n_rows_inserted - srv_n_rows_inserted_old)
02009     / time_elapsed,
02010     (srv_n_rows_updated - srv_n_rows_updated_old)
02011     / time_elapsed,
02012     (srv_n_rows_deleted - srv_n_rows_deleted_old)
02013     / time_elapsed,
02014     (srv_n_rows_read - srv_n_rows_read_old)
02015     / time_elapsed);
02016 
02017   srv_n_rows_inserted_old = srv_n_rows_inserted;
02018   srv_n_rows_updated_old = srv_n_rows_updated;
02019   srv_n_rows_deleted_old = srv_n_rows_deleted;
02020   srv_n_rows_read_old = srv_n_rows_read;
02021 
02022   fputs("----------------------------\n"
02023         "END OF INNODB MONITOR OUTPUT\n"
02024         "============================\n", file);
02025   mutex_exit(&srv_innodb_monitor_mutex);
02026   fflush(file);
02027 
02028   return(ret);
02029 }
02030 
02031 /******************************************************************/
02033 UNIV_INTERN
02034 void
02035 srv_export_innodb_status(void)
02036 /*==========================*/
02037 {
02038   buf_pool_stat_t stat;
02039   ulint   LRU_len;
02040   ulint   free_len;
02041   ulint   flush_list_len;
02042 
02043   buf_get_total_stat(&stat);
02044   buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len);
02045 
02046   mutex_enter(&srv_innodb_monitor_mutex);
02047 
02048   export_vars.innodb_data_pending_reads
02049     = os_n_pending_reads;
02050   export_vars.innodb_data_pending_writes
02051     = os_n_pending_writes;
02052   export_vars.innodb_data_pending_fsyncs
02053     = fil_n_pending_log_flushes
02054     + fil_n_pending_tablespace_flushes;
02055   export_vars.innodb_data_fsyncs = os_n_fsyncs;
02056   export_vars.innodb_data_read = srv_data_read;
02057   export_vars.innodb_data_reads = os_n_file_reads;
02058   export_vars.innodb_data_writes = os_n_file_writes;
02059   export_vars.innodb_data_written = srv_data_written;
02060   export_vars.innodb_buffer_pool_read_requests = stat.n_page_gets;
02061   export_vars.innodb_buffer_pool_write_requests
02062     = srv_buf_pool_write_requests;
02063   export_vars.innodb_buffer_pool_wait_free = srv_buf_pool_wait_free;
02064   export_vars.innodb_buffer_pool_pages_flushed = srv_buf_pool_flushed;
02065   export_vars.innodb_buffer_pool_reads = srv_buf_pool_reads;
02066   export_vars.innodb_buffer_pool_read_ahead
02067     = stat.n_ra_pages_read;
02068   export_vars.innodb_buffer_pool_read_ahead_evicted
02069     = stat.n_ra_pages_evicted;
02070   export_vars.innodb_buffer_pool_pages_data = LRU_len;
02071   export_vars.innodb_buffer_pool_pages_dirty = flush_list_len;
02072   export_vars.innodb_buffer_pool_pages_free = free_len;
02073 #ifdef UNIV_DEBUG
02074   export_vars.innodb_buffer_pool_pages_latched
02075     = buf_get_latched_pages_number();
02076 #endif /* UNIV_DEBUG */
02077   export_vars.innodb_buffer_pool_pages_total = buf_pool_get_n_pages();
02078 
02079   export_vars.innodb_buffer_pool_pages_misc
02080           = buf_pool_get_n_pages() - LRU_len - free_len;
02081 #ifdef HAVE_ATOMIC_BUILTINS
02082   export_vars.innodb_have_atomic_builtins = 1;
02083 #else
02084   export_vars.innodb_have_atomic_builtins = 0;
02085 #endif
02086   export_vars.innodb_page_size = UNIV_PAGE_SIZE;
02087   export_vars.innodb_log_waits = srv_log_waits;
02088   export_vars.innodb_os_log_written = srv_os_log_written;
02089   export_vars.innodb_os_log_fsyncs = fil_n_log_flushes;
02090   export_vars.innodb_os_log_pending_fsyncs = fil_n_pending_log_flushes;
02091   export_vars.innodb_os_log_pending_writes = srv_os_log_pending_writes;
02092   export_vars.innodb_log_write_requests = srv_log_write_requests;
02093   export_vars.innodb_log_writes = srv_log_writes;
02094   export_vars.innodb_dblwr_pages_written = srv_dblwr_pages_written;
02095   export_vars.innodb_dblwr_writes = srv_dblwr_writes;
02096   export_vars.innodb_pages_created = stat.n_pages_created;
02097   export_vars.innodb_pages_read = stat.n_pages_read;
02098   export_vars.innodb_pages_written = stat.n_pages_written;
02099   export_vars.innodb_row_lock_waits = srv_n_lock_wait_count;
02100   export_vars.innodb_row_lock_current_waits
02101     = srv_n_lock_wait_current_count;
02102   export_vars.innodb_row_lock_time = srv_n_lock_wait_time / 1000;
02103   if (srv_n_lock_wait_count > 0) {
02104     export_vars.innodb_row_lock_time_avg = (ulint)
02105       (srv_n_lock_wait_time / 1000 / srv_n_lock_wait_count);
02106   } else {
02107     export_vars.innodb_row_lock_time_avg = 0;
02108   }
02109   export_vars.innodb_row_lock_time_max
02110     = srv_n_lock_max_wait_time / 1000;
02111   export_vars.innodb_rows_read = srv_n_rows_read;
02112   export_vars.innodb_rows_inserted = srv_n_rows_inserted;
02113   export_vars.innodb_rows_updated = srv_n_rows_updated;
02114   export_vars.innodb_rows_deleted = srv_n_rows_deleted;
02115   export_vars.innodb_truncated_status_writes = srv_truncated_status_writes;
02116 
02117   mutex_exit(&srv_innodb_monitor_mutex);
02118 }
02119 
02120 /*********************************************************************/
02123 UNIV_INTERN
02124 os_thread_ret_t
02125 srv_monitor_thread(
02126 /*===============*/
02127   void* /*arg __attribute__((unused))*/)
02130 {
02131   ib_int64_t  sig_count;
02132   double    time_elapsed;
02133   time_t    current_time;
02134   time_t    last_table_monitor_time;
02135   time_t    last_tablespace_monitor_time;
02136   time_t    last_monitor_time;
02137   ulint   mutex_skipped;
02138   ibool   last_srv_print_monitor;
02139 
02140 #ifdef UNIV_DEBUG_THREAD_CREATION
02141   fprintf(stderr, "Lock timeout thread starts, id %lu\n",
02142     os_thread_pf(os_thread_get_curr_id()));
02143 #endif
02144 
02145 #ifdef UNIV_PFS_THREAD
02146   pfs_register_thread(srv_monitor_thread_key);
02147 #endif
02148 
02149   srv_last_monitor_time = ut_time();
02150   last_table_monitor_time = ut_time();
02151   last_tablespace_monitor_time = ut_time();
02152   last_monitor_time = ut_time();
02153   mutex_skipped = 0;
02154   last_srv_print_monitor = srv_print_innodb_monitor;
02155 loop:
02156   srv_monitor_active = TRUE;
02157 
02158   /* Wake up every 5 seconds to see if we need to print
02159   monitor information or if signalled at shutdown. */
02160 
02161   sig_count = os_event_reset(srv_monitor_event);
02162 
02163   os_event_wait_time_low(srv_monitor_event, 5000000, sig_count);
02164 
02165   current_time = ut_time();
02166 
02167   time_elapsed = difftime(current_time, last_monitor_time);
02168 
02169   if (time_elapsed > 15) {
02170     last_monitor_time = ut_time();
02171 
02172     if (srv_print_innodb_monitor) {
02173       /* Reset mutex_skipped counter everytime
02174       srv_print_innodb_monitor changes. This is to
02175       ensure we will not be blocked by kernel_mutex
02176       for short duration information printing,
02177       such as requested by sync_array_print_long_waits() */
02178       if (!last_srv_print_monitor) {
02179         mutex_skipped = 0;
02180         last_srv_print_monitor = TRUE;
02181       }
02182 
02183       if (!srv_printf_innodb_monitor(stderr,
02184             MUTEX_NOWAIT(mutex_skipped),
02185             NULL, NULL)) {
02186         mutex_skipped++;
02187       } else {
02188         /* Reset the counter */
02189         mutex_skipped = 0;
02190       }
02191     } else {
02192       last_srv_print_monitor = FALSE;
02193     }
02194 
02195 
02196     if (srv_innodb_status) {
02197       mutex_enter(&srv_monitor_file_mutex);
02198       rewind(srv_monitor_file);
02199       if (!srv_printf_innodb_monitor(srv_monitor_file,
02200             MUTEX_NOWAIT(mutex_skipped),
02201             NULL, NULL)) {
02202         mutex_skipped++;
02203       } else {
02204         mutex_skipped = 0;
02205       }
02206 
02207       os_file_set_eof(srv_monitor_file);
02208       mutex_exit(&srv_monitor_file_mutex);
02209     }
02210 
02211     if (srv_print_innodb_tablespace_monitor
02212         && difftime(current_time,
02213         last_tablespace_monitor_time) > 60) {
02214       last_tablespace_monitor_time = ut_time();
02215 
02216       fputs("========================"
02217             "========================\n",
02218             stderr);
02219 
02220       ut_print_timestamp(stderr);
02221 
02222       fputs(" INNODB TABLESPACE MONITOR OUTPUT\n"
02223             "========================"
02224             "========================\n",
02225             stderr);
02226 
02227       fsp_print(0);
02228       fputs("Validating tablespace\n", stderr);
02229       fsp_validate(0);
02230       fputs("Validation ok\n"
02231             "---------------------------------------\n"
02232             "END OF INNODB TABLESPACE MONITOR OUTPUT\n"
02233             "=======================================\n",
02234             stderr);
02235     }
02236 
02237     if (srv_print_innodb_table_monitor
02238         && difftime(current_time, last_table_monitor_time) > 60) {
02239 
02240       last_table_monitor_time = ut_time();
02241 
02242       fputs("===========================================\n",
02243             stderr);
02244 
02245       ut_print_timestamp(stderr);
02246 
02247       fputs(" INNODB TABLE MONITOR OUTPUT\n"
02248             "===========================================\n",
02249             stderr);
02250       dict_print();
02251 
02252       fputs("-----------------------------------\n"
02253             "END OF INNODB TABLE MONITOR OUTPUT\n"
02254             "==================================\n",
02255             stderr);
02256     }
02257   }
02258 
02259   if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
02260     goto exit_func;
02261   }
02262 
02263   if (srv_print_innodb_monitor
02264       || srv_print_innodb_lock_monitor
02265       || srv_print_innodb_tablespace_monitor
02266       || srv_print_innodb_table_monitor) {
02267     goto loop;
02268   }
02269 
02270   srv_monitor_active = FALSE;
02271 
02272   goto loop;
02273 
02274 exit_func:
02275   srv_monitor_active = FALSE;
02276 
02277   /* We count the number of threads in os_thread_exit(). A created
02278   thread should always use that to exit and not use return() to exit. */
02279 
02280   os_thread_exit(NULL);
02281 
02282   OS_THREAD_DUMMY_RETURN;
02283 }
02284 
02285 /*********************************************************************/
02288 UNIV_INTERN
02289 os_thread_ret_t
02290 srv_lock_timeout_thread(
02291 /*====================*/
02292   void* /*arg __attribute__((unused))*/)
02293       /* in: a dummy parameter required by
02294       os_thread_create */
02295 {
02296   srv_slot_t* slot;
02297   ibool   some_waits;
02298   double    wait_time;
02299   ulint   i;
02300   ib_int64_t  sig_count;
02301 
02302 #ifdef UNIV_PFS_THREAD
02303   pfs_register_thread(srv_lock_timeout_thread_key);
02304 #endif
02305 
02306 loop:
02307 
02308   /* When someone is waiting for a lock, we wake up every second
02309   and check if a timeout has passed for a lock wait */
02310 
02311   sig_count = os_event_reset(srv_timeout_event);
02312 
02313   os_event_wait_time_low(srv_timeout_event, 1000000, sig_count);
02314 
02315   srv_lock_timeout_active = TRUE;
02316 
02317   mutex_enter(&kernel_mutex);
02318 
02319   some_waits = FALSE;
02320 
02321   /* Check of all slots if a thread is waiting there, and if it
02322   has exceeded the time limit */
02323 
02324   for (i = 0; i < OS_THREAD_MAX_N; i++) {
02325 
02326     slot = srv_mysql_table + i;
02327 
02328     if (slot->in_use) {
02329       trx_t*  trx;
02330       ulong lock_wait_timeout;
02331 
02332       some_waits = TRUE;
02333 
02334       wait_time = ut_difftime(ut_time(), slot->suspend_time);
02335 
02336       trx = thr_get_trx(slot->thr);
02337       lock_wait_timeout = thd_lock_wait_timeout(
02338         trx->mysql_thd);
02339 
02340       if (trx_is_interrupted(trx)
02341           || (lock_wait_timeout < 100000000
02342         && (wait_time > (double) lock_wait_timeout
02343             || wait_time < 0))) {
02344 
02345         /* Timeout exceeded or a wrap-around in system
02346         time counter: cancel the lock request queued
02347         by the transaction and release possible
02348         other transactions waiting behind; it is
02349         possible that the lock has already been
02350         granted: in that case do nothing */
02351 
02352         if (trx->wait_lock) {
02353           lock_cancel_waiting_and_release(
02354             trx->wait_lock);
02355         }
02356       }
02357     }
02358   }
02359 
02360   os_event_reset(srv_lock_timeout_thread_event);
02361 
02362   mutex_exit(&kernel_mutex);
02363 
02364   if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
02365     goto exit_func;
02366   }
02367 
02368   if (some_waits) {
02369     goto loop;
02370   }
02371 
02372   srv_lock_timeout_active = FALSE;
02373 
02374 #if 0
02375   /* The following synchronisation is disabled, since
02376   the InnoDB monitor output is to be updated every 15 seconds. */
02377   os_event_wait(srv_lock_timeout_thread_event);
02378 #endif
02379   goto loop;
02380 
02381 exit_func:
02382   srv_lock_timeout_active = FALSE;
02383 
02384   /* We count the number of threads in os_thread_exit(). A created
02385   thread should always use that to exit and not use return() to exit. */
02386 
02387   os_thread_exit(NULL);
02388 
02389   OS_THREAD_DUMMY_RETURN;
02390 }
02391 
02392 /*********************************************************************/
02396 UNIV_INTERN
02397 os_thread_ret_t
02398 srv_error_monitor_thread(
02399 /*=====================*/
02400   void* /*arg __attribute__((unused))*/)
02403 {
02404   /* number of successive fatal timeouts observed */
02405   ulint   fatal_cnt = 0;
02406   ib_uint64_t old_lsn;
02407   ib_uint64_t new_lsn;
02408   ib_int64_t  sig_count;
02409 
02410   old_lsn = srv_start_lsn;
02411 
02412 #ifdef UNIV_DEBUG_THREAD_CREATION
02413   fprintf(stderr, "Error monitor thread starts, id %lu\n",
02414     os_thread_pf(os_thread_get_curr_id()));
02415 #endif
02416 
02417 #ifdef UNIV_PFS_THREAD
02418   pfs_register_thread(srv_error_monitor_thread_key);
02419 #endif
02420 
02421 loop:
02422   srv_error_monitor_active = TRUE;
02423 
02424   /* Try to track a strange bug reported by Harald Fuchs and others,
02425   where the lsn seems to decrease at times */
02426 
02427   new_lsn = log_get_lsn();
02428 
02429   if (new_lsn < old_lsn) {
02430           drizzled::errmsg_printf(drizzled::error::INFO,
02431                                   "InnoDB: Error: old log sequence number %"PRIu64" was greater than the new log sequence number %"PRIu64"!"
02432                                   "InnoDB: Please submit a bug report to http://bugs.launchpad.net/drizzle",
02433                                   old_lsn, new_lsn);
02434   }
02435 
02436   old_lsn = new_lsn;
02437 
02438   if (difftime(time(NULL), srv_last_monitor_time) > 60) {
02439     /* We referesh InnoDB Monitor values so that averages are
02440     printed from at most 60 last seconds */
02441 
02442     srv_refresh_innodb_monitor_stats();
02443   }
02444 
02445   /* Update the statistics collected for deciding LRU
02446   eviction policy. */
02447   buf_LRU_stat_update();
02448 
02449   /* Update the statistics collected for flush rate policy. */
02450   buf_flush_stat_update();
02451 
02452   /* In case mutex_exit is not a memory barrier, it is
02453   theoretically possible some threads are left waiting though
02454   the semaphore is already released. Wake up those threads: */
02455 
02456   sync_arr_wake_threads_if_sema_free();
02457 
02458   if (sync_array_print_long_waits()) {
02459     fatal_cnt++;
02460     if (fatal_cnt > 10) {
02461 
02462       fprintf(stderr,
02463         "InnoDB: Error: semaphore wait has lasted"
02464         " > %lu seconds\n"
02465         "InnoDB: We intentionally crash the server,"
02466         " because it appears to be hung.\n",
02467         (ulong) srv_fatal_semaphore_wait_threshold);
02468 
02469       ut_error;
02470     }
02471   } else {
02472     fatal_cnt = 0;
02473   }
02474 
02475   /* Flush stderr so that a database user gets the output
02476   to possible MySQL error file */
02477 
02478   fflush(stderr);
02479 
02480   sig_count = os_event_reset(srv_error_event);
02481 
02482   os_event_wait_time_low(srv_error_event, 1000000, sig_count);
02483 
02484   if (srv_shutdown_state < SRV_SHUTDOWN_CLEANUP) {
02485 
02486     goto loop;
02487   }
02488 
02489   srv_error_monitor_active = FALSE;
02490 
02491   /* We count the number of threads in os_thread_exit(). A created
02492   thread should always use that to exit and not use return() to exit. */
02493 
02494   os_thread_exit(NULL);
02495 
02496   OS_THREAD_DUMMY_RETURN;
02497 }
02498 
02499 /*********************************************************************/
02503 UNIV_INTERN
02504 os_thread_ret_t
02505 srv_LRU_dump_restore_thread(
02506 /*====================*/
02507   void* /*arg __attribute__((unused))*/)
02510 {
02511   uint  auto_lru_dump;
02512   time_t  last_dump_time;
02513   time_t  time_elapsed;
02514 
02515 #ifdef UNIV_DEBUG_THREAD_CREATION
02516   fprintf(stderr, "The LRU dump/restore thread has started, id %lu\n",
02517     os_thread_pf(os_thread_get_curr_id()));
02518 #endif
02519 
02520   if (srv_auto_lru_dump)
02521     buf_LRU_file_restore();
02522 
02523   last_dump_time = time(NULL);
02524 
02525 loop:
02526   os_thread_sleep(5000000);
02527 
02528   if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
02529     goto exit_func;
02530   }
02531 
02532   time_elapsed = time(NULL) - last_dump_time;
02533   auto_lru_dump = srv_auto_lru_dump;
02534   if (auto_lru_dump > 0 && (time_t) auto_lru_dump < time_elapsed) {
02535     last_dump_time = time(NULL);
02536     buf_LRU_file_dump();
02537   }
02538 
02539   goto loop;
02540 exit_func:
02541   /* We count the number of threads in os_thread_exit(). A created
02542   thread should always use that to exit and not use return() to exit. */
02543 
02544   os_thread_exit(NULL);
02545 
02546   OS_THREAD_DUMMY_RETURN;
02547 }
02548 
02549 /**********************************************************************/
02552 UNIV_INTERN
02553 ibool
02554 srv_is_any_background_thread_active(void)
02555 /*=====================================*/
02556 {
02557   ulint i;
02558   ibool ret = FALSE;
02559 
02560   mutex_enter(&kernel_mutex);
02561 
02562   for (i = SRV_COM; i <= SRV_MASTER; ++i) {
02563     if (srv_n_threads_active[i] != 0) {
02564       ret = TRUE;
02565       break;
02566     }
02567   }
02568 
02569   mutex_exit(&kernel_mutex);
02570 
02571   return(ret);
02572 }
02573 
02574 /*******************************************************************/
02580 UNIV_INTERN
02581 void
02582 srv_active_wake_master_thread(void)
02583 /*===============================*/
02584 {
02585   srv_activity_count++;
02586 
02587   if (srv_n_threads_active[SRV_MASTER] == 0) {
02588 
02589     mutex_enter(&kernel_mutex);
02590 
02591     srv_release_threads(SRV_MASTER, 1);
02592 
02593     mutex_exit(&kernel_mutex);
02594   }
02595 }
02596 
02597 /*******************************************************************/
02603 UNIV_INTERN
02604 void
02605 srv_wake_purge_thread_if_not_active(void)
02606 /*=====================================*/
02607 {
02608   ut_ad(!mutex_own(&kernel_mutex));
02609 
02610   if (srv_n_purge_threads > 0
02611       && srv_n_threads_active[SRV_WORKER] == 0) {
02612 
02613     mutex_enter(&kernel_mutex);
02614 
02615     srv_release_threads(SRV_WORKER, 1);
02616 
02617     mutex_exit(&kernel_mutex);
02618   }
02619 }
02620 
02621 /*******************************************************************/
02623 UNIV_INTERN
02624 void
02625 srv_wake_master_thread(void)
02626 /*========================*/
02627 {
02628   srv_activity_count++;
02629 
02630   mutex_enter(&kernel_mutex);
02631 
02632   srv_release_threads(SRV_MASTER, 1);
02633 
02634   mutex_exit(&kernel_mutex);
02635 }
02636 
02637 /*******************************************************************/
02639 UNIV_INTERN
02640 void
02641 srv_wake_purge_thread(void)
02642 /*=======================*/
02643 {
02644   ut_ad(!mutex_own(&kernel_mutex));
02645 
02646   if (srv_n_purge_threads > 0) {
02647 
02648     mutex_enter(&kernel_mutex);
02649 
02650     srv_release_threads(SRV_WORKER, 1);
02651 
02652     mutex_exit(&kernel_mutex);
02653   }
02654 }
02655 
02656 /**********************************************************************
02657 The master thread is tasked to ensure that flush of log file happens
02658 once every second in the background. This is to ensure that not more
02659 than one second of trxs are lost in case of crash when
02660 innodb_flush_logs_at_trx_commit != 1 */
02661 static
02662 void
02663 srv_sync_log_buffer_in_background(void)
02664 /*===================================*/
02665 {
02666   time_t  current_time = time(NULL);
02667 
02668   srv_main_thread_op_info = "flushing log";
02669   if (difftime(current_time, srv_last_log_flush_time) >= 1) {
02670     log_buffer_sync_in_background(TRUE);
02671     srv_last_log_flush_time = current_time;
02672     srv_log_writes_and_flush++;
02673   }
02674 }
02675 
02676 /********************************************************************/
02679 static
02680 void
02681 srv_master_do_purge(void)
02682 /*=====================*/
02683 {
02684   ulint n_pages_purged;
02685 
02686   ut_ad(!mutex_own(&kernel_mutex));
02687 
02688   ut_a(srv_n_purge_threads == 0);
02689 
02690   do {
02691     /* Check for shutdown and change in purge config. */
02692     if (srv_fast_shutdown && srv_shutdown_state > 0) {
02693       /* Nothing to purge. */
02694       n_pages_purged = 0;
02695     } else {
02696       n_pages_purged = trx_purge(srv_purge_batch_size);
02697     }
02698 
02699     srv_sync_log_buffer_in_background();
02700 
02701   } while (n_pages_purged > 0);
02702 }
02703 
02704 /*********************************************************************/
02707 UNIV_INTERN
02708 os_thread_ret_t
02709 srv_master_thread(
02710 /*==============*/
02711   void* /*arg __attribute__((unused))*/)
02714 {
02715   buf_pool_stat_t buf_stat;
02716   os_event_t  event;
02717   ulint   old_activity_count;
02718   ulint   n_pages_purged  = 0;
02719   ulint   n_bytes_merged;
02720   ulint   n_pages_flushed;
02721   uint32_t  n_pages_flushed_prev = 0;
02722   ulint   n_bytes_archived;
02723   ulint   n_tables_to_drop;
02724   ulint   n_ios;
02725   ulint   n_ios_old;
02726   ulint   n_ios_very_old;
02727   ulint   n_pend_ios;
02728   ulint   next_itr_time;
02729   uint32_t  prev_adaptive_flushing_method = ULINT32_UNDEFINED;
02730   uint32_t  inner_loop = 0;
02731   bool    skip_sleep = false;
02732   ulint   i;
02733 
02734   struct t_prev_flush_info_struct {
02735       uint32_t  count;
02736       uint32_t  space;
02737       uint32_t  offset;
02738       uint64_t  oldest_modification;
02739   } prev_flush_info[MAX_BUFFER_POOLS];
02740 
02741   uint64_t  lsn_old;
02742   uint64_t  oldest_lsn;
02743 
02744 #ifdef UNIV_DEBUG_THREAD_CREATION
02745   fprintf(stderr, "Master thread starts, id %lu\n",
02746     os_thread_pf(os_thread_get_curr_id()));
02747 #endif
02748 
02749 #ifdef UNIV_PFS_THREAD
02750   pfs_register_thread(srv_master_thread_key);
02751 #endif
02752 
02753   srv_main_thread_process_no = os_proc_get_number();
02754   srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
02755 
02756   srv_table_reserve_slot(SRV_MASTER);
02757 
02758   mutex_enter(&kernel_mutex);
02759 
02760   srv_n_threads_active[SRV_MASTER]++;
02761 
02762   mutex_exit(&kernel_mutex);
02763 
02764   mutex_enter(&(log_sys->mutex));
02765   lsn_old = log_sys->lsn;
02766   mutex_exit(&(log_sys->mutex));
02767 loop:
02768   /*****************************************************************/
02769   /* ---- When there is database activity by users, we cycle in this
02770   loop */
02771 
02772   srv_main_thread_op_info = "reserving kernel mutex";
02773 
02774   buf_get_total_stat(&buf_stat);
02775   n_ios_very_old = log_sys->n_log_ios + buf_stat.n_pages_read
02776     + buf_stat.n_pages_written;
02777   mutex_enter(&kernel_mutex);
02778 
02779   /* Store the user activity counter at the start of this loop */
02780   old_activity_count = srv_activity_count;
02781 
02782   mutex_exit(&kernel_mutex);
02783 
02784   if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
02785 
02786     goto suspend_thread;
02787   }
02788 
02789   /* ---- We run the following loop approximately once per second
02790   when there is database activity */
02791 
02792   srv_last_log_flush_time = time(NULL);
02793 
02794   /* Sleep for 1 second on entrying the for loop below the first time. */
02795   next_itr_time = ut_time_ms() + 1000;
02796 
02797   skip_sleep = false;
02798 
02799   for (i = 0; i < 10; i++) {
02800     ulint cur_time = ut_time_ms();
02801 
02802     n_pages_flushed = 0;
02803 
02804     /* ALTER TABLE in MySQL requires on Unix that the table handler
02805     can drop tables lazily after there no longer are SELECT
02806     queries to them. */
02807 
02808     srv_main_thread_op_info = "doing background drop tables";
02809 
02810     row_drop_tables_for_mysql_in_background();
02811 
02812     srv_main_thread_op_info = "";
02813 
02814     if (srv_fast_shutdown && srv_shutdown_state > 0) {
02815 
02816       goto background_loop;
02817     }
02818 
02819     buf_get_total_stat(&buf_stat);
02820 
02821     n_ios_old = log_sys->n_log_ios + buf_stat.n_pages_read
02822       + buf_stat.n_pages_written;
02823 
02824     srv_main_thread_op_info = "sleeping";
02825     srv_main_1_second_loops++;
02826 
02827     if (skip_sleep == false) {
02828         if (next_itr_time > cur_time
02829       && srv_shutdown_state == SRV_SHUTDOWN_NONE) {
02830 
02831       /* Get sleep interval in micro seconds. We use
02832          ut_min() to avoid long sleep in case of
02833          wrap around. */
02834       os_thread_sleep(ut_min(1000000,
02835                  (next_itr_time - cur_time)
02836                  * 1000));
02837       srv_main_sleeps++;
02838 
02839       /*
02840         TODO: tracing code unported to Drizzle
02841         mutex_enter(&(log_sys->mutex));
02842         oldest_lsn = buf_pool_get_oldest_modification();
02843         ib_uint64_t lsn = log_sys->lsn;
02844         mutex_exit(&(log_sys->mutex));
02845 
02846         if(oldest_lsn)
02847             fprintf(stderr,
02848                     "InnoDB flush: age pct: %lu, lsn progress: %lu\n",
02849                     (lsn - oldest_lsn) * 100 / log_sys->max_checkpoint_age,
02850                     lsn - lsn_old);
02851       */
02852 
02853         }
02854 
02855         /* Each iteration should happen at 1 second interval. */
02856         next_itr_time = ut_time_ms() + 1000;
02857     }
02858 
02859     skip_sleep = false;
02860 
02861     /* Flush logs if needed */
02862     srv_sync_log_buffer_in_background();
02863 
02864     srv_main_thread_op_info = "making checkpoint";
02865     log_free_check();
02866 
02867     /* If i/os during one second sleep were less than 5% of
02868     capacity, we assume that there is free disk i/o capacity
02869     available, and it makes sense to do an insert buffer merge. */
02870 
02871     buf_get_total_stat(&buf_stat);
02872     n_pend_ios = buf_get_n_pending_ios()
02873       + log_sys->n_pending_writes;
02874     n_ios = log_sys->n_log_ios + buf_stat.n_pages_read
02875       + buf_stat.n_pages_written;
02876     if (n_pend_ios < SRV_PEND_IO_THRESHOLD
02877         && (n_ios - n_ios_old < SRV_RECENT_IO_ACTIVITY)) {
02878       srv_main_thread_op_info = "doing insert buffer merge";
02879       ibuf_contract_for_n_pages(FALSE, PCT_IBUF_IO(5));
02880 
02881       /* Flush logs if needed */
02882       srv_sync_log_buffer_in_background();
02883     }
02884 
02885     if (UNIV_UNLIKELY(buf_get_modified_ratio_pct()
02886           > srv_max_buf_pool_modified_pct)) {
02887 
02888       /* Try to keep the number of modified pages in the
02889       buffer pool under the limit wished by the user */
02890 
02891       srv_main_thread_op_info =
02892         "flushing buffer pool pages";
02893       n_pages_flushed = buf_flush_list(
02894         PCT_IO(100), IB_ULONGLONG_MAX);
02895 
02896       mutex_enter(&(log_sys->mutex));
02897       lsn_old = log_sys->lsn;
02898       mutex_exit(&(log_sys->mutex));
02899       prev_adaptive_flushing_method = ULINT32_UNDEFINED;
02900     } else if (srv_adaptive_flushing
02901          && srv_adaptive_flushing_method == 0) {
02902 
02903       /* Try to keep the rate of flushing of dirty
02904       pages such that redo log generation does not
02905       produce bursts of IO at checkpoint time. */
02906       ulint n_flush = buf_flush_get_desired_flush_rate();
02907 
02908       if (n_flush) {
02909         srv_main_thread_op_info =
02910           "flushing buffer pool pages";
02911         n_flush = ut_min(PCT_IO(100), n_flush);
02912         n_pages_flushed =
02913           buf_flush_list(
02914             n_flush,
02915             IB_ULONGLONG_MAX);
02916       }
02917 
02918       mutex_enter(&(log_sys->mutex));
02919       lsn_old = log_sys->lsn;
02920       mutex_exit(&(log_sys->mutex));
02921       prev_adaptive_flushing_method = ULINT32_UNDEFINED;
02922     } else if (srv_adaptive_flushing
02923          && srv_adaptive_flushing_method == 1) {
02924 
02925       /* Try to keep modified age not to exceed
02926          max_checkpoint_age * 7/8 line */
02927 
02928       mutex_enter(&(log_sys->mutex));
02929 
02930       oldest_lsn = buf_pool_get_oldest_modification();
02931       if (oldest_lsn == 0) {
02932         lsn_old = log_sys->lsn;
02933         mutex_exit(&(log_sys->mutex));
02934 
02935       } else {
02936         if ((log_sys->lsn - oldest_lsn)
02937             > (log_sys->max_checkpoint_age)
02938             - ((log_sys->max_checkpoint_age) / 8)) {
02939           /* LOG_POOL_PREFLUSH_RATIO_ASYNC is exceeded. */
02940           /* We should not flush from here. */
02941           lsn_old = log_sys->lsn;
02942           mutex_exit(&(log_sys->mutex));
02943         } else if ((log_sys->lsn - oldest_lsn)
02944              > (log_sys->max_checkpoint_age)/4) {
02945 
02946           /* defence line (max_checkpoint_age * 1/2) */
02947           uint64_t  lsn = log_sys->lsn;
02948 
02949           uint64_t  level, bpl;
02950           buf_page_t* bpage;
02951           ulint   j;
02952 
02953           mutex_exit(&(log_sys->mutex));
02954 
02955           bpl = 0;
02956 
02957           for (j = 0; j < srv_buf_pool_instances; j++) {
02958             buf_pool_t* buf_pool;
02959             uint32_t  n_blocks = 0;
02960 
02961             buf_pool = buf_pool_from_array(j);
02962 
02963             /* The scanning flush_list is optimistic here */
02964 
02965             level = 0;
02966             bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
02967 
02968             while (bpage != NULL) {
02969               uint64_t  oldest_modification = bpage->oldest_modification;
02970               if (oldest_modification != 0) {
02971                 level += log_sys->max_checkpoint_age
02972                   - (lsn - oldest_modification);
02973               }
02974               bpage = UT_LIST_GET_NEXT(list, bpage);
02975               n_blocks++;
02976             }
02977 
02978             if (level) {
02979               bpl += ((ib_uint64_t) n_blocks * n_blocks
02980                 * (lsn - lsn_old)) / level;
02981             }
02982 
02983           }
02984 
02985           if (!srv_use_doublewrite_buf) {
02986             /* flush is faster than when doublewrite */
02987             bpl = (bpl * 7) / 8;
02988           }
02989 
02990           if (bpl) {
02991 retry_flush_batch:
02992             n_pages_flushed = buf_flush_list(bpl,
02993                      oldest_lsn + (lsn - lsn_old));
02994             if (n_pages_flushed == ULINT32_UNDEFINED) {
02995               os_thread_sleep(5000);
02996               goto retry_flush_batch;
02997             }
02998           }
02999 
03000           lsn_old = lsn;
03001           /*
03002             TODO: tracing code unported to Drizzle
03003             fprintf(stderr,
03004                     "InnoDB flush: age pct: %lu, lsn progress: %lu, blocks to flush:%llu\n",
03005               (lsn - oldest_lsn) * 100 / log_sys->max_checkpoint_age,
03006               lsn - lsn_old, bpl);
03007           */
03008         } else {
03009           lsn_old = log_sys->lsn;
03010           mutex_exit(&(log_sys->mutex));
03011         }
03012       }
03013       prev_adaptive_flushing_method = 1;
03014     } else if (srv_adaptive_flushing && srv_adaptive_flushing_method == 2) {
03015       buf_pool_t* buf_pool;
03016       buf_page_t* bpage;
03017       uint64_t  lsn;
03018       ulint   j;
03019 
03020       mutex_enter(&(log_sys->mutex));
03021       oldest_lsn = buf_pool_get_oldest_modification();
03022       lsn = log_sys->lsn;
03023       mutex_exit(&(log_sys->mutex));
03024 
03025       /* upper loop/sec. (x10) */
03026       next_itr_time -= 900; /* 1000 - 900 == 100 */
03027       inner_loop++;
03028       if (inner_loop < 10) {
03029         i--;
03030       } else {
03031         inner_loop = 0;
03032       }
03033 
03034       if (prev_adaptive_flushing_method == 2) {
03035         int32_t   n_flush;
03036         int32_t   blocks_sum = 0;
03037         uint32_t  new_blocks_sum = 0;
03038         uint32_t flushed_blocks_sum = 0;
03039 
03040         /* prev_flush_info[j] should be the previous loop's */
03041         for (j = 0; j < srv_buf_pool_instances; j++) {
03042           int32_t blocks_num, new_blocks_num, flushed_blocks_num;
03043           bool  found = false;
03044 
03045           buf_pool = buf_pool_from_array(j);
03046 
03047           blocks_num = UT_LIST_GET_LEN(buf_pool->flush_list);
03048           bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
03049           new_blocks_num = 0;
03050 
03051           while (bpage != NULL) {
03052             if (prev_flush_info[j].space == bpage->space
03053                 && prev_flush_info[j].offset == bpage->offset
03054                 && prev_flush_info[j].oldest_modification
03055                 == bpage->oldest_modification) {
03056               found = true;
03057               break;
03058             }
03059             bpage = UT_LIST_GET_NEXT(list, bpage);
03060             new_blocks_num++;
03061           }
03062           if (!found) {
03063             new_blocks_num = blocks_num;
03064           }
03065           flushed_blocks_num = new_blocks_num
03066             + prev_flush_info[j].count
03067             - blocks_num;
03068           if (flushed_blocks_num < 0) {
03069             flushed_blocks_num = 0;
03070           }
03071 
03072           bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
03073 
03074           prev_flush_info[j].count = UT_LIST_GET_LEN(buf_pool->flush_list);
03075           if (bpage) {
03076             prev_flush_info[j].space = bpage->space;
03077             prev_flush_info[j].offset = bpage->offset;
03078             prev_flush_info[j].oldest_modification = bpage->oldest_modification;
03079           } else {
03080             prev_flush_info[j].space = 0;
03081             prev_flush_info[j].offset = 0;
03082             prev_flush_info[j].oldest_modification = 0;
03083           }
03084 
03085           new_blocks_sum += new_blocks_num;
03086           flushed_blocks_sum += flushed_blocks_num;
03087           blocks_sum += blocks_num;
03088         }
03089 
03090         n_flush = blocks_sum * (lsn - lsn_old) / log_sys->max_modified_age_async;
03091         if (flushed_blocks_sum > n_pages_flushed_prev) {
03092           n_flush -= (flushed_blocks_sum - n_pages_flushed_prev);
03093         }
03094 
03095         if (n_flush > 0) {
03096           n_flush++;
03097           n_pages_flushed = buf_flush_list(n_flush, oldest_lsn + (lsn - lsn_old));
03098         } else {
03099           n_pages_flushed = 0;
03100         }
03101       } else {
03102         /* store previous first pages of the flush_list */
03103         for (j = 0; j < srv_buf_pool_instances; j++) {
03104           buf_pool = buf_pool_from_array(j);
03105 
03106           bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
03107 
03108           prev_flush_info[j].count = UT_LIST_GET_LEN(buf_pool->flush_list);
03109           if (bpage) {
03110             prev_flush_info[j].space = bpage->space;
03111             prev_flush_info[j].offset = bpage->offset;
03112             prev_flush_info[j].oldest_modification =  bpage->oldest_modification;
03113           } else {
03114             prev_flush_info[j].space = 0;
03115             prev_flush_info[j].offset = 0;
03116             prev_flush_info[j].oldest_modification = 0;
03117           }
03118         }
03119         n_pages_flushed = 0;
03120       }
03121 
03122       lsn_old = lsn;
03123       prev_adaptive_flushing_method = 2;
03124     } else {
03125       mutex_enter(&(log_sys->mutex));
03126       lsn_old = log_sys->lsn;
03127       mutex_exit(&(log_sys->mutex));
03128       prev_adaptive_flushing_method = ULINT32_UNDEFINED;
03129     }
03130 
03131     if (n_pages_flushed == ULINT_UNDEFINED) {
03132       n_pages_flushed_prev = 0;
03133     } else {
03134       n_pages_flushed_prev = n_pages_flushed;
03135     }
03136 
03137     if (srv_activity_count == old_activity_count) {
03138 
03139       /* There is no user activity at the moment, go to
03140       the background loop */
03141 
03142       goto background_loop;
03143     }
03144   }
03145 
03146   /* ---- We perform the following code approximately once per
03147   10 seconds when there is database activity */
03148 
03149 #ifdef MEM_PERIODIC_CHECK
03150   /* Check magic numbers of every allocated mem block once in 10
03151   seconds */
03152   mem_validate_all_blocks();
03153 #endif
03154   /* If i/os during the 10 second period were less than 200% of
03155   capacity, we assume that there is free disk i/o capacity
03156   available, and it makes sense to flush srv_io_capacity pages.
03157 
03158   Note that this is done regardless of the fraction of dirty
03159   pages relative to the max requested by the user. The one second
03160   loop above requests writes for that case. The writes done here
03161   are not required, and may be disabled. */
03162 
03163   buf_get_total_stat(&buf_stat);
03164   n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
03165   n_ios = log_sys->n_log_ios + buf_stat.n_pages_read
03166     + buf_stat.n_pages_written;
03167 
03168   srv_main_10_second_loops++;
03169   if (n_pend_ios < SRV_PEND_IO_THRESHOLD
03170       && (n_ios - n_ios_very_old < SRV_PAST_IO_ACTIVITY)) {
03171 
03172     srv_main_thread_op_info = "flushing buffer pool pages";
03173     buf_flush_list(PCT_IO(100), IB_ULONGLONG_MAX);
03174 
03175     /* Flush logs if needed */
03176     srv_sync_log_buffer_in_background();
03177   }
03178 
03179   /* We run a batch of insert buffer merge every 10 seconds,
03180   even if the server were active */
03181 
03182   srv_main_thread_op_info = "doing insert buffer merge";
03183   ibuf_contract_for_n_pages(FALSE, PCT_IBUF_IO(5));
03184 
03185   /* Flush logs if needed */
03186   srv_sync_log_buffer_in_background();
03187 
03188   if (srv_n_purge_threads == 0) {
03189     srv_main_thread_op_info = "master purging";
03190 
03191     srv_master_do_purge();
03192 
03193     if (srv_fast_shutdown && srv_shutdown_state > 0) {
03194 
03195       goto background_loop;
03196     }
03197   }
03198 
03199   srv_main_thread_op_info = "flushing buffer pool pages";
03200 
03201   /* Flush a few oldest pages to make a new checkpoint younger */
03202 
03203   if (buf_get_modified_ratio_pct() > 70) {
03204 
03205     /* If there are lots of modified pages in the buffer pool
03206     (> 70 %), we assume we can afford reserving the disk(s) for
03207     the time it requires to flush 100 pages */
03208 
03209     n_pages_flushed = buf_flush_list(
03210       PCT_IO(100), IB_ULONGLONG_MAX);
03211   } else {
03212     /* Otherwise, we only flush a small number of pages so that
03213     we do not unnecessarily use much disk i/o capacity from
03214     other work */
03215 
03216     n_pages_flushed = buf_flush_list(
03217         PCT_IO(10), IB_ULONGLONG_MAX);
03218   }
03219 
03220   srv_main_thread_op_info = "making checkpoint";
03221 
03222   /* Make a new checkpoint about once in 10 seconds */
03223 
03224   log_checkpoint(TRUE, FALSE);
03225 
03226   srv_main_thread_op_info = "reserving kernel mutex";
03227 
03228   mutex_enter(&kernel_mutex);
03229 
03230   /* ---- When there is database activity, we jump from here back to
03231   the start of loop */
03232 
03233   if (srv_activity_count != old_activity_count) {
03234     mutex_exit(&kernel_mutex);
03235     goto loop;
03236   }
03237 
03238   mutex_exit(&kernel_mutex);
03239 
03240   /* If the database is quiet, we enter the background loop */
03241 
03242   /*****************************************************************/
03243 background_loop:
03244   /* ---- In this loop we run background operations when the server
03245   is quiet from user activity. Also in the case of a shutdown, we
03246   loop here, flushing the buffer pool to the data files. */
03247 
03248   /* The server has been quiet for a while: start running background
03249   operations */
03250   srv_main_background_loops++;
03251   srv_main_thread_op_info = "doing background drop tables";
03252 
03253   n_tables_to_drop = row_drop_tables_for_mysql_in_background();
03254 
03255   if (n_tables_to_drop > 0) {
03256     /* Do not monopolize the CPU even if there are tables waiting
03257     in the background drop queue. (It is essentially a bug if
03258     MySQL tries to drop a table while there are still open handles
03259     to it and we had to put it to the background drop queue.) */
03260 
03261     if (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
03262       os_thread_sleep(100000);
03263     }
03264   }
03265 
03266   if (srv_n_purge_threads == 0) {
03267     srv_main_thread_op_info = "master purging";
03268 
03269     srv_master_do_purge();
03270   }
03271 
03272   srv_main_thread_op_info = "reserving kernel mutex";
03273 
03274   mutex_enter(&kernel_mutex);
03275   if (srv_activity_count != old_activity_count) {
03276     mutex_exit(&kernel_mutex);
03277     goto loop;
03278   }
03279   mutex_exit(&kernel_mutex);
03280 
03281   srv_main_thread_op_info = "doing insert buffer merge";
03282 
03283   if (srv_fast_shutdown && srv_shutdown_state > 0) {
03284     n_bytes_merged = 0;
03285   } else {
03286     /* This should do an amount of IO similar to the number of
03287     dirty pages that will be flushed in the call to
03288     buf_flush_list below. Otherwise, the system favors
03289     clean pages over cleanup throughput. */
03290     n_bytes_merged = ibuf_contract_for_n_pages(FALSE,
03291                  PCT_IBUF_IO(100));
03292   }
03293 
03294   srv_main_thread_op_info = "reserving kernel mutex";
03295 
03296   mutex_enter(&kernel_mutex);
03297   if (srv_activity_count != old_activity_count) {
03298     mutex_exit(&kernel_mutex);
03299     goto loop;
03300   }
03301   mutex_exit(&kernel_mutex);
03302 
03303 flush_loop:
03304   srv_main_thread_op_info = "flushing buffer pool pages";
03305   srv_main_flush_loops++;
03306   if (srv_fast_shutdown < 2) {
03307     n_pages_flushed = buf_flush_list(
03308         PCT_IO(100), IB_ULONGLONG_MAX);
03309   } else {
03310     /* In the fastest shutdown we do not flush the buffer pool
03311     to data files: we set n_pages_flushed to 0 artificially. */
03312 
03313     n_pages_flushed = 0;
03314   }
03315 
03316   srv_main_thread_op_info = "reserving kernel mutex";
03317 
03318   mutex_enter(&kernel_mutex);
03319   if (srv_activity_count != old_activity_count) {
03320     mutex_exit(&kernel_mutex);
03321     goto loop;
03322   }
03323   mutex_exit(&kernel_mutex);
03324 
03325   srv_main_thread_op_info = "waiting for buffer pool flush to end";
03326   buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
03327 
03328   /* Flush logs if needed */
03329   srv_sync_log_buffer_in_background();
03330 
03331   srv_main_thread_op_info = "making checkpoint";
03332 
03333   log_checkpoint(TRUE, FALSE);
03334 
03335   if (buf_get_modified_ratio_pct() > srv_max_buf_pool_modified_pct) {
03336 
03337     /* Try to keep the number of modified pages in the
03338     buffer pool under the limit wished by the user */
03339 
03340     goto flush_loop;
03341   }
03342 
03343   srv_main_thread_op_info = "reserving kernel mutex";
03344 
03345   mutex_enter(&kernel_mutex);
03346   if (srv_activity_count != old_activity_count) {
03347     mutex_exit(&kernel_mutex);
03348     goto loop;
03349   }
03350   mutex_exit(&kernel_mutex);
03351   /*
03352   srv_main_thread_op_info = "archiving log (if log archive is on)";
03353 
03354   log_archive_do(FALSE, &n_bytes_archived);
03355   */
03356   n_bytes_archived = 0;
03357 
03358   /* Keep looping in the background loop if still work to do */
03359 
03360   if (srv_fast_shutdown && srv_shutdown_state > 0) {
03361     if (n_tables_to_drop + n_pages_flushed
03362         + n_bytes_archived != 0) {
03363 
03364       /* If we are doing a fast shutdown (= the default)
03365       we do not do purge or insert buffer merge. But we
03366       flush the buffer pool completely to disk.
03367       In a 'very fast' shutdown we do not flush the buffer
03368       pool to data files: we have set n_pages_flushed to
03369       0 artificially. */
03370 
03371       goto background_loop;
03372     }
03373   } else if (n_tables_to_drop
03374        + n_pages_purged + n_bytes_merged + n_pages_flushed
03375        + n_bytes_archived != 0) {
03376     /* In a 'slow' shutdown we run purge and the insert buffer
03377     merge to completion */
03378 
03379     goto background_loop;
03380   }
03381 
03382   /* There is no work for background operations either: suspend
03383   master thread to wait for more server activity */
03384 
03385 suspend_thread:
03386   srv_main_thread_op_info = "suspending";
03387 
03388   mutex_enter(&kernel_mutex);
03389 
03390   if (row_get_background_drop_list_len_low() > 0) {
03391     mutex_exit(&kernel_mutex);
03392 
03393     goto loop;
03394   }
03395 
03396   event = srv_suspend_thread();
03397 
03398   mutex_exit(&kernel_mutex);
03399 
03400   /* DO NOT CHANGE THIS STRING. innobase_start_or_create_for_mysql()
03401   waits for database activity to die down when converting < 4.1.x
03402   databases, and relies on this string being exactly as it is. InnoDB
03403   manual also mentions this string in several places. */
03404   srv_main_thread_op_info = "waiting for server activity";
03405 
03406   os_event_wait(event);
03407 
03408   if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
03409     /* This is only extra safety, the thread should exit
03410     already when the event wait ends */
03411 
03412     os_thread_exit(NULL);
03413 
03414   }
03415 
03416   /* When there is user activity, InnoDB will set the event and the
03417   main thread goes back to loop. */
03418 
03419   goto loop;
03420 
03421 
03422 #if !defined(__SUNPRO_C)
03423   OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
03424 #endif
03425 }
03426 
03427 /*********************************************************************/
03430 UNIV_INTERN
03431 os_thread_ret_t
03432 srv_purge_thread(
03433 /*=============*/
03434   void* /*arg __attribute__((unused))*/)  
03436 {
03437   srv_slot_t* slot;
03438   ulint   slot_no = ULINT_UNDEFINED;
03439   ulint   n_total_purged = ULINT_UNDEFINED;
03440   ulint   next_itr_time;
03441 
03442   ut_a(srv_n_purge_threads == 1);
03443 
03444 #ifdef UNIV_DEBUG_THREAD_CREATION
03445   fprintf(stderr, "InnoDB: Purge thread running, id %lu\n",
03446     os_thread_pf(os_thread_get_curr_id()));
03447 #endif /* UNIV_DEBUG_THREAD_CREATION */
03448 
03449   mutex_enter(&kernel_mutex);
03450 
03451   slot_no = srv_table_reserve_slot(SRV_WORKER);
03452 
03453   slot = srv_table_get_nth_slot(slot_no);
03454 
03455   ++srv_n_threads_active[SRV_WORKER];
03456 
03457   mutex_exit(&kernel_mutex);
03458 
03459   next_itr_time = ut_time_ms();
03460 
03461   while (srv_shutdown_state != SRV_SHUTDOWN_EXIT_THREADS) {
03462 
03463     ulint n_pages_purged;
03464     ulint cur_time;
03465 
03466     /* If there are very few records to purge or the last
03467     purge didn't purge any records then wait for activity.
03468           We peek at the history len without holding any mutex
03469     because in the worst case we will end up waiting for
03470     the next purge event. */
03471     if (trx_sys->rseg_history_len < srv_purge_batch_size
03472         || n_total_purged == 0) {
03473 
03474       os_event_t  event;
03475 
03476       mutex_enter(&kernel_mutex);
03477 
03478       event = srv_suspend_thread();
03479 
03480       mutex_exit(&kernel_mutex);
03481 
03482       os_event_wait(event);
03483     }
03484 
03485     /* Check for shutdown and whether we should do purge at all. */
03486     if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND
03487         || srv_shutdown_state != 0
03488         || srv_fast_shutdown) {
03489 
03490       break;
03491     }
03492 
03493     n_total_purged = 0;
03494 
03495     /* Purge until there are no more records to purge and there is
03496     no change in configuration or server state. */
03497     do {
03498       n_pages_purged = trx_purge(srv_purge_batch_size);
03499 
03500       n_total_purged += n_pages_purged;
03501 
03502     } while (n_pages_purged > 0 && !srv_fast_shutdown);
03503 
03504     srv_sync_log_buffer_in_background();
03505 
03506     cur_time = ut_time_ms();
03507     if (next_itr_time > cur_time) {
03508       os_thread_sleep(ut_min(1000000,
03509                  (next_itr_time - cur_time)
03510                  * 1000));
03511       next_itr_time = ut_time_ms() + 1000;
03512     } else {
03513       next_itr_time = cur_time + 1000;
03514     }
03515   }
03516 
03517   mutex_enter(&kernel_mutex);
03518 
03519   ut_ad(srv_table_get_nth_slot(slot_no) == slot);
03520 
03521   /* Decrement the active count. */
03522   srv_suspend_thread();
03523 
03524   slot->in_use = FALSE;
03525 
03526   /* Free the thread local memory. */
03527   thr_local_free(os_thread_get_curr_id());
03528 
03529   mutex_exit(&kernel_mutex);
03530 
03531 #ifdef UNIV_DEBUG_THREAD_CREATION
03532   fprintf(stderr, "InnoDB: Purge thread exiting, id %lu\n",
03533     os_thread_pf(os_thread_get_curr_id()));
03534 #endif /* UNIV_DEBUG_THREAD_CREATION */
03535 
03536   /* We count the number of threads in os_thread_exit(). A created
03537   thread should always use that to exit and not use return() to exit. */
03538   os_thread_exit(NULL);
03539 
03540   OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
03541 }
03542 
03543 /**********************************************************************/
03546 UNIV_INTERN
03547 void
03548 srv_que_task_enqueue_low(
03549 /*=====================*/
03550   que_thr_t*  thr)  
03551 {
03552   ut_ad(thr);
03553 
03554   mutex_enter(&kernel_mutex);
03555 
03556   UT_LIST_ADD_LAST(queue, srv_sys->tasks, thr);
03557 
03558   srv_release_threads(SRV_WORKER, 1);
03559 
03560   mutex_exit(&kernel_mutex);
03561 }