Implement JobManager 73/137373/4
authorMu-Woong Lee <muwoong.lee@samsung.com>
Wed, 5 Jul 2017 11:06:27 +0000 (20:06 +0900)
committerMu-Woong Lee <muwoong.lee@samsung.com>
Fri, 7 Jul 2017 04:59:29 +0000 (13:59 +0900)
DB operations are not yet implemented.

Change-Id: I6a776ca0da572cbbb3e8be71095b32f1cb4cc31c
Signed-off-by: Mu-Woong Lee <muwoong.lee@samsung.com>
src/server/JobManager.cpp
src/server/JobManager.h
src/server/JobRunner.cpp [new file with mode: 0644]
src/server/JobRunner.h [new file with mode: 0644]
src/server/MethodCallHandler.cpp
src/shared/JobInfo.cpp
src/shared/JobInfo.h

index 262b4df..3ba3baa 100644 (file)
  * limitations under the License.
  */
 
+#include <ServerUtil.h>
+#include <JobAction.h>
+#include "JobRunner.h"
 #include "JobManager.h"
 
 using namespace ctx;
 
-JobManager::JobManager(uid_t uid)
+JobManager::JobManager(uid_t uid) :
+       __uid(uid)
 {
 }
 
@@ -29,43 +33,245 @@ JobManager::~JobManager()
 bool JobManager::isSupported(JobContext::Type type, const std::string& uri)
 {
        //TODO
-       return false;
+       return true;
 }
 
-int JobManager::addJob(JobInfo* jobInfo)
+int JobManager::addJob(JobInfo* jobInfo, IClient* owner)
 {
-       //TODO
-       delete jobInfo;
-       return E_SUPPORT;
+       if (jobInfo->getType() == JobInfo::Type::PERIODIC)
+               return __addPeriodicJob(static_cast<PeriodicJobInfo*>(jobInfo), owner);
+       else if (jobInfo->getType() == JobInfo::Type::ON_DEMAND)
+               return __addOnDemandJob(static_cast<OnDemandJobInfo*>(jobInfo), owner);
+
+       return E_PARAM;
 }
 
-int JobManager::startJob(int jobId)
+int JobManager::__addPeriodicJob(PeriodicJobInfo* jobInfo, IClient* owner)
 {
-       //TODO
-       return E_SUPPORT;
+       __verifyPeriodicJob(jobInfo, owner);
+
+       const std::string& ownerId = owner->getName();
+       IF_FAIL_RETURN(!ownerId.empty(), E_ACCESS);
+
+       jobInfo->setId(__generateJobId());
+
+       //TODO: insert to the DB, if it is a persistent job
+
+       JobRunner* runner = new JobRunner(jobInfo);
+       __jobRunners[ownerId].push_back(runner);
+
+       return jobInfo->getId();
 }
 
-int JobManager::stopJob(int jobId)
+int JobManager::__addOnDemandJob(OnDemandJobInfo* jobInfo, IClient* owner)
 {
-       //TODO
-       return E_SUPPORT;
+       __verifyOnDemandJob(jobInfo, owner);
+
+       const std::string& ownerId = owner->getName();
+       IF_FAIL_RETURN(!ownerId.empty(), E_ACCESS);
+
+       jobInfo->setId(__generateJobId());
+
+       //TODO: insert to the DB, if it is a persistent job
+
+       JobRunner* runner = new JobRunner(jobInfo);
+       __jobRunners[ownerId].push_back(runner);
+
+       return jobInfo->getId();
 }
 
-int JobManager::removeJob(int jobId)
+int JobManager::startJob(int jobId, IClient* owner)
 {
+       JobRunner* jobRunner = __findJobRunner(owner->getName(), jobId);
+       IF_FAIL_RETURN(jobRunner, E_PARAM);
+
+       if (jobRunner->getJobInfo()->isStarted()) {
+               _D("Job-%d of %s has started already", jobId, owner->getName());
+               return E_RULE_ON;
+       }
+
+       jobRunner->getJobInfo()->setStarted(true);
+
        //TODO
-       return E_SUPPORT;
+
+       return E_NONE;
 }
 
