All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgroups.stack.RouterStubManager Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS 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).

There is a newer version: 33.0.2.Final
Show newest version

package org.jgroups.stack;

import org.jgroups.Address;
import org.jgroups.Event;
import org.jgroups.PhysicalAddress;
import org.jgroups.annotations.GuardedBy;
import org.jgroups.logging.Log;
import org.jgroups.logging.LogFactory;
import org.jgroups.util.TimeScheduler;

import java.net.InetAddress;
import java.util.List;
import java.util.concurrent.*;

/**
 * Manages a list of RouterStubs (e.g. health checking, reconnecting etc.
 * @author Vladimir Blagojevic
 * @author Bela Ban
 */
public class RouterStubManager implements RouterStub.ConnectionListener {

    @GuardedBy("reconnectorLock")
    private final ConcurrentMap> futures=new ConcurrentHashMap<>();
    private final List stubs;
    
    private final Protocol owner;
    private final TimeScheduler timer;
    private final String channelName;
    private final Address logicalAddress;
    private final long interval;

    protected final Log log;

    public RouterStubManager(Protocol owner, String channelName, Address logicalAddress, long interval) {
        this.owner = owner;
        this.stubs = new CopyOnWriteArrayList<>();
        this.log = LogFactory.getLog(owner.getClass());     
        this.timer = owner.getTransport().getTimer();
        this.channelName = channelName;
        this.logicalAddress = logicalAddress;
        this.interval = interval;
    }
    
    private RouterStubManager(Protocol p) {
       this(p,null,null,0L);
    }
    
    public List getStubs(){
        return stubs;
    }
    
    public RouterStub createAndRegisterStub(String routerHost, int routerPort, InetAddress bindAddress) {
        RouterStub s = new RouterStub(routerHost,routerPort,bindAddress,this);
        unregisterAndDestroyStub(s);
        stubs.add(s);   
        return s;
    }
    
    public void registerStub(RouterStub s) {        
        unregisterAndDestroyStub(s);
        stubs.add(s);           
    }
    
    public RouterStub unregisterStub(final RouterStub stub) {
        if(stub == null)
            throw new IllegalArgumentException("Cannot remove null stub");
        RouterStub found=null;
        for (RouterStub s: stubs) {
            if (s.equals(stub)) {
                found=s;
                break;
            }
        }
        if(found != null)
            stubs.remove(found);
        return found;
    }
    
    public boolean unregisterAndDestroyStub(final RouterStub stub) {
        RouterStub unregisteredStub = unregisterStub(stub);
        if(unregisteredStub != null) {
            unregisteredStub.destroy();
            return true;
        }
        return false;
    }
    
    public void disconnectStubs() {
        for (RouterStub stub : stubs) {
            try {
                stub.disconnect(channelName, logicalAddress);                
            } catch (Exception e) {
            }
        }       
    }
    
    public void destroyStubs() {
        for (RouterStub s : stubs) {
            stopReconnecting(s);
            s.destroy();            
        }
        stubs.clear();
    }

    public void startReconnecting(final RouterStub stub) {
        Future f = futures.remove(stub);
        if (f != null)
            f.cancel(true);

        final Runnable reconnector = new Runnable() {
            public void run() {
                try {
                    if (log.isTraceEnabled()) log.trace("Reconnecting " + stub);
                    String logical_name = org.jgroups.util.UUID.get(logicalAddress);
                    PhysicalAddress physical_addr = (PhysicalAddress) owner.down(new Event(
                      Event.GET_PHYSICAL_ADDRESS, logicalAddress));
                    stub.connect(channelName, logicalAddress, logical_name, physical_addr);
                    if (log.isTraceEnabled()) log.trace("Reconnected " + stub);
                } catch (Throwable ex) {
                    if (log.isWarnEnabled())
                        log.warn("failed reconnecting stub to GR at "+ stub.getGossipRouterAddress() + ": " + ex);
                }
            }

            public String toString() {
                return RouterStubManager.class.getSimpleName() + ": Reconnector";
            }
        };
        f = timer.scheduleWithFixedDelay(reconnector, 0, interval, TimeUnit.MILLISECONDS);
        if(f != null && stub != null)
            futures.putIfAbsent(stub, f);
    }

    public void stopReconnecting(final RouterStub stub) {
        Future f = futures.get(stub);
        if (f != null) {
            f.cancel(true);
            futures.remove(stub);
        }

        final Runnable pinger = new Runnable() {
            public void run() {
                try {
                    if(log.isTraceEnabled()) log.trace("Pinging " + stub);
                    stub.checkConnection();
                    if(log.isTraceEnabled()) log.trace("Pinged " + stub);
                } catch (Throwable ex) {
                    if (log.isWarnEnabled())
                        log.warn("failed pinging stub, GR at " + stub.getGossipRouterAddress()+ ": " + ex);
                }
            }

            public String toString() {
                return RouterStubManager.class.getSimpleName() + ": Pinger";
            }
        };
        f = timer.scheduleWithFixedDelay(pinger, 1000, interval, TimeUnit.MILLISECONDS);
        futures.putIfAbsent(stub, f);
    }
   

    public void connectionStatusChange(RouterStub stub, RouterStub.ConnectionStatus newState) {
        if (newState == RouterStub.ConnectionStatus.CONNECTION_BROKEN) {
            stub.interrupt();
            stub.destroy();
            startReconnecting(stub);
        } else if (newState == RouterStub.ConnectionStatus.CONNECTED) {
            stopReconnecting(stub);
        } else if (newState == RouterStub.ConnectionStatus.DISCONNECTED) {
            // wait for disconnect ack;
            try {
                stub.join(interval);
            } catch (InterruptedException e) {
            }
        }
    }
    
    public static RouterStubManager emptyGossipClientStubManager(Protocol p) {
        return new RouterStubManager(p);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy