cn.leancloud.diamond.client.processor.LocalConfigInfoProcessor.java Source code

Java tutorial

Introduction

Here is the source code for cn.leancloud.diamond.client.processor.LocalConfigInfoProcessor.java

Source

/*
 * (C) 2007-2012 Alibaba Group Holding Limited.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 * Authors:
 *   leiwen <chrisredfield1985@126.com> , boyan <killme2008@gmail.com>
 */
package cn.leancloud.diamond.client.processor;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import cn.leancloud.diamond.io.watch.WatchService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import cn.leancloud.diamond.common.Constants;
import cn.leancloud.diamond.configinfo.CacheData;
import cn.leancloud.diamond.io.FileSystem;
import cn.leancloud.diamond.io.Path;
import cn.leancloud.diamond.io.watch.StandardWatchEventKind;
import cn.leancloud.diamond.io.watch.WatchEvent;
import cn.leancloud.diamond.io.watch.WatchKey;
import cn.leancloud.diamond.utils.FileUtils;

public class LocalConfigInfoProcessor {
    private static final Log log = LogFactory.getLog(LocalConfigInfoProcessor.class);
    private ScheduledExecutorService singleExecutor = Executors.newSingleThreadScheduledExecutor();;

    private final Map<String/* filePath */, Long/* version */> existFiles = new HashMap<String, Long>();

    private volatile boolean isRun;
    private String rootPath = null;

    /**
     * ??
     * 
     * @param cacheData
     * @param force
     *            ???null
     * @return
     * @throws IOException
     */
    public String getLocalConfigureInfomation(CacheData cacheData, boolean force) throws IOException {
        String filePath = getFilePath(cacheData.getDataId(), cacheData.getGroup());
        if (!existFiles.containsKey(filePath)) {
            if (cacheData.isUseLocalConfigInfo()) {
                cacheData.setLastModifiedHeader(Constants.NULL);
                cacheData.setMd5(Constants.NULL);
                cacheData.setLocalConfigInfoFile(null);
                cacheData.setLocalConfigInfoVersion(0L);
                cacheData.setUseLocalConfigInfo(false);
            }
            return null;
        }
        if (force) {
            log.info("???, dataId:" + cacheData.getDataId() + ", group:"
                    + cacheData.getGroup());

            String content = FileUtils.getFileContent(filePath);
            return content;
        }
        // ???null
        if (!filePath.equals(cacheData.getLocalConfigInfoFile())
                || existFiles.get(filePath) != cacheData.getLocalConfigInfoVersion()) {
            String content = FileUtils.getFileContent(filePath);
            cacheData.setLocalConfigInfoFile(filePath);
            cacheData.setLocalConfigInfoVersion(existFiles.get(filePath));
            cacheData.setUseLocalConfigInfo(true);

            if (log.isInfoEnabled()) {
                log.info("????, dataId:" + cacheData.getDataId() + ", group:"
                        + cacheData.getGroup());
            }

            return content;
        } else {
            cacheData.setUseLocalConfigInfo(true);

            if (log.isInfoEnabled()) {
                log.debug("????, dataId:" + cacheData.getDataId() + ", group:"
                        + cacheData.getGroup());
            }

            return null;
        }
    }

    String getFilePath(String dataId, String group) {
        StringBuilder filePathBuilder = new StringBuilder();
        filePathBuilder.append(rootPath).append("/").append(Constants.BASE_DIR).append("/").append(group)
                .append("/").append(dataId);
        File file = new File(filePathBuilder.toString());
        return file.getAbsolutePath();
    }

    public synchronized void start(String rootPath) {
        if (this.isRun) {
            return;
        }
        this.rootPath = rootPath;
        this.isRun = true;
        if (this.singleExecutor == null || singleExecutor.isTerminated()) {
            singleExecutor = Executors.newSingleThreadScheduledExecutor();
        }
        initDataDir(rootPath);
        startCheckLocalDir(rootPath);
    }

    private void initDataDir(String rootPath) {
        try {
            File flie = new File(rootPath);
            flie.mkdir();
        } catch (Exception e) {
        }
    }

    public synchronized void stop() {
        if (!this.isRun) {
            return;
        }
        this.isRun = false;
        this.singleExecutor.shutdownNow();
        this.singleExecutor = null;
    }

    private void startCheckLocalDir(final String filePath) {
        final WatchService watcher = FileSystem.getDefault().newWatchService();

        Path path = new Path(new File(filePath));
        // 
        watcher.register(path, true, StandardWatchEventKind.ENTRY_CREATE, StandardWatchEventKind.ENTRY_DELETE,
                StandardWatchEventKind.ENTRY_MODIFY);
        // ?check
        checkAtFirst(watcher);
        singleExecutor.execute(new Runnable() {
            public void run() {
                log.debug(">>>>>>?<<<<<<");
                // ?
                while (isRun) {
                    // ?
                    WatchKey key;
                    try {
                        key = watcher.take();
                    } catch (InterruptedException x) {
                        continue;
                    }
                    // reset,??
                    if (!processEvents(key)) {
                        log.error("reset unvalid,?");
                        break;
                    }
                }
                log.debug(">>>>>><<<<<<");
                watcher.close();

            }

        });
    }

    private void checkAtFirst(final WatchService watcher) {
        watcher.check();
        WatchKey key = null;
        while ((key = watcher.poll()) != null) {
            processEvents(key);
        }
    }

    /**
     * ??
     * 
     * @param key
     * @return
     */
    @SuppressWarnings({ "unchecked" })
    private boolean processEvents(WatchKey key) {
        /**
         * ??
         */
        for (WatchEvent<?> event : key.pollEvents()) {
            // 
            // WatchEvent.Kind<?> kind = event.kind();

            // context?path
            WatchEvent<Path> ev = (WatchEvent<Path>) event;
            Path eventPath = ev.context();

            String realPath = eventPath.getAbsolutePath();
            if (ev.kind() == StandardWatchEventKind.ENTRY_CREATE
                    || ev.kind() == StandardWatchEventKind.ENTRY_MODIFY) {

                String grandpaDir = null;
                try {
                    grandpaDir = FileUtils.getGrandpaDir(realPath);
                } catch (Exception e1) {

                }
                if (!Constants.BASE_DIR.equals(grandpaDir)) {
                    log.error(": " + realPath);
                    continue;
                }
                existFiles.put(realPath, System.currentTimeMillis());
                if (log.isInfoEnabled()) {
                    log.info(realPath + "");
                }
            } else if (ev.kind() == StandardWatchEventKind.ENTRY_DELETE) {
                String grandpaDir = null;
                try {
                    grandpaDir = FileUtils.getGrandpaDir(realPath);
                } catch (Exception e1) {

                }
                if (Constants.BASE_DIR.equals(grandpaDir)) {
                    // 
                    existFiles.remove(realPath);
                    if (log.isInfoEnabled()) {
                        log.info(realPath + "");
                    }
                } else {
                    // 
                    Set<String> keySet = new HashSet<String>(existFiles.keySet());
                    for (String filePath : keySet) {
                        if (filePath.startsWith(realPath)) {
                            existFiles.remove(filePath);
                            if (log.isInfoEnabled()) {
                                log.info(filePath + "");
                            }
                        }
                    }

                }
            }
        }
        return key.reset();
    }
}