http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/impl/ManagedCacheableKeyBytes.cpp ---------------------------------------------------------------------- diff --git a/clicache/src/impl/ManagedCacheableKeyBytes.cpp b/clicache/src/impl/ManagedCacheableKeyBytes.cpp new file mode 100644 index 0000000..93e01bc --- /dev/null +++ b/clicache/src/impl/ManagedCacheableKeyBytes.cpp @@ -0,0 +1,288 @@ +/* + * 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 "begin_native.hpp" +#include <geode/Cache.hpp> +#include <GeodeTypeIdsImpl.hpp> +#include "DataInputInternal.hpp" +#include "end_native.hpp" + +#include "ManagedCacheableKeyBytes.hpp" +#include "../DataInput.hpp" +#include "../DataOutput.hpp" +#include "../Serializable.hpp" +#include "../CacheableString.hpp" +#include "../ExceptionTypes.hpp" +#include "ManagedString.hpp" + + +using namespace System; + +namespace apache +{ + namespace geode + { + namespace client + { + void ManagedCacheableKeyBytesGeneric::toData(apache::geode::client::DataOutput& output) const + { + Apache::Geode::Client::Log::Debug("ManagedCacheableKeyBytesGeneric::toData: current domain ID: " + System::Threading::Thread::GetDomainID() + " for object: " + System::Convert::ToString((uint64_t) this) + " with its domain ID: " + m_domainId); + try { + //TODO: I think this should work as it is + output.writeBytesOnly(m_bytes, m_size); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + } + + apache::geode::client::Serializable* ManagedCacheableKeyBytesGeneric::fromData(apache::geode::client::DataInput& input) + { + try { + + Apache::Geode::Client::Log::Debug("ManagedCacheableKeyBytesGeneric::fromData: classid " + m_classId + "aid = " + +System::Threading::Thread::GetDomainID()); + Apache::Geode::Client::DataInput mg_input(&input, true, input.getCache()); + const System::Byte* objStartPos = input.currentBufferPosition(); + + Apache::Geode::Client::IGeodeSerializable^ obj = Apache::Geode::Client::Serializable::GetTypeFactoryMethodGeneric(m_classId)(); + obj->FromData(%mg_input); + + input.advanceCursor(mg_input.BytesReadInternally); + + m_hashCode = obj->GetHashCode(); + + const System::Byte* objEndPos = input.currentBufferPosition(); + + //m_size = mg_input.BytesRead; + m_size = (System::UInt32)(objEndPos - objStartPos); + Apache::Geode::Client::Log::Debug("ManagedCacheableKeyBytesGeneric::fromData: objectSize = " + m_size + " m_hashCode = " + m_hashCode); + m_bytes = input.getBufferCopyFrom(objStartPos, m_size); + + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + return this; + } + + System::UInt32 ManagedCacheableKeyBytesGeneric::objectSize() const + { + try { + //return m_managedptr->ObjectSize; + return m_size; + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + return 0; + } + + System::Int32 ManagedCacheableKeyBytesGeneric::classId() const + { + System::UInt32 classId; + try { + //classId = m_managedptr->ClassId; + classId = m_classId; + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + return (classId >= 0x80000000 ? 0 : classId); + } + + int8_t ManagedCacheableKeyBytesGeneric::typeId() const + { + try { + //System::UInt32 classId = m_managedptr->ClassId; + System::UInt32 classId = m_classId; + if (classId >= 0x80000000) { + return (int8_t)((classId - 0x80000000) % 0x20000000); + } + else if (classId <= 0x7F) { + return (int8_t)apache::geode::client::GeodeTypeIdsImpl::CacheableUserData; + } + else if (classId <= 0x7FFF) { + return (int8_t)apache::geode::client::GeodeTypeIdsImpl::CacheableUserData2; + } + else { + return (int8_t)apache::geode::client::GeodeTypeIdsImpl::CacheableUserData4; + } + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + return 0; + } + + int8_t ManagedCacheableKeyBytesGeneric::DSFID() const + { + // convention that [0x8000000, 0xa0000000) is for FixedIDDefault, + // [0xa000000, 0xc0000000) is for FixedIDByte, + // [0xc0000000, 0xe0000000) is for FixedIDShort + // and [0xe0000000, 0xffffffff] is for FixedIDInt + // Note: depends on fact that FixedIDByte is 1, FixedIDShort is 2 + // and FixedIDInt is 3; if this changes then correct this accordingly + //System::UInt32 classId = m_managedptr->ClassId; + System::UInt32 classId = m_classId; + if (classId >= 0x80000000) { + return (int8_t)((classId - 0x80000000) / 0x20000000); + } + return 0; + } + + apache::geode::client::CacheableStringPtr ManagedCacheableKeyBytesGeneric::toString() const + { + try { + Apache::Geode::Client::IGeodeSerializable^ manageObject = getManagedObject(); + if (manageObject != nullptr) + { + apache::geode::client::CacheableStringPtr cStr; + Apache::Geode::Client::CacheableString::GetCacheableString( + manageObject->ToString(), cStr); + return cStr; + } + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + return nullptr; + } + + bool ManagedCacheableKeyBytesGeneric::operator ==(const apache::geode::client::CacheableKey& other) const + { + try { + Apache::Geode::Client::Log::Debug("ManagedCacheableKeyBytesGeneric::equal"); + // now checking classId(), typeId(), DSFID() etc. will be much more + // expensive than just a dynamic_cast + const ManagedCacheableKeyBytesGeneric* p_other = + dynamic_cast<const ManagedCacheableKeyBytesGeneric*>(&other); + if (p_other != NULL) { + DataInputInternal di(m_bytes, m_size, nullptr); + Apache::Geode::Client::DataInput mg_input(&di, true, nullptr); + Apache::Geode::Client::IGeodeSerializable^ obj = + Apache::Geode::Client::Serializable::GetTypeFactoryMethodGeneric(m_classId)(); + obj->FromData(%mg_input); + bool ret = obj->Equals(p_other->ptr()); + Apache::Geode::Client::Log::Debug("ManagedCacheableKeyBytesGeneric::equal return VAL = " + ret); + return ret; + } + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + Apache::Geode::Client::Log::Debug("ManagedCacheableKeyBytesGeneric::equal returns false"); + return false; + } + + bool ManagedCacheableKeyBytesGeneric::operator ==(const ManagedCacheableKeyBytesGeneric& other) const + { + try { + Apache::Geode::Client::Log::Debug("ManagedCacheableKeyBytesGeneric::equal. "); + DataInputInternal di(m_bytes, m_size, nullptr); + Apache::Geode::Client::DataInput mg_input(&di, true, nullptr); + Apache::Geode::Client::IGeodeSerializable^ obj = + Apache::Geode::Client::Serializable::GetTypeFactoryMethodGeneric(m_classId)(); + obj->FromData(%mg_input); + bool ret = obj->Equals(other.ptr()); + Apache::Geode::Client::Log::Debug("ManagedCacheableKeyBytesGeneric::equal return VAL = " + ret); + return ret; + //return obj->Equals(other.get()); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + Apache::Geode::Client::Log::Debug("ManagedCacheableKeyBytesGeneric::equal return false"); + return false; + } + + System::Int32 ManagedCacheableKeyBytesGeneric::hashcode() const + { + return m_hashCode; + } + + size_t ManagedCacheableKeyBytesGeneric::logString(char* buffer, size_t maxLength) const + { + try { + Apache::Geode::Client::IGeodeSerializable^ manageObject = getManagedObject(); + if (manageObject != nullptr) + { + if (maxLength > 0) { + String^ logstr = manageObject->GetType()->Name + '(' + + manageObject->ToString() + ')'; + Apache::Geode::Client::ManagedString mg_str(logstr); + return snprintf(buffer, maxLength, "%s", mg_str.CharPtr); + } + } + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + return 0; + } + + Apache::Geode::Client::IGeodeSerializable^ + ManagedCacheableKeyBytesGeneric::getManagedObject() const + { + + Apache::Geode::Client::Log::Debug("ManagedCacheableKeyBytesGeneric::getManagedObject " + m_size); + + //System::Text::StringBuilder^ sb = gcnew System::Text::StringBuilder(2000); + //for(System::UInt32 i = 0; i<m_size; i++) + //{ + // if(m_bytes[i] != 0) + // sb->Append(System::Convert::ToChar( m_bytes[i])); + // //sb->Append(' '); + //} + + // Apache::Geode::Client::Log::Debug("ManagedCacheableKeyBytesGeneric::getManagedObject " + sb); + DataInputInternal dinp(m_bytes, m_size, nullptr); + Apache::Geode::Client::DataInput mg_dinp(&dinp, true, nullptr); + Apache::Geode::Client::TypeFactoryMethodGeneric^ creationMethod = + Apache::Geode::Client::Serializable::GetTypeFactoryMethodGeneric(m_classId); + Apache::Geode::Client::IGeodeSerializable^ newObj = creationMethod(); + return newObj->FromData(%mg_dinp); + } + } // namespace client + } // namespace geode +} // namespace apache
http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/impl/ManagedCacheableKeyBytes.hpp ---------------------------------------------------------------------- diff --git a/clicache/src/impl/ManagedCacheableKeyBytes.hpp b/clicache/src/impl/ManagedCacheableKeyBytes.hpp new file mode 100644 index 0000000..10f0466 --- /dev/null +++ b/clicache/src/impl/ManagedCacheableKeyBytes.hpp @@ -0,0 +1,208 @@ +/* + * 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. + */ + +#pragma once + +#include "../geode_defs.hpp" +#include <vcclr.h> +#include "begin_native.hpp" +#include <geode/CacheableKey.hpp> +#include "DataOutputInternal.hpp" +#include "end_native.hpp" + +#include "../Log.hpp" +#include "../DataOutput.hpp" + + +using namespace System; + +namespace Apache +{ + namespace Geode + { + namespace Client + { + + interface class IGeodeSerializable; + } // namespace Client + } // namespace Geode +} // namespace Apache + + +namespace apache +{ + namespace geode + { + namespace client + { + + /// <summary> + /// Wraps the managed <see cref="Apache.Geode.Client.IGeodeSerializable" /> + /// object and implements the native <c>apache::geode::client::CacheableKey</c> interface. + /// </summary> + class ManagedCacheableKeyBytesGeneric + : public apache::geode::client::CacheableKey + { + public: + + /// <summary> + /// Constructor to initialize with the provided managed object. + /// </summary> + /// <param name="managedptr"> + /// The managed object. + /// </param> + inline ManagedCacheableKeyBytesGeneric( + Apache::Geode::Client::IGeodeSerializable^ managedptr, bool storeBytes) + : m_domainId(System::Threading::Thread::GetDomainID()), + m_classId(managedptr->ClassId), + m_bytes(NULL), + m_size(0), + m_hashCode(0) + { + if (managedptr != nullptr) + { + if (storeBytes)//if value is from app + { + DataOutputInternal dataOut; + Apache::Geode::Client::DataOutput mg_output(&dataOut, true); + managedptr->ToData(%mg_output); + + //move cursor + //dataOut.advanceCursor(mg_output.BufferLength); + mg_output.WriteBytesToUMDataOutput(); + + m_bytes = dataOut.getBufferCopy(); + m_size = dataOut.getBufferLength(); + + m_hashCode = managedptr->GetHashCode(); + Apache::Geode::Client::Log::Fine( + "ManagedCacheableKeyBytes::Constructor objectSize = " + m_size + " m_hashCode = " + m_hashCode); + } + } + } + + /// <summary> + /// serialize this object + /// </summary> + virtual void toData(apache::geode::client::DataOutput& output) const; + + /// <summary> + /// deserialize this object, typical implementation should return + /// the 'this' pointer. + /// </summary> + virtual apache::geode::client::Serializable* fromData(apache::geode::client::DataInput& input); + + + /// <summary> + /// return the size of this object in bytes + /// </summary> + virtual System::UInt32 objectSize() const; + + /// <summary> + /// return the classId of the instance being serialized. + /// This is used by deserialization to determine what instance + /// type to create and deserialize into. + /// </summary> + virtual System::Int32 classId() const; + + /// <summary> + /// return the typeId of the instance being serialized. + /// This is used by deserialization to determine what instance + /// type to create and deserialize into. + /// </summary> + virtual int8_t typeId() const; + + /// <summary> + /// return the Data Serialization Fixed ID type. + /// This is used to determine what instance type to create + /// and deserialize into. + /// + /// Note that this should not be overridden by custom implementations + /// and is reserved only for builtin types. + /// </summary> + virtual int8_t DSFID() const; + + /// <summary> + /// Display this object as 'string', which depends on the implementation in + /// the managed class + /// </summary> + virtual apache::geode::client::CacheableStringPtr toString() const; + + /// <summary> + /// return true if this key matches other CacheableKey + /// </summary> + virtual bool operator == (const apache::geode::client::CacheableKey& other) const; + /// <summary> + /// return true if this key matches other ManagedCacheableKeyBytes + /// </summary> + virtual bool operator == (const ManagedCacheableKeyBytesGeneric& other) const; + + /// <summary> + /// return the hashcode for this key. + /// </summary> + virtual System::Int32 hashcode() const; + + /// <summary> + /// Copy the string form of a key into a char* buffer for logging purposes. + /// implementations should only generate a string as long as maxLength chars, + /// and return the number of chars written. buffer is expected to be large + /// enough to hold at least maxLength chars. + /// The default implementation renders the classname and instance address. + /// </summary> + virtual size_t logString(char* buffer, size_t maxLength) const; + + /// <summary> + /// Returns the wrapped managed object reference. + /// </summary> + inline Apache::Geode::Client::IGeodeSerializable^ ptr() const + { + return getManagedObject(); + } + + inline ~ManagedCacheableKeyBytesGeneric() + { + Apache::Geode::Client::Log::Fine( + "ManagedCacheableKeyBytes::Destructor current AppDomain ID: " + + System::Threading::Thread::GetDomainID() + " for object: " + + System::Convert::ToString((UInt64) this) + " with its AppDomain ID: " + m_domainId); + GF_SAFE_DELETE(m_bytes); + } + + private: + + Apache::Geode::Client::IGeodeSerializable^ getManagedObject() const; + + /// <summary> + /// Using gcroot to hold the managed delegate pointer (since it cannot be stored directly). + /// Note: not using auto_gcroot since it will result in 'Dispose' of the IGeodeSerializable + /// to be called which is not what is desired when this object is destroyed. Normally this + /// managed object may be created by the user and will be handled automatically by the GC. + /// </summary> + // gcroot<IGeodeSerializable^> m_managedptr; + int m_domainId; + UInt32 m_classId; + System::Byte * m_bytes; + System::UInt32 m_size; + System::UInt32 m_hashCode; + // Disable the copy and assignment constructors + ManagedCacheableKeyBytesGeneric(const ManagedCacheableKeyBytesGeneric&); + ManagedCacheableKeyBytesGeneric& operator = (const ManagedCacheableKeyBytesGeneric&); + }; + + } // namespace client + } // namespace geode +} // namespace apache http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/impl/ManagedCqListener.cpp ---------------------------------------------------------------------- diff --git a/clicache/src/impl/ManagedCqListener.cpp b/clicache/src/impl/ManagedCqListener.cpp new file mode 100644 index 0000000..92678d8 --- /dev/null +++ b/clicache/src/impl/ManagedCqListener.cpp @@ -0,0 +1,189 @@ +/* + * 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 "../geode_includes.hpp" +#include "ManagedCqListener.hpp" +#include "../ICqListener.hpp" +#include "../CqEvent.hpp" + +#include "ManagedString.hpp" +#include "../ExceptionTypes.hpp" +#include "SafeConvert.hpp" +#include <string> + + +using namespace System; +using namespace System::Text; +using namespace System::Reflection; + + +//using namespace apache::geode::client; +namespace apache +{ + namespace geode + { + namespace client + { + + apache::geode::client::CqListener* ManagedCqListenerGeneric::create(const char* assemblyPath, + const char* factoryFunctionName) + { + try + { + String^ mg_assemblyPath = + Apache::Geode::Client::ManagedString::Get(assemblyPath); + String^ mg_factoryFunctionName = + Apache::Geode::Client::ManagedString::Get(factoryFunctionName); + String^ mg_typeName = nullptr; + System::Int32 dotIndx = -1; + + if (mg_factoryFunctionName == nullptr || + (dotIndx = mg_factoryFunctionName->LastIndexOf('.')) < 0) + { + std::string ex_str = "ManagedCqListener: Factory function name '"; + ex_str += factoryFunctionName; + ex_str += "' does not contain type name"; + throw IllegalArgumentException(ex_str.c_str()); + } + + mg_typeName = mg_factoryFunctionName->Substring(0, dotIndx); + mg_factoryFunctionName = mg_factoryFunctionName->Substring(dotIndx + 1); + + Assembly^ assmb = nullptr; + try + { + assmb = Assembly::Load(mg_assemblyPath); + } + catch (System::Exception^) + { + assmb = nullptr; + } + if (assmb == nullptr) + { + std::string ex_str = "ManagedCqListener: Could not load assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + Object^ typeInst = assmb->CreateInstance(mg_typeName, true); + if (typeInst != nullptr) + { + MethodInfo^ mInfo = typeInst->GetType()->GetMethod(mg_factoryFunctionName, + BindingFlags::Public | BindingFlags::Static | BindingFlags::IgnoreCase); + if (mInfo != nullptr) + { + Apache::Geode::Client::ICqListener<Object^, Object^>^ managedptr = nullptr; + try + { + managedptr = dynamic_cast<Apache::Geode::Client::ICqListener<Object^, Object^>^>( + mInfo->Invoke(typeInst, nullptr)); + } + catch (System::Exception^) + { + managedptr = nullptr; + } + if (managedptr == nullptr) + { + std::string ex_str = "ManagedCqListener: Could not create " + "object on invoking factory function ["; + ex_str += factoryFunctionName; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + return new ManagedCqListenerGeneric((Apache::Geode::Client::ICqListener<Object^, Object^>^)managedptr); + } + else + { + std::string ex_str = "ManagedCqListener: Could not load " + "function with name ["; + ex_str += factoryFunctionName; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + } + else + { + Apache::Geode::Client::ManagedString typeName(mg_typeName); + std::string ex_str = "ManagedCqListener: Could not load type ["; + ex_str += typeName.CharPtr; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + } + catch (const apache::geode::client::Exception&) + { + throw; + } + catch (System::Exception^ ex) + { + Apache::Geode::Client::ManagedString mg_exStr(ex->ToString()); + std::string ex_str = "ManagedCqListener: Got an exception while " + "loading managed library: "; + ex_str += mg_exStr.CharPtr; + throw IllegalArgumentException(ex_str.c_str()); + } + return NULL; + } + + void ManagedCqListenerGeneric::onEvent(const CqEvent& ev) + { + try { + + Apache::Geode::Client::CqEvent<Object^, Object^> mevent(&ev); + m_managedptr->OnEvent(%mevent); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::ManagedString mg_exStr(ex->ToString()); + std::string ex_str = "ManagedCqListener: Got an exception in" + "onEvent: "; + ex_str += mg_exStr.CharPtr; + throw IllegalArgumentException(ex_str.c_str()); + } + } + + void ManagedCqListenerGeneric::onError(const CqEvent& ev) + { + Apache::Geode::Client::CqEvent<Object^, Object^> mevent(&ev); + m_managedptr->OnError(%mevent); + } + + void ManagedCqListenerGeneric::close() + { + try { + m_managedptr->Close(); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::ManagedString mg_exStr(ex->ToString()); + std::string ex_str = "ManagedCqListener: Got an exception in" + "close: "; + ex_str += mg_exStr.CharPtr; + throw IllegalArgumentException(ex_str.c_str()); + } + } + + } // namespace client + } // namespace geode +} // namespace apache + http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/impl/ManagedCqListener.hpp ---------------------------------------------------------------------- diff --git a/clicache/src/impl/ManagedCqListener.hpp b/clicache/src/impl/ManagedCqListener.hpp new file mode 100644 index 0000000..f5a3267 --- /dev/null +++ b/clicache/src/impl/ManagedCqListener.hpp @@ -0,0 +1,147 @@ +/* + * 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. + */ + +#pragma once +#include "../geode_defs.hpp" +#include <vcclr.h> +#include "begin_native.hpp" +#include <geode/CqListener.hpp> +#include "end_native.hpp" + +//#include "../ICqListener.hpp" +#include "../ICqListener.hpp" +#include "CqListenerProxy.hpp" + +//using namespace apache::geode::client; +namespace apache { + namespace geode { + namespace client { + + /// <summary> + /// Wraps the managed <see cref="Apache.Geode.Client.ICacheListener" /> + /// object and implements the native <c>apache::geode::client::CacheListener</c> interface. + /// </summary> + class ManagedCqListenerGeneric + : public apache::geode::client::CqListener + { + public: + + /// <summary> + /// Constructor to initialize with the provided managed object. + /// </summary> + /// <param name="userptr"> + /// The user object. + /// </param> + inline ManagedCqListenerGeneric( /*Generic::ICqListener<Object^, Object^>^ managedptr*/Object^ userptr) + : /*m_managedptr( managedptr )*/m_userptr(userptr) { } + + /// <summary> + /// Static function to create a <c>ManagedCacheListener</c> using given + /// managed assembly path and given factory function. + /// </summary> + /// <param name="assemblyPath"> + /// The path of the managed assembly that contains the <c>ICacheListener</c> + /// factory function. + /// </param> + /// <param name="factoryFunctionName"> + /// The name of the factory function of the managed class for creating + /// an object that implements <c>ICacheListener</c>. + /// This should be a static function of the format + /// {Namespace}.{Class Name}.{Method Name}. + /// </param> + /// <exception cref="IllegalArgumentException"> + /// If the managed library cannot be loaded or the factory function fails. + /// </exception> + static CqListener* create(const char* assemblyPath, + const char* factoryFunctionName); + + /// <summary> + /// Destructor -- does nothing. + /// </summary> + virtual ~ManagedCqListenerGeneric() { } + + /// <summary> + /// Handles the event of a new key being added to a region. + /// </summary> + /// <remarks> + /// The entry did not previously exist in this region in the local cache + /// (even with a null value). + /// <para> + /// This function does not throw any exception. + /// </para> + /// </remarks> + /// <param name="ev"> + /// Denotes the event object associated with the entry creation. + /// </param> + /// <seealso cref="Apache.Geode.Client.Region.Create" /> + /// <seealso cref="Apache.Geode.Client.Region.Put" /> + /// <seealso cref="Apache.Geode.Client.Region.Get" /> + virtual void onEvent(const apache::geode::client::CqEvent& ev); + + /// <summary> + /// Handles the event of an entry's value being modified in a region. + /// </summary> + /// <remarks> + /// This entry previously existed in this region in the local cache, + /// but its previous value may have been null. + /// </remarks> + /// <param name="ev"> + /// EntryEvent denotes the event object associated with updating the entry. + /// </param> + /// <seealso cref="Apache.Geode.Client.Region.Put" /> + virtual void onError(const apache::geode::client::CqEvent& ev); + + /// <summary> + /// Handles the event of an entry's value being invalidated. + /// </summary> + /// EntryEvent denotes the event object associated with the entry invalidation. + /// </param> + virtual void close(); + /// <summary> + /// Returns the wrapped managed object reference. + /// </summary> + inline Apache::Geode::Client::ICqListener<Object^, Object^>^ ptr() const + { + return m_managedptr; + } + + inline void setptr(Apache::Geode::Client::ICqListener<Object^, Object^>^ managedptr) + { + m_managedptr = managedptr; + } + + inline Object^ userptr() const + { + return m_userptr; + } + private: + + + /// <summary> + /// Using gcroot to hold the managed delegate pointer (since it cannot be stored directly). + /// Note: not using auto_gcroot since it will result in 'Dispose' of the ICacheListener + /// to be called which is not what is desired when this object is destroyed. Normally this + /// managed object may be created by the user and will be handled automatically by the GC. + /// </summary> + gcroot<Apache::Geode::Client::ICqListener<Object^, Object^>^> m_managedptr; + + gcroot<Object^> m_userptr; + }; + + } // namespace client + } // namespace geode +} // namespace apache http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/impl/ManagedCqStatusListener.cpp ---------------------------------------------------------------------- diff --git a/clicache/src/impl/ManagedCqStatusListener.cpp b/clicache/src/impl/ManagedCqStatusListener.cpp new file mode 100644 index 0000000..21c8473 --- /dev/null +++ b/clicache/src/impl/ManagedCqStatusListener.cpp @@ -0,0 +1,220 @@ +/* + * 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 "ManagedCqStatusListener.hpp" +#include "../ICqStatusListener.hpp" +#include "../CqEvent.hpp" + +#include "ManagedString.hpp" +#include "../ExceptionTypes.hpp" +#include "SafeConvert.hpp" +#include <string> + +using namespace System; +using namespace System::Text; +using namespace System::Reflection; + + +namespace apache +{ + namespace geode + { + namespace client + { + + apache::geode::client::CqListener* ManagedCqStatusListenerGeneric::create(const char* assemblyPath, + const char* factoryFunctionName) + { + try + { + String^ mg_assemblyPath = + Apache::Geode::Client::ManagedString::Get(assemblyPath); + String^ mg_factoryFunctionName = + Apache::Geode::Client::ManagedString::Get(factoryFunctionName); + String^ mg_typeName = nullptr; + System::Int32 dotIndx = -1; + + if (mg_factoryFunctionName == nullptr || + (dotIndx = mg_factoryFunctionName->LastIndexOf('.')) < 0) + { + std::string ex_str = "ManagedCqStatusListenerGeneric: Factory function name '"; + ex_str += factoryFunctionName; + ex_str += "' does not contain type name"; + throw IllegalArgumentException(ex_str.c_str()); + } + + mg_typeName = mg_factoryFunctionName->Substring(0, dotIndx); + mg_factoryFunctionName = mg_factoryFunctionName->Substring(dotIndx + 1); + + Assembly^ assmb = nullptr; + try + { + assmb = Assembly::Load(mg_assemblyPath); + } + catch (System::Exception^) + { + assmb = nullptr; + } + if (assmb == nullptr) + { + std::string ex_str = "ManagedCqStatusListenerGeneric: Could not load assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + Object^ typeInst = assmb->CreateInstance(mg_typeName, true); + if (typeInst != nullptr) + { + MethodInfo^ mInfo = typeInst->GetType()->GetMethod(mg_factoryFunctionName, + BindingFlags::Public | BindingFlags::Static | BindingFlags::IgnoreCase); + if (mInfo != nullptr) + { + Apache::Geode::Client::ICqStatusListener<Object^, Object^>^ managedptr = nullptr; + try + { + managedptr = dynamic_cast<Apache::Geode::Client::ICqStatusListener<Object^, Object^>^>( + mInfo->Invoke(typeInst, nullptr)); + } + catch (System::Exception^) + { + managedptr = nullptr; + } + if (managedptr == nullptr) + { + std::string ex_str = "ManagedCqStatusListenerGeneric: Could not create " + "object on invoking factory function ["; + ex_str += factoryFunctionName; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + return new ManagedCqStatusListenerGeneric((Apache::Geode::Client::ICqListener<Object^, Object^>^)managedptr); + } + else + { + std::string ex_str = "ManagedCqStatusListenerGeneric: Could not load " + "function with name ["; + ex_str += factoryFunctionName; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + } + else + { + Apache::Geode::Client::ManagedString typeName(mg_typeName); + std::string ex_str = "ManagedCqStatusListenerGeneric: Could not load type ["; + ex_str += typeName.CharPtr; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + } + catch (const apache::geode::client::Exception&) + { + throw; + } + catch (System::Exception^ ex) + { + Apache::Geode::Client::ManagedString mg_exStr(ex->ToString()); + std::string ex_str = "ManagedCqStatusListenerGeneric: Got an exception while " + "loading managed library: "; + ex_str += mg_exStr.CharPtr; + throw IllegalArgumentException(ex_str.c_str()); + } + return NULL; + } + + void ManagedCqStatusListenerGeneric::onEvent(const CqEvent& ev) + { + try { + + Apache::Geode::Client::CqEvent<Object^, Object^> mevent(&ev); + m_managedptr->OnEvent(%mevent); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::ManagedString mg_exStr(ex->ToString()); + std::string ex_str = "ManagedCqStatusListenerGeneric: Got an exception in" + "onEvent: "; + ex_str += mg_exStr.CharPtr; + throw IllegalArgumentException(ex_str.c_str()); + } + } + + void ManagedCqStatusListenerGeneric::onError(const CqEvent& ev) + { + Apache::Geode::Client::CqEvent<Object^, Object^> mevent(&ev); + m_managedptr->OnError(%mevent); + } + + void ManagedCqStatusListenerGeneric::close() + { + try { + m_managedptr->Close(); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::ManagedString mg_exStr(ex->ToString()); + std::string ex_str = "ManagedCqStatusListenerGeneric: Got an exception in" + "close: "; + ex_str += mg_exStr.CharPtr; + throw IllegalArgumentException(ex_str.c_str()); + } + } + + void ManagedCqStatusListenerGeneric::onCqDisconnected() + { + try { + m_managedptr->OnCqDisconnected(); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::ManagedString mg_exStr(ex->ToString()); + std::string ex_str = "ManagedCqStatusListenerGeneric: Got an exception in" + "onCqDisconnected: "; + ex_str += mg_exStr.CharPtr; + throw IllegalArgumentException(ex_str.c_str()); + } + } + + void ManagedCqStatusListenerGeneric::onCqConnected() + { + try { + m_managedptr->OnCqConnected(); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::ManagedString mg_exStr(ex->ToString()); + std::string ex_str = "ManagedCqStatusListenerGeneric: Got an exception in" + "OnCqConnected: "; + ex_str += mg_exStr.CharPtr; + throw IllegalArgumentException(ex_str.c_str()); + } + } + + } // namespace client + } // namespace geode +} // namespace apache http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/impl/ManagedCqStatusListener.hpp ---------------------------------------------------------------------- diff --git a/clicache/src/impl/ManagedCqStatusListener.hpp b/clicache/src/impl/ManagedCqStatusListener.hpp new file mode 100644 index 0000000..42a2988 --- /dev/null +++ b/clicache/src/impl/ManagedCqStatusListener.hpp @@ -0,0 +1,142 @@ +/* + * 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. + */ + + +#pragma once +#include "../geode_defs.hpp" +#include <vcclr.h> +#include "begin_native.hpp" +#include <geode/CqStatusListener.hpp> +#include "end_native.hpp" + +#include "../ICqStatusListener.hpp" +#include "CqStatusListenerProxy.hpp" + +namespace apache { + namespace geode { + namespace client { + + /// <summary> + /// Wraps the managed <see cref="Apache.Geode.Client.ICqStatusListener" /> + /// object and implements the native <c>apache::geode::client::CqStatusListener</c> interface. + /// </summary> + class ManagedCqStatusListenerGeneric + : public apache::geode::client::CqStatusListener + { + public: + + /// <summary> + /// Constructor to initialize with the provided managed object. + /// </summary> + /// <param name="userptr"> + /// The user object. + /// </param> + inline ManagedCqStatusListenerGeneric(Object^ userptr) + : m_userptr(userptr) { } + + /// <summary> + /// Static function to create a <c>ManagedCqStatusListenerGeneric</c> using given + /// managed assembly path and given factory function. + /// </summary> + /// <param name="assemblyPath"> + /// The path of the managed assembly that contains the <c>ICqStatusListener</c> + /// factory function. + /// </param> + /// <param name="factoryFunctionName"> + /// The name of the factory function of the managed class for creating + /// an object that implements <c>ICqStatusListener</c>. + /// This should be a static function of the format + /// {Namespace}.{Class Name}.{Method Name}. + /// </param> + /// <exception cref="IllegalArgumentException"> + /// If the managed library cannot be loaded or the factory function fails. + /// </exception> + static CqListener* create(const char* assemblyPath, + const char* factoryFunctionName); + + /// <summary> + /// Destructor -- does nothing. + /// </summary> + virtual ~ManagedCqStatusListenerGeneric() { } + + /// <summary> + /// This method is invoked when an event is occurred on the region + /// that satisfied the query condition of this CQ. + /// This event does not contain an error. + /// </summary> + virtual void onEvent(const apache::geode::client::CqEvent& ev); + + /// <summary> + /// This method is invoked when there is an error during CQ processing. + /// The error can appear while applying query condition on the event. + /// e.g if the event doesn't has attributes as specified in the CQ query. + /// This event does contain an error. The newValue may or may not be + /// available, and will be nullptr if not available. + /// </summary> + virtual void onError(const apache::geode::client::CqEvent& ev); + + /// <summary> + /// Handles the event of an entry's value being invalidated. + /// </summary> + /// EntryEvent denotes the event object associated with the entry invalidation. + /// </param> + virtual void close(); + + /// <summary> + /// Called when the cq loses connection with all servers + /// </summary> + virtual void onCqDisconnected(); + + /// <summary> + /// Called when the cq establishes a connection with a server + /// </summary> + virtual void onCqConnected(); + + /// <summary> + /// Returns the wrapped managed object reference. + /// </summary> + inline Apache::Geode::Client::ICqStatusListener<Object^, Object^>^ ptr() const + { + return m_managedptr; + } + + inline void setptr(Apache::Geode::Client::ICqStatusListener<Object^, Object^>^ managedptr) + { + m_managedptr = managedptr; + } + + inline Object^ userptr() const + { + return m_userptr; + } + private: + + + /// <summary> + /// Using gcroot to hold the managed delegate pointer (since it cannot be stored directly). + /// Note: not using auto_gcroot since it will result in 'Dispose' of the ICqStatusListener + /// to be called which is not what is desired when this object is destroyed. Normally this + /// managed object may be created by the user and will be handled automatically by the GC. + /// </summary> + gcroot<Apache::Geode::Client::ICqStatusListener<Object^, Object^>^> m_managedptr; + + gcroot<Object^> m_userptr; + }; + + } // namespace client + } // namespace geode +} // namespace apache http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/impl/ManagedFixedPartitionResolver.cpp ---------------------------------------------------------------------- diff --git a/clicache/src/impl/ManagedFixedPartitionResolver.cpp b/clicache/src/impl/ManagedFixedPartitionResolver.cpp new file mode 100644 index 0000000..26f3f3b --- /dev/null +++ b/clicache/src/impl/ManagedFixedPartitionResolver.cpp @@ -0,0 +1,262 @@ +/* + * 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 "ManagedFixedPartitionResolver.hpp" +#include "../IFixedPartitionResolver.hpp" +#include "../Region.hpp" +#include "../Log.hpp" +#include "ManagedString.hpp" +#include "../EntryEvent.hpp" +#include "../ExceptionTypes.hpp" +#include "SafeConvert.hpp" +#include "FixedPartitionResolver.hpp" + +using namespace System; +using namespace System::Text; +using namespace System::Reflection; + +namespace apache +{ + namespace geode + { + namespace client + { + PartitionResolver* ManagedFixedPartitionResolverGeneric::create(const char* assemblyPath, + const char* factoryFunctionName) + { + try + { + String^ mg_assemblyPath = + Apache::Geode::Client::ManagedString::Get(assemblyPath); + String^ mg_factoryFunctionName = + Apache::Geode::Client::ManagedString::Get(factoryFunctionName); + String^ mg_typeName = nullptr; + + String^ mg_genericKey = nullptr; + String^ mg_genericVal = nullptr; + + System::Int32 dotIndx = -1; + System::Int32 genericsOpenIndx = -1; + System::Int32 genericsCloseIndx = -1; + System::Int32 commaIndx = -1; + + if (mg_factoryFunctionName == nullptr || + (dotIndx = mg_factoryFunctionName->LastIndexOf('.')) < 0) + { + std::string ex_str = "ManagedFixedPartitionResolverGeneric: Factory function name '"; + ex_str += factoryFunctionName; + ex_str += "' does not contain type name"; + throw IllegalArgumentException(ex_str.c_str()); + } + + if ((genericsCloseIndx = mg_factoryFunctionName->LastIndexOf('>')) < 0) + { + std::string ex_str = "ManagedFixedPartitionResolverGeneric: Factory function name '"; + ex_str += factoryFunctionName; + ex_str += "' does not contain any generic type parameters"; + throw apache::geode::client::IllegalArgumentException(ex_str.c_str()); + } + + if ((genericsOpenIndx = mg_factoryFunctionName->LastIndexOf('<')) < 0 || + genericsOpenIndx > genericsCloseIndx) + { + std::string ex_str = "ManagedFixedPartitionResolverGeneric: Factory function name '"; + ex_str += factoryFunctionName; + ex_str += "' does not contain expected generic type parameters"; + throw apache::geode::client::IllegalArgumentException(ex_str.c_str()); + } + + if ((commaIndx = mg_factoryFunctionName->LastIndexOf(',')) < 0 || + (commaIndx < genericsOpenIndx || commaIndx > genericsCloseIndx)) + { + std::string ex_str = "ManagedFixedPartitionResolverGeneric: Factory function name '"; + ex_str += factoryFunctionName; + ex_str += "' does not contain expected generic type parameter comma separator"; + throw apache::geode::client::IllegalArgumentException(ex_str.c_str()); + } + + StringBuilder^ typeBuilder = gcnew StringBuilder(mg_factoryFunctionName->Substring(0, genericsOpenIndx)); + mg_typeName = typeBuilder->ToString(); + mg_genericKey = mg_factoryFunctionName->Substring(genericsOpenIndx + 1, commaIndx - genericsOpenIndx - 1); + mg_genericKey = mg_genericKey->Trim(); + mg_genericVal = mg_factoryFunctionName->Substring(commaIndx + 1, genericsCloseIndx - commaIndx - 1); + mg_genericVal = mg_genericVal->Trim(); + mg_factoryFunctionName = mg_factoryFunctionName->Substring(dotIndx + 1); + + Apache::Geode::Client::Log::Fine( + "Attempting to instantiate a [{0}<{1}, {2}>] via the [{3}] factory method.", + mg_typeName, mg_genericKey, mg_genericVal, mg_factoryFunctionName); + + typeBuilder->Append("`2"); + mg_typeName = typeBuilder->ToString(); + + Assembly^ assmb = nullptr; + try + { + assmb = Assembly::Load(mg_assemblyPath); + } + catch (System::Exception^) + { + assmb = nullptr; + } + if (assmb == nullptr) + { + std::string ex_str = "ManagedFixedPartitionResolverGeneric: Could not load assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + + Apache::Geode::Client::Log::Debug("Loading type: [{0}]", mg_typeName); + + Type^ typeInst = assmb->GetType(mg_typeName, false, true); + + if (typeInst != nullptr) + { + array<Type^>^ types = gcnew array<Type^>(2); + types[0] = Type::GetType(mg_genericKey, false, true); + types[1] = Type::GetType(mg_genericVal, false, true); + + if (types[0] == nullptr || types[1] == nullptr) + { + std::string ex_str = "ManagedFixedPartitionResolverGeneric: Could not get both generic type argument instances"; + throw apache::geode::client::IllegalArgumentException(ex_str.c_str()); + } + + typeInst = typeInst->MakeGenericType(types); + Apache::Geode::Client::Log::Info("Loading function: [{0}]", mg_factoryFunctionName); + + MethodInfo^ mInfo = typeInst->GetMethod(mg_factoryFunctionName, + BindingFlags::Public | BindingFlags::Static | BindingFlags::IgnoreCase); + + if (mInfo != nullptr) + { + Object^ managedptr = nullptr; + try + { + managedptr = mInfo->Invoke(typeInst, nullptr); + } + catch (System::Exception^ ex) + { + Apache::Geode::Client::Log::Debug("{0}: {1}", ex->GetType()->Name, ex->Message); + managedptr = nullptr; + } + if (managedptr == nullptr) + { + std::string ex_str = "ManagedFixedPartitionResolverGeneric: Could not create " + "object on invoking factory function ["; + ex_str += factoryFunctionName; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + + ManagedFixedPartitionResolverGeneric * mgpr = new ManagedFixedPartitionResolverGeneric(managedptr); + + Type^ prgType = Type::GetType("Apache.Geode.Client.FixedPartitionResolverGeneric`2"); + prgType = prgType->MakeGenericType(types); + Object^ prg = Activator::CreateInstance(prgType); + + mInfo = prgType->GetMethod("SetPartitionResolver"); + array<Object^>^ params = gcnew array<Object^>(1); + params[0] = managedptr; + mInfo->Invoke(prg, params); + + mgpr->setptr((Apache::Geode::Client::IFixedPartitionResolverProxy^)prg); + + return mgpr; + } + else + { + std::string ex_str = "ManagedFixedPartitionResolverGeneric: Could not load " + "function with name ["; + ex_str += factoryFunctionName; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + } + else + { + Apache::Geode::Client::ManagedString typeName(mg_typeName); + std::string ex_str = "ManagedFixedPartitionResolverGeneric: Could not load type ["; + ex_str += typeName.CharPtr; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + } + catch (const apache::geode::client::Exception&) + { + throw; + } + catch (System::Exception^ ex) + { + Apache::Geode::Client::ManagedString mg_exStr(ex->ToString()); + std::string ex_str = "ManagedFixedPartitionResolverGeneric: Got an exception while " + "loading managed library: "; + ex_str += mg_exStr.CharPtr; + throw IllegalArgumentException(ex_str.c_str()); + } + return NULL; + } + + CacheableKeyPtr ManagedFixedPartitionResolverGeneric::getRoutingObject(const EntryEvent& key) + { + try { + return m_managedptr->getRoutingObject(key); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + return nullptr; + } + + const char* ManagedFixedPartitionResolverGeneric::getName() + { + try { + return m_managedptr->getName(); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + return NULL; + } + + const char* ManagedFixedPartitionResolverGeneric::getPartitionName(const EntryEvent& opDetails) + { + try { + return m_managedptr->getPartitionName(opDetails); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + return NULL; + } + + } // namespace client + } // namespace geode +} // namespace apache + http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/impl/ManagedFixedPartitionResolver.hpp ---------------------------------------------------------------------- diff --git a/clicache/src/impl/ManagedFixedPartitionResolver.hpp b/clicache/src/impl/ManagedFixedPartitionResolver.hpp new file mode 100644 index 0000000..aba0bf0 --- /dev/null +++ b/clicache/src/impl/ManagedFixedPartitionResolver.hpp @@ -0,0 +1,147 @@ +/* + * 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. + */ + +#pragma once + +#include "../geode_defs.hpp" +#include <vcclr.h> +#include "begin_native.hpp" +#include <geode/FixedPartitionResolver.hpp> +#include "end_native.hpp" + + +#include "FixedPartitionResolver.hpp" + +namespace apache { + namespace geode { + namespace client { + + /// <summary> + /// Wraps the managed <see cref="Apache.Geode.Client.IFixedPartitionResolver" /> + /// object and implements the native <c>apache::geode::client::FixedPartitionResolver</c> interface. + /// </summary> + class ManagedFixedPartitionResolverGeneric + : public FixedPartitionResolver + { + public: + + /// <summary> + /// Constructor to initialize with the provided managed object. + /// </summary> + /// <param name="userptr"> + /// The managed object. + /// </param> + inline ManagedFixedPartitionResolverGeneric(Object^ userptr) : m_userptr(userptr) { } + + /// <summary> + /// Destructor -- does nothing. + /// </summary> + virtual ~ManagedFixedPartitionResolverGeneric() { } + + /// <summary> + /// Static function to create a <c>ManagedFixedPartitionResolver</c> using given + /// managed assembly path and given factory function. + /// </summary> + /// <param name="assemblyPath"> + /// The path of the managed assembly that contains the <c>IFixedPartitionResolver</c> + /// factory function. + /// </param> + /// <param name="factoryFunctionName"> + /// The name of the factory function of the managed class for creating + /// an object that implements <c>IFixedPartitionResolver</c>. + /// This should be a static function of the format + /// {Namespace}.{Class Name}.{Method Name}. + /// </param> + /// <exception cref="IllegalArgumentException"> + /// If the managed library cannot be loaded or the factory function fails. + /// </exception> + static PartitionResolver* create(const char* assemblyPath, + const char* factoryFunctionName); + + /// <summary> + /// return object associated with entry event which allows the Partitioned Region to store associated data together. + /// </summary> + /// <remarks> + /// throws RuntimeException - any exception thrown will terminate the operation and the exception will be passed to the + /// calling thread. + /// </remarks> + /// <param name="key"> + /// key the detail of the entry event. + /// </param> + + virtual CacheableKeyPtr getRoutingObject(const EntryEvent& key); + + /// <summary> + /// Returns the name of the FixedPartitionResolver. + /// </summary> + /// <remarks> + /// <para> + /// This function does not throw any exception. + /// </para> + /// <returns> + /// the name of the FixedPartitionResolver + /// </returns> + /// </remarks> + virtual const char* getName(); + + + /// <summary> + /// This method is used to get the name of the partition for the given entry + /// operation. + /// <param name="opDetails"> + /// the details of the entry event e.g. {@link Region#get(Object)} + /// </param> + /// <returns> + /// partition-name associated with node which allows mapping of given data to user defined partition. + /// </returns> + virtual const char* getPartitionName(const EntryEvent& opDetails); + + + /// <summary> + /// Returns the wrapped managed object reference. + /// </summary> + inline Apache::Geode::Client::IFixedPartitionResolverProxy^ ptr() const + { + return m_managedptr; + } + + inline void setptr(Apache::Geode::Client::IFixedPartitionResolverProxy^ managedptr) + { + m_managedptr = managedptr; + } + + inline Object^ userptr() const + { + return m_userptr; + } + + private: + + /// <summary> + /// Using gcroot to hold the managed delegate pointer (since it cannot be stored directly). + /// Note: not using auto_gcroot since it will result in 'Dispose' of the IFixedPartitionResolver + /// to be called which is not what is desired when this object is destroyed. Normally this + /// managed object may be created by the user and will be handled automatically by the GC. + /// </summary> + gcroot<Apache::Geode::Client::IFixedPartitionResolverProxy^> m_managedptr; + + gcroot<Object^> m_userptr; + }; + + } // namespace client + } // namespace geode +} // namespace apache http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/impl/ManagedPartitionResolver.cpp ---------------------------------------------------------------------- diff --git a/clicache/src/impl/ManagedPartitionResolver.cpp b/clicache/src/impl/ManagedPartitionResolver.cpp new file mode 100644 index 0000000..51279c5 --- /dev/null +++ b/clicache/src/impl/ManagedPartitionResolver.cpp @@ -0,0 +1,252 @@ +/* + * 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 "../geode_includes.hpp" +#include "ManagedPartitionResolver.hpp" +#include "../IPartitionResolver.hpp" +#include "../Region.hpp" +#include "../Log.hpp" +#include "ManagedString.hpp" +//#include "../../../Region.hpp" +#include "../EntryEvent.hpp" +#include "ManagedString.hpp" +#include "../ExceptionTypes.hpp" +#include "SafeConvert.hpp" +#include "PartitionResolver.hpp" + +using namespace System; +using namespace System::Text; +using namespace System::Reflection; + +namespace apache +{ + namespace geode + { + namespace client + { + + PartitionResolver* ManagedPartitionResolverGeneric::create(const char* assemblyPath, + const char* factoryFunctionName) + { + try + { + String^ mg_assemblyPath = + Apache::Geode::Client::ManagedString::Get(assemblyPath); + String^ mg_factoryFunctionName = + Apache::Geode::Client::ManagedString::Get(factoryFunctionName); + String^ mg_typeName = nullptr; + + String^ mg_genericKey = nullptr; + String^ mg_genericVal = nullptr; + + System::Int32 dotIndx = -1; + System::Int32 genericsOpenIndx = -1; + System::Int32 genericsCloseIndx = -1; + System::Int32 commaIndx = -1; + + if (mg_factoryFunctionName == nullptr || + (dotIndx = mg_factoryFunctionName->LastIndexOf('.')) < 0) + { + std::string ex_str = "ManagedPartitionResolverGeneric: Factory function name '"; + ex_str += factoryFunctionName; + ex_str += "' does not contain type name"; + throw IllegalArgumentException(ex_str.c_str()); + } + + if ((genericsCloseIndx = mg_factoryFunctionName->LastIndexOf('>')) < 0) + { + std::string ex_str = "ManagedPartitionResolverGeneric: Factory function name '"; + ex_str += factoryFunctionName; + ex_str += "' does not contain any generic type parameters"; + throw apache::geode::client::IllegalArgumentException(ex_str.c_str()); + } + + if ((genericsOpenIndx = mg_factoryFunctionName->LastIndexOf('<')) < 0 || + genericsOpenIndx > genericsCloseIndx) + { + std::string ex_str = "ManagedPartitionResolverGeneric: Factory function name '"; + ex_str += factoryFunctionName; + ex_str += "' does not contain expected generic type parameters"; + throw apache::geode::client::IllegalArgumentException(ex_str.c_str()); + } + + if ((commaIndx = mg_factoryFunctionName->LastIndexOf(',')) < 0 || + (commaIndx < genericsOpenIndx || commaIndx > genericsCloseIndx)) + { + std::string ex_str = "ManagedPartitionResolverGeneric: Factory function name '"; + ex_str += factoryFunctionName; + ex_str += "' does not contain expected generic type parameter comma separator"; + throw apache::geode::client::IllegalArgumentException(ex_str.c_str()); + } + + StringBuilder^ typeBuilder = gcnew StringBuilder(mg_factoryFunctionName->Substring(0, genericsOpenIndx)); + mg_typeName = typeBuilder->ToString(); + mg_genericKey = mg_factoryFunctionName->Substring(genericsOpenIndx + 1, commaIndx - genericsOpenIndx - 1); + mg_genericKey = mg_genericKey->Trim(); + mg_genericVal = mg_factoryFunctionName->Substring(commaIndx + 1, genericsCloseIndx - commaIndx - 1); + mg_genericVal = mg_genericVal->Trim(); + mg_factoryFunctionName = mg_factoryFunctionName->Substring(dotIndx + 1); + + Apache::Geode::Client::Log::Fine( + "Attempting to instantiate a [{0}<{1}, {2}>] via the [{3}] factory method.", + mg_typeName, mg_genericKey, mg_genericVal, mg_factoryFunctionName); + + typeBuilder->Append("`2"); + mg_typeName = typeBuilder->ToString(); + + Assembly^ assmb = nullptr; + try + { + assmb = Assembly::Load(mg_assemblyPath); + } + catch (System::Exception^) + { + assmb = nullptr; + } + if (assmb == nullptr) + { + std::string ex_str = "ManagedPartitionResolverGeneric: Could not load assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + + Apache::Geode::Client::Log::Debug("Loading type: [{0}]", mg_typeName); + + Type^ typeInst = assmb->GetType(mg_typeName, false, true); + + if (typeInst != nullptr) + { + array<Type^>^ types = gcnew array<Type^>(2); + types[0] = Type::GetType(mg_genericKey, false, true); + types[1] = Type::GetType(mg_genericVal, false, true); + + if (types[0] == nullptr || types[1] == nullptr) + { + std::string ex_str = "ManagedPartitionResolverGeneric: Could not get both generic type argument instances"; + throw apache::geode::client::IllegalArgumentException(ex_str.c_str()); + } + + typeInst = typeInst->MakeGenericType(types); + Apache::Geode::Client::Log::Info("Loading function: [{0}]", mg_factoryFunctionName); + + MethodInfo^ mInfo = typeInst->GetMethod(mg_factoryFunctionName, + BindingFlags::Public | BindingFlags::Static | BindingFlags::IgnoreCase); + + if (mInfo != nullptr) + { + Object^ managedptr = nullptr; + try + { + managedptr = mInfo->Invoke(typeInst, nullptr); + } + catch (System::Exception^ ex) + { + Apache::Geode::Client::Log::Debug("{0}: {1}", ex->GetType()->Name, ex->Message); + managedptr = nullptr; + } + if (managedptr == nullptr) + { + std::string ex_str = "ManagedPartitionResolverGeneric: Could not create " + "object on invoking factory function ["; + ex_str += factoryFunctionName; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + + ManagedPartitionResolverGeneric * mgpr = new ManagedPartitionResolverGeneric(managedptr); + + Type^ prgType = Type::GetType("Apache.Geode.Client.PartitionResolverGeneric`2"); + prgType = prgType->MakeGenericType(types); + Object^ prg = Activator::CreateInstance(prgType); + + mInfo = prgType->GetMethod("SetPartitionResolver"); + array<Object^>^ params = gcnew array<Object^>(1); + params[0] = managedptr; + mInfo->Invoke(prg, params); + + mgpr->setptr((Apache::Geode::Client::IPartitionResolverProxy^)prg); + + return mgpr; + } + else + { + std::string ex_str = "ManagedPartitionResolverGeneric: Could not load " + "function with name ["; + ex_str += factoryFunctionName; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + } + else + { + Apache::Geode::Client::ManagedString typeName(mg_typeName); + std::string ex_str = "ManagedPartitionResolverGeneric: Could not load type ["; + ex_str += typeName.CharPtr; + ex_str += "] in assembly: "; + ex_str += assemblyPath; + throw IllegalArgumentException(ex_str.c_str()); + } + } + catch (const apache::geode::client::Exception&) + { + throw; + } + catch (System::Exception^ ex) + { + Apache::Geode::Client::ManagedString mg_exStr(ex->ToString()); + std::string ex_str = "ManagedPartitionResolverGeneric: Got an exception while " + "loading managed library: "; + ex_str += mg_exStr.CharPtr; + throw IllegalArgumentException(ex_str.c_str()); + } + return NULL; + } + + CacheableKeyPtr ManagedPartitionResolverGeneric::getRoutingObject(const EntryEvent& key) + { + try { + return m_managedptr->getRoutingObject(key); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + return nullptr; + } + + const char* ManagedPartitionResolverGeneric::getName() + { + try { + return m_managedptr->getName(); + } + catch (Apache::Geode::Client::GeodeException^ ex) { + ex->ThrowNative(); + } + catch (System::Exception^ ex) { + Apache::Geode::Client::GeodeException::ThrowNative(ex); + } + return NULL; + } + + } // namespace client + } // namespace geode +} // namespace apache + http://git-wip-us.apache.org/repos/asf/geode-native/blob/6cbd424f/clicache/src/impl/ManagedPartitionResolver.hpp ---------------------------------------------------------------------- diff --git a/clicache/src/impl/ManagedPartitionResolver.hpp b/clicache/src/impl/ManagedPartitionResolver.hpp new file mode 100644 index 0000000..9640cf9 --- /dev/null +++ b/clicache/src/impl/ManagedPartitionResolver.hpp @@ -0,0 +1,137 @@ +/* + * 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. + */ + +#pragma once + +#include "../geode_defs.hpp" +#include <vcclr.h> +#include "begin_native.hpp" +#include <geode/PartitionResolver.hpp> +#include "end_native.hpp" + + +#include "PartitionResolver.hpp" + +using namespace System; + +namespace apache { + namespace geode { + namespace client { + + /// <summary> + /// Wraps the managed <see cref="Apache.Geode.Client.IPartitionResolver" /> + /// object and implements the native <c>apache::geode::client::PartitionResolver</c> interface. + /// </summary> + class ManagedPartitionResolverGeneric + : public PartitionResolver + { + public: + + /// <summary> + /// Constructor to initialize with the provided managed object. + /// </summary> + /// <param name="userptr"> + /// The managed object. + /// </param> + inline ManagedPartitionResolverGeneric(Object^ userptr) : m_userptr(userptr) { } + + /// <summary> + /// Static function to create a <c>ManagedPartitionResolver</c> using given + /// managed assembly path and given factory function. + /// </summary> + /// <param name="assemblyPath"> + /// The path of the managed assembly that contains the <c>IPartitionResolver</c> + /// factory function. + /// </param> + /// <param name="factoryFunctionName"> + /// The name of the factory function of the managed class for creating + /// an object that implements <c>IPartitionResolver</c>. + /// This should be a static function of the format + /// {Namespace}.{Class Name}.{Method Name}. + /// </param> + /// <exception cref="IllegalArgumentException"> + /// If the managed library cannot be loaded or the factory function fails. + /// </exception> + static PartitionResolver* create(const char* assemblyPath, + const char* factoryFunctionName); + + /// <summary> + /// Destructor -- does nothing. + /// </summary> + virtual ~ManagedPartitionResolverGeneric() { } + + /// <summary> + /// return object associated with entry event which allows the Partitioned Region to store associated data together. + /// </summary> + /// <remarks> + /// throws RuntimeException - any exception thrown will terminate the operation and the exception will be passed to the + /// calling thread. + /// </remarks> + /// <param name="key"> + /// key the detail of the entry event. + /// </param> + + virtual CacheableKeyPtr getRoutingObject(const EntryEvent& key); + + /// <summary> + /// Returns the name of the PartitionResolver. + /// </summary> + /// <remarks> + /// <para> + /// This function does not throw any exception. + /// </para> + /// <returns> + /// the name of the PartitionResolver + /// </returns> + /// </remarks> + virtual const char* getName(); + + + /// <summary> + /// Returns the wrapped managed object reference. + /// </summary> + inline Apache::Geode::Client::IPartitionResolverProxy^ ptr() const + { + return m_managedptr; + } + + inline void setptr(Apache::Geode::Client::IPartitionResolverProxy^ managedptr) + { + m_managedptr = managedptr; + } + + inline Object^ userptr() const + { + return m_userptr; + } + + private: + + /// <summary> + /// Using gcroot to hold the managed delegate pointer (since it cannot be stored directly). + /// Note: not using auto_gcroot since it will result in 'Dispose' of the IPartitionResolver + /// to be called which is not what is desired when this object is destroyed. Normally this + /// managed object may be created by the user and will be handled automatically by the GC. + /// </summary> + gcroot<Apache::Geode::Client::IPartitionResolverProxy^> m_managedptr; + + gcroot<Object^> m_userptr; + }; + + } // namespace client + } // namespace geode +} // namespace apache