com.alibaba.doris.common.config.ConfigManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.alibaba.doris.common.config.ConfigManagerImpl.java

Source

/**
 * Project: doris.config.client-1.0-SNAPSHOT File Created at 2011-4-26 $Id: ConfigManagerImpl.java 97082 2011-06-27
 * 07:15:00Z mian.hem $ Copyright 1999-2100 Alibaba.com Corporation Limited. All rights reserved. This software is the
 * confidential and proprietary information of Alibaba Company. ("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 Alibaba.com.
 */
package com.alibaba.doris.common.config;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.doris.common.adminservice.AdminServiceFactory;
import com.alibaba.doris.common.adminservice.CommonConfigService;
import com.alibaba.doris.common.adminservice.connenctor.AdminConnector;
import com.alibaba.doris.common.util.PropertiesLoadUtil;

/**
 * ?? 3000ms http ?????? ? <code>ConfigManagerImpl</code><code>ConfigListener</code>
 *  ??????<code>ConfigListener</code>
 * 
 * @see ConfigListener
 * @see ConfigConnector
 * @author mianhe
 */
public class ConfigManagerImpl implements ConfigManager {

    private static final Log logger = LogFactory.getLog(ConfigManagerImpl.class);

    // configuration location
    private String location;
    private long interval = 3000;
    // ???
    private volatile boolean stopped = false;

    // ???
    private volatile boolean initialized = false;

    private final Object lock = new Object();

    private volatile List<ConfigListener> configListeners = new ArrayList<ConfigListener>();

    private Properties properties = null;
    // ?????
    private Thread fetchThread;

    private CommonConfigService commonConfigService = AdminServiceFactory.getCommonConfigService();

    private volatile Map<String, String> configurationCache = new ConcurrentHashMap<String, String>();

    private ClientConfiguration clientConfiguration;

    /**
     * ?? ??<code>ConfigConnector</code> ????????
     * 
     * @throws ConfigException ?? <code>ConfigConnector</code> ??
     */
    public void initConfig() throws ConfigException {
        if (initialized) {
            logger.warn("ConfigManagerImpl is already initialized!");
            return;
        }

        Properties defaultProperties = loadDefaultConfig();

        // propertieslocation??properties?String
        if (properties == null) {
            this.properties = PropertiesLoadUtil.loadProperties(location);
        } else {
            Properties tempProperties = new Properties();
            Enumeration<Object> keysEnum = properties.keys();
            while (keysEnum.hasMoreElements()) {
                Object key = keysEnum.nextElement();
                if (key instanceof String) {
                    tempProperties.setProperty((String) key, properties.get(key).toString());
                } else {
                    throw new ConfigException(String.format(
                            "The key[%s]'type of client properties file must be 'String',not support the type:%s",
                            key, key.getClass()));
                }
            }
            this.properties = tempProperties;
        }

        if (defaultProperties != null) {

            defaultProperties.putAll(properties);

            properties = defaultProperties;
        }

        loadClientConfiguration(properties);
        // initialize the connector
        AdminConnector adminConnector = AdminConnector.getInstance();
        adminConnector.init(properties);// this init must be execute when client initialized

        if (!adminConnector.isConnected()) {
            String mainAdminUrl = properties.getProperty("doris.config.adminserver.main.url");
            String backupAdminUrl = properties.getProperty("doris.config.adminserver.backup.url");

            throw new ConfigException(
                    "admin server is not available,main admin:" + mainAdminUrl + ",backup admin:" + backupAdminUrl);
        }

        String autoFetchProp = properties.getProperty("doris.admin.config.autofetch.enable", "true");
        boolean autoFetchEnable = Boolean.parseBoolean(autoFetchProp);

        if (autoFetchEnable) {
            // the interval to dectect configuration changes.
            String intervalConfig = properties.getProperty("doris.config.fetch.interval");
            if (StringUtils.isEmpty(intervalConfig)) {
                throw new IllegalArgumentException("confg 'doris.config.fetch.interval' is not valid.");
            }
            this.interval = Long.parseLong(intervalConfig.trim());

            // start fetch thread.
            fetchThread = new Thread(new ConfigFetchTask(), "doris-config-fetcher");
            fetchThread.setDaemon(true);
            fetchThread.start();
        }

        // initialize completed.
        initialized = true;
    }

