package com.justdebugit.thrift.pool; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.commons.lang3.tuple.ImmutablePair; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.Lists; import com.justdebugit.fastpool.Pool; import com.justdebugit.thrift.common.LifeCycle; public class MultiPool<T> implements Pool<T>,LifeCycle { private static final LoadBalance DEFAULT_LOAD_BALANCE = new RandomPolicy(); private AtomicBoolean state = new AtomicBoolean(false); private final StatefulPoolMapManager<T> path2pool; private final Cache<T,StatefulPool<T>> cache = CacheBuilder.newBuilder().weakKeys().build(); private LoadBalance loadBalance; public MultiPool(StatefulPoolMapManager<T> path2pool,LoadBalance loadBalance) { this.path2pool = path2pool; this.loadBalance = loadBalance; start(); } public MultiPool(StatefulPoolMapManager<T> path2pool) { this(path2pool, DEFAULT_LOAD_BALANCE); } @Override public T get() throws InterruptedException { ImmutablePair<String, StatefulPool<T>> pair = getPool(); if (pair==null) { throw new IllegalPoolStateException("there is no pool available"); } T entry = null; StatefulPool<T> pool = pair.getValue(); cache.put(entry=pool.get(), pool); pool.getRefCnt().incrementAndGet(); return entry; } @Override public T get(long timeout, TimeUnit timeUnit) throws InterruptedException, TimeoutException { T entry = null; ImmutablePair<String, StatefulPool<T>> pair = getPool(); if (pair==null) { throw new IllegalPoolStateException("there is no pool available"); } StatefulPool<T> pool = pair.getValue(); cache.put(entry=pool.get(timeout,timeUnit), pool); pool.getRefCnt().incrementAndGet(); return entry; } @Override public void release(T entry, boolean broken) { StatefulPool<T> statefulPool = cache.getIfPresent(entry); if (statefulPool!=null) { try { statefulPool.release(entry,broken); } finally{ statefulPool.getRefCnt().decrementAndGet(); } } } @Override public void release(T entry) { StatefulPool<T> statefulPool = cache.getIfPresent(entry); if (statefulPool!=null) { try { statefulPool.release(entry); } finally{ statefulPool.getRefCnt().decrementAndGet(); } } } @Override public int size() { return path2pool.size(); } @Override public void scale(int size) { throw new UnsupportedOperationException(); } private ImmutablePair<String, StatefulPool<T>> getPool() { Map<String, StatefulPool<T>> objectMap = path2pool.getObjectMap(); StatefulPool<T> foundPool = null; for (int i = 0; i < objectMap.size(); i++) { String key = loadBalance.select(Lists.newArrayList(objectMap .keySet())); foundPool = path2pool.get(key); if (foundPool == null || foundPool.state().get() != State.INITIALIZED) { continue; } else { return ImmutablePair.of(key, foundPool); } } throw new IllegalPoolStateException( " thers is no useful pool in the container"); } public static class RandomPolicy implements LoadBalance{ Random random = new Random(); @Override public String select(List<String> list) { if (list.size()<1) { throw new IllegalPoolStateException(" pool size must greater than one"); } return list.get(random.nextInt(list.size())); } } public interface LoadBalance { String select(List<String> list); } @Override public void start() { if (state.compareAndSet(false, true)) { path2pool.start(); } } @Override public void stop() { if (state.compareAndSet(true, false)) { path2pool.stop(); try { close(); } catch (IOException e) { } }; } @Override public boolean isStarted() { return state.get(); } @Override public void close() throws IOException { // TODO Auto-generated method stub } }