Skip to content

Commit

Permalink
IGNITE-2365 - Notify policy if swap or offheap is enabled and rebalan…
Browse files Browse the repository at this point in the history
…ced entry was not preloaded.

IGNITE-2099 - Fixing custom collections.
This closes #396
  • Loading branch information
agoncharuk committed Jan 15, 2016
1 parent 2af1d9b commit 6524c79
Show file tree
Hide file tree
Showing 10 changed files with 515 additions and 72 deletions.
Expand Up @@ -589,6 +589,43 @@ public static boolean isBinaryType(Class<?> cls) {
(cls.isArray() && cls.getComponentType().isEnum());
}

/**
* @param map Map to check.
* @return {@code True} if this map type is supported.
*/
public static boolean knownMap(Object map) {
Class<?> cls = map == null ? null : map.getClass();

return cls == HashMap.class ||
cls == LinkedHashMap.class ||
cls == TreeMap.class ||
cls == ConcurrentHashMap8.class ||
cls == ConcurrentHashMap.class;
}

/**
* Attempts to create a new map of the same known type. Will return null if map type is not supported.
*
* @param map Map.
* @return New map of the same type or null.
*/
public static <K, V> Map<K, V> newKnownMap(Object map) {
Class<?> cls = map == null ? null : map.getClass();

if (cls == HashMap.class)
return U.newHashMap(((Map)map).size());
else if (cls == LinkedHashMap.class)
return U.newLinkedHashMap(((Map)map).size());
else if (cls == TreeMap.class)
return new TreeMap<>(((TreeMap<Object, Object>)map).comparator());
else if (cls == ConcurrentHashMap8.class)
return new ConcurrentHashMap8<>(U.capacity(((Map)map).size()));
else if (cls == ConcurrentHashMap.class)
return new ConcurrentHashMap<>(U.capacity(((Map)map).size()));

return null;
}

/**
* Attempts to create a new map of the same type as {@code map} has. Otherwise returns new {@code HashMap} instance.
*
Expand All @@ -608,6 +645,47 @@ else if (map instanceof ConcurrentHashMap)
return U.newHashMap(map.size());
}

/**
* @param col Collection to check.
* @return True if this is a collection of a known type.
*/
public static boolean knownCollection(Object col) {
Class<?> cls = col == null ? null : col.getClass();

return cls == HashSet.class ||
cls == LinkedHashSet.class ||
cls == TreeSet.class ||
cls == ConcurrentSkipListSet.class ||
cls == ArrayList.class ||
cls == LinkedList.class;
}

/**
* Attempts to create a new collection of the same known type. Will return null if collection type is
* unknown.
*
* @param col Collection.
* @return New empty collection.
*/
public static <V> Collection<V> newKnownCollection(Object col) {
Class<?> cls = col == null ? null : col.getClass();

if (cls == HashSet.class)
return U.newHashSet(((Collection)col).size());
else if (cls == LinkedHashSet.class)
return U.newLinkedHashSet(((Collection)col).size());
else if (cls == TreeSet.class)
return new TreeSet<>(((TreeSet<Object>)col).comparator());
else if (cls == ConcurrentSkipListSet.class)
return new ConcurrentSkipListSet<>(((ConcurrentSkipListSet<Object>)col).comparator());
else if (cls == ArrayList.class)
return new ArrayList<>(((Collection)col).size());
else if (cls == LinkedList.class)
return new LinkedList<>();

return null;
}

/**
* Attempts to create a new set of the same type as {@code set} has. Otherwise returns new {@code HashSet} instance.
*
Expand Down
Expand Up @@ -19,8 +19,11 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import org.apache.ignite.cache.affinity.AffinityKeyMapper;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.binary.BinaryUtils;
Expand Down Expand Up @@ -161,13 +164,25 @@ public Collection<Object> unwrapBinariesIfNeeded(Collection<Object> col, boolean
* @return Unwrapped collection.
*/
public Collection<Object> unwrapBinariesIfNeeded(Collection<Object> col, boolean keepBinary, boolean cpy) {
if (col instanceof ArrayList)
return unwrapBinaries((ArrayList<Object>)col, keepBinary, cpy);
Collection<Object> col0 = BinaryUtils.newKnownCollection(col);

if (col instanceof Set)
return unwrapBinaries((Set<Object>)col, keepBinary, cpy);
if (col0 == null)
col0 = new ArrayList<>(col.size());

Collection<Object> col0 = new ArrayList<>(col.size());
for (Object obj : col)
col0.add(unwrapBinary(obj, keepBinary, cpy));

return col0;
}

