You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2015/07/21 03:55:43 UTC

[50/50] [abbrv] incubator-ignite git commit: IGNITE-950 - Fixed compilation WIP

IGNITE-950 - Fixed compilation WIP


Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/680ffa0b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/680ffa0b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/680ffa0b

Branch: refs/heads/ignite-950
Commit: 680ffa0b1e841fccce9a7a16c2d213b32274f8a9
Parents: 4f63227
Author: Alexey Goncharuk <ag...@gridgain.com>
Authored: Mon Jul 20 18:54:36 2015 -0700
Committer: Alexey Goncharuk <ag...@gridgain.com>
Committed: Mon Jul 20 18:54:36 2015 -0700

----------------------------------------------------------------------
 .../apache/ignite/cache/CacheTypeMetadata.java  |  48 +++-
 .../configuration/CacheConfiguration.java       |  23 ++
 .../ignite/internal/IgniteComponentType.java    |   2 +-
 .../processors/cache/CacheIndexedObject.java    |  56 +++++
 ...CacheIndexedObjectDefaultAffinityMapper.java |  61 +++++
 .../cache/CacheIndexedObjectImpl.java           |  95 ++++----
 .../internal/processors/cache/CacheObject.java  |   1 +
 .../processors/cache/CacheObjectContext.java    |  65 ++++--
 .../processors/cache/GridCacheContext.java      |  20 +-
 .../cache/KeyCacheIndexedObjectImpl.java        |   9 +-
 .../cache/store/CacheOsStoreManager.java        |   5 -
 .../store/GridCacheStoreManagerAdapter.java     |  28 +--
 .../cacheobject/IgniteCacheObjectProcessor.java |  68 +++---
 .../IgniteCacheObjectProcessorImpl.java         | 228 +++++++++++--------
 .../processors/query/GridQueryProcessor.java    |  87 +++++--
 .../ignite/internal/util/IgniteUtils.java       |   9 +-
 .../optimized/OptimizedMarshaller.java          |   5 +-
 .../OptimizedMarshallerIndexingHandler.java     |   9 +-
 .../optimized/OptimizedObjectInputStream.java   |   4 +-
 .../OptimizedMarshallerExtSelfTest.java         |  58 +++--
 .../processors/query/h2/IgniteH2Indexing.java   |   9 +-
 21 files changed, 587 insertions(+), 303 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/cache/CacheTypeMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/CacheTypeMetadata.java b/modules/core/src/main/java/org/apache/ignite/cache/CacheTypeMetadata.java
