All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.client.hotrod.impl.operations.IterationNextOperation Maven / Gradle / Ivy

The newest version!
package org.infinispan.client.hotrod.impl.operations;

import static org.infinispan.client.hotrod.logging.Log.HOTROD;

import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;

import org.infinispan.client.hotrod.impl.InternalRemoteCache;
import org.infinispan.client.hotrod.impl.MetadataValueImpl;
import org.infinispan.client.hotrod.impl.iteration.KeyTracker;
import org.infinispan.client.hotrod.impl.protocol.Codec;
import org.infinispan.client.hotrod.impl.protocol.HotRodConstants;
import org.infinispan.client.hotrod.impl.transport.netty.ByteBufUtil;
import org.infinispan.client.hotrod.impl.transport.netty.HeaderDecoder;
import org.infinispan.commons.configuration.ClassAllowList;
import org.infinispan.commons.util.IntSet;
import org.infinispan.commons.util.IntSets;

import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;

/**
 * @author gustavonalle
 * @since 8.0
 */
public class IterationNextOperation extends AbstractCacheOperation> {

   private final byte[] iterationId;
   private final KeyTracker segmentKeyTracker;

   private byte[] finishedSegments;
   private int entriesSize = -1;
   private List> entries;
   private int projectionsSize;
   private int untrackedEntries;

   protected IterationNextOperation(InternalRemoteCache cache, byte[] iterationId,
                                    KeyTracker segmentKeyTracker) {
      super(cache);
      this.iterationId = iterationId;
      this.segmentKeyTracker = segmentKeyTracker;
   }

   @Override
   public void writeOperationRequest(Channel channel, ByteBuf buf, Codec codec) {
      ByteBufUtil.writeArray(buf, iterationId);
   }

   @Override
   public IterationNextResponse createResponse(ByteBuf buf, short status, HeaderDecoder decoder, Codec codec, CacheUnmarshaller unmarshaller) {
      if (entriesSize < 0) {
         finishedSegments = ByteBufUtil.readArray(buf);
         entriesSize = ByteBufUtil.readVInt(buf);
         if (entriesSize == 0) {
            IntSet finishedSegmentSet = IntSets.from(finishedSegments);
            segmentKeyTracker.segmentsFinished(finishedSegmentSet);
            return new IterationNextResponse<>(status, Collections.emptyList(), finishedSegmentSet, false);
         }
         entries = new ArrayList<>(entriesSize);
         projectionsSize = -1;
         decoder.checkpoint();
      }

      if (projectionsSize < 0) {
         projectionsSize = ByteBufUtil.readVInt(buf);
         decoder.checkpoint();
      }

      ClassAllowList classAllowList = internalRemoteCache.getRemoteCacheContainer().getConfiguration().getClassAllowList();

      while (entries.size() + untrackedEntries < entriesSize) {
         short meta = buf.readUnsignedByte();
         long creation = -1;
         int lifespan = -1;
         long lastUsed = -1;
         int maxIdle = -1;
         long version = 0;
         if (meta == 1) {
            short flags = buf.readUnsignedByte();
            if ((flags & INFINITE_LIFESPAN) != INFINITE_LIFESPAN) {
               creation = buf.readLong();
               lifespan = ByteBufUtil.readVInt(buf);
            }
            if ((flags & INFINITE_MAXIDLE) != INFINITE_MAXIDLE) {
               lastUsed = buf.readLong();
               maxIdle = ByteBufUtil.readVInt(buf);
            }
            version = buf.readLong();
         }
         byte[] key = ByteBufUtil.readArray(buf);
         E value;
         if (projectionsSize > 1) {
            Object[] projections = new Object[projectionsSize];
            for (int j = 0; j < projectionsSize; j++) {
               projections[j] = unmarshaller.readValue(buf);
            }
            value = (E) projections;
         } else {
            value = unmarshaller.readValue(buf);
         }
         if (meta == 1) {
            value = (E) new MetadataValueImpl<>(creation, lifespan, lastUsed, maxIdle, version, value);
         }

         if (segmentKeyTracker.track(key, status, classAllowList)) {
            K unmarshallKey = internalRemoteCache.getDataFormat().keyToObj(key, classAllowList);
            entries.add(new SimpleEntry<>(unmarshallKey, value));
         } else {
            untrackedEntries++;
         }
         decoder.checkpoint();
      }
      IntSet finishedSegmentSet = IntSets.from(finishedSegments);
      segmentKeyTracker.segmentsFinished(finishedSegmentSet);
      if (HotRodConstants.isInvalidIteration(status)) {
         throw HOTROD.errorRetrievingNext(new String(iterationId, HOTROD_STRING_CHARSET));
      }
      return new IterationNextResponse<>(status, entries, finishedSegmentSet, true);
   }

   @Override
   public short requestOpCode() {
      return ITERATION_NEXT_REQUEST;
   }

   @Override
   public short responseOpCode() {
      return ITERATION_NEXT_RESPONSE;
   }

   @Override
   public boolean supportRetry() {
      return false;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy