std::runtime_error(error)
{
}
+
+ virtual ~Exception() {}
+ virtual const char *name() const;
+ virtual const char *className() const;
};
+
+#define EXCEPTION_DEFINE(CLS) \
+ class CLS : public Exception { \
+ public: \
+ CLS(const std::string& error); \
+ ~CLS() {} \
+ const char *className() const; \
+ const char *name() const; \
+ };
+
+
+#define EXCEPTION_IMPLEMENT(CLS, NAME) \
+ CLS::CLS(const std::string& error) : \
+ Exception(error) \
+ { \
+ } \
+ const char *CLS::className() const \
+ { \
+ return STRINGIFY(CLS); \
+ } \
+ const char *CLS::name() const \
+ { \
+ return NAME; \
+ }
+
+EXCEPTION_DEFINE(AssertionViolationException)
+EXCEPTION_DEFINE(NullPointerException)
+EXCEPTION_DEFINE(InvalidArgumentException)
+EXCEPTION_DEFINE(NotImplementedException)
+EXCEPTION_DEFINE(RangeException)
+EXCEPTION_DEFINE(NotFoundException)
+EXCEPTION_DEFINE(UnsupportedException)
+EXCEPTION_DEFINE(TimeoutException)
+EXCEPTION_DEFINE(NoPermissionException)
+EXCEPTION_DEFINE(OutOfMemoryException)
+EXCEPTION_DEFINE(IOException)
} // namespace runtime
#endif //__RUNTIME_EXCEPTION_H__
namespace rmi {
-class Client {
+template <typename ExceptionModel>
+class RemoteAccessClient {
public:
- Client(const std::string& address);
- virtual ~Client();
+ RemoteAccessClient(const std::string& address);
+ virtual ~RemoteAccessClient();
- Client(const Client&) = delete;
- Client& operator=(const Client&) = delete;
+ RemoteAccessClient(const RemoteAccessClient&) = delete;
+ RemoteAccessClient& operator=(const RemoteAccessClient&) = delete;
void connect();
void disconnect();
std::thread dispatcher;
};
-template<typename... Args>
-int Client::subscribe(const std::string& provider, const std::string& name,
+template <typename ExceptionModel>
+RemoteAccessClient<ExceptionModel>::RemoteAccessClient(const std::string& path) :
+ address(path)
+{
+}
+
+template <typename ExceptionModel>
+RemoteAccessClient<ExceptionModel>::~RemoteAccessClient()
+{
+ try {
+ disconnect();
+ } catch (runtime::Exception& e) {}
+}
+
+template <typename ExceptionModel>
+void RemoteAccessClient<ExceptionModel>::connect()
+{
+ connection = std::make_shared<Connection>(Socket::connect(address));
+
+ dispatcher = std::thread([this] { mainloop.run(); });
+}
+
+template <typename ExceptionModel>
+int RemoteAccessClient<ExceptionModel>::unsubscribe(const std::string& provider, int id)
+{
+ // file descriptor(id) is automatically closed when mainloop callback is destroyed.
+ mainloop.removeEventSource(id);
+ return 0;
+}
+
+template <typename ExceptionModel>
+int RemoteAccessClient<ExceptionModel>::subscribe(const std::string& provider, const std::string& name)
+{
+ Message request = connection->createMessage(Message::MethodCall, provider);
+ request.packParameters(name);
+ connection->send(request);
+
+ runtime::FileDescriptor response;
+ Message reply = connection->dispatch();
+ if (reply.isError()) {
+ std::string klass;
+ reply.disclose(klass);
+
+ ExceptionModel exception;
+ exception.raise(reply.target(), klass);
+ }
+
+ reply.disclose(response);
+
+ return response.fileDescriptor;
+}
+
+template <typename ExceptionModel>
+void RemoteAccessClient<ExceptionModel>::disconnect()
+{
+ mainloop.stop();
+ if (dispatcher.joinable()) {
+ dispatcher.join();
+ }
+}
+
+template <typename ExceptionModel>
+template <typename... Args>
+int RemoteAccessClient<ExceptionModel>::subscribe(const std::string& provider, const std::string& name,
const typename MethodHandler<void, Args...>::type& handler)
{
int id = subscribe(provider, name);
return id;
}
-template<typename Type, typename... Args>
-Type Client::methodCall(const std::string& method, Args&&... args)
+template <typename ExceptionModel>
+template <typename Type, typename... Args>
+Type RemoteAccessClient<ExceptionModel>::methodCall(const std::string& method, Args&&... args)
{
Message request = connection->createMessage(Message::MethodCall, method);
request.packParameters(std::forward<Args>(args)...);
Type response;
Message reply = connection->dispatch();
+ if (reply.isError()) {
+ std::string klass;
+ reply.disclose(klass);
+ ExceptionModel exception;
+ exception.raise(reply.target(), klass);
+ }
+
reply.disclose<Type>(response);
return response;
}
+class DefaultExceptionModel {
+public:
+ void raise(const std::string& target, const std::string& except);
+};
+
+using Client = RemoteAccessClient<DefaultExceptionModel>;
+
} // namespace rmi
#endif //__RMI_CLIENT_H__
// [TBD] Take arguments
Message createReplyMessage() const;
- Message createErrorMessage(const std::string& message) const;
+ Message createErrorMessage(const std::string& target, const std::string& message) const;
unsigned int id() const
{
SET(LIB_SOVERSION "0")
SET (KLAY_SOURCES ${KLAY_SRC}/error.cpp
+ ${KLAY_SRC}/exception.cpp
${KLAY_SRC}/cgroup.cpp
${KLAY_SRC}/process.cpp
${KLAY_SRC}/eventfd.cpp
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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 <klay/exception.h>
+#include <klay/preprocessor.h>
+
+namespace runtime {
+
+const char *Exception::name() const
+{
+ return "Exception";
+}
+
+const char *Exception::className() const
+{
+ return name();
+}
+
+EXCEPTION_IMPLEMENT(AssertionViolationException, "Assertion violation")
+EXCEPTION_IMPLEMENT(NullPointerException, "Null pointer")
+EXCEPTION_IMPLEMENT(InvalidArgumentException, "Invalid argument")
+EXCEPTION_IMPLEMENT(NotImplementedException, "Not implemented")
+EXCEPTION_IMPLEMENT(RangeException, "Out og range")
+EXCEPTION_IMPLEMENT(NotFoundException, "Not found")
+EXCEPTION_IMPLEMENT(UnsupportedException, "Unsupported")
+EXCEPTION_IMPLEMENT(TimeoutException, "Timeout")
+EXCEPTION_IMPLEMENT(NoPermissionException, "No permission")
+EXCEPTION_IMPLEMENT(OutOfMemoryException, "Out of memory")
+EXCEPTION_IMPLEMENT(IOException, "I/O error")
+} // namespace runtime
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <klay/exception.h>
#include <klay/rmi/client.h>
namespace rmi {
-Client::Client(const std::string& path) :
- address(path)
+void DefaultExceptionModel::raise(const std::string& target, const std::string& msg)
{
-}
-
-Client::~Client()
-{
- try {
- disconnect();
- } catch (runtime::Exception& e) {}
-}
-
-void Client::connect()
-{
- connection = std::make_shared<Connection>(Socket::connect(address));
-
- dispatcher = std::thread([this] { mainloop.run(); });
-}
-
-int Client::unsubscribe(const std::string& provider, int id)
-{
- // file descriptor(id) is automatically closed when mainloop callback is destroyed.
- mainloop.removeEventSource(id);
- return 0;
-}
-
-int Client::subscribe(const std::string& provider, const std::string& name)
-{
- Message request = connection->createMessage(Message::MethodCall, provider);
- request.packParameters(name);
- connection->send(request);
-
- runtime::FileDescriptor response;
- Message reply = connection->dispatch();
- reply.disclose(response);
-
- return response.fileDescriptor;
-}
-
-void Client::disconnect()
-{
- mainloop.stop();
- if (dispatcher.joinable()) {
- dispatcher.join();
- }
+ if (target == "InvalidArgumentException")
+ throw runtime::InvalidArgumentException(msg);
+ else if (target == "NotImplementedException")
+ throw runtime::InvalidArgumentException(msg);
+ else if (target == "RangeException")
+ throw runtime::RangeException(msg);
+ else if (target == "NotFoundException")
+ throw runtime::NotFoundException(msg);
+ else if (target == "UnsupportedException")
+ throw runtime::UnsupportedException(msg);
+ else if (target == "NoPermissionException")
+ throw runtime::NoPermissionException(msg);
+ else if (target == "IOException")
+ throw runtime::IOException(msg);
+ else if (target == "OutOfMemoryException")
+ throw runtime::OutOfMemoryException(msg);
+ else
+ throw runtime::Exception(msg);
}
} // namespace rmi
std::lock_guard<std::mutex> lock(receiveMutex);
message.decode(socket);
- if (message.isError()) {
- std::string exception;
- message.disclose(exception);
-
- throw runtime::Exception(exception);
- }
return message;
}
return Message(id(), Reply, target());
}
-Message Message::createErrorMessage(const std::string& message) const
+Message Message::createErrorMessage(const std::string& target, const std::string& message) const
{
- Message error(id(), Error, target());
+ Message error(id(), Error, target);
error.enclose(message);
return error;
// we should increase the reference count of the shared_ptr by capturing it as value
auto process = [&, connection](Message& request) {
try {
+ if (!methodRegistry.count(request.target()))
+ throw runtime::NotFoundException("Method not found");
+
std::shared_ptr<MethodContext> methodContext = methodRegistry.at(request.target());
processingContext = ProcessingContext(connection);
bool allowed = onPrivilegeCheck(processingContext.credentials, methodContext->privilege);
onAuditTrail(processingContext.credentials, request.target(), allowed);
if (!allowed) {
- throw runtime::Exception("Permission denied");
+ throw runtime::NoPermissionException("Permission denied");
}
connection->send(methodContext->dispatcher(request));
+ } catch (runtime::Exception& e) {
+ connection->send(request.createErrorMessage(e.className(), e.what()));
} catch (std::exception& e) {
try {
// Forward the exception to the peer
- connection->send(request.createErrorMessage(e.what()));
+ connection->send(request.createErrorMessage("Exception", e.what()));
} catch (std::exception& ex) {
// The connection is abnormally closed by the peer.
ERROR(KSINK, ex.what());