Package com.google.code.fqueue.memcached.storage

Source Code of com.google.code.fqueue.memcached.storage.FSStorage

/*
*  Copyright 2011 sunli [sunli1223@gmail.com][weibo.com@sunli1223]
*
*  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.google.code.fqueue.memcached.storage;

import java.io.IOException;
import java.util.AbstractQueue;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.code.fqueue.FQueue;
import com.google.code.fqueue.exception.ConfigException;
import com.google.code.fqueue.util.Config;
import com.thimbleware.jmemcached.LocalCacheElement;
import com.thimbleware.jmemcached.protocol.exceptions.ClientException;
import com.thimbleware.jmemcached.protocol.exceptions.DatabaseException;
import com.thimbleware.jmemcached.storage.CacheStorage;

/**
* Memcached的缓存存储实现,底层通过FQueue实现。 通过Memcached协议的key来实现二次协议
*
* @author sunli
* @date 2011-5-11
* @version $Id: FSStorage.java 2 2011-07-31 12:25:36Z sunli1223@gmail.com $
*/
public class FSStorage implements CacheStorage<String, LocalCacheElement> {
    /**
     * 存储所有的队列服务
     */
    private Map<String, AbstractQueue<byte[]>> queuemMap = new ConcurrentHashMap<String, AbstractQueue<byte[]>>();
    private final ReentrantLock lock = new ReentrantLock();
    private final static Log log = LogFactory.getLog(FSStorage.class);
    /**
     * 每个队列服务的单个日至存储的大小限制 配置文件中的单位为M
     */
    private final static int logSize = 1024 * 1024 * Integer.parseInt(Config.getSetting("logsize"));
    /**
     * 数据存储路径
     */
    private final static String dbpath = Config.getSetting("path").trim();
    /**
     * 安全验证map
     */
    private static Map<String, String> authorizationMap = new ConcurrentHashMap<String, String>(20);
    static {
        loadAuthorization();
    }

    private static void loadAuthorization() {
        String line = Config.getSetting("authorization");
        if (line != null) {
            if (line.indexOf("_") != -1) {
                log.error("权限配置不能包含'_'符号");
            }
            String[] group = line.split("@@");
            for (int i = 0, groupLen = group.length; i < groupLen; i++) {
                String[] item = group[i].split("\\|");
                if (item.length == 2) {
                    authorizationMap.put(item[0], item[1]);
                }
            }
        }
    }

    /**
     * 重新加载安全验证数据,可用于在线动态增加队列,修改密码等操作
     */
    private static void reloadAuthorization() {
        Config.reload();
        loadAuthorization();
    }

    @Override
    public int capacity() {
        return 0;
    }

    @Override
    public void clear() throws DatabaseException, Exception {
    }

    @Override
    public void close() throws IOException {
        for (String key : queuemMap.keySet()) {
            ((FQueue) queuemMap.get(key)).close();
        }
        log.info("close queue");
    }

    /**
     * get方式的二次协议实现
     *
     * @param keystring
     * @return
     * @throws ClientException
     */
    private LocalCacheElement getProtocol(String keystring) throws ClientException {
        // 获取队列中元素的个数
        if (keystring.startsWith("size")) {
            try {
                // size|bbs|pass
                // size操作无密码验证,只需要队列名称正确即可
                String[] clientInfo = QueueClient.parse(keystring, '|');
                if (clientInfo.length < 2 || authorizationMap.containsKey(clientInfo[1]) == false) {
                    return null;
                }
                AbstractQueue<byte[]> sizeQueue = getClientQueue(clientInfo[1]);
                if (sizeQueue == null) {
                    return null;
                }
                int size = sizeQueue.size();
                LocalCacheElement element = new LocalCacheElement(keystring, 0, 0, 0);
                element.setData(String.valueOf(size).getBytes());
                return element;
            } catch (Exception e) {
                log.error("getsize " + keystring + "error", e);
                return null;
            }
        }
        // 清空队列中所有的元素
        if (keystring.startsWith("clear")) {
            try {
                // clear|bbs|pass
                String[] clientInfo = QueueClient.parse(keystring, '|');
                if (clientInfo.length < 3 || valid(clientInfo[1], clientInfo[2]) == false) {
                    throw new ClientException("Authorization error");
                }
                AbstractQueue<byte[]> queue = getClientQueue(clientInfo[1]);
                queue.clear();
                LocalCacheElement element = new LocalCacheElement(keystring, 0, 0, 0);
                element.setData(String.valueOf(queue.size()).getBytes());
                return element;
            } catch (Exception e) {
                log.error("getsize " + keystring + "error", e);
                return null;
            }
        }
        // 重新加载权限信息
        if (keystring.startsWith("reload")) {
            try {
                // reload|bbs|pass
                String[] clientInfo = QueueClient.parse(keystring, '|');
                if (clientInfo.length < 3 || valid(clientInfo[1], clientInfo[2]) == false) {
                    throw new ClientException("Authorization error");
                }
                reloadAuthorization();
                LocalCacheElement element = new LocalCacheElement(keystring, 0, 0, 0);
                element.setData("reloadAuthorization".getBytes());
                return element;
            } catch (ConfigException e) {
                log.error(e.getMessage(), e);
            } catch (Exception e) {
                log.error("reloadAuthorization error", e);
                return null;
            }
        }
        throw new ClientException(keystring + " command Unsupported now");
    }

