00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00060
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"
00090
00091
00092
00093 UNIV_INTERN ibool srv_lower_case_table_names = FALSE;
00094
00095
00096
00097 UNIV_INTERN ulint srv_activity_count = 0;
00098
00099
00100 UNIV_INTERN ulint srv_fatal_semaphore_wait_threshold = 600;
00101
00102
00103
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
00113
00114
00115
00116
00117 UNIV_INTERN char* srv_data_home = NULL;
00118 #ifdef UNIV_LOG_ARCHIVE
00119 UNIV_INTERN char* srv_arch_dir = NULL;
00120 #endif
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
00140
00141
00142
00143 UNIV_INTERN my_bool srv_use_native_aio = TRUE;
00144
00145 #ifdef __WIN__
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 UNIV_INTERN ibool srv_use_native_conditions = FALSE;
00158 #endif
00159
00160 UNIV_INTERN ulint srv_n_data_files = 0;
00161 UNIV_INTERN char** srv_data_file_names = NULL;
00162
00163 UNIV_INTERN ulint* srv_data_file_sizes = NULL;
00164
00165
00166 UNIV_INTERN ibool srv_auto_extend_last_data_file = FALSE;
00167
00168
00169 UNIV_INTERN ulint srv_last_file_size_max = 0;
00170
00171
00172 UNIV_INTERN unsigned int srv_auto_extend_increment = 8;
00173 UNIV_INTERN ulint* srv_data_file_is_raw_partition = NULL;
00174
00175
00176
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
00185 UNIV_INTERN ulint srv_log_file_size = ULINT_MAX;
00186
00187 UNIV_INTERN ulint srv_log_buffer_size = ULINT_MAX;
00188 UNIV_INTERN ulong srv_flush_log_at_trx_commit = 1;
00189
00190
00191
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]
00208
00209
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
00247
00248
00249
00250 UNIV_INTERN my_bool srv_use_sys_malloc = TRUE;
00251
00252 UNIV_INTERN ulint srv_buf_pool_size = ULINT_MAX;
00253
00254 UNIV_INTERN ulint srv_buf_pool_instances = 1;
00255
00256 UNIV_INTERN ulint srv_buf_pool_old_size;
00257
00258 UNIV_INTERN ulint srv_buf_pool_curr_size = 0;
00259
00260 UNIV_INTERN ulint srv_mem_pool_size = ULINT_MAX;
00261 UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX;
00262
00263
00264
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
00270 UNIV_INTERN ulint srv_page_size_shift = 0;
00271 UNIV_INTERN ulint srv_page_size = 0;
00272
00273
00274 UNIV_INTERN uint32_t srv_log_block_size = 0;
00275
00276
00277
00278
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
00286
00287
00288
00289
00290
00291
00292
00293
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
00304 UNIV_INTERN ulong srv_io_capacity = 200;
00305
00306
00307
00308
00309
00310
00311 UNIV_INTERN ulong srv_max_buf_pool_modified_pct = 75;
00312
00313
00314 UNIV_INTERN ulong srv_n_purge_threads = 0;
00315
00316
00317 UNIV_INTERN ulong srv_purge_batch_size = 20;
00318
00319
00320 UNIV_INTERN ulint srv_data_read = 0;
00321
00322
00323 UNIV_INTERN ulint srv_data_written = 0;
00324
00325
00326 UNIV_INTERN ulint srv_log_write_requests = 0;
00327
00328
00329 UNIV_INTERN ulint srv_log_writes = 0;
00330
00331
00332 UNIV_INTERN ulint srv_os_log_written = 0;
00333
00334
00335 UNIV_INTERN ulint srv_os_log_pending_writes = 0;
00336
00337
00338
00339 UNIV_INTERN ulint srv_log_waits = 0;
00340
00341
00342
00343 UNIV_INTERN ulint srv_dblwr_writes = 0;
00344
00345
00346
00347 UNIV_INTERN ulint srv_dblwr_pages_written = 0;
00348
00349
00350 UNIV_INTERN ulint srv_buf_pool_write_requests = 0;
00351
00352
00353
00354
00355 UNIV_INTERN ulint srv_buf_pool_wait_free = 0;
00356
00357
00358
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
00369 UNIV_INTERN export_struc export_vars;
00370
00371
00372
00373
00374 UNIV_INTERN ulint srv_force_recovery = 0;
00375
00376
00377
00378
00379
00380 UNIV_INTERN ulint srv_max_n_threads = 0;
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 UNIV_INTERN ulong srv_thread_concurrency = 0;
00391
00392
00393 UNIV_INTERN os_fast_mutex_t srv_conc_mutex;
00394
00395
00396
00397
00398 UNIV_INTERN lint srv_conc_n_threads = 0;
00399
00400
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
00419 UNIV_INTERN UT_LIST_BASE_NODE_T(srv_conc_slot_t) srv_conc_queue;
00420
00421 UNIV_INTERN srv_conc_slot_t* srv_conc_slots;
00422
00423
00424
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
00429
00430
00431
00432 UNIV_INTERN ulint srv_fast_shutdown = 0;
00433
00434
00435 UNIV_INTERN ibool srv_innodb_status = FALSE;
00436
00437
00438
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;
00457 UNIV_INTERN uint32_t srv_adaptive_flushing_method = 0;
00458
00459
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
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
00499
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
00508
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
00518 UNIV_INTERN mutex_t srv_monitor_file_mutex;
00519
00520 #ifdef UNIV_PFS_MUTEX
00521
00522 UNIV_INTERN mysql_pfs_key_t kernel_mutex_key;
00523
00524 UNIV_INTERN mysql_pfs_key_t commit_id_mutex_key;
00525
00526 UNIV_INTERN mysql_pfs_key_t srv_innodb_monitor_mutex_key;
00527
00528 UNIV_INTERN mysql_pfs_key_t srv_monitor_file_mutex_key;
00529
00530 UNIV_INTERN mysql_pfs_key_t srv_dict_tmpfile_mutex_key;
00531
00532 UNIV_INTERN mysql_pfs_key_t srv_misc_tmpfile_mutex_key;
00533 #endif
00534
00535
00536 UNIV_INTERN FILE* srv_monitor_file;
00537
00538
00539
00540 UNIV_INTERN mutex_t srv_dict_tmpfile_mutex;
00541
00542 UNIV_INTERN FILE* srv_dict_tmpfile;
00543
00544
00545
00546 UNIV_INTERN mutex_t srv_misc_tmpfile_mutex;
00547
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
00554
00555
00556 static ulint srv_main_1_second_loops = 0;
00557
00558 static ulint srv_main_sleeps = 0;
00559
00560 static ulint srv_main_10_second_loops = 0;
00561
00562 static ulint srv_main_background_loops = 0;
00563
00564 static ulint srv_main_flush_loops = 0;
00565
00566 static ulint srv_log_writes_and_flush = 0;
00567
00568
00569
00570
00571
00572 static time_t srv_last_log_flush_time;
00573
00574
00575
00576
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
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
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
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
00779
00780 UNIV_INTERN byte srv_pad1[64];
00781
00782 UNIV_INTERN mutex_t* kernel_mutex_temp;
00783
00784 UNIV_INTERN mutex_t* commit_id_mutex_temp;
00785
00786
00787
00788 UNIV_INTERN byte srv_pad2[64];
00789
00790 #if 0
00791
00792
00793
00794
00795
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
00806 static
00807 void
00808 srv_print_master_thread_info(
00809
00810 FILE *file)
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
00822
00823
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;
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
01112
01113 dict_ind_init();
01114
01115
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
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
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
01178
01179
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
01207
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
01243
01244
01245 if (!has_slept && !trx->has_search_latch
01246 && NULL == UT_LIST_GET_FIRST(trx->trx_locks)) {
01247
01248 has_slept = TRUE;
01249
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
01258
01259
01260
01261
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
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
01288
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
01300 if (trx->has_search_latch) {
01301 trx_search_latch_release_if_reserved(trx);
01302 }
01303
01304
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
01317
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
01330
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
01400
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
01412
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
01436
01437
01438
01439
01440
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
01491
01492
01493 err = srv_normalize_init_values();
01494
01495 if (err != DB_SUCCESS) {
01496 return(err);
01497 }
01498
01499
01500
01501
01502 srv_general_init();
01503
01504
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
01617
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
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
01663
01664
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
01674 row_mysql_unfreeze_data_dictionary(trx);
01675 break;
01676 case RW_X_LATCH:
01677
01678
01679
01680
01681
01682
01683 ut_print_timestamp(stderr);
01684 fputs(" InnoDB: Error: dict X latch held in "
01685 "srv_suspend_mysql_thread\n", stderr);
01686
01687
01688
01689
01690 row_mysql_unlock_data_dictionary(trx);
01691 break;
01692 }
01693
01694 ut_a(trx->dict_operation_lock_mode == 0);
01695
01696
01697
01698 os_event_wait(event);
01699
01700
01701
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
01709
01710
01711 row_mysql_lock_data_dictionary(trx);
01712 break;
01713 }
01714
01715 if (was_declared_inside_innodb) {
01716
01717
01718
01719 srv_conc_force_enter_innodb(trx);
01720 }
01721
01722 mutex_enter(&kernel_mutex);
01723
01724
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
01743
01744 start_time != -1 && finish_time != -1) {
01745 srv_n_lock_max_wait_time = diff_time;
01746 }
01747
01748
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
01761
01762
01763
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
01799
01800 os_event_set(slot->event);
01801
01802 return;
01803 }
01804 }
01805
01806
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
01862
01863
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
01890
01891
01892
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
01906
01907
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
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* )
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
02159
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
02174
02175
02176
02177
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
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
02278
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* )
02293
02294
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
02309
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
02322
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
02346
02347
02348
02349
02350
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
02376
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
02385
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* )
02403 {
02404
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
02425
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
02440
02441
02442 srv_refresh_innodb_monitor_stats();
02443 }
02444
02445
02446
02447 buf_LRU_stat_update();
02448
02449
02450 buf_flush_stat_update();
02451
02452
02453
02454
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
02476
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
02492
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* )
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
02542
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
02658
02659
02660
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
02692 if (srv_fast_shutdown && srv_shutdown_state > 0) {
02693
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* )
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
02770
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
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
02790
02791
02792 srv_last_log_flush_time = time(NULL);
02793
02794
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
02805
02806
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
02832
02833
02834 os_thread_sleep(ut_min(1000000,
02835 (next_itr_time - cur_time)
02836 * 1000));
02837 srv_main_sleeps++;
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853 }
02854
02855
02856 next_itr_time = ut_time_ms() + 1000;
02857 }
02858
02859 skip_sleep = false;
02860
02861
02862 srv_sync_log_buffer_in_background();
02863
02864 srv_main_thread_op_info = "making checkpoint";
02865 log_free_check();
02866
02867
02868
02869
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
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
02889
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
02904
02905
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
02926
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
02940
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
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
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
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
03003
03004
03005
03006
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
03026 next_itr_time -= 900;
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
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
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
03140
03141
03142 goto background_loop;
03143 }
03144 }
03145
03146
03147
03148
03149 #ifdef MEM_PERIODIC_CHECK
03150
03151
03152 mem_validate_all_blocks();
03153 #endif
03154
03155
03156
03157
03158
03159
03160
03161
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
03176 srv_sync_log_buffer_in_background();
03177 }
03178
03179
03180
03181
03182 srv_main_thread_op_info = "doing insert buffer merge";
03183 ibuf_contract_for_n_pages(FALSE, PCT_IBUF_IO(5));
03184
03185
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
03202
03203 if (buf_get_modified_ratio_pct() > 70) {
03204
03205
03206
03207
03208
03209 n_pages_flushed = buf_flush_list(
03210 PCT_IO(100), IB_ULONGLONG_MAX);
03211 } else {
03212
03213
03214
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
03223
03224 log_checkpoint(TRUE, FALSE);
03225
03226 srv_main_thread_op_info = "reserving kernel mutex";
03227
03228 mutex_enter(&kernel_mutex);
03229
03230
03231
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
03241
03242
03243 background_loop:
03244
03245
03246
03247
03248
03249
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
03257
03258
03259
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
03287
03288
03289
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
03311
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
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
03338
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
03353
03354
03355
03356 n_bytes_archived = 0;
03357
03358
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
03365
03366
03367
03368
03369
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
03377
03378
03379 goto background_loop;
03380 }
03381
03382
03383
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
03401
03402
03403
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
03410
03411
03412 os_thread_exit(NULL);
03413
03414 }
03415
03416
03417
03418
03419 goto loop;
03420
03421
03422 #if !defined(__SUNPRO_C)
03423 OS_THREAD_DUMMY_RETURN;
03424 #endif
03425 }
03426
03427
03430 UNIV_INTERN
03431 os_thread_ret_t
03432 srv_purge_thread(
03433
03434 void* )
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
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
03467
03468
03469
03470
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
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
03496
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
03522 srv_suspend_thread();
03523
03524 slot->in_use = FALSE;
03525
03526
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
03535
03536
03537
03538 os_thread_exit(NULL);
03539
03540 OS_THREAD_DUMMY_RETURN;
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 }