You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2017/02/10 12:52:12 UTC

[2/4] ignite git commit: IGNITE-1680: CPP: Implemented API for user entry point lookup. This closes #1430.

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/include/ignite/impl/ignite_binding_impl.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/impl/ignite_binding_impl.h b/modules/platforms/cpp/core/include/ignite/impl/ignite_binding_impl.h
new file mode 100644
index 0000000..32de2cb
--- /dev/null
+++ b/modules/platforms/cpp/core/include/ignite/impl/ignite_binding_impl.h
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#ifndef _IGNITE_IMPL_IGNITE_BINDING_IMPL
+#define _IGNITE_IMPL_IGNITE_BINDING_IMPL
+
+#include <map>
+
+#include <ignite/common/common.h>
+
+#include <ignite/impl/binary/binary_reader_impl.h>
+#include <ignite/impl/binary/binary_writer_impl.h>
+
+namespace ignite
+{
+    namespace impl
+    {
+        /**
+         * Ignite binding implementation.
+         *
+         * Used to register and invoke callbacks.
+         */
+        class IgniteBindingImpl
+        {
+            typedef void (Callback)(binary::BinaryReaderImpl&, binary::BinaryWriterImpl&);
+
+        public:
+            /**
+             * Default constructor.
+             */
+            IgniteBindingImpl() : callbacks()
+            {
+                // No-op.
+            }
+
+            /**
+             * Invoke callback using provided ID.
+             *
+             * Deserializes data and callback itself, invokes callback and
+             * serializes processing result using providede reader and writer.
+             *
+             * @param id Processor ID.
+             * @param reader Reader.
+             * @param writer Writer.
+             * @return True if callback is registered and false otherwise.
+             */
+            bool InvokeCallbackById(int64_t id, binary::BinaryReaderImpl& reader, binary::BinaryWriterImpl& writer)
+            {
+                common::concurrent::CsLockGuard guard(lock);
+
+                std::map<int64_t, Callback*>::iterator it = callbacks.find(id);
+
+                if (it != callbacks.end())
+                {
+                    Callback* callback = it->second;
+
+                    // We have found callback and does not need lock here anymore.
+                    guard.Reset();
+
+                    callback(reader, writer);
+
+                    return true;
+                }
+
+                return false;
+            }
+
+            /**
+             * Register cache entry processor and associate it with provided ID.
+             *
+             * @throw IgniteError another processor is already associated with
+             *     the given ID.
+             *
+             * @param id Identifier for processor to be associated with.
+             * @param proc Callback.
+             */
+            void RegisterCallback(int64_t id, Callback* proc, IgniteError& err)
+            {
+                common::concurrent::CsLockGuard guard(lock);
+
+                bool inserted = callbacks.insert(std::make_pair(id, proc)).second;
+
+                guard.Reset();
+
+                if (!inserted)
+                {
+                    std::stringstream builder;
+
+                    builder << "Trying to register multiple PRC callbacks with the same ID. [id=" << id << ']';
+
+                    err = IgniteError(IgniteError::IGNITE_ERR_ENTRY_PROCESSOR, builder.str().c_str());
+                }
+            }
+
+        private:
+            IGNITE_NO_COPY_ASSIGNMENT(IgniteBindingImpl);
+
+            /** Registered callbacks. */
+            std::map<int64_t, Callback*> callbacks;
+
+            /** Callback lock. */
+            common::concurrent::CriticalSection lock;
+        };
+    }
+}
+
+#endif //_IGNITE_IMPL_IGNITE_BINDING_IMPL

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/include/ignite/impl/ignite_environment.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/impl/ignite_environment.h b/modules/platforms/cpp/core/include/ignite/impl/ignite_environment.h
index 2b2a117..5fc9a27 100644
--- a/modules/platforms/cpp/core/include/ignite/impl/ignite_environment.h
+++ b/modules/platforms/cpp/core/include/ignite/impl/ignite_environment.h
@@ -21,10 +21,14 @@
 #include <ignite/common/concurrent.h>
 #include <ignite/jni/java.h>
 #include <ignite/jni/utils.h>
+#include <ignite/ignite_binding_context.h>
+#include <ignite/ignite_configuration.h>
 
 #include "ignite/impl/interop/interop_memory.h"
 #include "ignite/impl/binary/binary_type_manager.h"
 #include "ignite/impl/handle_registry.h"
+#include "ignite/impl/module_manager.h"
+#include "ignite/impl/ignite_binding_impl.h"
 
 namespace ignite
 {
@@ -52,9 +56,11 @@ namespace ignite
             enum { DEFAULT_SLOW_PATH_CONTAINERS_CAP = 16 };
 
             /**
-             * Default constructor.
+             * Constructor.
+             *
+             * @param cfg Node configuration.
              */
-            IgniteEnvironment();
+            IgniteEnvironment(const IgniteConfiguration& cfg);
 
             /**
              * Destructor.
@@ -62,6 +68,13 @@ namespace ignite
             ~IgniteEnvironment();
 
             /**
+             * Get node configuration.
+             *
+             * @return Node configuration.
+             */
+            const IgniteConfiguration& GetConfiguration() const;
+
+            /**
              * Populate callback handlers.
              *
              * @param target (current env wrapped into a shared pointer).
@@ -85,6 +98,7 @@ namespace ignite
              * Start callback.
              *
              * @param memPtr Memory pointer.
+             * @param proc Processor instance.
              */
             void OnStartCallback(long long memPtr, jobject proc);
 
@@ -96,6 +110,13 @@ namespace ignite
             void OnContinuousQueryListenerApply(common::concurrent::SharedPointer<interop::InteropMemory>& mem);
 
             /**
+             * Cache Invoke callback.
+             *
+             * @param mem Input-output memory.
+             */
+            void CacheInvokeCallback(common::concurrent::SharedPointer<interop::InteropMemory>& mem);
+
+            /**
              * Get name of Ignite instance.
              *
              * @return Name.
@@ -103,6 +124,13 @@ namespace ignite
             const char* InstanceName() const;
 
             /**
+             * Get processor associated with the instance.
+             *
+             * @return Processor.
+             */
+            void* GetProcessor();
+
+            /**
              * Get JNI context.
              *
              * @return Context.
@@ -158,12 +186,29 @@ namespace ignite
              */
             HandleRegistry& GetHandleRegistry();
 
+            /**
+             * Get binding.
+             *
+             * @return IgniteBinding instance.
+             */
+            IgniteBinding GetBinding() const;
+
+            /**
+             * Get binding context.
+             *
+             * @return Binding context.
+             */
+            IgniteBindingContext GetBindingContext() const;
+
         private:
+            /** Node configuration. */
+            IgniteConfiguration* cfg;
+
             /** Context to access Java. */
             common::concurrent::SharedPointer<jni::java::JniContext> ctx;
 
             /** Startup latch. */
-            common::concurrent::SingleLatch* latch;
+            common::concurrent::SingleLatch latch;
 
             /** Ignite name. */
             char* name;
@@ -171,14 +216,20 @@ namespace ignite
             /** Processor instance. */
             jni::JavaGlobalRef proc;
 
+            /** Handle registry. */
+            HandleRegistry registry;
+
             /** Type manager. */
             binary::BinaryTypeManager* metaMgr;
 
             /** Type updater. */
             binary::BinaryTypeUpdater* metaUpdater;
 
-            /** Handle registry. */
-            HandleRegistry registry;
+            /** Ignite binding */
+            common::concurrent::SharedPointer<IgniteBindingImpl> binding;
+
+            /** Module manager. */
+            common::concurrent::SharedPointer<ModuleManager> moduleMgr;
 
             IGNITE_NO_COPY_ASSIGNMENT(IgniteEnvironment);
         };

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h b/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h
index aa4059e..776678d 100644
--- a/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h
+++ b/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h
@@ -24,6 +24,7 @@
 
 #include "ignite/impl/cache/cache_impl.h"
 #include "ignite/impl/transactions/transactions_impl.h"
+#include "ignite/impl/cluster/cluster_group_impl.h"
 #include "ignite/impl/ignite_environment.h"
 
 namespace ignite 
@@ -35,8 +36,9 @@ namespace ignite
          */
         class IGNITE_FRIEND_EXPORT IgniteImpl
         {
-            typedef ignite::common::concurrent::SharedPointer<IgniteEnvironment> SP_IgniteEnvironment;
-            typedef ignite::common::concurrent::SharedPointer<impl::transactions::TransactionsImpl> SP_TransactionsImpl;
+            typedef common::concurrent::SharedPointer<IgniteEnvironment> SP_IgniteEnvironment;
+            typedef common::concurrent::SharedPointer<transactions::TransactionsImpl> SP_TransactionsImpl;
+            typedef common::concurrent::SharedPointer<cluster::ClusterGroupImpl> SP_ClusterGroupImpl;
         public:
             /**
              * Constructor used to create new instance.
@@ -54,11 +56,18 @@ namespace ignite
             /**
              * Get name of the Ignite.
              *
-             * @param Name.
+             * @return Name.
              */
             const char* GetName() const;
 
             /**
+             * Get node configuration.
+             *
+             * @return Node configuration.
+             */
+            const IgniteConfiguration& GetConfiguration() const;
+
+            /**
              * Get JNI context associated with this instance.
              *
              * @return JNI context for this instance.
@@ -80,7 +89,7 @@ namespace ignite
 
                 if (!cacheJavaRef)
                 {
-                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err);
+                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
 
                     return NULL;
                 }
@@ -105,7 +114,7 @@ namespace ignite
 
                 if (!cacheJavaRef)
                 {
-                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err);
+                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
 
                     return NULL;
                 }
@@ -130,7 +139,7 @@ namespace ignite
 
                 if (!cacheJavaRef)
                 {
-                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err);
+                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
 
                     return NULL;
                 }
@@ -141,6 +150,13 @@ namespace ignite
             }
 
             /**
+             * Get ignite binding.
+             *
+             * @return IgniteBinding class instance.
+             */
+            IgniteBinding GetBinding();
+
+            /**
              * Get instance of the implementation from the proxy class.
              * Internal method. Should not be used by user.
              *
@@ -158,11 +174,21 @@ namespace ignite
              *
              * @return TransactionsImpl instance.
              */
-            SP_TransactionsImpl GetTransactions()
+            SP_TransactionsImpl GetTransactions() const
             {
                 return txImpl;
             }
 
+            /**
+             * Get projection.
+             *
+             * @return ClusterGroupImpl instance.
+             */
+            SP_ClusterGroupImpl GetProjection() const
+            {
+                return prjImpl;
+            }
+
         private:
             /**
              * Get transactions internal call.
@@ -171,6 +197,13 @@ namespace ignite
              */
             SP_TransactionsImpl InternalGetTransactions(IgniteError &err);
 
+            /**
+             * Get current projection internal call.
+             *
+             * @return ClusterGroupImpl instance.
+             */
+            SP_ClusterGroupImpl InternalGetProjection(IgniteError &err);
+
             /** Environment. */
             SP_IgniteEnvironment env;
 
@@ -180,6 +213,9 @@ namespace ignite
             /** Transactions implementaion. */
             SP_TransactionsImpl txImpl;
 
+            /** Projection implementation. */
+            SP_ClusterGroupImpl prjImpl;
+
             IGNITE_NO_COPY_ASSIGNMENT(IgniteImpl)
         };
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h b/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h
index 432d2ac..a7a3094 100644
--- a/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h
+++ b/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h
@@ -54,7 +54,7 @@ namespace ignite
                  * @param err Error.
                  * @return Result.
                  */
