com.quancheng.saluki.core.registry.internal.AbstractRegistry.java Source code

Java tutorial

Introduction

Here is the source code for com.quancheng.saluki.core.registry.internal.AbstractRegistry.java

Source

/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the
 * confidential and proprietary information of Quancheng-ec.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Quancheng-ec.com.
 */
package com.quancheng.saluki.core.registry.internal;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;

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

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.quancheng.saluki.core.common.Constants;
import com.quancheng.saluki.core.common.GrpcURL;
import com.quancheng.saluki.core.common.GrpcURLUtils;
import com.quancheng.saluki.core.common.NamedThreadFactory;
import com.quancheng.saluki.core.registry.NotifyListener;
import com.quancheng.saluki.core.registry.Registry;

/**
 * @author shimingliu 20161214 ?1:55:28
 * @version AbstractRegistry1.java, v 0.0.1 20161214 ?1:55:28 shimingliu
 */
public abstract class AbstractRegistry implements Registry {

    protected final Logger logger = LoggerFactory.getLogger(getClass());
    private final GrpcURL registryUrl;
    private final Set<GrpcURL> registered = Sets.newConcurrentHashSet();
    private final ConcurrentMap<GrpcURL, Set<NotifyListener.NotifyServiceListener>> subscribed = Maps
            .newConcurrentMap();
    private final ConcurrentMap<GrpcURL, Map<NotifyListener.NotifyServiceListener, List<GrpcURL>>> notified = Maps
            .newConcurrentMap();
    private final ExecutorService notifyExecutor;
    private final int cpus = Runtime.getRuntime().availableProcessors();

    public AbstractRegistry(GrpcURL registryUrl) {
        if (registryUrl == null) {
            throw new IllegalArgumentException("registry url == null");
        }
        this.registryUrl = registryUrl;
        this.notifyExecutor = Executors.newFixedThreadPool(cpus * 3,
                new NamedThreadFactory("SalukiNotifyListener.NotifyServiceListener", true));
    }

    public int getCpus() {
        return cpus;
    }

    public GrpcURL getRegistryUrl() {
        return registryUrl;
    }

    public Set<GrpcURL> getRegistered() {
        return registered;
    }

    public Map<GrpcURL, Set<NotifyListener.NotifyServiceListener>> getSubscribed() {
        return subscribed;
    }

    public Map<GrpcURL, Map<NotifyListener.NotifyServiceListener, List<GrpcURL>>> getNotified() {
        return notified;
    }

    public List<GrpcURL> discover(GrpcURL url) {
        String[] keys = new String[] { Constants.ASYNC_KEY, Constants.GENERIC_KEY, Constants.TIMEOUT };
        url = url.removeParameters(keys);
        List<GrpcURL> result = new ArrayList<GrpcURL>();
        Map<NotifyListener.NotifyServiceListener, List<GrpcURL>> notifiedUrls = getNotified().get(url);
        if (notifiedUrls != null && notifiedUrls.size() > 0) {
            for (List<GrpcURL> urls : notifiedUrls.values()) {
                for (GrpcURL u : urls) {
                    result.add(u);
                }
            }
        } else {
            final AtomicReference<List<GrpcURL>> reference = new AtomicReference<List<GrpcURL>>();
            NotifyListener.NotifyServiceListener listener = new NotifyListener.NotifyServiceListener() {

                public void notify(List<GrpcURL> urls) {
                    reference.set(urls);
                }
            };
            subscribe(url, listener); // ??notify??
            List<GrpcURL> urls = reference.get();
            if (urls != null && urls.size() > 0) {
                for (GrpcURL u : urls) {
                    result.add(u);
                }
            }
        }
        return result;
    }

    public void register(GrpcURL url) {
        if (url == null) {
            throw new IllegalArgumentException("register url == null");
        }
        if (logger.isInfoEnabled()) {
            logger.info("Register: " + url);
        }
        registered.add(url);
    }

    public void unregister(GrpcURL url) {
        if (url == null) {
            throw new IllegalArgumentException("unregister url == null");
        }
        if (logger.isInfoEnabled()) {
            logger.info("Unregister: " + url);
        }
        registered.remove(url);
    }

