void KaaChannelManager::clearChannelList() { KAA_MUTEX_LOCKING("channelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(channelLock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); KAA_MUTEX_LOCKING("mappedChannelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(mappedChannelLock, mappedChannelGuard_); KAA_MUTEX_LOCKED("mappedChannelGuard_"); channels_.clear(); mappedChannels_.clear(); }
void KaaChannelManager::onTransportConnectionInfoUpdated(ITransportConnectionInfoPtr connectionInfo) { if (isShutdown_) { KAA_LOG_WARN("Can't update server. Channel manager is down"); return; } if (!connectionInfo) { KAA_LOG_WARN("Failed to update connection info: bad input data") throw KaaException("empty connection info pointer"); } connectionInfo->resetFailedState(); TransportProtocolId protocolId = connectionInfo->getTransportId(); if (connectionInfo->getServerType() == ServerType::OPERATIONS) { KAA_MUTEX_LOCKING("lastOpsServersGuard_"); KAA_MUTEX_UNIQUE_DECLARE(lastOpsServers_Lock, lastOpsServersGuard_); KAA_MUTEX_LOCKED("lastOpsServersGuard_"); lastOpsServers_[protocolId] = connectionInfo; } KAA_MUTEX_LOCKING("channelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(channelLock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); for (auto& channel : channels_) { if (channel->getServerType() == connectionInfo->getServerType() && channel->getTransportProtocolId() == protocolId) { KAA_LOG_DEBUG(boost::format("Setting a new connection data for channel \"%1%\" %2%") % channel->getId() % LoggingUtils::TransportProtocolIdToString(protocolId)); channel->setServer(connectionInfo); } } }
std::list<IDataChannelPtr> KaaChannelManager::getChannels() { KAA_MUTEX_LOCKING("channelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(channelLock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); std::list<IDataChannelPtr> channels(channels_.begin(), channels_.end()); return channels; }
void BootstrapManager::setTransport(IBootstrapTransport* transport) { KAA_R_MUTEX_UNIQUE_DECLARE(lock, guard_); bootstrapTransport_ = dynamic_cast<BootstrapTransport*>(transport); if (bootstrapTransport_ != nullptr) { return; } throw KaaException("Bad bootstrap transport"); }
void BootstrapManager::useNextOperationsServerByAccessPointId(std::int32_t id) { KAA_R_MUTEX_UNIQUE_DECLARE(lock, guard_); KAA_LOG_DEBUG(boost::format("Going to use new operations server: access_point=0x%X") % id); auto servers = getOPSByAccessPointId(id); if (servers.size() > 0) { notifyChannelManangerAboutServer(servers); } else { serverToApply.reset(new std::int32_t(id)); bootstrapTransport_->sync(); } }
void KaaChannelManager::doShutdown() { if (!isShutdown_) { isShutdown_ = true; KAA_MUTEX_LOCKING("mappedChannelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(mappedChannelLock, mappedChannelGuard_); KAA_MUTEX_LOCKED("mappedChannelGuard_"); for (auto& channel : mappedChannels_) { channel.second->shutdown(); } } }
void BootstrapManager::useNextOperationsServer(const TransportProtocolId& protocolId) { KAA_R_MUTEX_UNIQUE_DECLARE(lock, guard_); auto lastServerIt = lastOperationsServers_.find(protocolId); auto serverIt = operationServers_.find(protocolId); if (lastServerIt != lastOperationsServers_.end() && serverIt != operationServers_.end()) { OperationsServers::iterator nextOperationIterator = (lastServerIt->second)+1; if (nextOperationIterator != serverIt->second.end()) { KAA_LOG_INFO(boost::format("New server [%1%] will be user for %2%") % (*nextOperationIterator)->getAccessPointId() % LoggingUtils::TransportProtocolIdToString(protocolId)); lastOperationsServers_[protocolId] = nextOperationIterator; if (channelManager_ != nullptr) { channelManager_->onTransportConnectionInfoUpdated(*(nextOperationIterator)); } else { KAA_LOG_ERROR("Can not process server change. Channel manager was not specified"); } } else { KAA_LOG_WARN(boost::format("Failed to find server for channel %1%.") % LoggingUtils::TransportProtocolIdToString(protocolId)); FailoverStrategyDecision decision = failoverStrategy_->onFailover(Failover::OPERATION_SERVERS_NA); switch (decision.getAction()) { case FailoverStrategyAction::NOOP: KAA_LOG_WARN("No operation is performed according to failover strategy decision."); break; case FailoverStrategyAction::RETRY: { std::size_t period = decision.getRetryPeriod(); KAA_LOG_WARN(boost::format("Attempt to receive operations server list will be made in %1% secs " "according to failover strategy decision.") % period); retryTimer_.stop(); retryTimer_.start(period, [&] { receiveOperationsServerList(); }); break; } case FailoverStrategyAction::STOP_APP: KAA_LOG_WARN("Stopping application according to failover strategy decision!"); exit(EXIT_FAILURE); break; default: break; } } } else { throw KaaException("There are no available servers at the time"); } }
IDataChannelPtr KaaChannelManager::getChannelByTransportType(TransportType type) { KAA_MUTEX_LOCKING("mappedChannelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(mappedChannelLock, mappedChannelGuard_); KAA_MUTEX_LOCKED("mappedChannelGuard_"); IDataChannelPtr channel = nullptr; auto it = mappedChannels_.find(type); if (it != mappedChannels_.end()) { channel = it->second; } return channel; }
void KaaChannelManager::removeChannel(const std::string& id) { KAA_MUTEX_LOCKING("channelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(channelLock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); for (auto it = channels_.begin(); it != channels_.end(); ++it) { if ((*it)->getId() == id) { IDataChannelPtr channel = *it; channels_.erase(it); replaceChannel(channel); return; } } }
bool KaaChannelManager::useChannelForType(const std::pair<TransportType, ChannelDirection>& type, IDataChannelPtr channel) { if (type.second == ChannelDirection::UP || type.second == ChannelDirection::BIDIRECTIONAL) { KAA_LOG_INFO(boost::format("Channel (id='%1%') will be used for %2% transport type") % channel->getId() % LoggingUtils::TransportTypeToString(type.first)); KAA_MUTEX_LOCKING("mappedChannelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(mappedChannelLock, mappedChannelGuard_); KAA_MUTEX_LOCKED("mappedChannelGuard_"); mappedChannels_[type.first] = channel; return true; } return false; }
void KaaChannelManager::replaceChannel(IDataChannelPtr channel) { KAA_MUTEX_LOCKING("mappedChannelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(mappedChannelLock, mappedChannelGuard_); KAA_MUTEX_LOCKED("mappedChannelGuard_"); for (const auto& channelInfo : mappedChannels_) { if (channelInfo.second == channel) { useNewChannelForType(channelInfo.first); } } KAA_UNLOCK(mappedChannelLock); channel->shutdown(); }
IDataChannelPtr KaaChannelManager::getChannel(const std::string& channelId) { KAA_MUTEX_LOCKING("channelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(channelLock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); IDataChannelPtr channel = nullptr; for (const auto& c : channels_) { if (c->getId() == channelId) { channel = c; } } return channel; }
void KaaChannelManager::removeChannel(IDataChannelPtr channel) { if (!channel) { KAA_LOG_WARN("Failed to remove channel: bad input data") throw KaaException("empty channel pointer"); } KAA_MUTEX_LOCKING("channelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(channelLock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); if (channels_.erase(channel)) { replaceChannel(channel); } }
bool KaaChannelManager::addChannelToList(IDataChannelPtr channel) { KAA_MUTEX_LOCKING("channelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(channelLock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); auto res = channels_.insert(channel); if (res.second) { channel->setFailoverStrategy(failoverStrategy_); channel->setConnectivityChecker(connectivityChecker_); ITransportConnectionInfoPtr connectionInfo; TransportProtocolId protocolId = channel->getTransportProtocolId(); if (channel->getServerType() == ServerType::BOOTSTRAP) { connectionInfo = getCurrentBootstrapServer(protocolId); } else { KAA_MUTEX_LOCKING("lastOpsServersGuard_"); KAA_MUTEX_UNIQUE_DECLARE(lastOpsServers_Lock, lastOpsServersGuard_); KAA_MUTEX_LOCKED("lastOpsServersGuard_"); auto it = lastOpsServers_.find(channel->getTransportProtocolId()); if (it != lastOpsServers_.end()) { connectionInfo = it->second; } } if (connectionInfo) { KAA_LOG_DEBUG(boost::format("Setting a new server for channel \"%1%\" %2%") % channel->getId() % LoggingUtils::TransportProtocolIdToString(protocolId)); channel->setServer(connectionInfo); } else { if (channel->getServerType() == ServerType::BOOTSTRAP) { KAA_LOG_WARN(boost::format("Failed to find bootstrap server for channel \"%1%\" %2%") % channel->getId() % LoggingUtils::TransportProtocolIdToString(protocolId)); } else { KAA_LOG_INFO(boost::format("Failed to find operations server for channel \"%1%\" %2%") % channel->getId() % LoggingUtils::TransportProtocolIdToString(protocolId)); } } } return res.second; }
void KaaChannelManager::resume() { if (isShutdown_) { KAA_LOG_WARN("Can't resume. Channel manager is down"); return; } if (isPaused_) { isPaused_ = false; KAA_MUTEX_LOCKING("mappedChannelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(mappedChannelLock, mappedChannelGuard_); KAA_MUTEX_LOCKED("mappedChannelGuard_"); for (auto& channel : mappedChannels_) { channel.second->resume(); } } }
void KaaChannelManager::setConnectivityChecker(ConnectivityCheckerPtr checker) { if (isShutdown_) { KAA_LOG_WARN("Can't set connectivity checker. Channel manager is down"); return; } if (!checker) { KAA_LOG_WARN("Connectivity checker is null"); return; } connectivityChecker_ = checker; KAA_MUTEX_LOCKING("channelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(channelLock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); for (auto& channel : channels_) { channel->setConnectivityChecker(connectivityChecker_); } }
void KaaChannelManager::setFailoverStrategy(IFailoverStrategyPtr strategy) { if (isShutdown_) { KAA_LOG_WARN("Can't set failover strategy. Channel manager is down"); return; } if (!strategy) { KAA_LOG_WARN("Failover strategy is null"); return; } failoverStrategy_ = strategy; KAA_MUTEX_LOCKING("channelGuard_"); KAA_R_MUTEX_UNIQUE_DECLARE(channelLock, channelGuard_); KAA_MUTEX_LOCKED("channelGuard_"); bootstrapManager_.setFailoverStrategy(failoverStrategy_); for (auto& channel : channels_) { channel->setFailoverStrategy(failoverStrategy_); } }
void BootstrapManager::onServerListUpdated(const std::vector<ProtocolMetaData>& operationsServers) { if (operationsServers.empty()) { KAA_LOG_WARN("Received empty operations server list"); FailoverStrategyDecision decision = failoverStrategy_->onFailover(Failover::NO_OPERATION_SERVERS); switch (decision.getAction()) { case FailoverStrategyAction::NOOP: KAA_LOG_WARN("No operation is performed according to failover strategy decision."); break; case FailoverStrategyAction::RETRY: { std::size_t period = decision.getRetryPeriod(); KAA_LOG_WARN(boost::format("Attempt to receive operations server list will be made in %1% secs " "according to failover strategy decision.") % period); retryTimer_.stop(); retryTimer_.start(period, [&] { receiveOperationsServerList(); }); break; } case FailoverStrategyAction::STOP_APP: KAA_LOG_WARN("Stopping application according to failover strategy decision!"); exit(EXIT_FAILURE); break; } return; } KAA_R_MUTEX_UNIQUE_DECLARE(lock, guard_); KAA_LOG_INFO(boost::format("Received %1% new operations servers") % operationsServers.size()); lastOperationsServers_.clear(); operationServers_.clear(); for (const auto& serverMetaData : operationsServers) { ITransportConnectionInfoPtr connectionInfo( new GenericTransportInfo(ServerType::OPERATIONS, serverMetaData)); auto& servers = operationServers_[serverMetaData.protocolVersionInfo]; servers.push_back(connectionInfo); } for (auto& transportSpecificServers : operationServers_) { std::shuffle (transportSpecificServers.second.begin() , transportSpecificServers.second.end() , std::default_random_engine(std::chrono::high_resolution_clock::now().time_since_epoch().count())); lastOperationsServers_[transportSpecificServers.first] = transportSpecificServers.second.begin(); } if (serverToApply) { auto servers = getOPSByAccessPointId(*serverToApply); if (!servers.empty()) { KAA_LOG_DEBUG(boost::format("Found %1% servers by access point id %2%") % servers.size() % *serverToApply); serverToApply.reset(); notifyChannelManangerAboutServer(servers); } } else { for (const auto& transportSpecificServers : operationServers_) { channelManager_->onTransportConnectionInfoUpdated(transportSpecificServers.second.front()); } } }
void BootstrapManager::setChannelManager(IKaaChannelManager* manager) { KAA_R_MUTEX_UNIQUE_DECLARE(lock, guard_); channelManager_ = manager; }