-                bool OutOp(int32_t opType, InputOperation& inOp, IgniteError* err);
+                bool OutOp(int32_t opType, InputOperation& inOp, IgniteError& err);
 
                 /**
                  * Internal out operation.
@@ -63,17 +63,26 @@ namespace ignite
                  * @param err Error.
                  * @return Result.
                  */
-                bool OutOp(int32_t opType, IgniteError* err);
+                bool OutOp(int32_t opType, IgniteError& err);
 
                 /**
-                 * Internal out operation.
+                 * Internal in operation.
                  *
                  * @param opType Operation type.
-                 * @param inOp Input.
+                 * @param outOp Output.
                  * @param err Error.
                  * @return Result.
                  */
-                bool InOp(int32_t opType, OutputOperation& outOp, IgniteError* err);
+                bool InOp(int32_t opType, OutputOperation& outOp, IgniteError& err);
+
+                /**
+                 * Internal in Object operation.
+                 *
+                 * @param opType Operation type.
+                 * @param err Error.
+                 * @return Object.
+                 */
+                jobject InOpObject(int32_t opType, IgniteError& err);
 
                 /**
                  * Internal out-in operation.
@@ -84,7 +93,7 @@ namespace ignite
                  * @param outOp Output.
                  * @param err Error.
                  */
-                void OutInOp(int32_t opType, InputOperation& inOp, OutputOperation& outOp, IgniteError* err);
+                void OutInOp(int32_t opType, InputOperation& inOp, OutputOperation& outOp, IgniteError& err);
 
                 /**
                  * Internal out-in operation.
@@ -95,7 +104,7 @@ namespace ignite
                  * @param outOp Output.
                  * @param err Error.
                  */
-                void OutInOpX(int32_t opType, InputOperation& inOp, OutputOperation& outOp, IgniteError* err);
+                void OutInOpX(int32_t opType, InputOperation& inOp, OutputOperation& outOp, IgniteError& err);
 
                 /**
                 * Internal out-in operation.
@@ -104,7 +113,7 @@ namespace ignite
                 * @param val Value.
                 * @param err Error.
                 */
-                int64_t OutInOpLong(int32_t opType, int64_t val, IgniteError* err);
+                int64_t OutInOpLong(int32_t opType, int64_t val, IgniteError& err);
 
                 /**
                  * Get environment shared pointer.
@@ -154,7 +163,7 @@ namespace ignite
                  * @param err Error.
                  * @return Memory pointer.
                  */
-                int64_t WriteTo(interop::InteropMemory* mem, InputOperation& inOp, IgniteError* err);
+                int64_t WriteTo(interop::InteropMemory* mem, InputOperation& inOp, IgniteError& err);
 
                 /**
                  * Read data from memory.
@@ -163,9 +172,17 @@ namespace ignite
                  * @param outOp Output operation.
                  */
                 void ReadFrom(interop::InteropMemory* mem, OutputOperation& outOp);
+
+                /**
+                 * Read error data from memory.
+                 *
+                 * @param mem Memory.
+                 * @param err Error.
+                 */
+                void ReadError(interop::InteropMemory* mem, IgniteError& err);
             };
         }
     }    
 }
 
-#endif //_IGNITE_IMPL_INTEROP_INTEROP_TARGET
\ No newline at end of file
+#endif //_IGNITE_IMPL_INTEROP_INTEROP_TARGET

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/include/ignite/impl/module_manager.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/impl/module_manager.h b/modules/platforms/cpp/core/include/ignite/impl/module_manager.h
new file mode 100644
index 0000000..55e6943
--- /dev/null
+++ b/modules/platforms/cpp/core/include/ignite/impl/module_manager.h
@@ -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.
+ */
+
+#ifndef _IGNITE_IMPL_MODULE_MANAGER
+#define _IGNITE_IMPL_MODULE_MANAGER
+
+#include <vector>
+
+#include <ignite/common/common.h>
+#include <ignite/common/dynamic_load_os.h>
+#include <ignite/ignite_binding_context.h>
+
+/**
+ * @def IGNITE_CACHE_ENTRY_PROCESSOR_INVOKER_NAME
+ * Function name in which user Invoke callbacks are registred.
+ */
+#define IGNITE_MODULE_INIT_CALLBACK_NAME "IgniteModuleInit"
+
+#define IGNITE_EXPORTED_CALL \
+    extern "C" IGNITE_IMPORT_EXPORT
+
+namespace ignite
+{
+    namespace impl
+    {
+        /**
+         * Module manager.
+         * Provides methods to manipulate loadable modules.
+         */
+        class ModuleManager
+        {
+            typedef common::dynamic::Module Module;
+            typedef void (ModuleInitCallback)(IgniteBindingContext&);
+
+        public:
+            /**
+             * Constructor.
+             *
+             * @param context Ignite binding context.
+             */
+            ModuleManager(const IgniteBindingContext& context) :
+                loadedModules(),
+                bindingContext(context)
+            {
+                // No-op.
+            }
+
+            /**
+             * Destructor.
+             */
+            ~ModuleManager()
+            {
+                for (std::vector<Module>::iterator it = loadedModules.begin(); it != loadedModules.end(); ++it)
+                    it->Unload();
+            }
+
+            /**
+             * Load module.
+             *
+             * @param path Module path.
+             * @param err Error.
+             */
+            void LoadModule(const std::string& path, IgniteError& err)
+            {
+                common::dynamic::Module module = common::dynamic::LoadModule(path);
+
+                if (!module.IsLoaded())
+                {
+                    err = IgniteError(IgniteError::IGNITE_ERR_GENERIC,
+                        ("Can not load module [path=" + path + ']').c_str());
+
+                    return;
+                }
+
+                RegisterModule(module);
+            }
+
+            /**
+             * Register module in ModuleManager.
+             *
+             * @param module Module to register.
+             */
+            void RegisterModule(Module& module)
+            {
+                loadedModules.push_back(module);
+
+                ModuleInitCallback* callback = GetModuleInitCallback(module);
+
+                if (callback)
+                    callback(bindingContext);
+            }
+
+        private:
+            IGNITE_NO_COPY_ASSIGNMENT(ModuleManager);
+
+            /**
+             * Get callback that inits Ignite module.
+             *
+             * @param module Module for which callback should be retrieved.
+             * @return Callback if found and null-pointer otherwise.
+             */
+            static ModuleInitCallback* GetModuleInitCallback(Module& module)
+            {
+                return reinterpret_cast<ModuleInitCallback*>(
+                    module.FindSymbol(IGNITE_MODULE_INIT_CALLBACK_NAME));
+            }
+
+            /** Collection of loaded modules. */
+            std::vector<Module> loadedModules;
+
+            /** Ignite environment. */
+            IgniteBindingContext bindingContext;
+        };
+    }
+}
+
+#endif //_IGNITE_IMPL_MODULE_MANAGER

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/include/ignite/impl/operations.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/impl/operations.h b/modules/platforms/cpp/core/include/ignite/impl/operations.h
index 177529d..dfaa4e8 100644
--- a/modules/platforms/cpp/core/include/ignite/impl/operations.h
+++ b/modules/platforms/cpp/core/include/ignite/impl/operations.h
@@ -68,18 +68,18 @@ namespace ignite
              * 
              * @param val Value.
              */
-            In1Operation(const T* val) : val(val)
+            In1Operation(const T& val) : val(val)
             {
                 // No-op.
             }
 
             virtual void ProcessInput(ignite::impl::binary::BinaryWriterImpl& writer)
             {
-                writer.WriteTopObject<T>(*val);
+                writer.WriteTopObject<T>(val);
             }
         private:
             /** Value. */
-            const T* val; 
+            const T val;
 
             IGNITE_NO_COPY_ASSIGNMENT(In1Operation)
         };
@@ -97,22 +97,22 @@ namespace ignite
              * @param val1 First value.
              * @param val2 Second value.
              */
-            In2Operation(const T1* val1, const T2* val2) : val1(val1), val2(val2)
+            In2Operation(const T1& val1, const T2& val2) : val1(val1), val2(val2)
             {
                 // No-op.
             }
 
             virtual void ProcessInput(ignite::impl::binary::BinaryWriterImpl& writer)
             {
-                writer.WriteTopObject<T1>(*val1);
-                writer.WriteTopObject<T2>(*val2);
+                writer.WriteTopObject<T1>(val1);
+                writer.WriteTopObject<T2>(val2);
             }
         private:
             /** First value. */
-            const T1* val1; 
+            const T1& val1;
 
             /** Second value. */
-            const T2* val2; 
+            const T2& val2;
 
             IGNITE_NO_COPY_ASSIGNMENT(In2Operation)
         };
