Each provider handler is self-destructed if there is no remaining request 72/67672/1
authorMu-Woong Lee <muwoong.lee@samsung.com>
Thu, 28 Apr 2016 02:56:00 +0000 (11:56 +0900)
committerMu-Woong Lee <muwoong.lee@samsung.com>
Thu, 28 Apr 2016 02:56:00 +0000 (11:56 +0900)
Change-Id: I688b0bd36cd56eb91e754d2a5acd55ab14996557
Signed-off-by: Mu-Woong Lee <muwoong.lee@samsung.com>
src/ProviderHandler.cpp
src/ProviderHandler.h
src/ProviderLoader.cpp

index a9521a2..c7ab57e 100644 (file)
 #include "Request.h"
 #include "ProviderHandler.h"
 
+#define DELETE_DELAY 10
+
 using namespace ctx;
 
 std::map<std::string, ProviderHandler*> ProviderHandler::__instanceMap;
 
-ProviderHandler::ProviderHandler(const char *subject) :
-       __subject(subject)
+ProviderHandler::ProviderHandler(const std::string &subject) :
+       __subject(subject),
+       __deleteScheduled(false)
 {
+       _D("Subject: %s", __subject.c_str());
 }
 
 ProviderHandler::~ProviderHandler()
 {
+       _D("Subject: %s", __subject.c_str());
+
        for (RequestInfo*& info : __subscribeRequests) {
                delete info;
        }
@@ -45,7 +51,7 @@ ProviderHandler::~ProviderHandler()
 }
 
 /* TODO: Return proper error code */
-ProviderHandler* ProviderHandler::getInstance(const char *subject, bool force)
+ProviderHandler* ProviderHandler::getInstance(std::string subject, bool force)
 {
        InstanceMap::iterator it = __instanceMap.find(subject);
 
@@ -99,7 +105,7 @@ bool ProviderHandler::isAllowed(const Credentials *creds)
 
 void ProviderHandler::subscribe(RequestInfo *request)
 {
-       _I(CYAN("'%s' subscribes '%s' (RID-%d)"), request->getClient(), __subject, request->getId());
+       _I(CYAN("'%s' subscribes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
 
        Json requestResult;
        int error = __provider->subscribe(request->getDescription().str(), &requestResult);
@@ -114,7 +120,7 @@ void ProviderHandler::subscribe(RequestInfo *request)
 
 void ProviderHandler::unsubscribe(RequestInfo *request)
 {
-       _I(CYAN("'%s' unsubscribes '%s' (RID-%d)"), request->getClient(), __subject, request->getId());
+       _I(CYAN("'%s' unsubscribes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
 
        /* Search the subscribe request to be removed */
        auto target = __findRequest(__subscribeRequests, request->getClient(), request->getId());
@@ -145,11 +151,14 @@ void ProviderHandler::unsubscribe(RequestInfo *request)
        request->reply(error);
        delete request;
        delete reqFound;
+
+       /* If idle, self destruct */
+       __scheduleToDelete();
 }
 
 void ProviderHandler::read(RequestInfo *request)
 {
-       _I(CYAN("'%s' reads '%s' (RID-%d)"), request->getClient(), __subject, request->getId());
+       _I(CYAN("'%s' reads '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
 
        Json requestResult;
        int error = __provider->read(request->getDescription().str(), &requestResult);
@@ -164,13 +173,16 @@ void ProviderHandler::read(RequestInfo *request)
 
 void ProviderHandler::write(RequestInfo *request)
 {
-       _I(CYAN("'%s' writes '%s' (RID-%d)"), request->getClient(), __subject, request->getId());
+       _I(CYAN("'%s' writes '%s' (RID-%d)"), request->getClient(), __subject.c_str(), request->getId());
 
        Json requestResult;
        int error = __provider->write(request->getDescription(), &requestResult);
 
        request->reply(error, requestResult);
        delete request;
+
+       /* If idle, self destruct */
+       __scheduleToDelete();
 }
 
 bool ProviderHandler::publish(Json &option, int error, Json &dataUpdated)
@@ -205,15 +217,46 @@ bool ProviderHandler::replyToRead(Json &option, int error, Json &dataRead)
                __readRequests.erase(prev);
        }
 
+       /* If idle, self destruct */
+       __scheduleToDelete();
+
        return true;
 }
 
 bool ProviderHandler::__loadProvider()
 {
-       __provider = __loader.load(__subject);
+       __provider = __loader.load(__subject.c_str());
        return (__provider != NULL);
 }
 
+bool ProviderHandler::__idle()
+{
+       return __subscribeRequests.empty() && __readRequests.empty();
+}
+
+void ProviderHandler::__scheduleToDelete()
+{
+       if (!__deleteScheduled && __idle()) {
+               __deleteScheduled = true;
+               g_timeout_add_seconds(DELETE_DELAY, __deletor, this);
+               _D("Delete scheduled for '%s' (%#x)", __subject.c_str(), this);
+       }
+}
+
+gboolean ProviderHandler::__deletor(gpointer data)
+{
+       ProviderHandler *handle = static_cast<ProviderHandler*>(data);
+
+       if (handle->__idle()) {
+               __instanceMap.erase(handle->__subject);
+               delete handle;
+               return FALSE;
+       }
+
+       handle->__deleteScheduled = false;
+       return FALSE;
+}
+
 ProviderHandler::RequestList::iterator
 ProviderHandler::__findRequest(RequestList &reqList, Json &option)
 {
index 634819e..a86e2ef 100644 (file)
@@ -44,26 +44,32 @@ namespace ctx {
                bool publish(ctx::Json &option, int error, ctx::Json &dataUpdated);
                bool replyToRead(ctx::Json &option, int error, ctx::Json &dataRead);
 
-               static ProviderHandler* getInstance(const char *subject, bool force);
+               static ProviderHandler* getInstance(std::string subject, bool force);
                static void purge();
 
        private:
-               const char *__subject;
+               std::string __subject;
                ContextProvider *__provider;
                RequestList __subscribeRequests;
                RequestList __readRequests;
                ProviderLoader __loader;
+               bool __deleteScheduled;
 
                static InstanceMap __instanceMap;
 
-               ProviderHandler(const char *subject);
+               ProviderHandler(const std::string &subject);
                ~ProviderHandler();
 
                bool __loadProvider();
+               bool __idle();
+               void __scheduleToDelete();
+
                RequestList::iterator __findRequest(RequestList &reqList, Json &option);
                RequestList::iterator __findRequest(RequestList &reqList, std::string client, int reqId);
                RequestList::iterator __findRequest(RequestList::iterator begin, RequestList::iterator end, Json &option);
 
+               static gboolean __deletor(gpointer data);
+
        };      /* class ProviderHandler */
 
 }      /* namespace ctx */
index e99ba10..b84ae93 100644 (file)
@@ -55,7 +55,7 @@ ContextProvider* ProviderLoader::load(const char *subject)
 
 ContextProvider* ProviderLoader::__load(const char *soPath, const char *subject)
 {
-       _I("Load '%s' from '%s'", subject, soPath);
+       _SI("Load '%s' from '%s'", subject, soPath);
 
        __soHandle = dlopen(soPath, RTLD_LAZY | RTLD_GLOBAL);
        IF_FAIL_RETURN_TAG(__soHandle, NULL, _E, "%s", dlerror());