package org.infinispan.client.hotrod.impl.iteration;
import static org.infinispan.server.hotrod.test.HotRodTestingUtil.hotRodCacheConfiguration;
import static org.testng.Assert.assertEquals;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.commons.util.CloseableIterator;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.query.dsl.embedded.testdomain.hsearch.AccountHS;
import org.infinispan.test.TestingUtil;
import org.testng.annotations.Test;
/**
* @author gustavonalle
* @since 8.0
*/
@Test(groups = "functional", testName = "client.hotrod.iteration.MultiServerDistRemoteIteratorTest")
public class MultiServerDistRemoteIteratorTest extends BaseMultiServerRemoteIteratorTest {
private static final int NUM_SERVERS = 3;
@Override
protected void createCacheManagers() throws Throwable {
createHotRodServers(NUM_SERVERS, getCacheConfiguration());
}
private ConfigurationBuilder getCacheConfiguration() {
ConfigurationBuilder builder = hotRodCacheConfiguration(getDefaultClusteredCacheConfig(CacheMode.DIST_SYNC, false));
builder.clustering().hash().numSegments(60).numOwners(2);
return builder;
}
private static class TestSegmentKeyTracker implements KeyTracker {
List<Integer> finished = new ArrayList<>();
@Override
public boolean track(byte[] key, short status) {
return true;
}
@Override
public void segmentsFinished(byte[] finishedSegments) {
BitSet bitSet = BitSet.valueOf(finishedSegments);
bitSet.stream().forEach(finished::add);
}
@Override
public Set<Integer> missedSegments() {
return null;
}
}
public void testSegmentFinishedCallback() {
RemoteCache<Integer, AccountHS> cache = clients.get(0).getCache();
populateCache(CACHE_SIZE, this::newAccount, cache);
TestSegmentKeyTracker testSegmentKeyTracker = new TestSegmentKeyTracker();
try (CloseableIterator<Map.Entry<Object, Object>> iterator = cache.retrieveEntries(null, 3)) {
TestingUtil.replaceField(testSegmentKeyTracker, "segmentKeyTracker", iterator, RemoteCloseableIterator.class);
while (iterator.hasNext()) iterator.next();
assertEquals(60, testSegmentKeyTracker.finished.size());
}
}
@Override
protected org.infinispan.client.hotrod.configuration.ConfigurationBuilder createHotRodClientConfigurationBuilder(int serverPort) {
org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder();
clientBuilder.addServer()
.host("localhost")
.port(serverPort)
.maxRetries(maxRetries())
.balancingStrategy(new PreferredServerBalancingStrategy(new InetSocketAddress("localhost", serverPort)));
return clientBuilder;
}
@Test
public void testIterationRouting() throws Exception {
for (int i = 0; i < clients.size(); i++) {
RemoteCacheManager client = client(i);
try (CloseableIterator<Map.Entry<Object, Object>> ignored = client.getCache().retrieveEntries(null, 10)) {
assertIterationActiveOnlyOnServer(i);
}
}
}
private void assertIterationActiveOnlyOnServer(int index) {
for (int i = 0; i < servers.size(); i++) {
int activeIterations = server(i).getIterationManager().activeIterations();
if (i == index) {
assertEquals(1L, activeIterations);
} else {
assertEquals(0L, activeIterations);
}
}
}
}