* 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)
{
}
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;
+}
#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);
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;
};
}
_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);
_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);
_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);
_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);
_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()));
{
_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;