Java tutorial
/* * 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.lang.StringUtils; 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.google.code.fqueue.util.JVMMonitor; 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; /** * MemcachedFQueue Memcached??key??? * * @author sunli * @date 2011-5-11 * @version $Id$ */ 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 // 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; } } // ???? if (keystring.startsWith("monitor")) { try { // size|bbs // size????????? String[] clientInfo = QueueClient.parse(keystring, '|'); if (clientInfo.length < 2) { return null; } String items = clientInfo[1]; StringBuilder stats = new StringBuilder(); if (items != null) { String[] itemList = StringUtils.split(items, ","); for (int i = 0, len = itemList.length; i < len; i++) { if (i > 0) { stats.append("\r\n"); } String data = JVMMonitor.getMonitorStats(itemList[i]); stats.append(data); } } else { stats.append("need items"); } LocalCacheElement element = new LocalCacheElement(keystring, 0, 0, 0); element.setData(stats.toString().getBytes()); return element; } catch (Exception e) { log.error("monitor " + keystring + "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); } }