@@ -131,26 +131,26 @@ namespace ignite
              * @param val2 Second value.
              * @param val3 Third value.
              */
-            In3Operation(const T1* val1, const T2* val2, const T3* val3) : val1(val1), val2(val2), val3(val3)
+            In3Operation(const T1& val1, const T2& val2, const T3& val3) : val1(val1), val2(val2), val3(val3)
             {
                 // No-op.
             }
 
             virtual void ProcessInput(ignite::impl::binary::BinaryWriterImpl& writer)
             {
-                writer.WriteTopObject<T1>(*val1);
-                writer.WriteTopObject<T2>(*val2);
-                writer.WriteTopObject<T3>(*val3);
+                writer.WriteTopObject<T1>(val1);
+                writer.WriteTopObject<T2>(val2);
+                writer.WriteTopObject<T3>(val3);
             }
         private:
             /** First value. */
-            const T1* val1;
+            const T1& val1;
 
             /** Second value. */
-            const T2* val2;
+            const T2& val2;
 
             /** Third value. */
-            const T3* val3;
+            const T3& val3;
 
             IGNITE_NO_COPY_ASSIGNMENT(In3Operation)
         };
@@ -167,21 +167,21 @@ namespace ignite
              *
              * @param val Value.
              */
-            InSetOperation(const std::set<T>* val) : val(val)
+            InSetOperation(const std::set<T>& val) : val(val)
             {
                 // No-op.
             }
 
             virtual void ProcessInput(ignite::impl::binary::BinaryWriterImpl& writer)
             {
-                writer.GetStream()->WriteInt32(static_cast<int32_t>(val->size()));
+                writer.GetStream()->WriteInt32(static_cast<int32_t>(val.size()));
 
-                for (typename std::set<T>::const_iterator it = val->begin(); it != val->end(); ++it)
+                for (typename std::set<T>::const_iterator it = val.begin(); it != val.end(); ++it)
                     writer.WriteTopObject<T>(*it);
             }
         private:
             /** Value. */
-            const std::set<T>* val; 
+            const std::set<T>& val;
 
             IGNITE_NO_COPY_ASSIGNMENT(InSetOperation)
         };
@@ -198,23 +198,23 @@ namespace ignite
              *
              * @param val Value.
              */
-            InMapOperation(const std::map<K, V>* val) : val(val)
+            InMapOperation(const std::map<K, V>& val) : val(val)
             {
                 // No-op.
             }
 
             virtual void ProcessInput(ignite::impl::binary::BinaryWriterImpl& writer)
             {
-                writer.GetStream()->WriteInt32(static_cast<int32_t>(val->size()));
+                writer.GetStream()->WriteInt32(static_cast<int32_t>(val.size()));
 
-                for (typename std::map<K, V>::const_iterator it = val->begin(); it != val->end(); ++it) {
+                for (typename std::map<K, V>::const_iterator it = val.begin(); it != val.end(); ++it) {
                     writer.WriteTopObject<K>(it->first);
                     writer.WriteTopObject<V>(it->second);
                 }
             }
         private:
             /** Value. */
-            const std::map<K, V>* val; 
+            const std::map<K, V>& val;
 
             IGNITE_NO_COPY_ASSIGNMENT(InMapOperation)
         };
@@ -232,19 +232,19 @@ namespace ignite
              * @param key Key.
              * @param peekModes Peek modes.
              */
-            InCacheLocalPeekOperation(const T* key, int32_t peekModes) : key(key), peekModes(peekModes)
+            InCacheLocalPeekOperation(const T& key, int32_t peekModes) : key(key), peekModes(peekModes)
             {
                 // No-op.
             }
 
             virtual void ProcessInput(ignite::impl::binary::BinaryWriterImpl& writer)
             {
-                writer.WriteTopObject<T>(*key);
+                writer.WriteTopObject<T>(key);
                 writer.GetStream()->WriteInt32(peekModes);
             }
         private:
             /** Key. */
-            const T* key;   
+            const T& key;
 
             /** Peek modes. */
             int32_t peekModes; 
@@ -531,7 +531,7 @@ namespace ignite
             /**
              * Constructor.
              */
-            OutQueryGetAllOperation(std::vector<ignite::cache::CacheEntry<K, V> >* res) : res(res)
+            OutQueryGetAllOperation(std::vector<ignite::cache::CacheEntry<K, V> >& res) : res(res)
             {
                 // No-op.
             }
@@ -545,22 +545,22 @@ namespace ignite
                     K key = reader.ReadTopObject<K>();
                     V val = reader.ReadTopObject<V>();
 
-                    res->push_back(ignite::cache::CacheEntry<K, V>(key, val));
+                    res.push_back(ignite::cache::CacheEntry<K, V>(key, val));
                 }
             }
 
             virtual void SetNull()
             {
-                res->clear();
+                res.clear();
             }
 
         private:
             /** Entries. */
-            std::vector<ignite::cache::CacheEntry<K, V> >* res;
+            std::vector<ignite::cache::CacheEntry<K, V> >& res;
             
             IGNITE_NO_COPY_ASSIGNMENT(OutQueryGetAllOperation)
         };
     }
 }
 
-#endif //_IGNITE_IMPL_OPERATIONS
\ No newline at end of file
+#endif //_IGNITE_IMPL_OPERATIONS

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/project/vs/core.vcxproj
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/project/vs/core.vcxproj b/modules/platforms/cpp/core/project/vs/core.vcxproj
index 89a2dff..9a5a80b 100644
--- a/modules/platforms/cpp/core/project/vs/core.vcxproj
+++ b/modules/platforms/cpp/core/project/vs/core.vcxproj
@@ -192,11 +192,13 @@
   <ItemGroup>
     <ClInclude Include="..\..\include\ignite\cache\cache.h" />
     <ClInclude Include="..\..\include\ignite\cache\cache_entry.h" />
+    <ClInclude Include="..\..\include\ignite\cache\cache_entry_processor.h" />
     <ClInclude Include="..\..\include\ignite\cache\cache_peek_mode.h" />
     <ClInclude Include="..\..\include\ignite\cache\event\cache_entry_event.h" />
     <ClInclude Include="..\..\include\ignite\cache\event\cache_entry_event_listener.h" />
     <ClInclude Include="..\..\include\ignite\cache\query\continuous\continuous_query.h" />
     <ClInclude Include="..\..\include\ignite\cache\query\continuous\continuous_query_handle.h" />
+    <ClInclude Include="..\..\include\ignite\cache\mutable_cache_entry.h" />
     <ClInclude Include="..\..\include\ignite\cache\query\query.h" />
     <ClInclude Include="..\..\include\ignite\cache\query\query_argument.h" />
     <ClInclude Include="..\..\include\ignite\cache\query\query_cursor.h" />
@@ -206,24 +208,30 @@
     <ClInclude Include="..\..\include\ignite\cache\query\query_sql.h" />
     <ClInclude Include="..\..\include\ignite\cache\query\query_sql_fields.h" />
     <ClInclude Include="..\..\include\ignite\cache\query\query_text.h" />
+    <ClInclude Include="..\..\include\ignite\ignite_binding_context.h" />
     <ClInclude Include="..\..\include\ignite\ignite.h" />
     <ClInclude Include="..\..\include\ignite\ignite_configuration.h" />
     <ClInclude Include="..\..\include\ignite\ignition.h" />
     <ClInclude Include="..\..\include\ignite\impl\binary\binary_type_updater_impl.h" />
+    <ClInclude Include="..\..\include\ignite\impl\cache\cache_entry_processor_holder.h" />
     <ClInclude Include="..\..\include\ignite\impl\cache\cache_impl.h" />
     <ClInclude Include="..\..\include\ignite\impl\cache\query\query_batch.h" />
     <ClInclude Include="..\..\include\ignite\impl\cache\query\continuous\continuous_query_handle_impl.h" />
     <ClInclude Include="..\..\include\ignite\impl\cache\query\continuous\continuous_query_impl.h" />
     <ClInclude Include="..\..\include\ignite\impl\cache\query\query_fields_row_impl.h" />
     <ClInclude Include="..\..\include\ignite\impl\cache\query\query_impl.h" />
+    <ClInclude Include="..\..\include\ignite\impl\cluster\cluster_group_impl.h" />
     <ClInclude Include="..\..\include\ignite\impl\ignite_environment.h" />
     <ClInclude Include="..\..\include\ignite\impl\ignite_impl.h" />
     <ClInclude Include="..\..\include\ignite\impl\handle_registry.h" />
     <ClInclude Include="..\..\include\ignite\impl\interop\interop_external_memory.h" />
     <ClInclude Include="..\..\include\ignite\impl\interop\interop_target.h" />
+    <ClInclude Include="..\..\include\ignite\impl\ignite_binding_impl.h" />
+    <ClInclude Include="..\..\include\ignite\impl\module_manager.h" />
     <ClInclude Include="..\..\include\ignite\impl\operations.h" />
     <ClInclude Include="..\..\include\ignite\impl\transactions\transactions_impl.h" />
     <ClInclude Include="..\..\include\ignite\impl\transactions\transaction_impl.h" />
+    <ClInclude Include="..\..\include\ignite\ignite_binding.h" />
     <ClInclude Include="..\..\include\ignite\transactions\transaction.h" />
     <ClInclude Include="..\..\include\ignite\transactions\transactions.h" />
     <ClInclude Include="..\..\include\ignite\transactions\transaction_consts.h" />
@@ -237,6 +245,7 @@
     <ClCompile Include="..\..\src\impl\cache\query\query_batch.cpp" />
     <ClCompile Include="..\..\src\impl\cache\query\continuous\continuous_query_handle_impl.cpp" />
     <ClCompile Include="..\..\src\impl\cache\query\query_impl.cpp" />
+    <ClCompile Include="..\..\src\impl\cluster\cluster_group_impl.cpp" />
     <ClCompile Include="..\..\src\impl\ignite_environment.cpp" />
     <ClCompile Include="..\..\src\impl\ignite_impl.cpp" />
     <ClCompile Include="..\..\src\impl\handle_registry.cpp" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/project/vs/core.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/project/vs/core.vcxproj.filters b/modules/platforms/cpp/core/project/vs/core.vcxproj.filters
