package code.google.nfs.rpc.client; /** * nfs-rpc * Apache License * * http://code.google.com/p/nfs-rpc (c) 2011 */ import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.FutureTask; /** * Abstract Client Factory,create custom nums client * * @author <a href="mailto:bluedavy@gmail.com">bluedavy</a> */ public abstract class AbstractClientFactory implements ClientFactory { // Cache client private static ConcurrentHashMap<String, FutureTask<List<Client>>> clients = new ConcurrentHashMap<String, FutureTask<List<Client>>>(); private static boolean isSendLimitEnabled = false; public Client get(final String targetIP, final int targetPort, final int connectTimeout, String... customKey) throws Exception { return get(targetIP, targetPort, connectTimeout, 1, customKey); } public Client get(final String targetIP, final int targetPort, final int connectTimeout, final int clientNums, String... customKey) throws Exception { String key = targetIP + ":" + targetPort; if (customKey != null && customKey.length == 1) { key = customKey[0]; } if (clients.containsKey(key)) { if (clientNums == 1) { return clients.get(key).get().get(0); } else { Random random = new Random(); return clients.get(key).get().get(random.nextInt(clientNums)); } } else { final String cacheKey = key; FutureTask<List<Client>> task = new FutureTask<List<Client>>( new Callable<List<Client>>() { public List<Client> call() throws Exception { List<Client> clients = new ArrayList<Client>( clientNums); for (int i = 0; i < clientNums; i++) { clients.add(createClient(targetIP, targetPort, connectTimeout, cacheKey)); } return clients; } }); FutureTask<List<Client>> currentTask = clients.putIfAbsent(key,task); if (currentTask == null) { task.run(); } else { task = currentTask; } if (clientNums == 1) return task.get().get(0); else { Random random = new Random(); return task.get().get(random.nextInt(clientNums)); } } } public void removeClient(String key, Client client) { try { // TODO: Fix It clients.remove(key); // clients.get(key).get().remove(client); // clients.get(key) // .get() // .add(createClient(client.getServerIP(), // client.getServerPort(), client.getConnectTimeout(), // key)); } catch (Exception e) { // IGNORE } } public void enableSendLimit(){ isSendLimitEnabled = true; } /** * check if sending bytes size exceed limit threshold */ public void checkSendLimit() throws Exception{ if(!isSendLimitEnabled) return; long threshold = javaHeapSize * sendLimitPercent / 100; long sendingBytesSize = getSendingBytesSize(); if(sendingBytesSize >= threshold){ if(sendLimitPolicy == SendLimitPolicy.REJECT){ throw new Exception("sending bytes size exceed threshold,size: "+sendingBytesSize+", threshold: "+threshold); } else{ Thread.sleep(1000); sendingBytesSize = getSendingBytesSize(); if(sendingBytesSize >= threshold){ throw new Exception("sending bytes size exceed threshold,size: "+sendingBytesSize+", threshold: "+threshold); } } } } private long getSendingBytesSize() throws Exception{ long sendingBytesSize = 0; for (FutureTask<List<Client>> clientListTask : clients.values()) { List<Client> clientList = clientListTask.get(); for (Client client : clientList) { sendingBytesSize += client.getSendingBytesSize(); } } return sendingBytesSize; } public static ClientFactory getInstance() { throw new UnsupportedOperationException( "should be implemented by true class"); } protected abstract Client createClient(String targetIP, int targetPort, int connectTimeout, String key) throws Exception; }