org.jgroups.blocks.AbstractConnectionMap Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including
all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and
Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
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