Package com.hellblazer.gossip.configuration

Source Code of com.hellblazer.gossip.configuration.GossipConfiguration

/**
* (C) Copyright 2010 Hal Hildebrand, All Rights Reserved
*
* 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.
*/

package com.hellblazer.gossip.configuration;

import static com.hellblazer.gossip.Gossip.DEFAULT_CLEANUP_CYCLES;
import static com.hellblazer.gossip.Gossip.DEFAULT_HEARTBEAT_CYCLE;

import java.lang.Thread.UncaughtExceptionHandler;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.uuid.Generators;
import com.hellblazer.gossip.Gossip;
import com.hellblazer.gossip.SystemView;
import com.hellblazer.gossip.UdpCommunications;
import com.hellblazer.utils.Base64Coder;
import com.hellblazer.utils.Utils;
import com.hellblazer.utils.fd.FailureDetectorFactory;
import com.hellblazer.utils.fd.impl.AdaptiveFailureDetectorFactory;

/**
* A configuration bean for constructing Gossip instances
*
* @author hhildebrand
*
*/
public class GossipConfiguration {
    private static final Logger    log                     = LoggerFactory.getLogger(GossipConfiguration.class);

    public int                     cleanupCycles           = DEFAULT_CLEANUP_CYCLES;
    public int                     commThreads             = 2;
    public InetSocketAddress       endpoint                = new InetSocketAddress(
                                                                                   "localhost",
                                                                                   0);
    public FailureDetectorFactory  fdFactory;
    public int                     gossipInterval          = 3;
    public TimeUnit                gossipUnit              = TimeUnit.SECONDS;
    public int                     heartbeatCycle          = DEFAULT_HEARTBEAT_CYCLE;
    public String                  hmac;
    public String                  hmacKey;
    public String                  networkInterface;
    public long                    quarantineDelay         = TimeUnit.SECONDS.toMillis(30);
    public int                     redundancy              = 3;
    public int                     receiveBufferMultiplier = UdpCommunications.DEFAULT_RECEIVE_BUFFER_MULTIPLIER;
    public List<InetSocketAddress> seeds                   = Collections.emptyList();
    public int                     sendBufferMultiplier    = UdpCommunications.DEFAULT_SEND_BUFFER_MULTIPLIER;
    public long                    unreachableDelay        = (int) TimeUnit.DAYS.toMillis(2);

    public Gossip construct() throws SocketException {
        Random entropy = new Random();
        UdpCommunications comms = constructUdpComms();
        SystemView view = new SystemView(entropy, comms.getLocalAddress(),
                                         seeds, quarantineDelay,
                                         unreachableDelay);
        return new Gossip(Generators.timeBasedGenerator(), comms, view,
                          getFdFactory(), entropy, gossipInterval, gossipUnit,
                          cleanupCycles, heartbeatCycle, redundancy);
    }

    public UdpCommunications constructUdpComms() throws SocketException {
        ThreadFactory threadFactory = new ThreadFactory() {
            int i = 0;

            @Override
            public Thread newThread(Runnable runnable) {
                Thread daemon = new Thread(runnable,
                                           String.format("UDP Comms[%s]", i++));
                daemon.setDaemon(true);
                daemon.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
                    @Override
                    public void uncaughtException(Thread t, Throwable e) {
                        UdpCommunications.log.error(String.format("Uncaught exception on dispatcher %s",
                                                                  t), e);
                    }
                });
                return daemon;
            }
        };
        return new UdpCommunications(
                                     getEndpoint(),
                                     Executors.newFixedThreadPool(commThreads,
                                                                  threadFactory),
                                     receiveBufferMultiplier,
                                     sendBufferMultiplier, getMac());
    }

    public InetSocketAddress getEndpoint() throws SocketException {
        if (endpoint.getAddress().isAnyLocalAddress()) {
            if (networkInterface == null) {
                NetworkInterface iface = NetworkInterface.getByIndex(1);
                if (iface == null) {
                    String msg = String.format("Supplied ANY address for endpoint: %s with no networkInterface defined, cannot find network interface 1",
                                               endpoint);
                    log.error(msg);
                    throw new IllegalArgumentException(msg);
                }
                log.info(String.format("Supplied ANY address for endpoint: %s with no networkInterface defined, using %s",
                                       endpoint, iface));
                return new InetSocketAddress(Utils.getAddress(iface),
                                             endpoint.getPort());
            } else {
                NetworkInterface iface = NetworkInterface.getByName(networkInterface);
                if (iface == null) {
                    String msg = String.format("Cannot find network interface: %s ",
                                               networkInterface);
                    log.error(msg);
                    throw new IllegalArgumentException(msg);
                }
                return new InetSocketAddress(Utils.getAddress(iface),
                                             endpoint.getPort());
            }
        }
        return endpoint;
    }

    public FailureDetectorFactory getFdFactory() {
        if (fdFactory == null) {
            long gossipIntervalMillis = gossipUnit.toMillis(gossipInterval);
            fdFactory = new AdaptiveFailureDetectorFactory(
                                                           0.9,
                                                           100,
                                                           0.8,
                                                           2
                                                                   * cleanupCycles
                                                                   * gossipIntervalMillis,
                                                           10,
                                                           gossipIntervalMillis);
        }
        return fdFactory;
    }

    public Mac getMac() {
        if (hmac == null || hmacKey == null) {
            return UdpCommunications.defaultMac();
        }
        Mac mac;
        try {
            mac = Mac.getInstance(hmac);
            mac.init(new SecretKeySpec(Base64Coder.decode(hmacKey), hmac));
        } catch (NoSuchAlgorithmException e) {
            log.error(String.format("Unable to create mac %s", hmac));
            throw new IllegalStateException(
                                            String.format("Unable to create mac %s",
                                                          hmac));
        } catch (InvalidKeyException e) {
            log.error(String.format("Invalid key %s for mac %s", hmacKey, hmac));
            throw new IllegalStateException(
                                            String.format("Invalid key %s for mac %s",
                                                          hmacKey, hmac));
        }
        return mac;
    }
}
TOP

Related Classes of com.hellblazer.gossip.configuration.GossipConfiguration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.