package org.infinispan.client.hotrod.impl.operations; import static java.util.Arrays.stream; import java.net.SocketAddress; import java.util.BitSet; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.infinispan.client.hotrod.configuration.ClientIntelligence; import org.infinispan.client.hotrod.impl.consistenthash.SegmentConsistentHash; import org.infinispan.client.hotrod.impl.protocol.Codec; import org.infinispan.client.hotrod.impl.protocol.HeaderParams; import org.infinispan.client.hotrod.impl.transport.Transport; import org.infinispan.client.hotrod.impl.transport.TransportFactory; /** * @author gustavonalle * @since 8.0 */ public class IterationStartOperation extends RetryOnFailureOperation<IterationStartResponse> { private final String filterConverterFactory; private final byte[][] filterParameters; private final Set<Integer> segments; private final int batchSize; private final TransportFactory transportFactory; private final boolean metadata; IterationStartOperation(Codec codec, int flags, ClientIntelligence clientIntelligence, byte[] cacheName, AtomicInteger topologyId, String filterConverterFactory, byte[][] filterParameters, Set<Integer> segments, int batchSize, TransportFactory transportFactory, boolean metadata) { super(codec, transportFactory, cacheName, topologyId, flags, clientIntelligence); this.filterConverterFactory = filterConverterFactory; this.filterParameters = filterParameters; this.segments = segments; this.batchSize = batchSize; this.transportFactory = transportFactory; this.metadata = metadata; } @Override protected Transport getTransport(int retryCount, Set<SocketAddress> failedServers) { return transportFactory.getTransport(failedServers, cacheName); } @Override protected IterationStartResponse executeOperation(Transport transport) { HeaderParams params = writeHeader(transport, ITERATION_START_REQUEST); if (segments == null) { transport.writeSignedVInt(-1); } else { // TODO use a more compact BitSet implementation, like http://roaringbitmap.org/ BitSet bitSet = new BitSet(); segments.stream().forEach(bitSet::set); transport.writeOptionalArray(bitSet.toByteArray()); } transport.writeOptionalString(filterConverterFactory); if (filterConverterFactory != null) { if (filterParameters != null && filterParameters.length > 0) { transport.writeByte((short) filterParameters.length); stream(filterParameters).forEach(transport::writeArray); } else { transport.writeByte((short) 0); } } transport.writeVInt(batchSize); transport.writeByte((short) (metadata ? 1 : 0)); transport.flush(); readHeaderAndValidate(transport, params); return new IterationStartResponse(transport.readString(), (SegmentConsistentHash) transportFactory.getConsistentHash(cacheName), topologyId.get(), transport); } @Override protected void releaseTransport(Transport transport) { } }