PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/gemfire-core/src/main/java/com/gemstone/gemfire/cache/client/internal/ConnectionImpl.java

https://gitlab.com/kidaa/incubator-geode
Java | 353 lines | 261 code | 46 blank | 46 comment | 33 complexity | ab06cab9f819bd8bc34ebba680e13032 MD5 | raw file
  1. /*=========================================================================
  2. * Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
  3. * This product is protected by U.S. and international copyright
  4. * and intellectual property laws. Pivotal products are covered by
  5. * more patents listed at http://www.pivotal.io/patents.
  6. *=========================================================================
  7. */
  8. package com.gemstone.gemfire.cache.client.internal;
  9. import java.io.IOException;
  10. import java.io.InputStream;
  11. import java.io.OutputStream;
  12. import java.net.InetAddress;
  13. import java.net.NoRouteToHostException;
  14. import java.net.Socket;
  15. import java.net.SocketException;
  16. import java.nio.ByteBuffer;
  17. import java.util.concurrent.atomic.AtomicBoolean;
  18. import org.apache.logging.log4j.Logger;
  19. import com.gemstone.gemfire.CancelCriterion;
  20. import com.gemstone.gemfire.CancelException;
  21. import com.gemstone.gemfire.ForcedDisconnectException;
  22. import com.gemstone.gemfire.cache.client.internal.ExecuteFunctionOp.ExecuteFunctionOpImpl;
  23. import com.gemstone.gemfire.cache.client.internal.ExecuteRegionFunctionOp.ExecuteRegionFunctionOpImpl;
  24. import com.gemstone.gemfire.cache.client.internal.ExecuteRegionFunctionSingleHopOp.ExecuteRegionFunctionSingleHopOpImpl;
  25. import com.gemstone.gemfire.cache.wan.GatewaySender;
  26. import com.gemstone.gemfire.distributed.DistributedSystem;
  27. import com.gemstone.gemfire.distributed.internal.DistributionConfig;
  28. import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
  29. import com.gemstone.gemfire.distributed.internal.ServerLocation;
  30. import com.gemstone.gemfire.internal.SocketCreator;
  31. import com.gemstone.gemfire.internal.SocketUtils;
  32. import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
  33. import com.gemstone.gemfire.internal.cache.tier.Acceptor;
  34. import com.gemstone.gemfire.internal.cache.tier.sockets.HandShake;
  35. import com.gemstone.gemfire.internal.cache.tier.sockets.ServerConnection;
  36. import com.gemstone.gemfire.internal.cache.tier.sockets.ServerQueueStatus;
  37. import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
  38. import com.gemstone.gemfire.internal.logging.LogService;
  39. import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
  40. /**
  41. * A single client to server connection.
  42. *
  43. * The execute method of this class is synchronized to
  44. * prevent two ops from using the client to server connection
  45. * at the same time.
  46. * @author dsmith
  47. * @since 5.7
  48. *
  49. */
  50. public class ConnectionImpl implements Connection {
  51. private static Logger logger = LogService.getLogger();
  52. /**Test hook to simulate a client crashing. If true, we will
  53. * not notify the server when we close the connection.
  54. */
  55. private static boolean TEST_DURABLE_CLIENT_CRASH = false;
  56. private Socket theSocket;
  57. private ByteBuffer commBuffer;
  58. private ByteBuffer commBufferForAsyncRead;
  59. // private int handShakeTimeout = AcceptorImpl.DEFAULT_HANDSHAKE_TIMEOUT_MS;
  60. private ServerQueueStatus status;
  61. private volatile boolean connectFinished;
  62. private final AtomicBoolean destroyed = new AtomicBoolean();
  63. private Endpoint endpoint;
  64. private short wanSiteVersion = -1;//In Gateway communication version of connected wan site
  65. //will be stored after successful handshake
  66. // private final CancelCriterion cancelCriterion;
  67. private final DistributedSystem ds;
  68. private OutputStream out;
  69. private InputStream in;
  70. private long connectionID = Connection.DEFAULT_CONNECTION_ID;
  71. private HandShake handShake;
  72. public ConnectionImpl(DistributedSystem ds, CancelCriterion cancelCriterion) {
  73. // this.cancelCriterion = cancelCriterion;
  74. this.ds = ds;
  75. }
  76. public ServerQueueStatus connect(EndpointManager endpointManager,
  77. ServerLocation location, HandShake handShake, int socketBufferSize,
  78. int handShakeTimeout, int readTimeout, byte communicationMode, GatewaySender sender)
  79. throws IOException {
  80. SocketCreator sc = SocketCreator.getDefaultInstance();
  81. DistributionConfig config = InternalDistributedSystem.getConnectedInstance().getConfig();
  82. if (communicationMode == Acceptor.GATEWAY_TO_GATEWAY) {
  83. sc = SocketCreator.createNonDefaultInstance(config.getGatewaySSLEnabled(),
  84. config.getGatewaySSLRequireAuthentication(), config.getGatewaySSLProtocols(),
  85. config.getGatewaySSLCiphers(), config.getGatewaySSLProperties());
  86. if (sender!= null && !sender.getGatewayTransportFilters().isEmpty()) {
  87. sc.initializeTransportFilterClientSocketFactory(sender);
  88. }
  89. } else {
  90. //If configured use SSL properties for cache-server
  91. sc = SocketCreator.createNonDefaultInstance(config.getServerSSLEnabled(),
  92. config.getServerSSLRequireAuthentication(),
  93. config.getServerSSLProtocols(),
  94. config.getServerSSLCiphers(),
  95. config.getServerSSLProperties());
  96. }
  97. if (!sc
  98. .isHostReachable(InetAddress.getByName(location.getHostName()))) {
  99. throw new NoRouteToHostException("Server is not reachable: " + location.getHostName());
  100. }
  101. theSocket = sc.connectForClient(
  102. location.getHostName(), location.getPort(), handShakeTimeout, socketBufferSize);
  103. theSocket.setTcpNoDelay(true);
  104. //System.out.println("ConnectionImpl setting buffer sizes: " +
  105. // socketBufferSize);
  106. theSocket.setSendBufferSize(socketBufferSize);
  107. // Verify buffer sizes
  108. verifySocketBufferSize(socketBufferSize, theSocket.getReceiveBufferSize(), "receive");
  109. verifySocketBufferSize(socketBufferSize, theSocket.getSendBufferSize(), "send");
  110. theSocket.setSoTimeout(handShakeTimeout);
  111. out = SocketUtils.getOutputStream(theSocket);//theSocket.getOutputStream();
  112. in = SocketUtils.getInputStream(theSocket);//theSocket.getInputStream();
  113. this.status = handShake.greet(this, location, communicationMode);
  114. commBuffer = ServerConnection.allocateCommBuffer(socketBufferSize, theSocket);
  115. if (sender != null) {
  116. commBufferForAsyncRead = ServerConnection
  117. .allocateCommBuffer(socketBufferSize, theSocket);
  118. }
  119. theSocket.setSoTimeout(readTimeout);
  120. endpoint = endpointManager.referenceEndpoint(location, this.status.getMemberId());
  121. //logger.warning("ESTABLISHING ENDPOINT:"+location+" MEMBERID:"+endpoint.getMemberId(),new Exception());
  122. this.connectFinished = true;
  123. this.endpoint.getStats().incConnections(1);
  124. return status;
  125. }
  126. public void close(boolean keepAlive) throws Exception {
  127. try {
  128. // if a forced-disconnect has occurred, we can't send messages to anyone
  129. SocketCreator sc = SocketCreator.getDefaultInstance();
  130. if (!sc.isHostReachable(this.theSocket.getInetAddress())) {
  131. return;
  132. }
  133. boolean sendCloseMsg = !TEST_DURABLE_CLIENT_CRASH;
  134. if (sendCloseMsg) {
  135. try {
  136. ((InternalDistributedSystem)ds).getDistributionManager();
  137. }
  138. catch (CancelException e) { // distribution has stopped
  139. Throwable t = e.getCause();
  140. if (t instanceof ForcedDisconnectException) {
  141. // we're crashing - don't attempt to send a message (bug 39317)
  142. sendCloseMsg = false;
  143. }
  144. }
  145. }
  146. if (sendCloseMsg) {
  147. if (logger.isDebugEnabled()) {
  148. logger.debug("Closing connection {} with keepAlive: {}", this, keepAlive);
  149. }
  150. CloseConnectionOp.execute(this, keepAlive);
  151. }
  152. }
  153. finally {
  154. destroy();
  155. }
  156. }
  157. public void emergencyClose() {
  158. commBuffer = null;
  159. try {
  160. theSocket.close();
  161. } catch (IOException e) {
  162. //ignore
  163. } catch (RuntimeException e) {
  164. //ignore
  165. }
  166. }
  167. public boolean isDestroyed() {
  168. return this.destroyed.get();
  169. }
  170. public void destroy() {
  171. if (!this.destroyed.compareAndSet(false, true)) {
  172. // was already set to true so someone else did the destroy
  173. return;
  174. }
  175. if (endpoint != null) {
  176. if (this.connectFinished) {
  177. endpoint.getStats().incConnections(-1);
  178. }
  179. endpoint.removeReference();
  180. }
  181. try {
  182. if (theSocket != null)
  183. theSocket.close();
  184. }
  185. catch (Exception e) {
  186. if (logger.isDebugEnabled()) {
  187. logger.debug(e.getMessage(), e);
  188. }
  189. }
  190. releaseCommBuffers();
  191. }
  192. private void releaseCommBuffers() {
  193. ByteBuffer bb = this.commBuffer;
  194. if (bb != null) {
  195. this.commBuffer = null;
  196. ServerConnection.releaseCommBuffer(bb);
  197. }
  198. bb = this.commBufferForAsyncRead;
  199. if (bb != null) {
  200. this.commBufferForAsyncRead = null;
  201. ServerConnection.releaseCommBuffer(bb);
  202. }
  203. }
  204. public ByteBuffer getCommBuffer() throws SocketException {
  205. if (isDestroyed()) {
  206. // see bug 52193. Since the code used to see this
  207. // as an attempt to use a close socket just throw
  208. // a SocketException.
  209. throw new SocketException("socket was closed");
  210. }
  211. return commBuffer;
  212. }
  213. public ServerLocation getServer() {
  214. return endpoint.getLocation();
  215. }
  216. public Socket getSocket() {
  217. return theSocket;
  218. }
  219. public OutputStream getOutputStream() {
  220. return out;
  221. }
  222. public InputStream getInputStream() {
  223. return in;
  224. }
  225. public ConnectionStats getStats() {
  226. return endpoint.getStats();
  227. }
  228. @Override
  229. public String toString() {
  230. return "Connection[" + endpoint + "]@" + this.hashCode();
  231. }
  232. public Endpoint getEndpoint() {
  233. return endpoint;
  234. }
  235. public ServerQueueStatus getQueueStatus() {
  236. return status;
  237. }
  238. public Object execute(Op op) throws Exception {
  239. Object result;
  240. // Do not synchronize when used for GatewaySender
  241. // as the same connection is being used
  242. if ((op instanceof AbstractOp) && ((AbstractOp)op).isGatewaySenderOp()) {
  243. result = op.attempt(this);
  244. endpoint.updateLastExecute();
  245. return result;
  246. }
  247. synchronized (this) {
  248. if (op instanceof ExecuteFunctionOpImpl
  249. || op instanceof ExecuteRegionFunctionOpImpl
  250. || op instanceof ExecuteRegionFunctionSingleHopOpImpl) {
  251. int earliertimeout = this.getSocket().getSoTimeout();
  252. this.getSocket().setSoTimeout(GemFireCacheImpl.getClientFunctionTimeout());
  253. result = op.attempt(this);
  254. this.getSocket().setSoTimeout(earliertimeout);
  255. } else {
  256. result = op.attempt(this);
  257. }
  258. }
  259. endpoint.updateLastExecute();
  260. return result;
  261. }
  262. public static void loadEmergencyClasses() {
  263. //do nothing
  264. }
  265. public short getWanSiteVersion(){
  266. return wanSiteVersion;
  267. }
  268. public void setWanSiteVersion(short wanSiteVersion){
  269. this.wanSiteVersion = wanSiteVersion;
  270. }
  271. public int getDistributedSystemId() {
  272. return ((InternalDistributedSystem)this.ds).getDistributionManager().getDistributedSystemId();
  273. }
  274. public void setConnectionID(long id) {
  275. this.connectionID = id;
  276. }
  277. public long getConnectionID() {
  278. return this.connectionID;
  279. }
  280. protected HandShake getHandShake() {
  281. return handShake;
  282. }
  283. protected void setHandShake(HandShake handShake) {
  284. this.handShake = handShake;
  285. }
  286. /**
  287. * test hook
  288. */
  289. public static void setTEST_DURABLE_CLIENT_CRASH(boolean v) {
  290. TEST_DURABLE_CLIENT_CRASH = v;
  291. }
  292. public ByteBuffer getCommBufferForAsyncRead() throws SocketException {
  293. if (isDestroyed()) {
  294. // see bug 52193. Since the code used to see this
  295. // as an attempt to use a close socket just throw
  296. // a SocketException.
  297. throw new SocketException("socket was closed");
  298. }
  299. return commBufferForAsyncRead;
  300. }
  301. private void verifySocketBufferSize(int requestedBufferSize, int actualBufferSize, String type) {
  302. if (actualBufferSize < requestedBufferSize) {
  303. logger.info(LocalizedMessage.create(LocalizedStrings.Connection_SOCKET_0_IS_1_INSTEAD_OF_THE_REQUESTED_2,
  304. new Object[] { new StringBuilder(type).append(" buffer size").toString(), actualBufferSize, requestedBufferSize }));
  305. }
  306. }
  307. }