From ee9ee29065f3dbb5c891a60a109586e53c474dc5 Mon Sep 17 00:00:00 2001 From: "jihwan.seo" Date: Tue, 25 Oct 2016 18:58:52 +0900 Subject: [PATCH] add stop API of base stack in android. since some user application want to use IoTivity more dynamically. stop API of IoTivity should be provided effeciently. Change-Id: Ie9ebb874b9b1d49703d5023a972cff5c630acaf3 Signed-off-by: jihwan.seo Reviewed-on: https://gerrit.iotivity.org/gerrit/13649 Tested-by: jenkins-iotivity Reviewed-by: Larry Sachs Reviewed-by: Jaehong Jo Reviewed-by: Ashok Babu Channa --- android/android_api/base/jni/JniOcPlatform.cpp | 50 +++++++++++++ android/android_api/base/jni/JniOcPlatform.h | 16 ++++ .../main/java/org/iotivity/base/OcPlatform.java | 29 ++++++++ resource/csdk/stack/src/ocstack.c | 2 +- resource/include/IClientWrapper.h | 4 + resource/include/IServerWrapper.h | 4 + resource/include/InProcClientWrapper.h | 3 + resource/include/InProcServerWrapper.h | 5 ++ resource/include/OCPlatform.h | 15 ++++ resource/include/OCPlatform_impl.h | 3 + resource/include/OutOfProcClientWrapper.h | 10 +++ resource/include/OutOfProcServerWrapper.h | 10 +++ resource/include/StringConstants.h | 1 + resource/src/InProcClientWrapper.cpp | 36 +++++++-- resource/src/InProcServerWrapper.cpp | 54 ++++++++++---- resource/src/OCPlatform.cpp | 10 +++ resource/src/OCPlatform_impl.cpp | 86 ++++++++++++++++++++++ 17 files changed, 317 insertions(+), 21 deletions(-) diff --git a/android/android_api/base/jni/JniOcPlatform.cpp b/android/android_api/base/jni/JniOcPlatform.cpp index 8f76dc8..07f6d3e 100644 --- a/android/android_api/base/jni/JniOcPlatform.cpp +++ b/android/android_api/base/jni/JniOcPlatform.cpp @@ -578,6 +578,56 @@ JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_configure /* * Class: org_iotivity_base_OcPlatform +* Method: stop +* Signature: ()V +*/ +JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_stop +(JNIEnv *env, jclass clazz) +{ + LOGI("OcPlatform.stop"); + + try { + OCStackResult result = OCPlatform::stop(); + if (OC_STACK_OK != result) + { + ThrowOcException(result, "Failed to stop ocplatform"); + return; + } + } + catch (OCException& e) + { + LOGE("%s", e.reason().c_str()); + ThrowOcException(e.code(), e.reason().c_str()); + } +} + +/* +* Class: org_iotivity_base_OcPlatform +* Method: start +* Signature: ()V +*/ +JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_start +(JNIEnv *env, jclass clazz) +{ + LOGI("OcPlatform.start"); + + try { + OCStackResult result = OCPlatform::start(); + if (OC_STACK_OK != result) + { + ThrowOcException(result, "Failed to start ocplatform"); + return; + } + } + catch (OCException& e) + { + LOGE("%s", e.reason().c_str()); + ThrowOcException(e.code(), e.reason().c_str()); + } +} + +/* +* Class: org_iotivity_base_OcPlatform * Method: notifyAllObservers0 * Signature: (Lorg/iotivity/base/OcResourceHandle;)V */ diff --git a/android/android_api/base/jni/JniOcPlatform.h b/android/android_api/base/jni/JniOcPlatform.h index cff6800..4a9d134 100644 --- a/android/android_api/base/jni/JniOcPlatform.h +++ b/android/android_api/base/jni/JniOcPlatform.h @@ -85,6 +85,22 @@ extern "C" { /* * Class: org_iotivity_base_OcPlatform + * Method: stop + * Signature: ()V + */ + JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_stop + (JNIEnv *, jclass); + + /* + * Class: org_iotivity_base_OcPlatform + * Method: start + * Signature: ()V + */ + JNIEXPORT void JNICALL Java_org_iotivity_base_OcPlatform_start + (JNIEnv *, jclass); + + /* + * Class: org_iotivity_base_OcPlatform * Method: notifyAllObservers0 * Signature: (Lorg/iotivity/base/OcResourceHandle;)V */ diff --git a/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java b/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java index c62e170..0af5565 100644 --- a/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java +++ b/android/android_api/base/src/main/java/org/iotivity/base/OcPlatform.java @@ -78,6 +78,8 @@ public final class OcPlatform { private static volatile boolean sIsPlatformInitialized = false; private static QualityOfService sPlatformQualityOfService = QualityOfService.NA; + private static volatile boolean sIsStopPlatform = false; + private OcPlatform() { } @@ -90,6 +92,12 @@ public final class OcPlatform { * @param platformConfig platform configuration */ public synchronized static void Configure(PlatformConfig platformConfig) { + if (sIsStopPlatform) + { + OcPlatform.start(); + sIsStopPlatform = false; + } + if (!sIsPlatformInitialized) { CaInterface.initialize(platformConfig.getActivity(), platformConfig.getContext()); @@ -116,6 +124,27 @@ public final class OcPlatform { String dbPath); /** + * API for stop all process of the OcPlatform. + * All of threads and memory will be terminated by this API. + * Iotivity Core can be started again through Configure(PlatformConfig platformConfig) API. + * Both Configure and Shutdown API is filtering for duplicated calling even while processing. + *

+ * Note: This API is for both server and client side. + *

+ */ + public synchronized static void Shutdown() { + if (!sIsStopPlatform) + { + OcPlatform.stop(); + sIsStopPlatform = true; + sIsPlatformInitialized = false; + } + } + + private static native void stop(); + private static native void start(); + + /** * API for notifying base that resource's attributes have changed. *

* Note: This API is for server side only. diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index c89716f..7ff1551 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -2277,7 +2277,7 @@ OCStackResult OCStop() } else if (stackState != OC_STACK_INITIALIZED) { - OIC_LOG(ERROR, TAG, "Stack not initialized"); + OIC_LOG(INFO, TAG, "Stack not initialized"); return OC_STACK_ERROR; } diff --git a/resource/include/IClientWrapper.h b/resource/include/IClientWrapper.h index b453068..d1658c7 100644 --- a/resource/include/IClientWrapper.h +++ b/resource/include/IClientWrapper.h @@ -150,6 +150,10 @@ namespace OC const QueryParamsMap& queryParams, const HeaderOptions& headerOptions, MQTopicCallback& callback, QualityOfService QoS) = 0; #endif + virtual OCStackResult stop() = 0; + + virtual OCStackResult start() = 0; + virtual ~IClientWrapper(){} }; } diff --git a/resource/include/IServerWrapper.h b/resource/include/IServerWrapper.h index d49dc1b..112ced6 100644 --- a/resource/include/IServerWrapper.h +++ b/resource/include/IServerWrapper.h @@ -77,6 +77,10 @@ namespace OC virtual OCStackResult setPropertyValue(OCPayloadType type, const std::string& tag, const std::string& value) = 0; virtual OCStackResult getPropertyValue(OCPayloadType type, const std::string& tag, std::string& value) = 0; + + virtual OCStackResult stop() = 0; + + virtual OCStackResult start() = 0; }; } diff --git a/resource/include/InProcClientWrapper.h b/resource/include/InProcClientWrapper.h index bbf6a38..530b076 100644 --- a/resource/include/InProcClientWrapper.h +++ b/resource/include/InProcClientWrapper.h @@ -227,6 +227,9 @@ namespace OC MQTopicCallback& callback, QualityOfService QoS); #endif + virtual OCStackResult stop(); + virtual OCStackResult start(); + private: void listeningFunc(); std::string assembleSetResourceUri(std::string uri, const QueryParamsMap& queryParams); diff --git a/resource/include/InProcServerWrapper.h b/resource/include/InProcServerWrapper.h index 0ea25e8..e5dc0cd 100644 --- a/resource/include/InProcServerWrapper.h +++ b/resource/include/InProcServerWrapper.h @@ -72,11 +72,16 @@ namespace OC virtual OCStackResult setPropertyValue(OCPayloadType type, const std::string& tag, const std::string& value); virtual OCStackResult getPropertyValue(OCPayloadType type, const std::string& tag, std::string& value); + virtual OCStackResult stop(); + + virtual OCStackResult start(); + private: void processFunc(); std::thread m_processThread; bool m_threadRun; std::weak_ptr m_csdkLock; + PlatformConfig m_cfg; }; } diff --git a/resource/include/OCPlatform.h b/resource/include/OCPlatform.h index 9903611..1adcb82 100644 --- a/resource/include/OCPlatform.h +++ b/resource/include/OCPlatform.h @@ -50,6 +50,21 @@ namespace OC typedef OCDoHandle OCPresenceHandle; /** + * API for stop Base layer including resource and connectivity abstraction. + * + * @return Returns ::OC_STACK_OK if success. + */ + OCStackResult stop(); + + /** + * API for start Base layer including resource and connectivity abstraction. + * OCInit will be invoked. + * + * @return Returns ::OC_STACK_OK if success. + */ + OCStackResult start(); + + /** * API for notifying base that resource's attributes have changed. * * @param resourceHandle resource handle of the resource diff --git a/resource/include/OCPlatform_impl.h b/resource/include/OCPlatform_impl.h index 6adefc7..e20dc7d 100644 --- a/resource/include/OCPlatform_impl.h +++ b/resource/include/OCPlatform_impl.h @@ -269,8 +269,11 @@ namespace OC OCStackResult setDeviceId(const OCUUIdentity *myUuid); + OCStackResult stop(); + OCStackResult start(); private: PlatformConfig m_cfg; + OCMode m_modeType; private: std::unique_ptr m_WrapperInstance; diff --git a/resource/include/OutOfProcClientWrapper.h b/resource/include/OutOfProcClientWrapper.h index c32656c..0fb6fa4 100644 --- a/resource/include/OutOfProcClientWrapper.h +++ b/resource/include/OutOfProcClientWrapper.h @@ -32,6 +32,16 @@ namespace OC PlatformConfig /*cfg*/) {} + virtual OCStackResult stop() + { + return OC_STACK_NOTIMPL; + } + + virtual OCStackResult start() + { + return OC_STACK_NOTIMPL; + } + virtual OCStackResult ListenForResource(const std::string& /*servUrl*/, const std::string& /*rsrcType*/, OCConnectivityType /*connType*/, diff --git a/resource/include/OutOfProcServerWrapper.h b/resource/include/OutOfProcServerWrapper.h index 05d79e4..9f5b21c 100644 --- a/resource/include/OutOfProcServerWrapper.h +++ b/resource/include/OutOfProcServerWrapper.h @@ -31,6 +31,16 @@ namespace OC OutOfProcServerWrapper(PlatformConfig /*cfg*/) {} + virtual OCStackResult stop() + { + return OC_STACK_NOTIMPL; + } + + virtual OCStackResult start() + { + return OC_STACK_NOTIMPL; + } + virtual OCStackResult registerResource( OCResourceHandle& /*resourceHandle*/, std::string& /*resourceURI*/, diff --git a/resource/include/StringConstants.h b/resource/include/StringConstants.h index 4f856c2..177bd1d 100644 --- a/resource/include/StringConstants.h +++ b/resource/include/StringConstants.h @@ -48,6 +48,7 @@ namespace OC static const char UNKNOWN_ERROR[] = "Unknown Error"; static const char STACK_INIT_ERROR[] = "Error Initializing Stack"; + static const char STACK_TERMINATE_ERROR[] = "Error Terminating Stack"; static const char NOT_CONFIGURED_AS_SERVER[] = "Cannot static construct a Server when configured as a client"; static const char INVALID_PARAM[] = "Invalid Param"; diff --git a/resource/src/InProcClientWrapper.cpp b/resource/src/InProcClientWrapper.cpp index ce2fb92..9c63705 100644 --- a/resource/src/InProcClientWrapper.cpp +++ b/resource/src/InProcClientWrapper.cpp @@ -25,6 +25,10 @@ #include "OCResource.h" #include "ocpayload.h" #include +#include "logger.h" + +#define TAG "OIC_CLIENT_WRAPPER" + using namespace std; namespace OC @@ -36,7 +40,17 @@ namespace OC { // if the config type is server, we ought to never get called. If the config type // is both, we count on the server to run the thread and do the initialize + start(); + } + + InProcClientWrapper::~InProcClientWrapper() + { + stop(); + } + OCStackResult InProcClientWrapper::start() + { + OIC_LOG(INFO, TAG, "start ocplatform"); if (m_cfg.mode == ModeType::Client) { OCTransportFlags serverFlags = @@ -50,25 +64,37 @@ namespace OC throw InitializeException(OC::InitException::STACK_INIT_ERROR, result); } - m_threadRun = true; - m_listeningThread = std::thread(&InProcClientWrapper::listeningFunc, this); + if (false == m_threadRun) + { + m_threadRun = true; + m_listeningThread = std::thread(&InProcClientWrapper::listeningFunc, this); + } } + return OC_STACK_OK; } - InProcClientWrapper::~InProcClientWrapper() + OCStackResult InProcClientWrapper::stop() { + OIC_LOG(INFO, TAG, "stop ocplatform"); + if (m_threadRun && m_listeningThread.joinable()) { m_threadRun = false; m_listeningThread.join(); } - // only stop if we are the ones who actually called 'init'. We are counting + // only stop if we are the ones who actually called 'start'. We are counting // on the server to do the stop. if (m_cfg.mode == ModeType::Client) { - OCStop(); + OCStackResult result = OCStop(); + + if (OC_STACK_OK != result) + { + throw InitializeException(OC::InitException::STACK_TERMINATE_ERROR, result); + } } + return OC_STACK_OK; } void InProcClientWrapper::listeningFunc() diff --git a/resource/src/InProcServerWrapper.cpp b/resource/src/InProcServerWrapper.cpp index fb26655..cd762e3 100644 --- a/resource/src/InProcServerWrapper.cpp +++ b/resource/src/InProcServerWrapper.cpp @@ -38,6 +38,9 @@ #include #include #include +#include "logger.h" + +#define TAG "OIC_SERVER_WRAPPER" using namespace std; using namespace OC; @@ -254,19 +257,27 @@ namespace OC { InProcServerWrapper::InProcServerWrapper( std::weak_ptr csdkLock, PlatformConfig cfg) - : m_csdkLock(csdkLock) + : m_csdkLock(csdkLock), + m_cfg { cfg } + { + start(); + } + + OCStackResult InProcServerWrapper::start() { + OIC_LOG(INFO, TAG, "start"); + OCMode initType; - if(cfg.mode == ModeType::Server) + if(m_cfg.mode == ModeType::Server) { initType = OC_SERVER; } - else if (cfg.mode == ModeType::Both) + else if (m_cfg.mode == ModeType::Both) { initType = OC_CLIENT_SERVER; } - else if (cfg.mode == ModeType::Gateway) + else if (m_cfg.mode == ModeType::Gateway) { initType = OC_GATEWAY; } @@ -277,9 +288,9 @@ namespace OC } OCTransportFlags serverFlags = - static_cast(cfg.serverConnectivity & CT_MASK_FLAGS); + static_cast(m_cfg.serverConnectivity & CT_MASK_FLAGS); OCTransportFlags clientFlags = - static_cast(cfg.clientConnectivity & CT_MASK_FLAGS); + static_cast(m_cfg.clientConnectivity & CT_MASK_FLAGS); OCStackResult result = OCInit1(initType, serverFlags, clientFlags); if(OC_STACK_OK != result) @@ -287,8 +298,27 @@ namespace OC throw InitializeException(OC::InitException::STACK_INIT_ERROR, result); } - m_threadRun = true; - m_processThread = std::thread(&InProcServerWrapper::processFunc, this); + if (false == m_threadRun) + { + m_threadRun = true; + m_processThread = std::thread(&InProcServerWrapper::processFunc, this); + } + return OC_STACK_OK; + } + + OCStackResult InProcServerWrapper::stop() + { + OIC_LOG(INFO, TAG, "stop"); + + if(m_processThread.joinable()) + { + m_threadRun = false; + m_processThread.join(); + } + + OCStackResult res = OCStop(); + + return res; } void InProcServerWrapper::processFunc() @@ -626,12 +656,6 @@ namespace OC InProcServerWrapper::~InProcServerWrapper() { - if(m_processThread.joinable()) - { - m_threadRun = false; - m_processThread.join(); - } - - OCStop(); + stop(); } } diff --git a/resource/src/OCPlatform.cpp b/resource/src/OCPlatform.cpp index e9e90a1..c41d665 100644 --- a/resource/src/OCPlatform.cpp +++ b/resource/src/OCPlatform.cpp @@ -37,6 +37,16 @@ namespace OC OCPlatform_impl::Configure(config); } + OCStackResult start() + { + return OCPlatform_impl::Instance().start(); + } + + OCStackResult stop() + { + return OCPlatform_impl::Instance().stop(); + } + OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler) { return OCPlatform_impl::Instance().setDefaultDeviceEntityHandler(entityHandler); diff --git a/resource/src/OCPlatform_impl.cpp b/resource/src/OCPlatform_impl.cpp index a8e8fd3..f23688f 100644 --- a/resource/src/OCPlatform_impl.cpp +++ b/resource/src/OCPlatform_impl.cpp @@ -44,8 +44,11 @@ #include "OCUtilities.h" #include "ocpayload.h" +#include "logger.h" #include "oc_logger.hpp" +#define TAG "OIC_PLATFORM" + namespace OC { @@ -67,22 +70,105 @@ namespace OC return platform; } + OCStackResult OCPlatform_impl::start() + { + OIC_LOG(INFO, TAG, "start"); + + OCStackResult res = OC_STACK_OK; + if (OC_CLIENT == m_modeType) + { + if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::start)) + { + res = OC_STACK_ERROR; + } + } + else if (OC_SERVER == m_modeType) + { + if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::start)) + { + res = OC_STACK_ERROR; + } + } + else if (OC_CLIENT_SERVER == m_modeType || OC_GATEWAY == m_modeType) + { + if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::start)) + { + res = OC_STACK_ERROR; + } + + if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::start)) + { + res = OC_STACK_ERROR; + } + } + else + { + res = OC_STACK_ERROR; + } + + return res; + } + + OCStackResult OCPlatform_impl::stop() + { + OIC_LOG(INFO, TAG, "stop"); + + OCStackResult res = OC_STACK_OK; + if (OC_CLIENT == m_modeType) + { + if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::stop)) + { + res = OC_STACK_ERROR; + } + } + else if (OC_SERVER == m_modeType) + { + if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::stop)) + { + res = OC_STACK_ERROR; + } + } + else if (OC_CLIENT_SERVER == m_modeType) + { + if (OC_STACK_OK != checked_guard(m_client, &IClientWrapper::stop)) + { + res = OC_STACK_ERROR; + } + + if (OC_STACK_OK != checked_guard(m_server, &IServerWrapper::stop)) + { + res = OC_STACK_ERROR; + } + } + else + { + res = OC_STACK_ERROR; + } + + return res; + } + void OCPlatform_impl::init(const PlatformConfig& config) { + OIC_LOG(INFO, TAG, "init"); + switch(config.mode) { case ModeType::Server: m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config); + m_modeType = OC_SERVER; break; case ModeType::Client: m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config); + m_modeType = OC_CLIENT; break; case ModeType::Both: case ModeType::Gateway: m_server = m_WrapperInstance->CreateServerWrapper(m_csdkLock, config); m_client = m_WrapperInstance->CreateClientWrapper(m_csdkLock, config); + m_modeType = OC_CLIENT_SERVER; break; } } -- 2.7.4