-JobInfo* JobManager::getJob(int jobId)
+int JobManager::stopJob(int jobId, IClient* owner)
 {
+       JobRunner* jobRunner = __findJobRunner(owner->getName(), jobId);
+       IF_FAIL_RETURN(jobRunner, E_PARAM);
+
+       if (!jobRunner->getJobInfo()->isStarted()) {
+               _D("Job-%d of %s has stopped already", jobId, owner->getName());
+               return E_RULE_OFF;
+       }
+
+       jobRunner->getJobInfo()->setStarted(false);
+
        //TODO
-       return NULL;
+
+       return E_NONE;
+}
+
+int JobManager::removeJob(int jobId, IClient* owner)
+{
+       IF_FAIL_RETURN(stopJob(jobId, owner) != E_PARAM, E_PARAM);
+
+       auto& runners = __jobRunners[owner->getName()];
+
+       for (auto iter = runners.begin(); iter != runners.end(); ++iter) {
+               JobRunner* runner = *iter;
+
+               if (runner->getJobInfo()->getId() != jobId)
+                       continue;
+
+               //TODO: delete from the DB
+
+               delete runner;
+               runners.erase(iter);
+
+               break;
+       }
+
+       return E_NONE;
+}
+
+JobInfo* JobManager::getJobInfo(int jobId, IClient* owner)
+{
+       JobRunner* jobRunner = __findJobRunner(owner->getName(), jobId);
+       IF_FAIL_RETURN(jobRunner, NULL);
+
+       return jobRunner->getJobInfo();
 }
 
-std::vector<JobInfo*> JobManager::getAllJob()
+std::vector<JobInfo*> JobManager::getAllJobInfo(IClient* owner)
 {
        std::vector<JobInfo*> jobInfos;
-       //TODO
+
+       auto runnerMapIterator = __jobRunners.find(owner->getName());
+       IF_FAIL_RETURN(runnerMapIterator != __jobRunners.end(), jobInfos);
+
+       for (auto& runner : runnerMapIterator->second) {
+               jobInfos.push_back(runner->getJobInfo());
+       }
+
        return jobInfos;
 }
+
+bool JobManager::__isPermitted(IClient* client, const std::string& uri)
+{
+       //TODO
+       return true;
+}
+
+void JobManager::__verifyPeriodicJob(PeriodicJobInfo* jobInfo, IClient* owner)
+{
+       //TODO: parameter check
+       __verifyRequirements(jobInfo, owner);
+       __verifyAction(jobInfo, owner);
+}
+
+void JobManager::__verifyOnDemandJob(OnDemandJobInfo* jobInfo, IClient* owner)
+{
+       //TODO: parameter check
+       __verifyTriggers(jobInfo, owner);
+       __verifyRequirements(jobInfo, owner);
+       __verifyAction(jobInfo, owner);
+}
+
+void JobManager::__verifyTriggers(OnDemandJobInfo* jobInfo, IClient* owner)
+{
+       for (auto& trig : jobInfo->getTriggers()) {
+               const std::string& uri = trig->getUri();
+               _D("Check %s", uri.c_str());
+
+               if (!isSupported(JobContext::Type::TRIGGER, uri))
+                       throw static_cast<int>(E_SUPPORT);
+
+               if (!__isPermitted(owner, uri))
+                       throw static_cast<int>(E_ACCESS);
+       }
+}
+
+void JobManager::__verifyRequirements(JobInfo* jobInfo, IClient* owner)
+{
+       for (auto& req : jobInfo->getRequirements()) {
+               const std::string& uri = req->getUri();
+               _D("Check %s", uri.c_str());
+
+               if (!isSupported(JobContext::Type::REQUIREMENT, uri))
+                       throw static_cast<int>(E_SUPPORT);
+
+               if (!__isPermitted(owner, uri))
+                       throw static_cast<int>(E_ACCESS);
+       }
+}
+
+void JobManager::__verifyAction(JobInfo* jobInfo, IClient* owner)
+{
+       bool verified = false;
+       JobAction* action = jobInfo->getAction();
+
+       // App Control
+       verified = [&]()->bool {
+               JobAppControl* appControlAction = dynamic_cast<JobAppControl*>(action);
+               IF_FAIL_RETURN(!util::isSystem(__uid), false);
+               IF_FAIL_RETURN(appControlAction, false);
+               IF_FAIL_RETURN(appControlAction->getAppControl(), false);
+               return true;
+       }();
+       if (verified) return;
+
+       // Notification
+       verified = [&]()->bool {
+               JobNotification* notiAction = dynamic_cast<JobNotification*>(action);
+               IF_FAIL_RETURN(!util::isSystem(__uid), false);
+               IF_FAIL_RETURN(notiAction, false);
+               IF_FAIL_RETURN(!(notiAction->getTitle().empty()), false);
+               return true;
+       }();
+       if (verified) return;
+
+       // DBus Method
+       verified = [&]()->bool {
+               JobDBusCall* dbusAction = dynamic_cast<JobDBusCall*>(action);
+               IF_FAIL_RETURN(dbusAction, false);
+               IF_FAIL_RETURN(!(dbusAction->getBusName().empty()), false);
+               IF_FAIL_RETURN(!(dbusAction->getObjectPath().empty()), false);
+               IF_FAIL_RETURN(!(dbusAction->getInterface().empty()), false);
+               IF_FAIL_RETURN(!(dbusAction->getMethodName().empty()), false);
+               return true;
+       }();
+       if (verified) return;
+
+       throw static_cast<int>(E_PARAM);
+}
+
+int JobManager::__generateJobId()
+{
+       static int lastJobId = 0;
+
+       if (lastJobId == 0) {
+               //TODO: get the last "persistent" job id
+       }
+
+       if (++lastJobId < 0)
+               lastJobId = 1;
+
+       return lastJobId;
+}
+
+JobRunner* JobManager::__findJobRunner(const std::string& ownerId, int jobId)
+{
+       auto runnerMapIterator = __jobRunners.find(ownerId);
+       IF_FAIL_RETURN_TAG(runnerMapIterator != __jobRunners.end(), NULL, _I, "%s has no job", ownerId.c_str());
+
+       for (auto& runner : runnerMapIterator->second) {
+               if (runner->getJobInfo()->getId() == jobId)
+                       return runner;
+       }
+
+       _I("%s does not have the Job-%d", ownerId.c_str(), jobId);
+       return NULL;
+}
index f4de4aa..de649ae 100644 (file)
 #define __CONTEXT_JOB_SCHEDULER_JOB_MANAGER_H__
 
 #include <vector>