/**
* @param col Collection to unwrap.
* @param keepBinary Keep binary flag.
* @param cpy Copy flag.
* @return Unwrapped collection.
*/
private Collection<Object> unwrapKnownCollection(Collection<Object> col, boolean keepBinary, boolean cpy) {
Collection<Object> col0 = BinaryUtils.newKnownCollection(col);

for (Object obj : col)
col0.add(unwrapBinary(obj, keepBinary, cpy));
Expand Down Expand Up @@ -211,44 +226,6 @@ private Map<Object, Object> unwrapBinariesIfNeeded(Map<Object, Object> map, bool
return map0;
}

/**
* Unwraps array list.
*
* @param col List to unwrap.
* @return Unwrapped list.
*/
private Collection<Object> unwrapBinaries(ArrayList<Object> col, boolean keepBinary, boolean cpy) {
int size = col.size();

col = new ArrayList<>(col);

for (int i = 0; i < size; i++) {
Object o = col.get(i);

Object unwrapped = unwrapBinary(o, keepBinary, cpy);

if (o != unwrapped)
col.set(i, unwrapped);
}

return col;
}

/**
* Unwraps set with binary.
*
* @param set Set to unwrap.
* @return Unwrapped set.
*/
private Set<Object> unwrapBinaries(Set<Object> set, boolean keepBinary, boolean cpy) {
Set<Object> set0 = BinaryUtils.newSet(set);

for (Object obj : set)
set0.add(unwrapBinary(obj, keepBinary, cpy));

return set0;
}

/**
* @param o Object to unwrap.
* @return Unwrapped object.
Expand All @@ -267,9 +244,9 @@ private Object unwrapBinary(Object o, boolean keepBinary, boolean cpy) {

return (key != uKey || val != uVal) ? F.t(uKey, uVal) : o;
}
else if (o instanceof Collection)
return unwrapBinariesIfNeeded((Collection<Object>)o, keepBinary, cpy);
else if (o instanceof Map)
else if (BinaryUtils.knownCollection(o))
return unwrapKnownCollection((Collection<Object>)o, keepBinary, cpy);
else if (BinaryUtils.knownMap(o))
return unwrapBinariesIfNeeded((Map<Object, Object>)o, keepBinary, cpy);
else if (o instanceof Object[])
return unwrapBinariesInArrayIfNeeded((Object[])o, keepBinary, cpy);
Expand All @@ -282,4 +259,24 @@ else if (o instanceof CacheObject) {

return o;
}

/**
* @param o Object to test.
* @return True if collection should be recursively unwrapped.
*/
private boolean knownCollection(Object o) {
Class<?> cls = o == null ? null : o.getClass();

return cls == ArrayList.class || cls == LinkedList.class || cls == HashSet.class;
}

/**
* @param o Object to test.
* @return True if map should be recursively unwrapped.
*/
private boolean knownMap(Object o) {
Class<?> cls = o == null ? null : o.getClass();

return cls == HashMap.class || cls == LinkedHashMap.class;
}
}
Expand Up @@ -402,31 +402,30 @@ public Object unmarshal(long ptr, boolean forceHeap) throws BinaryObjectExceptio
return new IgniteBiTuple<>(marshalToBinary(tup.get1()), marshalToBinary(tup.get2()));
}