    public void subscribe(GrpcURL url, NotifyListener.NotifyServiceListener listener) {
        if (url == null) {
            throw new IllegalArgumentException("subscribe url == null");
        }
        if (listener == null) {
            throw new IllegalArgumentException("subscribe listener == null");
        }
        String[] keys = new String[] { Constants.ASYNC_KEY, Constants.GENERIC_KEY, Constants.TIMEOUT };
        url = url.removeParameters(keys);
        if (logger.isInfoEnabled()) {
            logger.info("Subscribe: " + url);
        }
        Set<NotifyListener.NotifyServiceListener> listeners = subscribed.get(url);
        if (listeners == null) {
            subscribed.putIfAbsent(url, Sets.newConcurrentHashSet());
            listeners = subscribed.get(url);
        }
        listeners.add(listener);
    }

    public void unsubscribe(GrpcURL url, NotifyListener.NotifyServiceListener listener) {
        if (url == null) {
            throw new IllegalArgumentException("unsubscribe url == null");
        }
        if (listener == null) {
            throw new IllegalArgumentException("unsubscribe listener == null");
        }
        if (logger.isInfoEnabled()) {
            logger.info("Unsubscribe: " + url);
        }
        Set<NotifyListener.NotifyServiceListener> listeners = subscribed.get(url);
        if (listeners != null) {
            listeners.remove(listener);
        }
    }

    protected void notify(List<GrpcURL> providerUrls) {
        if (providerUrls == null || providerUrls.isEmpty())
            return;
        for (Map.Entry<GrpcURL, Set<NotifyListener.NotifyServiceListener>> entry : getSubscribed().entrySet()) {
            GrpcURL subscribedUrl = entry.getKey();
            if (!GrpcURLUtils.isMatch(subscribedUrl, providerUrls.get(0))) {
                continue;
            }
            Set<NotifyListener.NotifyServiceListener> listeners = entry.getValue();
            if (listeners != null) {
                for (NotifyListener.NotifyServiceListener listener : listeners) {
                    notify(subscribedUrl, listener, providerUrls);
                }
            }
        }
    }

    protected void notify(GrpcURL subscribedUrl, NotifyListener.NotifyServiceListener listener,
            List<GrpcURL> providerUrls) {
        addNotified(subscribedUrl, listener, providerUrls);
        notifyExecutor.submit(new Runnable() {

            @Override
            public void run() {
                listener.notify(providerUrls);
            }
        });
    }

    protected void recover() throws Exception {
        // register
        Set<GrpcURL> recoverRegistered = Sets.newHashSet(getRegistered());
        if (!recoverRegistered.isEmpty()) {
            if (logger.isInfoEnabled()) {
                logger.info("Recover register url " + recoverRegistered);
            }
            for (GrpcURL url : recoverRegistered) {
                register(url);
            }
        }
        // subscribe
        Map<GrpcURL, Set<NotifyListener.NotifyServiceListener>> recoverSubscribed = Maps
                .newHashMap(getSubscribed());
        if (!recoverSubscribed.isEmpty()) {
            if (logger.isInfoEnabled()) {
                logger.info("Recover subscribe url " + recoverSubscribed.keySet());
            }
            for (Map.Entry<GrpcURL, Set<NotifyListener.NotifyServiceListener>> entry : recoverSubscribed
                    .entrySet()) {
                GrpcURL url = entry.getKey();
                for (NotifyListener.NotifyServiceListener listener : entry.getValue()) {
                    subscribe(url, listener);
                }
            }
        }
    }

    private void addNotified(GrpcURL subscribedUrl, NotifyListener.NotifyServiceListener listener,
            List<GrpcURL> providerUrls) {
        Map<NotifyListener.NotifyServiceListener, List<GrpcURL>> notifiedUrlMap = notified.get(subscribedUrl);
        List<GrpcURL> notifiedUrlList;
        if (notifiedUrlMap == null) {
            notifiedUrlMap = Maps.newConcurrentMap();
            notifiedUrlList = providerUrls;
        } else {
            notifiedUrlList = notifiedUrlMap.get(listener);
            if (notifiedUrlList == null) {
                notifiedUrlList = Lists.newArrayList();
            }
            notifiedUrlList.addAll(providerUrls);
        }
        notifiedUrlMap.putIfAbsent(listener, notifiedUrlList);
        notified.putIfAbsent(subscribedUrl, notifiedUrlMap);
    }
}