You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2015/06/26 10:34:55 UTC

incubator-ignite git commit: ignite-950: performance optimizations

Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-950 6bf4fa755 -> 8df87710b


ignite-950: performance optimizations


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

Branch: refs/heads/ignite-950
Commit: 8df87710bcc75786c9ac90477297528e6763591b
Parents: 6bf4fa7
Author: Denis Magda <dm...@gridgain.com>
Authored: Fri Jun 26 08:33:47 2015 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Fri Jun 26 08:33:47 2015 +0300

----------------------------------------------------------------------
 README.md                                       | 179 +++++++++++++++++++
 .../cache/CacheIndexedObjectImpl.java           |  45 +++--
 .../cache/KeyCacheIndexedObjectImpl.java        |   9 +
 .../cacheobject/IgniteCacheObjectProcessor.java |   3 +-
 .../IgniteCacheObjectProcessorImpl.java         |  25 +--
 .../processors/query/GridQueryProcessor.java    |  42 +++--
 .../ignite/internal/util/io/GridDataInput.java  |  27 +++
 .../internal/util/io/GridUnsafeDataInput.java   |  15 ++
 .../optimized/IgniteFieldNotFoundException.java |  38 ++++
 .../optimized/OptimizedMarshallerExt.java       |   1 +
 .../optimized/OptimizedObjectInputStream.java   |  80 ++++-----
 11 files changed, 371 insertions(+), 93 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8df87710/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f1b9b05