index 9cb5f78..fc58633 100644
--- a/modules/platforms/cpp/core/project/vs/core.vcxproj.filters
+++ b/modules/platforms/cpp/core/project/vs/core.vcxproj.filters
@@ -49,6 +49,9 @@
     <ClCompile Include="..\..\src\impl\cache\query\continuous\continuous_query_handle_impl.cpp">
       <Filter>Code\impl\cache\query\continuous</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\impl\cluster\cluster_group_impl.cpp">
+      <Filter>Code\impl\cluster</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\ignite\impl\cache\cache_impl.h">
@@ -165,6 +168,30 @@
     <ClInclude Include="..\..\include\ignite\impl\cache\query\continuous\continuous_query_impl.h">
       <Filter>Code\impl\cache\query\continuous</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\ignite\cache\mutable_cache_entry.h">
+      <Filter>Code\cache</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\impl\cache\cache_entry_processor_holder.h">
+      <Filter>Code\impl\cache</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\impl\module_manager.h">
+      <Filter>Code\impl</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\impl\cluster\cluster_group_impl.h">
+      <Filter>Code\impl\cluster</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\cache\cache_entry_processor.h">
+      <Filter>Code\cache</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\ignite_binding.h">
+      <Filter>Code</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\impl\ignite_binding_impl.h">
+      <Filter>Code\impl</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\ignite\ignite_binding_context.h">
+      <Filter>Code</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Filter Include="Code">
@@ -206,5 +233,8 @@
     <Filter Include="Code\cache\event">
       <UniqueIdentifier>{e03c3690-ff22-4c78-83a0-b77cebb7f980}</UniqueIdentifier>
     </Filter>
+    <Filter Include="Code\impl\cluster">
+      <UniqueIdentifier>{f5b54635-91a1-447e-923a-1b4608d7e5bc}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
 </Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/src/ignite.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/ignite.cpp b/modules/platforms/cpp/core/src/ignite.cpp
index c546ea5..2665916 100644
--- a/modules/platforms/cpp/core/src/ignite.cpp
+++ b/modules/platforms/cpp/core/src/ignite.cpp
@@ -24,7 +24,7 @@ using namespace ignite::common::concurrent;
 using namespace ignite::impl;
 
 namespace ignite
