Skip to content
Snippets Groups Projects
Unverified Commit da31cf1e authored by spilledyear's avatar spilledyear Committed by GitHub
Browse files

bugfix: DataSourceProxyHolder#putDataSource deadlock (#3568)

parent efefd177
No related branches found
No related tags found
No related merge requests found
...@@ -16,9 +16,9 @@ ...@@ -16,9 +16,9 @@
package io.seata.spring.annotation.datasource; package io.seata.spring.annotation.datasource;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.util.concurrent.ConcurrentHashMap; import java.util.HashMap;
import java.util.Map;
import io.seata.common.util.CollectionUtils;
import io.seata.core.model.BranchType; import io.seata.core.model.BranchType;
import io.seata.rm.datasource.DataSourceProxy; import io.seata.rm.datasource.DataSourceProxy;
import io.seata.rm.datasource.SeataDataSourceProxy; import io.seata.rm.datasource.SeataDataSourceProxy;
...@@ -31,10 +31,10 @@ import io.seata.rm.datasource.xa.DataSourceProxyXA; ...@@ -31,10 +31,10 @@ import io.seata.rm.datasource.xa.DataSourceProxyXA;
*/ */
public class DataSourceProxyHolder { public class DataSourceProxyHolder {
private static final int MAP_INITIAL_CAPACITY = 8; private static final int MAP_INITIAL_CAPACITY = 8;
private ConcurrentHashMap<DataSource, SeataDataSourceProxy> dataSourceProxyMap; private Map<DataSource, SeataDataSourceProxy> dataSourceProxyMap;
private DataSourceProxyHolder() { private DataSourceProxyHolder() {
dataSourceProxyMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY); dataSourceProxyMap = new HashMap<>(MAP_INITIAL_CAPACITY);
} }
/** /**
...@@ -71,7 +71,7 @@ public class DataSourceProxyHolder { ...@@ -71,7 +71,7 @@ public class DataSourceProxyHolder {
//If it's an right proxy, return it directly. //If it's an right proxy, return it directly.
if (dataSourceProxyMode == dataSourceProxy.getBranchType()) { if (dataSourceProxyMode == dataSourceProxy.getBranchType()) {
return (SeataDataSourceProxy)dataSource; return (SeataDataSourceProxy) dataSource;
} }
//Get the original data source. //Get the original data source.
...@@ -79,7 +79,21 @@ public class DataSourceProxyHolder { ...@@ -79,7 +79,21 @@ public class DataSourceProxyHolder {
} else { } else {
originalDataSource = dataSource; originalDataSource = dataSource;
} }
return CollectionUtils.computeIfAbsent(this.dataSourceProxyMap, originalDataSource,
BranchType.XA == dataSourceProxyMode ? DataSourceProxyXA::new : DataSourceProxy::new); SeataDataSourceProxy dsProxy = dataSourceProxyMap.get(originalDataSource);
if (dsProxy == null) {
synchronized (dataSourceProxyMap) {
dsProxy = dataSourceProxyMap.get(originalDataSource);
if (dsProxy == null) {
dsProxy = createDsProxyByMode(dataSourceProxyMode, originalDataSource);
dataSourceProxyMap.put(originalDataSource, dsProxy);
}
}
}
return dsProxy;
}
private SeataDataSourceProxy createDsProxyByMode(BranchType mode, DataSource originDs) {
return BranchType.XA == mode ? new DataSourceProxyXA(originDs) : new DataSourceProxy(originDs);
} }
} }
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
*/ */
package io.seata.spring.annotation.datasource; package io.seata.spring.annotation.datasource;
import java.lang.reflect.Method;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.lang.reflect.Method;
import io.seata.core.context.RootContext; import io.seata.core.context.RootContext;
import io.seata.core.model.BranchType; import io.seata.core.model.BranchType;
...@@ -53,15 +53,14 @@ public class SeataAutoDataSourceProxyAdvice implements MethodInterceptor, Introd ...@@ -53,15 +53,14 @@ public class SeataAutoDataSourceProxyAdvice implements MethodInterceptor, Introd
@Override @Override
public Object invoke(MethodInvocation invocation) throws Throwable { public Object invoke(MethodInvocation invocation) throws Throwable {
if (!RootContext.requireGlobalLock() if (!RootContext.requireGlobalLock() && dataSourceProxyMode != RootContext.getBranchType()) {
&& dataSourceProxyMode != RootContext.getBranchType()) {
return invocation.proceed(); return invocation.proceed();
} }
Method method = invocation.getMethod(); Method method = invocation.getMethod();
Object[] args = invocation.getArguments(); Object[] args = invocation.getArguments();
Method m = BeanUtils.findDeclaredMethod(dataSourceProxyClazz, method.getName(), method.getParameterTypes()); Method m = BeanUtils.findDeclaredMethod(dataSourceProxyClazz, method.getName(), method.getParameterTypes());
if (m != null) { if (m != null && DataSource.class.isAssignableFrom(method.getDeclaringClass())) {
SeataDataSourceProxy dataSourceProxy = DataSourceProxyHolder.get().putDataSource((DataSource) invocation.getThis(), dataSourceProxyMode); SeataDataSourceProxy dataSourceProxy = DataSourceProxyHolder.get().putDataSource((DataSource) invocation.getThis(), dataSourceProxyMode);
return m.invoke(dataSourceProxy, args); return m.invoke(dataSourceProxy, args);
} else { } else {
...@@ -73,4 +72,6 @@ public class SeataAutoDataSourceProxyAdvice implements MethodInterceptor, Introd ...@@ -73,4 +72,6 @@ public class SeataAutoDataSourceProxyAdvice implements MethodInterceptor, Introd
public Class<?>[] getInterfaces() { public Class<?>[] getInterfaces() {
return new Class[]{SeataProxy.class}; return new Class[]{SeataProxy.class};
} }
} }
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment