From fc70573a25776830380a050a673e9003c1c629c7 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Fri, 27 May 2016 00:08:02 +0200 Subject: [PATCH] [DEV] extract Future in separate file and start test it in real case --- jus/Client.cpp | 73 +++---- jus/Client.h | 341 +------------------------------- jus/Future.cpp | 173 ++++++++++++++++ jus/Future.h | 36 ++++ jus/FutureBase.cpp | 116 +++++++++++ jus/FutureBase.h | 32 +++ jus/FutureData.h | 19 ++ jus/ServiceRemote.cpp | 5 +- jus/ServiceRemote.h | 205 +------------------ lutin_jus.py | 5 + test/client/appl/main.cpp | 7 +- tools/system-user/appl/main.cpp | 2 +- 12 files changed, 426 insertions(+), 588 deletions(-) create mode 100644 jus/Future.cpp create mode 100644 jus/Future.h create mode 100644 jus/FutureBase.cpp create mode 100644 jus/FutureBase.h create mode 100644 jus/FutureData.h diff --git a/jus/Client.cpp b/jus/Client.cpp index fac5d68..d2f60f1 100644 --- a/jus/Client.cpp +++ b/jus/Client.cpp @@ -25,7 +25,7 @@ void jus::Client::onClientData(std::string _value) { ejson::Object obj(_value); jus::FutureBase future; { - uint64_t tid = etk::string_to_uint64_t(obj["id"].toString().get()); + uint64_t tid = obj["id"].toNumber().get(); if (tid == 0) { JUS_ERROR("call with no ID ==> error ..."); return; @@ -43,7 +43,7 @@ void jus::Client::onClientData(std::string _value) { } future = *it; it = m_pendingCall.erase(it); - return; + break; } } if (future.isValid() == false) { @@ -51,8 +51,7 @@ void jus::Client::onClientData(std::string _value) { m_newData.push_back(std::move(_value)); return; } - // TODO : Call future ... - + future.setAnswer(obj); } jus::ServiceRemote jus::Client::getService(const std::string& _name) { @@ -61,18 +60,23 @@ jus::ServiceRemote jus::Client::getService(const std::string& _name) { bool jus::Client::link(const std::string& _serviceName) { // TODO : Check the number of connection of this service ... - bool ret = call_b("link", _serviceName); - if (ret == false) { - JUS_ERROR("Can not link with the service named: '" << _serviceName << "'"); + jus::Future ret = call("link", _serviceName); + ret.wait(); + if (ret.hasError() == true) { + JUS_WARNING("Can not link with the service named: '" << _serviceName << "' ==> link error"); + return false; } - return ret; + return ret.get(); } -void jus::Client::unlink(const std::string& _serviceName) { - bool ret = call_b("unlink", _serviceName); - if (ret == false) { - JUS_ERROR("Can not unlink with the service named: '" << _serviceName << "'"); +bool jus::Client::unlink(const std::string& _serviceName) { + jus::Future ret = call("unlink", _serviceName); + ret.wait(); + if (ret.hasError() == true) { + JUS_WARNING("Can not unlink with the service named: '" << _serviceName << "' ==> link error"); + return false; } + return ret.get(); } std::string jus::Client::asyncRead() { @@ -107,17 +111,19 @@ void jus::Client::onPropertyChangePort(){ } -void jus::Client::connect(const std::string& _remoteUserToConnect){ +bool jus::Client::connect(const std::string& _remoteUserToConnect){ disconnect(); JUS_DEBUG("connect [START]"); enet::Tcp connection = std::move(enet::connectTcpClient(*propertyIp, *propertyPort)); m_interfaceClient.setInterface(std::move(connection)); m_interfaceClient.connect(); - bool ret = call_b("connectToUser", _remoteUserToConnect, "jus-client"); - if (ret == false) { - JUS_ERROR("Connection error"); + jus::Future ret = call("connectToUser", _remoteUserToConnect, "jus-client"); + ret.wait(); + if (ret.hasError() == true) { + JUS_WARNING("Can not connect to user named: '" << _remoteUserToConnect << "' ==> return error"); + return false; } - JUS_DEBUG("connect [STOP]"); + return ret.get(); } void jus::Client::disconnect() { @@ -130,20 +136,7 @@ uint64_t jus::Client::getId() { return m_id++; } -ejson::Object jus::Client::callJson(const ejson::Object& _obj) { - JUS_VERBOSE("Call JSON [START] "); - if (m_interfaceClient.isActive() == false) { - return ejson::Object(); - } - JUS_DEBUG("Call JSON '" << _obj.generateHumanString() << "'"); - m_interfaceClient.write(_obj.generateMachineString()); - std::string ret = asyncRead(); - JUS_VERBOSE("Call JSON [STOP]"); - return ejson::Object(ret); -} - - -jus::FutureBase jus::Client::sendJson(uint64_t _transactionId, const ejson::Object& _obj) { +jus::FutureBase jus::Client::callJson(uint64_t _transactionId, const ejson::Object& _obj) { JUS_VERBOSE("Send JSON [START] "); if (m_interfaceClient.isActive() == false) { ejson::Object obj; @@ -161,22 +154,4 @@ jus::FutureBase jus::Client::sendJson(uint64_t _transactionId, const ejson::Obje JUS_VERBOSE("Send JSON [STOP]"); return tmpFuture; } -namespace jus { - template<> - bool jus::Future::get() { - if (m_data == nullptr) { - return false; - } - ejson::Value val = m_data->m_returnData["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return false; - } - if (val.isBoolean() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Boolean'"); - return false; - } - return val.toBoolean().get(); - } -} diff --git a/jus/Client.h b/jus/Client.h index 4768ac7..480d191 100644 --- a/jus/Client.h +++ b/jus/Client.h @@ -12,118 +12,9 @@ #include #include #include +#include namespace jus { - class FutureData { - public: - uint64_t m_transactionId; - bool m_isFinished; - ejson::Object m_returnData; - }; - class FutureBase { - public: // TODO: Do it better .. - ememory::SharedPtr m_data; - public: - FutureBase() { - m_data = nullptr; - } - FutureBase(uint64_t _transactionId) { - m_data = std::make_shared(); - if (m_data == nullptr) { - return; - } - m_data->m_transactionId = _transactionId; - m_data->m_isFinished = false; - } - FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData) { - m_data = std::make_shared(); - if (m_data == nullptr) { - return; - } - m_data->m_transactionId = _transactionId; - m_data->m_isFinished = _isFinished; - m_data->m_returnData = _returnData; - } - jus::FutureBase operator= (const jus::FutureBase& _base) { - m_data = _base.m_data; - return *this; - } - void setAnswer(const ejson::Object& _returnValue) { - if (m_data == nullptr) { - JUS_ERROR(" Not a valid future ..."); - return; - } - m_data->m_returnData = _returnValue; - m_data->m_isFinished = true; - } - uint64_t getTransactionId() { - if (m_data == nullptr) { - return 0; - } - return m_data->m_transactionId; - } - bool hasError() { - if (m_data == nullptr) { - return true; - } - return m_data->m_returnData.valueExist("error"); - } - std::string getErrorType() { - if (m_data == nullptr) { - return "NULL_PTR"; - } - return m_data->m_returnData["error"].toString().get(); - } - std::string getErrorHelp() { - if (m_data == nullptr) { - return "Thsi is a nullptr future"; - } - return m_data->m_returnData["error-help"].toString().get(); - } - bool isValid() { - return m_data != nullptr; - } - bool isFinished() { - if (m_data == nullptr) { - return true; - } - return m_data->m_isFinished; - } - void wait() { - while (isFinished() == false) { - // TODO : Do it better ... like messaging/mutex_locked ... - usleep(10000); - } - } - bool waitFor(std::chrono::microseconds _delta) { - std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); - while ( std::chrono::steady_clock::now() - start < _delta - && isFinished() == false) { - // TODO : Do it better ... like messaging/mutex_locked ... - usleep(10000); - } - return isFinished(); - } - bool waitUntile(std::chrono::steady_clock::time_point _endTime) { - while ( std::chrono::steady_clock::now() < _endTime - && isFinished() == false) { - // TODO : Do it better ... like messaging/mutex_locked ... - usleep(10000); - } - return isFinished(); - } - }; - - template - class Future : public jus::FutureBase { - public: - jus::Future& operator= (const jus::FutureBase& _base) { - m_data = _base.m_data; - return *this; - } - JUS_RETURN get(); - }; - class Client : public eproperty::Interface { friend class ServiceRemote; public: @@ -138,12 +29,12 @@ namespace jus { public: Client(); virtual ~Client(); - void connect(const std::string& _remoteUserToConnect); + bool connect(const std::string& _remoteUserToConnect); void disconnect(); public: jus::ServiceRemote getService(const std::string& _serviceName); bool link(const std::string& _serviceName); - void unlink(const std::string& _serviceName); + bool unlink(const std::string& _serviceName); // Connect that is not us //bool identify("clientTest1#atria-soft.com", "QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968"); @@ -152,236 +43,18 @@ namespace jus { private: void onClientData(std::string _value); std::string asyncRead(); - ejson::Object callJson(const ejson::Object& _obj); - jus::FutureBase sendJson(uint64_t _transactionId, const ejson::Object& _obj); + jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj); public: - uint64_t getId(); - template - jus::Future callAsync(const std::string& _functionName, _ARGS&&... _args) { + template + jus::FutureBase call(const std::string& _functionName, _ARGS&&... _args) { uint64_t id = getId(); ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); - jus::Future out = sendJson(id, callElem); - return out; - } - - template - void call(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCall(getId(), _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - } - template - int32_t call_i(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCall(getId(), _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return 0; - } - if (val.isNumber() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Number'"); - return 0; - } - return int32_t(val.toNumber().get()); - } - template - double call_d(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCall(getId(), _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return 0.0; - } - if (val.isNumber() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Number'"); - return 0.0; - } - return val.toNumber().get(); - } - template - std::string call_s(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCall(getId(), _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return ""; - } - if (val.isString() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'String'"); - return ""; - } - return val.toString().get(); - } - template - bool call_b(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCall(getId(), _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return false; - } - if (val.isBoolean() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Boolean'"); - return false; - } - return val.toBoolean().get(); - } - template - std::vector call_vi(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCall(getId(), _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - if (obj.valueExist("return") == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - if (val.isArray() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); - return std::vector(); - } - std::vector out; - for (auto it : val.toArray()) { - if (val.isNumber() == false) { - JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Number'"); - continue; - } - out.push_back(int32_t(val.toNumber().get())); - } - return out; - } - template - std::vector call_vd(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCall(getId(), _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - if (obj.valueExist("return") == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - if (val.isArray() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); - return std::vector(); - } - std::vector out; - for (auto it : val.toArray()) { - if (it.isNumber() == false) { - JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Number'"); - continue; - } - out.push_back(it.toNumber().get()); - } - return out; - } - template - std::vector call_vs(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCall(getId(), _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - if (obj.valueExist("return") == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - if (val.isArray() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); - return std::vector(); - } - std::vector out; - for (auto it : val.toArray()) { - if (it.isString() == false) { - JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'String'"); - continue; - } - out.push_back(it.toString().get()); - } - return out; - } - template - std::vector call_vb(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCall(getId(), _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - if (obj.valueExist("return") == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - if (val.isArray() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); - return std::vector(); - } - std::vector out; - for (auto it : val.toArray()) { - if (it.isBoolean() == false) { - JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Boolean'"); - continue; - } - out.push_back(it.toBoolean().get()); - } - return out; + return callJson(id, callElem); } private: void onPropertyChangeIp(); void onPropertyChangePort(); }; - /* - template - RETURN_TYPE Client::call(const std::string& _functionName) { - ejson::Object callElem = ejson::Object(std::string("{ 'call':'") + _functionName + "'}"); - ejson::Object obj = callJson(callElem); - return 256; - } - template - RETURN_TYPE Client::call(const std::string& _functionName) { - ejson::Object callElem = ejson::Object(std::string("{ 'call':'") + _functionName + "'}"); - ejson::Object obj = callJson(callElem); - return std::vector(); - } - */ } diff --git a/jus/Future.cpp b/jus/Future.cpp new file mode 100644 index 0000000..f9b5fac --- /dev/null +++ b/jus/Future.cpp @@ -0,0 +1,173 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2014, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#include +#include +#include + +namespace jus { + template<> + bool jus::Future::get() { + if (m_data == nullptr) { + return false; + } + ejson::Value val = m_data->m_returnData["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return false; + } + if (val.isBoolean() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Boolean'"); + return false; + } + return val.toBoolean().get(); + } + template<> + int32_t jus::Future::get() { + if (m_data == nullptr) { + return 0; + } + ejson::Value val = m_data->m_returnData["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return 0; + } + if (val.isNumber() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Number'"); + return 0; + } + return int32_t(val.toNumber().get()); + } + template<> + double jus::Future::get() { + if (m_data == nullptr) { + return 0; + } + ejson::Value val = m_data->m_returnData["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return 0.0; + } + if (val.isNumber() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Number'"); + return 0.0; + } + return val.toNumber().get(); + } + template<> + std::string jus::Future::get() { + if (m_data == nullptr) { + return ""; + } + ejson::Value val = m_data->m_returnData["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return ""; + } + if (val.isString() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'String'"); + return ""; + } + return val.toString().get(); + } + template<> + std::vector jus::Future>::get() { + std::vector out; + if (m_data == nullptr) { + return out; + } + ejson::Value val = m_data->m_returnData["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return std::vector(); + } + if (val.isArray() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); + return std::vector(); + } + for (auto it : val.toArray()) { + if (val.isNumber() == false) { + JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Number'"); + continue; + } + out.push_back(int32_t(val.toNumber().get())); + } + return out; + } + template<> + std::vector jus::Future>::get() { + std::vector out; + if (m_data == nullptr) { + return out; + } + ejson::Value val = m_data->m_returnData["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return out; + } + if (val.isArray() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); + return out; + } + for (auto it : val.toArray()) { + if (it.isNumber() == false) { + JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Number'"); + continue; + } + out.push_back(it.toNumber().get()); + } + return out; + } + template<> + std::vector jus::Future>::get() { + std::vector out; + if (m_data == nullptr) { + return out; + } + ejson::Value val = m_data->m_returnData["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return out; + } + if (val.isArray() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); + return out; + } + for (auto it : val.toArray()) { + if (it.isString() == false) { + JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'String'"); + continue; + } + out.push_back(it.toString().get()); + } + return out; + } + template<> + std::vector jus::Future>::get() { + std::vector out; + if (m_data == nullptr) { + return out; + } + ejson::Value val = m_data->m_returnData["return"]; + if (val.exist() == false) { + JUS_WARNING("No Return value ..."); + return out; + } + if (val.isArray() == false) { + JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); + return out; + } + for (auto it : val.toArray()) { + if (it.isBoolean() == false) { + JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Boolean'"); + continue; + } + out.push_back(it.toBoolean().get()); + } + return out; + } +} + + diff --git a/jus/Future.h b/jus/Future.h new file mode 100644 index 0000000..9642553 --- /dev/null +++ b/jus/Future.h @@ -0,0 +1,36 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2014, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#pragma once + +#include + +namespace jus { + template + class Future : public jus::FutureBase { + public: + Future(const jus::FutureBase& _base): + jus::FutureBase(_base) { + + } + jus::Future& operator= (const jus::FutureBase& _base) { + m_data = _base.m_data; + return *this; + } + JUS_RETURN get(); + }; + template<> + class Future : public jus::FutureBase { + public: + Future(const jus::FutureBase& _base): + jus::FutureBase(_base) { + + } + jus::Future& operator= (const jus::FutureBase& _base) { + m_data = _base.m_data; + return *this; + } + }; +} diff --git a/jus/FutureBase.cpp b/jus/FutureBase.cpp new file mode 100644 index 0000000..75d85f8 --- /dev/null +++ b/jus/FutureBase.cpp @@ -0,0 +1,116 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2014, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#include +#include +#include + +jus::FutureBase::FutureBase(const jus::FutureBase& _base): + m_data(_base.m_data) { + +} + +jus::FutureBase::FutureBase() { + m_data = nullptr; +} + +jus::FutureBase::FutureBase(uint64_t _transactionId) { + m_data = std::make_shared(); + if (m_data == nullptr) { + return; + } + m_data->m_transactionId = _transactionId; + m_data->m_isFinished = false; +} + +jus::FutureBase::FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData) { + m_data = std::make_shared(); + if (m_data == nullptr) { + return; + } + m_data->m_transactionId = _transactionId; + m_data->m_isFinished = _isFinished; + m_data->m_returnData = _returnData; +} + +jus::FutureBase jus::FutureBase::operator= (const jus::FutureBase& _base) { + m_data = _base.m_data; + return *this; +} + +void jus::FutureBase::setAnswer(const ejson::Object& _returnValue) { + if (m_data == nullptr) { + JUS_ERROR(" Not a valid future ..."); + return; + } + m_data->m_returnData = _returnValue; + m_data->m_isFinished = true; +} + +uint64_t jus::FutureBase::getTransactionId() { + if (m_data == nullptr) { + return 0; + } + return m_data->m_transactionId; +} + +bool jus::FutureBase::hasError() { + if (m_data == nullptr) { + return true; + } + return m_data->m_returnData.valueExist("error"); +} + +std::string jus::FutureBase::getErrorType() { + if (m_data == nullptr) { + return "NULL_PTR"; + } + return m_data->m_returnData["error"].toString().get(); +} + +std::string jus::FutureBase::getErrorHelp() { + if (m_data == nullptr) { + return "Thsi is a nullptr future"; + } + return m_data->m_returnData["error-help"].toString().get(); +} + +bool jus::FutureBase::isValid() { + return m_data != nullptr; +} + +bool jus::FutureBase::isFinished() { + if (m_data == nullptr) { + return true; + } + return m_data->m_isFinished; +} + +void jus::FutureBase::wait() { + while (isFinished() == false) { + // TODO : Do it better ... like messaging/mutex_locked ... + usleep(10000); + } +} + +bool jus::FutureBase::waitFor(std::chrono::microseconds _delta) { + std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); + while ( std::chrono::steady_clock::now() - start < _delta + && isFinished() == false) { + // TODO : Do it better ... like messaging/mutex_locked ... + usleep(10000); + } + return isFinished(); +} + +bool jus::FutureBase::waitUntil(std::chrono::steady_clock::time_point _endTime) { + while ( std::chrono::steady_clock::now() < _endTime + && isFinished() == false) { + // TODO : Do it better ... like messaging/mutex_locked ... + usleep(10000); + } + return isFinished(); +} + diff --git a/jus/FutureBase.h b/jus/FutureBase.h new file mode 100644 index 0000000..66ea4c6 --- /dev/null +++ b/jus/FutureBase.h @@ -0,0 +1,32 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2014, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#pragma once + +#include + +namespace jus { + class FutureBase { + public: + ememory::SharedPtr m_data; + public: + FutureBase(const jus::FutureBase& _base); + FutureBase(); + FutureBase(uint64_t _transactionId); + FutureBase(uint64_t _transactionId, bool _isFinished, ejson::Object _returnData); + jus::FutureBase operator= (const jus::FutureBase& _base); + void setAnswer(const ejson::Object& _returnValue); + uint64_t getTransactionId(); + bool hasError(); + std::string getErrorType(); + std::string getErrorHelp(); + bool isValid(); + bool isFinished(); + void wait(); + bool waitFor(std::chrono::microseconds _delta); + bool waitUntil(std::chrono::steady_clock::time_point _endTime); + }; +} + diff --git a/jus/FutureData.h b/jus/FutureData.h new file mode 100644 index 0000000..8ef6e63 --- /dev/null +++ b/jus/FutureData.h @@ -0,0 +1,19 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2014, Edouard DUPIN, all right reserved + * @license APACHE v2.0 (see license file) + */ +#pragma once + +#include +#include + +namespace jus { + class FutureData { + public: + uint64_t m_transactionId; + bool m_isFinished; + ejson::Object m_returnData; + }; +} + diff --git a/jus/ServiceRemote.cpp b/jus/ServiceRemote.cpp index debe5ff..671f360 100644 --- a/jus/ServiceRemote.cpp +++ b/jus/ServiceRemote.cpp @@ -28,6 +28,7 @@ uint64_t jus::ServiceRemote::getId() { return m_clientInterface->getId(); } -ejson::Object jus::ServiceRemote::callJson(const ejson::Object& _obj) { - return m_clientInterface->callJson(_obj); +jus::FutureBase jus::ServiceRemote::callJson(uint64_t _transactionId, const ejson::Object& _obj) { + return m_clientInterface->callJson(_transactionId, _obj); } + diff --git a/jus/ServiceRemote.h b/jus/ServiceRemote.h index a285d5b..a659f26 100644 --- a/jus/ServiceRemote.h +++ b/jus/ServiceRemote.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace jus { class Client; @@ -24,208 +25,14 @@ namespace jus { ~ServiceRemote(); bool exist(); private: - ejson::Object callJson(const ejson::Object& _obj); + jus::FutureBase callJson(uint64_t _transactionId, const ejson::Object& _obj); uint64_t getId(); public: template - void call(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCallService(getId(), m_name, _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - } - template - int32_t call_i(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCallService(getId(), m_name, _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return 0; - } - if (val.isNumber() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Number'"); - return 0; - } - return int32_t(val.toNumber().get()); - } - template - double call_d(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCallService(getId(), m_name, _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return 0.0; - } - if (val.isNumber() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Number'"); - return 0.0; - } - return val.toNumber().get(); - } - template - std::string call_s(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCallService(getId(), m_name, _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return ""; - } - if (val.isString() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'String'"); - return ""; - } - return val.toString().get(); - } - template - bool call_b(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCallService(getId(), m_name, _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return false; - } - if (val.isBoolean() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Boolean'"); - return false; - } - return val.toBoolean().get(); - } - template - std::vector call_vi(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCallService(getId(), m_name, _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - if (obj.valueExist("return") == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - if (val.isArray() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); - return std::vector(); - } - std::vector out; - for (auto it : val.toArray()) { - if (val.isNumber() == false) { - JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Number'"); - continue; - } - out.push_back(int32_t(val.toNumber().get())); - } - return out; - } - template - std::vector call_vd(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCallService(getId(), m_name, _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - if (obj.valueExist("return") == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - if (val.isArray() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); - return std::vector(); - } - std::vector out; - for (auto it : val.toArray()) { - if (it.isNumber() == false) { - JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Number'"); - continue; - } - out.push_back(it.toNumber().get()); - } - return out; - } - template - std::vector call_vs(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCallService(getId(), m_name, _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - if (obj.valueExist("return") == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - if (val.isArray() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); - return std::vector(); - } - std::vector out; - for (auto it : val.toArray()) { - if (it.isString() == false) { - JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'String'"); - continue; - } - out.push_back(it.toString().get()); - } - return out; - } - template - std::vector call_vb(const std::string& _functionName, _ARGS&&... _args) { - ejson::Object callElem = jus::createCallService(getId(), m_name, _functionName, std::forward<_ARGS>(_args)...); - ejson::Object obj = callJson(callElem); - if (obj.valueExist("error") == true) { - JUS_WARNING("call error: " << obj["error"]); - } - if (obj.valueExist("return") == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - ejson::Value val = obj["return"]; - if (val.exist() == false) { - JUS_WARNING("No Return value ..."); - return std::vector(); - } - if (val.isArray() == false) { - JUS_WARNING("Wrong return Type get '" << val.getType() << " instead of 'Array'"); - return std::vector(); - } - std::vector out; - for (auto it : val.toArray()) { - if (it.isBoolean() == false) { - JUS_WARNING("Wrong return Type (part of array) get '" << it.getType() << " instead of 'Boolean'"); - continue; - } - out.push_back(it.toBoolean().get()); - } - return out; + jus::FutureBase call(const std::string& _functionName, _ARGS&&... _args) { + uint64_t id = getId(); + ejson::Object callElem = jus::createCall(id, _functionName, std::forward<_ARGS>(_args)...); + return callJson(id, callElem); } }; } diff --git a/lutin_jus.py b/lutin_jus.py index 5e337e5..66ea843 100644 --- a/lutin_jus.py +++ b/lutin_jus.py @@ -35,6 +35,8 @@ def create(target, module_name): 'jus/AbstractFunction.cpp', 'jus/AbstractFunctionTypeDirect.cpp', 'jus/AbstractFunctionTypeClass.cpp', + 'jus/FutureBase.cpp', + 'jus/Future.cpp', 'jus/ParamType.cpp', 'jus/Client.cpp', 'jus/GateWay.cpp', @@ -49,6 +51,9 @@ def create(target, module_name): 'jus/AbstractFunction.h', 'jus/AbstractFunctionTypeDirect.h', 'jus/AbstractFunctionTypeClass.h', + 'jus/FutureData.h', + 'jus/FutureBase.h', + 'jus/Future.h', 'jus/ParamType.h', 'jus/debug.h', 'jus/Client.h', diff --git a/test/client/appl/main.cpp b/test/client/appl/main.cpp index cd76444..64aa7fb 100644 --- a/test/client/appl/main.cpp +++ b/test/client/appl/main.cpp @@ -36,7 +36,7 @@ int main(int _argc, const char *_argv[]) { client1.connect("test1#atria-soft.com"); // Connect that is not us //client1.identify("clientTest1#atria-soft.com", "QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968"); - jus::Future retIdentify = client1.callAsync("identify", "clientTest1#atria-soft.com", "QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968"); + jus::Future retIdentify = client1.call("identify", "clientTest1#atria-soft.com", "QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968"); retIdentify.wait(); //bool retIdentify = client1.call_b("identify", "clientTest1#atria-soft.com", "QSDQSDGQSF54HSXWVCSQDJ654URTDJ654NBXCDFDGAEZ51968"); @@ -68,8 +68,9 @@ int main(int _argc, const char *_argv[]) { jus::ServiceRemote remoteServiceUser = client1.getService("system-user"); if (remoteServiceUser.exist() == true) { - std::vector retCall = remoteServiceUser.call_vs("getClientGroups"); - APPL_INFO("system-user.getClientGroups() = " << retCall); + jus::Future> retCall = client1.call("getClientGroups", "clientTest1#atria-soft.com"); + retCall.wait(); + APPL_INFO("system-user.getClientGroups() = " << retCall.get()); } int32_t iii=0; while (iii < 3) { diff --git a/tools/system-user/appl/main.cpp b/tools/system-user/appl/main.cpp index cf84839..51a17f7 100644 --- a/tools/system-user/appl/main.cpp +++ b/tools/system-user/appl/main.cpp @@ -165,7 +165,7 @@ int main(int _argc, const char *_argv[]) { serviceInterface.setLastFuncDesc("Get list of group availlable for a client name"); serviceInterface.addLastFuncParam("clientName", "Name of the client"); serviceInterface.advertise("checkTocken", &appl::SystemService::checkTocken); - serviceInterface.advertise("checkTocken", &appl::SystemService::getServices); + serviceInterface.advertise("getServices", &appl::SystemService::getServices); for (int32_t iii=0; iii<_argc ; ++iii) { std::string data = _argv[iii]; if (etk::start_with(data, "--ip=") == true) {