--- /dev/null
+++ b/README.md
@@ -0,0 +1,179 @@
+<center>
+![Ignite Logo](https://ignite.incubator.apache.org/images/logo3.png "Ignite Logo")
+</center>
+
+Apache Ignite In-Memory Data Fabric is a high-performance, integrated and distributed in-memory platform for computing and transacting on large-scale data sets in real-time, orders of magnitude faster than possible with traditional disk-based or flash technologies.
+![Ignite Features](https://ignite.incubator.apache.org/images/apache-ignite.png "Ignite Features")
+
+##Features
+You can view Ignite as a collection of independent, well-integrated, in-memory components geared to improve performance and scalability of you application. Some of these components include:
+
+  * Advanced Clustering
+  * Compute Grid
+  * Data Grid (JCache)
+  * Service Grid
+  * Ignite File System
+  * Distributed Data Structures
+  * Distributed Messaging
+  * Distributed Events
+  * Streaming & CEP
+  * In-Memory Hadoop Accelerator
+
+## Installation
+Here is the quick summary on installation of Apache Ignite:
+  * Download Apache Ignite as ZIP archive from https://ignite.incubator.apache.org/
+  * Unzip ZIP archive into the installation folder in your system
+  * Set `IGNITE_HOME` environment variable to point to the installation folder and make sure there is no trailing `/` in the path (this step is optional)
+
+## Start From Command Line
+An Ignite node can be started from command line either with default configuration or by passing a configuration file. You can start as many nodes as you like and they will all automatically discover each other.
+
+### With Default Configuration
+To start a grid node with default configuration, open the command shell and, assuming you are in `IGNITE_HOME` (Ignite installation folder), just type this:
+
+	$ bin/ignite.sh
+
+and you will see the output similar to this:
+
+	[02:49:12] Ignite node started OK (id=ab5d18a6)
+	[02:49:12] Topology snapshot [ver=1, nodes=1, CPUs=8, heap=1.0GB]
+
+By default `ignite.sh` starts Ignite node with the default configuration: `config/default-config.xml`.
+
+### Passing Configuration File
+To pass configuration file explicitly,  from command line, you can type ggstart.sh <path to configuration file> from within your Ignite installation folder. For example:
+
+	$ bin/ignite.sh examples/config/example-cache.xml
+
+Path to configuration file can be absolute, or relative to either `IGNITE_HOME` (Ignite installation folder) or `META-INF` folder in your classpath.
+
+### Interactive Mode
+To pick a configuration file in interactive mode just pass `-i` flag, like so: `ignite.sh -i`.
+
+## Get It With Maven
+Another easy way to get started with Apache Ignite in your project is to use Maven 2 dependency management.
+
+Ignite requires only one `ignite-core` mandatory dependency. Usually you will also need to add `ignite-spring` for spring-based XML configuration and `ignite-indexing` for SQL querying.
+
+Replace `${ignite-version}` with actual Ignite version.
+
+	<dependency>
+	    <groupId>org.apache.ignite</groupId>
+	    <artifactId>ignite-core</artifactId>
+	    <version>${ignite.version}</version>
+	</dependency>
+	<dependency>
+	    <groupId>org.apache.ignite</groupId>
+	    <artifactId>ignite-spring</artifactId>
+	    <version>${ignite.version}</version>
+	</dependency>
+	<dependency>
+	    <groupId>org.apache.ignite</groupId>
+	    <artifactId>ignite-indexing</artifactId>
+	    <version>${ignite.version}</version>
+	</dependency>
+
+## First Ignite Compute Application
+Let's write our first grid application which will count a number of non-white-space characters in a sentence. As an example, we will take a sentence, split it into multiple words, and have every compute job count number of characters in each individual word. At the end we simply add up results received from individual jobs to get our total count.
+
+	try (Ignite ignite = Ignition.start()) {
+	    Collection<GridCallable<Integer>> calls = new ArrayList<>();
+
+	    // Iterate through all the words in the sentence and create Callable jobs.
+	    for (final String word : "Count characters using callable".split(" ")) {
+	        calls.add(new GridCallable<Integer>() {
+	            @Override public Integer call() throws Exception {
+	                return word.length();
+	            }
+	        });
+	    }
+
+	    // Execute collection of Callables on the grid.
+	    Collection<Integer> res = ignite.compute().call(calls).get();
+
+	    int sum = 0;
+
+	    // Add up individual word lengths received from remote nodes.
+	    for (int len : res)
+	        sum += len;
+
+	    System.out.println(">>> Total number of characters in the phrase is '" + sum + "'.");
+	}
+
+### Zero Deployment
+Note that when running above application from your IDE, remote nodes will execute received jobs without having your code on the class path. This is called Zero Deployment. Ignite automatically detects missing classes and loads class definitions from the nodes that have them.
+
+## First Ignite Data Grid Application
+Now let's write a simple set of mini-examples which will put and get values to/from distributed cache, and perform basic transactions.
+
+Since we are using cache in this example, we should make sure that it is configured. Let's use example configuration shipped with Ignite that already has several caches configured:
+
+	$ bin/ignite.sh examples/config/example-cache.xml
+
+### Put and Get
+
+	try (Ignite ignite = Ignition.start("examples/config/example-cache.xml")) {
+	    IgniteCache<Integer, String> cache = ignite.cache(CACHE_NAME);
+
+	    // Store keys in cache (values will end up on different cache nodes).
+	    for (int i = 0; i < 10; i++)
+	        cache.put(i, Integer.toString(i));
+
+	    for (int i = 0; i < 10; i++)
+	        System.out.println("Got [key=" + i + ", val=" + cache.get(i) + ']');
+	}
+
+### Atomic Operations
+
+	// Put-if-absent which returns previous value.
+	Integer oldVal = cache.getAndPutIfAbsent("Hello", 11);
+
+	// Put-if-absent which returns boolean success flag.
+	boolean success = cache.putIfAbsent("World", 22);
+
+	// Replace-if-exists operation (opposite of getAndPutIfAbsent), returns previous value.
+	oldVal = cache.getAndReplace("Hello", 11);
+
+	// Replace-if-exists operation (opposite of putIfAbsent), returns boolean success flag.
+	success = cache.getAndReplace("World", 22);
+
+	// Replace-if-matches operation.
+	success = cache.replace("World", 2, 22);
+
+	// Remove-if-matches operation.
+	success = cache.remove("Hello", 1);
+
+### Transactions
+
+	try (Transaction tx = ignite.transactions().txStart()) {
+	    Integer hello = cache.get("Hello");
+
+	    if (hello == 1)
+	        cache.put("Hello", 11);
+
+	    cache.put("World", 22);
+
+	    tx.commit();
+	}
+
+### Distributed Locks
+
+	// Lock cache key "Hello".
+	Lock lock = cache.lock("Hello");
+
+	lock.lock();
+
+	try {
+	    cache.put("Hello", 11);
+	    cache.put("World", 22);
+	}
+	finally {
+	    lock.unlock();
+	}
+
+## Ignite Visor Admin Console
+The easiest way to examine the content of the data grid as well as perform a long list of other management and monitoring operations is to use Ignite Visor Command Line Utility.
+
+To start Visor simply run:
+
+	$ bin/ignitevisorcmd.sh
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8df87710/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 47b83ae..c51d98c 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
@@ -107,37 +107,25 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
     @Override public byte[] valueBytes(CacheObjectContext ctx) throws IgniteCheckedException {
         toMarshaledFormIfNeeded(ctx);
 
-        if (detached())
-            return valBytes;
-
-        byte[] arr = new byte[len];
+        shrinkToSize();
 
-        U.arrayCopy(valBytes, start, arr, 0, len);
-
-        return arr;
+        return valBytes;
     }
 
     /** {@inheritDoc} */
     @Override public CacheObject prepareForCache(CacheObjectContext ctx) {
-        if (detached())
-            return this;
-
         return detach();
     }
 
     /** {@inheritDoc} */
     @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException {
-        assert val != null || valBytes != null;
-
-        if (val == null && ctx.storeValue())
-            val = ctx.processor().unmarshal(ctx, valBytes, start, len, ldr);
+        // No-op
     }
 
     /** {@inheritDoc} */
     @Override public void prepareMarshal(CacheObjectContext ctx) throws IgniteCheckedException {
-        assert val != null || valBytes != null;
-
         toMarshaledFormIfNeeded(ctx);
+        shrinkToSize();
     }
 
     /** {@inheritDoc} */
@@ -187,6 +175,7 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
      * @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.
      */
     public Object field(String fieldName, OptimizedMarshallerExt marsh) throws IgniteCheckedException {
@@ -326,14 +315,9 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
      * @return Detached object wrapped by {@code CacheIndexedObjectImpl}.
      */
     protected CacheIndexedObjectImpl detach() {
-        if (detached())
-            return this;
-
-        byte[] arr = new byte[len];
+        shrinkToSize();
 
-        U.arrayCopy(valBytes, start, arr, 0, len);
-
-        return new CacheIndexedObjectImpl(arr, 0, len);
+        return this;
     }
 
     /**
@@ -361,4 +345,19 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter {
             len = valBytes.length;
         }
     }
+
+    /**
+     * Shrinks byte array to size boundaries.
+     */
+    private void shrinkToSize() {
+        if (detached())
+            return;
+
+        byte[] arr = new byte[len];
+
+        U.arrayCopy(valBytes, start, arr, 0, len);
+
+        valBytes = arr;
+        start = 0;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8df87710/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 b63bca6..e9c8973 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
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.internal.processors.cache;
 
+import org.apache.ignite.*;
 import org.jetbrains.annotations.*;
 
 /**
@@ -66,6 +67,14 @@ public class KeyCacheIndexedObjectImpl extends CacheIndexedObjectImpl implements
     }
 
     /** {@inheritDoc} */
+    @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException {
+        assert val != null || valBytes != null;
+
+        if (val == null && ctx.storeValue())
+            val = ctx.processor().unmarshal(ctx, valBytes, start, len, ldr);
+    }
+
+    /** {@inheritDoc} */
     @Override public byte directType() {
         // refer to GridIoMessageFactory.
         return 113;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8df87710/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 a4964b2..7d1eec3 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
@@ -84,9 +84,10 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
     /**
      * @param obj Portable object to get field from.
      * @param fieldName Field name.
+     * @throws IgniteFieldNotFoundException In case if there is no such a field.
      * @return Field value.
      */
-    public Object field(Object obj, String fieldName);
+    public Object field(Object obj, String fieldName) throws IgniteFieldNotFoundException;
 
     /**
      * Checks whether field is set in the object.

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8df87710/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 d29b64a..5456fad 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
@@ -334,19 +334,22 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
     }
 
     /** {@inheritDoc} */
-    @Override public Object field(Object obj, String fieldName) {
-        if (obj instanceof CacheIndexedObjectImpl) {
-            assert optMarshExt != null;
+    @Override public Object field(Object obj, String fieldName) throws IgniteFieldNotFoundException {
+        assert optMarshExt != null;
 
-            try {
-                return ((CacheIndexedObjectImpl)obj).field(fieldName, optMarshExt);
-            }
-            catch (IgniteCheckedException e) {
-                throw new IgniteException(e);
-            }
+        try {
+            return ((CacheIndexedObjectImpl)obj).field(fieldName, optMarshExt);
+        }
+        catch (IgniteFieldNotFoundException e) {
+            throw e;
+        }
+        catch (IgniteCheckedException e) {
+            throw new IgniteException(e);
+        }
+        catch (ClassCastException e) {
+            throw new IgniteFieldNotFoundException("Object doesn't have field [obj=" + obj + ", field=" + fieldName
+                + "]");
         }
-
-        return null;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8df87710/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 f51a0bb..3ce561a 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
@@ -35,6 +35,7 @@ import org.apache.ignite.internal.util.typedef.*;
 import org.apache.ignite.internal.util.typedef.internal.*;
 import org.apache.ignite.internal.util.worker.*;
 import org.apache.ignite.lang.*;
+import org.apache.ignite.marshaller.optimized.*;
 import org.apache.ignite.spi.indexing.*;
 import org.jetbrains.annotations.*;
 import org.jsr166.*;
@@ -1740,9 +1741,6 @@ public class GridQueryProcessor extends GridProcessorAdapter {
         /** Result class. */
         private Class<?> type;
 
-        /** */
-        private volatile int isKeyProp;
-
         /**
          * Constructor.
          *
@@ -1765,27 +1763,37 @@ public class GridQueryProcessor extends GridProcessorAdapter {
 
                 if (obj == null)
                     return null;
+
+                if (!(obj instanceof CacheIndexedObjectImpl))
+                    throw new IgniteCheckedException("Non-indexed object received as a result of property extraction " +
+                        "[parent=" + parent + ", propName=" + propName + ", obj=" + obj + ']');
+
+                return ctx.cacheObjects().field(obj, propName);
             }
             else {
-                int isKeyProp0 = isKeyProp;
-
-                if (isKeyProp0 == 0) {
-                    if (ctx.cacheObjects().hasField(key, propName))
-                        isKeyProp = isKeyProp0 = 1;
-                    else if (ctx.cacheObjects().hasField(val, propName))
-                        isKeyProp = isKeyProp0 = -1;
-                    else {
-                        U.warn(log, "Neither key nor value have property " +
-                            "[propName=" + propName + ", key=" + key + ", val=" + val + "]");
+                if (key instanceof CacheIndexedObjectImpl) {
+                    try {
+                        return ctx.cacheObjects().field(key, propName);
+                    }
+                    catch (IgniteFieldNotFoundException e) {
+                        // Ignore
+                    }
+                }
 
-                        return null;
+                if (val instanceof CacheIndexedObjectImpl) {
+                    try {
+                        return ctx.cacheObjects().field(val, propName);
+                    }
+                    catch (IgniteFieldNotFoundException e) {
+                        // Ignore
                     }
                 }
 
-                obj = isKeyProp0 == 1 ? key : val;
-            }
+                U.warn(log, "Neither key nor value have property " +
+                    "[propName=" + propName + ", key=" + key + ", val=" + val + "]");
 
-            return ctx.cacheObjects().field(obj, propName);
+                return null;
+            }
         }
 
         /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8df87710/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridDataInput.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridDataInput.java b/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridDataInput.java
index ad139a2..975fb68 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridDataInput.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridDataInput.java
@@ -167,4 +167,31 @@ public interface GridDataInput extends DataInput {
      * @throws IOException In case of error.
      */
     public char[] readCharArray() throws IOException;
+
+    /**
+     * Fast read of byte value at {@code pos}.
+     *
+     * @param pos Position in array.
+     *
+     * @return Byte value.
+     */
+    public byte readByte(int pos);
+
+    /**
+     * Fast read of short value at {@code pos}.
+     *
+     * @param pos Position in array.
+     *
+     * @return Short value.
+     */
+    public short readShort(int pos);
+
+    /**
+     * Fast read of integer value at {@code pos}.
+     *
+     * @param pos Position in array.
+     *
+     * @return Integer value.
+     */
+    public int readInt(int pos);
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8df87710/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridUnsafeDataInput.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridUnsafeDataInput.java b/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridUnsafeDataInput.java
index d76aac2..ed04cfe 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridUnsafeDataInput.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridUnsafeDataInput.java
@@ -496,6 +496,21 @@ public class GridUnsafeDataInput extends InputStream implements GridDataInput {
         return readUTFBody(readInt());
     }
 
+    /** {@inheritDoc} */
+    @Override public byte readByte(int pos) {
+        return UNSAFE.getByte(buf, byteArrOff + pos);
+    }
+
+    /** {@inheritDoc} */
+    @Override public short readShort(int pos) {
+        return UNSAFE.getShort(buf, byteArrOff + pos);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int readInt(int pos) {
+        return UNSAFE.getInt(buf, byteArrOff + pos);
+    }
+
     /**
      * Reads in the "body" (i.e., the UTF representation minus the 2-byte
      * or 8-byte length header) of a UTF encoding, which occupies the next

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8df87710/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/IgniteFieldNotFoundException.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/IgniteFieldNotFoundException.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/IgniteFieldNotFoundException.java
new file mode 100644
index 0000000..e5c3b5f
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/IgniteFieldNotFoundException.java
@@ -0,0 +1,38 @@
+/*
+ * 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.marshaller.optimized;
+
+import org.apache.ignite.*;
+
+/**
+ * Exception is thrown when there is an attempt to retrieve or deserialize an unexisting field from byte array
+ * that keeps serialized object.
+ */
+public class IgniteFieldNotFoundException extends IgniteCheckedException {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /**
+     * Creates new exception with given error message.
+     *
+     * @param msg Error message.
+     */
+    public IgniteFieldNotFoundException(String msg) {
+        super(msg);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8df87710/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExt.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExt.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExt.java
index 684b29b..fd0fa47 100644
--- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExt.java
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExt.java
@@ -371,6 +371,7 @@ public class OptimizedMarshallerExt extends OptimizedMarshaller {
      * @param clsLdr Class loader.
      * @param <T> Expected field class.
      * @return Field.
+     * @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)

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/8df87710/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 57f1a53..b941c41 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
@@ -1305,18 +1305,14 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt
      * @throws IOException in case of error.
      */
     public boolean hasField(String fieldName) throws IOException {
-        int pos = in.position();
+        int start = in.position();
 
-        byte type = in.readByte();
+        byte type = in.readByte(start);
 
-        if (type != SERIALIZABLE && type != MARSHAL_AWARE) {
-            in.position(pos);
+        if (type != SERIALIZABLE && type != MARSHAL_AWARE)
             return false;
-        }
-
-        FieldRange range = fieldRange(fieldName, pos);
 
-        in.position(pos);
+        FieldRange range = fieldRange(fieldName, start);
 
         return range != null && range.start >= 0;
     }
@@ -1328,41 +1324,38 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt
      *
      * @param fieldName Field name.
      * @return Field.
+     * @throws IgniteFieldNotFoundException In case if there is no such a field.
      * @throws IOException In case of error.
      * @throws ClassNotFoundException In case of error.
      */
-    public <F> F readField(String fieldName) throws IOException, ClassNotFoundException {
-        int pos = in.position();
+    public <F> F readField(String fieldName) throws IgniteFieldNotFoundException, IOException, ClassNotFoundException {
+        int start = in.position();
 
-        byte type = in.readByte();
+        byte type = in.readByte(start);
 
-        if (type != SERIALIZABLE && type != MARSHAL_AWARE) {
-            in.position(pos);
-            return null;
-        }
-
-        FieldRange range = fieldRange(fieldName, pos);
+        if (type != SERIALIZABLE && type != MARSHAL_AWARE)
+            throw new IgniteFieldNotFoundException("Object doesn't support fields indexing.");
 
-        F field = null;
+        FieldRange range = fieldRange(fieldName, start);
 
         if (range != null && range.start >= 0) {
-            in.position(range.start);
+            byte fieldType = in.readByte(range.start);
 
-            byte fieldType = in.readByte();
-
-            if ((fieldType == SERIALIZABLE && metaHandler.metadata(in.readInt()) != null) ||
-                fieldType == MARSHAL_AWARE)
-                //Do we need to make a copy of array?
-                field = (F)new CacheIndexedObjectImpl(in.array(), range.start, range.len);
+            if ((fieldType == SERIALIZABLE && metaHandler.metadata(in.readInt(range.start + 1)) != null)
+                || fieldType == MARSHAL_AWARE)
+                return  (F)new CacheIndexedObjectImpl(in.array(), range.start, range.len);
             else {
                 in.position(range.start);
-                field = (F)readObject();
-            }
-        }
 
-        in.position(pos);
+                F obj = (F)readObject();
+
+                in.position(start);
 
-        return field;
+                return obj;
+            }
+        }
+        else
+            throw new IgniteFieldNotFoundException("Object doesn't have a field with the name: " + fieldName);
     }
 
     /**
@@ -1374,18 +1367,25 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt
      * @throws IOException in case of error.
      */
     private FieldRange fieldRange(String fieldName, int start) throws IOException {
+        int pos = start + 1;
+
         int fieldId = resolveFieldId(fieldName);
 
-        int typeId = readInt();
+        int typeId = in.readInt(pos);
+        pos += 4;
 
         int clsNameLen = 0;
 
         if (typeId == 0) {
-            int pos = in.position();
+            int oldPos = in.position();
+
+            in.position(pos);
 
             typeId = OptimizedMarshallerUtils.resolveTypeId(readUTF(), mapper);
 
             clsNameLen = in.position() - pos;
+
+            in.position(oldPos);
         }
 
         OptimizedObjectMetadata meta = metaHandler.metadata(typeId);
@@ -1396,16 +1396,13 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt
 
         int end = in.size();
 
-        in.position(end - FOOTER_LEN_OFF);
-
-        short footerLen = in.readShort();
+        short footerLen = in.readShort(end - FOOTER_LEN_OFF);
 
         if (footerLen == EMPTY_FOOTER)
             return null;
 
-        // +2 - skipping length at the beginning
-        int footerOff = (end - footerLen) + 2;
-        in.position(footerOff);
+        // Calculating footer offset. +2 - skipping length at the beginning
+        pos = (end - footerLen) + 2;
 
         int fieldOff = 0;
 
@@ -1414,8 +1411,9 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt
             boolean isHandle;
 
             if (info.length() == VARIABLE_LEN) {
-                int fieldInfo = in.readInt();
+                int fieldInfo = in.readInt(pos);
 
+                pos += 4;
                 len = fieldInfo & FOOTER_BODY_LEN_MASK;
                 isHandle = ((fieldInfo & FOOTER_BODY_IS_HANDLE_MASK) >> FOOTER_BODY_HANDLE_MASK_BIT) == 1;
             }
@@ -1432,13 +1430,13 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt
                     return new FieldRange(start + fieldOff, len);
                 }
                 else
-                    return new FieldRange(in.readInt(), in.readInt());
+                    return new FieldRange(in.readInt(pos), in.readInt(pos + 4));
             }
             else {
                 fieldOff += len;
 
                 if (isHandle) {
-                    in.skipBytes(8);
+                    pos += 8;
                     fieldOff += 8;
                 }
             }