-{    
+{
     Ignite::Ignite() : impl(SharedPointer<IgniteImpl>())
     {
         // No-op.
@@ -40,6 +40,11 @@ namespace ignite
         return impl.Get()->GetName();
     }
 
+    const IgniteConfiguration& Ignite::GetConfiguration() const
+    {
+        return impl.Get()->GetConfiguration();
+    }
+
     transactions::Transactions Ignite::GetTransactions()
     {
         using ignite::common::concurrent::SharedPointer;
@@ -49,5 +54,10 @@ namespace ignite
 
         return transactions::Transactions(txImpl);
     }
+
+    IgniteBinding Ignite::GetBinding()
+    {
+        return impl.Get()->GetBinding();
+    }
 }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/src/ignition.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/ignition.cpp b/modules/platforms/cpp/core/src/ignition.cpp
index cd7ad70..6a00eab 100644
--- a/modules/platforms/cpp/core/src/ignition.cpp
+++ b/modules/platforms/cpp/core/src/ignition.cpp
@@ -16,6 +16,7 @@
  */
 
 #include <sstream>
+#include <memory>
 
 #include <ignite/common/common.h>
 #include <ignite/common/concurrent.h>
@@ -56,71 +57,134 @@ namespace ignite
     std::string JvmMemoryString(const std::string& prefix, int32_t val)
     {
         std::ostringstream ss;
-        ss << val;
 
-        std::string valStr = ss.str();
+        ss << prefix << val << 'm';
 
-        std::string res = std::string(prefix);
-        res.append(valStr);
-        res.append("m");
-
-        return res;
+        return ss.str();
     }
 
     /**
-     * Create JVM options.
+     * JVM options
      *
-     * @param cfg Configuration.
-     * @param home Optional GG home.
-     * @param cp Classpath.
-     * @param opts Options.
-     * @param optsLen Options length.
-     * @return Options.
+     * Used to build JVM options in a exception-safe way.
      */
-    char** CreateJvmOptions(const IgniteConfiguration& cfg, const std::string* home, const std::string& cp, int* optsLen)
+    class JvmOptions
     {
-        *optsLen = 3 + (home ? 1 : 0) + static_cast<int>(cfg.jvmOpts.size());
-        char** opts = new char*[*optsLen];
+    public:
+        /**
+         * Constructor.
+         */
+        JvmOptions() :
+            size(0),
+            opts(0)
+        {
+            // No-op.
+        }
+
+        /**
+         * Destructor.
+         */
+        ~JvmOptions()
+        {
+            Deinit();
+        }
+
+        /**
+         * Create JVM options from configuration.
+         *
+         * @param cfg Configuration.
+         * @param home Optional GG home.
+         * @param cp Classpath.
+         */
+        void FromConfiguration(const IgniteConfiguration& cfg, const std::string& home, const std::string& cp)
+        {
+            Deinit();
 
-        int idx = 0;
+            size = 3 + static_cast<int>(cfg.jvmOpts.size());
 
-        // 1. Set classpath.
-        std::string cpFull = std::string("-Djava.class.path=") + cp;
+            if (!home.empty())
+                ++size;
 
-        *(opts + idx++) = CopyChars(cpFull.c_str());
+            // Brackets '()' here guarantee for the array to be zeroed.
+            // Important to avoid crash in case of exception.
+            opts = new char*[size]();
 
-        // 2. Set home.
-        if (home) {
-            std::string homeFull = std::string("-DIGNITE_HOME=") + *home;
+            int idx = 0;
 
-            *(opts + idx++) = CopyChars(homeFull.c_str());
+            // 1. Set classpath.
+            std::string cpFull = "-Djava.class.path=" + cp;
+
+            opts[idx++] = CopyChars(cpFull.c_str());
+
+            // 2. Set home.
+            if (!home.empty()) {
+                std::string homeFull = "-DIGNITE_HOME=" + home;
+
+                opts[idx++] = CopyChars(homeFull.c_str());
+            }
+
+            // 3. Set Xms, Xmx.
+            std::string xmsStr = JvmMemoryString("-Xms", cfg.jvmInitMem);
+            std::string xmxStr = JvmMemoryString("-Xmx", cfg.jvmMaxMem);
+
+            opts[idx++] = CopyChars(xmsStr.c_str());
+            opts[idx++] = CopyChars(xmxStr.c_str());
+
+            // 4. Set the rest options.
+            for (std::list<std::string>::const_iterator i = cfg.jvmOpts.begin(); i != cfg.jvmOpts.end(); ++i)
+                opts[idx++] = CopyChars(i->c_str());
         }
 
-        // 3. Set Xms, Xmx.
-        std::string xmsStr = JvmMemoryString(std::string("-Xms"), cfg.jvmInitMem);
-        std::string xmxStr = JvmMemoryString(std::string("-Xmx"), cfg.jvmMaxMem);
+        /**
+         * Deallocates all allocated data.
+         */
+        void Deinit()
+        {
+            if (opts)
+            {
+                for (int i = 0; i < size; ++i)
+                    ReleaseChars(opts[i]);
 
-        *(opts + idx++) = CopyChars(xmsStr.c_str());
-        *(opts + idx++) = CopyChars(xmxStr.c_str());
+                delete[] opts;
+            }
+        }
 
-        // 4. Set the rest options.
-        for (std::list<std::string>::const_iterator i = cfg.jvmOpts.begin(); i != cfg.jvmOpts.end(); ++i) {
-            char* optCopy = CopyChars(i->c_str());
+        /**
+         * Get built options.
+         *
+         * @return Built options
+         */
+        char** GetOpts() const
+        {
+            return opts;
+        }
 
-            opts[idx++] = optCopy;
+        /**
+         * Get options number.
+         *
+         * @return Options number.
+         */
+        int GetSize() const
+        {
+            return size;
         }
 
-        return opts;
-    }
+    private:
+        /** Size */
+        int size;
+
+        /** Options array. */
+        char** opts;
+    };
 
     Ignite Ignition::Start(const IgniteConfiguration& cfg)
     {
-        return Start(cfg, static_cast<const char*>(NULL));
+        return Start(cfg, static_cast<const char*>(0));
     }
 
     Ignite Ignition::Start(const IgniteConfiguration& cfg, IgniteError* err)
     {
-        return Start(cfg, NULL, err);
+        return Start(cfg, 0, err);
     }
 
     Ignite Ignition::Start(const IgniteConfiguration& cfg, const char* name)
@@ -136,153 +200,126 @@ namespace ignite
 
     Ignite Ignition::Start(const IgniteConfiguration& cfg, const char* name, IgniteError* err)
     {
-        bool failed = false;
+        CsLockGuard guard(factoryLock);
 
-        SharedPointer<IgniteEnvironment> env;
-        SharedPointer<IgniteEnvironment>* envTarget = NULL;
-
-        jobject javaRef = NULL;
-
-        factoryLock.Enter();
+        std::string jvmLib = FindJvmLibrary(cfg.jvmLibPath);
 
         // 1. Load JVM library if needed.
         if (!JVM_LIB_LOADED)
         {
-            bool jvmLibFound;
-            std::string jvmLib;
-
-            if (!cfg.jvmLibPath.empty())
-            {
-                std::string jvmLibPath = std::string(cfg.jvmLibPath);
-
-                jvmLib = FindJvmLibrary(&jvmLibPath, &jvmLibFound);
-            }
-            else
-                jvmLib = FindJvmLibrary(NULL, &jvmLibFound);
-
-            if (!jvmLibFound)
+            if (jvmLib.empty())
             {
                 *err = IgniteError(IgniteError::IGNITE_ERR_JVM_LIB_NOT_FOUND,
                     "JVM library is not found (did you set JAVA_HOME environment variable?)");
 
-                failed = true;
+                return Ignite();
             }
 
-            if (!failed) {
-                if (!LoadJvmLibrary(jvmLib))
-                {
-                    *err = IgniteError(IgniteError::IGNITE_ERR_JVM_LIB_LOAD_FAILED, "Failed to load JVM library.");
+            if (!LoadJvmLibrary(jvmLib))
+            {
+                *err = IgniteError(IgniteError::IGNITE_ERR_JVM_LIB_LOAD_FAILED, "Failed to load JVM library.");
 
-                    failed = true;
-                }
+                return Ignite();
             }
 
             JVM_LIB_LOADED = true;
         }
 
-        if (!failed)
-        {
-            // 2. Resolve IGNITE_HOME.
-            bool homeFound;
-            std::string home;
+        // 2. Resolve IGNITE_HOME.
+        std::string home;
+        bool homeFound = ResolveIgniteHome(cfg.igniteHome, home);
 
-            if (!cfg.igniteHome.empty())
-            {
-                std::string homePath = std::string(cfg.igniteHome);
+        // 3. Create classpath.
+        std::string cp;
 
-                home = ResolveIgniteHome(&homePath, &homeFound);
-            }
-            else
-                home = ResolveIgniteHome(NULL, &homeFound);
+        if (homeFound)
+            cp = CreateIgniteClasspath(cfg.jvmClassPath, home);
+        else
+            cp = CreateIgniteClasspath(cfg.jvmClassPath);
 
-            // 3. Create classpath.
-            std::string cp;
+        if (cp.empty())
+        {
+            *err = IgniteError(IgniteError::IGNITE_ERR_JVM_NO_CLASSPATH,
+                "Java classpath is empty (did you set IGNITE_HOME environment variable?)");
 
-            if (!cfg.jvmClassPath.empty())
-            {
-                std::string usrCp = cfg.jvmClassPath;
+            return Ignite();
+        }
 
-                cp = CreateIgniteClasspath(&usrCp, homeFound ? &home : NULL);
-            }
-            else
-                cp = CreateIgniteClasspath(NULL, homeFound ? &home : NULL);
+        // 4. Resolving spring config path
+        std::string springCfgPath0;
 
-            if (!cp.empty())
-            {
-                // 4. Start JVM if needed.
-                JniErrorInfo jniErr;
+        if (!cfg.springCfgPath.empty())
+            springCfgPath0 = cfg.springCfgPath;
+        else
+            springCfgPath0 = DFLT_CFG;
 
-                env = SharedPointer<IgniteEnvironment>(new IgniteEnvironment());
+        // 5. Start JVM if needed.
+        IgniteConfiguration cfg0(cfg);
 
-                int optsLen;
-                char** opts = CreateJvmOptions(cfg, homeFound ? &home : NULL, cp, &optsLen);
+        cfg0.jvmLibPath = jvmLib;
+        cfg0.igniteHome = home;
+        cfg0.jvmClassPath = cp;
+        cfg0.springCfgPath = springCfgPath0;
 
-                envTarget = new SharedPointer<IgniteEnvironment>(env);
+        JniErrorInfo jniErr;
 
-                SharedPointer<JniContext> ctx(
-                    JniContext::Create(opts, optsLen, env.Get()->GetJniHandlers(envTarget), &jniErr));
+        SharedPointer<IgniteEnvironment> env = SharedPointer<IgniteEnvironment>(new IgniteEnvironment(cfg0));
 
-                for (int i = 0; i < optsLen; i++)
-                    ReleaseChars(*(opts + i));
+        JvmOptions opts;
+        opts.FromConfiguration(cfg, home, cp);
 
-                delete[] opts;
+        std::auto_ptr< SharedPointer<IgniteEnvironment> > envTarget(new SharedPointer<IgniteEnvironment>(env));
 
-                if (!ctx.Get())
-                {
-                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
+        SharedPointer<JniContext> ctx(
+            JniContext::Create(opts.GetOpts(), opts.GetSize(), env.Get()->GetJniHandlers(envTarget.get()), &jniErr));
 
-                    failed = true;
-                }
+        if (!ctx.Get())
+        {
+            IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, *err);
 
-                env.Get()->SetContext(ctx);
+            return Ignite();
+        }
 
-                // 5. Start Ignite.
-                if (!failed)
-                {
-                    char* springCfgPath0 = NULL;
+        env.Get()->SetContext(ctx);
 
-                    if (!cfg.springCfgPath.empty())
-                        springCfgPath0 = CopyChars(cfg.springCfgPath.c_str());
-                    else
-                        springCfgPath0 = CopyChars(DFLT_CFG);
+        // 6. Start Ignite.
 
-                    char* name0 = CopyChars(name);
+        // Workaround for nullable strings as we can't use unique_ptr nor
+        // can we construct std::string from the null-pointer.
+        char* namep = 0;
 
-                    interop::InteropUnpooledMemory mem(16);
-                    interop::InteropOutputStream stream(&mem);
-                    stream.WriteBool(false);
-                    stream.Synchronize();
+        std::string name0;
+        if (name)
+        {
+            name0 = name;
 
-                    javaRef = ctx.Get()->IgnitionStart(springCfgPath0, name0, 2, mem.PointerLong(), &jniErr);
+            namep = &name0[0];
+        }
 
-                    ReleaseChars(springCfgPath0);
-                    ReleaseChars(name0);
+        interop::InteropUnpooledMemory mem(16);
+        interop::InteropOutputStream stream(&mem);
+        stream.WriteBool(false);
+        stream.Synchronize();
 
-                    if (!javaRef) {
-                        IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
+        jobject javaRef = ctx.Get()->IgnitionStart(&springCfgPath0[0], namep, 2, mem.PointerLong(), &jniErr);
 
-                        failed = true;
-                    }
-                    else {
-                        // 6. Ignite is started at this point.
-                        env.Get()->Initialize();
+        // Releasing control over environment as it is controlled by Java at this point.
+        // Even if the call has failed environment are going to be released by the Java.
+        envTarget.release();
 
-                        started = true;
-                    }
-                }
-            }
-            else {
-                *err = IgniteError(IgniteError::IGNITE_ERR_JVM_NO_CLASSPATH,
-                    "Java classpath is empty (did you set IGNITE_HOME environment variable?)");
+        if (!javaRef)
+        {
+            IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, *err);
 
-                failed = true;
-            }
+            return Ignite();
         }
 
-        factoryLock.Leave();
+        // 7. Ignite is started at this point.
+        env.Get()->Initialize();
 
-        if (failed) 
-            return Ignite();
+        started = true;
+
+        guard.Reset();
 
         env.Get()->ProcessorReleaseStart();
 
@@ -293,12 +330,12 @@ namespace ignite
 
     Ignite Ignition::Get()
     {
-        return Get(static_cast<const char*>(NULL));
+        return Get(static_cast<const char*>(0));
     }
 
     Ignite Ignition::Get(IgniteError* err)
     {
-        return Get(NULL, err);
+        return Get(0, err);
     }
 
     Ignite Ignition::Get(const char* name)
@@ -325,16 +362,16 @@ namespace ignite
             // 1. Create context for this operation.
             JniErrorInfo jniErr;
 
-            SharedPointer<JniContext> ctx(JniContext::Create(NULL, 0, JniHandlers(), &jniErr));
+            SharedPointer<JniContext> ctx(JniContext::Create(0, 0, JniHandlers(), &jniErr));
 
-            IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
+            IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, *err);
 
             if (err->GetCode() == IgniteError::IGNITE_SUCCESS)
             {
                 // 2. Get environment pointer.
                 long long ptr = ctx.Get()->IgnitionEnvironmentPointer(name0, &jniErr);
 
-                IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
+                IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, *err);
 
                 if (err->GetCode() == IgniteError::IGNITE_SUCCESS)
                 {
@@ -384,12 +421,12 @@ namespace ignite
 
     bool Ignition::Stop(bool cancel)
     {
-        return Stop(NULL, cancel);
+        return Stop(0, cancel);
     }
 
     bool Ignition::Stop(bool cancel, IgniteError* err)
     {
-        return Stop(NULL, cancel, err);
+        return Stop(0, cancel, err);
     }
 
     bool Ignition::Stop(const char* name, bool cancel)
@@ -413,9 +450,9 @@ namespace ignite
         {
             JniErrorInfo jniErr;
 
-            SharedPointer<JniContext> ctx(JniContext::Create(NULL, 0, JniHandlers(), &jniErr));
+            SharedPointer<JniContext> ctx(JniContext::Create(0, 0, JniHandlers(), &jniErr));
 
-            IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
+            IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, *err);
 
             if (err->GetCode() == IgniteError::IGNITE_SUCCESS)
             {
@@ -425,7 +462,7 @@ namespace ignite
 
                 ReleaseChars(name0);
 
-                IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
+                IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, *err);
 
                 if (err->GetCode() == IgniteError::IGNITE_SUCCESS)
                     res = res0;
@@ -454,15 +491,15 @@ namespace ignite
         {
             JniErrorInfo jniErr;
 
-            SharedPointer<JniContext> ctx(JniContext::Create(NULL, 0, JniHandlers(), &jniErr));
+            SharedPointer<JniContext> ctx(JniContext::Create(0, 0, JniHandlers(), &jniErr));
 
-            IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
+            IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, *err);
 
             if (err->GetCode() == IgniteError::IGNITE_SUCCESS)
             {
                 ctx.Get()->IgnitionStopAll(cancel, &jniErr);
 
-                IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
+                IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, *err);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp b/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp
index ff6df9e..42d6fd0 100644
--- a/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp
+++ b/modules/platforms/cpp/core/src/impl/binary/binary_type_updater_impl.cpp
@@ -48,7 +48,7 @@ namespace ignite
                 JniContext::Release(javaRef);
             }
 
-            bool BinaryTypeUpdaterImpl::Update(Snap* snap, IgniteError* err)
+            bool BinaryTypeUpdaterImpl::Update(Snap* snap, IgniteError& err)
             {
                 JniErrorInfo jniErr;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/src/impl/cache/cache_impl.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/impl/cache/cache_impl.cpp b/modules/platforms/cpp/core/src/impl/cache/cache_impl.cpp
index 5d09e46..7b98f65 100644
--- a/modules/platforms/cpp/core/src/impl/cache/cache_impl.cpp
+++ b/modules/platforms/cpp/core/src/impl/cache/cache_impl.cpp
@@ -70,6 +70,9 @@ namespace ignite
             /** Operation: GetAndReplace. */
             const int32_t OP_GET_AND_REPLACE = 10;
 
+            /** Operation: Invoke. */
+            const int32_t OP_INVOKE = 12;
+
             /** Operation: LocalEvict. */
             const int32_t OP_LOCAL_EVICT = 16;
 
@@ -152,82 +155,82 @@ namespace ignite
                 return name;
             }
 
-            bool CacheImpl::ContainsKey(InputOperation& inOp, IgniteError* err)
+            bool CacheImpl::ContainsKey(InputOperation& inOp, IgniteError& err)
             {
                 return OutOp(OP_CONTAINS_KEY, inOp, err);
             }
 
-            bool CacheImpl::ContainsKeys(InputOperation& inOp, IgniteError* err)
+            bool CacheImpl::ContainsKeys(InputOperation& inOp, IgniteError& err)
             {
                 return OutOp(OP_CONTAINS_KEYS, inOp, err);
             }
 
-            void CacheImpl::LocalPeek(InputOperation& inOp, OutputOperation& outOp, int32_t peekModes, IgniteError* err)
+            void CacheImpl::LocalPeek(InputOperation& inOp, OutputOperation& outOp, int32_t peekModes, IgniteError& err)
             {
                 OutInOpX(OP_LOCAL_PEEK, inOp, outOp, err);
             }
 
-            void CacheImpl::Get(InputOperation& inOp, OutputOperation& outOp, IgniteError* err)
+            void CacheImpl::Get(InputOperation& inOp, OutputOperation& outOp, IgniteError& err)
             {
                 OutInOpX(OP_GET, inOp, outOp, err);
             }
 
-            void CacheImpl::GetAll(InputOperation& inOp, OutputOperation& outOp, IgniteError* err)
+            void CacheImpl::GetAll(InputOperation& inOp, OutputOperation& outOp, IgniteError& err)
             {
                 OutInOpX(OP_GET_ALL, inOp, outOp, err);
             }
 
-            void CacheImpl::Put(InputOperation& inOp, IgniteError* err)
+            void CacheImpl::Put(InputOperation& inOp, IgniteError& err)
             {
                 OutOp(OP_PUT, inOp, err);
             }
 
-            void CacheImpl::PutAll(ignite::impl::InputOperation& inOp, IgniteError* err)
+            void CacheImpl::PutAll(ignite::impl::InputOperation& inOp, IgniteError& err)
             {
                 OutOp(OP_PUT_ALL, inOp, err);
             }
 
-            void CacheImpl::GetAndPut(InputOperation& inOp, OutputOperation& outOp, IgniteError* err)
+            void CacheImpl::GetAndPut(InputOperation& inOp, OutputOperation& outOp, IgniteError& err)
             {
                 OutInOpX(OP_GET_AND_PUT, inOp, outOp, err);
             }
 
-            void CacheImpl::GetAndReplace(InputOperation& inOp, OutputOperation& outOp, IgniteError* err)
+            void CacheImpl::GetAndReplace(InputOperation& inOp, OutputOperation& outOp, IgniteError& err)
             {
                 OutInOpX(OP_GET_AND_REPLACE, inOp, outOp, err);
             }
 
-            void CacheImpl::GetAndRemove(InputOperation& inOp, OutputOperation& outOp, IgniteError* err)
+            void CacheImpl::GetAndRemove(InputOperation& inOp, OutputOperation& outOp, IgniteError& err)
             {
                 OutInOpX(OP_GET_AND_REMOVE, inOp, outOp, err);
             }
 
-            bool CacheImpl::PutIfAbsent(InputOperation& inOp, IgniteError* err)
+            bool CacheImpl::PutIfAbsent(InputOperation& inOp, IgniteError& err)
             {
                 return OutOp(OP_PUT_IF_ABSENT, inOp, err);
             }
 
-            void CacheImpl::GetAndPutIfAbsent(InputOperation& inOp, OutputOperation& outOp, IgniteError* err)
+            void CacheImpl::GetAndPutIfAbsent(InputOperation& inOp, OutputOperation& outOp, IgniteError& err)
             {
                 OutInOpX(OP_GET_AND_PUT_IF_ABSENT, inOp, outOp, err);
             }
 
-            bool CacheImpl::Replace(InputOperation& inOp, IgniteError* err)
+            bool CacheImpl::Replace(InputOperation& inOp, IgniteError& err)
             {
                 return OutOp(OP_REPLACE_2, inOp, err);
             }
 
-            bool CacheImpl::ReplaceIfEqual(InputOperation& inOp, IgniteError* err)
+            bool CacheImpl::ReplaceIfEqual(InputOperation& inOp, IgniteError& err)
             {
                 return OutOp(OP_REPLACE_3, inOp, err);
             }
 
-            void CacheImpl::LocalEvict(InputOperation& inOp, IgniteError* err)
+            void CacheImpl::LocalEvict(InputOperation& inOp, IgniteError& err)
             {
                 OutOp(OP_LOCAL_EVICT, inOp, err);
             }
 
-            void CacheImpl::Clear(IgniteError* err)
+            void CacheImpl::Clear(IgniteError& err)
             {
                 JniErrorInfo jniErr;
 
@@ -236,42 +239,42 @@ namespace ignite
                 IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
             }
 
-            void CacheImpl::Clear(InputOperation& inOp, IgniteError* err)
+            void CacheImpl::Clear(InputOperation& inOp, IgniteError& err)
             {
                 OutOp(OP_CLEAR, inOp, err);
             }
 
-            void CacheImpl::ClearAll(InputOperation& inOp, IgniteError* err)
+            void CacheImpl::ClearAll(InputOperation& inOp, IgniteError& err)
             {
                 OutOp(OP_CLEAR_ALL, inOp, err);
             }
 
-            void CacheImpl::LocalClear(InputOperation& inOp, IgniteError* err)
+            void CacheImpl::LocalClear(InputOperation& inOp, IgniteError& err)
             {
                 OutOp(OP_LOCAL_CLEAR, inOp, err);
             }
 
-            void CacheImpl::LocalClearAll(InputOperation& inOp, IgniteError* err)
+            void CacheImpl::LocalClearAll(InputOperation& inOp, IgniteError& err)
             {
                 OutOp(OP_LOCAL_CLEAR_ALL, inOp, err);
             }
 
-            bool CacheImpl::Remove(InputOperation& inOp, IgniteError* err)
+            bool CacheImpl::Remove(InputOperation& inOp, IgniteError& err)
             {
                 return OutOp(OP_REMOVE_1, inOp, err);
             }
 
-            bool CacheImpl::RemoveIfEqual(InputOperation& inOp, IgniteError* err)
+            bool CacheImpl::RemoveIfEqual(InputOperation& inOp, IgniteError& err)
             {
                 return OutOp(OP_REMOVE_2, inOp, err);
             }
 
-            void CacheImpl::RemoveAll(InputOperation& inOp, IgniteError* err)
+            void CacheImpl::RemoveAll(InputOperation& inOp, IgniteError& err)
             {
                 OutOp(OP_REMOVE_ALL, inOp, err);
             }
 
-            void CacheImpl::RemoveAll(IgniteError* err)
+            void CacheImpl::RemoveAll(IgniteError& err)
             {
                 JniErrorInfo jniErr;
 
@@ -280,29 +283,34 @@ namespace ignite
                 IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
             }
 
-            int32_t CacheImpl::Size(int32_t peekModes, bool local, IgniteError* err)
+            int32_t CacheImpl::Size(int32_t peekModes, bool local, IgniteError& err)
             {
                 int32_t op = local ? OP_SIZE_LOC : OP_SIZE;
 
                 return static_cast<int32_t>(OutInOpLong(op, peekModes, err));
             }
 
-            QueryCursorImpl* CacheImpl::QuerySql(const SqlQuery& qry, IgniteError* err)
+            QueryCursorImpl* CacheImpl::QuerySql(const SqlQuery& qry, IgniteError& err)
             {
                 return QueryInternal(qry, OP_QRY_SQL, err);
             }
 
-            QueryCursorImpl* CacheImpl::QueryText(const TextQuery& qry, IgniteError* err)
+            QueryCursorImpl* CacheImpl::QueryText(const TextQuery& qry, IgniteError& err)
             {
                 return QueryInternal(qry, OP_QRY_TEXT, err);
             }
 
-            QueryCursorImpl* CacheImpl::QueryScan(const ScanQuery& qry, IgniteError* err)
+            QueryCursorImpl* CacheImpl::QueryScan(const ScanQuery& qry, IgniteError& err)
             {
                 return QueryInternal(qry, OP_QRY_SCAN, err);
             }
 
-            QueryCursorImpl* CacheImpl::QuerySqlFields(const SqlFieldsQuery& qry, IgniteError* err)
+            void CacheImpl::Invoke(InputOperation& inOp, OutputOperation& outOp, IgniteError& err)
+            {
+                OutInOpX(OP_INVOKE, inOp, outOp, err);
+            }
+
+            QueryCursorImpl* CacheImpl::QuerySqlFields(const SqlFieldsQuery& qry, IgniteError& err)
             {
                 return QueryInternal(qry, OP_QRY_SQL_FIELDS, err);
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/src/impl/cache/query/continuous/continuous_query_handle_impl.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/impl/cache/query/continuous/continuous_query_handle_impl.cpp b/modules/platforms/cpp/core/src/impl/cache/query/continuous/continuous_query_handle_impl.cpp
index 04e64c9..b2fa1fd 100644
--- a/modules/platforms/cpp/core/src/impl/cache/query/continuous/continuous_query_handle_impl.cpp
+++ b/modules/platforms/cpp/core/src/impl/cache/query/continuous/continuous_query_handle_impl.cpp
@@ -75,7 +75,7 @@ namespace ignite
 
                         jobject res = env.Get()->Context()->TargetOutObject(javaRef, GET_INITIAL_QUERY, &jniErr);
 
-                        IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err);
+                        IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
 
                         if (jniErr.code != IGNITE_JNI_ERR_SUCCESS)
                             return 0;

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/src/impl/cache/query/query_impl.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/impl/cache/query/query_impl.cpp b/modules/platforms/cpp/core/src/impl/cache/query/query_impl.cpp
index aaeb822..018bd99 100644
--- a/modules/platforms/cpp/core/src/impl/cache/query/query_impl.cpp
+++ b/modules/platforms/cpp/core/src/impl/cache/query/query_impl.cpp
@@ -178,7 +178,7 @@ namespace ignite
 
                     env.Get()->Context()->TargetOutStream(javaRef, OP_GET_ALL, inMem.Get()->PointerLong(), &jniErr);
 
-                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err);
+                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
 
                     if (jniErr.code == IGNITE_JNI_ERR_SUCCESS)
                     {
@@ -201,7 +201,7 @@ namespace ignite
 
                     env.Get()->Context()->TargetInLongOutLong(javaRef, OP_ITERATOR, 0, &jniErr);
 
-                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err);
+                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
 
                     if (jniErr.code == IGNITE_JNI_ERR_SUCCESS)
                         iterCalled = true;
@@ -228,7 +228,7 @@ namespace ignite
                     env.Get()->Context()->TargetOutStream(
                         javaRef, OP_GET_BATCH, inMem.Get()->PointerLong(), &jniErr);
 
-                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err);
+                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
 
                     if (jniErr.code != IGNITE_JNI_ERR_SUCCESS)
                         return false;
