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

org.infinispan.server.resp.commands.set.SDIFF Maven / Gradle / Ivy

There is a newer version: 15.1.4.Final
Show newest version
package org.infinispan.server.resp.commands.set;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletionStage;

import org.infinispan.multimap.impl.EmbeddedSetCache;
import org.infinispan.multimap.impl.SetBucket;
import org.infinispan.server.resp.Resp3Handler;
import org.infinispan.server.resp.RespCommand;
import org.infinispan.server.resp.RespRequestHandler;
import org.infinispan.server.resp.commands.Resp3Command;
import org.infinispan.server.resp.serialization.Resp3Response;

import io.netty.channel.ChannelHandlerContext;

/**
 * {@link} https://redis.io/commands/sdiff/
 * Returns the members of the set resulting from the difference between
 * the first set and all the successive sets.
 * @since 15.0
 */
public class SDIFF extends RespCommand implements Resp3Command {

   public SDIFF() {
      super(-2, 1, -1, 1);
   }

   @Override
   public CompletionStage perform(Resp3Handler handler,
         ChannelHandlerContext ctx,
         List arguments) {
      EmbeddedSetCache esc = handler.getEmbeddedSetCache();
      // If the diff is with the set itself the result will be an empty set
      // but we need to go through the process to check all the keys are set type
      boolean diffItself = arguments.stream().skip(1)
            .anyMatch(item -> Objects.deepEquals(arguments.get(0), item));
      // Wrapping to exclude duplicate keys
      var uniqueKeys = SINTER.getUniqueKeys(handler, arguments);
      var allEntries = esc.getAll(uniqueKeys);
      return handler.stageToReturn(allEntries.thenApply(entriesMap -> diff(arguments.get(0), entriesMap, diffItself)),
            ctx, Resp3Response.SET_BULK_STRING);
   }

   public static Set diff(byte[] key, Map> buckets, boolean diffItself) {
      Set minuend = Collections.emptySet();
      if (!diffItself) {
         byte[] kInMap = getKeyForMap(key, buckets);
         if (kInMap != null) {
            minuend = buckets.get(kInMap).toSet();
         }
         buckets.remove(kInMap);
      }
      for (var bucket : buckets.values()) {
         for (byte[] item : bucket.toList()) {
            if (minuend.isEmpty()) {
               break;
            }
            minuend.removeIf(v -> Objects.deepEquals(v, item));
         }
      }
      return minuend;
   }

   static byte[] getKeyForMap(byte[] key, Map> buckets) {
      if (buckets.isEmpty())
         return null;
      return buckets.keySet().stream().filter(item -> Arrays.equals(item, key)).findFirst().orElse(null);
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy