Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alachisoft.ncache.client.internal.communication.Connection Maven / Gradle / Ivy
package com.alachisoft.ncache.client.internal.communication;
import Alachisoft.NCache.Common.Communication.Secure.SecureStream;
import Alachisoft.NCache.Common.Net.Address;
import Alachisoft.NCache.Common.StopWatch;
import Alachisoft.NCache.Common.Streams.BufferedStream;
import Alachisoft.NCache.Common.Threading.Latch;
import Alachisoft.NCache.Common.Threading.Monitor;
import Alachisoft.NCache.Management.Statistics.StatisticsCounter;
import Util.ResponseHelper;
import com.alachisoft.ncache.client.internal.command.Command;
import com.alachisoft.ncache.client.internal.command.CommandOptions;
import com.alachisoft.ncache.client.internal.command.CommandResponse;
import com.alachisoft.ncache.client.internal.util.Logs;
import com.alachisoft.ncache.common.protobuf.ResponseProtocol;
import com.alachisoft.ncache.runtime.exceptions.CacheException;
import com.alachisoft.ncache.runtime.exceptions.CommandException;
import com.alachisoft.ncache.runtime.exceptions.ConnectionException;
import com.alachisoft.ncache.runtime.exceptions.OperationFailedException;
import com.alachisoft.ncache.runtime.util.HelperFxn;
import com.alachisoft.ncache.runtime.util.TimeSpan;
import com.google.common.base.Stopwatch;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
// Copyright (c) 2020 Alachisoft
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License
//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases:
//using Exception = System.Exception;
public final class Connection {
public static final int CmdSizeHolderBytesCount = 10;
public static final int ValSizeHolderBytesCount = 10;
public static final int ValTypeHolderBytesCount = 4;
public static final int TotSizeHolderBytesCount = ValSizeHolderBytesCount + CmdSizeHolderBytesCount;
//10 bytes for the message size...
private static final int MessageHeader = 10;
//Threshold for maximum number of commands in a request.
private static final int MaxCmdsThreshold = 100;
public static long s_receiveBufferSize = 2048000;
public static boolean WriteRequestIdInResponse = true;
private static SocketAddress _bindIP;
private final CommandQueue _queue = new CommandQueue();
AtomicInteger inWriteQueue = new AtomicInteger(0);
private ServerLostListener _serverLost = null;
private boolean _isConnected = true;
private Socket _primaryClient = null;
private Socket _secondaryClient = null;
private InetAddress _address;
private String _ipAddress = "";
private String _intendedRecipientIPAddress = "";
private int _port = 0;
private Object _connectionMutex = new Object();
private Latch _connectionStatusLatch = new Latch(ConnectionStatus.Disconnected);
private long _processID = ProcessHandle.current().pid();
private String _cacheId;
private Thread _primaryReceiveThread = null;
private Thread _secondaryReceiveThread = null;
private boolean _notificationsRegistered = false;
private boolean _isReconnecting = false;
private boolean _forcedDisconnect = false;
private boolean _nagglingEnabled = false;
private long _nagglingSize = 5 * 100 * 1024; //500k
private NagglingManager _priNagglingMgr;
private NagglingManager _secNagglingMgr;
private Alachisoft.NCache.Common.DataStructures.Queue _msgQueue;
private boolean _supportDualSocket = false;
private Object _syncLock = new Object();
private Logs _logger;
private ResponseIntegrator _responseIntegrator;
private Address _serverAddress;
private Broker _container;
private StatisticsCounter _perfStatsColl = null;
private Object _socketSelectionMutex = new Object();
private boolean _usePrimary = true;
private boolean _requestLoggingEnabled;
private boolean _optimized = false;
private int _hostPort;
private boolean _isIdle = false;
private String _targetHost;
private boolean _provideCert;
private String[] tlsProtocols = {"TLSv1", "SSLv3"};
private SecureStream privatePrimarySecureStream;
private SecureStream privateSecondarySecureStream;
private boolean privateIsSecured;
private BufferedStream _bufferedStream;
private AtomicInteger activeWriters = new AtomicInteger(0);
private InetAddress _localEndpoint;
private RequestInformation _requestInformation;
private java.util.LinkedList _retrySendQueue = new java.util.LinkedList();
private java.util.LinkedList _outstandingQueue = new java.util.LinkedList();
public Connection(Broker container, Logs logs, StatisticsCounter perfStatsCollector, ResponseIntegrator rspIntegraotr, String bindIP, String cacheName) {
_connectionStatusLatch = new Latch(ConnectionStatus.Disconnected);
Initialize(container, logs, perfStatsCollector, rspIntegraotr, bindIP, cacheName);
}
public Connection(Broker broker) {
this(broker, broker.getLogger(), broker._perfStatsColl, broker.getResponseIntegrator(), broker.getClientConfig().getBindIP(), broker.getCache().getName());
}
private void Initialize(Broker container, Logs logs, StatisticsCounter perfStatsCollector, ResponseIntegrator rspIntegraotr, String bindIP, String cacheName) {
_serverLost = container;
_isConnected = true;
_primaryClient = null;
_secondaryClient = null;
_ipAddress = "";
_intendedRecipientIPAddress = "";
_port = 0;
_connectionMutex = new Object();
s_receiveBufferSize = 2048000;
_processID = ProcessHandle.current().pid();
_primaryReceiveThread = null;
_secondaryReceiveThread = null;
_notificationsRegistered = false;
_isReconnecting = false;
_forcedDisconnect = false;
_nagglingEnabled = false;
_nagglingSize = 5 * 100 * 1024; //500k
_supportDualSocket = false;
_syncLock = new Object();
_perfStatsColl = null;
_socketSelectionMutex = new Object();
_usePrimary = true;
_optimized = false;
_isIdle = false;
_container = container;
_logger = logs;
_responseIntegrator = rspIntegraotr;
_cacheId = cacheName;
_perfStatsColl = perfStatsCollector;
_requestInformation = new RequestInformation();
SetBindIP(bindIP);
if (System.getProperty("EnableNaggling") != null) {
_nagglingEnabled = Boolean.parseBoolean(System.getProperty("EnableNaggling"));
}
if (System.getProperty("NagglingSize") != null) {
_nagglingSize = 1024 * Long.parseLong(System.getProperty("NagglingSize"));
}
if (System.getProperty("EnableDualSockets") != null) {
_supportDualSocket = Boolean.parseBoolean(System.getProperty("EnableDualSockets"));
}
}
public boolean getIsSecured() {
return privateIsSecured;
}
public void setIsSecured(boolean value) {
privateIsSecured = value;
}
public SecureStream getPrimarySecureStream() {
return privatePrimarySecureStream;
}
public void setPrimarySecureStream(SecureStream value) {
privatePrimarySecureStream = value;
}
public SecureStream getSecondarySecureStream() {
return privateSecondarySecureStream;
}
public void setSecondarySecureStream(SecureStream value) {
privateSecondarySecureStream = value;
}
public void UpdateBulkThreshold() {
if (_requestInformation != null) {
_requestInformation.UpdateBulkThreshold();
}
}
public AtomicInteger getInWriteQueue() {
return inWriteQueue;
}
public int GetBulkThreshold() {
if (_requestInformation != null && _requestInformation.getBulkingEnabled()) {
return _requestInformation.getBulkThreshold();
}
return 1;
}
public String getClientLocalIP() {
String ip = "";
if (getPrimaryClientSocket() != null) {
if (getIsConnected()) {
InetAddress add = getPrimaryClientSocket().getInetAddress();
ip = add.getAddress().toString();
}
}
return ip;
}
public boolean HasMinimumCommands() {
return _queue.Count() >= GetBulkThreshold();
}
public boolean getOptimized() {
return _optimized;
}
public void setOptimized(boolean value) {
_optimized = value;
}
private boolean getDoNaggling() {
return (_nagglingEnabled && _priNagglingMgr != null);
}
public boolean getSupportDualSocket() {
return _supportDualSocket;
}
public Socket getPrimaryClientSocket() {
return _primaryClient;
}
public Socket getSecondaryClientSocket() {
return _secondaryClient;
}
public Latch getStatusLatch() {
return _connectionStatusLatch;
}
/**
* Checks if request logging is enabled on this server or not.
*/
public boolean getRequestInquiryEnabled() {
return _requestLoggingEnabled;
}
public void setRequestInquiryEnabled(boolean value) {
_requestLoggingEnabled = value;
}
public boolean getIsConnected() {
return _connectionStatusLatch.IsAnyBitsSet(ConnectionStatus.Connected);
}
/**
* Get ip address of machine to which connection is made
*/
public String getIpAddress() {
return this._ipAddress;
}
public InetAddress getAddress() {
return this._address;
}
public Address getServerAddress() {
return this._serverAddress;
}
public void setServerAddress(Address value) {
_serverAddress = value;
}
public String getIntendedRecipientIPAddress() {
return this._intendedRecipientIPAddress;
}
public void setIntendedRecipientIPAddress(String value) {
this._intendedRecipientIPAddress = value;
}
/**
* Get port on which connection is made
*/
public int getPort() {
return this._port;
}
private void setPort(int value) {
_port = value;
}
public boolean getNotifRegistered() {
return this._notificationsRegistered;
}
public void setNotifRegistered(boolean value) {
this._notificationsRegistered = value;
}
public boolean getIsReconnecting() {
return this._isReconnecting;
}
public void setIsReconnecting(boolean value) {
this._isReconnecting = value;
}
private Socket getCommunicationSocket() {
Socket selectedSocket = _primaryClient;
if (getSupportDualSocket()) {
selectedSocket = _primaryClient;
synchronized (_socketSelectionMutex) {
if (!_usePrimary) {
selectedSocket = _secondaryClient;
}
_usePrimary = !_usePrimary;
}
}
return selectedSocket;
}
public boolean getIsIdle() {
synchronized (_connectionMutex) {
return _isIdle;
}
}
public void setIsIdle(boolean value) {
synchronized (_connectionMutex) {
_isIdle = value;
}
}
//function that sets string provided to bindIP
public void SetBindIP(String value) {
if (value != null && !value.equals("")) {
try {
_bindIP = new InetSocketAddress(InetAddress.getByName(value.trim()), this._port);
} catch (RuntimeException | UnknownHostException ex) {
}
}
}
@Override
public boolean equals(Object obj) {
Connection connection = (Connection) ((obj instanceof Connection) ? obj : null);
return (connection != null && this.getIpAddress().equals(connection.getIpAddress()));
}
public void dispose() {
if (_msgQueue != null && !_msgQueue.getClosed()) {
_msgQueue.close(true);
_msgQueue = null;
}
try {
if (_priNagglingMgr != null && _priNagglingMgr.isAlive()) {
_priNagglingMgr.interrupt();
}
if (_secNagglingMgr != null && _secNagglingMgr.isAlive()) {
_secNagglingMgr.interrupt();
}
} catch (RuntimeException e) {
}
}
public boolean connect(InetAddress ipAddress, int port) {
int retry = 0;
setOptimized(false);
_ipAddress = ipAddress.toString();
_address = ipAddress;
_port = port;
_serverAddress = new Address(ipAddress, port);
synchronized (_connectionMutex) {
_primaryClient = PrepareToConnect(_primaryClient);
SocketAddress endPoint = null;
endPoint = new InetSocketAddress(ipAddress, port);
while (retry < 3) {
try {
_primaryClient.connect(endPoint);
_bufferedStream = new BufferedStream(_primaryClient, false);
_localEndpoint = (_primaryClient.getInetAddress() instanceof InetAddress) ? _primaryClient.getLocalAddress() : null;
if (_logger != null && _logger.getIsErrorLogsEnabled()) {
_logger.getNCacheLog().CriticalInfo("Connection.Connect", String.format("established TCP connection with %s:%d. Local endpoint: {%s}",_ipAddress,_port,_localEndpoint.getHostAddress()));
}
return true;
} catch (RuntimeException | IOException e) {
if (_logger != null && _logger.getIsErrorLogsEnabled()) {
_logger.getNCacheLog().Error("Connection.Connect", " can not connect to " + ipAddress + ":" + port + ". error: " + e.toString());
}
if (e.getMessage().contains("A connection attempt failed because the connected party did not properly respond after a period of time")) {
retry++;
} else {
return false;
}
}
}
}
return false;
}
public void Init() {
StartThread();
}
private Socket PrepareToConnect(Socket client) {
client = new Socket();
try {
client.setTcpNoDelay(false);
} catch (SocketException e) {
}
if (_bindIP != null) {
try {
client.bind(_bindIP);
} catch (RuntimeException | IOException e) {
throw new RuntimeException("Invalid bind-ip-address specified in client configuration");
}
}
_forcedDisconnect = false;
return client;
}
public void Secure(String targetHost, boolean provideCert) {
synchronized (_connectionMutex) {
if (!getIsSecured()) {
setPrimarySecureStream(new SecureStream(_primaryClient));
getPrimarySecureStream().InitializeAsClient(_targetHost = targetHost, _provideCert = provideCert);
setIsSecured(true);
}
}
}
public void ConnectSecondarySocket(InetAddress address, int port) {
_secondaryClient = PrepareToConnect(_secondaryClient);
SocketAddress socketAddress = new InetSocketAddress(address, port);
try {
_secondaryClient.connect(socketAddress);
} catch (RuntimeException | IOException e) {
if (_logger.getIsErrorLogsEnabled()) {
_logger.getNCacheLog().Error("Connection.Connect", " can not connect to " + address + ":" + port + ". error: " + e.toString());
}
}
synchronized (_connectionMutex) {
if (getIsSecured()) {
setSecondarySecureStream(new SecureStream(_secondaryClient));
getSecondarySecureStream().InitializeAsClient(_targetHost, _provideCert);
}
}
}
/**
* it transfers the existing connection to a new connection without changing the object container
*
* @param container
* @param perfStatsCollector
* @param rspIntegraotr
* @param bindIP
* @param cacheName
* @param ipAddress
* @param cachePort
* @return
*/
public boolean SwitchTo(Broker container, Logs logs, StatisticsCounter perfStatsCollector, ResponseIntegrator rspIntegraotr, String bindIP, String cacheName, InetAddress ipAddress, int cachePort) {
int oldPort = getPort();
Initialize(container, logs, perfStatsCollector, rspIntegraotr, bindIP, cacheName);
if (this.connect(getAddress(), cachePort)) {
_hostPort = cachePort;
this.setPort(oldPort);
this._serverAddress = new Address(ipAddress, oldPort);
return true;
}
this.setPort(oldPort);
this._serverAddress = new Address(ipAddress, oldPort);
return false;
}
public void Disconnect() {
Disconnect(true);
}
public void Disconnect(boolean changeStatus) {
_forcedDisconnect = true;
if (changeStatus) {
this._connectionStatusLatch.SetStatusBit(ConnectionStatus.Disconnected, ConnectionStatus.Connected);
}
if (_primaryReceiveThread != null && _primaryReceiveThread.getState() != Thread.State.TERMINATED) {
_primaryReceiveThread.interrupt();
_primaryReceiveThread = null;
}
if (_primaryClient != null && _primaryClient.isConnected()) {
try {
_primaryClient.shutdownInput();
_primaryClient.shutdownOutput();
} catch (SocketException e3) {
} catch (IOException e) {
}finally {
try {
_primaryClient.close();
} catch (IOException e) {
}
}
}
//dispose the secondary socket
if (_secondaryReceiveThread != null && _secondaryReceiveThread.getState() != Thread.State.TERMINATED) {
_secondaryReceiveThread.interrupt();
_secondaryReceiveThread = null;
}
if (_secondaryClient != null && _secondaryClient.isConnected()) {
try {
_secondaryClient.shutdownInput();
_secondaryClient.shutdownOutput();
} catch (SocketException e3) {
} catch (IOException e) {
}finally {
try {
_secondaryClient.close();
} catch (IOException e) {
}
}
}
setIsSecured(false);
setSecondarySecureStream(null);
setPrimarySecureStream(null);
}
public CommandResponse RecieveCommandResponse(boolean _usingSecondary) throws ConnectionException {
if (getIsSecured()) {
if (_usingSecondary) {
return SecureRecieveCommandResponse(getSecondarySecureStream());
}
return SecureRecieveCommandResponse(getPrimarySecureStream());
}
if (_usingSecondary) {
return RecieveCommandResponse(_secondaryClient);
}
return RecieveCommandResponse(_primaryClient);
}
private CommandResponse RecieveCommandResponse(Socket client) throws ConnectionException {
CommandResponse cmdRespose = null;
try {
byte[] value = AssureRecieve(client, getOptimized());
ResponseProtocol.Response response = ResponseProtocol.Response.parseFrom(value);
if (response != null && response.getResponseType() == ResponseProtocol.Response.Type.RESPONSE_FRAGMENT) {
response = _responseIntegrator.AddResponseFragment(this._serverAddress, response.getGetResponseFragment());
}
if (response != null) {
cmdRespose = new CommandResponse(false, new Address());
cmdRespose.setCacheId(this._cacheId);
cmdRespose.setResult(response);
}
} catch (IOException | CacheException e) {
throw new ConnectionException(e.getMessage(), this._serverAddress.getIpAddress(), this._serverAddress.getPort());
}
return cmdRespose;
}
private CommandResponse SecureRecieveCommandResponse(SecureStream client) throws ConnectionException {
byte[] value = null;
CommandResponse cmdRespose = null;
try {
value = AssureSecureRecieve(client, getOptimized());
ResponseProtocol.Response response = ResponseProtocol.Response.parseFrom(value);
if (response != null && response.getResponseType() == ResponseProtocol.Response.Type.RESPONSE_FRAGMENT) {
response = _responseIntegrator.AddResponseFragment(this._serverAddress, response.getGetResponseFragment());
}
if (response != null) {
cmdRespose = new CommandResponse(false, new Address());
cmdRespose.setCacheId(this._cacheId);
cmdRespose.setResult(response);
}
} catch (IOException | CacheException e) {
throw new ConnectionException(e.getMessage(), this._serverAddress.getIpAddress(), this._serverAddress.getPort());
}
return cmdRespose;
}
public void AssureSendDirect(byte[] buffer, Socket client, boolean checkConnected) throws IOException, ConnectionException {
int dataSent = 0, dataLeft = buffer.length;
synchronized (_connectionMutex) {
if (checkConnected && _connectionStatusLatch.IsAnyBitsSet((byte) (ConnectionStatus.Disconnected | ConnectionStatus.Connecting))) {
throw new ConnectionException(_serverAddress.getIpAddress(), _serverAddress.getPort());
}
synchronized (client.getOutputStream()) {
try {
client.getOutputStream().write(buffer);
client.getOutputStream().flush();
} catch (IOException se) {
if (_logger.getIsErrorLogsEnabled()) {
_logger.getNCacheLog().Error("Connection.AssureSendDirect() ", se.toString());
}
_connectionStatusLatch.SetStatusBit(ConnectionStatus.Disconnected, ConnectionStatus.Connected);
throw new ConnectionException(_serverAddress.getIpAddress(), _serverAddress.getPort());
}
}
}
}
public void AssureSendToBufferedStream(byte[] buffer, Socket client, boolean checkConnected) throws ConnectionException {
int dataSent = 0, dataLeft = buffer.length;
if (checkConnected && _connectionStatusLatch.IsAnyBitsSet((byte) (ConnectionStatus.Disconnected | ConnectionStatus.Connecting))) {
throw new ConnectionException(_serverAddress.getIpAddress(), _serverAddress.getPort());
}
try {
_bufferedStream.write(buffer, dataSent, dataLeft);
setIsIdle(false);
} catch (IOException se) {
if (_logger.getIsErrorLogsEnabled()) {
_logger.getNCacheLog().Error("Connection.AssureSend() ", se.toString());
}
_connectionStatusLatch.SetStatusBit(ConnectionStatus.Disconnected, ConnectionStatus.Connected);
throw new ConnectionException(_serverAddress.getIpAddress(), _serverAddress.getPort());
}
}
public void AssureSendNaggledData(Socket client, byte[] buffer, int bytesToSent, boolean checkConnected) throws ConnectionException {
int dataSent = 0, dataLeft = bytesToSent;
synchronized (_connectionMutex) {
if (checkConnected && _connectionStatusLatch.IsAnyBitsSet((byte) (ConnectionStatus.Disconnected | ConnectionStatus.Connecting))) {
throw new ConnectionException(_serverAddress.getIpAddress(), _serverAddress.getPort());
}
while (dataSent < bytesToSent) {
try {
dataLeft = bytesToSent - dataSent;
client.getOutputStream().write(buffer, dataSent, dataLeft);
} catch (IOException se) {
if (_logger.getIsErrorLogsEnabled()) {
_logger.getNCacheLog().Error("Connection.AssureSendDirect() ", se.toString());
}
_connectionStatusLatch.SetStatusBit(ConnectionStatus.Disconnected, ConnectionStatus.Connected);
throw new ConnectionException(_serverAddress.getIpAddress(), _serverAddress.getPort());
}
}
setIsIdle(false);
}
}
private byte[] AssureRecieve(Socket client, boolean optimized) throws IOException, ConnectionException {
byte[] buffer = new byte[CmdSizeHolderBytesCount + (optimized ? CmdSizeHolderBytesCount : 0)];
AssureRecieve(buffer, client);
String s = new String(buffer, 0 + (optimized ? CmdSizeHolderBytesCount : 0), CmdSizeHolderBytesCount);
int commandSize = 0;
try
{
commandSize = Integer.parseInt(s.trim());
}
catch (NumberFormatException ex){ }
if (commandSize == 0) {
return new byte[0];
}
buffer = new byte[commandSize];
AssureRecieve(buffer, client);
return buffer;
}
private void AssureRecieve(byte[] buffer, Socket client) throws ConnectionException {
int bytesRecieved = 0;
try
{
synchronized (client.getInputStream())
{
do
{
bytesRecieved += client.getInputStream().read(buffer, bytesRecieved, (buffer.length - bytesRecieved));
}
while (bytesRecieved != -1 && bytesRecieved < buffer.length);
}
}
catch (Exception e)
{
_connectionStatusLatch.SetStatusBit(ConnectionStatus.Disconnected, ConnectionStatus.Connected);
throw new ConnectionException("Disconnected: can not receive." + e.toString() );
}
setIsIdle(false);
}
public void AssureSendSecure(byte[] buffer, SecureStream stream, boolean checkConnected) throws ConnectionException {
synchronized (_connectionMutex) {
if (checkConnected && _connectionStatusLatch.IsAnyBitsSet((byte) (ConnectionStatus.Disconnected | ConnectionStatus.Connecting))) {
throw new ConnectionException(_serverAddress.getIpAddress(), _serverAddress.getPort());
}
try {
stream.write(buffer);
} catch (IOException se) {
if (_logger.getIsErrorLogsEnabled()) {
_logger.getNCacheLog().Error("Connection.AssureSendSecure() ", se.toString());
}
_connectionStatusLatch.SetStatusBit(ConnectionStatus.Disconnected, ConnectionStatus.Connected);
throw new ConnectionException(_serverAddress.getIpAddress(), _serverAddress.getPort());
}
setIsIdle(false);
}
}
private byte[] AssureSecureRecieve(SecureStream client, boolean optimized) throws IOException, ConnectionException {
byte[] buffer = new byte[CmdSizeHolderBytesCount + (optimized ? CmdSizeHolderBytesCount : 0)];
AssureSecureRecieve(buffer, client);
String s = new String(buffer, 0 + (optimized ? CmdSizeHolderBytesCount : 0), CmdSizeHolderBytesCount);
int commandSize = 0;
try
{
commandSize = Integer.parseInt(s.trim());
}
catch (NumberFormatException ex){ }
if (commandSize == 0) {
return new byte[0];
}
buffer = new byte[commandSize];
AssureSecureRecieve(buffer, client);
return buffer;
}
private void AssureSecureRecieve(byte[] buffer, SecureStream client) throws IOException, ConnectionException {
int bytesRecieved = 0;
try
{
synchronized (client.getInputStream())
{
do
{
bytesRecieved += client.getInputStream().read(buffer, bytesRecieved, (buffer.length - bytesRecieved));
}
while (bytesRecieved != -1 && bytesRecieved < buffer.length);
}
}
catch (Exception e)
{
_connectionStatusLatch.SetStatusBit(ConnectionStatus.Disconnected, ConnectionStatus.Connected);
throw new ConnectionException("Disconnected: can not receive." + e.toString() );
}
setIsIdle(false);
}
public void SendCommand(byte[] commandBytes, boolean checkConnected) throws ConnectionException {
if (_perfStatsColl.getIsEnabled()) {
_perfStatsColl.IncrementClientRequestsPerSecStats(1);
}
byte[] dataWithSize = new byte[commandBytes.length + MessageHeader];
byte[] lengthBytes = HelperFxn.toBytes(commandBytes.length);
System.arraycopy(lengthBytes, 0, dataWithSize, 0, lengthBytes.length);
System.arraycopy(commandBytes, 0, dataWithSize, MessageHeader, commandBytes.length);
if (getDoNaggling()) {
_msgQueue.add(commandBytes);
} else {
if (getIsSecured()) {
if (getSupportDualSocket()) {
SecureStream selectedStream = getPrimarySecureStream();
synchronized (_socketSelectionMutex) {
if (!_usePrimary) {
selectedStream = getSecondarySecureStream();
}
_usePrimary = !_usePrimary;
}
AssureSendSecure(dataWithSize, selectedStream, checkConnected);
} else {
AssureSendSecure(dataWithSize, getPrimarySecureStream(), checkConnected);
}
} else {
if (getSupportDualSocket()) {
Socket selectedSocket = _primaryClient;
synchronized (_socketSelectionMutex) {
if (!_usePrimary) {
selectedSocket = _secondaryClient;
}
_usePrimary = !_usePrimary;
}
AssureSendToBufferedStream(dataWithSize, selectedSocket, checkConnected);
} else {
AssureSendToBufferedStream(dataWithSize, _primaryClient, checkConnected);
}
}
}
}
public void StartThread() {
_primaryReceiveThread = new Thread(() -> {
Socket client = getIsSecured() ? getPrimarySecureStream() : _primaryClient;
RecieveThread(client);
});
_primaryReceiveThread.setPriority(5);
_primaryReceiveThread.setDaemon(true); //Taimoor:Now application can exit without calling dispose()
_primaryReceiveThread.start();
if (getSupportDualSocket()) {
_secondaryReceiveThread = new Thread(() -> {
Socket client = getIsSecured() ? getSecondarySecureStream() : _secondaryClient;
RecieveThread(client);
});
_secondaryReceiveThread.setPriority(5);
_secondaryReceiveThread.setDaemon(true); //Taimoor:Now application can exit without calling dispose()
_secondaryReceiveThread.start();
}
}
private void RecieveThread(Socket client) {
Socket clientSocket = (client instanceof Socket) ? client : null;
SecureStream stream = (SecureStream) ((client instanceof SecureStream) ? client : null);
int count;
while (true) {
try {
count = 0;
byte[] cmdBytes = clientSocket != null ? AssureRecieve(clientSocket, false) : AssureSecureRecieve(stream, false);
InputStream targetStream = new ByteArrayInputStream(cmdBytes);
try {
while (targetStream.available() > 0) {
ProcessResponse(targetStream);
count++;
}
} finally {
targetStream.close();
}
// Broker.AverageCounterRecieve.IncrementBy(count);
}
catch(SocketException se)
{
OnConnectionBroken(se,ExType.Socket);
break;
}
catch (IOException ie) {
//System.IOException is going to thrown in the case SslStream when the connection gets forcibly closed.
//Thus we are going to handle it as a SocketException....
OnConnectionBroken(ie, ExType.Socket);
break;
}
catch(ConnectionException ce)
{
OnConnectionBroken(ce,ExType.Connection);
break;
}
catch (Exception e) {
OnConnectionBroken(e, ExType.General);
break;
}
}
}
private void OnConnectionBroken(Exception e, ExType exType) {
if (_logger != null) {
switch (exType) {
case Socket:
case Connection:
if (_forcedDisconnect) {
if (_logger.getIsErrorLogsEnabled()) {
_logger.getNCacheLog().Error("Connection.ReceivedThread", "Connection with server lost gracefully");
}
} else {
if (_logger.getIsErrorLogsEnabled()) {
_logger.getNCacheLog().Error("Connection.ReceivedThread", "An established connection with the server " + _serverAddress + " is lost. Error:" + e.toString());
}
}
if (!_forcedDisconnect) {
_connectionStatusLatch.SetStatusBit(ConnectionStatus.Disconnected, ConnectionStatus.Connected);
}
_primaryReceiveThread = null;
_serverLost.OnServerLost(_serverAddress, _forcedDisconnect);
break;
case Interrupt:
case Abort:
if (_forcedDisconnect) {
if (_logger.getIsErrorLogsEnabled()) {
_logger.getNCacheLog().Error("Connection.ReceivedThread", "Connection with server lost gracefully");
_logger.getNCacheLog().Flush();
}
}
if (!_forcedDisconnect) {
_connectionStatusLatch.SetStatusBit(ConnectionStatus.Disconnected, ConnectionStatus.Connected);
}
_serverLost.OnServerLost(_serverAddress, _forcedDisconnect);
break;
case General:
if (_logger.getIsErrorLogsEnabled()) {
_logger.getNCacheLog().Error("Connection.ReceivedThread", e.toString());
_logger.getNCacheLog().Flush();
}
if (!_forcedDisconnect) {
_connectionStatusLatch.SetStatusBit(ConnectionStatus.Disconnected, ConnectionStatus.Connected);
}
_serverLost.OnServerLost(_serverAddress, _forcedDisconnect);
break;
}
}
setIsSecured(false);
}
/**
* Reads a single single response from the stream and processes it.
*
* @param stream
*/
private void ProcessResponse(InputStream stream) throws IOException, OperationFailedException {
ResponseProtocol.Response response;
long requestId = 0;
if (WriteRequestIdInResponse) {
byte[] requestIdBytes = new byte[CmdSizeHolderBytesCount];
stream.read(requestIdBytes, 0, requestIdBytes.length);
String s = new String(requestIdBytes, 0, requestIdBytes.length);
requestId = Long.parseLong(s.trim());
}
byte[] responseTypeBytes = new byte[ValTypeHolderBytesCount];
stream.read(responseTypeBytes, 0, responseTypeBytes.length);
String responseTypeString = new String(responseTypeBytes, 0, responseTypeBytes.length);
int requestType = Integer.parseInt(responseTypeString.trim());
ResponseProtocol.Response.Type responseType = ResponseProtocol.Response.Type.valueOf(requestType);
byte[] cmdSzBytes = new byte[CmdSizeHolderBytesCount];
stream.read(cmdSzBytes, 0, CmdSizeHolderBytesCount);
String s = new String(cmdSzBytes, 0, cmdSzBytes.length);
int commandSize = Integer.parseInt(s.trim());
byte[] cmdBytes = new byte[commandSize];
stream.read(cmdBytes, 0, commandSize);
CommandResponse cmdRespose = new CommandResponse(false, new Address());
cmdRespose.setCacheId(_cacheId);
cmdRespose.setSourceAddress(this.getServerAddress());
if (WriteRequestIdInResponse) {
cmdRespose.setNeedsDeserialization(true);
cmdRespose.setRequestId(requestId);
cmdRespose.setRawResult(cmdBytes);
cmdRespose.setType(responseType);
} else {
InputStream targetStream = new ByteArrayInputStream(cmdBytes);
try {
response = ResponseHelper.deserializeResponse(responseType, targetStream);
} finally {
targetStream.close();
}
cmdRespose.setNeedsDeserialization(false);
if (response != null) {
cmdRespose.setResult(response);
}
}
if (_perfStatsColl.getIsEnabled()) {
_perfStatsColl.incrementClientResponsesPerSecStats(1);
}
if (cmdRespose != null) {
_container.ProcessResponse(cmdRespose, _serverAddress);
}
}
public boolean TryEnqueue(Command command, boolean checkConnected) {
if (_requestInformation != null) {
_requestInformation.AddRequest();
}
boolean reqWrite = _queue.Push(command);
if (reqWrite) {
_container.getSocketManagerHandler().RequestWrite(this, false);
}
return true;
}
public WriteResult WriteQueue(int maxWork) {
boolean weAreWriter = false;
try {
weAreWriter = activeWriters.compareAndExchange(0, 1) == 0;
if (!weAreWriter) {
return WriteResult.CompetingWriter;
}
if (_bufferedStream == null) {
return WriteResult.NoConnection;
}
int count = 0;
while (true) {
Command command = _queue.Dequeue();
if (command == null) {
if (count == 0) {
Flush();
//if (_container.getLogger().getIsErrorLogsEnabled()) {
// _container.getLogger().getNCacheLog().Info("Connection.WriteQueue", "Flushed");
//}
return WriteResult.NothingToDo;
}
return WriteResult.QueueEmptyAfterWrite;
}
command.setFinalDestinationAddress(_serverAddress);
if (command.getPulseOnSend()) {
_retrySendQueue.offer(command);
} else {
_outstandingQueue.offer(command);
}
long prevWriteCount = _bufferedStream.getWriteCount();
if (!WriteMessageDirect(command)) {
return WriteResult.NoConnection;
}
long currentWriteCount = _bufferedStream.getWriteCount();
// if (_container.getLogger().getIsErrorLogsEnabled()) {
// _container.getLogger().getNCacheLog().Error("Connection.WriteQueue", "RequestID :" + command.getRequestId() + " " + command.getCommandName() + " with Previous Count:"+prevWriteCount+" and current write count:"+currentWriteCount);
// }
if (currentWriteCount > prevWriteCount) {
OnWriteSuccess();
}
count++;
if (maxWork > 0 && count >= maxWork) {
Flush();
break;
}
}
} catch (IOException ce) {
if (_logger.getIsErrorLogsEnabled())
_logger.getNCacheLog().Error("Connection.AssureSend().IOException ", ce.toString());
_connectionStatusLatch.SetStatusBit(ConnectionStatus.Disconnected, ConnectionStatus.Connected);
SendError sendError = new SendError(ErrorType.ConnectionException, new ConnectionException(this._serverAddress.getIpAddress(), this._serverAddress.getPort()));
OnWriteFailure(sendError);
} catch (ConnectionException exs) {
SendError sendError = new SendError(ErrorType.ConnectionException, exs);
OnWriteFailure(sendError);
} catch (Exception ex) {
SendError sendError = new SendError(ErrorType.Exception, ex);
OnWriteFailure(sendError);
} finally {
if (weAreWriter) {
activeWriters.set(0);
}
}
return _queue.Any() ? WriteResult.MoreWork : WriteResult.QueueEmptyAfterWrite;
}
private void OnWriteSuccess() {
PulseRetrySendCommands(null);
_outstandingQueue.clear();
}
private void OnWriteFailure(SendError sendError) {
PulseRetrySendCommands(sendError);
SendFailureResponse(sendError);
}
public void Flush() throws IOException {
_bufferedStream.flush();
OnWriteSuccess();
}
private void PulseRetrySendCommands(SendError sendError) {
while (_retrySendQueue.size() != 0) {
Command command = _retrySendQueue.poll();
synchronized (command) {
command.setSendError(sendError);
command.setSentOverWire(true);
Monitor.pulse(command);
}
}
}
private void SendFailureResponse(SendError sendError) {
while (_outstandingQueue.size() != 0) {
Command command = _outstandingQueue.poll();
command.setSendError(sendError);
Request request = _container.GetRequest(command.getRequestId());
if (request == null) {
continue;
}
synchronized (request) {
request.InitializeFailedSendResponse(this._serverAddress, command);
Monitor.pulse(request);
}
}
}
public boolean ConfirmRemoveFromWriteQueue() {
synchronized (_queue.getSyncLock()) {
if (_queue.Count() == 0) {
inWriteQueue.set(0);
return true;
}
}
return false;
}
private boolean WriteMessageDirect(Command command) throws CommandException, ConnectionException, IOException {
SendCommand(command.toByte(command.getAcknowledgmentId(), getRequestInquiryEnabled()), true);
return true;
}
public void WaitUntillPipelineFilled() {
int iterations = 10;
int timeout = Extensions.getTimeout();
StopWatch watch = new StopWatch();
watch.start();
long elapsedTime = 0;
while (timeout > elapsedTime && !HasMinimumCommands()) {
int spinWaitCount = 0;
while (spinWaitCount++ < iterations) {
Thread.onSpinWait();
}
elapsedTime = watch.getElapsedTime();
if (elapsedTime < 10) {
iterations *= 2;
}
}
}
}