@@ -251,7 +251,7 @@ namespace ignite
 
                     bool res = env.Get()->Context()->TargetInLongOutLong(javaRef, OP_ITERATOR_HAS_NEXT, 0, &jniErr) == 1;
 
-                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err);
+                    IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
 
                     if (jniErr.code == IGNITE_JNI_ERR_SUCCESS)
                         return res;

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/src/impl/cluster/cluster_group_impl.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/impl/cluster/cluster_group_impl.cpp b/modules/platforms/cpp/core/src/impl/cluster/cluster_group_impl.cpp
new file mode 100644
index 0000000..d30c321
--- /dev/null
+++ b/modules/platforms/cpp/core/src/impl/cluster/cluster_group_impl.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#include "ignite/impl/cluster/cluster_group_impl.h"
+
+using namespace ignite::jni::java;
+using namespace ignite::impl::cluster;
+
+namespace ignite
+{
+    namespace impl
+    {
+        namespace cluster
+        {
+            enum Command
+            {
+                FOR_SERVERS = 23
+            };
+
+            ClusterGroupImpl::ClusterGroupImpl(SP_IgniteEnvironment env, jobject javaRef) :
+                InteropTarget(env, javaRef)
+            {
+                // No-op.
+            }
+
+            ClusterGroupImpl::~ClusterGroupImpl()
+            {
+                // No-op.
+            }
+
+            ClusterGroupImpl::SP_ClusterGroupImpl ClusterGroupImpl::ForServers(IgniteError& err)
+            {
+                JniErrorInfo jniErr;
+
+                jobject res = InOpObject(FOR_SERVERS, err);
+
+                if (jniErr.code != java::IGNITE_JNI_ERR_SUCCESS)
+                    return SP_ClusterGroupImpl();
+
+                return FromTarget(res);
+            }
+
+            ClusterGroupImpl::SP_ClusterGroupImpl ClusterGroupImpl::FromTarget(jobject javaRef)
+            {
+                return SP_ClusterGroupImpl(new ClusterGroupImpl(GetEnvironmentPointer(), javaRef));
+            }
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/src/impl/ignite_environment.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/impl/ignite_environment.cpp b/modules/platforms/cpp/core/src/impl/ignite_environment.cpp
index b058f7c..1a1c80f 100644
--- a/modules/platforms/cpp/core/src/impl/ignite_environment.cpp
+++ b/modules/platforms/cpp/core/src/impl/ignite_environment.cpp
@@ -21,6 +21,8 @@
 #include "ignite/cache/query/continuous/continuous_query.h"
 #include "ignite/binary/binary.h"
 #include "ignite/impl/binary/binary_type_updater_impl.h"
+#include "ignite/impl/module_manager.h"
+#include "ignite/ignite_binding.h"
 
 using namespace ignite::common::concurrent;
 using namespace ignite::jni::java;
@@ -29,15 +31,16 @@ using namespace ignite::impl::binary;
 using namespace ignite::binary;
 using namespace ignite::impl::cache::query::continuous;
 
-namespace ignite 
+namespace ignite
 {
     namespace impl
     {
         /**
-        * Callback codes.
-        */
+         * Callback codes.
+         */
         enum CallbackOp
         {
+            CACHE_INVOKE = 8,
             CONTINUOUS_QUERY_LISTENER_APPLY = 18,
             CONTINUOUS_QUERY_FILTER_RELEASE = 21,
             REALLOC = 36,
@@ -80,6 +83,15 @@ namespace ignite
                     break;
                 }
 
+                case CACHE_INVOKE:
+                {
+                    SharedPointer<InteropMemory> mem = env->Get()->GetMemory(val);
+
+                    env->Get()->CacheInvokeCallback(mem);
+
+                    break;
+                }
+
                 default:
                 {
                     break;
@@ -131,24 +143,33 @@ namespace ignite
             return 0;
         }
 
-        IgniteEnvironment::IgniteEnvironment() :
+        IgniteEnvironment::IgniteEnvironment(const IgniteConfiguration& cfg) :
+            cfg(new IgniteConfiguration(cfg)),
             ctx(SharedPointer<JniContext>()),
-            latch(new SingleLatch),
+            latch(),
             name(0),
             proc(),
+            registry(DEFAULT_FAST_PATH_CONTAINERS_CAP, DEFAULT_SLOW_PATH_CONTAINERS_CAP),
             metaMgr(new BinaryTypeManager()),
             metaUpdater(0),
-            registry(DEFAULT_FAST_PATH_CONTAINERS_CAP, DEFAULT_SLOW_PATH_CONTAINERS_CAP)
+            binding(new IgniteBindingImpl()),
+            moduleMgr(new ModuleManager(GetBindingContext()))
         {
             // No-op.
         }
 
         IgniteEnvironment::~IgniteEnvironment()
         {
-            delete latch;
-            delete name;
-            delete metaMgr;
+            delete[] name;
+
             delete metaUpdater;
+            delete metaMgr;
+            delete cfg;
+        }
+
+        const IgniteConfiguration& IgniteEnvironment::GetConfiguration() const
+        {
+            return *cfg;
         }
 
         JniHandlers IgniteEnvironment::GetJniHandlers(SharedPointer<IgniteEnvironment>* target)
@@ -172,11 +193,13 @@ namespace ignite
 
         void IgniteEnvironment::Initialize()
         {
-            latch->CountDown();
+            latch.CountDown();
 
             jobject binaryProc = Context()->ProcessorBinaryProcessor(proc.Get());
-
             metaUpdater = new BinaryTypeUpdaterImpl(*this, binaryProc);
+
+            common::dynamic::Module currentModule = common::dynamic::GetCurrent();
+            moduleMgr.Get()->RegisterModule(currentModule);
         }
 
         const char* IgniteEnvironment::InstanceName() const
@@ -184,6 +207,11 @@ namespace ignite
             return name;
         }
 
+        void* IgniteEnvironment::GetProcessor()
+        {
+            return (void*)proc.Get();
+        }
+
         JniContext* IgniteEnvironment::Context()
         {
             return ctx.Get();
@@ -233,6 +261,16 @@ namespace ignite
             return metaUpdater;
         }
 
+        IgniteBinding IgniteEnvironment::GetBinding() const
+        {
+            return IgniteBinding(binding);
+        }
+
+        IgniteBindingContext IgniteEnvironment::GetBindingContext() const
+        {
+            return IgniteBindingContext(*cfg, GetBinding());
+        }
+
         void IgniteEnvironment::ProcessorReleaseStart()
         {
             if (proc.Get())
@@ -280,10 +318,38 @@ namespace ignite
                 contQry->ReadAndProcessEvents(rawReader);
             }
         }
-    }
-}
 
+        void IgniteEnvironment::CacheInvokeCallback(SharedPointer<InteropMemory>& mem)
+        {
+            if (!binding.Get())
+                throw IgniteError(IgniteError::IGNITE_ERR_UNKNOWN, "IgniteBinding is not initialized.");
+
+            InteropInputStream inStream(mem.Get());
+            BinaryReaderImpl reader(&inStream);
 
+            InteropOutputStream outStream(mem.Get());
+            BinaryWriterImpl writer(&outStream, GetTypeManager());
 
+            bool local = reader.ReadBool();
 
+            if (local)
+                throw IgniteError(IgniteError::IGNITE_ERR_UNSUPPORTED_OPERATION, "Local invokation is not supported.");
 
+            BinaryObjectImpl binProcHolder = BinaryObjectImpl::FromMemory(*mem.Get(), inStream.Position());
+            BinaryObjectImpl binProc = binProcHolder.GetField(0);
+
+            int64_t procId = binProc.GetTypeId();
+
+            bool invoked = binding.Get()->InvokeCallbackById(procId, reader, writer);
+
+            if (!invoked)
+            {
+                IGNITE_ERROR_FORMATTED_1(IgniteError::IGNITE_ERR_COMPUTE_USER_UNDECLARED_EXCEPTION,
+                    "C++ entry processor is not registered on the node (did you compile your program without -rdynamic?).",
+                    "procId", procId);
+            }
+
+            outStream.Synchronize();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/src/impl/ignite_impl.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/impl/ignite_impl.cpp b/modules/platforms/cpp/core/src/impl/ignite_impl.cpp
index fdc1008..fd9bf45 100644
--- a/modules/platforms/cpp/core/src/impl/ignite_impl.cpp
+++ b/modules/platforms/cpp/core/src/impl/ignite_impl.cpp
@@ -33,6 +33,10 @@ namespace ignite
             txImpl = InternalGetTransactions(err);
 
             IgniteError::ThrowIfNeeded(err);
+
+            prjImpl = InternalGetProjection(err);
+
+            IgniteError::ThrowIfNeeded(err);
         }
 
         IgniteImpl::~IgniteImpl()
@@ -45,11 +49,21 @@ namespace ignite
             return env.Get()->InstanceName();
         }
 
