Merge remote-tracking branch 'remotes/origin/ignite-1157' into ignite-1.3.3
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index d0dd29b..7e96b29 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -248,7 +248,7 @@
      */
     public static final String IGNITE_OFFHEAP_SAFE_RELEASE = "IGNITE_OFFHEAP_SAFE_RELEASE";
 
-    /** Maximum size for atomic cache queue delete history. */
+    /** Maximum size for atomic cache queue delete history (default is 200 000 entries per partition). */
     public static final String IGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE = "IGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE";
 
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
index 22d6d7a..b1e223b 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
@@ -138,6 +138,7 @@
      * @param fieldName Field name.
      * @param obj Cache object.
      * @return Field value from object.
+     * @throws CacheException in case of error.
      */
     @Nullable protected abstract Object extractParameter(@Nullable String cacheName, String typeName, String fieldName,
         Object obj) throws CacheException;
@@ -179,6 +180,7 @@
     /**
      * Prepare internal store specific builders for provided types metadata.
      *
+     * @param cacheName Cache name to prepare builders for.
      * @param types Collection of types.
      * @throws CacheException If failed to prepare internal builders for types.
      */
@@ -503,6 +505,7 @@
     }
 
     /**
+     * @param cacheName Cache name to check mapping for.
      * @param clsName Class name.
      * @param fields Fields descriptors.
      * @throws CacheException If failed to check type metadata.
@@ -546,6 +549,7 @@
     }
 
     /**
+     * @param cacheName Cache name to check mappings for.
      * @return Type mappings for specified cache name.
      * @throws CacheException If failed to initialize cache mappings.
      */
@@ -607,9 +611,12 @@
     private EntryMapping entryMapping(String cacheName, Object keyTypeId, Object key) throws CacheException {
         EntryMapping em = cacheMappings(cacheName).get(keyTypeId);
 
-        if (em == null)
+        if (em == null) {
+            String maskedCacheName = U.maskName(cacheName);
+
             throw new CacheException("Failed to find mapping description [key=" + key +
-                ", cache=" + U.maskName(cacheName) + "]");
+                ", cache=" + maskedCacheName + "]. Please configure CacheTypeMetadata to associate '" + maskedCacheName + "' with JdbcPojoStore.");
+        }
 
         return em;
     }
@@ -1541,6 +1548,7 @@
          * Extract database column names from {@link CacheTypeFieldMetadata}.
          *
          * @param dsc collection of {@link CacheTypeFieldMetadata}.
