===== File: extra/yassl/src/ssl.cpp ===== 774 : : const char* path) 775 : : { 776 : : int ret = SSL_FAILURE; 777 : : 778 : : if (file) ret = read_file(ctx, file, SSL_FILETYPE_PEM, CA); 779 : : ===== File: sql/item_func.cc ===== 3958 : : else 3959 : 15 : connection_name= thd->variables.default_master_connection; 3960 : : 3961 : 15 : + if (!(mi= get_master_info(&connection_name, Sql_condition::WARN_LEVEL_WARN))) : b 1: 0 :: : b 2: 15 :: 3962 : 0 : goto err; 3963 : : 3964 : 15 : if ((event_count = mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2) : b 1: 15 :: : b 2: 0 :: 3966 : 15 : null_value = 1; 3967 : 15 : event_count=0; 3968 : : } 3969 : 15 : + mi->release(); 3970 : : #endif 3971 : 15 : return event_count; 3972 : : ===== File: sql/log_event.cc ===== 6244 : : 6245 : : @retval 6246 : : 0 ok 6247 : : + 1 error 6248 : : */ 6249 : 2606 : int Rotate_log_event::do_update_pos(rpl_group_info *rgi) 6250 : : { 6251 : 2606 : + int error= 0; 6252 : 2606 : Relay_log_info *rli= rgi->rli; 6253 : 2606 : DBUG_ENTER("Rotate_log_event::do_update_pos"); 6254 : : #ifndef DBUG_OFF 6300 : : (ulong) rli->group_master_log_pos)); 6301 : 594 : mysql_mutex_unlock(&rli->data_lock); 6302 : 594 : rpl_global_gtid_slave_state->record_and_update_gtid(thd, rgi); 6303 : 594 : + error= flush_relay_log_info(rli); 6304 : : 6305 : : /* 6306 : : Reset thd->variables.option_bits and sql_mode etc, because this could 6318 : : else 6319 : 2012 : rgi->inc_event_relay_log_pos(); 6320 : : 6321 : 2606 : + DBUG_RETURN(error); 6322 : : } 6323 : : 6324 : : 8175 : : 8176 : 249 : int Stop_log_event::do_update_pos(rpl_group_info *rgi) 8177 : : { 8178 : 249 : + int error= 0; 8179 : 249 : Relay_log_info *rli= rgi->rli; 8180 : 249 : DBUG_ENTER("Stop_log_event::do_update_pos"); 8181 : : /* 8191 : : { 8192 : 249 : rpl_global_gtid_slave_state->record_and_update_gtid(thd, rgi); 8193 : 249 : rli->inc_group_relay_log_pos(0, rgi); 8194 : 249 : + if (flush_relay_log_info(rli)) : b 1: 0 :: : b 2: 249 :: 8195 : 0 : + error= 1; 8196 : : } 8197 : 249 : + DBUG_RETURN(error); 8198 : : } 8199 : : 8200 : : #endif /* !MYSQL_CLIENT */ 10181 : 780 : Rows_log_event::do_update_pos(rpl_group_info *rgi) 10182 : : { 10183 : 780 : Relay_log_info *rli= rgi->rli; 10184 : 780 : int error= 0; 10185 : 780 : + DBUG_ENTER("Rows_log_event::do_update_pos"); 10186 : : 10187 : 780 : DBUG_PRINT("info", ("flags: %s", : b 2: 604 :: : b 3: 176 :: 10188 : : get_flags(STMT_END_F) ? "STMT_END_F " : "")); 10194 : : Step the group log position if we are not in a transaction, 10195 : : otherwise increase the event log position. 10196 : : */ 10197 : 604 : + error= rli->stmt_done(log_pos, thd, rgi); 10198 : : /* 10199 : : Clear any errors in thd->net.last_err*. It is not known if this is 10200 : : needed or not. It is believed that any errors that may exist in ===== File: sql/mysqld.cc ===== 702 : : LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, 703 : : LOCK_crypt, 704 : : LOCK_global_system_variables, 705 : : + LOCK_user_conn, LOCK_slave_list, 706 : : LOCK_connection_count, LOCK_error_messages, LOCK_slave_init; 707 : : 708 : : mysql_mutex_t LOCK_stats, LOCK_global_user_client_stats, 709 : : LOCK_global_table_stats, LOCK_global_index_stats; 710 : : 711 : : +/* This protects against changes in master_info_index */ 712 : : +mysql_mutex_t LOCK_active_mi; 713 : : + 714 : : /** 715 : : The below lock protects access to two global server variables: 716 : : max_prepared_stmt_count and prepared_stmt_count. These variables 863 : : key_LOCK_system_variables_hash, key_LOCK_thd_data, 864 : : key_LOCK_user_conn, key_LOCK_uuid_short_generator, key_LOG_LOCK_log, 865 : : key_master_info_data_lock, key_master_info_run_lock, 866 : : + key_master_info_sleep_lock, key_master_info_start_stop_lock, 867 : : key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock, 868 : : key_rpl_group_info_sleep_lock, 869 : : key_relay_log_info_log_space_lock, key_relay_log_info_run_lock, 933 : : { &key_LOCK_uuid_short_generator, "LOCK_uuid_short_generator", PSI_FLAG_GLOBAL}, 934 : : { &key_LOG_LOCK_log, "LOG::LOCK_log", 0}, 935 : : { &key_master_info_data_lock, "Master_info::data_lock", 0}, 936 : : + { &key_master_info_start_stop_lock, "Master_info::start_stop_lock", 0}, 937 : : { &key_master_info_run_lock, "Master_info::run_lock", 0}, 938 : : { &key_master_info_sleep_lock, "Master_info::sleep_lock", 0}, 939 : : { &key_mutex_slave_reporting_capability_err_lock, "Slave_reporting_capability::err_lock", 0}, 1655 : 360 : mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list 1656 : : 1657 : 360 : Events::deinit(); 1658 : 360 : + slave_prepare_for_shutdown(); 1659 : : 1660 : : /* 1661 : : Give threads time to die. 1704 : 83 : DBUG_PRINT("quit",("Unlocking LOCK_thread_count")); 1705 : 83 : mysql_mutex_unlock(&LOCK_thread_count); 1706 : : } 1707 : 360 : + end_slave(); 1708 : : /* All threads has now been aborted */ 1709 : 360 : DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); 1710 : 360 : mysql_mutex_lock(&LOCK_thread_count); 4928 : 0 : unireg_abort(1); 4929 : : } 4930 : : 4931 : 388 : + if (opt_bin_log) : b 0: 360 :: : b 1: 28 :: 4932 : : + { 4933 : : + int error; 4934 : 360 : + mysql_mutex_t *log_lock= mysql_bin_log.get_log_lock(); 4935 : 360 : + mysql_mutex_lock(log_lock); 4936 : : + error= mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0, 4937 : 360 : + WRITE_CACHE, max_binlog_size, 0, TRUE); 4938 : 360 : + mysql_mutex_unlock(log_lock); 4939 : 360 : + if (error) : b 0: 0 :: : b 1: 360 :: 4940 : 360 : + unireg_abort(1); 4941 : : + } 4942 : : 4943 : : #ifdef HAVE_REPLICATION 4944 : 388 : if (opt_bin_log && expire_logs_days) : b 0: 360 :: : b 1: 28 :: : b 2: 0 :: : b 3: 360 :: 7227 : : 7228 : 106939 : var->type= SHOW_MY_BOOL; 7229 : 106939 : var->value= buff; 7230 : : + 7231 : 106939 : + if ((mi= get_master_info(&thd->variables.default_master_connection, : b 1: 97875 :: : b 2: 9064 :: 7232 : 106939 : + Sql_condition::WARN_LEVEL_NOTE))) 7233 : : { 7234 : 97875 : + tmp= (my_bool) (mi->slave_running == MYSQL_SLAVE_RUN_READING && : b 0: 12880 :: : b 1: 84995 :: : b 2: 9877 :: : b 3: 3003 :: 7235 : 110755 : + mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN); 7236 : 97875 : + mi->release(); 7237 : : } 7238 : 106939 : if (mi) : b 0: 97875 :: : b 1: 9064 :: 7239 : 97875 : *((my_bool *)buff)= tmp; 7240 : : else 7266 : : { 7267 : 106939 : var->type= SHOW_LONGLONG; 7268 : 106939 : var->value= buff; 7269 : : 7270 : 106939 : + *((longlong *)buff)= any_slave_sql_running(); 7271 : : 7272 : 106939 : return 0; 7273 : : } 7274 : : 7275 : : 7276 : 106939 : static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff) 7277 : : { 7278 : : + Master_info *mi; 7279 : : 7280 : 106939 : var->type= SHOW_LONGLONG; 7281 : 106939 : var->value= buff; 7282 : : + 7283 : 106939 : + if ((mi= get_master_info(&thd->variables.default_master_connection, : b 1: 97894 :: : b 2: 9045 :: 7284 : 106939 : + Sql_condition::WARN_LEVEL_NOTE))) 7285 : : { 7286 : 97894 : + *((longlong *)buff)= mi->received_heartbeats; 7287 : 97894 : + mi->release(); 7288 : : } 7289 : : else 7290 : 9045 : var->type= SHOW_UNDEF; 7291 : 106939 : return 0; 7295 : 106939 : static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff) 7296 : : { 7297 : 106939 : Master_info *mi= NULL; 7298 : : 7299 : 106939 : var->type= SHOW_CHAR; 7300 : 106939 : var->value= buff; 7301 : : + 7302 : 106939 : + if ((mi= get_master_info(&thd->variables.default_master_connection, : b 1: 97938 :: : b 2: 9001 :: 7303 : 106939 : + Sql_condition::WARN_LEVEL_NOTE))) 7304 : : { 7305 : 97938 : + sprintf(buff, "%.3f", mi->heartbeat_period); 7306 : 97938 : + mi->release(); 7307 : : } 7308 : : else 7309 : 9001 : var->type= SHOW_UNDEF; 7310 : 106939 : return 0; ===== File: sql/rpl_mi.cc ===== 40 : : sync_counter(0), heartbeat_period(0), received_heartbeats(0), 41 : : master_id(0), prev_master_id(0), 42 : : using_gtid(USE_GTID_NO), events_queued_since_last_gtid(0), 43 : : + gtid_reconnect_event_skip_count(0), gtid_event_seen(false), 44 : : + in_start_all_slaves(0), in_stop_all_slaves(0), 45 : 1379 : + users(0), killed(0) 46 : : { 47 : 1379 : host[0] = 0; user[0] = 0; password[0] = 0; 48 : 1379 : ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0; 80 : 1379 : bzero((char*) &file, sizeof(file)); 81 : 1379 : mysql_mutex_init(key_master_info_run_lock, &run_lock, MY_MUTEX_INIT_FAST); 82 : 1379 : mysql_mutex_init(key_master_info_data_lock, &data_lock, MY_MUTEX_INIT_FAST); 83 : 1379 : + mysql_mutex_init(key_master_info_start_stop_lock, &start_stop_lock, 84 : 1379 : + MY_MUTEX_INIT_SLOW); 85 : 1379 : mysql_mutex_setflags(&run_lock, MYF_NO_DEADLOCK_DETECTION); 86 : 1379 : mysql_mutex_setflags(&data_lock, MYF_NO_DEADLOCK_DETECTION); 87 : 1379 : mysql_mutex_init(key_master_info_sleep_lock, &sleep_lock, MY_MUTEX_INIT_FAST); 91 : 1379 : mysql_cond_init(key_master_info_sleep_cond, &sleep_cond, NULL); 92 : 1379 : } 93 : : 94 : : + 95 : : +/** 96 : : + Wait until no one is using Master_info 97 : : +*/ 98 : : + 99 : 1379 : +void Master_info::wait_until_free() 100 : : +{ 101 : 1379 : + mysql_mutex_lock(&sleep_lock); 102 : 1379 : + killed= 1; 103 : 1410 : + while (users) : b 0: 31 :: : b 1: 1379 :: 104 : 31 : + mysql_cond_wait(&sleep_cond, &sleep_lock); 105 : 1379 : + mysql_mutex_unlock(&sleep_lock); 106 : 1379 : +} 107 : : + 108 : : +/** 109 : : + Delete master_info 110 : : +*/ 111 : : + 112 : 4137 : Master_info::~Master_info() 113 : : { 114 : 1379 : + wait_until_free(); 115 : : rpl_filters.delete_element(connection_name.str, connection_name.length, 116 : 1379 : (void (*)(const char*, uchar*)) free_rpl_filter); 117 : 1379 : my_free(connection_name.str); 119 : 1379 : mysql_mutex_destroy(&run_lock); 120 : 1379 : mysql_mutex_destroy(&data_lock); 121 : 1379 : mysql_mutex_destroy(&sleep_lock); 122 : 1379 : + mysql_mutex_destroy(&start_stop_lock); 123 : 1379 : mysql_cond_destroy(&data_cond); 124 : 1379 : mysql_cond_destroy(&start_cond); 125 : 1379 : mysql_cond_destroy(&stop_cond); 733 : 1205 : void free_key_master_info(Master_info *mi) 734 : : { 735 : 1205 : DBUG_ENTER("free_key_master_info"); 736 : : + /* Ensure that we are not in reset_slave while this is done */ 737 : 1205 : + mi->lock_slave_threads(); 738 : 1205 : terminate_slave_threads(mi,SLAVE_FORCE_ALL); 739 : : + /* We use 2 here instead of 1 just to make it easier when debugging */ 740 : 1205 : + mi->killed= 2; 741 : 1205 : end_master_info(mi); 742 : 1205 : + mi->unlock_slave_threads(); 743 : 1205 : delete mi; : b 0: 1205 :: : b 1: 0 :: 744 : 1205 : DBUG_VOID_RETURN; 745 : : } 896 : 360 : index_file.file= -1; 897 : 360 : } 898 : : 899 : : + 900 : : +/** 901 : : + Free all connection threads 902 : : + 903 : : + This is done during early stages of shutdown 904 : : + to give connection threads and slave threads time 905 : : + to die before ~Master_info_index is called 906 : : +*/ 907 : : + 908 : 360 : +void Master_info_index::free_connections() 909 : : +{ 910 : 360 : + my_hash_reset(&master_info_hash); 911 : 360 : +} 912 : : + 913 : : + 914 : : +/** 915 : : + Free all connection threads and free structures 916 : : +*/ 917 : : + 918 : 360 : Master_info_index::~Master_info_index() 919 : : { 920 : 360 : my_hash_free(&master_info_hash); 921 : 360 : end_io_cache(&index_file); 922 : 360 : if (index_file.file >= 0) : b 0: 360 :: : b 1: 0 :: 939 : : File index_file_nr; 940 : 360 : DBUG_ENTER("init_all_master_info"); 941 : : 942 : 360 : DBUG_ASSERT(master_info_index); : b 0: 0 :: : b 1: 360 :: 943 : : 944 : 360 : if ((index_file_nr= my_open(index_file_name, : b 0: 0 :: : b 1: 360 :: 986 : 0 : DBUG_RETURN(1); 987 : : } 988 : : 989 : 548 : + mi->lock_slave_threads(); 990 : 548 : init_thread_mask(&thread_mask,mi,0 /*not inverse*/); 991 : : 992 : : create_logfile_name_with_suffix(buf_master_info_file, 1014 : 0 : if (master_info_index->add_master_info(mi, FALSE)) : b 1: 0 :: : b 2: 0 :: 1015 : 0 : DBUG_RETURN(1); 1016 : 0 : succ_num++; 1017 : 0 : + mi->unlock_slave_threads(); 1018 : : } 1019 : : else 1020 : : { 1021 : : /* Master_info already in HASH */ 1022 : 0 : sql_print_error(ER(ER_CONNECTION_ALREADY_EXISTS), 1023 : 0 : (int) connection_name.length, connection_name.str); 1024 : 0 : + mi->unlock_slave_threads(); 1025 : 0 : delete mi; : b 0: 0 :: : b 1: 0 :: 1026 : : } 1027 : 0 : continue; 1037 : : { 1038 : : /* Master_info was already registered */ 1039 : 0 : sql_print_error(ER(ER_CONNECTION_ALREADY_EXISTS), 1040 : : + (int) connection_name.length, connection_name.str, 1041 : 0 : (int) connection_name.length, connection_name.str); 1042 : 0 : + mi->unlock_slave_threads(); 1043 : 0 : delete mi; : b 0: 0 :: : b 1: 0 :: 1044 : 0 : continue; 1045 : : } 1048 : 548 : if (master_info_index->add_master_info(mi, FALSE)) : b 1: 0 :: : b 2: 548 :: 1049 : 0 : DBUG_RETURN(1); 1050 : 548 : succ_num++; 1051 : : 1052 : 548 : if (!opt_skip_slave_start) : b 0: 548 :: : b 1: 0 :: 1053 : : { 1068 : : (int) connection_name.length, 1069 : 548 : connection_name.str); 1070 : : } 1071 : 548 : + mi->unlock_slave_threads(); 1072 : : } 1073 : : } 1074 : : 1120 : : 1121 : : 1122 : : /** 1123 : : + Get Master_info for a connection and lock the object from deletion 1124 : : + 1125 : : + @param 1126 : : + connection_name Connection name 1127 : : + warning WARN_LEVEL_NOTE -> Don't print anything 1128 : : + WARN_LEVEL_WARN -> Issue warning if not exists 1129 : : + WARN_LEVEL_ERROR-> Issue error if not exists 1130 : : +*/ 1131 : : + 1132 : 403829 : +Master_info *get_master_info(LEX_STRING *connection_name, 1133 : : + Sql_condition::enum_warning_level warning) 1134 : : +{ 1135 : : + Master_info *mi; 1136 : 403829 : + DBUG_ENTER("get_master_info"); 1137 : : + 1138 : : + /* Protect against inserts into hash */ 1139 : 403828 : + mysql_mutex_lock(&LOCK_active_mi); 1140 : : + /* 1141 : : + The following can only be true during shutdown when slave has been killed 1142 : : + but some other threads are still trying to access slave statistics. 1143 : : + */ 1144 : 403832 : + if (unlikely(!master_info_index)) : b 0: 0 :: : b 1: 403832 :: : b 2: 0 :: : b 3: 403832 :: 1145 : : + { 1146 : 0 : + if (warning != Sql_condition::WARN_LEVEL_NOTE) : b 0: 0 :: : b 1: 0 :: 1147 : : + my_error(WARN_NO_MASTER_INFO, 1148 : : + MYF(warning == Sql_condition::WARN_LEVEL_WARN ? 1149 : : + ME_JUST_WARNING : 0), 1150 : 0 : + (int) connection_name->length, connection_name->str); : b 0: 0 :: : b 1: 0 :: 1151 : 0 : + mysql_mutex_unlock(&LOCK_active_mi); 1152 : 0 : + DBUG_RETURN(0); 1153 : : + } 1154 : 403832 : + if ((mi= master_info_index->get_master_info(connection_name, warning))) : b 1: 369168 :: : b 2: 34664 :: 1155 : : + { 1156 : : + /* 1157 : : + We have to use sleep_lock here. If we would use LOCK_active_mi 1158 : : + then we would take locks in wrong order in Master_info::release() 1159 : : + */ 1160 : 369168 : + mysql_mutex_lock(&mi->sleep_lock); 1161 : 369168 : + mi->users++; 1162 : 369168 : + DBUG_PRINT("info",("users: %d", mi->users)); 1163 : 369168 : + mysql_mutex_unlock(&mi->sleep_lock); 1164 : : + } 1165 : 403832 : + mysql_mutex_unlock(&LOCK_active_mi); 1166 : 403832 : + DBUG_RETURN(mi); 1167 : : +} 1168 : : + 1169 : : + 1170 : : +/** 1171 : : + Release master info. 1172 : : + Signals ~Master_info that it's now safe to delete it 1173 : : +*/ 1174 : : + 1175 : 373277 : +void Master_info::release() 1176 : : +{ 1177 : 373277 : + mysql_mutex_lock(&sleep_lock); 1178 : 373277 : + if (!--users && killed) : b 0: 248129 :: : b 1: 125148 :: : b 2: 31 :: : b 3: 248098 :: : b 4: 31 :: : b 5: 373246 :: 1179 : : + { 1180 : : + /* Signal ~Master_info that it's ok to now free it */ 1181 : 31 : + mysql_cond_signal(&sleep_cond); 1182 : : + } 1183 : 373277 : + mysql_mutex_unlock(&sleep_lock); 1184 : 373277 : +} 1185 : : + 1186 : : + 1187 : : +/** 1188 : : Get Master_info for a connection 1189 : : 1190 : : @param 1206 : : ("connection_name: '%.*s'", (int) connection_name->length, 1207 : : connection_name->str)); 1208 : : 1209 : : /* Make name lower case for comparison */ 1210 : 410825 : res= strmake(buff, connection_name->str, connection_name->length); 1211 : 410825 : my_casedn_str(system_charset_info, buff); 1297 : : atomic 1298 : : */ 1299 : : 1300 : 253 : +bool Master_info_index::remove_master_info(Master_info *mi) 1301 : : { 1302 : 253 : DBUG_ENTER("remove_master_info"); 1303 : 253 : + mysql_mutex_assert_owner(&LOCK_active_mi); : b 0: 253 :: : b 1: 0 :: : b 4: 0 :: : b 5: 253 :: 1304 : : 1305 : : + // Delete Master_info and rewrite others to file 1306 : 253 : + if (!my_hash_delete(&master_info_hash, (uchar*) mi)) : b 1: 252 :: : b 2: 1 :: 1307 : : { 1308 : : + File index_file_nr; 1309 : : + 1310 : : + // Close IO_CACHE and FILE handler fisrt 1311 : 252 : + end_io_cache(&index_file); 1312 : 252 : + my_close(index_file.file, MYF(MY_WME)); 1313 : : + 1314 : : + // Reopen File and truncate it 1315 : 252 : + if ((index_file_nr= my_open(index_file_name, : b 0: 0 :: : b 1: 252 :: 1316 : : + O_RDWR | O_CREAT | O_TRUNC | O_BINARY , 1317 : 504 : + MYF(MY_WME))) < 0 || : b 1: 252 :: : b 2: 0 :: : b 3: 0 :: : b 4: 252 :: 1318 : : + init_io_cache(&index_file, index_file_nr, 1319 : : + IO_SIZE, WRITE_CACHE, 1320 : : + my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)), 1321 : 252 : + 0, MYF(MY_WME | MY_WAIT_IF_FULL))) 1322 : : { 1323 : 0 : + int error= my_errno; 1324 : 0 : + if (index_file_nr >= 0) : b 0: 0 :: : b 1: 0 :: 1325 : 0 : + my_close(index_file_nr,MYF(0)); 1326 : : 1327 : : + sql_print_error("Create of Master Info Index file '%s' failed with " 1328 : : + "error: %M", 1329 : 0 : + index_file_name, error); 1330 : 0 : + DBUG_RETURN(TRUE); 1331 : : + } 1332 : : + 1333 : : + // Rewrite Master_info.index 1334 : 704 : + for (uint i= 0; i< master_info_hash.records; ++i) : b 0: 452 :: : b 1: 252 :: 1335 : : + { 1336 : : + Master_info *tmp_mi; 1337 : 452 : + tmp_mi= (Master_info *) my_hash_element(&master_info_hash, i); 1338 : 452 : + write_master_name_to_index_file(&tmp_mi->connection_name, 0); 1339 : : } 1340 : 252 : + if (my_sync(index_file_nr, MYF(MY_WME))) : b 1: 0 :: : b 2: 252 :: 1341 : 252 : + DBUG_RETURN(TRUE); 1342 : : } 1343 : 253 : DBUG_RETURN(FALSE); 1344 : : } 1345 : : 1346 : : 1347 : : /** 1348 : : + give_error_if_slave_running() 1349 : : + 1350 : : + @param 1351 : : + already_locked 0 if we need to lock, 1 if we have LOCK_active_mi_locked 1352 : : 1353 : : @return 1354 : : TRUE If some slave is running. An error is printed 1355 : : FALSE No slave is running 1356 : : */ 1357 : : 1358 : 148 : +bool give_error_if_slave_running(bool already_locked) 1359 : : { 1360 : 148 : + bool ret= 0; 1361 : 148 : DBUG_ENTER("give_error_if_slave_running"); 1362 : : 1363 : 148 : + if (!already_locked) : b 0: 130 :: : b 1: 18 :: 1364 : 130 : + mysql_mutex_lock(&LOCK_active_mi); 1365 : 148 : + if (!master_info_index) : b 0: 0 :: : b 1: 148 :: 1366 : : { 1367 : 0 : + my_error(ER_SERVER_SHUTDOWN, MYF(0)); 1368 : 0 : + ret= 1; 1369 : : + } 1370 : : + else 1371 : : + { 1372 : 148 : + HASH *hash= &master_info_index->master_info_hash; 1373 : 375 : + for (uint i= 0; i< hash->records; ++i) : b 0: 285 :: : b 1: 90 :: 1374 : : { 1375 : : + Master_info *mi; 1376 : 285 : + mi= (Master_info *) my_hash_element(hash, i); 1377 : 285 : + if (mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN) : b 0: 58 :: : b 1: 227 :: 1378 : : + { 1379 : : + my_error(ER_SLAVE_MUST_STOP, MYF(0), (int) mi->connection_name.length, 1380 : 58 : + mi->connection_name.str); 1381 : 58 : + ret= 1; 1382 : 58 : + break; 1383 : : + } 1384 : : } 1385 : : } 1386 : 148 : + if (!already_locked) : b 0: 130 :: : b 1: 18 :: 1387 : 130 : + mysql_mutex_unlock(&LOCK_active_mi); 1388 : 148 : + DBUG_RETURN(ret); 1389 : : } 1390 : : 1391 : : 1392 : : /** 1393 : : + any_slave_sql_running() 1394 : : 1395 : : @return 1396 : : 0 No Slave SQL thread is running 1397 : : # Number of slave SQL thread running 1398 : : */ 1399 : : 1400 : 110911 : +uint any_slave_sql_running() 1401 : : { 1402 : 110911 : uint count= 0; 1403 : 110911 : DBUG_ENTER("any_slave_sql_running"); 1404 : : 1405 : 110911 : + mysql_mutex_lock(&LOCK_active_mi); 1406 : 110912 : + if (likely(master_info_index)) // Not shutdown : b 0: 110533 :: : b 1: 379 :: 1407 : : { 1408 : 110533 : + HASH *hash= &master_info_index->master_info_hash; 1409 : 394450 : + for (uint i= 0; i< hash->records; ++i) : b 0: 283917 :: : b 1: 110533 :: 1410 : : + { 1411 : 283917 : + Master_info *mi= (Master_info *)my_hash_element(hash, i); 1412 : 283917 : + if (mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN) : b 0: 100664 :: : b 1: 183253 :: 1413 : 100664 : + count++; 1414 : : + } 1415 : : } 1416 : 110912 : + mysql_mutex_unlock(&LOCK_active_mi); 1417 : 110912 : DBUG_RETURN(count); 1418 : : } 1419 : : 1426 : : @return 1427 : : TRUE Error 1428 : : FALSE Everything ok. 1429 : : + 1430 : : + This code is written so that we don't keep LOCK_active_mi active 1431 : : + while we are starting a slave. 1432 : : */ 1433 : : 1434 : 1872 : bool Master_info_index::start_all_slaves(THD *thd) 1435 : : { 1436 : 1872 : bool result= FALSE; 1437 : 1872 : + DBUG_ENTER("start_all_slaves"); 1438 : 1872 : mysql_mutex_assert_owner(&LOCK_active_mi); : b 0: 1872 :: : b 1: 0 :: : b 4: 0 :: : b 5: 1872 :: 1439 : : 1440 : 6715 : + for (uint i= 0; i< master_info_hash.records; i++) : b 0: 4843 :: : b 1: 1872 :: 1441 : : + { 1442 : : + Master_info *mi; 1443 : 4843 : + mi= (Master_info *) my_hash_element(&master_info_hash, i); 1444 : 4843 : + mi->in_start_all_slaves= 0; 1445 : : + } 1446 : : + 1447 : 9933 : + for (uint i= 0; i< master_info_hash.records; ) : b 0: 8097 :: : b 1: 1836 :: 1448 : : { 1449 : : int error; 1450 : : Master_info *mi; 1454 : : Try to start all slaves that are configured (host is defined) 1455 : : and are not already running 1456 : : */ 1457 : 12832 : + if (!((mi->slave_running == MYSQL_SLAVE_NOT_RUN || : b 0: 496 :: : b 1: 4239 :: : b 2: 6137 :: : b 3: 1960 :: 1458 : 12832 : + !mi->rli.slave_running) && *mi->host) || : b 0: 4735 :: : b 1: 3362 :: : b 2: 2320 :: : b 3: 1538 :: : b 4: 360 :: : b 5: 1960 :: 1459 : : + mi->in_start_all_slaves) 1460 : : { 1461 : 6137 : + i++; 1462 : 6137 : + continue; 1463 : : + } 1464 : 1960 : + mi->in_start_all_slaves= 1; 1465 : : + 1466 : 1960 : + mysql_mutex_lock(&mi->sleep_lock); 1467 : 1960 : + mi->users++; // Mark used 1468 : 1960 : + mysql_mutex_unlock(&mi->sleep_lock); 1469 : 1960 : + mysql_mutex_unlock(&LOCK_active_mi); 1470 : 1960 : + error= start_slave(thd, mi, 1); 1471 : 1960 : + mi->release(); 1472 : 1960 : + mysql_mutex_lock(&LOCK_active_mi); 1473 : 1960 : + if (error) : b 0: 37 :: : b 1: 1923 :: 1474 : : + { 1475 : : + my_error(ER_CANT_START_STOP_SLAVE, MYF(0), 1476 : : + "START", 1477 : : + (int) mi->connection_name.length, 1478 : 37 : + mi->connection_name.str); 1479 : 37 : + result= 1; 1480 : 37 : + if (error < 0) // fatal error : b 0: 36 :: : b 1: 1 :: 1481 : 36 : + break; 1482 : : } 1483 : : + else 1484 : : + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, 1485 : 1923 : + ER_SLAVE_STARTED, ER(ER_SLAVE_STARTED), 1486 : : + (int) mi->connection_name.length, 1487 : 1923 : + mi->connection_name.str); 1488 : : + /* Restart from first element as master_info_hash may have changed */ 1489 : 1924 : + i= 0; 1490 : 1924 : + continue; 1491 : : } 1492 : 1872 : DBUG_RETURN(result); 1493 : : } 1501 : : @return 1502 : : TRUE Error 1503 : : FALSE Everything ok. 1504 : : + 1505 : : + This code is written so that we don't keep LOCK_active_mi active 1506 : : + while we are stopping a slave. 1507 : : */ 1508 : : 1509 : 2035 : bool Master_info_index::stop_all_slaves(THD *thd) 1510 : : { 1511 : 2035 : bool result= FALSE; 1512 : 2035 : + DBUG_ENTER("stop_all_slaves"); 1513 : 2035 : mysql_mutex_assert_owner(&LOCK_active_mi); : b 0: 2035 :: : b 1: 0 :: : b 4: 0 :: : b 5: 2035 :: 1514 : : 1515 : 7332 : + for (uint i= 0; i< master_info_hash.records; i++) : b 0: 5297 :: : b 1: 2035 :: 1516 : : + { 1517 : : + Master_info *mi; 1518 : 5297 : + mi= (Master_info *) my_hash_element(&master_info_hash, i); 1519 : 5297 : + mi->in_stop_all_slaves= 0; 1520 : : + } 1521 : : + 1522 : 10824 : + for (uint i= 0; i< master_info_hash.records ;) : b 0: 8789 :: : b 1: 2035 :: 1523 : : { 1524 : : int error; 1525 : : Master_info *mi; 1526 : 8789 : mi= (Master_info *) my_hash_element(&master_info_hash, i); 1527 : 8789 : + if (!(mi->slave_running != MYSQL_SLAVE_NOT_RUN || : b 0: 6640 :: : b 1: 2149 :: 1528 : 8789 : + mi->rli.slave_running) || : b 0: 6124 :: : b 1: 2665 :: : b 2: 31 :: : b 3: 6093 :: : b 4: 547 :: : b 5: 2149 :: 1529 : : + mi->in_stop_all_slaves) 1530 : : { 1531 : 6640 : + i++; 1532 : 6640 : + continue; 1533 : : } 1534 : 2149 : + mi->in_stop_all_slaves= 1; // Protection for loops 1535 : : + 1536 : 2149 : + mysql_mutex_lock(&mi->sleep_lock); 1537 : 2149 : + mi->users++; // Mark used 1538 : 2149 : + mysql_mutex_unlock(&mi->sleep_lock); 1539 : 2149 : + mysql_mutex_unlock(&LOCK_active_mi); 1540 : 2149 : + error= stop_slave(thd, mi, 1); 1541 : 2149 : + mi->release(); 1542 : 2149 : + mysql_mutex_lock(&LOCK_active_mi); 1543 : 2149 : + if (error) : b 0: 0 :: : b 1: 2149 :: 1544 : : + { 1545 : : + my_error(ER_CANT_START_STOP_SLAVE, MYF(0), 1546 : : + "STOP", 1547 : : + (int) mi->connection_name.length, 1548 : 0 : + mi->connection_name.str); 1549 : 0 : + result= 1; 1550 : 0 : + if (error < 0) // Fatal error : b 0: 0 :: : b 1: 0 :: 1551 : 0 : + break; 1552 : : + } 1553 : : + else 1554 : : + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, 1555 : 2149 : + ER_SLAVE_STOPPED, ER(ER_SLAVE_STOPPED), 1556 : : + (int) mi->connection_name.length, 1557 : 2149 : + mi->connection_name.str); 1558 : : + /* Restart from first element as master_info_hash may have changed */ 1559 : 2149 : + i= 0; 1560 : 2149 : + continue; 1561 : : } 1562 : 2035 : DBUG_RETURN(result); 1563 : : } ===== File: sql/rpl_parallel.cc ===== 1312 : : } 1313 : 5970 : if (!in_event_group) : b 0: 5927 :: : b 1: 43 :: 1314 : : { 1315 : : + /* If we are in a FLUSH TABLES FOR READ LOCK, wait for it */ 1316 : 5929 : + while (rpt->current_entry && rpt->pause_for_ftwrl) : b 0: 700 :: : b 1: 5229 :: : b 2: 4 :: : b 3: 696 :: 1317 : : + { 1318 : 4 : + mysql_mutex_lock(&rpt->current_entry->LOCK_parallel_entry); 1319 : 4 : + mysql_mutex_unlock(&rpt->LOCK_rpl_thread); 1320 : 4 : + if (rpt->pause_for_ftwrl) : b 0: 4 :: : b 1: 0 :: 1321 : 4 : + mysql_cond_wait(&rpt->current_entry->COND_parallel_entry, 1322 : 4 : + &rpt->current_entry->LOCK_parallel_entry); 1323 : 4 : + mysql_mutex_unlock(&rpt->current_entry->LOCK_parallel_entry); 1324 : 4 : + mysql_mutex_lock(&rpt->LOCK_rpl_thread); 1325 : : + } 1326 : 5925 : rpt->current_owner= NULL; 1327 : : /* Tell wait_for_done() that we are done, if it is waiting. */ 1328 : 5925 : if (likely(rpt->current_entry) && : b 0: 696 :: : b 1: 5229 :: : b 2: 488 :: : b 3: 208 :: 1329 : 696 : unlikely(rpt->current_entry->force_abort)) 1330 : 488 : mysql_cond_broadcast(&rpt->COND_rpl_thread_stop); 1331 : : + 1332 : 5925 : rpt->current_entry= NULL; 1333 : 5925 : if (!rpt->stop) : b 0: 696 :: : b 1: 5229 :: 1334 : 696 : rpt->pool->release_thread(rpt); 1382 : 11 : return res; 1383 : : 1384 : : /* 1385 : : + If we are about to delete pool, do an extra check that there are no new 1386 : : + slave threads running since we marked pool busy 1387 : : + */ 1388 : 2249 : + if (!new_count) : b 0: 1590 :: : b 1: 659 :: 1389 : : + { 1390 : 1590 : + if (any_slave_sql_running()) : b 1: 3 :: : b 2: 1587 :: 1391 : : + { 1392 : 3 : + DBUG_PRINT("warning", 1393 : : + ("SQL threads running while trying to reset parallel pool")); 1394 : 3 : + pool_mark_not_busy(pool); 1395 : 3 : + return 1; 1396 : : + } 1397 : : + } 1398 : : + 1399 : : + /* 1400 : : Allocate the new list of threads up-front. 1401 : : That way, if we fail half-way, we only need to free whatever we managed 1402 : : to allocate, and will not be left with a half-functional thread pool. 1409 : : { 1410 : : my_error(ER_OUTOFMEMORY, MYF(0), (int(new_count*sizeof(*new_list) + 1411 : 0 : new_count*sizeof(*rpt_array)))); 1412 : 0 : + goto err; 1413 : : } 1414 : : 1415 : 7481 : for (i= 0; i < new_count; ++i) : b 0: 5235 :: : b 1: 2246 :: 1530 : 2260 : return 1; 1531 : : } 1532 : : 1533 : : +/* 1534 : : + Deactivate the parallel replication thread pool, if there are now no more 1535 : : + SQL threads running. 1536 : : +*/ 1537 : : + 1538 : 5475 : +int rpl_parallel_resize_pool_if_no_slaves(void) 1539 : : +{ 1540 : : + /* master_info_index is set to NULL on shutdown */ 1541 : 5475 : + if (opt_slave_parallel_threads > 0 && !any_slave_sql_running() && : b 0: 2383 :: : b 1: 3092 :: : b 3: 1259 :: : b 4: 1124 :: : b 5: 1240 :: : b 6: 19 :: : b 7: 1240 :: : b 8: 4235 :: 1542 : : + master_info_index) 1543 : 1240 : + return rpl_parallel_inactivate_pool(&global_rpl_thread_pool); 1544 : 4235 : + return 0; 1545 : : +} 1546 : : + 1547 : : 1548 : : int 1549 : 1344 : rpl_parallel_activate_pool(rpl_parallel_thread_pool *pool) ===== File: sql/rpl_rli.cc ===== 208 : 1924 : Master_info* mi= rli->mi; 209 : : char buf_relay_logname[FN_REFLEN], buf_relaylog_index_name_buff[FN_REFLEN]; 210 : 1924 : char *buf_relaylog_index_name= opt_relaylog_index_name; 211 : : + mysql_mutex_t *log_lock; 212 : : 213 : : create_logfile_name_with_suffix(buf_relay_logname, 214 : : sizeof(buf_relay_logname), 228 : : note, that if open() fails, we'll still have index file open 229 : : but a destructor will take care of that 230 : : */ 231 : 1924 : + log_lock= rli->relay_log.get_log_lock(); 232 : 1924 : + mysql_mutex_lock(log_lock); 233 : 3848 : if (rli->relay_log.open_index_file(buf_relaylog_index_name, ln, TRUE) || : b 1: 1924 :: : b 2: 0 :: : b 3: 0 :: : b 4: 1924 :: : b 5: 0 :: : b 6: 1924 :: 234 : : rli->relay_log.open(ln, LOG_BIN, 0, SEQ_READ_APPEND, 235 : 1924 : mi->rli.max_relay_log_size, 1, TRUE)) 236 : : { 237 : 0 : + mysql_mutex_unlock(log_lock); 238 : 0 : mysql_mutex_unlock(&rli->data_lock); 239 : 0 : sql_print_error("Failed when trying to open logs for '%s' in init_relay_log_info(). Error: %M", ln, my_errno); 240 : 0 : DBUG_RETURN(1); 241 : : } 242 : 1924 : + mysql_mutex_unlock(log_lock); 243 : : } 244 : : 245 : : /* if file does not exist */ 437 : : } 438 : 1924 : rli->inited= 1; 439 : 1924 : mysql_mutex_unlock(&rli->data_lock); 440 : 1924 : + DBUG_RETURN(0); 441 : : 442 : : err: 443 : 0 : sql_print_error("%s", msg); 1309 : : } 1310 : : 1311 : : 1312 : 5571 : +bool Relay_log_info::stmt_done(my_off_t event_master_log_pos, THD *thd, 1313 : : rpl_group_info *rgi) 1314 : : { 1315 : 5571 : + int error= 0; 1316 : 5571 : DBUG_ENTER("Relay_log_info::stmt_done"); 1317 : : 1318 : 5571 : DBUG_ASSERT(rgi->rli == this); : b 0: 0 :: : b 1: 5571 :: 1364 : : } 1365 : 3856 : DBUG_EXECUTE_IF("inject_crash_before_flush_rli", DBUG_SUICIDE();); : b 1: 0 :: : b 2: 3856 :: 1366 : 3856 : if (mi->using_gtid == Master_info::USE_GTID_NO) : b 0: 0 :: : b 1: 3856 :: 1367 : 0 : + if (flush_relay_log_info(this)) : b 1: 0 :: : b 2: 0 :: 1368 : 0 : + error= 1; 1369 : 3856 : DBUG_EXECUTE_IF("inject_crash_after_flush_rli", DBUG_SUICIDE();); : b 1: 0 :: : b 2: 3856 :: 1370 : : } 1371 : 5571 : + DBUG_RETURN(error); 1372 : : } 1373 : : 1374 : : ===== File: sql/slave.cc ===== 228 : : 229 : : 230 : : /* 231 : : + lock_slave_threads() against other threads doing STOP, START or RESET SLAVE 232 : : + 233 : : */ 234 : : 235 : 14383 : +void Master_info::lock_slave_threads() 236 : : { 237 : 14383 : DBUG_ENTER("lock_slave_threads"); 238 : 14383 : + mysql_mutex_lock(&start_stop_lock); 239 : 14382 : DBUG_VOID_RETURN; 240 : : } 241 : : 244 : : unlock_slave_threads() 245 : : */ 246 : : 247 : 14383 : +void Master_info::unlock_slave_threads() 248 : : { 249 : 14383 : DBUG_ENTER("unlock_slave_threads"); 250 : 14383 : + mysql_mutex_unlock(&start_stop_lock); 251 : 14383 : DBUG_VOID_RETURN; 252 : : } 253 : : 369 : : accepted. However bootstrap may conflict with us if it does START SLAVE. 370 : : So it's safer to take the lock. 371 : : */ 372 : : 373 : 360 : if (pthread_key_create(&RPL_MASTER_INFO, NULL)) : b 1: 0 :: : b 2: 360 :: 374 : 0 : goto err; 377 : 360 : if (!master_info_index || master_info_index->init_all_master_info()) : b 0: 360 :: : b 1: 0 :: : b 3: 0 :: : b 4: 360 :: : b 5: 0 :: : b 6: 360 :: 378 : : { 379 : 0 : sql_print_error("Failed to initialize multi master structures"); 380 : 0 : DBUG_RETURN(1); 381 : : } 382 : 360 : if (!(active_mi= new Master_info(&default_master_connection_name, : b 0: 0 :: : b 1: 360 :: 434 : : } 435 : : 436 : : end: 437 : 360 : DBUG_RETURN(error); 438 : : 439 : : err: 606 : 3877 : if (!mi->inited) : b 0: 285 :: : b 1: 3592 :: 607 : 285 : DBUG_RETURN(0); /* successfully do nothing */ 608 : 3592 : int error,force_all = (thread_mask & SLAVE_FORCE_ALL); 609 : 3592 : + int retval= 0; 610 : 3592 : mysql_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock; 611 : 3592 : mysql_mutex_t *log_lock= mi->rli.relay_log.get_log_lock(); 612 : : 626 : 3587 : skip_lock)) && : b 1: 0 :: : b 2: 3587 :: : b 3: 0 :: : b 4: 0 :: 627 : : !force_all) 628 : 0 : DBUG_RETURN(error); 629 : 3587 : + retval= error; 630 : : 631 : 3587 : mysql_mutex_lock(log_lock); 632 : : 633 : 3587 : DBUG_PRINT("info",("Flushing relay-log info file.")); 634 : 3587 : if (current_thd) : b 1: 2678 :: : b 2: 909 :: 635 : 2678 : THD_STAGE_INFO(current_thd, stage_flushing_relay_log_info_file); 636 : 7174 : + if (flush_relay_log_info(&mi->rli) || : b 1: 3587 :: : b 2: 0 :: : b 3: 0 :: : b 4: 3587 :: : b 5: 0 :: : b 6: 3587 :: 637 : 3587 : + my_sync(mi->rli.info_fd, MYF(MY_WME))) 638 : 0 : + retval= ER_ERROR_DURING_FLUSH_LOGS; 639 : : 640 : 3587 : mysql_mutex_unlock(log_lock); 641 : : } 642 : 3592 : if (thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)) : b 0: 3540 :: : b 1: 52 :: 643 : : { 644 : 3540 : DBUG_PRINT("info",("Terminating IO thread")); 649 : 3540 : skip_lock)) && : b 1: 0 :: : b 2: 3540 :: : b 3: 0 :: : b 4: 0 :: 650 : : !force_all) 651 : 0 : DBUG_RETURN(error); 652 : 3540 : + if (!retval) : b 0: 3540 :: : b 1: 0 :: 653 : 3540 : + retval= error; 654 : : 655 : 3540 : mysql_mutex_lock(log_lock); 656 : : 657 : 3540 : DBUG_PRINT("info",("Flushing relay log and master info file.")); 658 : 3540 : if (current_thd) : b 1: 2631 :: : b 2: 909 :: 659 : 2631 : THD_STAGE_INFO(current_thd, stage_flushing_relay_log_and_master_info_repository); 660 : 3540 : + if (likely(mi->fd >= 0)) : b 0: 3540 :: : b 1: 0 :: : b 2: 3540 :: : b 3: 0 :: 661 : : + { 662 : 3540 : + if (flush_master_info(mi, TRUE, FALSE) || my_sync(mi->fd, MYF(MY_WME))) : b 1: 3540 :: : b 2: 0 :: : b 4: 0 :: : b 5: 3540 :: : b 6: 0 :: : b 7: 3540 :: 663 : 0 : + retval= ER_ERROR_DURING_FLUSH_LOGS; 664 : : + } 665 : 7080 : if (mi->rli.relay_log.is_open() && : b 1: 3540 :: : b 2: 0 :: : b 3: 0 :: : b 4: 3540 :: : b 5: 0 :: : b 6: 3540 :: 666 : 3540 : my_sync(mi->rli.relay_log.get_log_file()->file, MYF(MY_WME))) 667 : 0 : + retval= ER_ERROR_DURING_FLUSH_LOGS; 668 : : 669 : 3540 : mysql_mutex_unlock(log_lock); 670 : : } 671 : 3877 : + DBUG_RETURN(retval); 672 : : } 673 : : 674 : : 831 : 0 : mysql_mutex_unlock(start_lock); 832 : 0 : DBUG_RETURN(ER_SLAVE_THREAD); 833 : : } 834 : : + 835 : : + /* 836 : : + In the following loop we can't check for thd->killed as we have to 837 : : + wait until THD structures for the slave thread are created 838 : : + before we can return. 839 : : + This should be ok as there is no major work done in the slave 840 : : + threads before they signal that we can stop waiting. 841 : : + */ 842 : : + 843 : 6299 : if (start_cond && cond_lock) // caller has cond_lock : b 0: 4745 :: : b 1: 1554 :: : b 2: 4745 :: : b 3: 0 :: 844 : : { 845 : 4745 : THD* thd = current_thd; 857 : : registered, we could otherwise go waiting though thd->killed is 858 : : set. 859 : : */ 860 : 4768 : + mysql_cond_wait(start_cond, cond_lock); 861 : 4768 : thd->EXIT_COND(& saved_stage); 862 : 4768 : mysql_mutex_lock(cond_lock); // re-acquire it as exit_cond() released 863 : : } 864 : : } 865 : 6299 : if (start_lock) : b 0: 6299 :: : b 1: 0 :: 966 : : 967 : : 968 : : /* 969 : : + Kill slaves preparing for shutdown 970 : : +*/ 971 : : 972 : 360 : +void slave_prepare_for_shutdown() 973 : : +{ 974 : 360 : + mysql_mutex_lock(&LOCK_active_mi); 975 : 360 : + master_info_index->free_connections(); 976 : 360 : + mysql_mutex_unlock(&LOCK_active_mi); 977 : 360 : +} 978 : : + 979 : : +/* 980 : : + Release slave threads at time of executing shutdown. 981 : : */ 982 : : 983 : 1149 : void end_slave() 995 : : startup parameter to the server was wrong. 996 : : */ 997 : 1149 : mysql_mutex_lock(&LOCK_active_mi); 998 : : + /* 999 : : + master_info_index should not have any threads anymore as they where 1000 : : + killed as part of slave_prepare_for_shutdown() 1001 : : + */ 1002 : 1149 : delete master_info_index; : b 0: 360 :: : b 1: 789 :: 1003 : 1149 : master_info_index= 0; 1004 : 1149 : active_mi= 0; 2659 : : 2660 : 111033 : mysql_mutex_lock(&mi->data_lock); 2661 : 111029 : mysql_mutex_lock(&mi->rli.data_lock); 2662 : : + /* err_lock is to protect mi->last_error() */ 2663 : 111033 : mysql_mutex_lock(&mi->err_lock); 2664 : : + /* err_lock is to protect mi->rli.last_error() */ 2665 : 111033 : mysql_mutex_lock(&mi->rli.err_lock); 2666 : 111033 : protocol->store(mi->host, &my_charset_bin); 2667 : 111026 : protocol->store(mi->user, &my_charset_bin); 4783 : 3145 : if (rli->mi->using_gtid != Master_info::USE_GTID_NO) : b 0: 1938 :: : b 1: 1207 :: 4784 : : { 4785 : : ulong domain_count; 4786 : 1938 : + my_bool save_log_all_errors= thd->log_all_errors; 4787 : : 4788 : : + /* 4789 : : + We don't need to check return value for flush_relay_log_info() 4790 : : + as any errors should be logged to stderr 4791 : : + */ 4792 : 1938 : + thd->log_all_errors= 1; 4793 : 1938 : flush_relay_log_info(rli); 4794 : 1938 : + thd->log_all_errors= save_log_all_errors; 4795 : 1938 : if (mi->using_parallel()) : b 1: 804 :: : b 2: 1134 :: 4796 : : { 4797 : : /* 4873 : 3145 : DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5);); : b 1: 0 :: : b 2: 3145 :: 4874 : 3145 : mysql_mutex_unlock(&rli->run_lock); // tell the world we are done 4875 : : 4876 : 3145 : + rpl_parallel_resize_pool_if_no_slaves(); 4877 : : 4878 : 3145 : mysql_mutex_lock(&LOCK_thread_count); 4879 : 3145 : delete thd; : b 0: 3145 :: : b 1: 0 :: 5983 : : 5984 : 1924 : void end_relay_log_info(Relay_log_info* rli) 5985 : : { 5986 : : + mysql_mutex_t *log_lock; 5987 : 1924 : DBUG_ENTER("end_relay_log_info"); 5988 : : 5989 : 1924 : if (!rli->inited) : b 0: 0 :: : b 1: 1924 :: 6001 : 176 : rli->cur_log_fd = -1; 6002 : : } 6003 : 1924 : rli->inited = 0; 6004 : 1924 : + log_lock= rli->relay_log.get_log_lock(); 6005 : 1924 : + mysql_mutex_lock(log_lock); 6006 : 1924 : rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); 6007 : 1924 : rli->relay_log.harvest_bytes_written(&rli->log_space_total); 6008 : 1924 : + mysql_mutex_unlock(log_lock); 6009 : : /* 6010 : : Delete the slave's temporary tables from memory. 6011 : : In the future there will be other actions than this, to ensure persistance 6721 : : } 6722 : 0 : rli->event_relay_log_pos = BIN_LOG_HEADER_SIZE; 6723 : 0 : strmake_buf(rli->event_relay_log_name,rli->linfo.log_file_name); 6724 : 0 : + if (flush_relay_log_info(rli)) : b 1: 0 :: : b 2: 0 :: 6725 : : + { 6726 : 0 : + errmsg= "error flushing relay log"; 6727 : 0 : + goto err; 6728 : : + } 6729 : : } 6730 : : /* 6731 : : Now we want to open this next log. To know if it's a hot log (the one 6732 : : being written by the I/O thread now) or a cold log, we can use ===== File: sql/sql_class.cc ===== 6516 : : 6517 : : So in this case, do a re-init of the mutex. In release builds, we want to 6518 : : avoid the overhead of a re-init though. 6519 : : + 6520 : : + To ensure that no one is locking the mutex, we take a lock of it first. 6521 : : + For full explanation, see wait_for_commit::~wait_for_commit() 6522 : : */ 6523 : 9527 : + mysql_mutex_lock(&LOCK_wait_commit); 6524 : 9527 : + mysql_mutex_unlock(&LOCK_wait_commit); 6525 : : + 6526 : 9527 : mysql_mutex_destroy(&LOCK_wait_commit); 6527 : 9527 : mysql_mutex_init(key_LOCK_wait_commit, &LOCK_wait_commit, MY_MUTEX_INIT_FAST); 6528 : : #endif ===== File: sql/sql_reload.cc ===== 174 : : slave is not likely to have the same connection names. 175 : : */ 176 : 2271 : tmp_write_to_binlog= 0; 177 : : + 178 : 2271 : + if (!(mi= (get_master_info(&connection_name, : b 1: 206 :: : b 2: 2065 :: 179 : : + Sql_condition::WARN_LEVEL_ERROR)))) 180 : : { 181 : 206 : + result= 1; 182 : : + } 183 : : + else 184 : : + { 185 : 2065 : + mysql_mutex_lock(&mi->data_lock); 186 : 2065 : + if (rotate_relay_log(mi)) : b 1: 0 :: : b 2: 2065 :: 187 : 0 : + *write_to_binlog= -1; 188 : 2065 : + mysql_mutex_unlock(&mi->data_lock); 189 : 2271 : + mi->release(); 190 : : } 191 : : #endif 192 : : } 193 : : #ifdef HAVE_QUERY_CACHE 345 : 2648 : LEX_MASTER_INFO* lex_mi= &thd->lex->mi; 346 : : Master_info *mi; 347 : 2648 : tmp_write_to_binlog= 0; 348 : : + 349 : 2648 : + if (!(mi= get_master_info(&lex_mi->connection_name, : b 1: 445 :: : b 2: 2203 :: 350 : 2648 : + Sql_condition::WARN_LEVEL_ERROR))) 351 : : { 352 : 445 : + result= 1; 353 : : + } 354 : : + else 355 : : + { 356 : : + /* The following will fail if slave is running */ 357 : 2203 : + if (reset_slave(thd, mi)) : b 1: 1074 :: : b 2: 1129 :: 358 : : { 359 : 1074 : + mi->release(); 360 : : /* NOTE: my_error() has been already called by reset_slave(). */ 361 : 1074 : result= 1; 362 : : } 363 : 1129 : else if (mi->connection_name.length && thd->lex->reset_slave_info.all) : b 0: 820 :: : b 1: 309 :: : b 2: 253 :: : b 3: 567 :: 364 : : { 365 : : /* If not default connection and 'all' is used */ 366 : 253 : + mi->release(); 367 : 253 : + mysql_mutex_lock(&LOCK_active_mi); 368 : 253 : + if (master_info_index->remove_master_info(mi)) : b 1: 0 :: : b 2: 253 :: 369 : 0 : + result= 1; 370 : 253 : + mysql_mutex_unlock(&LOCK_active_mi); 371 : : } 372 : : + else 373 : 2648 : + mi->release(); 374 : : } 375 : : } 376 : : #endif 377 : 46437 : if (options & REFRESH_USER_RESOURCES) : b 0: 0 :: : b 1: 46437 :: ===== File: sql/sys_vars.cc ===== 1527 : 27 : Sys_var_gtid_slave_pos::do_check(THD *thd, set_var *var) 1528 : : { 1529 : 27 : String str, *res; 1530 : : 1531 : 27 : DBUG_ASSERT(var->type == OPT_GLOBAL); : b 0: 0 :: : b 1: 27 :: 1532 : : 1537 : 0 : return true; 1538 : : } 1539 : : 1540 : 27 : + if (give_error_if_slave_running(0)) : b 1: 9 :: : b 2: 18 :: 1541 : 9 : return true; 1542 : 18 : if (!(res= var->value->val_str(&str))) : b 1: 0 :: : b 2: 18 :: 1543 : 0 : return true; 1575 : : 1576 : 18 : mysql_mutex_unlock(&LOCK_global_system_variables); 1577 : 18 : mysql_mutex_lock(&LOCK_active_mi); 1578 : 18 : + if (give_error_if_slave_running(1)) : b 1: 0 :: : b 2: 18 :: 1579 : 0 : err= true; 1580 : : else 1581 : : err= rpl_gtid_pos_update(thd, var->save_result.string_value.str, 1761 : : static bool 1762 : 45 : check_slave_parallel_threads(sys_var *self, THD *thd, set_var *var) 1763 : : { 1764 : 45 : + return give_error_if_slave_running(0); 1765 : : } 1766 : : 1767 : : static bool 1770 : : bool err; 1771 : : 1772 : 12 : mysql_mutex_unlock(&LOCK_global_system_variables); 1773 : 12 : + err= give_error_if_slave_running(0); 1774 : 12 : mysql_mutex_lock(&LOCK_global_system_variables); 1775 : : 1776 : 12 : return err; 1793 : : static bool 1794 : 31 : check_slave_domain_parallel_threads(sys_var *self, THD *thd, set_var *var) 1795 : : { 1796 : 31 : + return give_error_if_slave_running(0); 1797 : : } 1798 : : 1799 : : static bool 1802 : : bool running; 1803 : : 1804 : 15 : mysql_mutex_unlock(&LOCK_global_system_variables); 1805 : 15 : + running= give_error_if_slave_running(0); 1806 : 15 : mysql_mutex_lock(&LOCK_global_system_variables); 1807 : : 1808 : 15 : + return running; 1809 : : } 1810 : : 1811 : : 1836 : : static bool 1837 : 0 : check_gtid_ignore_duplicates(sys_var *self, THD *thd, set_var *var) 1838 : : { 1839 : 0 : + return give_error_if_slave_running(0); 1840 : : } 1841 : : 1842 : : static bool 1845 : : bool running; 1846 : : 1847 : 0 : mysql_mutex_unlock(&LOCK_global_system_variables); 1848 : 0 : + running= give_error_if_slave_running(0); 1849 : 0 : mysql_mutex_lock(&LOCK_global_system_variables); 1850 : : 1851 : 0 : + return running; 1852 : : } 1853 : : 1854 : : 2796 : 0 : DBUG_ENTER("Sys_var_replicate_events_marked_for_skip::global_update"); 2797 : : 2798 : 0 : mysql_mutex_unlock(&LOCK_global_system_variables); 2799 : 0 : + if (!give_error_if_slave_running(0)) : b 1: 0 :: : b 2: 0 :: 2800 : 0 : result= Sys_var_enum::global_update(thd, var); 2801 : 0 : mysql_mutex_lock(&LOCK_global_system_variables); 2802 : 0 : DBUG_RETURN(result); 2803 : : } 4069 : : Master_info *mi; 4070 : : 4071 : 0 : mysql_mutex_unlock(&LOCK_global_system_variables); 4072 : : 4073 : 0 : if (!var->base.length) // no base name : b 0: 0 :: : b 1: 0 :: 4074 : : { 4075 : : + mi= get_master_info(&thd->variables.default_master_connection, 4076 : 0 : + Sql_condition::WARN_LEVEL_ERROR); 4077 : : } 4078 : : else // has base name 4079 : : { 4080 : : + mi= get_master_info(&var->base, 4081 : 0 : + Sql_condition::WARN_LEVEL_WARN); 4082 : : } 4083 : : 4084 : 0 : if (mi) : b 0: 0 :: : b 1: 0 :: 4086 : 0 : if (mi->rli.slave_running) : b 0: 0 :: : b 1: 0 :: 4087 : : { 4088 : : my_error(ER_SLAVE_MUST_STOP, MYF(0), 4089 : : + mi->connection_name.length, 4090 : 0 : + mi->connection_name.str); 4091 : 0 : result= true; 4092 : : } 4093 : : else 4094 : : { 4095 : 0 : result= set_filter_value(var->save_result.string_value.str, mi); 4096 : : } 4097 : 0 : + mi->release(); 4098 : : } 4099 : : 4100 : 0 : mysql_mutex_lock(&LOCK_global_system_variables); 4101 : 0 : return result; 4102 : : } 4104 : 0 : bool Sys_var_rpl_filter::set_filter_value(const char *value, Master_info *mi) 4105 : : { 4106 : 0 : bool status= true; 4107 : 0 : + Rpl_filter* rpl_filter= mi->rpl_filter; 4108 : : 4109 : : + /* Proctect against other threads */ 4110 : 0 : + mysql_mutex_lock(&LOCK_active_mi); 4111 : 0 : switch (opt_id) { : b 0: 0 :: : b 1: 0 :: : b 2: 0 :: : b 3: 0 :: : b 4: 0 :: : b 5: 0 :: : b 6: 0 :: 4112 : : case OPT_REPLICATE_DO_DB: 4113 : 0 : status= rpl_filter->set_do_db(value); 4128 : 0 : status= rpl_filter->set_wild_ignore_table(value); 4129 : 0 : break; 4130 : : } 4131 : 0 : + mysql_mutex_unlock(&LOCK_active_mi); 4132 : 0 : return status; 4133 : : } 4134 : : 4141 : : Rpl_filter *rpl_filter; 4142 : : 4143 : 1116 : mysql_mutex_unlock(&LOCK_global_system_variables); 4144 : 1116 : if (!base->length) // no base name : b 0: 1116 :: : b 1: 0 :: 4145 : : { 4146 : : + mi= get_master_info(&thd->variables.default_master_connection, 4147 : 1116 : + Sql_condition::WARN_LEVEL_ERROR); 4148 : : } 4149 : : else // has base name 4150 : 0 : + mi= get_master_info(base, Sql_condition::WARN_LEVEL_WARN); 4151 : : 4152 : 1116 : if (!mi) : b 0: 0 :: : b 1: 1116 :: 4153 : : { 4154 : 0 : + mysql_mutex_lock(&LOCK_global_system_variables); 4155 : 0 : return 0; 4156 : : } 4157 : : + 4158 : 1116 : rpl_filter= mi->rpl_filter; 4159 : 1116 : tmp.length(0); 4160 : : 4161 : 1116 : + mysql_mutex_lock(&LOCK_active_mi); 4162 : 1116 : switch (opt_id) { : b 0: 186 :: : b 1: 186 :: : b 2: 186 :: : b 3: 186 :: : b 4: 186 :: : b 5: 186 :: : b 6: 0 :: 4163 : : case OPT_REPLICATE_DO_DB: 4164 : 186 : rpl_filter->get_do_db(&tmp); 4179 : 186 : rpl_filter->get_wild_ignore_table(&tmp); 4180 : 186 : break; 4181 : : } 4182 : 1116 : + mysql_mutex_unlock(&LOCK_active_mi); 4183 : 1116 : + mysql_mutex_lock(&LOCK_global_system_variables); 4184 : : + 4185 : 1116 : + mi->release(); 4186 : : 4187 : 1116 : ret= (uchar *) thd->strmake(tmp.ptr(), tmp.length()); 4188 : : 4189 : 1116 : return ret; 4190 : : } 4255 : : Master_info *mi; 4256 : 1710 : ulonglong res= 0; // Default value 4257 : 1710 : mysql_mutex_unlock(&LOCK_global_system_variables); 4258 : 1710 : + if ((mi= get_master_info(&thd->variables.default_master_connection, : b 1: 1575 :: : b 2: 135 :: 4259 : 1710 : + Sql_condition::WARN_LEVEL_WARN))) 4260 : : { 4261 : 1575 : res= *((ulonglong*) (((uchar*) mi) + master_info_offset)); 4262 : 1575 : + mi->release(); 4263 : : } 4264 : 1710 : mysql_mutex_lock(&LOCK_global_system_variables); 4265 : 1710 : return res; 4266 : : } 4275 : : 4276 : 0 : if (type == OPT_GLOBAL) : b 0: 0 :: : b 1: 0 :: 4277 : 0 : mysql_mutex_unlock(&LOCK_global_system_variables); 4278 : 0 : + if ((mi= (get_master_info(&thd->variables.default_master_connection, : b 1: 0 :: : b 2: 0 :: 4279 : 0 : + Sql_condition::WARN_LEVEL_ERROR)))) 4280 : : { 4281 : 0 : mysql_mutex_lock(&mi->rli.run_lock); 4282 : 0 : mysql_mutex_lock(&mi->rli.data_lock); 4283 : 0 : result= self->update_variable(thd, mi); 4284 : 0 : mysql_mutex_unlock(&mi->rli.data_lock); 4285 : 0 : mysql_mutex_unlock(&mi->rli.run_lock); 4286 : 0 : + mi->release(); 4287 : : } 4288 : 0 : if (type == OPT_GLOBAL) : b 0: 0 :: : b 1: 0 :: 4289 : 0 : mysql_mutex_lock(&LOCK_global_system_variables); 4290 : 0 : return result; ===== File: storage/connect/ioapi.c ===== 27 : : 28 : : 29 : : #include "ioapi.h" 30 : : +#include "my_attribute.h" 31 : : 32 : 0 : voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) 33 : : { 93 : : static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); 94 : : static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); 95 : : 96 : 0 : +static voidpf ZCALLBACK fopen_file_func (voidpf opaque __attribute__((unused)), const char* filename, int mode) 97 : : { 98 : 0 : FILE* file = NULL; 99 : 0 : const char* mode_fopen = NULL; 111 : 0 : return file; 112 : : } 113 : : 114 : 0 : +static voidpf ZCALLBACK fopen64_file_func (voidpf opaque __attribute__((unused)), const void* filename, int mode) 115 : : { 116 : 0 : FILE* file = NULL; 117 : 0 : const char* mode_fopen = NULL; 130 : : } 131 : : 132 : : 133 : 0 : +static uLong ZCALLBACK fread_file_func (voidpf opaque __attribute__((unused)), voidpf stream, void* buf, uLong size) 134 : : { 135 : : uLong ret; 136 : 0 : ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); 137 : 0 : return ret; 138 : : } 139 : : 140 : 0 : +static uLong ZCALLBACK fwrite_file_func (voidpf opaque __attribute__((unused)), voidpf stream, const void* buf, uLong size) 141 : : { 142 : : uLong ret; 143 : 0 : ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); 144 : 0 : return ret; 145 : : } 146 : : 147 : 0 : +static long ZCALLBACK ftell_file_func (voidpf opaque __attribute__((unused)), voidpf stream) 148 : : { 149 : : long ret; 150 : 0 : ret = ftell((FILE *)stream); 152 : : } 153 : : 154 : : 155 : 0 : +static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque __attribute__((unused)), voidpf stream) 156 : : { 157 : : ZPOS64_T ret; 158 : 0 : ret = FTELLO_FUNC((FILE *)stream); 159 : 0 : return ret; 160 : : } 161 : : 162 : 0 : +static long ZCALLBACK fseek_file_func (voidpf opaque __attribute__((unused)), voidpf stream, uLong offset, int origin) 163 : : { 164 : 0 : int fseek_origin=0; 165 : : long ret; 182 : 0 : return ret; 183 : : } 184 : : 185 : 0 : +static long ZCALLBACK fseek64_file_func (voidpf opaque __attribute__((unused)), voidpf stream, ZPOS64_T offset, int origin) 186 : : { 187 : 0 : int fseek_origin=0; 188 : : long ret; 208 : : } 209 : : 210 : : 211 : 0 : +static int ZCALLBACK fclose_file_func (voidpf opaque __attribute__((unused)), voidpf stream) 212 : : { 213 : : int ret; 214 : 0 : ret = fclose((FILE *)stream); 215 : 0 : return ret; 216 : : } 217 : : 218 : 0 : +static int ZCALLBACK ferror_file_func (voidpf opaque __attribute__((unused)), voidpf stream) 219 : : { 220 : : int ret; 221 : 0 : ret = ferror((FILE *)stream); ===== File: storage/oqgraph/mysql-test/oqgraph/regression_mdev6282.result ===== 33 : : WHERE `latch` = 'breadth_first' AND `origid` = '1' ORDER BY `weight` DESC LIMIT 1; 34 : : version nodeID 35 : : 0.0.3 3 36 : : DROP TABLE version_history; 37 : : +DROP TABLE db_history; ===== File: storage/oqgraph/mysql-test/oqgraph/regression_mdev6345.result ===== 8 : : breadth_first 1 6 NULL 0 1 9 : : breadth_first 1 6 1 1 2 10 : : breadth_first 1 6 1 2 6 11 : : DROP TABLE IF EXISTS oq_graph; 12 : : +DROP TABLE IF EXISTS oq_backing; ===== File: storage/xtradb/row/row0ftsort.cc ===== 623 : 0 : mem_heap_t* blob_heap = NULL; 624 : : fts_doc_t doc; 625 : 0 : dict_table_t* table = psort_info->psort_common->new_table; 626 : : + dict_field_t* idx_field __attribute__((unused)); 627 : : fts_tokenize_ctx_t t_ctx; 628 : 0 : ulint retried = 0; 629 : 0 : dberr_t error = DB_SUCCESS;