You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ir...@apache.org on 2019/08/11 23:33:32 UTC
[ignite] branch master updated: IGNITE-6957 Reduce excessive int
boxing when accessing cache by ID - Fixes #6536.
This is an automated email from the ASF dual-hosted git repository.
irakov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 4eda065 IGNITE-6957 Reduce excessive int boxing when accessing cache by ID - Fixes #6536.
4eda065 is described below
commit 4eda06575f1831350ff0545c2b78bb3cb9a811b5
Author: mstepachev <ma...@gmail.com>
AuthorDate: Mon Aug 12 02:32:55 2019 +0300
IGNITE-6957 Reduce excessive int boxing when accessing cache by ID - Fixes #6536.
Signed-off-by: Ivan Rakov <ir...@apache.org>
---
.../affinity/GridAffinityAssignmentV2.java | 15 +-
.../affinity/HistoryAffinityAssignmentImpl.java | 7 +-
.../processors/cache/CacheMetricsImpl.java | 9 +-
.../cache/IgniteCacheOffheapManagerImpl.java | 35 +--
.../dht/topology/GridDhtLocalPartition.java | 19 +-
.../util/{ => collection}/BitSetIntSet.java | 112 +++++---
.../internal/util/collection/ImmutableIntSet.java | 206 ++++++++++++++
.../internal/util/collection/IntHashMap.java | 309 +++++++++++++++++++++
.../ignite/internal/util/collection/IntMap.java | 85 ++++++
.../internal/util/collection/IntRWHashMap.java | 141 ++++++++++
.../ignite/internal/util/collection/IntSet.java | 37 +++
.../main/resources/META-INF/classnames.properties | 5 +-
.../affinity/GridAffinityAssignmentV2Test.java | 4 +-
.../util/collection/AbstractBaseIntMapTest.java | 248 +++++++++++++++++
.../util/{ => collection}/BitSetIntSetTest.java | 188 +++++++------
.../util/collection/ImmutableIntSetTest.java | 92 ++++++
.../internal/util/collection/IntHashMapTest.java | 126 +++++++++
.../internal/util/collection/IntRWHashMapTest.java | 28 ++
.../ignite/testsuites/IgniteBasicTestSuite.java | 4 +-
19 files changed, 1504 insertions(+), 166 deletions(-)
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2.java
index ddb5716..1c8ef38 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2.java
@@ -31,7 +31,8 @@ import java.util.Set;
import java.util.UUID;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.internal.dto.IgniteDataTransferObject;
-import org.apache.ignite.internal.util.BitSetIntSet;
+import org.apache.ignite.internal.util.collection.BitSetIntSet;
+import org.apache.ignite.internal.util.collection.ImmutableIntSet;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
@@ -117,16 +118,16 @@ public class GridAffinityAssignmentV2 extends IgniteDataTransferObject implement
for (int partsCnt = assignment.size(), p = 0; p < partsCnt; p++) {
isPrimary = true;
- List<ClusterNode> currentOwners = assignment.get(p);
+ List<ClusterNode> currOwners = assignment.get(p);
- for (ClusterNode node : currentOwners) {
+ for (ClusterNode node : currOwners) {
UUID id = node.id();
Map<UUID, Set<Integer>> tmp = isPrimary ? tmpPrimary : tmpBackup;
/*
https://issues.apache.org/jira/browse/IGNITE-4554 BitSet performs better than HashSet at most cases.
- However with 65k partition and high number of nodes (700+) BitSet is loosing HashSet.
+ However with 65k partition and high number of nodes (700+) BitSet is losing HashSet.
We need to replace it with sparse bitsets.
*/
tmp.computeIfAbsent(id, uuid ->
@@ -138,7 +139,7 @@ public class GridAffinityAssignmentV2 extends IgniteDataTransferObject implement
List<ClusterNode> idealOwners = p < idealAssignment.size() ? idealAssignment.get(p) : Collections.emptyList();
- ClusterNode curPrimary = !currentOwners.isEmpty() ? currentOwners.get(0) : null;
+ ClusterNode curPrimary = !currOwners.isEmpty() ? currOwners.get(0) : null;
ClusterNode idealPrimary = !idealOwners.isEmpty() ? idealOwners.get(0) : null;
if (curPrimary != null && !curPrimary.equals(idealPrimary))
@@ -288,7 +289,7 @@ public class GridAffinityAssignmentV2 extends IgniteDataTransferObject implement
@Override public Set<Integer> primaryPartitions(UUID nodeId) {
Set<Integer> set = primary.get(nodeId);
- return set == null ? Collections.emptySet() : Collections.unmodifiableSet(set);
+ return set == null ? ImmutableIntSet.emptySet() : ImmutableIntSet.wrap(set);
}
/**
@@ -300,7 +301,7 @@ public class GridAffinityAssignmentV2 extends IgniteDataTransferObject implement
@Override public Set<Integer> backupPartitions(UUID nodeId) {
Set<Integer> set = backup.get(nodeId);
- return set == null ? Collections.emptySet() : Collections.unmodifiableSet(set);
+ return set == null ? ImmutableIntSet.emptySet() : ImmutableIntSet.wrap(set);
}
/** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/HistoryAffinityAssignmentImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/HistoryAffinityAssignmentImpl.java
index 1123756..d303fdf 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/HistoryAffinityAssignmentImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/HistoryAffinityAssignmentImpl.java
@@ -29,7 +29,8 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.ignite.cluster.ClusterNode;
-import org.apache.ignite.internal.util.BitSetIntSet;
+import org.apache.ignite.internal.util.collection.BitSetIntSet;
+import org.apache.ignite.internal.util.collection.ImmutableIntSet;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.S;
@@ -300,7 +301,7 @@ public class HistoryAffinityAssignmentImpl implements HistoryAffinityAssignment
res.add(p);
}
- return Collections.unmodifiableSet(res);
+ return ImmutableIntSet.wrap(res);
}
/** {@inheritDoc} */
@@ -321,7 +322,7 @@ public class HistoryAffinityAssignmentImpl implements HistoryAffinityAssignment
}
}
- return Collections.unmodifiableSet(res);
+ return ImmutableIntSet.wrap(res);
}
/** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
index f26bf14..e1049a5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
@@ -17,7 +17,6 @@
package org.apache.ignite.internal.processors.cache;
-import java.util.Set;
import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.cache.CacheMetrics;
import org.apache.ignite.cache.CachePeekMode;
@@ -28,9 +27,11 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.topology.Grid
import org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtPartitionState;
import org.apache.ignite.internal.processors.cache.store.GridCacheWriteBehindStore;
import org.apache.ignite.internal.processors.metric.MetricRegistry;
-import org.apache.ignite.internal.processors.metric.impl.HitRateMetric;
import org.apache.ignite.internal.processors.metric.impl.AtomicLongMetric;
+import org.apache.ignite.internal.processors.metric.impl.HitRateMetric;
import org.apache.ignite.internal.processors.metric.impl.MetricUtils;
+import org.apache.ignite.internal.util.collection.ImmutableIntSet;
+import org.apache.ignite.internal.util.collection.IntSet;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
@@ -1118,8 +1119,8 @@ public class CacheMetricsImpl implements CacheMetrics {
else {
AffinityTopologyVersion topVer = cctx.affinity().affinityTopologyVersion();
- Set<Integer> primaries = cctx.affinity().primaryPartitions(cctx.localNodeId(), topVer);
- Set<Integer> backups = cctx.affinity().backupPartitions(cctx.localNodeId(), topVer);
+ IntSet primaries = ImmutableIntSet.wrap(cctx.affinity().primaryPartitions(cctx.localNodeId(), topVer));
+ IntSet backups = ImmutableIntSet.wrap(cctx.affinity().backupPartitions(cctx.localNodeId(), topVer));
if (cctx.isNear() && cache != null)
heapEntriesCnt = cache.nearSize();
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
index f184e6e..57cca44 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
@@ -102,6 +102,10 @@ import org.apache.ignite.internal.util.GridLongList;
import org.apache.ignite.internal.util.GridSpinBusyLock;
import org.apache.ignite.internal.util.GridStripedLock;
import org.apache.ignite.internal.util.IgniteTree;
+import org.apache.ignite.internal.util.collection.ImmutableIntSet;
+import org.apache.ignite.internal.util.collection.IntMap;
+import org.apache.ignite.internal.util.collection.IntRWHashMap;
+import org.apache.ignite.internal.util.collection.IntSet;
import org.apache.ignite.internal.util.lang.GridCloseableIterator;
import org.apache.ignite.internal.util.lang.GridCursor;
import org.apache.ignite.internal.util.lang.GridIterator;
@@ -111,9 +115,7 @@ import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiTuple;
-import org.apache.ignite.lang.IgniteClosure;
import org.apache.ignite.lang.IgniteInClosure;
-import org.apache.ignite.lang.IgnitePredicate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -412,27 +414,13 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
else {
final Iterator<GridDhtLocalPartition> it = grp.topology().currentLocalPartitions().iterator();
- if (primary && backup) {
- return F.iterator(it, new IgniteClosure<GridDhtLocalPartition, CacheDataStore>() {
- @Override public CacheDataStore apply(GridDhtLocalPartition part) {
- return part.dataStore();
- }
- }, true);
- }
+ if (primary && backup)
+ return F.iterator(it, GridDhtLocalPartition::dataStore, true);
- final Set<Integer> parts = primary ? grp.affinity().primaryPartitions(ctx.localNodeId(), topVer) :
- grp.affinity().backupPartitions(ctx.localNodeId(), topVer);
+ final IntSet parts = ImmutableIntSet.wrap(primary ? grp.affinity().primaryPartitions(ctx.localNodeId(), topVer) :
+ grp.affinity().backupPartitions(ctx.localNodeId(), topVer));
- return F.iterator(it, new IgniteClosure<GridDhtLocalPartition, CacheDataStore>() {
- @Override public CacheDataStore apply(GridDhtLocalPartition part) {
- return part.dataStore();
- }
- }, true,
- new IgnitePredicate<GridDhtLocalPartition>() {
- @Override public boolean apply(GridDhtLocalPartition part) {
- return parts.contains(part.id());
- }
- });
+ return F.iterator(it, GridDhtLocalPartition::dataStore, true, part -> parts.contains(part.id()));
}
}
@@ -1418,7 +1406,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
private final AtomicLong storageSize = new AtomicLong();
/** */
- private final ConcurrentMap<Integer, AtomicLong> cacheSizes = new ConcurrentHashMap<>();
+ private final IntMap<AtomicLong> cacheSizes = new IntRWHashMap();
/** Mvcc remove handler. */
private final PageHandler<MvccUpdateDataRow, Boolean> mvccUpdateMarker = new MvccMarkUpdatedHandler();
@@ -1494,8 +1482,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
Map<Integer, Long> res = new HashMap<>();
- for (Map.Entry<Integer, AtomicLong> e : cacheSizes.entrySet())
- res.put(e.getKey(), e.getValue().longValue());
+ cacheSizes.forEach((key, val) -> res.put(key, val.longValue()));
return res;
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/topology/GridDhtLocalPartition.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/topology/GridDhtLocalPartition.java
index 5e637e9..a827f02fb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/topology/GridDhtLocalPartition.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/topology/GridDhtLocalPartition.java
@@ -59,6 +59,8 @@ import org.apache.ignite.internal.processors.cache.transactions.TxCounters;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
import org.apache.ignite.internal.processors.query.GridQueryRowCacheCleaner;
import org.apache.ignite.internal.util.GridLongList;
+import org.apache.ignite.internal.util.collection.IntMap;
+import org.apache.ignite.internal.util.collection.IntRWHashMap;
import org.apache.ignite.internal.util.future.GridFutureAdapter;
import org.apache.ignite.internal.util.lang.GridIterator;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
@@ -145,7 +147,7 @@ public class GridDhtLocalPartition extends GridCacheConcurrentMapImpl implements
/** */
@GridToStringExclude
- private final ConcurrentMap<Integer, CacheMapHolder> cacheMaps;
+ private final IntMap<CacheMapHolder> cacheMaps;
/** */
@GridToStringExclude
@@ -195,7 +197,7 @@ public class GridDhtLocalPartition extends GridCacheConcurrentMapImpl implements
if (grp.sharedGroup()) {
singleCacheEntryMap = null;
- cacheMaps = new ConcurrentHashMap<>();
+ cacheMaps = new IntRWHashMap<>();
}
else {
singleCacheEntryMap = new CacheMapHolder(grp.singleCacheContext(), createEntriesMap());
@@ -256,12 +258,11 @@ public class GridDhtLocalPartition extends GridCacheConcurrentMapImpl implements
/** {@inheritDoc} */
@Override public int internalSize() {
if (grp.sharedGroup()) {
- int size = 0;
+ final AtomicInteger size = new AtomicInteger(0);
- for (CacheMapHolder hld : cacheMaps.values())
- size += hld.map.size();
+ cacheMaps.forEach((key, hld) -> size.addAndGet(hld.map.size()));
- return size;
+ return size.get();
}
return singleCacheEntryMap.map.size();
@@ -1129,10 +1130,8 @@ public class GridDhtLocalPartition extends GridCacheConcurrentMapImpl implements
boolean rec = grp.eventRecordable(EVT_CACHE_REBALANCE_OBJECT_UNLOADED);
- if (grp.sharedGroup()) {
- for (CacheMapHolder hld : cacheMaps.values())
- clear(hld.map, extras, rec);
- }
+ if (grp.sharedGroup())
+ cacheMaps.forEach((key, hld) -> clear(hld.map, extras, rec));
else
clear(singleCacheEntryMap.map, extras, rec);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/BitSetIntSet.java b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/BitSetIntSet.java
similarity index 60%
rename from modules/core/src/main/java/org/apache/ignite/internal/util/BitSetIntSet.java
rename to modules/core/src/main/java/org/apache/ignite/internal/util/collection/BitSetIntSet.java
index 47c0198..12e8075 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/BitSetIntSet.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/BitSetIntSet.java
@@ -14,21 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.ignite.internal.util;
+package org.apache.ignite.internal.util.collection;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
-import java.util.Set;
+import org.apache.ignite.internal.util.GridSerializableCollection;
import org.jetbrains.annotations.NotNull;
+import static org.apache.ignite.internal.util.IgniteUtils.EMPTY_INTS;
+
/**
* Set of Integers implementation based on BitSet.
*
* Implementation doesn't support negative values and null, cause we can't distinct null from 0 bit in BitSet.
*/
-public class BitSetIntSet extends GridSerializableCollection<Integer> implements Set<Integer> {
+public class BitSetIntSet extends GridSerializableCollection<Integer> implements IntSet {
/** */
private static final long serialVersionUID = 0L;
@@ -44,13 +46,21 @@ public class BitSetIntSet extends GridSerializableCollection<Integer> implements
}
/**
- *
* @param initCap initial capacity.
*/
public BitSetIntSet(int initCap) {
bitSet = new BitSet(initCap);
}
+ /**
+ * @param initCap initial capacity.
+ * @param coll initial collection.
+ */
+ public BitSetIntSet(int initCap, Collection<Integer> coll) {
+ bitSet = new BitSet(initCap);
+ addAll(coll);
+ }
+
/** {@inheritDoc} */
@Override public int size() {
return size;
@@ -59,74 +69,91 @@ public class BitSetIntSet extends GridSerializableCollection<Integer> implements
/** {@inheritDoc} */
@Override public boolean contains(Object o) {
if (o == null)
- throw new UnsupportedOperationException("Null values are not supported!");
+ throw new NullPointerException("Null values are not supported!");
- int val = (int)o;
+ return contains((int)o);
+ }
- if (val < 0)
- throw new UnsupportedOperationException("Negative values are not supported!");
+ /** {@inheritDoc} */
+ @Override public boolean contains(int element) {
+ if (element < 0)
+ return false;
- return bitSet.get(val);
+ return bitSet.get(element);
}
/** {@inheritDoc} */
@NotNull @Override public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
- private int next = -1;
+ /** */
+ private int idx = -1;
+
+ /** */
+ private int nextIdx = -1;
/** {@inheritDoc} */
@Override public boolean hasNext() {
- int nextBit = bitSet.nextSetBit(next + 1);
-
- if (nextBit != -1) {
- next = nextBit;
-
- return true;
- }
- else
- return false;
+ return nextIdx == idx ? (nextIdx = bitSet.nextSetBit(idx + 1)) != -1 : nextIdx != -1;
}
/** {@inheritDoc} */
@Override public Integer next() {
- if (next == -1)
+ if (nextIdx == idx)
+ nextIdx = bitSet.nextSetBit(idx + 1);
+
+ if (nextIdx == -1)
throw new NoSuchElementException();
- return next;
+ idx = nextIdx;
+
+ return idx;
}
};
}
- /** Unsupported operation. */
+ /** {@inheritDoc} */
@Override public boolean add(Integer integer) {
- if (integer == null || integer < 0)
- throw new UnsupportedOperationException("Negative or null values are not supported!");
+ if (integer == null)
+ throw new IllegalArgumentException("Negative or null values are not supported!");
- boolean alreadySet = bitSet.get(integer);
+ return add((int)integer);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean add(int element) {
+ if (element < 0)
+ throw new IllegalArgumentException("Negative or null values are not supported!");
+
+ boolean alreadySet = bitSet.get(element);
if (!alreadySet) {
- bitSet.set(integer);
+ bitSet.set(element);
size++;
- }
- return !alreadySet;
+ return true;
+ }
+ else
+ return false;
}
- /** Unsupported operation. */
+ /** {@inheritDoc} */
@Override public boolean remove(Object o) {
if (o == null)
- throw new UnsupportedOperationException("Null values are not supported!");
+ return false;
- int val = (int)o;
+ return remove((int)o);
+ }
- if (val < 0)
- throw new UnsupportedOperationException("Negative values are not supported!");
+ /** {@inheritDoc} */
+ @Override public boolean remove(int element) {
+ if (element < 0)
+ return false;
- boolean alreadySet = bitSet.get(val);
+ boolean alreadySet = bitSet.get(element);
if (alreadySet) {
- bitSet.clear(val);
+ bitSet.clear(element);
size--;
}
@@ -135,6 +162,21 @@ public class BitSetIntSet extends GridSerializableCollection<Integer> implements
}
/** {@inheritDoc} */
+ @Override public int[] toIntArray() {
+ if (size == 0)
+ return EMPTY_INTS;
+
+ int[] arr = new int[size];
+
+ for (int i = 0, pos = -1; i < size; i++) {
+ pos = bitSet.nextSetBit(pos + 1);
+ arr[i] = pos;
+ }
+
+ return arr;
+ }
+
+ /** {@inheritDoc} */
@Override public boolean containsAll(@NotNull Collection<?> c) {
for (Object o : c) {
if (!contains(o))
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/collection/ImmutableIntSet.java b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/ImmutableIntSet.java
new file mode 100644
index 0000000..d5ad568
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/ImmutableIntSet.java
@@ -0,0 +1,206 @@
+/*
+ * 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.util.collection;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Spliterator;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.NotNull;
+
+/** */
+public class ImmutableIntSet implements IntSet {
+ /** */
+ private static final ImmutableIntSet EMPTY_SET = new ImmutableIntSet(new BitSetIntSet(1));
+
+ /** Delegate. */
+ private final Set<Integer> delegate;
+
+ /**
+ * @param delegate Delegate.
+ */
+ public static ImmutableIntSet wrap(Set<Integer> delegate) {
+ return delegate instanceof ImmutableIntSet ? (ImmutableIntSet)delegate : new ImmutableIntSet(delegate);
+ }
+
+ /** */
+ public static ImmutableIntSet emptySet() {
+ return EMPTY_SET;
+ }
+
+ /**
+ * @param delegate Delegate.
+ */
+ public ImmutableIntSet(Set<Integer> delegate) {
+ this.delegate = delegate;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean contains(int element) {
+ if (delegate instanceof IntSet)
+ return ((IntSet)delegate).contains(element);
+ else
+ return delegate.contains(element);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean containsAll(Collection<?> coll) {
+ return delegate.containsAll(coll);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int size() {
+ return delegate.size();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean contains(Object o) {
+ return delegate.contains(o);
+ }
+
+ /** {@inheritDoc} */
+ @NotNull @Override public Object[] toArray() {
+ return delegate.toArray();
+ }
+
+ /** {@inheritDoc} */
+ @NotNull @Override public <T> T[] toArray(@NotNull T[] a) {
+ return delegate.toArray(a);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int[] toIntArray() {
+ if (delegate instanceof IntSet)
+ return ((IntSet)delegate).toIntArray();
+ else
+ return U.toIntArray(delegate);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return delegate.toString();
+ }
+
+ /** {@inheritDoc} */
+ @NotNull @Override public Iterator<Integer> iterator() {
+ return new Iterator<Integer>() {
+ /** */
+ private final Iterator<? extends Integer> iter = delegate.iterator();
+
+ /** {@inheritDoc} */
+ @Override public boolean hasNext() {
+ return iter.hasNext();
+ }
+
+ /** */
+ @Override public Integer next() {
+ return iter.next();
+ }
+
+ /** */
+ @Override public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** */
+ @Override public void forEachRemaining(Consumer<? super Integer> act) {
+ iter.forEachRemaining(act);
+ }
+ };
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean add(int element) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean remove(int element) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean add(Integer integer) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean addAll(@NotNull Collection<? extends Integer> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean retainAll(@NotNull Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean removeAll(@NotNull Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void forEach(Consumer<? super Integer> act) {
+ delegate.forEach(act);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean removeIf(Predicate<? super Integer> filter) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Spliterator<Integer> spliterator() {
+ return delegate.spliterator();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Stream<Integer> stream() {
+ return delegate.stream();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Stream<Integer> parallelStream() {
+ return delegate.parallelStream();
+ }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntHashMap.java b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntHashMap.java
new file mode 100644
index 0000000..ba68056
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntHashMap.java
@@ -0,0 +1,309 @@
+/*
+ * 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.util.collection;
+
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * The simple map for primitive types base on Robin-hood hashing with backward shift.
+ */
+public class IntHashMap<V> implements IntMap<V> {
+ /** Initial capacity. */
+ public static final int INITIAL_CAPACITY = 8;
+
+ /** Maximum capacity. */
+ public static final int MAXIMUM_CAPACITY = 1 << 30;
+
+ /** Magic hash mixer. */
+ private static final int MAGIC_HASH_MIXER = 0x9E3779B9;
+
+ /** Array load percentage before resize. */
+ private static final float SCALE_LOAD_FACTOR = 0.7F;
+
+ /** Array load percentage before decrise size. */
+ private static final float COMPACT_LOAD_FACTOR = 0.2F;
+
+ /** Scale threshold. */
+ private int scaleThreshold;
+
+ /** Compact threshold. */
+ private int compactThreshold;
+
+ /** Entries. */
+ private Entry<V>[] entries;
+
+ /** Count of elements in Map. */
+ private int size;
+
+ /** Inner entry structure. */
+ private static class Entry<V> {
+ /** Key. */
+ public final int key;
+
+ /** Value. */
+ public final V val;
+
+ /** Default constructor. */
+ Entry(int key, V val) {
+ this.key = key;
+ this.val = val;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "{key=" + key + ", val=" + val + '}';
+ }
+ }
+
+ /** Default constructor. */
+ public IntHashMap() {
+ entries = (Entry<V>[])new Entry[INITIAL_CAPACITY];
+ }
+
+ /** Create map with preallocated array. */
+ public IntHashMap(int cap) {
+ int n = cap - 1;
+ n |= n >>> 1;
+ n |= n >>> 2;
+ n |= n >>> 4;
+ n |= n >>> 8;
+ n |= n >>> 16;
+
+ int entriesSize = (n < INITIAL_CAPACITY) ? INITIAL_CAPACITY : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
+
+ compactThreshold = (int)(COMPACT_LOAD_FACTOR * (entries.length >> 1));
+
+ scaleThreshold = (int)(entries.length * SCALE_LOAD_FACTOR);
+
+ entries = (Entry<V>[])new Entry[entriesSize];
+ }
+
+ /** {@inheritDoc} */
+ @Override public V get(int key) {
+ int idx = find(key);
+
+ return idx < 0 ? null : entries[idx].val;
+ }
+
+ /** {@inheritDoc} */
+ @Override public V put(int key, V val) {
+ return put0(new Entry<>(key, val));
+ }
+
+ /** {@inheritDoc} */
+ @Override public V remove(int key) {
+ if (entries.length != INITIAL_CAPACITY && compactThreshold > size)
+ resize(false);
+
+ int idx = find(key);
+
+ if (idx < 0)
+ return null;
+
+ size--;
+
+ V tmp = entries[idx].val;
+
+ // Backward shift
+ for (int i = 0; i < entries.length; i++) {
+ int curIdx = (idx + i) & (entries.length - 1);
+ int nextIdx = (idx + i + 1) & (entries.length - 1);
+
+ Entry<V> nextEntry = entries[nextIdx];
+
+ if (nextEntry == null || distance(nextIdx, nextEntry.key) == 0) {
+ entries[curIdx] = null;
+
+ return tmp;
+ }
+
+ entries[curIdx] = nextEntry;
+ }
+
+ throw new IllegalStateException("Unreachable state exception. Backward shift has a problem. " +
+ "Removing key: " + key + " map state: " + toString());
+ }
+
+ /** {@inheritDoc} */
+ @Override public V putIfAbsent(int key, V val) {
+ int idx = find(key);
+
+ if (idx < 0) {
+ put(key, val);
+
+ return null;
+ }
+ else
+ return entries[idx].val;
+ }
+
+ /** {@inheritDoc} */
+ @Override public <E extends Throwable> void forEach(EntryConsumer<V, E> act) throws E {
+ for (Entry<V> entry : entries)
+ if (entry != null)
+ act.accept(entry.key, entry.val);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int size() {
+ return size;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isEmpty() {
+ return size() == 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean containsKey(int key) {
+ return find(key) >= 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean containsValue(V val) {
+ return Arrays.stream(entries)
+ .filter(Objects::nonNull)
+ .anyMatch(entry -> Objects.equals(val, entry.val));
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ String strEntries = Arrays.stream(entries)
+ .filter(Objects::nonNull)
+ .map(Entry::toString)
+ .collect(Collectors.joining(","));
+
+ return "IntHashMap{size=" + size + ", entries=[" + strEntries + "]}";
+ }
+
+ /**
+ * Returns size of shift from ideal position computing via index(key).
+ *
+ * @param curIdx Current index.
+ * @param key Target key.
+ */
+ protected int distance(int curIdx, int key) {
+ int keyIdx = index(key);
+
+ return curIdx >= keyIdx ? curIdx - keyIdx : entries.length - keyIdx + curIdx;
+ }
+
+ /**
+ * Position in entites array.
+ *
+ * @param key Targert key.
+ */
+ protected int index(int key) {
+ return (entries.length - 1) & ((key ^ (key >>> 16)) * MAGIC_HASH_MIXER);
+ }
+
+ /**
+ * Does insert of entry.
+ */
+ private V put0(Entry<V> entry) {
+ if (size >= scaleThreshold)
+ resize(true);
+
+ Entry<V> savedEntry = entry;
+
+ int startKey = savedEntry.key;
+
+ for (int i = 0; i < entries.length; i++) {
+ int idx = (index(startKey) + i) & (entries.length - 1);
+
+ Entry<V> curEntry = entries[idx];
+
+ if (curEntry == null) {
+ entries[idx] = savedEntry;
+
+ size++;
+
+ return null;
+ }
+ else if (curEntry.key == savedEntry.key) {
+ entries[idx] = savedEntry;
+
+ return curEntry.val;
+ }
+
+ int curDist = distance(idx, curEntry.key);
+ int savedDist = distance(idx, savedEntry.key);
+
+ if (curDist < savedDist) {
+ entries[idx] = savedEntry;
+
+ savedEntry = curEntry;
+ }
+ }
+
+ throw new IllegalStateException("Unreachable state exception. Insertion position not found. " +
+ "Entry: " + entry + " map state: " + toString());
+ }
+
+ /**
+ * @param key Key.
+ * @return position of element or -1 if absent.
+ */
+ private int find(int key) {
+ int idx = index(key);
+
+ for (int keyDist = 0; keyDist < entries.length; keyDist++) {
+ int curIdx = (idx + keyDist) & (entries.length - 1);
+
+ Entry<V> entry = entries[curIdx];
+
+ if (entry == null)
+ return -1;
+ else if (entry.key == key)
+ return curIdx;
+
+ int entryDist = distance(curIdx, entry.key);
+
+ if (keyDist > entryDist)
+ return -1;
+ }
+
+ return -1;
+ }
+
+ /**
+ * Does resize of entities array.
+ */
+ private void resize(boolean increase) {
+ if (MAXIMUM_CAPACITY == entries.length)
+ throw new IllegalStateException("Maximum capacity: " + MAXIMUM_CAPACITY + " is reached.");
+
+ Entry<V>[] oldEntries = entries;
+
+ int newCap = increase ? entries.length << 1 : entries.length >> 1;
+
+ entries = (Entry<V>[])new Entry[newCap];
+
+ compactThreshold = (int)(COMPACT_LOAD_FACTOR * (entries.length >> 1));
+
+ scaleThreshold = (int)(entries.length * SCALE_LOAD_FACTOR);
+
+ size = 0;
+
+ for (Entry<V> entry : oldEntries)
+ if (entry != null)
+ put0(entry);
+ }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntMap.java b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntMap.java
new file mode 100644
index 0000000..f1bbe51
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntMap.java
@@ -0,0 +1,85 @@
+/*
+ * 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.util.collection;
+
+/**
+ * The map for integer keys.
+ */
+public interface IntMap<V> {
+ /***
+ * The bridge for consuming all entries of the map.
+ */
+ public interface EntryConsumer<V, E extends Throwable> {
+ /**
+ * @param key entry key.
+ * @param val store value.
+ */
+ void accept(int key, V val) throws E;
+ }
+
+ /**
+ * Returns <tt>true</tt> if the map contains the key, otherwise <tt>false</tt>.
+ * @param key tests key value.
+ */
+ boolean containsKey(int key);
+
+ /**
+ * Returns <tt>true</tt> if the map contains one or more values, otherwise <tt>false</tt>.
+ * @param val value to be associated with the specified key.
+ */
+ boolean containsValue(V val);
+
+ /**
+ * Returns value associated with the key. if the map doesn't contain the key, returns null.
+ * @param key key with which the specified value is to be associated.
+ */
+ V get(int key);
+
+ /**
+ * Save the pair into the map. If a pair is present, returns old value and store new.
+ * @param key key with which the specified value is to be associated.
+ * @param val value to be associated with the specified key.
+ */
+ V put(int key, V val);
+
+ /**
+ * @param key key with which the specified value is to be associated.
+ */
+ V remove(int key);
+
+ /**
+ * Does put into the map if a pair isn't present, otherwise returns stored value.
+ * @param key key with which the specified value is to be associated..
+ * @param val value to be associated with the specified key..
+ */
+ V putIfAbsent(int key, V val);
+
+ /**
+ * This method work under a read lock, be careful with long operations inside.
+ * @param act Action.
+ */
+ <E extends Throwable> void forEach(EntryConsumer<V, E> act) throws E;
+
+ /** Returns count of elements. */
+ int size();
+
+ /**
+ * Returns <tt>true</tt> if this map contains no key-value mappings.
+ */
+ boolean isEmpty();
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntRWHashMap.java b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntRWHashMap.java
new file mode 100644
index 0000000..8d379bb
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntRWHashMap.java
@@ -0,0 +1,141 @@
+/*
+ * 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.util.collection;
+
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * Read-write lock wrapper for {@link IntMap}.
+ */
+public class IntRWHashMap<V> implements IntMap<V> {
+ /** RW Lock. */
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+ /** Map delegate. */
+ private final IntHashMap<V> delegate;
+
+ /** Default constructor. */
+ public IntRWHashMap() {
+ delegate = new IntHashMap<>();
+ }
+
+ /** {@inheritDoc} */
+ @Override public V get(int key) {
+ lock.readLock().lock();
+ try {
+ return delegate.get(key);
+ }
+ finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public V put(int key, V val) {
+ lock.writeLock().lock();
+ try {
+ return delegate.put(key, val);
+ }
+ finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public V remove(int key) {
+ lock.writeLock().lock();
+ try {
+ return delegate.remove(key);
+ }
+ finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public V putIfAbsent(int key, V val) {
+ lock.writeLock().lock();
+ try {
+ return delegate.putIfAbsent(key, val);
+ }
+ finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public <E extends Throwable> void forEach(EntryConsumer<V, E> act) throws E {
+ lock.readLock().lock();
+ try {
+ delegate.forEach(act);
+ }
+ finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public int size() {
+ lock.readLock().lock();
+ try {
+ return delegate.size();
+ }
+ finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isEmpty() {
+ return size() == 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean containsKey(int key) {
+ lock.readLock().lock();
+ try {
+ return delegate.containsKey(key);
+ }
+ finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean containsValue(V val) {
+ lock.readLock().lock();
+ try {
+ return delegate.containsValue(val);
+ }
+ finally {
+ lock.readLock().unlock();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ lock.readLock().lock();
+ try {
+ return delegate.toString();
+ }
+ finally {
+ lock.readLock().unlock();
+ }
+ }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntSet.java b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntSet.java
new file mode 100644
index 0000000..caac3d3
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/collection/IntSet.java
@@ -0,0 +1,37 @@
+/*
+ * 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.util.collection;
+
+import java.util.Set;
+
+/**
+ *
+ */
+public interface IntSet extends Set<Integer> {
+ /** Returns <tt>true</tt> if this set contains the specified element. */
+ boolean contains(int element);
+
+ /** Adds the specified element to this set. */
+ boolean add(int element);
+
+ /** Removes the specified element from this set. */
+ boolean remove(int element);
+
+ /** Returns array with primitive types **/
+ int[] toIntArray();
+}
diff --git a/modules/core/src/main/resources/META-INF/classnames.properties b/modules/core/src/main/resources/META-INF/classnames.properties
index 0f14356..bb2747b 100644
--- a/modules/core/src/main/resources/META-INF/classnames.properties
+++ b/modules/core/src/main/resources/META-INF/classnames.properties
@@ -1773,7 +1773,10 @@ org.apache.ignite.internal.transactions.IgniteTxSerializationCheckedException
org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException
org.apache.ignite.internal.transactions.IgniteTxUnexpectedStateCheckedException
org.apache.ignite.internal.transactions.TransactionCheckedException
-org.apache.ignite.internal.util.BitSetIntSet
+org.apache.ignite.internal.util.collection.BitSetIntSet
+org.apache.ignite.internal.util.collection.IntRWHashMap
+org.apache.ignite.internal.util.collection.ImmutableIntSet
+org.apache.ignite.internal.util.collection.IntSet
org.apache.ignite.internal.util.F0$1
org.apache.ignite.internal.util.F0$2
org.apache.ignite.internal.util.F0$3
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2Test.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2Test.java
index f71a06b..d854304 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2Test.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/affinity/GridAffinityAssignmentV2Test.java
@@ -29,7 +29,7 @@ import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.apache.ignite.cluster.ClusterNode;
-import org.apache.ignite.internal.util.BitSetIntSet;
+import org.apache.ignite.internal.util.collection.BitSetIntSet;
import org.apache.ignite.lang.IgniteProductVersion;
import org.apache.ignite.spi.discovery.DiscoveryMetricsProvider;
import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
@@ -154,7 +154,7 @@ public class GridAffinityAssignmentV2Test {
Set<Integer> unwrapped = (Set<Integer>)Whitebox.getInternalState(
gridAffinityAssignment2.primaryPartitions(clusterNode1.id()),
- "c"
+ "delegate"
);
if (AffinityAssignment.IGNITE_DISABLE_AFFINITY_MEMORY_OPTIMIZATION)
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/collection/AbstractBaseIntMapTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/collection/AbstractBaseIntMapTest.java
new file mode 100644
index 0000000..65b5521
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/collection/AbstractBaseIntMapTest.java
@@ -0,0 +1,248 @@
+/*
+ * 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.util.collection;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicLong;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Common map tests.
+ */
+public abstract class AbstractBaseIntMapTest {
+ /**
+ * @return Returns particular implementation of IntMap.
+ */
+ protected abstract IntMap<String> instantiateMap();
+
+ /**
+ *
+ */
+ @Test
+ public void sizeOfMap() {
+ IntMap<String> map = instantiateMap();
+
+ assertTrue(map.isEmpty());
+ assertEquals(0, map.size());
+
+ for (int i = 1; i < 100_000; i++) {
+ map.put(i, value(i));
+ assertFalse(map.isEmpty());
+ assertEquals(i, map.size());
+ }
+
+ for (int i = 99_999; i > 0; i--) {
+ map.remove(i);
+ assertEquals(i-1, map.size());
+ }
+
+ assertTrue(map.isEmpty());
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void getEmpty() {
+ IntMap<String> map = instantiateMap();
+
+ assertNull(map.get(0));
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void putAndGet() {
+ IntMap<String> map = instantiateMap();
+
+ map.put(0, value(0));
+ map.put(239, value(239));
+ map.put(677, value(677));
+
+ assertEquals(value(0), map.get(0));
+ assertEquals(value(239), map.get(239));
+ assertEquals(value(677), map.get(677));
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void getAbsentKey() {
+ IntMap<String> map = instantiateMap();
+
+ map.put(0, value(0));
+ map.put(239, value(239));
+ map.put(677, value(677));
+
+ assertNull(map.get(32));
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void putPresentKey() {
+ IntMap<String> map = instantiateMap();
+
+ map.put(0, value(0));
+ String oldVal = map.put(0, value(1));
+
+ assertEquals(value(0), oldVal);
+ assertEquals(value(1), map.get(0));
+ assertEquals(1, map.size());
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void remove() {
+ IntMap<String> map = instantiateMap();
+
+ map.put(0, value(0));
+
+ assertEquals(value(0), map.remove(0));
+ assertEquals(0, map.size());
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void removeAbsentKey() {
+ IntMap<String> map = instantiateMap();
+
+ assertNull(map.remove(0));
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void putIfAbsent() {
+ IntMap<String> map = instantiateMap();
+
+ String newVal = map.putIfAbsent(1, value(1));
+
+ assertNull(newVal);
+
+ assertEquals(value(1), map.get(1));
+
+ String retry = map.putIfAbsent(1, value(2));
+
+ assertEquals(value(1), retry);
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void forEach() {
+ IntMap<String> map = instantiateMap();
+
+ for (int i = 1; i < 100_000; i++)
+ map.put(i, value(i));
+
+ final AtomicLong cntr = new AtomicLong(0);
+
+ map.forEach((key, value) -> cntr.addAndGet(key));
+
+ assertEquals(99_999L * 100_000L / 2, cntr.get());
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void contains() {
+ IntMap<String> map = instantiateMap();
+
+ for (int i = 1; i < 10_000; i++)
+ map.put(i, value(i));
+
+ for (int i = 1; i < 10_000; i++) {
+ assertTrue(map.containsKey(i));
+ assertTrue(map.containsValue(value(i)));
+ }
+
+ assertFalse(map.containsKey(0));
+ assertFalse(map.containsValue(value(0)));
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void compareWithReferenceImplementation() {
+ Map<Integer, String> originMap = new HashMap<>();
+ IntMap<String> testable = instantiateMap();
+
+ ThreadLocalRandom randomGen = ThreadLocalRandom.current();
+
+ for (int i = 0; i < 10_000_000; i++) {
+ int nextKey = randomGen.nextInt(0, 1_000_000);
+ int actId = randomGen.nextInt(0, 4);
+
+ if (actId == 0) {
+ String oPut = originMap.put(nextKey, value(nextKey));
+ String ePut = testable.put(nextKey, value(nextKey));
+
+ assertEquals(oPut, ePut);
+ assertEquals(originMap.containsKey(nextKey), testable.containsKey(nextKey));
+ }
+ else if (actId == 1) {
+ assertEquals(originMap.get(nextKey), testable.get(nextKey));
+ assertEquals(originMap.containsKey(nextKey), testable.containsKey(nextKey));
+ }
+ else if (actId == 2) {
+ String oPutAbs = originMap.putIfAbsent(nextKey, value(nextKey));
+ String ePutAbs = testable.putIfAbsent(nextKey, value(nextKey));
+
+ assertEquals(oPutAbs, ePutAbs);
+ assertEquals(originMap.containsKey(nextKey), testable.containsKey(nextKey));
+ }
+ else {
+ String oRmv = originMap.remove(nextKey);
+ String eRmv = testable.remove(nextKey);
+
+ assertEquals(oRmv, eRmv);
+ assertEquals(originMap.get(nextKey), testable.get(nextKey));
+ assertEquals(originMap.containsKey(nextKey), testable.containsKey(nextKey));
+ }
+
+ Assert.assertEquals(originMap.size(), testable.size());
+ }
+ }
+
+ /**
+ * @return Returns value by key.
+ */
+ protected String value(int key) {
+ return "Value-" + key;
+ }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/BitSetIntSetTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/collection/BitSetIntSetTest.java
similarity index 62%
rename from modules/core/src/test/java/org/apache/ignite/internal/util/BitSetIntSetTest.java
rename to modules/core/src/test/java/org/apache/ignite/internal/util/collection/BitSetIntSetTest.java
index 0846f80..632e6c9 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/util/BitSetIntSetTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/collection/BitSetIntSetTest.java
@@ -15,15 +15,19 @@
* limitations under the License.
*/
-package org.apache.ignite.internal.util;
+package org.apache.ignite.internal.util.collection;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
/**
*
*/
@@ -41,7 +45,7 @@ public class BitSetIntSetTest extends GridCommonAbstractTest {
*
*/
private void sizeIsEmpty(int initCap) {
- BitSetIntSet bitSetIntSet = initCap != 0 ? new BitSetIntSet(initCap) : new BitSetIntSet();
+ IntSet bitSetIntSet = initCap != 0 ? new BitSetIntSet(initCap) : new BitSetIntSet();
assertEquals(0, bitSetIntSet.size());
assertTrue(bitSetIntSet.isEmpty());
@@ -66,9 +70,55 @@ public class BitSetIntSetTest extends GridCommonAbstractTest {
testIterator(1024);
}
+ @Test(expected = NoSuchElementException.class)
+ public void shouldThrowExceptionIfHasNotNextElement() {
+ IntSet intSet = new BitSetIntSet(2);
+ intSet.add(1);
+ intSet.add(2);
+ Iterator<Integer> iterator = intSet.iterator();
+
+ iterator.next();
+ iterator.next();
+ iterator.next();
+ }
+
+ @Test
+ public void hasNextShouldBeIdempotent() {
+ IntSet intSet = new BitSetIntSet(3);
+ intSet.add(1);
+ intSet.add(2);
+ intSet.add(3);
+ Iterator<Integer> iter = intSet.iterator();
+
+ assertEquals(1, (int) iter.next());
+
+ iter.hasNext();
+ iter.hasNext();
+ iter.hasNext();
+ assertEquals(2, (int) iter.next());
+
+ iter.hasNext();
+ iter.hasNext();
+ assertEquals(3, (int) iter.next());
+ }
+
+ @Test
+ public void toIntArray() {
+ IntSet emptySet = new BitSetIntSet();
+ int[] emptyArr = emptySet.toIntArray();
+ assertThat(emptyArr.length, is(0));
+
+ IntSet withGapsSet = new BitSetIntSet(100, Arrays.asList(43, 23, 53));
+ int[] arr = withGapsSet.toIntArray();
+ assertThat(arr.length, is(3));
+ assertThat(arr[0], is(23));
+ assertThat(arr[1], is(43));
+ assertThat(arr[2], is(53));
+ }
+
/** */
private void testIterator(int initCap) {
- BitSetIntSet bitSet = initCap != 0 ? new BitSetIntSet(initCap) : new BitSetIntSet();
+ IntSet bitSet = initCap != 0 ? new BitSetIntSet(initCap) : new BitSetIntSet();
for (Integer ignored : bitSet)
fail("BitSet is empty, shouldn't be invoked.");
@@ -142,22 +192,22 @@ public class BitSetIntSetTest extends GridCommonAbstractTest {
/** */
@Test
public void testContains() {
- BitSetIntSet bitSetInt = new BitSetIntSet();
-
- bitSetInt.add(1);
- bitSetInt.add(10);
- bitSetInt.add(10);
- bitSetInt.add(11);
- bitSetInt.add(1025);
-
- assertTrue(bitSetInt.contains(1));
- assertFalse(bitSetInt.contains(2));
- assertFalse(bitSetInt.contains(3));
- assertFalse(bitSetInt.contains(4));
- assertTrue(bitSetInt.contains(10));
- assertTrue(bitSetInt.contains(11));
- assertFalse(bitSetInt.contains(1024));
- assertTrue(bitSetInt.contains(1025));
+ IntSet intSet = new BitSetIntSet();
+
+ intSet.add(Integer.valueOf(1));
+ intSet.add(10);
+ intSet.add(10);
+ intSet.add(11);
+ intSet.add(1025);
+
+ assertTrue(intSet.contains(1));
+ assertFalse(intSet.contains(2));
+ assertFalse(intSet.contains(3));
+ assertFalse(intSet.contains(4));
+ assertTrue(intSet.contains(10));
+ assertTrue(intSet.contains(11));
+ assertFalse(intSet.contains(1024));
+ assertTrue(intSet.contains(1025));
}
/**
@@ -165,20 +215,20 @@ public class BitSetIntSetTest extends GridCommonAbstractTest {
*/
@Test
public void testContainsAll() {
- BitSetIntSet bitSetInt = new BitSetIntSet();
+ IntSet intSet = new BitSetIntSet();
- bitSetInt.add(1);
- bitSetInt.add(10);
- bitSetInt.add(10);
- bitSetInt.add(11);
- bitSetInt.add(1025);
+ intSet.add(1);
+ intSet.add(10);
+ intSet.add(10);
+ intSet.add(11);
+ intSet.add(1025);
- assertTrue(bitSetInt.containsAll(new ArrayList<Integer>() {{
+ assertTrue(intSet.containsAll(new ArrayList<Integer>() {{
add(1);
add(10);
}}));
- assertFalse(bitSetInt.containsAll(new ArrayList<Integer>() {{
+ assertFalse(intSet.containsAll(new ArrayList<Integer>() {{
add(1);
add(10);
add(11);
@@ -186,7 +236,7 @@ public class BitSetIntSetTest extends GridCommonAbstractTest {
add(1026);
}}));
- assertFalse(bitSetInt.containsAll(new ArrayList<Integer>() {{
+ assertFalse(intSet.containsAll(new ArrayList<Integer>() {{
add(1);
add(10);
add(12);
@@ -198,22 +248,22 @@ public class BitSetIntSetTest extends GridCommonAbstractTest {
*/
@Test
public void testAddAllRemoveAllRetainAll() {
- BitSetIntSet bitSetInt = new BitSetIntSet();
+ IntSet intSet = new BitSetIntSet();
- bitSetInt.add(1);
- bitSetInt.add(10);
- bitSetInt.add(10);
- bitSetInt.add(11);
- bitSetInt.add(1025);
+ intSet.add(1);
+ intSet.add(10);
+ intSet.add(10);
+ intSet.add(11);
+ intSet.add(1025);
- assertFalse(bitSetInt.addAll(new ArrayList<Integer>() {{
+ assertFalse(intSet.addAll(new ArrayList<Integer>() {{
add(1);
add(10);
}}));
- assertEquals(4, bitSetInt.size());
+ assertEquals(4, intSet.size());
- assertTrue(bitSetInt.addAll(new ArrayList<Integer>() {{
+ assertTrue(intSet.addAll(new ArrayList<Integer>() {{
add(1);
add(10);
add(11);
@@ -221,10 +271,10 @@ public class BitSetIntSetTest extends GridCommonAbstractTest {
add(1026);
}}));
- assertEquals(5, bitSetInt.size());
+ assertEquals(5, intSet.size());
try {
- bitSetInt.retainAll(new ArrayList<Integer>() {{
+ intSet.retainAll(new ArrayList<Integer>() {{
add(10);
add(1025);
}});
@@ -241,17 +291,17 @@ public class BitSetIntSetTest extends GridCommonAbstractTest {
*/
@Test
public void testToArray() {
- BitSetIntSet bitSetInt = new BitSetIntSet();
+ IntSet intSet = new BitSetIntSet();
- assertEquals(0, bitSetInt.toArray().length);
+ assertEquals(0, intSet.toArray().length);
- bitSetInt.add(1);
- bitSetInt.add(10);
- bitSetInt.add(10);
- bitSetInt.add(11);
- bitSetInt.add(1025);
+ intSet.add(1);
+ intSet.add(10);
+ intSet.add(10);
+ intSet.add(11);
+ intSet.add(1025);
- Object[] arr = bitSetInt.toArray();
+ Object[] arr = intSet.toArray();
assertEquals(4, arr.length);
@@ -262,7 +312,7 @@ public class BitSetIntSetTest extends GridCommonAbstractTest {
Integer[] input = new Integer[1];
- Integer[] output = bitSetInt.toArray(input);
+ Integer[] output = intSet.toArray(input);
assertNotSame(input, output);
@@ -275,7 +325,7 @@ public class BitSetIntSetTest extends GridCommonAbstractTest {
input = new Integer[6];
- output = bitSetInt.toArray(input);
+ output = intSet.toArray(input);
assertSame(input, output);
@@ -294,54 +344,34 @@ public class BitSetIntSetTest extends GridCommonAbstractTest {
*/
@Test
public void testInvalidValues() {
- BitSetIntSet bitSetInt = new BitSetIntSet();
+ IntSet intSet = new BitSetIntSet();
try {
- bitSetInt.add(null);
+ intSet.add(null);
fail("add should fail here");
}
- catch (UnsupportedOperationException ignored) {
+ catch (IllegalArgumentException ignored) {
// Ignored.
}
try {
- bitSetInt.add(-1);
+ intSet.add(-1);
fail("add should fail here");
}
- catch (UnsupportedOperationException ignored) {
+ catch (IllegalArgumentException ignored) {
// Ignored.
}
try {
- bitSetInt.contains(null);
+ intSet.contains(null);
fail("contains should fail here");
}
- catch (UnsupportedOperationException ignored) {
+ catch (NullPointerException ignored) {
// Ignored.
}
- try {
- bitSetInt.contains(-1);
- fail("contains should fail here");
- }
- catch (UnsupportedOperationException ignored) {
- // Ignored.
- }
-
- try {
- bitSetInt.remove(null);
- fail("remove should fail here");
- }
- catch (UnsupportedOperationException ignored) {
- // Ignored.
- }
-
- try {
- bitSetInt.remove(-1);
- fail("remove should fail here");
- }
- catch (UnsupportedOperationException ignored) {
- // Ignored.
- }
+ assertFalse(intSet.contains(-1));
+ assertFalse(intSet.remove(null));
+ assertFalse(intSet.remove(-1));
}
}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/collection/ImmutableIntSetTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/collection/ImmutableIntSetTest.java
new file mode 100644
index 0000000..e323cb0
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/collection/ImmutableIntSetTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.util.collection;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import org.junit.Test;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test for immutable int set wrapper
+ */
+public class ImmutableIntSetTest {
+ /** */
+ @Test
+ public void shouldWrapHashSet() {
+ IntSet immutableSet = ImmutableIntSet.wrap(new HashSet<>(Arrays.asList(2)));
+
+ assertTrue(immutableSet.contains(2));
+ assertFalse(immutableSet.contains(1));
+ }
+
+ /** */
+ @Test
+ public void emptySet() {
+ ImmutableIntSet emptySet = ImmutableIntSet.emptySet();
+
+ assertTrue(emptySet.isEmpty());
+ assertThat(emptySet.size(), is(0));
+ }
+
+ /** */
+ @Test
+ public void toIntArray() {
+ IntSet hashSet = ImmutableIntSet.wrap(new HashSet<>(Arrays.asList(2)));
+ int[] fromHash = hashSet.toIntArray();
+ assertThat(fromHash.length, is(1));
+ assertThat(fromHash[0], is(2));
+
+ IntSet bitSet = ImmutableIntSet.wrap(new BitSetIntSet(2, Arrays.asList(2)));
+ int[] fromBit = bitSet.toIntArray();
+ assertThat(fromBit.length, is(1));
+ assertThat(fromBit[0], is(2));
+ }
+
+ /** */
+ @Test
+ public void contains() {
+ IntSet immutableSet = ImmutableIntSet.wrap(new BitSetIntSet(2, Arrays.asList(2)));
+
+ assertThat(immutableSet.size(), is(1));
+ assertFalse(immutableSet.isEmpty());
+
+ assertTrue(immutableSet.contains(2));
+ assertFalse(immutableSet.contains(1));
+ }
+
+ /** */
+ @Test(expected = UnsupportedOperationException.class)
+ public void throwExceptionForAddOperation() {
+ IntSet immutableSet = ImmutableIntSet.wrap(new BitSetIntSet(4));
+
+ immutableSet.add(1);
+ }
+
+ /** */
+ @Test(expected = UnsupportedOperationException.class)
+ public void throwExceptionForRemoveOperation() {
+ IntSet immutableSet = ImmutableIntSet.wrap(new BitSetIntSet(2, Arrays.asList(2)));
+
+ immutableSet.remove(2);
+ }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/collection/IntHashMapTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/collection/IntHashMapTest.java
new file mode 100644
index 0000000..0af34c9
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/collection/IntHashMapTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.util.collection;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.apache.ignite.internal.util.collection.IntHashMap.INITIAL_CAPACITY;
+import static org.apache.ignite.internal.util.collection.IntHashMap.MAXIMUM_CAPACITY;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for the specific implementation of IntMap.
+ */
+public class IntHashMapTest extends AbstractBaseIntMapTest {
+ /** {@inheritDoc} */
+ @Override protected IntMap<String> instantiateMap() {
+ return new IntHashMap<>();
+ }
+
+ /** */
+ @Test
+ public void removeBackShift() {
+ HashMap<Integer, Integer> bijection = new HashMap<>();
+ bijection.put(1, 14);
+ bijection.put(2, 14);
+ bijection.put(3, 14);
+ bijection.put(4, 14);
+ bijection.put(5, 14);
+
+ IntMap<String> directPositionMap = bijectionHashFunctionMap(bijection);
+
+ directPositionMap.put(1, value(1));
+ directPositionMap.put(2, value(2));
+ directPositionMap.put(3, value(3));
+ directPositionMap.put(4, value(4));
+ directPositionMap.put(5, value(5));
+
+ directPositionMap.remove(1);
+
+ Assert.assertEquals(4, directPositionMap.size());
+ }
+
+ /** */
+ @Test
+ public void distance() {
+ HashMap<Integer, Integer> bijection = new HashMap<>();
+ bijection.put(1, 14);
+ bijection.put(2, 14);
+ bijection.put(3, 14);
+ bijection.put(4, 14);
+ bijection.put(5, 14);
+ bijection.put(6, 14);
+ bijection.put(7, 14);
+ bijection.put(8, 14);
+ bijection.put(9, 14);
+
+ IntHashMap<String> directPositionMap = (IntHashMap<String>)bijectionHashFunctionMap(bijection);
+
+ directPositionMap.put(1, value(1));
+ directPositionMap.put(2, value(2));
+ directPositionMap.put(3, value(3));
+ directPositionMap.put(4, value(4));
+ directPositionMap.put(5, value(5));
+ directPositionMap.put(6, value(6));
+ directPositionMap.put(7, value(7));
+ directPositionMap.put(8, value(8));
+ directPositionMap.put(9, value(9));
+
+ assertEquals(0, directPositionMap.distance(14, 1));
+ assertEquals(1, directPositionMap.distance(15, 1));
+ assertEquals(2, directPositionMap.distance(0, 1));
+ assertEquals(3, directPositionMap.distance(1, 1));
+ assertEquals(4, directPositionMap.distance(2, 1));
+ assertEquals(5, directPositionMap.distance(3, 1));
+ assertEquals(15, directPositionMap.distance(13, 1));
+ }
+
+ /**
+ *
+ */
+ @Test
+ public void shouldAllocateMapWithInitialCapacity() {
+ assertEquals(INITIAL_CAPACITY, realCapacityForInitialSize(1));
+ assertEquals(16, realCapacityForInitialSize(9));
+ assertEquals(128, realCapacityForInitialSize(99));
+ assertEquals(256, realCapacityForInitialSize(155));
+ assertEquals(MAXIMUM_CAPACITY, realCapacityForInitialSize(Integer.MAX_VALUE));
+ }
+
+ /**
+ * @param initSize Initial size.
+ */
+ private int realCapacityForInitialSize(int initSize) {
+ return ((Object[]) U.field(new IntHashMap<String>(initSize), "entries")).length;
+ }
+
+ /**
+ * @param bijection Bijection.
+ */
+ private IntMap<String> bijectionHashFunctionMap(Map<Integer, Integer> bijection) {
+ return new IntHashMap<String>() {
+ @Override protected int index(int key) {
+ return bijection.get(key);
+ }
+ };
+ }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/collection/IntRWHashMapTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/collection/IntRWHashMapTest.java
new file mode 100644
index 0000000..16b6d56
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/util/collection/IntRWHashMapTest.java
@@ -0,0 +1,28 @@
+/*
+ * 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.util.collection;
+
+/**
+ * Base scenarios for read-write map.
+ */
+public class IntRWHashMapTest extends AbstractBaseIntMapTest {
+ /** {@inheritDoc} */
+ @Override protected IntMap<String> instantiateMap() {
+ return new IntRWHashMap<>();
+ }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
index 3d5bfe2..d6b9b99 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
@@ -87,7 +87,8 @@ import org.apache.ignite.internal.processors.metastorage.persistence.Distributed
import org.apache.ignite.internal.processors.odbc.OdbcConfigurationValidationSelfTest;
import org.apache.ignite.internal.processors.odbc.OdbcEscapeSequenceSelfTest;
import org.apache.ignite.internal.product.GridProductVersionSelfTest;
-import org.apache.ignite.internal.util.BitSetIntSetTest;
+import org.apache.ignite.internal.util.collection.BitSetIntSetTest;
+import org.apache.ignite.internal.util.collection.ImmutableIntSetTest;
import org.apache.ignite.internal.util.GridCleanerTest;
import org.apache.ignite.internal.util.nio.IgniteExceptionInNioWorkerSelfTest;
import org.apache.ignite.marshaller.DynamicProxySerializationMultiJvmSelfTest;
@@ -198,6 +199,7 @@ import org.junit.runners.Suite;
DataRegionMetricsSelfTest.class,
SwapPathConstructionSelfTest.class,
BitSetIntSetTest.class,
+ ImmutableIntSetTest.class,
IgniteMarshallerCacheFSRestoreTest.class,
IgniteMarshallerCacheClassNameConflictTest.class,