+        const IgniteConfiguration& IgniteImpl::GetConfiguration() const
+        {
+            return env.Get()->GetConfiguration();
+        }
+
         JniContext* IgniteImpl::GetContext()
         {
             return env.Get()->Context();
         }
 
+        IgniteBinding IgniteImpl::GetBinding()
+        {
+            return env.Get()->GetBinding();
+        }
+
         IgniteImpl::SP_TransactionsImpl IgniteImpl::InternalGetTransactions(IgniteError &err)
         {
             SP_TransactionsImpl res;
@@ -61,7 +75,23 @@ namespace ignite
             if (txJavaRef)
                 res = SP_TransactionsImpl(new transactions::TransactionsImpl(env, txJavaRef));
             else
-                IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err);
+                IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
+
+            return res;
+        }
+
+        IgniteImpl::SP_ClusterGroupImpl IgniteImpl::InternalGetProjection(IgniteError& err)
+        {
+            SP_ClusterGroupImpl res;
+
+            JniErrorInfo jniErr;
+
+            jobject txJavaRef = env.Get()->Context()->ProcessorProjection(javaRef, &jniErr);
+
+            if (txJavaRef)
+                res = SP_ClusterGroupImpl(new cluster::ClusterGroupImpl(env, txJavaRef));
+            else
+                IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
 
             return res;
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/src/impl/interop/interop_target.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/impl/interop/interop_target.cpp b/modules/platforms/cpp/core/src/impl/interop/interop_target.cpp
index 4992ccb..0133894 100644
--- a/modules/platforms/cpp/core/src/impl/interop/interop_target.cpp
+++ b/modules/platforms/cpp/core/src/impl/interop/interop_target.cpp
@@ -57,7 +57,7 @@ namespace ignite
                 JniContext::Release(javaRef);
             }
 