+         * @return Collection with database column names.
          */
         private static Collection<String> databaseColumns(Collection<CacheTypeFieldMetadata> dsc) {
             return F.transform(dsc, new C1<CacheTypeFieldMetadata, String>() {
@@ -1555,6 +1563,7 @@
          * Construct query for select values with key count less or equal {@code maxKeysPerStmt}
          *
          * @param keyCnt Key count.
+         * @return Load query statement text.
          */
         protected String loadQuery(int keyCnt) {
             assert keyCnt <= maxKeysPerStmt;
@@ -1579,12 +1588,16 @@
             return dialect.loadCacheRangeQuery(fullTblName, keyCols, cols, appendLowerBound, appendUpperBound);
         }
 
-        /** Key type. */
+        /**
+         * @return Key type.
+         */
         protected String keyType() {
             return typeMeta.getKeyType();
         }
 
-        /** Value type. */
+        /**
+         * @return Value type.
+         */
         protected String valueType() {
             return typeMeta.getValueType();
         }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
index 5cbe377..3790703 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
@@ -583,22 +583,7 @@
     public static IgniteBiTuple<Collection<IgniteConfiguration>, ? extends GridSpringResourceContext>
     loadConfigurations(String springCfgPath) throws IgniteCheckedException {
         A.notNull(springCfgPath, "springCfgPath");
-
-        URL url;
-
-        try {
-            url = new URL(springCfgPath);
-        }
-        catch (MalformedURLException e) {
-            url = U.resolveIgniteUrl(springCfgPath);
-
-            if (url == null)
-                throw new IgniteCheckedException("Spring XML configuration path is invalid: " + springCfgPath +
-                    ". Note that this path should be either absolute or a relative local file system path, " +
-                    "relative to META-INF in classpath or valid URL to IGNITE_HOME.", e);
-        }
-
-        return loadConfigurations(url);
+        return loadConfigurations(IgniteUtils.resolveSpringUrl(springCfgPath));
     }
 
     /**
@@ -1087,6 +1072,32 @@
     }
 
     /**
+     * Gets grid instance without waiting its initialization and not throwing any exception.
+     *
+     * @param locNodeId ID of local node the requested grid instance is managing.
+     * @return Grid instance or {@code null}.
+     */
+    public static IgniteKernal gridxx(UUID locNodeId) {
+        IgniteNamedInstance dfltGrid0 = dfltGrid;
+
+        if (dfltGrid0 != null) {
+            IgniteKernal g = dfltGrid0.grid();
+
+            if (g != null && g.getLocalNodeId().equals(locNodeId))
+                return g;
+        }
+
+        for (IgniteNamedInstance grid : grids.values()) {
+            IgniteKernal g = grid.grid();
+
+            if (g != null && g.getLocalNodeId().equals(locNodeId))
+                return g;
+        }
+
+        return null;
+    }
+
+    /**
      * Gets an named grid instance. If grid name is {@code null} or empty string,
      * then default no-name grid will be returned. Note that caller of this method
      * should not assume that it will return the same instance every time.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
index c1fb79a..65b6fad 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
@@ -57,6 +57,9 @@
  * Grid communication manager.
  */
 public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializable>> {
+    /** */
+    public static volatile boolean TURBO_DEBUG_MODE;
+
     /** Empty array of message factories. */
     public static final MessageFactory[] EMPTY = {};
 
@@ -894,7 +897,7 @@
 
         if (msgC == null) {
             // Message from local node can be processed in sync manner.
-            assert locNodeId.equals(nodeId);
+            assert locNodeId.equals(nodeId) || TURBO_DEBUG_MODE;
 
             unwindMessageSet(set, lsnr);
 
@@ -1019,6 +1022,85 @@
     }
 
     /**
+     * This method can be used for debugging tricky concurrency issues
+     * with multi-nodes in single JVM.
+     * <p>
+     * This method eliminates network between nodes started in single JVM
+     * when {@link #TURBO_DEBUG_MODE} is set to {@code true}.
+     * <p>
+     * How to use it:
+     * <ol>
+     *     <li>Replace {@link #send(ClusterNode, Object, int, Message, byte, boolean, long, boolean)}
+     *          with this method.</li>
+     *     <li>Start all grids for your test, then set {@link #TURBO_DEBUG_MODE} to {@code true}.</li>
+     *     <li>Perform test operations on the topology. No network will be there.</li>
+     *     <li>DO NOT turn on turbo debug before all grids started. This will cause deadlocks.</li>
+     * </ol>
+     *
+     * @param node Destination node.
+     * @param topic Topic to send the message to.
+     * @param topicOrd GridTopic enumeration ordinal.
+     * @param msg Message to send.
+     * @param plc Type of processing.
+     * @param ordered Ordered flag.
+     * @param timeout Timeout.
+     * @param skipOnTimeout Whether message can be skipped on timeout.
+     * @throws IgniteCheckedException Thrown in case of any errors.
+     */
+    private void sendTurboDebug(
+        ClusterNode node,
+        Object topic,
+        int topicOrd,
+        Message msg,
+        byte plc,
+        boolean ordered,
+        long timeout,
+        boolean skipOnTimeout
+    ) throws IgniteCheckedException {
+        assert node != null;
+        assert topic != null;
+        assert msg != null;
+
+        GridIoMessage ioMsg = new GridIoMessage(plc, topic, topicOrd, msg, ordered, timeout, skipOnTimeout);
+
+        IgniteKernal rmt;
+
+        if (locNodeId.equals(node.id())) {
+            assert plc != P2P_POOL;
+
+            CommunicationListener commLsnr = this.commLsnr;
+
+            if (commLsnr == null)
+                throw new IgniteCheckedException("Trying to send message when grid is not fully started.");
+
+            if (ordered)
+                processOrderedMessage(locNodeId, ioMsg, plc, null);
+            else
+                processRegularMessage0(ioMsg, locNodeId);
+        }
+        else if (TURBO_DEBUG_MODE && (rmt = IgnitionEx.gridxx(locNodeId)) != null) {
+            if (ioMsg.isOrdered())
+                rmt.context().io().processOrderedMessage(locNodeId, ioMsg, ioMsg.policy(), null);
+            else
+                rmt.context().io().processRegularMessage0(ioMsg, locNodeId);
+        }
+        else {
+            if (topicOrd < 0)
+                ioMsg.topicBytes(marsh.marshal(topic));
+
+            try {
+                getSpi().sendMessage(node, ioMsg);
+            }
+            catch (IgniteSpiException e) {
+                throw new IgniteCheckedException("Failed to send message (node may have left the grid or " +
+                    "TCP connection cannot be established due to firewall issues) " +
+                    "[node=" + node + ", topic=" + topic +
+                    ", msg=" + msg + ", policy=" + plc + ']', e);
+            }
+        }
+    }
+
+    /**
      * @param nodeId Id of destination node.
      * @param topic Topic to send the message to.
      * @param msg Message to send.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
index bb87a86..8e2b20e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
@@ -497,6 +497,9 @@
         cleanup(cfg, cfg.getAffinityMapper(), false);
         cleanup(cfg, cctx.store().configuredStore(), false);
 
+        if (!CU.isUtilityCache(cfg.getName()) && !CU.isSystemCache(cfg.getName()))
+            unregisterMbean(cctx.cache().mxBean(), cfg.getName(), false);
+
         NearCacheConfiguration nearCfg = cfg.getNearConfiguration();
 
         if (nearCfg != null)
@@ -1356,6 +1359,9 @@
             cacheCtx.cache(dht);
         }
 
+        if (!CU.isUtilityCache(cache.name()) && !CU.isSystemCache(cache.name()))
+            registerMbean(cache.mxBean(), cache.name(), false);
+
         return ret;
     }
 
@@ -2940,7 +2946,7 @@
         cacheName = near ? cacheName + "-near" : cacheName;
 
         for (Class<?> itf : o.getClass().getInterfaces()) {
-            if (itf.getName().endsWith("MBean")) {
+            if (itf.getName().endsWith("MBean") || itf.getName().endsWith("MXBean")) {
                 try {
                     U.registerCacheMBean(srvr, ctx.gridName(), cacheName, o.getClass().getName(), o,
                         (Class<Object>)itf);
@@ -2973,7 +2979,7 @@
         cacheName = near ? cacheName + "-near" : cacheName;
 
         for (Class<?> itf : o.getClass().getInterfaces()) {
-            if (itf.getName().endsWith("MBean")) {
+            if (itf.getName().endsWith("MBean") || itf.getName().endsWith("MXBean")) {
                 try {
                     srvr.unregisterMBean(U.makeCacheMBeanName(ctx.gridName(), cacheName, o.getClass().getName()));
                 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProxyImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProxyImpl.java
index cec8c53..3bbd4af 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProxyImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProxyImpl.java
@@ -221,8 +221,8 @@
     @Override public <K1, V1> GridCacheProxyImpl<K1, V1> keepPortable() {
         if (opCtx != null && opCtx.isKeepPortable())
             return (GridCacheProxyImpl<K1, V1>)this;
-        
-        return new GridCacheProxyImpl<>((GridCacheContext<K1, V1>)ctx, 
+
+        return new GridCacheProxyImpl<>((GridCacheContext<K1, V1>)ctx,
             (GridCacheAdapter<K1, V1>)delegate,
             opCtx != null ? opCtx.keepPortable() : new CacheOperationContext(false, null, true, null, false));
     }
@@ -1486,25 +1486,6 @@
     }
 
     /** {@inheritDoc} */
-    @Override public void writeExternal(ObjectOutput out) throws IOException {
-        out.writeObject(ctx);
-        out.writeObject(delegate);
-        out.writeObject(opCtx);
-    }
-
-    /** {@inheritDoc} */
-    @SuppressWarnings({"unchecked"})
-    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-        ctx = (GridCacheContext<K, V>)in.readObject();
-        delegate = (GridCacheAdapter<K, V>)in.readObject();
-        opCtx = (CacheOperationContext)in.readObject();
-
-        gate = ctx.gate();
-
-        aff = new GridCacheAffinityProxy<>(ctx, ctx.cache().affinity());
-    }
-
-    /** {@inheritDoc} */
     @Nullable @Override public ExpiryPolicy expiry() {
         return opCtx != null ? opCtx.expiry() : null;
     }
@@ -1523,6 +1504,25 @@
     }
 
     /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(ctx);
+        out.writeObject(delegate);
+        out.writeObject(opCtx);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings({"unchecked"})
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        ctx = (GridCacheContext<K, V>)in.readObject();
+        delegate = (IgniteInternalCache<K, V>)in.readObject();
+        opCtx = (CacheOperationContext)in.readObject();
+
+        gate = ctx.gate();
+
+        aff = new GridCacheAffinityProxy<>(ctx, ctx.cache().affinity());
+    }
+
+    /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(GridCacheProxyImpl.class, this);
     }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
