package org.infinispan.client.hotrod.impl.operations; import java.io.OutputStream; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.infinispan.client.hotrod.configuration.ClientIntelligence; import org.infinispan.client.hotrod.exceptions.InvalidResponseException; import org.infinispan.client.hotrod.impl.protocol.Codec; import org.infinispan.client.hotrod.impl.protocol.HeaderParams; import org.infinispan.client.hotrod.impl.protocol.HotRodConstants; import org.infinispan.client.hotrod.impl.transport.Transport; import org.infinispan.client.hotrod.impl.transport.TransportFactory; import net.jcip.annotations.Immutable; /** * Streaming put operation * * @author Tristan Tarrant * @since 9.0 */ @Immutable public class PutStreamOperation extends AbstractKeyOperation<OutputStream> { static final long VERSION_PUT = 0; static final long VERSION_PUT_IF_ABSENT = -1; private final long version; private final long lifespan; private final long maxIdle; private final TimeUnit lifespanTimeUnit; private final TimeUnit maxIdleTimeUnit; private boolean retryable; public PutStreamOperation(Codec codec, TransportFactory transportFactory, Object key, byte[] keyBytes, byte[] cacheName, AtomicInteger topologyId, int flags, ClientIntelligence clientIntelligence, long version, long lifespan, TimeUnit lifespanTimeUnit, long maxIdle, TimeUnit maxIdleTimeUnit) { super(codec, transportFactory, key, keyBytes, cacheName, topologyId, flags, clientIntelligence); this.version = version; this.lifespan = lifespan; this.maxIdle = maxIdle; this.lifespanTimeUnit = lifespanTimeUnit; this.maxIdleTimeUnit = maxIdleTimeUnit; retryable = true; } @Override public OutputStream executeOperation(Transport transport) { HeaderParams params = writeHeader(transport, PUT_STREAM_REQUEST); transport.writeArray(keyBytes); codec.writeExpirationParams(transport, lifespan, lifespanTimeUnit, maxIdle, maxIdleTimeUnit); transport.writeLong(version); retryable = false; transport.setBusy(true); return codec.writeAsStream(transport, () -> { try { short status = readHeaderAndValidate(transport, params); if (!HotRodConstants.isSuccess(status)) { if (HotRodConstants.isNotExecuted(status) && (version != VERSION_PUT)) return; throw new InvalidResponseException("Unexpected response status: " + Integer.toHexString(status)); } } finally { transport.setBusy(false); transport.getTransportFactory().releaseTransport(transport); } }); } @Override protected boolean shouldRetry(int retryCount) { return retryable && super.shouldRetry(retryCount); } }