+#include <map>
 #include <JobInfo.h>
 #include <JobContext.h>
+#include <IClient.h>
 
 namespace ctx {
 
+       class JobRunner;
+
        class JobManager {
        public:
                JobManager(uid_t uid);
@@ -30,13 +34,31 @@ namespace ctx {
 
                bool isSupported(JobContext::Type type, const std::string& uri);
 
-               int addJob(JobInfo* jobInfo);
-               int startJob(int jobId);
-               int stopJob(int jobId);
-               int removeJob(int jobId);
+               int addJob(JobInfo* jobInfo, IClient* owner);
+               int startJob(int jobId, IClient* owner);
+               int stopJob(int jobId, IClient* owner);
+               int removeJob(int jobId, IClient* owner);
+
+               JobInfo* getJobInfo(int jobId, IClient* owner);
+               std::vector<JobInfo*> getAllJobInfo(IClient* owner);
+
+       private:
+               int __addPeriodicJob(PeriodicJobInfo* jobInfo, IClient* owner);
+               int __addOnDemandJob(OnDemandJobInfo* jobInfo, IClient* owner);
+
+               bool __isPermitted(IClient* client, const std::string& uri);
+
+               void __verifyPeriodicJob(PeriodicJobInfo* jobInfo, IClient* owner);
+               void __verifyOnDemandJob(OnDemandJobInfo* jobInfo, IClient* owner);
+               void __verifyTriggers(OnDemandJobInfo* jobInfo, IClient* owner);
+               void __verifyRequirements(JobInfo* jobInfo, IClient* owner);
+               void __verifyAction(JobInfo* jobInfo, IClient* owner);
+
+               int __generateJobId();
+               JobRunner* __findJobRunner(const std::string& ownerId, int jobId);
 
-               JobInfo* getJob(int jobId);
-               std::vector<JobInfo*> getAllJob();
+               uid_t __uid;
+               std::map<std::string, std::vector<JobRunner*>> __jobRunners;
        };
 
 }
diff --git a/src/server/JobRunner.cpp b/src/server/JobRunner.cpp
new file mode 100644 (file)
index 0000000..7c48720
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * 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 "JobRunner.h"
+
+using namespace ctx;
+
+JobRunner::JobRunner(JobInfo* jobInfo) :
+       __jobInfo(jobInfo)
+{
+}
+
+JobInfo* JobRunner::getJobInfo()
+{
+       return __jobInfo;
+}
diff --git a/src/server/JobRunner.h b/src/server/JobRunner.h
new file mode 100644 (file)
index 0000000..b8b6059
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * 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 __CONTEXT_JOB_SCHEDULER_JOB_RUNNER_H__
+#define __CONTEXT_JOB_SCHEDULER_JOB_RUNNER_H__
+
+#include <JobInfo.h>
+
+namespace ctx {
+
+       class JobRunner {
+       public:
+               JobRunner(JobInfo* jobInfo);
+
+               JobInfo* getJobInfo();
+
+       private:
+               JobInfo* __jobInfo;
+       };
+
+}
+
+#endif /* __CONTEXT_JOB_SCHEDULER_JOB_RUNNER_H__ */
index a4d95a6..73b8a63 100644 (file)
@@ -97,12 +97,22 @@ void MethodCallHandler::__addJob(IMethodCall& methodCall)
 
        _SI("Adding %s", jobInfoStr);
 
-       JobManager& manager = __getJobManager();
        JobInfo* jobInfo = JobInfo::deserialize(jobInfoStr);
        IF_FAIL_THROW_TAG(jobInfo, static_cast<int>(E_PARAM), _E, "JobInfo deserialization failed");
 
-       int jobId = manager.addJob(jobInfo);
-       IF_FAIL_THROW(jobId > 0, jobId);
+       int jobId = 0;
+
+       try {
+               jobId = __getJobManager().addJob(jobInfo, __caller);
+       } catch (const int error) {
+               delete jobInfo;
+               throw;
+       }
+
+       if (jobId < 0) {
+               delete jobInfo;
+               throw jobId;
+       }
 
        _I("Added Job-%d", jobId);
 
@@ -116,7 +126,7 @@ void MethodCallHandler::__startJob(IMethodCall& methodCall)
 
        _I("Starting Job-%d", jobId);
 
-       int err = __getJobManager().startJob(jobId);
+       int err = __getJobManager().startJob(jobId, __caller);
        IF_FAIL_THROW(IS_SUCCESS(err), err);
 
        methodCall.reply(E_NONE);
@@ -129,7 +139,7 @@ void MethodCallHandler::__stopJob(IMethodCall& methodCall)
 
        _I("Stopping Job-%d", jobId);
 
-       int err = __getJobManager().stopJob(jobId);
+       int err = __getJobManager().stopJob(jobId, __caller);
        IF_FAIL_THROW(IS_SUCCESS(err), err);
 
        methodCall.reply(E_NONE);
@@ -142,7 +152,7 @@ void MethodCallHandler::__removeJob(IMethodCall& methodCall)
 
        _I("Removing Job-%d", jobId);
 
-       int err = __getJobManager().removeJob(jobId);
+       int err = __getJobManager().removeJob(jobId, __caller);
        IF_FAIL_THROW(IS_SUCCESS(err), err);
 
        methodCall.reply(E_NONE);
@@ -155,7 +165,7 @@ void MethodCallHandler::__getJob(IMethodCall& methodCall)
 
        _I("Retrieving Job-%d", jobId);
 
-       JobInfo* jobInfo = __getJobManager().getJob(jobId);
+       JobInfo* jobInfo = __getJobManager().getJobInfo(jobId, __caller);
        IF_FAIL_THROW(jobInfo, static_cast<int>(E_PARAM));
 
        methodCall.reply(g_variant_new("(s)", jobInfo->serialize().c_str()));
@@ -167,7 +177,7 @@ void MethodCallHandler::__getAllJob(IMethodCall& methodCall)
 {
        _I("Retrieving all jobs");
 
-       std::vector<JobInfo*> jobInfos = __getJobManager().getAllJob();
+       std::vector<JobInfo*> jobInfos = __getJobManager().getAllJobInfo(__caller);
        IF_FAIL_THROW(!jobInfos.empty(), static_cast<int>(E_NO_DATA));
 
        GVariantBuilder builder;
index 7f33549..5ac127d 100644 (file)
@@ -119,6 +119,11 @@ JobInfo& JobInfo::addRequirement(JobRequirement* req)
        return *this;
 }
 
+std::list<JobRequirement*>& JobInfo::getRequirements()
+{
+       return __requirements;
+}
+
 JobInfo& JobInfo::setAction(JobAction* action)
 {
        if (__action)
@@ -129,6 +134,11 @@ JobInfo& JobInfo::setAction(JobAction* action)
        return *this;
 }
 
+JobAction* JobInfo::getAction()
+{
+       return __action;
+}
+
 std::string JobInfo::serialize()
 {
        Json::Value jsonRoot;
@@ -278,6 +288,11 @@ OnDemandJobInfo& OnDemandJobInfo::addTrigger(JobTrigger* trigger)
        return *this;
 }
 
+std::list<JobTrigger*>& OnDemandJobInfo::getTriggers()
+{
+       return __triggers;
+}
+
 void OnDemandJobInfo::__toJson(Json::Value& jsonRoot)
 {
        for (auto& trig : __triggers) {
index 58aa723..bec3e82 100644 (file)
@@ -53,7 +53,10 @@ namespace ctx {
                JobInfo& setUserData(const std::string& userData);
 
                JobInfo& addRequirement(JobRequirement* req);
+               std::list<JobRequirement*>& getRequirements();
+
                JobInfo& setAction(JobAction* action);
+               JobAction* getAction();
 
                std::string serialize();
                void toJson(Json::Value& jsonRoot);
@@ -118,6 +121,7 @@ namespace ctx {
                JobInfo::Type getType();
 
                OnDemandJobInfo& addTrigger(JobTrigger* trigger);
+               std::list<JobTrigger*>& getTriggers();
 
        private:
                void __toJson(Json::Value& jsonRoot);