You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ignite.apache.org by GitBox <gi...@apache.org> on 2021/04/23 16:21:29 UTC

[GitHub] [ignite-3] ascherbakoff commented on a change in pull request #103: Ignite 14235

ascherbakoff commented on a change in pull request #103:
URL: https://github.com/apache/ignite-3/pull/103#discussion_r619022356



##########
File path: modules/core/src/main/java/org/apache/ignite/lang/IgniteBiPredicate.java
##########
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.lang;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * Defines a predicate which accepts two parameters and returns {@code true} or {@code false}.
+ *
+ * @param <E1> Type of the first parameter.
+ * @param <E2> Type of the second parameter.
+ */
+public interface IgniteBiPredicate<E1, E2> extends Serializable {

Review comment:
       Avoid using functional classes from Ignite 2. Instead use build in functional interfaces: 
   java.util.function.BiPredicate

##########
File path: modules/affinity/src/main/java/org/apache/ignite/internal/affinity/AffinityManager.java
##########
@@ -17,15 +17,35 @@
 
 package org.apache.ignite.internal.affinity;
 
-import org.apache.ignite.internal.baseline.BaselineManager;
+import java.nio.charset.StandardCharsets;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
 import org.apache.ignite.configuration.internal.ConfigurationManager;
+import org.apache.ignite.configuration.schemas.network.NetworkConfiguration;
+import org.apache.ignite.configuration.schemas.runner.LocalConfiguration;
+import org.apache.ignite.configuration.schemas.table.TablesConfiguration;
+import org.apache.ignite.internal.baseline.BaselineManager;
 import org.apache.ignite.internal.metastorage.MetaStorageManager;
+import org.apache.ignite.internal.util.ArrayUtils;
+import org.apache.ignite.lang.IgniteLogger;
+import org.apache.ignite.lang.util.SerializationUtils;
+import org.apache.ignite.metastorage.common.Key;
+import org.apache.ignite.metastorage.common.WatchEvent;
+import org.apache.ignite.metastorage.common.WatchListener;
+import org.jetbrains.annotations.NotNull;
 
 /**
  * Affinity manager is responsible for affinity function related logic including calculating affinity assignments.
  */
 // TODO: IGNITE-14586 Remove @SuppressWarnings when implementation provided.
-@SuppressWarnings({"FieldCanBeLocal", "unused"}) public class AffinityManager {
+public class AffinityManager {
+    /** Tables prefix for the metasorage. */
+    public static final String INTERNAL_PREFIX = "internal.tables.";
+
+    /** Logger. */

Review comment:
       ```suggestion
       /** The logger. */
   ```

##########
File path: modules/table/src/test/java/org/apache/ignite/table/distributed/DistributedTableTest.java
##########
@@ -0,0 +1,349 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.table.distributed;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import org.apache.ignite.internal.affinity.RendezvousAffinityFunction;
+import org.apache.ignite.internal.schema.ByteBufferRow;
+import org.apache.ignite.internal.schema.Column;
+import org.apache.ignite.internal.schema.NativeType;
+import org.apache.ignite.internal.schema.Row;
+import org.apache.ignite.internal.schema.RowAssembler;
+import org.apache.ignite.internal.schema.SchemaDescriptor;
+import org.apache.ignite.internal.table.TableImpl;
+import org.apache.ignite.internal.table.TableSchemaView;
+import org.apache.ignite.internal.table.distributed.command.GetCommand;
+import org.apache.ignite.internal.table.distributed.command.InsertCommand;
+import org.apache.ignite.internal.table.distributed.command.response.KVGetResponse;
+import org.apache.ignite.internal.table.distributed.raft.PartitionCommandListener;
+import org.apache.ignite.internal.table.distributed.storage.InternalTableImpl;
+import org.apache.ignite.lang.IgniteLogger;
+import org.apache.ignite.network.ClusterLocalConfiguration;
+import org.apache.ignite.network.ClusterNode;
+import org.apache.ignite.network.ClusterService;
+import org.apache.ignite.network.ClusterServiceFactory;
+import org.apache.ignite.network.message.MessageSerializationRegistry;
+import org.apache.ignite.network.scalecube.ScaleCubeClusterServiceFactory;
+import org.apache.ignite.raft.client.Peer;
+import org.apache.ignite.raft.client.message.RaftClientMessageFactory;
+import org.apache.ignite.raft.client.message.impl.RaftClientMessageFactoryImpl;
+import org.apache.ignite.raft.client.service.RaftGroupService;
+import org.apache.ignite.raft.client.service.impl.RaftGroupServiceImpl;
+import org.apache.ignite.raft.server.RaftServer;
+import org.apache.ignite.raft.server.impl.RaftServerImpl;
+import org.apache.ignite.table.Table;
+import org.apache.ignite.table.Tuple;
+import org.jetbrains.annotations.NotNull;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Distributed internal table tests.
+ */
+public class DistributedTableTest {
+    /** Base network port. */
+    public static final int NODE_PORT_BASE = 20_000;
+
+    /** Nodes. */
+    public static final int NODES = 5;
+
+    /** Partitions. */
+    public static final int PARTS = 10;
+
+    /** Factory. */
+    private static RaftClientMessageFactory FACTORY = new RaftClientMessageFactoryImpl();
+
+    /** Network factory. */
+    private static final ClusterServiceFactory NETWORK_FACTORY = new ScaleCubeClusterServiceFactory();
+
+    /** */
+    // TODO: IGNITE-14088: Uncomment and use real serializer provider
+    private static final MessageSerializationRegistry SERIALIZATION_REGISTRY = new MessageSerializationRegistry();
+
+    /** Client. */
+    private ClusterService client;
+
+    /** Schema. */
+    public static SchemaDescriptor SCHEMA = new SchemaDescriptor(1, new Column[] {
+        new Column("key", NativeType.LONG, false)
+    }, new Column[] {
+        new Column("value", NativeType.LONG, false)
+    });
+
+    /** Logger. */
+    private static final IgniteLogger LOG = IgniteLogger.forClass(DistributedTableTest.class);

Review comment:
       Static logger usually goes first in the static declarations list.

##########
File path: modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListener.java
##########
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.table.distributed.raft;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import org.apache.ignite.internal.schema.BinaryRow;
+import org.apache.ignite.internal.table.distributed.command.DeleteCommand;
+import org.apache.ignite.internal.table.distributed.command.GetCommand;
+import org.apache.ignite.internal.table.distributed.command.InsertCommand;
+import org.apache.ignite.internal.table.distributed.command.ReplaceCommand;
+import org.apache.ignite.internal.table.distributed.command.UpsertCommand;
+import org.apache.ignite.internal.table.distributed.command.response.KVGetResponse;
+import org.apache.ignite.raft.client.ReadCommand;
+import org.apache.ignite.raft.client.WriteCommand;
+import org.apache.ignite.raft.client.service.CommandClosure;
+import org.apache.ignite.raft.client.service.RaftGroupCommandListener;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Partition command handler.
+ */
+public class PartitionCommandListener implements RaftGroupCommandListener {
+    /** Storage. */
+    private HashMap<KeyWrapper, BinaryRow> storage = new HashMap<>();

Review comment:
       Why is this not a ConcurrentHashMap ?

##########
File path: modules/api/src/main/java/org/apache/ignite/configuration/schemas/network/NetworkConfigurationSchema.java
##########
@@ -23,18 +23,24 @@
 import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.configuration.storage.ConfigurationType;
 
-/**
- * Configuration schema for network endpoint subtree.
- */
+@SuppressWarnings("PMD.UnusedPrivateField")
 @ConfigurationRoot(rootName = "network", type = ConfigurationType.LOCAL)
 public class NetworkConfigurationSchema {
-    /** */
+    /** Uniq local node name. */
+    @Value(hasDefault = true)
+    public String name = "";
+
+    /**
+     *
+     */
     @Min(1024)
     @Max(0xFFFF)
-    @Value(hasDefault = true)
-    public final int port = 3040;
+    @Value (hasDefault = true)
+    public int port = 47500;
 
-    /** */
-    @Value(hasDefault = true)
-    public String[] netClusterNodes = {"localhost:" + port};
-}
+    @Value (hasDefault = true)
+    public String[] netClusterNodes = new String[0];
+//
+//    @ConfigValue
+//    private DiscoveryConfigurationSchema discovery;
+}

Review comment:
       Broken style

##########
File path: modules/api/src/main/java/org/apache/ignite/configuration/schemas/network/NetworkConfigurationSchema.java
##########
@@ -23,18 +23,24 @@
 import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.configuration.storage.ConfigurationType;
 
-/**
- * Configuration schema for network endpoint subtree.
- */
+@SuppressWarnings("PMD.UnusedPrivateField")

Review comment:
       This seems unnecessary

##########
File path: modules/raft/src/main/java/org/apache/ignite/raft/internal/network/RaftMessageTypes.java
##########
@@ -0,0 +1,43 @@
+/*

Review comment:
       The enum is not needed in this PR.

##########
File path: modules/table/src/main/java/org/apache/ignite/internal/table/distributed/raft/PartitionCommandListener.java
##########
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.table.distributed.raft;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import org.apache.ignite.internal.schema.BinaryRow;
+import org.apache.ignite.internal.table.distributed.command.DeleteCommand;
+import org.apache.ignite.internal.table.distributed.command.GetCommand;
+import org.apache.ignite.internal.table.distributed.command.InsertCommand;
+import org.apache.ignite.internal.table.distributed.command.ReplaceCommand;
+import org.apache.ignite.internal.table.distributed.command.UpsertCommand;
+import org.apache.ignite.internal.table.distributed.command.response.KVGetResponse;
+import org.apache.ignite.raft.client.ReadCommand;
+import org.apache.ignite.raft.client.WriteCommand;
+import org.apache.ignite.raft.client.service.CommandClosure;
+import org.apache.ignite.raft.client.service.RaftGroupCommandListener;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Partition command handler.
+ */
+public class PartitionCommandListener implements RaftGroupCommandListener {
+    /** Storage. */
+    private HashMap<KeyWrapper, BinaryRow> storage = new HashMap<>();
+
+    /** {@inheritDoc} */
+    @Override public void onRead(Iterator<CommandClosure<ReadCommand>> iterator) {
+        while (iterator.hasNext()) {
+            CommandClosure<ReadCommand> clo = iterator.next();
+
+            assert clo.command() instanceof GetCommand;
+
+            clo.success(new KVGetResponse(storage.get(extractAndWrapKey(((GetCommand)clo.command()).getKeyRow()))));
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onWrite(Iterator<CommandClosure<WriteCommand>> iterator) {
+        while (iterator.hasNext()) {
+            CommandClosure<WriteCommand> clo = iterator.next();
+
+            if (clo.command() instanceof InsertCommand) {
+                BinaryRow previous = storage.putIfAbsent(
+                    extractAndWrapKey(((InsertCommand)clo.command()).getRow()),
+                    ((InsertCommand)clo.command()).getRow()
+                );
+
+                clo.success(previous == null);
+            }
+            else if (clo.command() instanceof DeleteCommand) {
+                BinaryRow deleted = storage.remove(
+                    extractAndWrapKey(((DeleteCommand)clo.command()).getKeyRow())
+                );
+
+                clo.success(deleted != null);
+            }
+            else if (clo.command() instanceof ReplaceCommand) {
+                ReplaceCommand cmd = ((ReplaceCommand)clo.command());
+
+                BinaryRow expected = cmd.getOldRow();
+
+                KeyWrapper key = extractAndWrapKey(expected);
+
+                BinaryRow current = storage.get(key);
+
+                if ((current == null && !expected.hasValue()) ||
+                    equalValues(current, expected)) {
+                    storage.put(key, cmd.getRow());
+
+                    clo.success(true);
+                }
+                else
+                    clo.success(false);
+            }
+            else if (clo.command() instanceof UpsertCommand) {
+                storage.put(
+                    extractAndWrapKey(((UpsertCommand)clo.command()).getRow()),
+                    ((UpsertCommand)clo.command()).getRow()
+                );
+
+                clo.success(null);
+            }
+            else
+                assert false : "Command was not found [cmd=" + clo.command() + ']';
+        }
+    }
+
+    /**
+     * @param row Row.
+     * @return Extracted key.
+     */
+    @NotNull private boolean equalValues(@NotNull BinaryRow row, @NotNull BinaryRow row2) {
+        if (row.hasValue() ^ row2.hasValue())

Review comment:
       Doesn't look correct.  If both rows have values it will return false.

##########
File path: modules/affinity/src/test/java/org/apache/ignite/internal/affinity/RendezvousAffinityFunctionTest.java
##########
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.affinity;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.function.Function;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.lang.IgniteLogger;
+import org.apache.ignite.network.ClusterNode;
+import org.jetbrains.annotations.NotNull;
+import org.junit.jupiter.api.Test;
+
+import static java.util.Objects.nonNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Test for affinity function.
+ */
+public class RendezvousAffinityFunctionTest {
+
+    /** Logger. */
+    private static final IgniteLogger LOG = IgniteLogger.forClass(RendezvousAffinityFunctionTest.class);
+
+    /** Affinity deviation ratio. */
+    public static final double AFFINITY_DEVIATION_RATIO = 0.2;
+
+    @Test
+    public void partitionDistribution() {
+        int nodes = 50;
+
+        int parts = 10_000;
+
+        int replicas = 4;
+
+        ArrayList<ClusterNode> clusterNodes = prepareNetworkTopology(nodes);
+
+        assertTrue(parts > nodes, "Partitions should be more that nodes");
+
+        int ideal = (parts * replicas) / nodes;
+
+        List<List<ClusterNode>> assignment = RendezvousAffinityFunction.assignPartitions(
+            clusterNodes,
+            parts,
+            replicas,
+            false,
+            null
+        );
+
+        HashMap<ClusterNode, ArrayList<Integer>> assignmentByNode = new HashMap<>(nodes);
+
+        int part = 0;
+
+        for (List<ClusterNode> partNodes : assignment) {
+            for (ClusterNode node : partNodes) {
+                ArrayList<Integer> nodeParts = assignmentByNode.get(node);
+
+                if (nodeParts == null)
+                    assignmentByNode.put(node, nodeParts = new ArrayList<>());
+
+                nodeParts.add(part);
+            }
+
+            part++;
+        }
+
+        for (ClusterNode node : clusterNodes) {
+            ArrayList<Integer> nodeParts = assignmentByNode.get(node);
+
+            assertNotNull(nodeParts);
+
+            assertTrue(nodeParts.size() > ideal * (1 - AFFINITY_DEVIATION_RATIO)
+                    && nodeParts.size() < ideal * (1 + AFFINITY_DEVIATION_RATIO),
+                "Partition distribution too fare from ideal [node=" + node

Review comment:
       ```suggestion
                   "Partition distribution is too far from ideal [node=" + node
   ```

##########
File path: modules/api/src/main/java/org/apache/ignite/configuration/schemas/network/NetworkConfigurationSchema.java
##########
@@ -23,18 +23,24 @@
 import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.configuration.storage.ConfigurationType;
 
-/**
- * Configuration schema for network endpoint subtree.
- */
+@SuppressWarnings("PMD.UnusedPrivateField")
 @ConfigurationRoot(rootName = "network", type = ConfigurationType.LOCAL)
 public class NetworkConfigurationSchema {
-    /** */
+    /** Uniq local node name. */
+    @Value(hasDefault = true)
+    public String name = "";
+
+    /**
+     *
+     */
     @Min(1024)
     @Max(0xFFFF)
-    @Value(hasDefault = true)
-    public final int port = 3040;
+    @Value (hasDefault = true)
+    public int port = 47500;
 
-    /** */
-    @Value(hasDefault = true)
-    public String[] netClusterNodes = {"localhost:" + port};
+    @Value (hasDefault = true)
+    public String[] netClusterNodes = new String[0];
+//
+//    @ConfigValue
+//    private DiscoveryConfigurationSchema discovery;

Review comment:
       The garbage.

##########
File path: modules/raft/src/main/java/org/apache/ignite/raft/server/impl/RaftServerImpl.java
##########
@@ -83,24 +77,20 @@
     private final Thread writeWorker;
 
     /**
-     * @param id Server id.
-     * @param localPort Local port.
+     * @param net Network.
      * @param clientMsgFactory Client message factory.
      * @param queueSize Queue size.
      * @param listeners Command listeners.
      */
     public RaftServerImpl(
-        @NotNull String id,
-        int localPort,
+        ClusterService net,

Review comment:
       ```suggestion
           ClusterService service,
   ```

##########
File path: modules/api/src/main/java/org/apache/ignite/configuration/schemas/network/NetworkConfigurationSchema.java
##########
@@ -23,18 +23,24 @@
 import org.apache.ignite.configuration.annotation.Value;
 import org.apache.ignite.configuration.storage.ConfigurationType;
 
-/**
- * Configuration schema for network endpoint subtree.
- */
+@SuppressWarnings("PMD.UnusedPrivateField")
 @ConfigurationRoot(rootName = "network", type = ConfigurationType.LOCAL)
 public class NetworkConfigurationSchema {
-    /** */
+    /** Uniq local node name. */
+    @Value(hasDefault = true)
+    public String name = "";
+
+    /**
+     *
+     */
     @Min(1024)
     @Max(0xFFFF)
-    @Value(hasDefault = true)
-    public final int port = 3040;
+    @Value (hasDefault = true)
+    public int port = 47500;
 
-    /** */
-    @Value(hasDefault = true)
-    public String[] netClusterNodes = {"localhost:" + port};
+    @Value (hasDefault = true)
+    public String[] netClusterNodes = new String[0];
+//
+//    @ConfigValue
+//    private DiscoveryConfigurationSchema discovery;

Review comment:
       The garbage.

##########
File path: modules/affinity/src/test/java/org/apache/ignite/internal/affinity/RendezvousAffinityFunctionTest.java
##########
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.affinity;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.function.Function;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.lang.IgniteLogger;
+import org.apache.ignite.network.ClusterNode;
+import org.jetbrains.annotations.NotNull;
+import org.junit.jupiter.api.Test;
+
+import static java.util.Objects.nonNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Test for affinity function.
+ */
+public class RendezvousAffinityFunctionTest {
+
+    /** Logger. */
+    private static final IgniteLogger LOG = IgniteLogger.forClass(RendezvousAffinityFunctionTest.class);
+
+    /** Affinity deviation ratio. */
+    public static final double AFFINITY_DEVIATION_RATIO = 0.2;
+
+    @Test
+    public void partitionDistribution() {

Review comment:
       ```suggestion
       public void testPartitionDistribution() {
   ```

##########
File path: modules/api/src/main/java/org/apache/ignite/app/IgnitionProcessor.java
##########
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.app;
+
+import java.util.ServiceLoader;
+
+public enum IgnitionProcessor implements Ignition {

Review comment:
       This class should not be in this pull request - it's related to node start.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org