org.jumpmind.symmetric.transport.ConcurrentConnectionManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of symmetric-ds Show documentation
Show all versions of symmetric-ds Show documentation
SymmetricDS is an open source database synchronization solution. It is platform-independent,
web-enabled, and database-agnostic. SymmetricDS was first built to replicate changes between 'retail store'
databases and ad centralized 'corporate' database.
The newest version!
/*
* Licensed to JumpMind Inc under one or more contributor
* license agreements. See the NOTICE file distributed
* with this work for additional information regarding
* copyright ownership. JumpMind Inc licenses this file
* to you under the GNU Lesser General Public License (the
* "License"); you may not use this file except in compliance
* with the License.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see
* .
*
* 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.
*/
package org.jumpmind.symmetric.transport;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.jumpmind.symmetric.common.ParameterConstants;
import org.jumpmind.symmetric.service.IParameterService;
import org.jumpmind.symmetric.statistic.IStatisticManager;
public class ConcurrentConnectionManager implements IConcurrentConnectionManager {
protected IParameterService parameterService;
protected IStatisticManager statisticManager;
protected Map> activeReservationsByNodeByPool = new HashMap>();
protected Map> nodeConnectionStatistics = new HashMap>();
protected Set whiteList = new HashSet();
protected void logTooBusyRejection(String nodeId, String poolId) {
getNodeConnectionStatistics(nodeId, poolId).numOfRejections++;
}
protected void logConnectedTimePeriod(String nodeId, long startMs, long endMs, String poolId) {
NodeConnectionStatistics stats = getNodeConnectionStatistics(nodeId, poolId);
stats.totalConnectionCount++;
stats.totalConnectionTimeMs += endMs - startMs;
stats.lastConnectionTimeMs = startMs;
}
private synchronized NodeConnectionStatistics getNodeConnectionStatistics(String nodeId, String poolId) {
Map statsMap = nodeConnectionStatistics.get(poolId);
if (statsMap == null) {
statsMap = new HashMap();
nodeConnectionStatistics.put(poolId, statsMap);
}
NodeConnectionStatistics stats = statsMap.get(nodeId);
if (stats == null) {
stats = new NodeConnectionStatistics();
statsMap.put(nodeId, stats);
}
return stats;
}
synchronized public boolean releaseConnection(String nodeId, String poolId) {
Map reservations = getReservationMap(poolId);
Reservation reservation = reservations.remove(nodeId);
if (reservation != null) {
logConnectedTimePeriod(nodeId, reservation.createTime, System.currentTimeMillis(), poolId);
return true;
} else {
return false;
}
}
synchronized public void addToWhitelist(String nodeId) {
whiteList.add(nodeId);
}
synchronized public void removeFromWhiteList(String nodeId) {
whiteList.remove(nodeId);
}
synchronized public String[] getWhiteList() {
return whiteList.toArray(new String[whiteList.size()]);
}
synchronized public int getReservationCount(String poolId) {
return getReservationMap(poolId).size();
}
synchronized public boolean reserveConnection(String nodeId, String poolId, ReservationType reservationRequest) {
Map reservations = getReservationMap(poolId);
int maxPoolSize = parameterService.getInt(ParameterConstants.CONCURRENT_WORKERS);
long timeout = parameterService.getLong(ParameterConstants.CONCURRENT_RESERVATION_TIMEOUT);
removeTimedOutReservations(reservations);
if (reservations.size() < maxPoolSize || reservations.containsKey(nodeId) || whiteList.contains(nodeId)) {
reservations.put(nodeId, new Reservation(nodeId, reservationRequest == ReservationType.SOFT ? System
.currentTimeMillis()
+ timeout : Long.MAX_VALUE));
return true;
} else {
return false;
}
}
protected void removeTimedOutReservations(Map reservations) {
long currentTime = System.currentTimeMillis();
String[] keys = reservations.keySet().toArray(new String[reservations.size()]);
if (keys != null) {
for (String nodeId : keys) {
Reservation reservation = reservations.get(nodeId);
if (reservation.timeToLiveInMs < currentTime) {
reservations.remove(nodeId);
}
}
}
}
private Map getReservationMap(String poolId) {
Map reservations = activeReservationsByNodeByPool.get(poolId);
if (reservations == null) {
reservations = new HashMap();
activeReservationsByNodeByPool.put(poolId, reservations);
}
return reservations;
}
public void setParameterService(IParameterService parameterService) {
this.parameterService = parameterService;
}
public void setStatisticManager(IStatisticManager statisticManager) {
this.statisticManager = statisticManager;
}
protected static class Reservation {
String nodeId;
long timeToLiveInMs;
long createTime = System.currentTimeMillis();
public Reservation(String nodeId, long timeToLiveInMs) {
this.nodeId = nodeId;
this.timeToLiveInMs = timeToLiveInMs;
}
@Override
public int hashCode() {
return nodeId.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Reservation) {
return nodeId.equals(((Reservation) obj).nodeId);
} else {
return false;
}
}
public String getNodeId() {
return nodeId;
}
public long getTimeToLiveInMs() {
return timeToLiveInMs;
}
public long getCreateTime() {
return createTime;
}
}
public Map> getNodeConnectionStatisticsByPoolByNodeId() {
return this.nodeConnectionStatistics;
}
public class NodeConnectionStatistics {
int numOfRejections;
long totalConnectionCount;
long totalConnectionTimeMs;
long lastConnectionTimeMs;
public int getNumOfRejections() {
return numOfRejections;
}
public long getTotalConnectionCount() {
return totalConnectionCount;
}
public long getTotalConnectionTimeMs() {
return totalConnectionTimeMs;
}
public long getLastConnectionTimeMs() {
return lastConnectionTimeMs;
}
}
public Map> getActiveReservationsByNodeByPool() {
return activeReservationsByNodeByPool;
}
}