    public Properties loadDefaultConfig() {
        return null;
    }

    private void loadClientConfiguration(Properties property) {
        clientConfiguration = new ClientConfiguration();
        // To get the time out value;
        String timeout = property.getProperty("doris.config.client.operation.timeout");
        if (StringUtils.isNotBlank(timeout)) {
            clientConfiguration.setTimeoutOfOperation(NumberUtils.toLong(timeout));
        }
    }

    public ClientConfiguration getClientConfiguration() {
        return this.clientConfiguration;
    }

    /**
     * ??
     * 
     * @throws ConfigException
     */
    public void close() throws ConfigException {
        if (logger.isInfoEnabled()) {
            logger.info("Closing config fetcher...");
        }

        stopped = true;
        initialized = false;
        fetchThread.interrupt();
    }

    private class ConfigFetchTask implements Runnable {

        public void run() {
            try {
                while (!stopped) {
                    try {
                        Thread.sleep(interval);
                    } catch (Exception e) {
                        logger.warn("Exception when the key fetch task sleep: " + e.toString());
                    }

                    if (stopped) {
                        return;
                    }

                    try {
                        fetch(null, false);
                    } catch (Exception e) {
                        logger.error("Exception when fetch doris config: ", e);
                    }
                }
            } finally {
                logger.warn("the key fetch thread exit!");
            }
        }
    }

    /**
     * ???
     * 
     * @param b
     */
    private void fetch(Map<String, String> map, boolean forceRefresh) {
        synchronized (lock) {
            Map<String, String> configurations = null;
            if (map == null) {
                if (this.configListeners == null || this.configListeners.isEmpty()) {
                    return;
                }
                Map<String, Long> actionVersions = new HashMap<String, Long>();
                for (ConfigListener confLstnr : configListeners) {
                    if (forceRefresh) {
                        actionVersions.put(confLstnr.getConfigListenerName(), null);
                    } else {
                        actionVersions.put(confLstnr.getConfigListenerName(), confLstnr.getConfigVersion());
                    }
                }

                if (forceRefresh) {
                    List<String> actions = new ArrayList<String>(actionVersions.keySet());
                    configurations = commonConfigService.getConfig(actions);
                } else {
                    configurations = commonConfigService.getConfig(actionVersions);
                }
            } else {
                configurations = map;
            }

            for (ConfigListener confLstnr : configListeners) {
                String lsnerName = confLstnr.getConfigListenerName();
                String conf = configurations.get(lsnerName);
                if (StringUtils.isNotEmpty(conf) && !"null".equalsIgnoreCase(conf)) {
                    configurationCache.put(lsnerName, conf);
                    confLstnr.onConfigChange(conf);
                }
            }
        }
    }

    public void refreshConfig() {
        fetch(null, true);
    }

    public void refreshConfig(Map<String, String> configurations) {
        fetch(configurations, false);
    }

    /**
     * ?????
     * 
     * @param configManager ????Doris??
     * @throws IllegalStateException ?
     */
    public void addConfigListener(ConfigListener configListener) {
        if (this.initialized) {
            this.configListeners.add(configListener);
            fetch(null, true);
        } else {
            throw new IllegalStateException("the configuration manager is not initialized yet.");
        }
    }

    /**
     * ??????
     * 
     * @param configManager ????Doris??
     * @throws IllegalStateException ?
     */
    public void removeConfigListener(ConfigListener configManager) {
        if (this.initialized) {
            this.configListeners.remove(configManager);
        } else {
            throw new IllegalStateException("the configuration manager is not initialized yet.");
        }
    }

    /**
     * set config properties.
     * @since 0.1.4
     */
    public void setConfigProperties(Properties properties) {
        this.properties = properties;
    }

    /**
     * set config location, local or remote.
     */
    public void setConfigLocation(String location) {
        this.location = location;
    }

    /**
     * get config properties.
     */
    public Properties getProperties() {
        return properties;
    }

    public String getConfig(String actionName) {
        return getConfig(actionName, null);
    }

    public String getConfig(String actionName, Long version) {
        Map<String, Long> paras = new HashMap<String, Long>();
        paras.put(actionName, version);
        Map<String, String> rsltMap = commonConfigService.getConfig(paras);
        return rsltMap.get(actionName);
    }

    public String getCachedConfig(String actionName) {
        return configurationCache.get(actionName);
    }

}