index 49177c3..1cd6d29 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/CacheTypeMetadata.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/CacheTypeMetadata.java
@@ -31,6 +31,9 @@ import java.util.*;
  * Cache type metadata need for configuration of indexes or automatic persistence.
  */
 public class CacheTypeMetadata implements Serializable {
+    /** Default query type flag value. */
+    public static final boolean DFLT_QRY_TYPE = true;
+
     /** */
     private static final long serialVersionUID = 0L;
 
@@ -81,6 +84,12 @@ public class CacheTypeMetadata implements Serializable {
     @GridToStringInclude
     private Map<String,String> aliases;
 
+    /** Affinity key field name for the cases when marshaller is used to access object fields. */
+    private String affKeyFieldName;
+
+    /** Query type flag. May be set to {@code false} if */
+    private boolean qryType = DFLT_QRY_TYPE;
+
     /**
      * Default constructor.
      */
@@ -204,7 +213,7 @@ public class CacheTypeMetadata implements Serializable {
 
         this.valType = valType;
 
-        Class<?> cls = U.classForName(valType, null);
+        Class<?> cls = U.classForName(valType, null, null);
 
         simpleValType = cls == null ? valType : GridQueryProcessor.typeName(cls);
     }
@@ -371,6 +380,43 @@ public class CacheTypeMetadata implements Serializable {
         return aliases;
     }
 
+    /**
+     * Gets affinity key field name.
+     *
+     * @return Affinity key field name.
+     */
+    public String getAffinityKeyFieldName() {
+        return affKeyFieldName;
+    }
+
+    /**
+     * Sets affinity key field name.
+     *
+     * @param affKeyFieldName Affinity key field name.
+     */
+    public void setAffinityKeyFieldName(String affKeyFieldName) {
+        this.affKeyFieldName = affKeyFieldName;
+    }
+
+    /**
+     * Returns the flag indicating whether this type metadata descriptor should be used to define indexing.
+     * Default value is {@link #DFLT_QRY_TYPE}.
+     *
+     * @return {@code True} if the corresponding key-value pairs should be indexed.
+     */
+    public boolean isQueryType() {
+        return qryType;
+    }
+
+    /**
+     * Sets the flag indicating whether this type metadata descriptor should be used to define indexing.
+     *
+     * @param qryType If {@code true}, the corresponding key-value type will be indexed.
+     */
+    public void setQueryType(boolean qryType) {
+
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(CacheTypeMetadata.class, this);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
index 0468cbf..dbe229e 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
@@ -322,6 +322,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
     /** Cache store session listeners. */
     private Factory<? extends CacheStoreSessionListener>[] storeSesLsnrs;
 
+    /** Flag indicating to pass Ignite objects to store when field-aware marshalling is enabled. */
+    private boolean keepIgniteObjInStore;
+
     /** Empty constructor (all values are initialized to their defaults). */
     public CacheConfiguration() {
         /* No-op. */
@@ -1807,6 +1810,26 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
     }
 
     /**
+     * Flag indicating whether Ignite objects should be passed as-is to cache store (without deserialization) when
+     * field-aware marshalling is enabled.
+     *
+     * @return Value for the keep Ignite objects in store flag.
+     */
+    public boolean isKeepIgniteObjectInStore() {
+        return keepIgniteObjInStore;
+    }
+
+    /**
+     * Sets flag indicating whether Ignite objects should be passed as-is (without deserialization) when
+     * field-aware marshalling is enabled.
+     *
+     * @param keepIgniteObjInStore Value for the keep Ignite objects in store flag.
+     */
+    public void setKeepIgniteObjectInStore(boolean keepIgniteObjInStore) {
+        this.keepIgniteObjInStore = keepIgniteObjInStore;
+    }
+
+    /**
      * @param desc Type descriptor.
      * @return Type metadata.
      */

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/IgniteComponentType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteComponentType.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteComponentType.java
index 4b937b1..799956c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteComponentType.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteComponentType.java
@@ -300,7 +300,7 @@ public enum IgniteComponentType {
     @Nullable public MessageFactory messageFactory() throws IgniteCheckedException {
         Class<?> cls;
 
-        if (msgFactoryCls == null || null == (cls = U.classForName(msgFactoryCls, null)))
+        if (msgFactoryCls == null || null == (cls = U.classForName(msgFactoryCls, null, null)))
             return null;
 
         return (MessageFactory)U.newInstance(cls);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObject.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObject.java
new file mode 100644
index 0000000..de931a2
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObject.java
@@ -0,0 +1,56 @@
+/*
+ * 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.processors.cache;
+
+import org.apache.ignite.*;
+import org.jetbrains.annotations.*;
+
+/**
+ *
+ */
+public interface CacheIndexedObject extends CacheObject {
+    /**
+     * Gets portable object type ID.
+     *
+     * @return Type ID.
+     */
+    public int typeId();
+
+    /**
+     * Gets fully deserialized instance of portable object.
+     *
+     * @return Fully deserialized instance of portable object.
+     */
+    @Nullable public <T> T deserialize() throws IgniteException;
+
+    /**
+     * Gets field value.
+     *
+     * @param fieldName Field name.
+     * @return Field value.
+     */
+    @Nullable public <T> T field(String fieldName);
+
+    /**
+     * Checks whether field is set.
+     *
+     * @param fieldName Field name.
+     * @return {@code true} if field is set.
+     */
+    public boolean hasField(String fieldName);
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectDefaultAffinityMapper.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectDefaultAffinityMapper.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectDefaultAffinityMapper.java
new file mode 100644
index 0000000..b896f55
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectDefaultAffinityMapper.java
@@ -0,0 +1,61 @@
+/*
+ * 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.processors.cache;
+
+import org.apache.ignite.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.internal.processors.cacheobject.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.apache.ignite.resources.*;
+
+/**
+ *
+ */
+public class CacheIndexedObjectDefaultAffinityMapper extends GridCacheDefaultAffinityKeyMapper {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Cache name resource. */
+    @CacheNameResource
+    private String cacheName;
+
+    /** Cache object context. */
+    private transient CacheObjectContext objCtx;
+
+    /** {@inheritDoc} */
+    @Override public Object affinityKey(Object key) {
+        IgniteEx kernal = (IgniteEx)ignite;
+
+        if (objCtx == null)
+            objCtx = kernal.context().cache().cache(cacheName).context().cacheObjectContext();
+
+        IgniteCacheObjectProcessor proc = kernal.context().cacheObjects();
+
+        try {
+            key = proc.toCacheKeyObject(objCtx, key, true);
+        }
+        catch (IgniteException e) {
+            U.error(log, "Failed to marshal key to portable: " + key, e);
+        }
+
+        if (proc.isIndexedObject(key))
+            return proc.affinityKey((CacheIndexedObject)key);
+        else
+            return super.affinityKey(key);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java
index 6e567eb..852f9df 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java
@@ -31,7 +31,7 @@ import java.nio.*;
  * Cache object implementation for classes that support footer injection is their serialized form thus enabling fields
  * search and extraction without necessity to fully deserialize an object.
  */
-public class CacheIndexedObjectImpl extends CacheObjectAdapter {
+public class CacheIndexedObjectImpl extends CacheObjectAdapter implements CacheIndexedObject {
     /** */
     private static final long serialVersionUID = 0L;
 
@@ -42,7 +42,7 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
     private static final long BYTE_ARR_OFF = UNSAFE.arrayBaseOffset(byte[].class);
 
     /** */
-    private Boolean hasClass;
+    private CacheObjectContext ctx;
 
     /** */
     protected int start;
@@ -61,8 +61,8 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
      * Instantiates {@code CacheIndexedObjectImpl} with object.
      * @param val Object.
      */
-    public CacheIndexedObjectImpl(Object val) {
-        this(val, null, 0, 0);
+    public CacheIndexedObjectImpl(CacheObjectContext ctx, Object val) {
+        this(ctx, val, null, 0, 0);
     }
 
     /**
@@ -71,8 +71,8 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
      * @param start Object's start in the array.
      * @param len Object's len in the array.
      */
-    public CacheIndexedObjectImpl(byte[] valBytes, int start, int len) {
-        this(null, valBytes, start, len);
+    public CacheIndexedObjectImpl(CacheObjectContext ctx, byte[] valBytes, int start, int len) {
+        this(ctx, null, valBytes, start, len);
     }
 
     /**
@@ -80,8 +80,8 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
      * @param val Object.
      * @param valBytes Object serialized to byte array.
      */
-    public CacheIndexedObjectImpl(Object val, byte[] valBytes) {
-        this(val, valBytes, 0, valBytes != null ? valBytes.length : 0);
+    public CacheIndexedObjectImpl(CacheObjectContext ctx, Object val, byte[] valBytes) {
+        this(ctx, val, valBytes, 0, valBytes != null ? valBytes.length : 0);
     }
 
     /**
@@ -91,9 +91,10 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
      * @param start Object's start in the array.
      * @param len Object's len in the array.
      */
-    public CacheIndexedObjectImpl(Object val, byte[] valBytes, int start, int len) {
+    public CacheIndexedObjectImpl(CacheObjectContext ctx, Object val, byte[] valBytes, int start, int len) {
         assert val != null || (valBytes != null && start >= 0 && len > 0);
 
+        this.ctx = ctx;
         this.val = val;
         this.valBytes = valBytes;
         this.start = start;
@@ -121,6 +122,8 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
     @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException {
         assert valBytes != null;
 
+        this.ctx = ctx;
+
         if (val == null && keepDeserialized(ctx, true))
             val = ctx.processor().unmarshal(ctx, valBytes, start, len, ldr);
     }
@@ -146,7 +149,7 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
      *
      * @return Type ID.
      */
-    public int typeId() {
+    @Override public int typeId() {
         assert valBytes != null;
 
         int typeId = UNSAFE.getInt(valBytes, BYTE_ARR_OFF + start + 1);
@@ -161,40 +164,47 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
      * Checks whether a wrapped object has field with name {@code fieldName}.
      *
      * @param fieldName Field name.
-     * @param marsh Marshaller.
      * @return {@code true} if has.
-     * @throws IgniteCheckedException In case of error.
+     * @throws IgniteException In case of error.
      */
-    public boolean hasField(String fieldName, OptimizedMarshaller marsh) throws IgniteCheckedException {
+    @Override public boolean hasField(String fieldName) {
         assert valBytes != null;
 
-        return marsh.hasField(fieldName, valBytes, start, len);
+        try {
+            OptimizedMarshaller marsh = (OptimizedMarshaller)ctx.kernalContext().config().getMarshaller();
+
+            return marsh.hasField(fieldName, valBytes, start, len);
+        }
+        catch (IgniteCheckedException e) {
+            throw new IgniteException(e);
+        }
     }
 
     /**
      * Searches and returns field if it exists.
      *
      * @param fieldName Field name.
-     * @param marsh Marshaller.
      * @return Field.
-     * @throws IgniteFieldNotFoundException In case if there is no such a field.
-     * @throws IgniteCheckedException In case of error.
+     * @throws IgniteException In case of error.
      */
-    public Object field(String fieldName, OptimizedMarshaller marsh) throws IgniteCheckedException {
+    @Override public <T> T field(String fieldName) {
         assert valBytes != null;
 
-        return marsh.readField(fieldName, valBytes, start, len, val != null ? val.getClass().getClassLoader() : null);
+        try {
+            OptimizedMarshaller marsh = (OptimizedMarshaller)ctx.kernalContext().config().getMarshaller();
+
+            return marsh.readField(fieldName, valBytes, start, len,
+                val != null ? val.getClass().getClassLoader() : null, ctx);
+        }
+        catch (IgniteCheckedException e) {
+            throw new IgniteException(e);
+        }
     }
 
-    /**
-     * Deserializes wrapped object.
-     *
-     * @param ctx Cache context.
-     * @return Deserialized object.
-     */
-    public Object deserialize(CacheObjectContext ctx) {
+    /** {@inheritDoc} */
+    @Override public <T> T deserialize() {
         if (val != null)
-            return val;
+            return (T)val;
 
         try {
             assert valBytes != null;
@@ -205,7 +215,7 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
             if (keepDeserialized(ctx, false))
                 this.val = val;
 
-            return val;
+            return (T)val;
         }
         catch (IgniteCheckedException e) {
             throw new IgniteException("Failed to unmarshall object.", e);
@@ -343,33 +353,6 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
         if (ctx.copyOnGet())
             return false;
 
-        return !checkCls || hasClassOnNode(ctx);
-    }
-
-    /**
-     * Checks whether a node has a class definition of a marhsaller object or not.
-     *
-     * @param ctx Cache object context.
-     * @return {@code true} if has, {@code false} otherwise.
-     */
-    private boolean hasClassOnNode(CacheObjectContext ctx) {
-        if (val != null)
-            return true;
-
-        if (hasClass != null)
-            return hasClass;
-
-        assert valBytes != null;
-
-        try {
-            Class<?> cls = ctx.kernalContext().marshallerContext().getClass(typeId(), null);
-
-            hasClass = cls != null;
-        }
-        catch (Exception ignore) {
-            hasClass = false;
-        }
-
-        return hasClass;
+        return !checkCls || ctx.processor().hasClass(typeId());
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
index 14c6196..28013aa 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java
@@ -31,6 +31,7 @@ public interface CacheObject extends Message {
     /** */
     public static final byte TYPE_BYTE_ARR = 2;
 
+    /** */
     public static final byte TYPE_OPTIMIZED = 3;
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
index 74e8ad5..9de267b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
@@ -22,14 +22,14 @@ import org.apache.ignite.internal.*;
 import org.apache.ignite.internal.processors.cacheobject.*;
 import org.apache.ignite.internal.util.typedef.*;
 import org.apache.ignite.internal.util.typedef.internal.*;
-import org.apache.ignite.marshaller.optimized.*;
 
+import java.io.*;
 import java.util.*;
 
 /**
  *
  */
-public class CacheObjectContext {
+public class CacheObjectContext implements Externalizable {
     /** */
     private GridKernalContext kernalCtx;
 
@@ -49,23 +49,29 @@ public class CacheObjectContext {
     private boolean p2pEnabled;
 
     /**
+     * Empty constructor required by {@link Externalizable}.
+     */
+    public CacheObjectContext() {
+        // No-op.
+    }
+
+    /**
      * @param kernalCtx Kernal context.
      * @param dfltAffMapper Default affinity mapper.
      * @param cpyOnGet Copy on get flag.
      * @param storeVal {@code True} if should store unmarshalled value in cache.
-     * @param
      */
     public CacheObjectContext(GridKernalContext kernalCtx,
         AffinityKeyMapper dfltAffMapper,
         boolean cpyOnGet,
         boolean storeVal
-        ) {
+    ) {
         this.kernalCtx = kernalCtx;
-        this.p2pEnabled = kernalCtx.config().isPeerClassLoadingEnabled();
         this.dfltAffMapper = dfltAffMapper;
         this.cpyOnGet = cpyOnGet;
         this.storeVal = storeVal;
 
+        p2pEnabled = kernalCtx.config().isPeerClassLoadingEnabled();
         proc = kernalCtx.cacheObjects();
     }
 
@@ -119,10 +125,16 @@ public class CacheObjectContext {
      * @return Unwrapped object.
      */
     public Object unwrapIfNeeded(Object o, boolean keepPortable) {
-        if (processor().isFieldsIndexingEnabled() && OptimizedMarshallerUtils.isObjectWithIndexedFieldsOrCollection(o))
-            return unwrapObject(o);
+        if (o == null)
+            return null;
+
+        if (!kernalContext().cacheObjects().isFieldsIndexingEnabled())
+            return o;
+
+        if (keepPortable || !kernalContext().cacheObjects().isIndexedObjectOrCollectionType(o.getClass()))
+            return o;
 
-        return o;
+        return unwrapObject(o);
     }
 
     /**
@@ -133,10 +145,13 @@ public class CacheObjectContext {
      * @return Unwrapped collection.
      */
     public Collection<Object> unwrapIfNeeded(Collection<Object> col, boolean keepPortable) {
-        if (processor().isFieldsIndexingEnabled())
-            return (Collection<Object>)unwrapObject(col);
+        if (F.isEmpty(col))
+            return col;
 
-        return col;
+        if (keepPortable || !kernalContext().cacheObjects().isFieldsIndexingEnabled())
+            return col;
+
+        return (Collection<Object>)unwrapObject(col);
     }
 
     /**
@@ -146,8 +161,10 @@ public class CacheObjectContext {
      * @return Unwrapped object.
      */
     private Object unwrapObject(Object obj) {
-        if (obj instanceof CacheIndexedObjectImpl)
-            return ((CacheIndexedObjectImpl)obj).deserialize(this);
+        IgniteCacheObjectProcessor objProc = kernalContext().cacheObjects();
+
+        if (objProc.isIndexedObject(obj))
+            return objProc.unwrapIndexedObject(obj);
         else if (obj instanceof Map.Entry) {
             Map.Entry<Object, Object> entry = (Map.Entry<Object, Object>)obj;
 
@@ -155,16 +172,16 @@ public class CacheObjectContext {
 
             boolean unwrapped = false;
 
-            if (key instanceof CacheIndexedObjectImpl) {
-                key = ((CacheIndexedObjectImpl)key).deserialize(this);
+            if (objProc.isIndexedObject(key)) {
+                key = objProc.unwrapIndexedObject(key);
 
                 unwrapped = true;
             }
 
             Object val = entry.getValue();
 
-            if (val instanceof CacheIndexedObjectImpl) {
-                val = ((CacheIndexedObjectImpl)val).deserialize(this);
+            if (objProc.isIndexedObject(val)) {
+                val = objProc.unwrapIndexedObject(val);
 
                 unwrapped = true;
             }
@@ -175,7 +192,7 @@ public class CacheObjectContext {
             Collection<Object> col = (Collection<Object>)obj;
 
             if (col instanceof ArrayList) {
-                ArrayList<Object> list = (ArrayList<Object>)col;
+                List<Object> list = (List<Object>)col;
 
                 int size = list.size();
 
@@ -191,7 +208,7 @@ public class CacheObjectContext {
                 return list;
             }
             else if (col instanceof Set) {
-                Set<Object> set = new HashSet<>();
+                Collection<Object> set = new HashSet<>();
 
                 for (Object obj0 : col)
                     set.add(unwrapObject(obj0));
@@ -216,4 +233,14 @@ public class CacheObjectContext {
 
         return obj;
     }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        assert false; // TODO IGNITE-950
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        assert false; // TODO IGNITE-950
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
index aa02d12..c317b79 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
@@ -196,6 +196,9 @@ public class GridCacheContext<K, V> implements Externalizable {
     /** Updates allowed flag. */
     private boolean updatesAllowed;
 
+    /** Flag indicating that marshalled cache object field access should be used. */
+    private boolean useClsFldsAccess;
+
     /**
      * Empty constructor required for {@link Externalizable}.
      */
@@ -521,6 +524,20 @@ public class GridCacheContext<K, V> implements Externalizable {
     }
 
     /**
+     * @return Whether indexing should use deserialized values to access object fields.
+     */
+    public boolean useClassFieldAccess() {
+        return useClsFldsAccess;
+    }
+
+    /**
+     * @param useClsFldsAccess Whether indexing should use deserialized values to access object fields.
+     */
+    public void useClassFieldAccess(boolean useClsFldsAccess) {
+        this.useClsFldsAccess = useClsFldsAccess;
+    }
+
+    /**
      * @return {@code True} if entries should not be deleted from cache immediately.
      */
     public boolean deferredDelete() {
@@ -1769,8 +1786,7 @@ public class GridCacheContext<K, V> implements Externalizable {
             if (ldr == null)
                 return null;
 
-            return ctx.cacheObjects().toCacheObject(cacheObjCtx,
-                ctx.cacheObjects().unmarshal(cacheObjCtx, bytes, ldr),
+            return ctx.cacheObjects().toCacheObject(cacheObjCtx, ctx.cacheObjects().unmarshal(cacheObjCtx, bytes, ldr),
                 false);
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheIndexedObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheIndexedObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheIndexedObjectImpl.java
index e0a0c8d..2a13f90 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheIndexedObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheIndexedObjectImpl.java
@@ -18,7 +18,6 @@
 package org.apache.ignite.internal.processors.cache;
 
 import org.apache.ignite.*;
-import org.jetbrains.annotations.*;
 
 /**
  * Cache object implementation for classes that support footer injection is their serialized form thus enabling fields
@@ -39,8 +38,8 @@ public class KeyCacheIndexedObjectImpl extends CacheIndexedObjectImpl implements
      * @param val Object.
      * @param valBytes Object in a serialized form.
      */
-    public KeyCacheIndexedObjectImpl(Object val, byte[] valBytes) {
-        super(val, valBytes);
+    public KeyCacheIndexedObjectImpl(CacheObjectContext objCtx, Object val, byte[] valBytes) {
+        super(objCtx, val, valBytes);
 
         assert val != null;
     }
@@ -51,8 +50,8 @@ public class KeyCacheIndexedObjectImpl extends CacheIndexedObjectImpl implements
      * @param start Object's start in the array.
      * @param len Object's len in the array.
      */
-    public KeyCacheIndexedObjectImpl(Object val, byte[] valBytes, int start, int len) {
-        super(val, valBytes, start, len);
+    public KeyCacheIndexedObjectImpl(CacheObjectContext objCtx, Object val, byte[] valBytes, int start, int len) {
+        super(objCtx, val, valBytes, start, len);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheOsStoreManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheOsStoreManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheOsStoreManager.java
index 02fe679..6614d4a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheOsStoreManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheOsStoreManager.java
@@ -50,9 +50,4 @@ public class CacheOsStoreManager extends GridCacheStoreManagerAdapter {
     @Override protected CacheConfiguration cacheConfiguration() {
         return cfg;
     }
-
-    /** {@inheritDoc} */
-    @Override protected boolean convertPortable() {
-        return true;
-    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
index 32882ff..8113c4a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
@@ -370,22 +370,15 @@ public abstract class GridCacheStoreManagerAdapter extends GridCacheManagerAdapt
                 return;
             }
 
-            Collection<Object> keys0;
+            final boolean unwrap = convertPortable();
 
-            if (OptimizedMarshallerUtils.isObjectWithIndexedFieldsOrCollection(keys) || convertPortable()) {
-                keys0 = F.viewReadOnly(keys, new C1<KeyCacheObject, Object>() {
-                    @Override public Object apply(KeyCacheObject key) {
-                        return cctx.unwrapIfNeeded(key.value(cctx.cacheObjectContext(), false), false);
-                    }
-                });
-            }
-            else {
-                keys0 = F.viewReadOnly(keys, new C1<KeyCacheObject, Object>() {
-                    @Override public Object apply(KeyCacheObject key) {
-                        return key.value(cctx.cacheObjectContext(), false);
-                    }
-                });
-            }
+            Collection<Object> keys0 = F.viewReadOnly(keys, new C1<KeyCacheObject, Object>() {
+                @Override public Object apply(KeyCacheObject key) {
+                    Object val = key.value(cctx.cacheObjectContext(), false);
+
+                    return unwrap ? cctx.unwrapIfNeeded(val, false) : val;
+                }
+            });
 
             if (log.isDebugEnabled())
                 log.debug("Loading values from store for keys: " + keys0);
@@ -836,7 +829,10 @@ public abstract class GridCacheStoreManagerAdapter extends GridCacheManagerAdapt
     /**
      * @return Convert-portable flag.
      */
-    protected abstract boolean convertPortable();
+    protected boolean convertPortable() {
+        return !(cctx.kernalContext().cacheObjects().isFieldsIndexingEnabled() &&
+            cacheConfiguration().isKeepIgniteObjectInStore());
+    }
 
     /**
      *

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
index 5991fff..399ba19 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
@@ -38,6 +38,15 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
     public void onUtilityCacheStarted() throws IgniteCheckedException;
 
     /**
+     * Callback invoked when cache is started.
+     *
+     * @param cctx Cache context.
+     */
+    public void onCacheStart(GridCacheContext cctx);
+
+    public void onCacheStop(GridCacheContext cctx);
+
+    /**
      * @param typeName Type name.
      * @return Type ID.
      */
@@ -60,6 +69,15 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
     @Nullable public Object unwrapTemporary(GridCacheContext ctx, @Nullable Object obj) throws IgniteException;
 
     /**
+     * Unwraps indexed object into user object.
+     *
+     * @param obj Indexed object.
+     * @return Unwrapped user object.
+     * @throws IgniteException If unwrap failed.
+     */
+    @Nullable public Object unwrapIndexedObject(Object obj) throws IgniteException;
+
+    /**
      * Prepares cache object for cache (e.g. copies user-provided object if needed).
      *
      * @param obj Cache object.
@@ -69,14 +87,6 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
     @Nullable public CacheObject prepareForCache(@Nullable CacheObject obj, GridCacheContext cctx);
 
     /**
-     * Checks whether object is portable object.
-     *
-     * @param obj Object to check.
-     * @return {@code True} if object is already a portable object, {@code false} otherwise.
-     */
-    public boolean isPortableObject(Object obj);
-
-    /**
      * Checks whether objects supports index fields extraction.
      *
      * @param obj Object to check.
@@ -85,30 +95,28 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
     public boolean isIndexedObject(Object obj);
 
     /**
-     * Checks whether given class is portable.
+     * Gets affinity key for the given cache object.
      *
-     * @return {@code true} If portable objects are enabled.
+     * @param idxObj Indexed object to get affinity key for.
+     * @return Affinity key for the given cache key object.
      */
-    public boolean isPortableEnabled();
+    public Object affinityKey(CacheIndexedObject idxObj);
 
     /**
-     * Retrieves field from the given object. Object should be an instance of {@link CacheObject}.
+     * Checks whether this node has class representing the given type ID.
      *
-     * @param obj Object to get field from.
-     * @param fieldName Field name.
-     * @throws IgniteFieldNotFoundException In case if there is no such a field.
-     * @return Field value.
+     * @param typeId Type ID to check.
+     * @return {@code True} if class for the given type ID is available.
      */
-    public Object field(Object obj, String fieldName) throws IgniteFieldNotFoundException;
+    public boolean hasClass(int typeId);
 
     /**
-     * Checks whether field is set in the object. Object should be an instance of {@link CacheObject}.
+     * Checks whether the given class needs to be potentially unwrapped.
      *
-     * @param obj Object.
-     * @param fieldName Field name.
-     * @return {@code true} if field is set.
+     * @param cls Class to check.
+     * @return {@code True} if needs to be unwrapped.
      */
-    public boolean hasField(Object obj, String fieldName);
+    boolean isIndexedObjectOrCollectionType(Class<?> cls);
 
     /**
      * Checks whether this functionality is globally supported.
@@ -122,21 +130,10 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
      * Footer contains information about fields location in the serialized form, thus enabling fast queries without
      * a need to deserialize the object.
      *
-     * Indexing is enabled with {@link OptimizedMarshallerIndexingHandler#enableFieldsIndexingForClass(Class)}.
-     *
      * @param cls Class.
      * @return {@code true} if the footer is enabled.
      */
-    public boolean isFieldsIndexingEnabled(Class<?> cls);
-
-    /**
-     * Tries to enables fields indexing for the object of the given {@code cls}.
-     *
-     * @param cls Class.
-     * @return {@code true} if fields indexing is enabled.
-     * @throws IgniteCheckedException In case of error.
-     */
-    public boolean enableFieldsIndexing(Class<?> cls) throws IgniteCheckedException;
+    public boolean isFieldsIndexingSupported(Class<?> cls);
 
     /**
      * @param ctx Cache object context.
@@ -175,7 +172,6 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
     public CacheObjectContext contextForCache(CacheConfiguration ccfg) throws IgniteCheckedException;
 
     /**
-     * @param ctx Cache context.
      * @param obj Key value.
      * @param userObj If {@code true} then given object is object provided by user and should be copied
      *        before stored in cache.
@@ -184,7 +180,6 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
     public KeyCacheObject toCacheKeyObject(CacheObjectContext ctx, Object obj, boolean userObj);
 
     /**
-     * @param ctx Cache context.
      * @param obj Object.
      * @param userObj If {@code true} then given object is object provided by user and should be copied
      *        before stored in cache.
@@ -193,7 +188,6 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
     @Nullable public CacheObject toCacheObject(CacheObjectContext ctx, @Nullable Object obj, boolean userObj);
 
     /**
-     * @param ctx Cache context.
      * @param type Object type.
      * @param bytes Object bytes.
      * @return Cache object.

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
index 7b556ee..2476499 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.cacheobject;
 
 import org.apache.ignite.*;
 import org.apache.ignite.cache.*;
+import org.apache.ignite.cache.affinity.*;
 import org.apache.ignite.configuration.*;
 import org.apache.ignite.internal.*;
 import org.apache.ignite.internal.processors.*;
@@ -30,8 +31,8 @@ import org.apache.ignite.lang.*;
 import org.apache.ignite.marshaller.*;
 import org.apache.ignite.marshaller.optimized.*;
 import org.jetbrains.annotations.*;
+import org.jsr166.*;
 
-import java.lang.reflect.*;
 import java.math.*;
 import java.util.*;
 import java.util.concurrent.*;
@@ -41,6 +42,7 @@ import static org.apache.ignite.cache.CacheMemoryMode.*;
 /**
  *
  */
+@SuppressWarnings("UnnecessaryFullyQualifiedName")
 public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter implements IgniteCacheObjectProcessor {
     /** */
     private static final sun.misc.Unsafe UNSAFE = GridUnsafe.unsafe();
@@ -55,17 +57,23 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
     private volatile IgniteCacheProxy<OptimizedObjectMetadataKey, OptimizedObjectMetadata> metaDataCache;
 
     /** Metadata updates collected before metadata cache is initialized. */
-    private final ConcurrentHashMap<Integer, OptimizedObjectMetadata> metaBuf = new ConcurrentHashMap<>();
+    private final ConcurrentMap<Integer, OptimizedObjectMetadata> metaBuf = new ConcurrentHashMap<>();
 
     /** */
     private final CountDownLatch startLatch = new CountDownLatch(1);
 
     /** */
-    private OptimizedMarshallerIndexingHandler indexingMgr;
+    private OptimizedMarshallerIndexingHandler idxHnd;
 
     /** */
     private OptimizedMarshaller optMarsh;
 
+    /** Class presence cache map. */
+    private ConcurrentMap<Integer, Boolean> clsPresenceMap = new ConcurrentHashMap8<>();
+
+    /** Affinity fields map by type ID. */
+    private ConcurrentMap<Integer, String> affFields = new ConcurrentHashMap8<>();
+
     /**
      *
      */
@@ -84,6 +92,13 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
         IMMUTABLE_CLS.add(BigDecimal.class);
     }
 
+    /**
+     * @param ctx Context.
+     */
+    public IgniteCacheObjectProcessorImpl(GridKernalContext ctx) {
+        super(ctx);
+    }
+
     /** {@inheritDoc} */
     @Override public void start() throws IgniteCheckedException {
         super.start();
@@ -93,11 +108,11 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
         if (marsh instanceof OptimizedMarshaller) {
             optMarsh = (OptimizedMarshaller)marsh;
 
-            indexingMgr = new OptimizedMarshallerIndexingHandler();
+            idxHnd = new OptimizedMarshallerIndexingHandler();
 
             OptimizedMarshallerMetaHandler metaHandler = new OptimizedMarshallerMetaHandler() {
                 @Override public void addMeta(int typeId, OptimizedObjectMetadata meta) {
-                    if (metaBuf.contains(typeId))
+                    if (metaBuf.containsKey(typeId))
                         return;
 
                     metaBuf.put(typeId, meta);
@@ -126,8 +141,8 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
                 }
             };
 
-            indexingMgr.setMetaHandler(metaHandler);
-            optMarsh.setIndexingHandler(indexingMgr);
+            idxHnd.setMetaHandler(metaHandler);
+            optMarsh.setIndexingHandler(idxHnd);
         }
     }
 
@@ -141,11 +156,70 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
             metaDataCache.putIfAbsent(new OptimizedObjectMetadataKey(e.getKey()), e.getValue());
     }
 
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
+    @Override public void onCacheStart(GridCacheContext cctx) {
+        if (!cctx.userCache())
+            return;
+
+        Collection<CacheTypeMetadata> typeMetadata = cctx.config().getTypeMetadata();
+
+        for (CacheTypeMetadata typeMeta : typeMetadata) {
+            int typeId = typeId(typeMeta.getKeyType());
+
+            if (typeId != 0 && typeMeta.getAffinityKeyFieldName() != null)
+                affFields.put(typeId, typeMeta.getAffinityKeyFieldName());
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onCacheStop(GridCacheContext cctx) {
+
+    }
+
     /**
-     * @param ctx Context.
+     * @param io Indexed object.
+     * @return Affinity key.
      */
-    public IgniteCacheObjectProcessorImpl(GridKernalContext ctx) {
-        super(ctx);
+    @Override public Object affinityKey(CacheIndexedObject io) {
+        try {
+            String affField = affFields.get(io.typeId());
+
+            if (affField != null)
+                return io.field(affField);
+        }
+        catch (IgniteException e) {
+            U.error(log, "Failed to get affinity field from Ignite object: " + io, e);
+        }
+
+        return io;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean hasClass(int typeId) {
+        Boolean res = clsPresenceMap.get(typeId);
+
+        if (res == null) {
+            try {
+                res = ctx.marshallerContext().getClass(typeId, null) != null;
+            }
+            catch (ClassNotFoundException | IgniteCheckedException ignore) {
+                res = false;
+            }
+
+            clsPresenceMap.put(typeId, res);
+        }
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isIndexedObjectOrCollectionType(Class<?> cls) {
+        return CacheIndexedObject.class.isAssignableFrom(cls) ||
+            cls == Object[].class ||
+            Collection.class.isAssignableFrom(cls) ||
+            Map.class.isAssignableFrom(cls) ||
+            Map.Entry.class.isAssignableFrom(cls);
     }
 
     /** {@inheritDoc} */
@@ -190,7 +264,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
         if (obj instanceof KeyCacheObject)
             return (KeyCacheObject)obj;
 
-        return toCacheKeyObject0(obj, userObj);
+        return toCacheKeyObject0(ctx, obj, userObj);
     }
 
     /**
@@ -200,12 +274,12 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
      * @return Key cache object.
      */
     @SuppressWarnings("ExternalizableWithoutPublicNoArgConstructor")
-    protected KeyCacheObject toCacheKeyObject0(Object obj, boolean userObj) {
+    protected KeyCacheObject toCacheKeyObject0(CacheObjectContext ctx, Object obj, boolean userObj) {
         if (!userObj)
-            return isFieldsIndexingEnabled(obj.getClass()) ? new KeyCacheIndexedObjectImpl(obj, null) :
+            return isFieldsIndexingSupported(obj.getClass()) ? new KeyCacheIndexedObjectImpl(ctx, obj, null) :
                 new KeyCacheObjectImpl(obj, null);
 
-        return isFieldsIndexingEnabled(obj.getClass()) ? new UserKeyCacheIndexedObjectImpl(obj) :
+        return isFieldsIndexingSupported(obj.getClass()) ? new UserKeyCacheIndexedObjectImpl(ctx, obj) :
             new UserKeyCacheObjectImpl(obj);
     }
 
@@ -245,7 +319,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
                 return new CacheObjectImpl(null, bytes);
 
             case CacheObject.TYPE_OPTIMIZED:
-                return new CacheIndexedObjectImpl(bytes, 0, bytes.length);
+                return new CacheIndexedObjectImpl(ctx, bytes, 0, bytes.length);
         }
 
         throw new IllegalArgumentException("Invalid object type: " + type);
@@ -256,7 +330,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
         if (obj == null || obj instanceof CacheObject)
             return (CacheObject)obj;
 
-        return toCacheObject0(obj, userObj);
+        return toCacheObject0(ctx, obj, userObj);
     }
 
     /**
@@ -266,7 +340,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
      * @return Cache object.
      */
     @SuppressWarnings("ExternalizableWithoutPublicNoArgConstructor")
-    protected CacheObject toCacheObject0(@Nullable Object obj, boolean userObj) {
+    protected CacheObject toCacheObject0(CacheObjectContext ctx, @Nullable Object obj, boolean userObj) {
         assert obj != null;
 
         if (obj instanceof byte[]) {
@@ -277,10 +351,10 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
         }
 
         if (!userObj)
-            return isFieldsIndexingEnabled(obj.getClass()) ? new CacheIndexedObjectImpl(obj) :
+            return isFieldsIndexingSupported(obj.getClass()) ? new CacheIndexedObjectImpl(ctx, obj) :
                 new CacheObjectImpl(obj, null);
 
-        return isFieldsIndexingEnabled(obj.getClass()) ? new UserCacheIndexedObjectImpl(obj, null) :
+        return isFieldsIndexingSupported(obj.getClass()) ? new UserCacheIndexedObjectImpl(ctx, obj, null) :
             new UserCacheObjectImpl(obj, null);
     }
 
@@ -294,14 +368,23 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
             GridQueryProcessor.isEnabled(ccfg) ||
             !ccfg.isCopyOnRead();
 
-        CacheObjectContext res = new CacheObjectContext(ctx,
-            ccfg.getAffinityMapper() != null ? ccfg.getAffinityMapper() : new GridCacheDefaultAffinityKeyMapper(),
-            ccfg.isCopyOnRead() && memMode != OFFHEAP_VALUES,
-            storeVal);
+        boolean idxObj = ctx.cacheObjects().isFieldsIndexingEnabled() && !GridCacheUtils.isSystemCache(ccfg.getName())
+            && !GridCacheUtils.isIgfsCache(ctx.config(), ccfg.getName());
 
-        ctx.resource().injectGeneric(res.defaultAffMapper());
+        AffinityKeyMapper affMapper = ccfg.getAffinityMapper();
 
-        return res;
+        if (affMapper == null)
+            affMapper = new GridCacheDefaultAffinityKeyMapper();
+
+        if (idxObj)
+            affMapper = new CacheIndexedObjectDefaultAffinityMapper();
+
+        ctx.resource().injectGeneric(affMapper);
+
+        return new CacheObjectContext(ctx,
+            affMapper,
+            ccfg.isCopyOnRead() && memMode != OFFHEAP_VALUES,
+            storeVal);
     }
 
     /** {@inheritDoc} */
@@ -313,13 +396,13 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
 
     /** {@inheritDoc} */
     @Override public int typeId(String typeName) {
-        return indexingMgr != null ? OptimizedMarshallerUtils.resolveTypeId(typeName, indexingMgr.idMapper()) : 0;
+        return idxHnd != null ? OptimizedMarshallerUtils.resolveTypeId(typeName, idxHnd.idMapper()) : 0;
     }
 
     /** {@inheritDoc} */
     @Override public int typeId(Object obj) {
         if (obj instanceof CacheIndexedObjectImpl)
-            return ((CacheIndexedObjectImpl)obj).typeId();
+            return ((CacheIndexedObject)obj).typeId();
 
         return 0;
     }
@@ -330,71 +413,24 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
     }
 
     /** {@inheritDoc} */
-    @Override public boolean isPortableObject(Object obj) {
-        return false;
+    @Nullable @Override public Object unwrapIndexedObject(Object obj) throws IgniteException {
+        return null;
     }
 
     /** {@inheritDoc} */
     @Override public boolean isIndexedObject(Object obj) {
-        return obj instanceof CacheIndexedObjectImpl;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isPortableEnabled() {
-        return false;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object field(Object obj, String fieldName) throws IgniteFieldNotFoundException {
-        assert indexingMgr != null;
-
-        if (obj instanceof CacheIndexedObjectImpl) {
-            try {
-                return ((CacheIndexedObjectImpl)obj).field(fieldName, optMarsh);
-            }
-            catch (IgniteFieldNotFoundException e) {
-                throw e;
-            }
-            catch (IgniteCheckedException e) {
-                throw new IgniteException(e);
-            }
-        }
-        else
-            throw new IgniteFieldNotFoundException("Object doesn't have field [obj=" + obj + ", field=" + fieldName
-                + "]");
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean hasField(Object obj, String fieldName) {
-        if (obj instanceof CacheIndexedObjectImpl) {
-            assert indexingMgr != null;
-
-            try {
-                return ((CacheIndexedObjectImpl)obj).hasField(fieldName, optMarsh);
-            }
-            catch (IgniteCheckedException e) {
-                throw new IgniteException(e);
-            }
-        }
-
-        return false;
+        return obj instanceof CacheIndexedObject;
     }
 
     /** {@inheritDoc} */
     @Override public boolean isFieldsIndexingEnabled() {
-        return indexingMgr != null && indexingMgr.isFieldsIndexingSupported();
+        return idxHnd != null && idxHnd.isFieldsIndexingSupported();
     }
 
     /** {@inheritDoc} */
-    @Override public boolean isFieldsIndexingEnabled(Class<?> cls) {
-        return indexingMgr != null && indexingMgr.isFieldsIndexingSupported() &&
-            indexingMgr.enableFieldsIndexingForClass(cls);
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean enableFieldsIndexing(Class<?> cls) throws IgniteCheckedException {
-        return indexingMgr != null && indexingMgr.isFieldsIndexingSupported() &&
-            indexingMgr.enableFieldsIndexingForClass(cls);
+    @Override public boolean isFieldsIndexingSupported(Class<?> cls) {
+        return idxHnd != null && idxHnd.isFieldsIndexingSupported() &&
+            idxHnd.enableFieldsIndexingForClass(cls);
     }
 
     /**
@@ -426,7 +462,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
                         valBytes = ctx.processor().marshal(ctx, val);
 
                     ClassLoader ldr = ctx.p2pEnabled() ?
-                        IgniteUtils.detectClassLoader(IgniteUtils.detectClass(this.val)) : U.gridClassLoader();
+                        IgniteUtils.detectClassLoader(IgniteUtils.detectClass(val)) : U.gridClassLoader();
 
                      Object val = ctx.processor().unmarshal(ctx, valBytes, ldr);
 
@@ -459,7 +495,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
          * @param val Value.
          * @param valBytes Value bytes.
          */
-        public UserCacheObjectImpl(Object val, byte[] valBytes) {
+        private UserCacheObjectImpl(Object val, byte[] valBytes) {
             super(val, valBytes);
         }
 
@@ -476,7 +512,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
 
                 if (ctx.storeValue()) {
                     ClassLoader ldr = ctx.p2pEnabled() ?
-                        IgniteUtils.detectClass(this.val).getClassLoader() : val.getClass().getClassLoader();
+                        IgniteUtils.detectClass(val).getClassLoader() : val.getClass().getClassLoader();
 
                     Object val = this.val != null && ctx.processor().immutable(this.val) ? this.val :
                         ctx.processor().unmarshal(ctx, valBytes, ldr);
@@ -494,7 +530,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
 
     /**
      * Wraps value provided by user, must be serialized before stored in cache.
-     * Used by classes that support fields indexing. Refer to {@link #isFieldsIndexingEnabled(Class)}.
+     * Used by classes that support fields indexing. Refer to {@link #isFieldsIndexingSupported(Class)}.
      */
     private static class UserCacheIndexedObjectImpl extends CacheIndexedObjectImpl {
         /** */
@@ -511,8 +547,8 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
          * @param val Value.
          * @param valBytes Value bytes.
          */
-        public UserCacheIndexedObjectImpl(Object val, byte[] valBytes) {
-            super(val, valBytes);
+        private UserCacheIndexedObjectImpl(CacheObjectContext ctx, Object val, byte[] valBytes) {
+            super(ctx, val, valBytes);
         }
 
         /** {@inheritDoc} */
@@ -527,12 +563,12 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
 
                 if (keepDeserialized(ctx, true)) {
                     ClassLoader ldr = ctx.p2pEnabled() ?
-                        IgniteUtils.detectClass(this.val).getClassLoader() : val.getClass().getClassLoader();
+                        IgniteUtils.detectClass(val).getClassLoader() : val.getClass().getClassLoader();
 
                     Object val = this.val != null && ctx.processor().immutable(this.val) ? this.val :
                         ctx.processor().unmarshal(ctx, valBytes, start, len, ldr);
 
-                    return new CacheIndexedObjectImpl(val, valBytes, start, len);
+                    return new CacheIndexedObjectImpl(ctx, val, valBytes, start, len);
                 }
 
                 return new CacheIndexedObjectImpl(null, valBytes, start, len);
@@ -545,7 +581,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
 
     /**
      * Wraps key provided by user, must be serialized before stored in cache.
-     * Used by classes that support fields indexing. Refer to {@link #isFieldsIndexingEnabled(Class)}.
+     * Used by classes that support fields indexing. Refer to {@link #isFieldsIndexingSupported(Class)}.
      */
     private static class UserKeyCacheIndexedObjectImpl extends KeyCacheIndexedObjectImpl {
         /** */
@@ -561,8 +597,8 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
         /**
          * @param key Key.
          */
-        UserKeyCacheIndexedObjectImpl(Object key) {
-            super(key, null);
+        UserKeyCacheIndexedObjectImpl(CacheObjectContext ctx, Object key) {
+            super(ctx, key, null);
         }
 
         /** {@inheritDoc} */
@@ -572,14 +608,14 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
                     toMarshaledFormIfNeeded(ctx);
 
                     ClassLoader ldr = ctx.p2pEnabled() ?
-                        IgniteUtils.detectClassLoader(IgniteUtils.detectClass(this.val)) : U.gridClassLoader();
+                        IgniteUtils.detectClassLoader(IgniteUtils.detectClass(val)) : U.gridClassLoader();
 
                     Object val = ctx.processor().unmarshal(ctx, valBytes, start, len, ldr);
 
-                    return new KeyCacheIndexedObjectImpl(val, valBytes, start, len);
+                    return new KeyCacheIndexedObjectImpl(ctx, val, valBytes, start, len);
                 }
 
-                return new KeyCacheIndexedObjectImpl(val, valBytes, start, len);
+                return new KeyCacheIndexedObjectImpl(ctx, val, valBytes, start, len);
             }
             catch (IgniteCheckedException e) {
                 throw new IgniteException("Failed to marshal object: " + val, e);
@@ -604,7 +640,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
         /**
          * @param val Value.
          */
-        public UserCacheObjectByteArrayImpl(byte[] val) {
+        private UserCacheObjectByteArrayImpl(byte[] val) {
             super(val);
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index 8ee5cfd..3b0cea3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -58,7 +58,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
     public static final String _VAL = "_val";
 
     /** */
-    private static final Class<?> GEOMETRY_CLASS = U.classForName("com.vividsolutions.jts.geom.Geometry", null);
+    private static final Class<?> GEOMETRY_CLASS = U.classForName("com.vividsolutions.jts.geom.Geometry", null, null);
 
     /** */
     private static final Collection<Class<?>> SQL_TYPES = new HashSet<>(F.<Class<?>>asList(
@@ -141,24 +141,51 @@ public class GridQueryProcessor extends GridProcessorAdapter {
     }
 
     /**
-     * @param ccfg Cache configuration.
+     * @param cctx Cache context.
      * @throws IgniteCheckedException If failed.
      */
-    public void initializeCache(CacheConfiguration<?, ?> ccfg) throws IgniteCheckedException {
+    public void initializeCache(GridCacheContext<?, ?> cctx) throws IgniteCheckedException {
+        CacheConfiguration<?, ?> ccfg = cctx.config();
+
         idx.registerCache(ccfg);
 
         try {
             if (!F.isEmpty(ccfg.getTypeMetadata())) {
+                boolean hasClasses = true;
+
+                // Check that we have all required classes on this server.
                 for (CacheTypeMetadata meta : ccfg.getTypeMetadata()) {
+                    if (!meta.isQueryType())
+                        continue;
+
                     if (F.isEmpty(meta.getValueType()))
                         throw new IgniteCheckedException("Value type is not set: " + meta);
 
+                    Class<?> keyCls = U.classForName(meta.getKeyType(), ctx.defaultClassLoader(), null);
+                    Class<?> valCls = U.classForName(meta.getValueType(), ctx.defaultClassLoader(), null);
+
+                    if (keyCls == null || valCls == null) {
+                        hasClasses = false;
+
+                        break;
+                    }
+                }
+
+                if (!hasClasses && !ctx.cacheObjects().isFieldsIndexingEnabled()) {
+                    throw new IgniteCheckedException(""); // TODO ignite-950
+                }
+
+                boolean useFieldAccess = !hasClasses || ccfg.isCopyOnRead();
+
+                cctx.useClassFieldAccess(!useFieldAccess);
+
+                for (CacheTypeMetadata meta : ccfg.getTypeMetadata()) {
                     TypeDescriptor desc = new TypeDescriptor();
 
                     // Key and value classes still can be available if they are primitive or JDK part.
                     // We need that to set correct types for _key and _val columns.
-                    Class<?> keyCls = U.classForName(meta.getKeyType(), null);
-                    Class<?> valCls = U.classForName(meta.getValueType(), null);
+                    Class<?> keyCls = U.classForName(meta.getKeyType(), ctx.defaultClassLoader(), null);
+                    Class<?> valCls = U.classForName(meta.getValueType(), ctx.defaultClassLoader(), null);
 
                     desc.name(meta.getSimpleValueType());
 
@@ -166,11 +193,13 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                     desc.keyClass(keyCls != null ? keyCls : Object.class);
 
                     TypeId typeId;
+                    TypeId altTypeId;
 
-                    if (ctx.cacheObjects().isPortableEnabled() || valCls == null || ccfg.isCopyOnRead()) {
+                    if (useFieldAccess) {
                         processCacheTypeMeta(meta, desc);
 
                         typeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(meta.getValueType()));
+                        altTypeId = null;
                     }
                     else {
                         assert valCls != null;
@@ -178,11 +207,15 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                         processClassMeta(meta, desc);
 
                         typeId = new TypeId(ccfg.getName(), valCls);
+                        altTypeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(meta.getValueType()));
                     }
 
                     addTypeByName(ccfg, desc);
                     types.put(typeId, desc);
 
+                    if (altTypeId != null)
+                        types.put(altTypeId, desc);
+
                     desc.registered(idx.registerType(ccfg.getName(), desc));
                 }
             }
@@ -240,7 +273,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
             return;
 
         try {
-            initializeCache(cctx.config());
+            initializeCache(cctx);
         }
         finally {
             busyLock.leaveBusy();
@@ -470,7 +503,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                     "(multiple classes with same simple name are stored in the same cache) " +
                     "[expCls=" + desc.valueClass().getName() + ", actualCls=" + valCls.getName() + ']');
 
-            if (!(key instanceof CacheIndexedObjectImpl) && !ctx.cacheObjects().isPortableObject(key)) {
+            if (!ctx.cacheObjects().isIndexedObject(key)) {
                 Class<?> keyCls = key.value(coctx, false).getClass();
 
                 if (!desc.keyClass().isAssignableFrom(keyCls))
@@ -1203,6 +1236,10 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                 int order = 0;
 
                 for (Map.Entry<String, IgniteBiTuple<Class<?>, Boolean>> idxField : idxFields.entrySet()) {
+                    // Skip _val field as it is an implicit field.
+                    if (_VAL.equals(idxField.getKey()))
+                        continue;
+
                     Property prop = buildPortableProperty(idxField.getKey(), idxField.getValue().get1(), aliases);
 
                     d.addProperty(prop, false);
@@ -1590,17 +1627,19 @@ public class GridQueryProcessor extends GridProcessorAdapter {
 
         /** {@inheritDoc} */
         @Override public Object value(Object key, Object val) throws IgniteCheckedException {
-            Object obj;
+            CacheIndexedObject obj;
 
             if (parent != null) {
-                obj = parent.value(key, val);
+                Object obj0 = parent.value(key, val);
 
-                if (obj == null)
+                if (obj0 == null)
                     return null;
 
-                if (!ctx.cacheObjects().isIndexedObject(obj))
+                if (!ctx.cacheObjects().isIndexedObject(obj0))
                     throw new IgniteCheckedException("Non-indexed object received as a result of property extraction " +
-                        "[parent=" + parent + ", propName=" + propName + ", obj=" + obj + ']');
+                        "[parent=" + parent + ", propName=" + propName + ", obj=" + obj0 + ']');
+
+                obj = (CacheIndexedObject)obj0;
             }
             else {
                 int isKeyProp0 = isKeyProp;
@@ -1608,10 +1647,18 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                 if (isKeyProp0 == 0) {
                     // Key is allowed to be a non-portable object here.
                     // We check key before value consistently with ClassProperty.
-                    if (ctx.cacheObjects().isIndexedObject(key) && ctx.cacheObjects().hasField(key, propName))
-                        isKeyProp = isKeyProp0 = 1;
-                    else if (ctx.cacheObjects().hasField(val, propName))
-                        isKeyProp = isKeyProp0 = -1;
+                    if (ctx.cacheObjects().isIndexedObject(key)) {
+                        CacheIndexedObject key0 = (CacheIndexedObject)key;
+
+                        if (key0.hasField(propName))
+                            isKeyProp = isKeyProp0 = 1;
+                    }
+                    else if (ctx.cacheObjects().isIndexedObject(val)) {
+                        CacheIndexedObject val0 = (CacheIndexedObject)val;
+
+                        if (val0.hasField(propName))
+                            isKeyProp = isKeyProp0 = -1;
+                    }
                     else {
                         U.warn(log, "Neither key nor value have property " +
                             "[propName=" + propName + ", key=" + key + ", val=" + val + "]");
@@ -1620,12 +1667,10 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                     }
                 }
 
-                obj = isKeyProp0 == 1 ? key : val;
+                obj = (CacheIndexedObject)(isKeyProp0 == 1 ? key : val);
             }
 
-            Object res = ctx.cacheObjects().field(obj, propName);
-
-            return res;
+            return obj.field(propName);
         }
 
         /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
index 167f832..c77ee59 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
@@ -1165,11 +1165,14 @@ public abstract class IgniteUtils {
      * @param dflt Default class to return.
      * @return Class or default given class if it can't be found.
      */
-    @Nullable public static Class<?> classForName(String cls, @Nullable Class<?> dflt) {
+    @Nullable public static Class<?> classForName(String cls, ClassLoader ldr, @Nullable Class<?> dflt) {
         try {
-            return Class.forName(cls);
+            if (ldr == null)
+                ldr = IgniteUtils.class.getClassLoader();
+
+            return Class.forName(cls, true, ldr);
         }
-        catch (ClassNotFoundException e) {
+        catch (ClassNotFoundException ignored) {
             return dflt;
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java
index c8e2dcc..4b06a4e 100644
--- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java
@@ -369,7 +369,8 @@ public class OptimizedMarshaller extends AbstractMarshaller {
      * @throws IgniteFieldNotFoundException In case if there is no such a field.
      * @throws IgniteCheckedException In case of error.
      */
-    public <T> T readField(String fieldName, byte[] arr, int off, int len, @Nullable ClassLoader clsLdr)
+    public <T> T readField(String fieldName, byte[] arr, int off, int len, @Nullable ClassLoader clsLdr,
+        CacheObjectContext objCtx)
         throws IgniteCheckedException {
 
         assert arr != null && fieldName != null;
@@ -383,7 +384,7 @@ public class OptimizedMarshaller extends AbstractMarshaller {
 
             objIn.in().bytes(arr, off, len);
 
-            return objIn.readField(fieldName);
+            return objIn.readField(fieldName, objCtx);
         }
         catch (IOException e) {
             throw new IgniteCheckedException("Failed to find field with name: " + fieldName, e);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIndexingHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIndexingHandler.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIndexingHandler.java
index 678e5b2..23b7044 100644
--- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIndexingHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIndexingHandler.java
@@ -30,7 +30,7 @@ import java.util.concurrent.*;
  */
 public class OptimizedMarshallerIndexingHandler {
     /** */
-    private static final ConcurrentMap<Class<?>, Boolean> indexingEnabledCache = new ConcurrentHashMap<>();
+    private final ConcurrentMap<Class<?>, Boolean> indexingEnabledCache = new ConcurrentHashMap<>();
 
     /** Class descriptors by class. */
     private ConcurrentMap<Class, OptimizedClassDescriptor> clsMap;
@@ -119,6 +119,13 @@ public class OptimizedMarshallerIndexingHandler {
     }
 
     /**
+     * Clears indexing enabled cache.
+     */
+    public void clearIndexingEnabledCache() {
+        indexingEnabledCache.clear();
+    }
+
+    /**
      * Enables fields indexing for the object of the given {@code cls}.
      *
      * If enabled then a footer will be added during marshalling of an object of the given {@code cls} to the end of

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java
index b6681ec..40d551c 100644
--- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java
@@ -1314,7 +1314,7 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt
      * @throws IOException In case of error.
      * @throws ClassNotFoundException In case of error.
      */
-    public <F> F readField(String fieldName) throws IgniteFieldNotFoundException, IOException, ClassNotFoundException {
+    public <F> F readField(String fieldName, CacheObjectContext objCtx) throws IgniteFieldNotFoundException, IOException, ClassNotFoundException {
         int start = in.position();
 
         byte type = in.readByte(start);
@@ -1329,7 +1329,7 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt
 
             if ((fieldType == SERIALIZABLE && idxHandler.metaHandler().metadata(in.readInt(range.start + 1)) != null)
                 || fieldType == MARSHAL_AWARE)
-                return  (F)new CacheIndexedObjectImpl(in.array(), range.start, range.len);
+                return  (F)new CacheIndexedObjectImpl(objCtx, in.array(), range.start, range.len);
             else {
                 in.position(range.start);
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExtSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExtSelfTest.java b/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExtSelfTest.java
index d9fd1ca..22877df 100644
--- a/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExtSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExtSelfTest.java
@@ -17,9 +17,7 @@
 
 package org.apache.ignite.marshaller.optimized;
 
-import org.apache.ignite.*;
 import org.apache.ignite.internal.processors.cache.*;
-import org.apache.ignite.marshaller.*;
 import org.apache.ignite.testframework.junits.common.*;
 
 import java.io.*;
@@ -33,12 +31,15 @@ import java.util.concurrent.*;
 @GridCommonTest(group = "Marshaller")
 public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest {
     /** */
-    private static ConcurrentHashMap<Integer, OptimizedObjectMetadata> META_BUF = new ConcurrentHashMap<>();
+    private static final ConcurrentHashMap<Integer, OptimizedObjectMetadata> META_BUF = new ConcurrentHashMap<>();
 
     /** */
     private static OptimizedMarshallerIndexingHandler idxHandler;
 
     /** */
+    private CacheObjectContext objCtx;
+
+    /** */
     private static final OptimizedMarshallerMetaHandler META_HANDLER = new OptimizedMarshallerMetaHandler() {
         @Override public void addMeta(int typeId, OptimizedObjectMetadata meta) {
             META_BUF.putIfAbsent(typeId, meta);
@@ -49,6 +50,17 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest
         }
     };
 
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        META_BUF.clear();
+
+        setupIndexingHandler();
+
+        objCtx = new CacheObjectContext(grid().context(), new CacheIndexedObjectDefaultAffinityMapper(), true, false);
+    }
+
     /**
      * @throws Exception
      */
@@ -60,16 +72,14 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest
         idxHandler = (OptimizedMarshallerIndexingHandler)field.get(marsh);
 
         idxHandler.setMetaHandler(META_HANDLER);
+
+        idxHandler.clearIndexingEnabledCache();
     }
 
     /**
      * @throws Exception In case of error.
      */
     public void testHasField() throws Exception {
-        META_BUF.clear();
-
-        setupIndexingHandler();
-
         OptimizedMarshaller marsh = (OptimizedMarshaller)OptimizedMarshallerExtSelfTest.marsh;
 
         assertTrue(idxHandler.enableFieldsIndexingForClass(TestObject.class));
@@ -90,10 +100,6 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest
      * @throws Exception In case of error.
      */
     public void testReadField() throws Exception {
-        META_BUF.clear();
-
-        setupIndexingHandler();
-
         OptimizedMarshaller marsh = (OptimizedMarshaller)OptimizedMarshallerExtSelfTest.marsh;
 
         assertTrue(idxHandler.enableFieldsIndexingForClass(TestObject.class));
@@ -105,12 +111,12 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest
 
         // Simple field extraction.
 
-        String text = marsh.readField("str", arr, 0, arr.length, null);
+        String text = marsh.readField("str", arr, 0, arr.length, null, objCtx);
 
         assertEquals(testObj.str, text);
 
         // Serializable extraction (doesn't have meta, thus doesn't have footer)
-        TestObject2 o2 = marsh.readField("o2", arr, 0, arr.length, null);
+        TestObject2 o2 = marsh.readField("o2", arr, 0, arr.length, null, objCtx);
 
         assertEquals(testObj.o2, o2);
 
@@ -121,7 +127,7 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest
         arr = marsh.marshal(testObj);
 
         // Must be returned in a wrapped form, since metadata was added enabling the footer.
-        CacheIndexedObjectImpl cacheObject = marsh.readField("o2", arr, 0, arr.length, null);
+        CacheIndexedObjectImpl cacheObject = marsh.readField("o2", arr, 0, arr.length, null, objCtx);
 
 
         arr = cacheObject.valueBytes(null);
@@ -135,17 +141,13 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest
         // Check enclosed objects fields
         assertTrue(marsh.hasField("i", arr, start.getInt(cacheObject), len.getInt(cacheObject)));
         assertEquals(testObj.o2.i, (int)marsh.readField("i", arr, start.getInt(cacheObject), len.getInt(cacheObject),
-            null));
+            null, objCtx));
     }
 
     /**
      * @throws Exception In case of error.
      */
     public void testHandles() throws Exception {
-        META_BUF.clear();
-
-        setupIndexingHandler();
-
         OptimizedMarshaller marsh = (OptimizedMarshaller)OptimizedMarshallerExtSelfTest.marsh;
 
         assertTrue(idxHandler.enableFieldsIndexingForClass(SelfLinkObject.class));
@@ -158,11 +160,11 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest
 
         byte[] arr = marsh.marshal(selfLinkObject);
 
-        String str2 = marsh.readField("str2", arr, 0, arr.length, null);
+        String str2 = marsh.readField("str2", arr, 0, arr.length, null, objCtx);
 
         assertEquals(selfLinkObject.str1, str2);
 
-        CacheIndexedObjectImpl cacheObj = marsh.readField("link", arr, 0, arr.length, null);
+        CacheIndexedObjectImpl cacheObj = marsh.readField("link", arr, 0, arr.length, null, objCtx);
 
         arr = cacheObj.valueBytes(null);
 
@@ -176,10 +178,6 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest
      * @throws Exception In case of error.
      */
     public void testMarshalAware() throws Exception {
-        META_BUF.clear();
-
-        setupIndexingHandler();
-
         OptimizedMarshaller marsh = (OptimizedMarshaller)OptimizedMarshallerExtSelfTest.marsh;
 
         assertTrue(idxHandler.enableFieldsIndexingForClass(TestMarshalAware.class));
@@ -196,11 +194,11 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest
         assertEquals(3, META_BUF.size());
 
         // Working with fields
-        String text = marsh.readField("text", arr, 0, arr.length, null);
+        String text = marsh.readField("text", arr, 0, arr.length, null, objCtx);
 
         assertEquals(test.text, text);
 
-        CacheIndexedObjectImpl cacheObj = marsh.readField("aware", arr, 0, arr.length, null);
+        CacheIndexedObjectImpl cacheObj = marsh.readField("aware", arr, 0, arr.length, null, objCtx);
         byte[] cacheObjArr = cacheObj.valueBytes(null);
 
         Field start = cacheObj.getClass().getDeclaredField("start");
@@ -209,11 +207,11 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest
         Field len = cacheObj.getClass().getDeclaredField("len");
         len.setAccessible(true);
 
-        Date date = marsh.readField("date", cacheObjArr, start.getInt(cacheObj), len.getInt(cacheObj), null);
+        Date date = marsh.readField("date", cacheObjArr, start.getInt(cacheObj), len.getInt(cacheObj), null, objCtx);
 
         assertEquals(test.aware.date, date);
 
-        cacheObj = marsh.readField("testObject2", arr, 0, arr.length, null);
+        cacheObj = marsh.readField("testObject2", arr, 0, arr.length, null, objCtx);
         cacheObjArr = cacheObj.valueBytes(null);
 
         start = cacheObj.getClass().getDeclaredField("start");
@@ -222,7 +220,7 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest
         len = cacheObj.getClass().getDeclaredField("len");
         len.setAccessible(true);
 
-        int n = marsh.readField("i", cacheObjArr, start.getInt(cacheObj), len.getInt(cacheObj), null);
+        int n = marsh.readField("i", cacheObjArr, start.getInt(cacheObj), len.getInt(cacheObj), null, objCtx);
 
         assertEquals(test.testObject2.i, n);
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/680ffa0b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 5fa76aa..65794da 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -376,11 +376,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
      * @param o Object.
      * @return {@code true} If it is a portable object.
      */
-    private boolean isPortable(CacheObject o) {
-        if (ctx == null)
-            return false;
-
-        return ctx.cacheObjects().isPortableObject(o);
+    private boolean isIndexed(CacheObject o) {
+        return ctx != null && ctx.cacheObjects().isIndexedObject(o);
     }
 
     /**
@@ -389,7 +386,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
      * @return Object class.
      */
     private Class<?> getClass(CacheObjectContext coctx, CacheObject o) {
-        return isPortable(o) ?
+        return isIndexed(o) ?
             Object.class :
             o.value(coctx, false).getClass();
     }