org.jgroups.blocks.AbstractConnectionMap Maven / Gradle / Ivy
package org.jgroups.blocks;
import org.jgroups.Address;
import org.jgroups.Global;
import org.jgroups.util.ThreadFactory;
import org.jgroups.util.Util;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public abstract class AbstractConnectionMap implements ConnectionMap {
protected final List> conn_listeners=new ArrayList<>();
protected final Map conns=new HashMap<>();
protected final Lock lock = new ReentrantLock(); // syncs conns
protected final Lock sock_creation_lock= new ReentrantLock(true); // syncs socket establishment
protected final ThreadFactory factory;
protected final long reaperInterval;
protected final Reaper reaper;
public AbstractConnectionMap(ThreadFactory factory) {
this(factory,0);
}
public AbstractConnectionMap(ThreadFactory factory,long reaperInterval) {
super();
this.factory=factory;
this.reaperInterval=reaperInterval;
reaper=reaperInterval > 0? new Reaper() : null;
}
public Lock getLock(){
return lock;
}
public boolean hasConnection(Address address) {
return conns.containsKey(address);
}
public void addConnection(Address address, V conn) {
V previous = conns.put(address, conn);
Util.close(previous); // closes previous connection (if present)
notifyConnectionOpened(address, conn);
}
public void addConnectionMapListener(ConnectionMapListener cml) {
if(cml != null && !conn_listeners.contains(cml))
conn_listeners.add(cml);
}
public int getNumConnections() {
lock.lock();
try {
return conns.size();
}
finally {
lock.unlock();
}
}
public int getNumOpenConnections() {
int retval=0;
lock.lock();
try {
for(Connection conn: conns.values())
if(conn.isOpen())
retval++;
return retval;
}
finally {
lock.unlock();
}
}
public String printConnections() {
StringBuilder sb=new StringBuilder();
lock.lock();
try {
for(Map.Entry entry: conns.entrySet()) {
sb.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
}
}
finally {
lock.unlock();
}
return sb.toString();
}
public ThreadFactory getThreadFactory() {
return factory;
}
/** Only removes the connection if conns.get(address) == conn */
public void removeConnectionIfPresent(Address address, V conn) {
if(address == null || conn == null)
return;
lock.lock();
try {
V existing=conns.get(address);
if(conn == existing) {
V tmp=conns.remove(address);
Util.close(tmp);
}
}
finally {
lock.unlock();
}
}
public void removeConnectionMapListener(ConnectionMapListener cml) {
if(cml != null)
conn_listeners.remove(cml);
}
/**
* Removes all connections which are not in current_mbrs
*
* @param current_mbrs
*/
public void retainAll(Collection current_mbrs) {
if(current_mbrs == null)
return;
Map copy=null;
lock.lock();
try {
copy=new HashMap<>(conns);
conns.keySet().retainAll(current_mbrs);
}
finally {
lock.unlock();
}
copy.keySet().removeAll(current_mbrs);
for(Iterator> i = copy.entrySet().iterator();i.hasNext();) {
Entry e = i.next();
Util.close(e.getValue());
}
copy.clear();
}
public void start() throws Exception {
if(reaper != null) {
reaper.start();
}
}
public void stop() {
if(reaper != null)
reaper.stop();
lock.lock();
try {
for(Iterator> i = conns.entrySet().iterator();i.hasNext();) {
Entry e = i.next();
Util.close(e.getValue());
}
clear();
}
finally {
lock.unlock();
}
conn_listeners.clear();
}
protected void clear() {
lock.lock();
try {
conns.clear();
}
finally {
lock.unlock();
}
}
protected void notifyConnectionClosed(Address address) {
for(ConnectionMapListener l:conn_listeners) {
l.connectionClosed(address);
}
}
protected void notifyConnectionOpened(Address address, V conn) {
for(ConnectionMapListener l:conn_listeners)
l.connectionOpened(address, conn);
}
class Reaper implements Runnable {
private Thread thread;
public synchronized void start() {
if(thread == null || !thread.isAlive()) {
thread=factory.newThread(new Reaper(), "Reaper");
thread.start();
}
}
public synchronized void stop() {
if(thread != null && thread.isAlive()) {
thread.interrupt();
try {
thread.join(Global.THREAD_SHUTDOWN_WAIT_TIME);
}
catch(InterruptedException ignored) {
}
}
thread=null;
}
public void run() {
while(!Thread.currentThread().isInterrupted()) {
lock.lock();
try {
for(Iterator> it=conns.entrySet().iterator();it.hasNext();) {
Entry entry=it.next();
V c=entry.getValue();
if(c.isExpired(System.nanoTime())) {
Util.close(c);
it.remove();
}
}
}
finally {
lock.unlock();
}
Util.sleep(reaperInterval);
}
}
}
public interface ConnectionMapListener {
public void connectionClosed(Address address);
public void connectionOpened(Address address, V conn);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy