com.alachisoft.ncache.client.internal.communication.ConnectionPool Maven / Gradle / Ivy
package com.alachisoft.ncache.client.internal.communication;
import Alachisoft.NCache.Common.AppUtil;
import Alachisoft.NCache.Common.DataStructures.NewHashmap;
import Alachisoft.NCache.Common.DataStructures.QueueDictionary;
import Alachisoft.NCache.Common.Extensibility.Client.RPC.Partition;
import Alachisoft.NCache.Common.Net.Address;
import java.util.concurrent.ConcurrentHashMap;
// 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
/**
* Hold connection objects and hashmap from partition and partition of replica.
* Makes decision on bases of key and hashmap.
*/
final class ConnectionPool {
private ConcurrentHashMap _connections;
private QueueDictionary loadBalancerQueue;
private java.util.HashMap _hashMap;
private java.util.ArrayList _hashMapMember;
private java.util.ArrayList _partitions = new java.util.ArrayList();
private int _bucketSize = 0;
private long _lastViewId = -1;
public ConnectionPool() {
this._connections = new ConcurrentHashMap<>();
this.loadBalancerQueue = new QueueDictionary<>();
this._hashMap = new java.util.HashMap();
_hashMapMember = new java.util.ArrayList();
}
/**
* Get or set connection in connection pool
*
* @param ip ip of system to which connection is made
* @return connection object
*/
public Connection getItem(Address ip) {
synchronized (this._connections) {
return this._connections.get(ip);
}
}
public void setItem(Address ip, Connection value) {
synchronized (this._connections) {
this._connections.put(ip, value);
this.loadBalancerQueue.Enqueue(ip);
}
}
public java.util.ArrayList getPartitins() {
return _partitions;
}
/**
* Get or set bucket size
*/
public int getBucketSize() {
return this._bucketSize;
}
public void setBucketSize(int value) {
this._bucketSize = value;
}
/**
* Get count of connection in pool
*/
public int getCount() {
synchronized (this._connections) {
return this._connections.size();
}
}
public ConcurrentHashMap getConnections() {
return _connections;
}
/**
* Get last view id that published this hashmap
*/
public long getLastViewId() {
return this._lastViewId;
}
public void setLastViewId(long value) {
this._lastViewId = value;
}
/**
* Get connection to server on which the item is residing.
* If no connection exists, null will be returned.
*
* @param key key of item
* @return connection to server on which item is residing
*/
public Connection GetConnection(String key) {
Object ip = GetIpInternal(key);
Connection connection = null;
if (ip != null) {
synchronized (this._connections) {
connection = this._connections.get(ip);
}
}
return connection;
}
public java.util.Collection getServers() {
synchronized (_connections) {
return _connections.keySet();
}
}
public void UpdateBulkThreshold() {
synchronized (this._connections) {
for (Connection conn : _connections.values()) {
conn.UpdateBulkThreshold();
}
}
}
public Connection GetAnyConnection() {
Connection connection = null;
Connection firstConnection = null;
for (Connection conn : _connections.values()) {
if (firstConnection == null) {
firstConnection = conn;
}
if (conn.getIsConnected()) {
connection = conn;
break;
}
}
if (connection == null) {
connection = firstConnection;
}
return connection;
}
/**
* @param key
* @return
*/
private Object GetIpInternal(String key) {
if (key == null || key.equals("")) {
return null;
}
if (this._hashMap == null || this._bucketSize == 0) {
return null;
}
int hashCode = AppUtil.hashCode(key);
int index = hashCode / this._bucketSize;
if (index < 0) {
index = index * -1;
}
synchronized (this._hashMap) {
return this._hashMap.get(index);
}
}
/**
* Get ip address of server on which key resides
*
* @param key key
* @return ip address of server
*/
public Address GetIp(String key) {
Object tempVar = GetIpInternal(key);
return (Address) ((tempVar instanceof Address) ? tempVar : null);
}
/**
* Set new hashmap to this new hashmap
*
* @param hashMap new hashmap
*/
public void SetHashmap(NewHashmap hashMap) {
this._lastViewId = hashMap.getLastViewId();
synchronized (this._hashMap) {
_hashMap = hashMap.getMap();
}
synchronized (this._connections) {
_hashMapMember = hashMap.getMembers();
java.util.ArrayList partitions = new java.util.ArrayList();
for (String ip : _hashMapMember) {
Partition partition = new Partition();
partition.setAddress(new Address(ip, 9800));
partitions.add(partition);
}
_partitions = partitions;
}
}
/**
* Add connection to pool. If connection already exists, it will be replaced with new
* connection instance
*
* @param ip ip address of machine to which connection is made
* @param connection connection object
*/
public void Add(Address ip, Connection connection) {
synchronized (this._connections) {
this._connections.put(ip, connection);
this.loadBalancerQueue.Enqueue(ip);
}
}
/**
* Remove connection from pool
*
* @param ip ip address of machine to which connection is made
*/
public void Remove(Alachisoft.NCache.Common.Net.Address ip) {
synchronized (this._connections) {
this._connections.remove(ip);
this.loadBalancerQueue.Remove(ip);
}
}
/**
* Check whether connection pool contains specified connection
*
* @param ip ip address of machine to which connection is made
* @return true if the connection exists, false otherwise
*/
public boolean Contains(Address ip) {
synchronized (this._connections) {
return this._connections.containsKey(ip);
}
}
/**
* Clone connection table.
*
* @return cloned connection table
*/
public ConcurrentHashMap CloneConnectionTable() {
synchronized (this._connections) {
return new ConcurrentHashMap(_connections);
}
}
public boolean getFullyConnnected() {
synchronized (this._connections) {
if (_hashMapMember.size() != _connections.size()) {
return false;
}
for (Connection conn : _connections.values()) {
if (!conn.getIsConnected()) {
return false;
}
}
return true;
}
}
public boolean getFullyDisConnnected() {
synchronized (this._connections) {
for (Connection conn : _connections.values()) {
if (conn.getIsConnected()) {
return false;
}
}
return true;
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("{ (");
builder.append(this._lastViewId);
builder.append(") ");
builder.append("[");
for (Address ip : _connections.keySet()) {
builder.append(ip.getIpAddress().toString());
builder.append(",");
}
builder.deleteCharAt(builder.length() - 1);
builder.append("] }");
return builder.toString();
}
public Address GetNextAddress() {
synchronized (this._connections) {
Address node = loadBalancerQueue.Dequeue();
if (node == null) {
Connection connection = GetAnyConnection();
if (connection == null || !connection.getIsConnected()) {
return null;
} else {
for (Address ad : this._connections.keySet()) {
loadBalancerQueue.Enqueue(ad);
}
}
}
Connection conn = _connections.get(node);
if (conn == null || !conn.getIsConnected()) {
conn = GetAnyConnection();
if (conn == null || !conn.getIsConnected()) {
return null;
}
} else {
loadBalancerQueue.Enqueue(node);
}
return conn.getServerAddress();
}
}
public void MarkConnectionsIdle() {
synchronized (_connections) {
for (Connection conn : _connections.values()) {
conn.setIsIdle(true);
}
}
}
public java.util.ArrayList GetIdleConnections() {
java.util.ArrayList conList = new java.util.ArrayList();
synchronized (_connections) {
for (Connection conn : _connections.values()) {
if (conn.getIsIdle()) {
conList.add(conn);
}
}
}
return conList;
}
}