/* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "rpl_msr.h" #include "rpl_rli.h" // Relay_log_info const char* Multisource_info::default_channel= ""; const char* Multisource_info::group_replication_channel_names[] = { "group_replication_applier", "group_replication_recovery" }; bool Multisource_info::add_mi(const char* channel_name, Master_info* mi) { DBUG_ENTER("Multisource_info::add_mi"); m_channel_map_lock->assert_some_wrlock(); mi_map::const_iterator it; std::pair ret; bool res= false; /* The check of mi exceeding MAX_CHANNELS shall be done in the caller */ DBUG_ASSERT(current_mi_count < MAX_CHANNELS); replication_channel_map::iterator map_it; enum_channel_type type= is_group_replication_channel_name(channel_name) ? GROUP_REPLICATION_CHANNEL: SLAVE_REPLICATION_CHANNEL; map_it= rep_channel_map.find(type); if (map_it == rep_channel_map.end()) { std::pair map_ret = rep_channel_map.insert(replication_channel_map::value_type(type, mi_map())); if (!map_ret.second) DBUG_RETURN(true); map_it = rep_channel_map.find(type); } ret = map_it->second.insert(mi_map::value_type(channel_name, mi)); /* If a map insert fails, ret.second is false */ if(!ret.second) DBUG_RETURN(true); /* Save the pointer for the default_channel to avoid searching it */ if (!strcmp(channel_name, get_default_channel())) default_channel_mi= mi; #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE res= add_mi_to_rpl_pfs_mi(mi); #endif current_mi_count++; DBUG_RETURN(res); } Master_info* Multisource_info::get_mi(const char* channel_name) { DBUG_ENTER("Multisource_info::get_mi"); m_channel_map_lock->assert_some_lock(); DBUG_ASSERT(channel_name != 0); mi_map::iterator it; replication_channel_map::iterator map_it; map_it= rep_channel_map.find(SLAVE_REPLICATION_CHANNEL); if (map_it != rep_channel_map.end()) { it= map_it->second.find(channel_name); } if (map_it == rep_channel_map.end() || //If not a slave channel, maybe a group one it == map_it->second.end()) { map_it= rep_channel_map.find(GROUP_REPLICATION_CHANNEL); if (map_it == rep_channel_map.end()) { DBUG_RETURN(0); } it= map_it->second.find(channel_name); if (it == map_it->second.end()) { DBUG_RETURN(0); } } DBUG_RETURN(it->second); } void Multisource_info::delete_mi(const char* channel_name) { DBUG_ENTER("Multisource_info::delete_mi"); m_channel_map_lock->assert_some_wrlock(); Master_info *mi= 0; mi_map::iterator it; DBUG_ASSERT(channel_name != 0); replication_channel_map::iterator map_it; map_it= rep_channel_map.find(SLAVE_REPLICATION_CHANNEL); if (map_it != rep_channel_map.end()) { it= map_it->second.find(channel_name); } if (map_it == rep_channel_map.end() || //If not a slave channel, maybe a group one it == map_it->second.end()) { map_it= rep_channel_map.find(GROUP_REPLICATION_CHANNEL); DBUG_ASSERT(map_it != rep_channel_map.end()); it= map_it->second.find(channel_name); DBUG_ASSERT(it != map_it->second.end()); } #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE int index= -1; /* get the index of mi from rpl_pfs_mi */ index= get_index_from_rpl_pfs_mi(channel_name); DBUG_ASSERT(index != -1); /* set the current index to 0 and decrease current_mi_count */ rpl_pfs_mi[index] = 0; #endif current_mi_count--; mi= it->second; it->second= 0; /* erase from the map */ map_it->second.erase(it); if (default_channel_mi == mi) default_channel_mi= NULL; /* delete the master info */ if (mi) { mi->channel_assert_some_wrlock(); mi->wait_until_no_reference(current_thd); if(mi->rli) { delete mi->rli; } delete mi; } DBUG_VOID_RETURN; } bool Multisource_info::is_group_replication_channel_name(const char* channel, bool is_applier) { if (is_applier) return !strcmp(channel, group_replication_channel_names[0]); else return !strcmp(channel, group_replication_channel_names[0]) || !strcmp(channel, group_replication_channel_names[1]); } #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE bool Multisource_info::add_mi_to_rpl_pfs_mi(Master_info *mi) { DBUG_ENTER("Multisource_info::add_mi_to_rpl_pfs_mi"); m_channel_map_lock->assert_some_wrlock(); bool res=true; // not added /* Point to this added mi in the rpl_pfs_mi*/ for (uint i = 0; i < MAX_CHANNELS; i++) { if (rpl_pfs_mi[i] == 0) { rpl_pfs_mi[i] = mi; res= false; // success break; } } DBUG_RETURN(res); } int Multisource_info::get_index_from_rpl_pfs_mi(const char * channel_name) { m_channel_map_lock->assert_some_lock(); Master_info* mi= 0; for (uint i= 0; i < MAX_CHANNELS; i++) { mi= rpl_pfs_mi[i]; if (mi) { if ( !strcmp(mi->get_channel(), channel_name)) return i; } } return -1; } Master_info* Multisource_info::get_mi_at_pos(uint pos) { DBUG_ENTER("Multisource_info::get_mi_at_pos"); m_channel_map_lock->assert_some_lock(); if ( pos < MAX_CHANNELS) DBUG_RETURN(rpl_pfs_mi[pos]); DBUG_RETURN(0); } #endif /*WITH_PERFSCHEMA_STORAGE_ENGINE */ /* There is only one channel_map for the whole server */ Multisource_info channel_map;