use of io.seata.core.rpc.RpcContext in project seata by seata.
the class ChannelManager method getChannel.
/**
* Gets get channel.
*
* @param resourceId Resource ID
* @param clientId Client ID - ApplicationId:IP:Port
* @return Corresponding channel, NULL if not found.
*/
public static Channel getChannel(String resourceId, String clientId) {
Channel resultChannel = null;
String[] clientIdInfo = readClientId(clientId);
if (clientIdInfo == null || clientIdInfo.length != 3) {
throw new FrameworkException("Invalid Client ID: " + clientId);
}
String targetApplicationId = clientIdInfo[0];
String targetIP = clientIdInfo[1];
int targetPort = Integer.parseInt(clientIdInfo[2]);
ConcurrentMap<String, ConcurrentMap<String, ConcurrentMap<Integer, RpcContext>>> applicationIdMap = RM_CHANNELS.get(resourceId);
if (targetApplicationId == null || applicationIdMap == null || applicationIdMap.isEmpty()) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("No channel is available for resource[{}]", resourceId);
}
return null;
}
ConcurrentMap<String, ConcurrentMap<Integer, RpcContext>> ipMap = applicationIdMap.get(targetApplicationId);
if (ipMap != null && !ipMap.isEmpty()) {
// Firstly, try to find the original channel through which the branch was registered.
ConcurrentMap<Integer, RpcContext> portMapOnTargetIP = ipMap.get(targetIP);
if (portMapOnTargetIP != null && !portMapOnTargetIP.isEmpty()) {
RpcContext exactRpcContext = portMapOnTargetIP.get(targetPort);
if (exactRpcContext != null) {
Channel channel = exactRpcContext.getChannel();
if (channel.isActive()) {
resultChannel = channel;
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Just got exactly the one {} for {}", channel, clientId);
}
} else {
if (portMapOnTargetIP.remove(targetPort, exactRpcContext)) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Removed inactive {}", channel);
}
}
}
}
// The original channel was broken, try another one.
if (resultChannel == null) {
for (ConcurrentMap.Entry<Integer, RpcContext> portMapOnTargetIPEntry : portMapOnTargetIP.entrySet()) {
Channel channel = portMapOnTargetIPEntry.getValue().getChannel();
if (channel.isActive()) {
resultChannel = channel;
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Choose {} on the same IP[{}] as alternative of {}", channel, targetIP, clientId);
}
break;
} else {
if (portMapOnTargetIP.remove(portMapOnTargetIPEntry.getKey(), portMapOnTargetIPEntry.getValue())) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Removed inactive {}", channel);
}
}
}
}
}
}
// No channel on the this app node, try another one.
if (resultChannel == null) {
for (ConcurrentMap.Entry<String, ConcurrentMap<Integer, RpcContext>> ipMapEntry : ipMap.entrySet()) {
if (ipMapEntry.getKey().equals(targetIP)) {
continue;
}
ConcurrentMap<Integer, RpcContext> portMapOnOtherIP = ipMapEntry.getValue();
if (portMapOnOtherIP == null || portMapOnOtherIP.isEmpty()) {
continue;
}
for (ConcurrentMap.Entry<Integer, RpcContext> portMapOnOtherIPEntry : portMapOnOtherIP.entrySet()) {
Channel channel = portMapOnOtherIPEntry.getValue().getChannel();
if (channel.isActive()) {
resultChannel = channel;
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Choose {} on the same application[{}] as alternative of {}", channel, targetApplicationId, clientId);
}
break;
} else {
if (portMapOnOtherIP.remove(portMapOnOtherIPEntry.getKey(), portMapOnOtherIPEntry.getValue())) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Removed inactive {}", channel);
}
}
}
}
if (resultChannel != null) {
break;
}
}
}
}
if (resultChannel == null) {
resultChannel = tryOtherApp(applicationIdMap, targetApplicationId);
if (resultChannel == null) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("No channel is available for resource[{}] as alternative of {}", resourceId, clientId);
}
} else {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Choose {} on the same resource[{}] as alternative of {}", resultChannel, resourceId, clientId);
}
}
}
return resultChannel;
}
use of io.seata.core.rpc.RpcContext in project seata by seata.
the class ChannelManager method getChannelFromSameClientMap.
private static Channel getChannelFromSameClientMap(Map<Integer, RpcContext> clientChannelMap, int exclusivePort) {
if (clientChannelMap != null && !clientChannelMap.isEmpty()) {
for (ConcurrentMap.Entry<Integer, RpcContext> entry : clientChannelMap.entrySet()) {
if (entry.getKey() == exclusivePort) {
clientChannelMap.remove(entry.getKey());
continue;
}
Channel channel = entry.getValue().getChannel();
if (channel.isActive()) {
return channel;
}
clientChannelMap.remove(entry.getKey());
}
}
return null;
}
use of io.seata.core.rpc.RpcContext in project seata by seata.
the class DefaultCoordinatorMetricsTest method test.
@Test
public void test() throws IOException, TransactionException, InterruptedException {
SessionHolder.init(null);
DefaultCoordinator coordinator = new DefaultCoordinator(new MockServerMessageSender());
coordinator.init();
try {
MetricsManager.get().init();
// start a transaction
GlobalBeginRequest request = new GlobalBeginRequest();
request.setTransactionName("test_transaction");
GlobalBeginResponse response = new GlobalBeginResponse();
coordinator.doGlobalBegin(request, response, new RpcContext());
Map<String, Measurement> measurements = new HashMap<>();
MetricsManager.get().getRegistry().measure().forEach(measurement -> measurements.put(measurement.getId().toString(), measurement));
Assertions.assertEquals(1, measurements.size());
Assertions.assertEquals(1, measurements.get("seata.transaction(applicationId=null,group=null,meter=counter,role=tc,status=active)").getValue(), 0);
// commit this transaction
GlobalCommitRequest commitRequest = new GlobalCommitRequest();
commitRequest.setXid(response.getXid());
coordinator.doGlobalCommit(commitRequest, new GlobalCommitResponse(), new RpcContext());
// we need sleep for a short while because default canBeCommittedAsync() is true
Thread.sleep(200);
measurements.clear();
MetricsManager.get().getRegistry().measure().forEach(measurement -> measurements.put(measurement.getId().toString(), measurement));
Assertions.assertEquals(9, measurements.size());
Assertions.assertEquals(0, measurements.get("seata.transaction(applicationId=null,group=null,meter=counter,role=tc,status=active)").getValue(), 0);
Assertions.assertEquals(1, measurements.get("seata.transaction(applicationId=null,group=null,meter=counter,role=tc,status=committed)").getValue(), 0);
Assertions.assertEquals(1, measurements.get("seata.transaction(applicationId=null,group=null,meter=summary,role=tc,statistic=count,status=committed)").getValue(), 0);
Assertions.assertEquals(1, measurements.get("seata.transaction(applicationId=null,group=null,meter=summary,role=tc,statistic=total,status=committed)").getValue(), 0);
Assertions.assertEquals(1, measurements.get("seata.transaction(applicationId=null,group=null,meter=timer,role=tc,statistic=count,status=committed)").getValue(), 0);
// start another new transaction
request = new GlobalBeginRequest();
request.setTransactionName("test_transaction_2");
response = new GlobalBeginResponse();
coordinator.doGlobalBegin(request, response, new RpcContext());
// rollback this transaction
GlobalRollbackRequest rollbackRequest = new GlobalRollbackRequest();
rollbackRequest.setXid(response.getXid());
coordinator.doGlobalRollback(rollbackRequest, new GlobalRollbackResponse(), new RpcContext());
Thread.sleep(200);
measurements.clear();
MetricsManager.get().getRegistry().measure().forEach(measurement -> measurements.put(measurement.getId().toString(), measurement));
Assertions.assertEquals(17, measurements.size());
Assertions.assertEquals(0, measurements.get("seata.transaction(applicationId=null,group=null,meter=counter,role=tc,status=active)").getValue(), 0);
Assertions.assertEquals(1, measurements.get("seata.transaction(applicationId=null,group=null,meter=counter,role=tc,status=committed)").getValue(), 0);
Assertions.assertEquals(0, measurements.get("seata.transaction(applicationId=null,group=null,meter=summary,role=tc,statistic=count,status=committed)").getValue(), 0);
Assertions.assertEquals(0, measurements.get("seata.transaction(applicationId=null,group=null,meter=summary,role=tc,statistic=total,status=committed)").getValue(), 0);
Assertions.assertEquals(0, measurements.get("seata.transaction(applicationId=null,group=null,meter=timer,role=tc,statistic=count,status=committed)").getValue(), 0);
Assertions.assertEquals(1, measurements.get("seata.transaction(applicationId=null,group=null,meter=counter,role=tc,status=rollbacked)").getValue(), 0);
Assertions.assertEquals(1, measurements.get("seata.transaction(applicationId=null,group=null,meter=summary,role=tc,statistic=count,status=rollbacked)").getValue(), 0);
Assertions.assertEquals(1, measurements.get("seata.transaction(applicationId=null,group=null,meter=summary,role=tc,statistic=total,status=rollbacked)").getValue(), 0);
Assertions.assertEquals(1, measurements.get("seata.transaction(applicationId=null,group=null,meter=timer,role=tc,statistic=count,status=rollbacked)").getValue(), 0);
} finally {
coordinator.destroy();
SessionHolder.destroy();
}
}
use of io.seata.core.rpc.RpcContext in project seata by seata.
the class ChannelManager method registerRMChannel.
/**
* Register rm channel.
*
* @param resourceManagerRequest the resource manager request
* @param channel the channel
* @throws IncompatibleVersionException the incompatible version exception
*/
public static void registerRMChannel(RegisterRMRequest resourceManagerRequest, Channel channel) throws IncompatibleVersionException {
Version.checkVersion(resourceManagerRequest.getVersion());
Set<String> dbkeySet = dbKeytoSet(resourceManagerRequest.getResourceIds());
RpcContext rpcContext;
if (!IDENTIFIED_CHANNELS.containsKey(channel)) {
rpcContext = buildChannelHolder(NettyPoolKey.TransactionRole.RMROLE, resourceManagerRequest.getVersion(), resourceManagerRequest.getApplicationId(), resourceManagerRequest.getTransactionServiceGroup(), resourceManagerRequest.getResourceIds(), channel);
rpcContext.holdInIdentifiedChannels(IDENTIFIED_CHANNELS);
} else {
rpcContext = IDENTIFIED_CHANNELS.get(channel);
rpcContext.addResources(dbkeySet);
}
if (dbkeySet == null || dbkeySet.isEmpty()) {
return;
}
for (String resourceId : dbkeySet) {
String clientIp;
ConcurrentMap<Integer, RpcContext> portMap = CollectionUtils.computeIfAbsent(RM_CHANNELS, resourceId, key -> new ConcurrentHashMap<>()).computeIfAbsent(resourceManagerRequest.getApplicationId(), key -> new ConcurrentHashMap<>()).computeIfAbsent(clientIp = ChannelUtil.getClientIpFromChannel(channel), key -> new ConcurrentHashMap<>());
rpcContext.holdInResourceManagerChannels(resourceId, portMap);
updateChannelsResource(resourceId, clientIp, resourceManagerRequest.getApplicationId());
}
}
use of io.seata.core.rpc.RpcContext in project seata by seata.
the class ChannelManager method registerTMChannel.
/**
* Register tm channel.
*
* @param request the request
* @param channel the channel
* @throws IncompatibleVersionException the incompatible version exception
*/
public static void registerTMChannel(RegisterTMRequest request, Channel channel) throws IncompatibleVersionException {
Version.checkVersion(request.getVersion());
RpcContext rpcContext = buildChannelHolder(NettyPoolKey.TransactionRole.TMROLE, request.getVersion(), request.getApplicationId(), request.getTransactionServiceGroup(), null, channel);
rpcContext.holdInIdentifiedChannels(IDENTIFIED_CHANNELS);
String clientIdentified = rpcContext.getApplicationId() + Constants.CLIENT_ID_SPLIT_CHAR + ChannelUtil.getClientIpFromChannel(channel);
ConcurrentMap<Integer, RpcContext> clientIdentifiedMap = CollectionUtils.computeIfAbsent(TM_CHANNELS, clientIdentified, key -> new ConcurrentHashMap<>());
rpcContext.holdInClientChannels(clientIdentifiedMap);
}
Aggregations