From: coderhyme
Date: Fri, 5 Feb 2016 02:42:12 +0000 (-0800)
Subject: Added SeparateResponse class for the RCSResourceObject in RE.
X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=61ff7411a690309b4832e1e639689f30b0e4b8e8;p=contrib%2Fiotivity.git
Added SeparateResponse class for the RCSResourceObject in RE.
The class is to support the SLOW response concept of the base.
For it, the RCSRequest now holds its owner resource object.
- how to use
RCSSeparateResponse separateResponse;
...
server->setSetRequestHandler([](const RCSRequest& r, RCSResourceAttributes& attrs){
// make separate response to set result later
separateResponse = RCSSeparateResponse(r);
return RCSSetResponse::separate();
});
...
// the set method will throw an exception when the operation is failed.
separateResponse.set();
Change-Id: I054ee3948d7742b5c45f821f3fec48216915f273
Signed-off-by: coderhyme
Reviewed-on: https://gerrit.iotivity.org/gerrit/4947
Tested-by: jenkins-iotivity
Reviewed-by: Madan Lanka
Reviewed-by: JungYong KIM
Reviewed-by: Uze Choi
---
diff --git a/service/resource-encapsulation/include/RCSRequest.h b/service/resource-encapsulation/include/RCSRequest.h
index 0b45032..eb5a350 100644
--- a/service/resource-encapsulation/include/RCSRequest.h
+++ b/service/resource-encapsulation/include/RCSRequest.h
@@ -38,38 +38,44 @@ namespace OIC
{
namespace Service
{
+ class RCSResourceObject;
+
/**
* This class describes the request.
*
*/
class RCSRequest
{
- public:
- /**
- * Constructor to set resource URI.
- *
- * @param resourceUri URI of the resource for which the request is generated.
- */
- explicit RCSRequest(const std::string& resourceUri);
+ public:
+ RCSRequest() = default;
+
+ /**
+ * Constructor to set resource URI.
+ *
+ * @param resourceUri URI of the resource for which the request is generated.
+ */
+ explicit RCSRequest(const std::string& resourceUri);
- explicit RCSRequest(const std::shared_ptr< OC::OCResourceRequest >&);
+ RCSRequest(const std::shared_ptr< RCSResourceObject >&,
+ const std::shared_ptr< OC::OCResourceRequest >&);
- RCSRequest &operator=(RCSRequest &) = delete;
+ std::weak_ptr< RCSResourceObject > getResourceObject() const noexcept;
- /**
- * @return Returns the URI of the request.
- *
- */
- std::string getResourceUri() const;
+ /**
+ * @return Returns the URI of the request.
+ *
+ */
+ std::string getResourceUri() const;
- const std::shared_ptr< OC::OCResourceRequest >& getOCRequest() const;
+ const std::shared_ptr< OC::OCResourceRequest >& getOCRequest() const noexcept;
- const std::map< std::string, std::string >& getQueryParams() const;
+ const std::map< std::string, std::string >& getQueryParams() const;
- std::string getInterface() const;
+ std::string getInterface() const;
- private:
- const std::shared_ptr< OC::OCResourceRequest > m_ocRequest;
+ private:
+ std::weak_ptr< RCSResourceObject > m_resourceObject;
+ std::shared_ptr< OC::OCResourceRequest > m_ocRequest;
};
}
diff --git a/service/resource-encapsulation/include/RCSResourceObject.h b/service/resource-encapsulation/include/RCSResourceObject.h
index 146ca8f..9eb4543 100644
--- a/service/resource-encapsulation/include/RCSResourceObject.h
+++ b/service/resource-encapsulation/include/RCSResourceObject.h
@@ -77,7 +77,7 @@ namespace OIC
* in instead of overriding SetRequestHandler.
*
*/
- class RCSResourceObject
+ class RCSResourceObject : public std::enable_shared_from_this< RCSResourceObject >
{
private:
class WeakGuard;
@@ -470,7 +470,8 @@ namespace OIC
private:
RCSResourceObject(const std::string&, uint8_t, RCSResourceAttributes&&);
- OCEntityHandlerResult entityHandler(const std::shared_ptr< OC::OCResourceRequest >&);
+ static OCEntityHandlerResult entityHandler(const std::weak_ptr< RCSResourceObject >&,
+ const std::shared_ptr< OC::OCResourceRequest >&);
OCEntityHandlerResult handleRequest(const std::shared_ptr< OC::OCResourceRequest >&);
OCEntityHandlerResult handleRequestGet(const std::shared_ptr< OC::OCResourceRequest >&);
diff --git a/service/resource-encapsulation/include/RCSResponse.h b/service/resource-encapsulation/include/RCSResponse.h
index 13d94c2..041a187 100644
--- a/service/resource-encapsulation/include/RCSResponse.h
+++ b/service/resource-encapsulation/include/RCSResponse.h
@@ -127,11 +127,16 @@ namespace OIC
*/
static RCSGetResponse create(RCSResourceAttributes&& attrs, int errorCode);
+ static RCSGetResponse separate();
+
+ bool isSeparate() const;
+
//! @cond
RequestHandler* getHandler() const;
//! @endcond
private:
+ RCSGetResponse();
RCSGetResponse(std::shared_ptr< RequestHandler >&&);
private:
@@ -289,6 +294,9 @@ namespace OIC
*/
static RCSSetResponse create(RCSResourceAttributes&& attrs, int errorCode);
+ static RCSSetResponse separate();
+
+ bool isSeparate() const;
//! @cond
SetRequestHandler* getHandler() const;
@@ -313,6 +321,7 @@ namespace OIC
RCSSetResponse& setAcceptanceMethod(AcceptanceMethod method);
private:
+ RCSSetResponse();
RCSSetResponse(std::shared_ptr< SetRequestHandler >&&);
RCSSetResponse(std::shared_ptr< SetRequestHandler >&&, AcceptanceMethod);
diff --git a/service/resource-encapsulation/include/RCSSeparateResponse.h b/service/resource-encapsulation/include/RCSSeparateResponse.h
new file mode 100755
index 0000000..b23cea5
--- /dev/null
+++ b/service/resource-encapsulation/include/RCSSeparateResponse.h
@@ -0,0 +1,56 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef SERVERBUILDER_RCSSEPARATERESPONSE_H
+#define SERVERBUILDER_RCSSEPARATERESPONSE_H
+
+#include "RCSRequest.h"
+
+namespace OIC
+{
+ namespace Service
+ {
+ class RCSResourceAttributes;
+ class RCSRequest;
+
+ class RCSSeparateResponse
+ {
+ public:
+ explicit RCSSeparateResponse(const RCSRequest&);
+ explicit RCSSeparateResponse(RCSRequest&&);
+
+ RCSSeparateResponse(const RCSSeparateResponse&) = delete;
+ RCSSeparateResponse& operator=(const RCSSeparateResponse&) = delete;
+
+ RCSSeparateResponse(RCSSeparateResponse&&) = default;
+ RCSSeparateResponse& operator=(RCSSeparateResponse&&) =default;
+
+ void set();
+
+ private:
+ RCSRequest m_request;
+
+ bool m_done;
+ };
+
+ }
+}
+
+#endif // SERVERBUILDER_RCSSEPARATERESPONSE_H
diff --git a/service/resource-encapsulation/src/serverBuilder/src/RCSRequest.cpp b/service/resource-encapsulation/src/serverBuilder/src/RCSRequest.cpp
index b6d5dfc..88513af 100644
--- a/service/resource-encapsulation/src/serverBuilder/src/RCSRequest.cpp
+++ b/service/resource-encapsulation/src/serverBuilder/src/RCSRequest.cpp
@@ -27,7 +27,9 @@ namespace OIC
namespace Service
{
- RCSRequest::RCSRequest(const std::shared_ptr< OC::OCResourceRequest >& ocRequest) :
+ RCSRequest::RCSRequest(const std::shared_ptr< RCSResourceObject >& resourceObject,
+ const std::shared_ptr< OC::OCResourceRequest >& ocRequest) :
+ m_resourceObject{ resourceObject },
m_ocRequest{ ocRequest }
{
}
@@ -38,12 +40,18 @@ namespace OIC
m_ocRequest->setResourceUri(resourceUri);
}
+
+ std::weak_ptr< RCSResourceObject > RCSRequest::getResourceObject() const noexcept
+ {
+ return m_resourceObject;
+ }
+
std::string RCSRequest::getResourceUri() const
{
return m_ocRequest->getResourceUri();
}
- const std::shared_ptr< OC::OCResourceRequest >& RCSRequest::getOCRequest() const
+ const std::shared_ptr< OC::OCResourceRequest >& RCSRequest::getOCRequest() const noexcept
{
return m_ocRequest;
}
@@ -63,5 +71,6 @@ namespace OIC
return it->second;
}
+
}
}
diff --git a/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp b/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp
index 5b4c8b7..feb2068 100644
--- a/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp
+++ b/service/resource-encapsulation/src/serverBuilder/src/RCSResourceObject.cpp
@@ -100,13 +100,13 @@ namespace
template< typename HANDLER, typename RESPONSE =
typename std::decay::type::result_type >
- RESPONSE invokeHandler(RCSResourceAttributes& attrs,
+ RESPONSE invokeHandler(const RCSResourceObject::Ptr& resObj, RCSResourceAttributes& attrs,
const std::shared_ptr< OC::OCResourceRequest >& ocRequest,
std::shared_ptr< HANDLER > handler)
{
if (handler)
{
- return (*handler)(RCSRequest{ ocRequest }, attrs);
+ return (*handler)(RCSRequest{ resObj, ocRequest }, attrs);
}
return RESPONSE::defaultAction();
@@ -240,7 +240,7 @@ namespace OIC
new RCSResourceObject{ m_uri, m_properties, std::move(m_resourceAttributes) } };
OC::EntityHandler entityHandler{ std::bind(&RCSResourceObject::entityHandler,
- server.get(), std::placeholders::_1) };
+ std::weak_ptr< RCSResourceObject >{ server }, std::placeholders::_1) };
typedef OCStackResult (*RegisterResource)(OCResourceHandle&, std::string&,
const std::string&, const std::string&, OC::EntityHandler, uint8_t);
@@ -535,6 +535,7 @@ namespace OIC
RCSRepresentation RCSResourceObject::toRepresentation() const
{
+ WeakGuard lock{*this};
return RCSRepresentation{ m_uri, m_interfaces, m_types, m_resourceAttributes };
}
@@ -554,8 +555,13 @@ namespace OIC
}
OCEntityHandlerResult RCSResourceObject::entityHandler(
+ const std::weak_ptr< RCSResourceObject >& weakRes,
const std::shared_ptr< OC::OCResourceRequest >& request)
{
+ auto resource = weakRes.lock();
+
+ if (!resource) return OC_EH_ERROR;
+
OIC_LOG(WARNING, LOG_TAG, "entityHandler");
if (!request)
{
@@ -566,12 +572,12 @@ namespace OIC
{
if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::RequestFlag)
{
- return handleRequest(request);
+ return resource->handleRequest(request);
}
if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::ObserverFlag)
{
- return handleObserve(request);
+ return resource->handleObserve(request);
}
}
catch (const std::exception& e)
@@ -618,7 +624,11 @@ namespace OIC
auto attrs = getAttributesFromOCRequest(request);
- return sendResponse(*this, request, invokeHandler(attrs, request, m_getRequestHandler));
+ auto response = invokeHandler(shared_from_this(), attrs, request, m_getRequestHandler);
+
+ if (response.isSeparate()) return OC_EH_SLOW;
+
+ return sendResponse(*this, request, response);
}
bool RCSResourceObject::applyAcceptanceMethod(const RCSSetResponse& response,
@@ -660,7 +670,9 @@ namespace OIC
assert(request != nullptr);
auto attrs = getAttributesFromOCRequest(request);
- auto response = invokeHandler(attrs, request, m_setRequestHandler);
+ auto response = invokeHandler(shared_from_this(), attrs, request, m_setRequestHandler);
+
+ if (response.isSeparate()) return OC_EH_SLOW;
auto attrsChanged = applyAcceptanceMethod(response, attrs);
diff --git a/service/resource-encapsulation/src/serverBuilder/src/RCSResponse.cpp b/service/resource-encapsulation/src/serverBuilder/src/RCSResponse.cpp
index 9a91c61..79d42c3 100644
--- a/service/resource-encapsulation/src/serverBuilder/src/RCSResponse.cpp
+++ b/service/resource-encapsulation/src/serverBuilder/src/RCSResponse.cpp
@@ -61,6 +61,20 @@ namespace OIC
std::move(attrs), errorCode) };
}
+ RCSGetResponse RCSGetResponse::separate()
+ {
+ return RCSGetResponse();
+ }
+
+ bool RCSGetResponse::isSeparate() const
+ {
+ return !m_handler;
+ }
+
+ RCSGetResponse::RCSGetResponse()
+ {
+ }
+
RCSGetResponse::RCSGetResponse(std::shared_ptr< RequestHandler >&& handler) :
m_handler{ std::move(handler) }
{
@@ -123,6 +137,16 @@ namespace OIC
return std::make_shared< SetRequestHandler >(std::move(attrs), errorCode);
}
+ RCSSetResponse RCSSetResponse::separate()
+ {
+ return RCSSetResponse();
+ }
+
+ RCSSetResponse::RCSSetResponse() :
+ m_acceptanceMethod { AcceptanceMethod::DEFAULT }
+ {
+ }
+
RCSSetResponse::RCSSetResponse(std::shared_ptr< SetRequestHandler >&& handler) :
m_acceptanceMethod { AcceptanceMethod::DEFAULT },
m_handler{ std::move(handler) }
@@ -137,6 +161,12 @@ namespace OIC
assert(m_handler);
}
+ bool RCSSetResponse::isSeparate() const
+ {
+ return !m_handler;
+ }
+
+
SetRequestHandler* RCSSetResponse::getHandler() const
{
return m_handler.get();
diff --git a/service/resource-encapsulation/src/serverBuilder/src/RCSSeparateResponse.cpp b/service/resource-encapsulation/src/serverBuilder/src/RCSSeparateResponse.cpp
new file mode 100755
index 0000000..98001e8
--- /dev/null
+++ b/service/resource-encapsulation/src/serverBuilder/src/RCSSeparateResponse.cpp
@@ -0,0 +1,93 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics 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 "RCSSeparateResponse.h"
+
+#include "RCSRequest.h"
+#include "RCSResourceObject.h"
+#include "RCSRepresentation.h"
+#include "AssertUtils.h"
+
+#include "OCPlatform.h"
+#include "OCResourceResponse.h"
+#include "OCResourceRequest.h"
+
+namespace OIC
+{
+ namespace Service
+ {
+
+ namespace
+ {
+ void validateRequest(const RCSRequest& request)
+ {
+ if (!request.getOCRequest() || request.getResourceObject().expired())
+ {
+ throw RCSInvalidParameterException{
+ "The request is incomplete. The resource for the request might be destroyed." };
+ }
+ }
+ }
+
+ RCSSeparateResponse::RCSSeparateResponse(const RCSRequest& request) :
+ m_request{ request },
+ m_done{ false }
+ {
+ validateRequest(m_request);
+ }
+
+ RCSSeparateResponse::RCSSeparateResponse(RCSRequest&& request) :
+ m_request{ std::move(request) },
+ m_done{ false }
+ {
+ validateRequest(m_request);
+ }
+
+ void RCSSeparateResponse::set()
+ {
+ assert(m_request.getOCRequest());
+
+ auto resObj = m_request.getResourceObject().lock();
+ if (!resObj)
+ {
+ throw RCSBadRequestException{ "ResourceObject is unspecified(or destroyed)!" };
+ }
+
+ if (m_done) throw RCSBadRequestException{ "The response is already set!" };
+
+ auto ocRequest = m_request.getOCRequest();
+ auto response = std::make_shared< OC::OCResourceResponse >();
+
+ response->setRequestHandle(ocRequest->getRequestHandle());
+ response->setResourceHandle(ocRequest->getResourceHandle());
+
+ response->setResponseResult(OC_EH_OK);
+
+ // TODO the response should be different by the request interface.
+ response->setResourceRepresentation(
+ RCSRepresentation::toOCRepresentation(resObj->toRepresentation()));
+
+ invokeOCFunc(OC::OCPlatform::sendResponse, response);
+
+ m_done = true;
+ }
+
+ }
+}
diff --git a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp
index a4ed8a3..52ee306 100644
--- a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp
+++ b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResourceObjectTest.cpp
@@ -21,6 +21,8 @@
#include "UnitTestHelper.h"
#include "RCSResourceObject.h"
+#include "RCSRequest.h"
+#include "RCSSeparateResponse.h"
#include "OCPlatform.h"
@@ -479,6 +481,54 @@ TEST_F(ResourceObjectHandlingRequestTest, SendSetResponseWithCustomAttrs)
ASSERT_EQ(OC_EH_OK, handler(createRequest(OC_REST_POST)));
}
+TEST_F(ResourceObjectHandlingRequestTest, SeparateResponseIsSlowResponse)
+{
+ server->setGetRequestHandler(
+ [](const RCSRequest&, RCSResourceAttributes&) -> RCSGetResponse
+ {
+ return RCSGetResponse::separate();
+ }
+ );
+
+ ASSERT_EQ(OC_EH_SLOW, handler(createRequest()));
+}
+
+TEST_F(ResourceObjectHandlingRequestTest, SetMethodOfSeparateResponseInvokesSendResponse)
+{
+ RCSRequest aRequest;
+ server->setGetRequestHandler(
+ [&aRequest](const RCSRequest& request, RCSResourceAttributes&) -> RCSGetResponse
+ {
+ aRequest = request;
+ return RCSGetResponse::separate();
+ }
+ );
+ handler(createRequest(OC_REST_GET));
+
+ mocks.ExpectCallFunc(OCPlatform::sendResponse).Return(OC_STACK_OK);
+
+ RCSSeparateResponse(aRequest).set();
+}
+
+
+TEST_F(ResourceObjectHandlingRequestTest, SetMethodOfSeparateResponseThrowsIfTheResourceIsDestroyed)
+{
+ RCSRequest aRequest;
+ server->setGetRequestHandler(
+ [&aRequest](const RCSRequest& request, RCSResourceAttributes&) -> RCSGetResponse
+ {
+ aRequest = request;
+ return RCSGetResponse::separate();
+ }
+ );
+ handler(createRequest(OC_REST_GET));
+
+ RCSSeparateResponse resp(aRequest);
+
+ server.reset();
+
+ EXPECT_THROW(resp.set(), RCSBadRequestException);
+}
class SetRequestHandlerPolicyTest: public ResourceObjectHandlingRequestTest
diff --git a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp
index 2ba3817..d76184e 100644
--- a/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp
+++ b/service/resource-encapsulation/src/serverBuilder/unittests/RCSResponseTest.cpp
@@ -18,15 +18,17 @@
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#include
+#include "UnitTestHelper.h"
-#include
-#include
+#include "RCSRequest.h"
+#include "RCSResponse.h"
+#include "RCSSeparateResponse.h"
+#include "RCSResourceObject.h"
-#include
-#include
+#include "RequestHandler.h"
+#include "ResourceAttributesConverter.h"
-#include
+#include "OCPlatform.h"
using namespace std;
@@ -185,3 +187,16 @@ TEST_F(RCSResponseTest, SetResponseHasMethodSetBySetter)
EXPECT_EQ(method, response.getAcceptanceMethod());
}
+
+TEST_F(RCSResponseTest, SeparateResponseHasNoHandler)
+{
+ RCSGetResponse response = RCSGetResponse::separate();
+ EXPECT_EQ(nullptr, response.getHandler());
+}
+
+TEST_F(RCSResponseTest, ThrowIfRequestIsInvalidWhenConstructingSeparateResponse)
+{
+ RCSRequest aRequest;
+
+ EXPECT_THROW(RCSSeparateResponse resp(aRequest), RCSInvalidParameterException);
+}