if (obj instanceof Collection) {
Collection<Object> col = (Collection<Object>)obj;
{
Collection<Object> pCol = BinaryUtils.newKnownCollection(obj);

Collection<Object> pCol;
if (pCol != null) {
Collection<?> col = (Collection<?>)obj;

if (col instanceof Set)
pCol = (Collection<Object>)BinaryUtils.newSet((Set<?>)col);
else
pCol = new ArrayList<>(col.size());
for (Object item : col)
pCol.add(marshalToBinary(item));

for (Object item : col)
pCol.add(marshalToBinary(item));

return pCol;
return pCol;
}
}

if (obj instanceof Map) {
Map<?, ?> map = (Map<?, ?>)obj;
{
Map<Object, Object> pMap = BinaryUtils.newKnownMap(obj);

Map<Object, Object> pMap = BinaryUtils.newMap((Map<Object, Object>)obj);
if (pMap != null) {
Map<?, ?> map = (Map<?, ?>)obj;

for (Map.Entry<?, ?> e : map.entrySet())
pMap.put(marshalToBinary(e.getKey()), marshalToBinary(e.getValue()));
for (Map.Entry<?, ?> e : map.entrySet())
pMap.put(marshalToBinary(e.getKey()), marshalToBinary(e.getValue()));

return pMap;
return pMap;
}
}

if (obj instanceof Map.Entry) {
Expand Down
Expand Up @@ -696,9 +696,14 @@ private boolean preloadEntry(
(IgniteUuid)null, null, EVT_CACHE_REBALANCE_OBJECT_LOADED, entry.value(), true, null,
false, null, null, null, true);
}
else if (log.isDebugEnabled())
log.debug("Rebalancing entry is already in cache (will ignore) [key=" + cached.key() +
", part=" + p + ']');
else {
if (cctx.isSwapOrOffheapEnabled())
cctx.evicts().touch(cached, topVer); // Start tracking.

if (log.isDebugEnabled())
log.debug("Rebalancing entry is already in cache (will ignore) [key=" + cached.key() +
", part=" + p + ']');
}
}
else if (log.isDebugEnabled())
log.debug("Rebalance predicate evaluated to false for entry (will ignore): " + entry);
Expand Down
Expand Up @@ -113,7 +113,7 @@ public void testNull() throws Exception {
* @throws Exception If failed.
*/
public void testByte() throws Exception {
assertEquals((byte) 100, marshalUnmarshal((byte)100).byteValue());
assertEquals((byte)100, marshalUnmarshal((byte)100).byteValue());
}

/**
Expand Down Expand Up @@ -401,7 +401,7 @@ public void testCustomCollections() throws Exception {
CustomCollections cc = new CustomCollections();

cc.list.add(1);
cc.customList.add(2);
cc.customList.add(new Value(1));

CustomCollections copiedCc = marshalUnmarshal(cc);

Expand All @@ -414,6 +414,28 @@ public void testCustomCollections() throws Exception {
assertEquals(cc.customList.get(0), copiedCc.customList.get(0));
}

/**
* Test serialization of custom collections.
*
* @throws Exception If failed.
*/
@SuppressWarnings("unchecked")
public void testCustomCollections2() throws Exception {
CustomArrayList arrList = new CustomArrayList();

arrList.add(1);

Object cp = marshalUnmarshal(arrList);

assert cp.getClass().equals(CustomArrayList.class);

CustomArrayList customCp = (CustomArrayList)cp;

assertEquals(customCp.size(), arrList.size());

assertEquals(customCp.get(0), arrList.get(0));
}

/**
* Test custom collections with factories.
*
Expand Down Expand Up @@ -3958,6 +3980,24 @@ private Value() {
private Value(int val) {
this.val = val;
}

/** {@inheritDoc} */
@Override public boolean equals(Object o) {
if (this == o)
return true;

if (!(o instanceof Value))
return false;

Value value = (Value)o;

return val == value.val;
}

/** {@inheritDoc} */
@Override public int hashCode() {
return val;
}
}

/**
Expand Down
Expand Up @@ -17,6 +17,7 @@

package org.apache.ignite.internal.processors.cache;

import java.util.ArrayList;
import java.util.Arrays;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
Expand Down Expand Up @@ -306,7 +307,7 @@ public void testDeployment5() throws Exception {

assert cache != null;

cache.put(key, Arrays.asList(val1Cls.newInstance()));
cache.put(key, new ArrayList<>(Arrays.asList(val1Cls.newInstance())));

info(">>>>>>> First put completed.");

Expand Down

0 comments on commit 6524c79

Please sign in to comment.