blob: fb31b2096b94bc32c1b74b04c42b2720e3285180 [file] [log] [blame]
/*
* 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 <Windows.h>
#include <msclr/marshal_cppstd.h>
#include "geode_defs.hpp"
#include "begin_native.hpp"
#include <geode/ExceptionTypes.hpp>
#include "end_native.hpp"
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Runtime::Serialization;
using namespace msclr::interop;
namespace Apache
{
namespace Geode
{
namespace Client
{
ref class GeodeException;
/// <summary>
/// Factory delegate to create a managed Geode exception.
/// </summary>
/// <remarks>
/// For each managed exception class, its factory delegate is registered
/// and maintained in a static dictionary mapped to its corresponding
/// native Geode C++ exception name.
/// </remarks>
delegate GeodeException^ CreateException2(
const apache::geode::client::Exception& nativeEx, System::Exception^ innerException);
/// <summary>
/// The base exception class of all managed Geode exceptions.
/// </summary>
[Serializable]
public ref class GeodeException
: public System::Exception
{
private:
/// <summary>
/// Prefix for distiguishing managed system exceptions
/// </summary>
literal String^ MgSysExPrefix = "GFCLI_EXCEPTION:";
/// <summary>
/// This contains a mapping of the native Geode exception class
/// name to the factory delegate of the corresponding managed Geode
/// exception class.
/// </summary>
static Dictionary<String^, CreateException2^>^ Native2ManagedExMap =
Init( );
/// <summary>
/// Name and delegate pair class. The Native2ManagedExMap dictionary
/// is populated from a static array of this class.
/// </summary>
value class NameDelegatePair
{
public:
/// <summary>
/// The name of the native Geode exception class.
/// </summary>
String^ m_name;
/// <summary>
/// The factory delegate of the managed Geode exception class
/// corresponding to <c>m_name</c>
/// </summary>
CreateException2^ m_delegate;
};
internal:
/// <summary>
/// Static method to associate the native exception names with
/// the corresponding managed exception factory delegates.
/// </summary>
/// <remarks>
/// This method is not thread-safe and should be called in a single thread.
/// </remarks>
static Dictionary<String^, CreateException2^>^ Init( );
/// <summary>
/// Create the managed Geode exception for a given native Geode exception.
/// As a special case normal system exceptions are also created when the
/// native exception is a wrapper of a managed system exception.
/// </summary>
/// <remarks>
/// Wherever the native Geode C++ code raises a <c>apache::geode::client::Exception</c>,
/// the CLI wrapper code should have a catch-all for those and use
/// this function to create the corresponding managed Geode exception.
/// If no managed Geode exception has been defined (or has not been
/// added using _GF_MG_EXCEPTION_ADD3 in ExceptionTypesMN.cpp) then a
/// generic <c>GeodeException</c> exception is returned.
/// </remarks>
/// <param name="nativeEx">The native Geode exception object</param>
/// <returns>
/// The managed Geode exception object corresponding to the provided
/// native Geode exception object.
/// </returns>
static Exception^ Get(const apache::geode::client::Exception& nativeEx);
/// <summary>
/// Get the stack trace for the given native exception.
/// </summary>
/// <param name="nativeEx">The native Geode exception object</param>
/// <returns>The stack trace of the native exception.</returns>
inline static String^ GetStackTrace(
const apache::geode::client::Exception& nativeEx )
{
return marshal_as<String^>(nativeEx.getStackTrace());
}
/// <summary>
/// Gets the C++ native exception object for a given managed exception.
/// </summary>
/// <remarks>
/// This method is to handle conversion of managed exceptions to
/// C++ exception for those thrown by managed callbacks.
/// For non-Geode .NET exceptions we wrap it inside the generic
/// <c>GeodeException</c> with a special prefix in message.
/// While converting the exception back from C++ to .NET if the
/// prefix is found in the message, then it tries to construct
/// the original exception by reflection on the name of exception
/// contained in the message. Note that in this process the
/// original stacktrace is appended to the message of the exception.
/// </remarks>
inline static std::shared_ptr<apache::geode::client::Exception> GetNative(Exception^ ex)
{
if (ex != nullptr) {
GeodeException^ gfEx = dynamic_cast<GeodeException^>(ex);
if (gfEx != nullptr) {
return gfEx->GetNative();
}
else {
std::shared_ptr<apache::geode::client::Exception> cause;
if (ex->InnerException != nullptr) {
cause = GeodeException::GetNative(ex->InnerException);
}
return std::make_shared<apache::geode::client::Exception>(
marshal_as<std::string>(MgSysExPrefix + ex->ToString())
+ (cause ? cause->getMessage() : ""));
}
}
return nullptr;
}
/// <summary>
/// Gets the C++ native exception object for this managed
/// <c>GeodeException</c>.
/// </summary>
virtual std::shared_ptr<apache::geode::client::Exception> GetNative()
{
std::shared_ptr<apache::geode::client::Exception> cause;
if (this->InnerException != nullptr) {
cause = GeodeException::GetNative(this->InnerException);
}
return std::make_shared<apache::geode::client::Exception>(
marshal_as<std::string>(this->Message + ": " + this->StackTrace)
+ (cause ? cause->getMessage() : ""));
}
/// <summary>
/// Throws the C++ native exception object for the given .NET exception.
/// </summary>
/// <remarks>
/// This method is to handle conversion of managed exceptions to
/// C++ exception for those thrown by managed callbacks.
/// For non-Geode .NET exceptions we wrap it inside the generic
/// <c>GeodeException</c> with a special prefix in message.
/// While converting the exception back from C++ to .NET if the
/// prefix is found in the message, then it tries to construct
/// the original exception by reflection on the name of exception
/// contained in the message. Note that in this process the
/// original stacktrace is appended to the message of the exception.
/// </remarks>
inline static void ThrowNative(Exception^ ex)
{
if (ex != nullptr) {
std::shared_ptr<apache::geode::client::Exception> cause;
if (ex->InnerException != nullptr) {
cause = GeodeException::GetNative(ex->InnerException);
}
throw apache::geode::client::Exception(
marshal_as<std::string>(MgSysExPrefix + ex->ToString())
+ (cause ? cause->getMessage() : ""));
}
}
/// <summary>
/// Throws the C++ native exception object for this managed
/// <c>GeodeException</c>.
/// </summary>
inline void ThrowNative()
{
throw GetNative();
}
public:
/// <summary>
/// Default constructor.
/// </summary>
inline GeodeException( )
: Exception( ) { }
/// <summary>
/// Constructor to create an exception object with the given message.
/// </summary>
/// <param name="message">The exception message.</param>
inline GeodeException( String^ message )
: Exception( message ) { }
/// <summary>
/// Constructor to create an exception object with the given message
/// and with the given inner exception.
/// </summary>
/// <param name="message">The exception message.</param>
/// <param name="innerException">The inner exception object.</param>
inline GeodeException( String^ message, System::Exception^ innerException )
: Exception( message, innerException ) { }
protected:
/// <summary>
/// Initializes a new instance of the <c>GeodeException</c> class with
/// serialized data.
/// This allows deserialization of this exception in .NET remoting.
/// </summary>
/// <param name="info">
/// holds the serialized object data about
/// the exception being thrown
/// </param>
/// <param name="context">
/// contains contextual information about
/// the source or destination
/// </param>
inline GeodeException( SerializationInfo^ info, StreamingContext context )
: Exception( info, context ) { }
};
/// Handle geode exceptions from native layer and convert to managed
/// exceptions.
#define _GF_MG_EXCEPTION_TRY2 \
try {
#define _GF_MG_EXCEPTION_CATCH_ALL2 \
} \
catch (const apache::geode::client::Exception& ex) { \
throw Apache::Geode::Client::GeodeException::Get(ex); \
} \
catch (System::AccessViolationException^ ex) { \
throw ex; \
}
/// Creates a class <c>x</c> named for each exception <c>y</c>.
#define _GF_MG_EXCEPTION_DEF4(x,y) \
[Serializable] \
public ref class x: public GeodeException \
{ \
public: \
\
/** <summary>Default constructor</summary> */ \
x( ) \
: GeodeException( ) { } \
\
/** <summary>
* Constructor to create an exception object with the given message.
* </summary>
* <param name="message">The exception message.</param>
*/ \
x( String^ message ) \
: GeodeException( message ) { } \
\
/** <summary>
* Constructor to create an exception object with the given message
* and with the given inner exception.
* </summary>
* <param name="message">The exception message.</param>
* <param name="innerException">The inner exception object.</param>
*/ \
x( String^ message, System::Exception^ innerException ) \
: GeodeException( message, innerException ) { } \
\
protected: \
\
/** <summary>
* Initializes a new instance of the class with serialized data.
* This allows deserialization of this exception in .NET remoting.
* </summary>
* <param name="info">
* holds the serialized object data about the exception being thrown
* </param>
* <param name="context">
* contains contextual information about the source or destination
* </param>
*/ \
x( SerializationInfo^ info, StreamingContext context ) \
: GeodeException( info, context ) { } \
\
internal: \
x(const apache::geode::client::y& nativeEx) \
: GeodeException(marshal_as<String^>(nativeEx.getMessage()), \
gcnew GeodeException(GeodeException::GetStackTrace( \
nativeEx))) { } \
\
x(const apache::geode::client::y& nativeEx, Exception^ innerException) \
: GeodeException(marshal_as<String^>(nativeEx.getMessage()), \
innerException) { } \
\
static GeodeException^ Create(const apache::geode::client::Exception& ex, \
Exception^ innerException) \
{ \
const apache::geode::client::y* nativeEx = dynamic_cast<const apache::geode::client::y*>( &ex ); \
if (nativeEx != nullptr) { \
if (innerException == nullptr) { \
return gcnew x(*nativeEx); \
} \
else { \
return gcnew x(*nativeEx, innerException); \
} \
} \
return nullptr; \
} \
virtual std::shared_ptr<apache::geode::client::Exception> GetNative() override \
{ \
auto message = marshal_as<std::string>(this->Message + ": " + this->StackTrace); \
if (this->InnerException != nullptr) { \
auto cause = GeodeException::GetNative(this->InnerException); \
message += "Caused by: " + cause->getMessage(); \
} \
return std::make_shared<apache::geode::client::y>(message); \
} \
}
/// Creates a class named for each exception <c>x</c>.
#define _GF_MG_EXCEPTION_DEF3(x) _GF_MG_EXCEPTION_DEF4(x,x)
// For all the native Geode C++ exceptions, a corresponding definition
// should be added below *AND* it should also be added to the static array
// in ExceptionTypesMN.cpp using _GF_MG_EXCEPTION_ADD3( x )
/// <summary>
/// A geode assertion exception.
/// </summary>
_GF_MG_EXCEPTION_DEF3( AssertionException );
/// <summary>
/// Thrown when an argument to a method is illegal.
/// </summary>
_GF_MG_EXCEPTION_DEF3( IllegalArgumentException );
/// <summary>
/// Thrown when the state of cache is manipulated to be illegal.
/// </summary>
_GF_MG_EXCEPTION_DEF3( IllegalStateException );
/// <summary>
/// Thrown when an attempt is made to create an existing cache.
/// </summary>
_GF_MG_EXCEPTION_DEF3( CacheExistsException );
/// <summary>
/// Thrown when the cache xml is incorrect.
/// </summary>
_GF_MG_EXCEPTION_DEF3( CacheXmlException );
/// <summary>
/// Thrown when a timout occurs.
/// </summary>
_GF_MG_EXCEPTION_DEF3( TimeoutException );
/// <summary>
/// Thrown when the cache writer aborts the operation.
/// </summary>
_GF_MG_EXCEPTION_DEF3( CacheWriterException );
/// <summary>
/// Thrown when the cache listener throws an exception.
/// </summary>
_GF_MG_EXCEPTION_DEF3( CacheListenerException );
/// <summary>
/// Thrown when an attempt is made to create an existing region.
/// </summary>
_GF_MG_EXCEPTION_DEF3( RegionExistsException );
/// <summary>
/// Thrown when an operation is attempted on a closed cache.
/// </summary>
_GF_MG_EXCEPTION_DEF3( CacheClosedException );
/// <summary>
/// Thrown when lease of cache proxy has expired.
/// </summary>
_GF_MG_EXCEPTION_DEF3( LeaseExpiredException );
/// <summary>
/// Thrown when the cache loader aborts the operation.
/// </summary>
_GF_MG_EXCEPTION_DEF3( CacheLoaderException );
/// <summary>
/// Thrown when an operation is attempted on a destroyed region.
/// </summary>
_GF_MG_EXCEPTION_DEF3( RegionDestroyedException );
/// <summary>
/// Thrown when an operation is attempted on a destroyed entry.
/// </summary>
_GF_MG_EXCEPTION_DEF3( EntryDestroyedException );
/// <summary>
/// Thrown when the connecting target is not running.
/// </summary>
_GF_MG_EXCEPTION_DEF3( NoSystemException );
/// <summary>
/// Thrown when an attempt is made to connect to
/// DistributedSystem second time.
/// </summary>
_GF_MG_EXCEPTION_DEF3( AlreadyConnectedException );
/// <summary>
/// Thrown when a non-existing file is accessed.
/// </summary>
_GF_MG_EXCEPTION_DEF3( FileNotFoundException );
/// <summary>
/// Thrown when an operation is interrupted.
/// </summary>
_GF_MG_EXCEPTION_DEF3( InterruptedException );
/// <summary>
/// Thrown when an operation unsupported by the
/// current configuration is attempted.
/// </summary>
_GF_MG_EXCEPTION_DEF3( UnsupportedOperationException );
/// <summary>
/// Thrown when statistics are invoked for a region where
/// they are disabled.
/// </summary>
_GF_MG_EXCEPTION_DEF3( StatisticsDisabledException );
/// <summary>
/// Thrown when a concurrent operation fails.
/// </summary>
_GF_MG_EXCEPTION_DEF3( ConcurrentModificationException );
/// <summary>
/// An unknown exception occurred.
/// </summary>
_GF_MG_EXCEPTION_DEF3( UnknownException );
/// <summary>
/// Thrown when a cast operation fails.
/// </summary>
_GF_MG_EXCEPTION_DEF3( ClassCastException );
/// <summary>
/// Thrown when an operation is attempted on a non-existent entry.
/// </summary>
_GF_MG_EXCEPTION_DEF3( EntryNotFoundException );
/// <summary>
/// Thrown when there is an input/output error.
/// </summary>
_GF_MG_EXCEPTION_DEF4( GeodeIOException, GeodeIOException );
/// <summary>
/// Thrown when geode configuration file is incorrect.
/// </summary>
_GF_MG_EXCEPTION_DEF4( GeodeConfigException, GeodeConfigException );
/// <summary>
/// Thrown when a null argument is provided to a method
/// where it is expected to be non-null.
/// </summary>
_GF_MG_EXCEPTION_DEF3( NullPointerException );
/// <summary>
/// Thrown when attempt is made to create an existing entry.
/// </summary>
_GF_MG_EXCEPTION_DEF3( EntryExistsException );
/// <summary>
/// Thrown when an operation is attempted before connecting
/// to the distributed system.
/// </summary>
_GF_MG_EXCEPTION_DEF3( NotConnectedException );
/// <summary>
/// Thrown when there is an error in the cache proxy.
/// </summary>
_GF_MG_EXCEPTION_DEF3( CacheProxyException );
/// <summary>
/// Thrown when the system cannot allocate any more memory.
/// </summary>
_GF_MG_EXCEPTION_DEF3( OutOfMemoryException );
/// <summary>
/// Thrown when an attempt is made to release a lock not
/// owned by the thread.
/// </summary>
_GF_MG_EXCEPTION_DEF3( NotOwnerException );
/// <summary>
/// Thrown when a region is created in an incorrect scope.
/// </summary>
_GF_MG_EXCEPTION_DEF3( WrongRegionScopeException );
/// <summary>
/// Thrown when the internal buffer size is exceeded.
/// </summary>
_GF_MG_EXCEPTION_DEF3( BufferSizeExceededException );
/// <summary>
/// Thrown when a region creation operation fails.
/// </summary>
_GF_MG_EXCEPTION_DEF3( RegionCreationFailedException );
/// <summary>
/// Thrown when there is a fatal internal exception in Geode.
/// </summary>
_GF_MG_EXCEPTION_DEF3( FatalInternalException );
/// <summary>
/// Thrown by the persistence manager when a write
/// fails due to disk failure.
/// </summary>
_GF_MG_EXCEPTION_DEF3( DiskFailureException );
/// <summary>
/// Thrown by the persistence manager when the data
/// to be read from disk is corrupt.
/// </summary>
_GF_MG_EXCEPTION_DEF3( DiskCorruptException );
/// <summary>
/// Thrown when persistence manager fails to initialize.
/// </summary>
_GF_MG_EXCEPTION_DEF3( InitFailedException );
/// <summary>
/// Thrown when persistence manager fails to close properly.
/// </summary>
_GF_MG_EXCEPTION_DEF3( ShutdownFailedException );
/// <summary>
/// Thrown when an exception occurs on the cache server.
/// </summary>
_GF_MG_EXCEPTION_DEF3( CacheServerException );
/// <summary>
/// Thrown when bound of array/vector etc. is exceeded.
/// </summary>
_GF_MG_EXCEPTION_DEF3( OutOfRangeException );
/// <summary>
/// Thrown when query exception occurs at the server.
/// </summary>
_GF_MG_EXCEPTION_DEF3( QueryException );
/// <summary>
/// Thrown when an unknown message is received from the server.
/// </summary>
_GF_MG_EXCEPTION_DEF3( MessageException );
/// <summary>
/// Thrown when a client operation is not authorized on the server.
/// </summary>
_GF_MG_EXCEPTION_DEF3( NotAuthorizedException );
/// <summary>
/// Thrown when authentication to the server fails.
/// </summary>
_GF_MG_EXCEPTION_DEF3( AuthenticationFailedException );
/// <summary>
/// Thrown when credentials are not provided to a server which expects them.
/// </summary>
_GF_MG_EXCEPTION_DEF3( AuthenticationRequiredException );
/// <summary>
/// Thrown when a duplicate durable client id is provided to the server.
/// </summary>
_GF_MG_EXCEPTION_DEF3( DuplicateDurableClientException );
/// <summary>
/// Thrown when a client is unable to contact any locators.
/// </summary>
_GF_MG_EXCEPTION_DEF3( NoAvailableLocatorsException );
/// <summary>
/// Thrown when all connections in a pool are in use..
/// </summary>
_GF_MG_EXCEPTION_DEF3( AllConnectionsInUseException );
/// <summary>
/// Thrown when cq is invalid
/// </summary>
_GF_MG_EXCEPTION_DEF3( CqInvalidException );
/// <summary>
/// Thrown when function execution failed
/// </summary>
_GF_MG_EXCEPTION_DEF3( FunctionExecutionException );
/// <summary>
/// Thrown during continuous query execution time.
/// </summary>
_GF_MG_EXCEPTION_DEF3( CqException );
/// <summary>
/// Thrown if the Cq on which the operaion performed is closed
/// </summary>
_GF_MG_EXCEPTION_DEF3( CqClosedException );
/// <summary>
/// Thrown if the Cq Query failed
/// </summary>
_GF_MG_EXCEPTION_DEF3( CqQueryException );
/// <summary>
/// Thrown if a Cq by this name already exists on this client
/// </summary>
_GF_MG_EXCEPTION_DEF3( CqExistsException );
_GF_MG_EXCEPTION_DEF3( InvalidDeltaException );
/// <summary>
/// Thrown if a Key is not present in the region.
/// </summary>
_GF_MG_EXCEPTION_DEF3( KeyNotFoundException );
/// <summary>
/// Thrown if commit fails.
/// </summary>
_GF_MG_EXCEPTION_DEF3( CommitConflictException );
/// <summary>
/// Thrown if transaction delegate went down.
/// </summary>
_GF_MG_EXCEPTION_DEF3( TransactionDataNodeHasDepartedException );
/// <summary>
/// Thrown if commit rebalance happens during a transaction.
/// </summary>
_GF_MG_EXCEPTION_DEF3( TransactionDataRebalancedException );
} // namespace Client
} // namespace Geode
} // namespace Apache