index f88e288..41e3896 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUtils.java
@@ -57,7 +57,6 @@
 import static org.apache.ignite.cache.CacheRebalanceMode.*;
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.*;
 import static org.apache.ignite.internal.GridTopic.*;
-import static org.apache.ignite.internal.IgniteNodeAttributes.*;
 import static org.apache.ignite.internal.processors.cache.GridCacheOperation.*;
 
 /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
index 58f6fe5..d109d2b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
@@ -437,17 +437,19 @@
 
                 ClusterNode primary = null;
 
-                if (v == null && allowLocRead) {
+                if (v == null && allowLocRead && cctx.affinityNode()) {
                     GridDhtCacheAdapter<K, V> dht = cache().dht();
 
+                    GridCacheEntryEx dhtEntry = null;
+
                     try {
-                        entry = dht.context().isSwapOrOffheapEnabled() ? dht.entryEx(key) : dht.peekEx(key);
+                        dhtEntry = dht.context().isSwapOrOffheapEnabled() ? dht.entryEx(key) : dht.peekEx(key);
 
                         // If near cache does not have value, then we peek DHT cache.
-                        if (entry != null) {
-                            boolean isNew = entry.isNewLocked() || !entry.valid(topVer);
+                        if (dhtEntry != null) {
+                            boolean isNew = dhtEntry.isNewLocked() || !dhtEntry.valid(topVer);
 
-                            v = entry.innerGet(tx,
+                            v = dhtEntry.innerGet(tx,
                                 /*swap*/true,
                                 /*read-through*/false,
                                 /*fail-fast*/true,
@@ -461,7 +463,7 @@
                                 expiryPlc);
 
                             // Entry was not in memory or in swap, so we remove it from cache.
-                            if (v == null && isNew && entry.markObsoleteIfEmpty(ver))
+                            if (v == null && isNew && dhtEntry.markObsoleteIfEmpty(ver))
                                 dht.removeIfObsolete(key);
                         }
 
@@ -483,12 +485,12 @@
                                 near.metrics0().onRead(false);
                         }
                     }
-                    catch (GridDhtInvalidPartitionException ignored) {
+                    catch (GridDhtInvalidPartitionException | GridCacheEntryRemovedException ignored) {
                         // No-op.
                     }
                     finally {
-                        if (entry != null && (tx == null || (!tx.implicit() && tx.isolation() == READ_COMMITTED))) {
-                            dht.context().evicts().touch(entry, topVer);
+                        if (dhtEntry != null && (tx == null || (!tx.implicit() && tx.isolation() == READ_COMMITTED))) {
+                            dht.context().evicts().touch(dhtEntry, topVer);
 
                             entry = null;
                         }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java
index 26b0568..cc349cc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java
@@ -39,6 +39,7 @@
 import org.apache.ignite.internal.util.typedef.*;
 import org.apache.ignite.internal.util.typedef.internal.*;
 import org.apache.ignite.lang.*;
+import org.apache.ignite.plugin.security.*;
 import org.apache.ignite.stream.*;
 import org.jetbrains.annotations.*;
 import org.jsr166.*;
@@ -406,6 +407,8 @@
     @Override public IgniteFuture<?> addData(Collection<? extends Map.Entry<K, V>> entries) {
         A.notEmpty(entries, "entries");
 
+        checkSecurityPermission(SecurityPermission.CACHE_PUT);
+
         enterBusy();
 
         try {
@@ -513,6 +516,11 @@
     @Override public IgniteFuture<?> addData(K key, V val) {
         A.notNull(key, "key");
 
+        if (val == null)
+            checkSecurityPermission(SecurityPermission.CACHE_REMOVE);
+        else
+            checkSecurityPermission(SecurityPermission.CACHE_PUT);
+
         KeyCacheObject key0 = cacheObjProc.toCacheKeyObject(cacheObjCtx, key, true);
         CacheObject val0 = cacheObjProc.toCacheObject(cacheObjCtx, val, true);
 
@@ -936,6 +944,20 @@
     }
 
     /**
+     * Check permissions for streaming.
+     *
+     * @param perm Security permission.
+     * @throws org.apache.ignite.plugin.security.SecurityException If permissions are not enough for streaming.
+     */
+    private void checkSecurityPermission(SecurityPermission perm)
+        throws org.apache.ignite.plugin.security.SecurityException{
+        if (!ctx.security().enabled())
+            return;
+
+        ctx.security().authorize(cacheName, perm, null);
+    }
+
+    /**
      *
      */
     private class Buffer {
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerUpdateJob.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerUpdateJob.java
index 21ba3ac..9e0703a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerUpdateJob.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerUpdateJob.java
@@ -22,6 +22,7 @@
 import org.apache.ignite.internal.processors.cache.*;
 import org.apache.ignite.internal.util.lang.*;
 import org.apache.ignite.internal.util.typedef.*;
+import org.apache.ignite.plugin.security.*;
 import org.apache.ignite.stream.*;
 import org.jetbrains.annotations.*;
 
@@ -106,8 +107,13 @@
 
                 CacheObject val = e.getValue();
 
-                if (val != null)
+                if (val != null) {
+                    checkSecurityPermission(SecurityPermission.CACHE_PUT);
+
                     val.finishUnmarshal(cctx.cacheObjectContext(), cctx.deploy().globalLoader());
+                }
+                else
+                    checkSecurityPermission(SecurityPermission.CACHE_REMOVE);
             }
 
             if (unwrapEntries()) {
@@ -139,4 +145,16 @@
     private boolean unwrapEntries() {
         return !(rcvr instanceof DataStreamerCacheUpdaters.InternalUpdater);
     }
+
+    /**
+     * @param perm Security permission.
+     * @throws org.apache.ignite.plugin.security.SecurityException If permission is not enough.
+     */
+    private void checkSecurityPermission(SecurityPermission perm)
+        throws org.apache.ignite.plugin.security.SecurityException {
+        if (!ctx.security().enabled())
+            return;
+
+        ctx.security().authorize(cacheName, perm, null);
+    }
 }
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 6bd361f..3366256 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
@@ -3308,6 +3308,9 @@
             url = U.resolveIgniteUrl(springCfgPath);
 
             if (url == null)
+                url = resolveInClasspath(springCfgPath);
+
+            if (url == null)
                 throw new IgniteCheckedException("Spring XML configuration path is invalid: " + springCfgPath +
                     ". Note that this path should be either absolute or a relative local file system path, " +
                     "relative to META-INF in classpath or valid URL to IGNITE_HOME.", e);
@@ -3317,6 +3320,19 @@
     }
 
     /**
+     * @param path Resource path.
+     * @return Resource URL inside classpath or {@code null}.
+     */
+    @Nullable private static URL resolveInClasspath(String path) {
+        ClassLoader clsLdr = Thread.currentThread().getContextClassLoader();
+
+        if (clsLdr == null)
+            return null;
+
+        return clsLdr.getResource(path.replaceAll("\\\\", "/"));
+    }
+
+    /**
      * Gets URL representing the path passed in. First the check is made if path is absolute.
      * If not, then the check is made if path is relative to {@code META-INF} folder in classpath.
      * If not, then the check is made if path is relative to ${IGNITE_HOME}.
diff --git a/modules/core/src/test/config/io-manager-benchmark.xml b/modules/core/src/test/config/io-manager-benchmark.xml
index 9b97407b..4f481ec 100644
--- a/modules/core/src/test/config/io-manager-benchmark.xml
+++ b/modules/core/src/test/config/io-manager-benchmark.xml
@@ -27,8 +27,7 @@
 
         <property name="communicationSpi">
             <bean class="org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi">
-                <property name="asyncSend" value="true"/>
-                <property name="tcpNoDelay" value="false"/>
+                <property name="sharedMemoryPort" value="-1"/>
             </bean>
         </property>
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteCacheNearOffheapGetSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteCacheNearOffheapGetSelfTest.java
new file mode 100644
index 0000000..6edf5b6
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteCacheNearOffheapGetSelfTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.distributed;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cache.*;
+import org.apache.ignite.cache.affinity.*;
+import org.apache.ignite.cache.eviction.fifo.*;
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.internal.processors.cache.*;
+
+import java.util.*;
+
+import static org.apache.ignite.cache.CacheMode.*;
+
+/**
+ *
+ */
+public class IgniteCacheNearOffheapGetSelfTest extends GridCacheAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected int gridCount() {
+        return 4;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        if (nearEnabled())
+            grid(gridCount() - 1).getOrCreateCache(new CacheConfiguration(), nearConfiguration());
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
+    @Override protected NearCacheConfiguration nearConfiguration() {
+        NearCacheConfiguration nearCfg = super.nearConfiguration();
+
+        nearCfg.setNearEvictionPolicy(new FifoEvictionPolicy(100));
+
+        return nearCfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        if (getTestGridName(gridCount() - 1).equals(gridName)) {
+            cfg.setClientMode(true);
+
+            cfg.setCacheConfiguration();
+        }
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
+    @Override protected CacheConfiguration cacheConfiguration(String gridName) throws Exception {
+        CacheConfiguration cfg = super.cacheConfiguration(gridName);
+
+        cfg.setBackups(1);
+        cfg.setMemoryMode(CacheMemoryMode.OFFHEAP_TIERED);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return PARTITIONED;
+    }
+
+    @Override
+    protected long getTestTimeout() {
+        return Long.MAX_VALUE;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testGetFromNear() throws Exception {
+
+        IgniteCache<Object, Object> nearOnly = ignite(gridCount() - 1).cache(null);
+
+        // Start extra node.
+        IgniteEx ignite = startGrid(gridCount());
+
+        try {
+            final int keyCnt = 30;
+
+            for (int i = 0; i < keyCnt; i++)
+                ignite(0).cache(null).put(i, i);
+
+            for (int i = 0; i < keyCnt; i++)
+                assertEquals(i, nearOnly.get(i));
+
+            Collection<Integer> invalidatedKeys = new ArrayList<>();
+
+            Affinity<Object> cacheAff = ignite.affinity(null);
+
+            // Going to stop the last node.
+            for (int i = 0; i < keyCnt; i++) {
+                if (cacheAff.mapKeyToNode(i).equals(ignite.localNode()))
+                    invalidatedKeys.add(i);
+            }
+
+            stopGrid(gridCount());
+
+            for (Integer key : invalidatedKeys)
+                assertEquals(key, nearOnly.get(key));
+        }
+        finally {
+            if (Ignition.state(getTestGridName(gridCount())) == IgniteState.STARTED)
+                stopGrid(gridCount());
+        }
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedMultiNodeFullApiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedMultiNodeFullApiSelfTest.java
index 30c9e8a..747de21 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedMultiNodeFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedMultiNodeFullApiSelfTest.java
@@ -306,7 +306,7 @@
         for (int i = 0; i < gridCount(); i++) {
             IgniteEx ignite = grid(i);
 
-            if (!ignite.configuration().isClientMode()) {
+            if (!Boolean.TRUE.equals(ignite.configuration().isClientMode())) {
                 if (ignite0 == null)
                     ignite0 = ignite;
                 else if (ignite1 == null)
@@ -361,7 +361,9 @@
         boolean nearEnabled = cache2.getConfiguration(CacheConfiguration.class).getNearConfiguration() != null;
 
         assertEquals(nearEnabled ? 2 : 0, cache2.localSize(NEAR));
-        assertEquals(0, cache2.localSize(CachePeekMode.ALL) - cache2.localSize(NEAR));
+
+        if (cacheMode() != REPLICATED)
+            assertEquals(0, cache2.localSize(CachePeekMode.ALL) - cache2.localSize(NEAR));
     }
 
     /**
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite2.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite2.java
index 6a59826..bf760f5 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite2.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite2.java
@@ -123,6 +123,7 @@
         suite.addTest(new TestSuite(GridCacheColocatedOptimisticTransactionSelfTest.class));
         suite.addTestSuite(GridCacheAtomicMessageCountSelfTest.class);
         suite.addTest(new TestSuite(GridCacheNearPartitionedClearSelfTest.class));
+        suite.addTest(new TestSuite(IgniteCacheNearOffheapGetSelfTest.class));
 
         suite.addTest(new TestSuite(GridCacheDhtExpiredEntriesPreloadSelfTest.class));
         suite.addTest(new TestSuite(GridCacheNearExpiredEntriesPreloadSelfTest.class));
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
index 0f38353..6ab1a1b 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
@@ -50,6 +50,7 @@
 import static org.apache.ignite.events.EventType.*;
 import static org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion.*;
 import static org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionState.*;
+import static org.apache.ignite.internal.processors.query.h2.twostep.GridReduceQueryExecutor.*;
 import static org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2ValueMessageFactory.*;
 
 /**
@@ -495,7 +496,7 @@
             if (node.isLocal())
                 h2.reduceQueryExecutor().onMessage(ctx.localNodeId(), msg);
             else
-                ctx.io().send(node, GridTopic.TOPIC_QUERY, msg, GridIoPolicy.PUBLIC_POOL);
+                ctx.io().send(node, GridTopic.TOPIC_QUERY, msg, QUERY_POOL);
         }
         catch (Exception e) {
             e.addSuppressed(err);
@@ -556,7 +557,7 @@
             if (loc)
                 h2.reduceQueryExecutor().onMessage(ctx.localNodeId(), msg);
             else
-                ctx.io().send(node, GridTopic.TOPIC_QUERY, msg, GridIoPolicy.PUBLIC_POOL);
+                ctx.io().send(node, GridTopic.TOPIC_QUERY, msg, QUERY_POOL);
         }
         catch (IgniteCheckedException e) {
             log.error("Failed to send message.", e);
@@ -583,7 +584,7 @@
         if (loc)
             h2.reduceQueryExecutor().onMessage(ctx.localNodeId(), msg);
         else
-            ctx.io().send(node, GridTopic.TOPIC_QUERY, msg, GridIoPolicy.PUBLIC_POOL);
+            ctx.io().send(node, GridTopic.TOPIC_QUERY, msg, QUERY_POOL);
     }
 
     /**
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
index 32d1c95..ffa2bc0 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
@@ -63,6 +63,9 @@
  * Reduce query executor.
  */
 public class GridReduceQueryExecutor {
+    /** Thread pool to process query messages. */
+    public static final byte QUERY_POOL = GridIoPolicy.SYSTEM_POOL;
+
     /** */
     private GridKernalContext ctx;
 
@@ -248,7 +251,7 @@
                         if (node.isLocal())
                             h2.mapQueryExecutor().onMessage(ctx.localNodeId(), msg0);
                         else
-                            ctx.io().send(node, GridTopic.TOPIC_QUERY, msg0, GridIoPolicy.PUBLIC_POOL);
+                            ctx.io().send(node, GridTopic.TOPIC_QUERY, msg0, QUERY_POOL);
                     }
                     catch (IgniteCheckedException e) {
                         throw new CacheException("Failed to fetch data from node: " + node.id(), e);
@@ -855,7 +858,7 @@
             }
 
             try {
-                ctx.io().send(node, GridTopic.TOPIC_QUERY, copy(msg, node, partsMap), GridIoPolicy.PUBLIC_POOL);
+                ctx.io().send(node, GridTopic.TOPIC_QUERY, copy(msg, node, partsMap), QUERY_POOL);
             }
             catch (IgniteCheckedException e) {
                 ok = false;
diff --git a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java
index 855c9f7..860ff68 100644
--- a/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java
+++ b/modules/schema-import/src/main/java/org/apache/ignite/schema/parser/dialect/OracleMetadataDialect.java
@@ -42,7 +42,7 @@
         " WHERE a.owner = ? and a.table_name = ? AND a.constraint_type = 'P'";
 
     /** SQL to get indexes metadata. */
-    private static final String SQL_INDEXES = "select i.index_name, u.column_expression, i.column_name, i.descend" +
+    private static final String SQL_INDEXES = "SELECT i.index_name, u.column_expression, i.column_name, i.descend" +
         " FROM all_ind_columns i" +
         " LEFT JOIN user_ind_expressions u on u.index_name = i.index_name and i.table_name = u.table_name" +
         " WHERE i.index_owner = ? and i.table_name = ?" +
@@ -238,7 +238,7 @@
             String user = conn.getMetaData().getUserName().toUpperCase();
 
             String sql = String.format(SQL_COLUMNS,
-                tblsOnly ? "INNER JOIN all_tables b on a.table_name = b.table_name" : "", user);
+                tblsOnly ? "INNER JOIN all_tables b on a.table_name = b.table_name and a.owner = b.owner" : "", user);
 
             try (ResultSet colsRs = colsStmt.executeQuery(sql)) {
                 String prevSchema = "";
diff --git a/modules/spring/src/test/java/config/ignite-test-config.xml b/modules/spring/src/test/java/config/ignite-test-config.xml
new file mode 100644
index 0000000..145d124
--- /dev/null
+++ b/modules/spring/src/test/java/config/ignite-test-config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<!--
+    Ignite configuration with all defaults and enabled p2p deployment and enabled events.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+        <property name="localHost" value="127.0.0.1" />
+
+        <property name="gridName" value="config-in-classpath"/>
+
+        <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. -->
+        <property name="discoverySpi">
+            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+                <property name="ipFinder">
+                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+                        <property name="shared" value="true"/>
+                    </bean>
+                </property>
+            </bean>
+        </property>
+    </bean>
+</beans>
diff --git a/modules/spring/src/test/java/org/apache/ignite/internal/GridFactorySelfTest.java b/modules/spring/src/test/java/org/apache/ignite/internal/GridFactorySelfTest.java
index ecc7fb7..fb8cbfe 100644
--- a/modules/spring/src/test/java/org/apache/ignite/internal/GridFactorySelfTest.java
+++ b/modules/spring/src/test/java/org/apache/ignite/internal/GridFactorySelfTest.java
@@ -824,6 +824,15 @@
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testConfigInClassPath() throws Exception {
+        try (Ignite ignite = Ignition.start("config/ignite-test-config.xml")) {
+            assert "config-in-classpath".equals(ignite.name());
+        }
+    }
+
+    /**
      * Test task.
      */
     private static class TestTask extends ComputeTaskSplitAdapter<Void, Void> {
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/kill/VisorKillCommand.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/kill/VisorKillCommand.scala
index f94e3ee..6cd1ffa 100644
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/kill/VisorKillCommand.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/kill/VisorKillCommand.scala
@@ -256,7 +256,7 @@
         askForHost("Select host from:") match {
             case Some(p) => ask("Do you want to [k]ill or [r]estart? (k/r) [r]: ", "r") match {
                 case "k" | "K" => killOrRestart(p.nodes().map(_.id), false)
-                case "r" | "R" => killOrRestart(p.nodes().map(_.id), false)
+                case "r" | "R" => killOrRestart(p.nodes().map(_.id), true)
                 case x => nl(); warn("Invalid answer: " + x)
             }
             case None => ()