-            int64_t InteropTarget::WriteTo(InteropMemory* mem, InputOperation& inOp, IgniteError* err)
+            int64_t InteropTarget::WriteTo(InteropMemory* mem, InputOperation& inOp, IgniteError& err)
             {
                 BinaryTypeManager* metaMgr = env.Get()->GetTypeManager();
 
@@ -72,7 +72,7 @@ namespace ignite
 
                 if (metaMgr->IsUpdatedSince(metaVer))
                 {
-                    if (!metaMgr->ProcessPendingUpdates(env.Get()->GetTypeUpdater(), err))
+                    if (!metaMgr->ProcessPendingUpdates(env.Get()->GetTypeUpdater(), &err))
                         return 0;
                 }
 
@@ -82,13 +82,25 @@ namespace ignite
             void InteropTarget::ReadFrom(InteropMemory* mem, OutputOperation& outOp)
             {
                 InteropInputStream in(mem);
-
                 BinaryReaderImpl reader(&in);
 
                 outOp.ProcessOutput(reader);
             }
 
-            bool InteropTarget::OutOp(int32_t opType, InputOperation& inOp, IgniteError* err)
+            void InteropTarget::ReadError(InteropMemory* mem, IgniteError& err)
+            {
+                InteropInputStream in(mem);
+                BinaryReaderImpl reader(&in);
+
+                // Reading and skipping error class name.
+                reader.ReadObject<std::string>();
+
+                std::string msg = reader.ReadObject<std::string>();
+
+                err = IgniteError(IgniteError::IGNITE_ERR_GENERIC, msg.c_str());
+            }
+
+            bool InteropTarget::OutOp(int32_t opType, InputOperation& inOp, IgniteError& err)
             {
                 JniErrorInfo jniErr;
 
@@ -109,7 +121,7 @@ namespace ignite
                 return false;
             }
 
-            bool InteropTarget::OutOp(int32_t opType, IgniteError* err)
+            bool InteropTarget::OutOp(int32_t opType, IgniteError& err)
             {
                 JniErrorInfo jniErr;
 
@@ -123,7 +135,7 @@ namespace ignite
                 return false;
             }
 
-            bool InteropTarget::InOp(int32_t opType, OutputOperation& outOp, IgniteError* err)
+            bool InteropTarget::InOp(int32_t opType, OutputOperation& outOp, IgniteError& err)
             {
                 JniErrorInfo jniErr;
 
@@ -143,7 +155,18 @@ namespace ignite
                 return false;
             }
 
-            void InteropTarget::OutInOp(int32_t opType, InputOperation& inOp, OutputOperation& outOp, IgniteError* err)
+            jobject InteropTarget::InOpObject(int32_t opType, IgniteError& err)
+            {
+                JniErrorInfo jniErr;
+
+                jobject res = env.Get()->Context()->TargetOutObject(javaRef, opType, &jniErr);
+
+                IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err);
+
+                return res;
+            }
+
+            void InteropTarget::OutInOp(int32_t opType, InputOperation& inOp, OutputOperation& outOp, IgniteError& err)
             {
                 JniErrorInfo jniErr;
 
@@ -164,7 +187,7 @@ namespace ignite
                 }
             }
 
-            void InteropTarget::OutInOpX(int32_t opType, InputOperation& inOp, OutputOperation& outOp, IgniteError* err)
+            void InteropTarget::OutInOpX(int32_t opType, InputOperation& inOp, OutputOperation& outOp, IgniteError& err)
             {
                 JniErrorInfo jniErr;
 
@@ -182,12 +205,14 @@ namespace ignite
                         ReadFrom(outInMem.Get(), outOp);
                     else if (res == ResultNull)
                         outOp.SetNull();
-
-                    //Read and process error if res == ResultError here.
+                    else if (res == ResultError)
+                        ReadError(outInMem.Get(), err);
+                    else
+                        assert(false);
                 }
             }
 
-            int64_t InteropTarget::OutInOpLong(int32_t opType, int64_t val, IgniteError* err)
+            int64_t InteropTarget::OutInOpLong(int32_t opType, int64_t val, IgniteError& err)
             {
                 JniErrorInfo jniErr;
 
@@ -199,4 +224,4 @@ namespace ignite
             }
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/core/src/impl/transactions/transactions_impl.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/src/impl/transactions/transactions_impl.cpp b/modules/platforms/cpp/core/src/impl/transactions/transactions_impl.cpp
index 9f43dad..79f58c5 100644
--- a/modules/platforms/cpp/core/src/impl/transactions/transactions_impl.cpp
+++ b/modules/platforms/cpp/core/src/impl/transactions/transactions_impl.cpp
@@ -148,7 +148,7 @@ namespace ignite
                 InTransactionStartOperation inOp(concurrency, isolation, timeout, txSize);
                 OutTransactionStartOperation outOp;
 
-                OutInOp(OP_START, inOp, outOp, &err);
+                OutInOp(OP_START, inOp, outOp, err);
 
                 return outOp.Get();
             }
@@ -157,7 +157,7 @@ namespace ignite
             {
                 JniErrorInfo jniErr;
 
-                int state = static_cast<int>(OutInOpLong(OP_COMMIT, id, &err));
+                int state = static_cast<int>(OutInOpLong(OP_COMMIT, id, err));
 
                 return ToTransactionState(state);
             }
@@ -166,7 +166,7 @@ namespace ignite
             {
                 JniErrorInfo jniErr;
 
-                int state = static_cast<int>(OutInOpLong(OP_ROLLBACK, id, &err));
+                int state = static_cast<int>(OutInOpLong(OP_ROLLBACK, id, err));
 
                 return ToTransactionState(state);
             }
@@ -175,7 +175,7 @@ namespace ignite
             {
                 JniErrorInfo jniErr;
 
-                int state = static_cast<int>(OutInOpLong(OP_CLOSE, id, &err));
+                int state = static_cast<int>(OutInOpLong(OP_CLOSE, id, err));
 
                 return ToTransactionState(state);
             }
@@ -184,7 +184,7 @@ namespace ignite
             {
                 JniErrorInfo jniErr;
 
-                bool rollbackOnly = OutInOpLong(OP_SET_ROLLBACK_ONLY, id, &err) == 1;
+                bool rollbackOnly = OutInOpLong(OP_SET_ROLLBACK_ONLY, id, err) == 1;
 
                 return rollbackOnly;
             }
@@ -193,7 +193,7 @@ namespace ignite
             {
                 JniErrorInfo jniErr;
 
-                int state = static_cast<int>(OutInOpLong(OP_STATE, id, &err));
+                int state = static_cast<int>(OutInOpLong(OP_STATE, id, err));
 
                 return ToTransactionState(state);
             }
@@ -248,7 +248,7 @@ namespace ignite
             {
                 OutTransactionMetricsOperation op;
 
-                InOp(OP_METRICS, op, &err);
+                InOp(OP_METRICS, op, err);
 
                 if (err.GetCode() == IgniteError::IGNITE_SUCCESS)
                     return op.Get();

http://git-wip-us.apache.org/repos/asf/ignite/blob/1410900f/modules/platforms/cpp/jni/include/ignite/jni/java.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/jni/include/ignite/jni/java.h b/modules/platforms/cpp/jni/include/ignite/jni/java.h
index b790db5..a07b844 100644
--- a/modules/platforms/cpp/jni/include/ignite/jni/java.h
+++ b/modules/platforms/cpp/jni/include/ignite/jni/java.h
@@ -347,7 +347,7 @@ namespace ignite
                 void IgnitionStopAll(bool cancel, JniErrorInfo* errInfo);
                 
                 void ProcessorReleaseStart(jobject obj);
-                jobject ProcessorProjection(jobject obj);
+                jobject ProcessorProjection(jobject obj, JniErrorInfo* errInfo = NULL);
                 jobject ProcessorCache(jobject obj, const char* name);
                 jobject ProcessorCache(jobject obj, const char* name, JniErrorInfo* errInfo);
                 jobject ProcessorCreateCache(jobject obj, const char* name);