    @Override
    public LocalCacheElement get(String keystring) {
        try {
            if (keystring.indexOf("_") == -1) {
                return getProtocol(keystring);
            }
            String[] clientInfo = QueueClient.parseWithCache(keystring);
            if (valid(clientInfo[0], clientInfo[1])) {
                byte[] data;
                data = getClientQueue(clientInfo[0]).poll();
                if (data != null) {
                    LocalCacheElement element = new LocalCacheElement(keystring, 0, 0, 0);
                    element.setData(data);
                    return element;
                } else {
                    log.info("queue empty");
                }
            } else {
                log.error("unvalid " + keystring);
                throw new ClientException("Authorization error");
            }
        } catch (Exception e) {
            log.error("get queue " + keystring + " error", e);
            return null;
        }
        return null;
    }

    @Override
    public long getMemoryCapacity() {
        return 0;
    }

    @Override
    public long getMemoryUsed() {
        return 0;
    }

    @Override
    public Set<String> keySet() {
        return null;
    }

    @Override
    public LocalCacheElement put(String keystring, LocalCacheElement e) throws DatabaseException, Exception {
        String[] clientInfo = QueueClient.parseWithCache(keystring);
        if (valid(clientInfo[0], clientInfo[1])) {// 先进行密码验证
            getClientQueue(clientInfo[0]).add(e.getData());
            return null;
        } else {
            throw new ClientException("Authorization error");
        }
    }

    @Override
    public LocalCacheElement putIfAbsent(String keystring, LocalCacheElement e) throws DatabaseException, Exception {
        String[] clientInfo = QueueClient.parseWithCache(keystring);
        if (valid(clientInfo[0], clientInfo[1])) {// 先进行密码验证
            getClientQueue(clientInfo[0]).add(e.getData());
            return null;
        } else {
            throw new ClientException("Authorization error");
        }

    }

    @Override
    public LocalCacheElement remove(String key) throws DatabaseException, Exception {
        return null;
    }

    @Override
    public boolean replace(String keystring, LocalCacheElement old, LocalCacheElement prepend)
            throws DatabaseException, Exception {
        return false;
    }

    @Override
    public LocalCacheElement replace(String key, LocalCacheElement placeHolder) throws DatabaseException, Exception {
        return null;
    }

    @Override
    public long size() {
        return 0;
    }

    private boolean valid(String appid, String pwd) {
        return pwd.equals(authorizationMap.get(appid));
    }

    /**
     * 获取指定名称的队列存储实例 如果不存存在,根据create参数决定是否创建
     *
     * @param name
     * @return
     * @throws Exception
     */
    private AbstractQueue<byte[]> getClientQueue(String name, boolean create) throws Exception {
        AbstractQueue<byte[]> queue = queuemMap.get(name);
        if (queue == null) {
            if (create == true) {
                lock.lock();
                try {
                    queue = queuemMap.get(name);
                    if (queue == null) {
                        queue = new FQueue(dbpath + "/" + name, logSize);
                        queuemMap.put(name, queue);
                    }
                } finally {
                    lock.unlock();
                }
            }
        }
        return queue;
    }

    /**
     * 获取或者创建指定名称的队列存储实例
     *
     * @param name
     * @return
     * @throws Exception
     */
    private AbstractQueue<byte[]> getClientQueue(String name) throws Exception {
        return getClientQueue(name, true);
    }
}
TOP

Related Classes of com.google.code.fqueue.memcached.storage.FSStorage

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.