package net.rubyeye.xmemcached.impl; import java.net.InetSocketAddress; import java.util.LinkedList; import java.util.NoSuchElementException; import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import net.rubyeye.xmemcached.KeyIterator; import net.rubyeye.xmemcached.MemcachedClient; import net.rubyeye.xmemcached.command.text.TextCacheDumpCommand; import net.rubyeye.xmemcached.exception.MemcachedException; import net.rubyeye.xmemcached.exception.MemcachedServerException; import net.rubyeye.xmemcached.utils.Protocol; import com.google.code.yanf4j.core.Session; /** * Default key iterator implementation * * @author dennis * */ public final class KeyIteratorImpl implements KeyIterator { private final LinkedList<Integer> itemNumbersList; private LinkedList<String> currentKeyList; private final MemcachedClient memcachedClient; private final InetSocketAddress inetSocketAddress; private long opTimeout = 1000; public KeyIteratorImpl(LinkedList<Integer> itemNumbersList, MemcachedClient memcachedClient, InetSocketAddress inetSocketAddress) { super(); this.itemNumbersList = itemNumbersList; this.memcachedClient = memcachedClient; this.inetSocketAddress = inetSocketAddress; } public final InetSocketAddress getServerAddress() { return this.inetSocketAddress; } public final void setOpTimeout(long opTimeout) { this.opTimeout = opTimeout; } public void close() { this.itemNumbersList.clear(); this.currentKeyList.clear(); this.currentKeyList = null; } public boolean hasNext() { return (this.itemNumbersList != null && !this.itemNumbersList.isEmpty()) || (this.currentKeyList != null && !this.currentKeyList .isEmpty()); } @SuppressWarnings("unchecked") public String next() throws MemcachedException, TimeoutException, InterruptedException { if (!hasNext()) { throw new NoSuchElementException(); } if (this.currentKeyList != null && !this.currentKeyList.isEmpty()) { return this.currentKeyList.remove(); } int itemNumber = this.itemNumbersList.remove(); Queue<Session> sessions = this.memcachedClient.getConnector() .getSessionByAddress(this.inetSocketAddress); if (sessions == null || sessions.size() == 0) { throw new MemcachedException( "The memcached server is not connected,address=" + this.inetSocketAddress); } Session session = sessions.peek(); CountDownLatch latch = new CountDownLatch(1); if (this.memcachedClient.getProtocol() == Protocol.Text) { TextCacheDumpCommand textCacheDumpCommand = new TextCacheDumpCommand( latch, itemNumber); session.write(textCacheDumpCommand); if (!latch.await(this.opTimeout, TimeUnit.MILLISECONDS)) { throw new TimeoutException("stats cachedump timeout"); } if (textCacheDumpCommand.getException() != null) { if (textCacheDumpCommand.getException() instanceof MemcachedException) { throw (MemcachedException) textCacheDumpCommand .getException(); } else { throw new MemcachedServerException(textCacheDumpCommand .getException()); } } this.currentKeyList = (LinkedList<String>) textCacheDumpCommand .getResult(); } else { throw new MemcachedException( this.memcachedClient.getProtocol().name() + " protocol doesn't support iterating all keys in memcached"); } return next(); } }