Modify the jobId generation logic to produce unique IDs across all users 88/138688/3
authorMu-Woong Lee <muwoong.lee@samsung.com>
Thu, 13 Jul 2017 08:14:50 +0000 (17:14 +0900)
committerMu-Woong Lee <muwoong.lee@samsung.com>
Fri, 14 Jul 2017 10:12:44 +0000 (10:12 +0000)
If a jobId has been returned by removing a job, the same ID can be used later.

Change-Id: Ib2d36d03c5bbc78eedbce28e60f227310cd1fc2f
Signed-off-by: Mu-Woong Lee <muwoong.lee@samsung.com>
src/server/JobInfoDatabase.cpp
src/server/JobInfoDatabase.h
src/server/JobManager.cpp
src/server/JobManager.h

index 19de08b43df6a7ca80a046db0e7fac44f72bc1e6..c36e36dd33f53bb24db018a0c9cd7ecf021f061f 100644 (file)
@@ -21,6 +21,7 @@
 
 #define DB_NAME                        "context-job-scheduler"
 #define JOB_INFO_TABLE "PersistentJobInfo"
+#define USED_ID_TABLE  "UsedJobId"
 #define ST_STARTED             "started"
 
 using namespace ctx;
@@ -36,15 +37,31 @@ static const char* __get_table_name(uid_t uid)
        return tableName;
 }
 
-static void __init_database(uid_t uid)
+static void __create_used_id_table()
 {
+       __database->execute(
+                       "CREATE TABLE IF NOT EXISTS " USED_ID_TABLE " (jobId INTEGER PRIMARY KEY)",
+                       NULL);
+}
+
+static void __create_job_info_table(uid_t uid)
+{
+       const char* tableName = __get_table_name(uid);
        char* query = sqlite3_mprintf(
                        "CREATE TABLE IF NOT EXISTS [%s] (" \
                                "jobId INTEGER NOT NULL PRIMARY KEY," \
                                "owner TEXT NOT NULL," \
                                "jobInfo TEXT NOT NULL," \
-                               "state TEXT NOT NULL DEFAULT ''" \
-                       ")", __get_table_name(uid));
+                               "state TEXT NOT NULL DEFAULT ''); " \
+                       "CREATE TRIGGER IF NOT EXISTS [%s_Insert] AFTER INSERT ON [%s] " \
+                       "BEGIN " \
+                               "INSERT INTO " USED_ID_TABLE " (jobId) VALUES (NEW.jobId); " \
+                       "END; " \
+                       "CREATE TRIGGER IF NOT EXISTS [%s_Delete] AFTER DELETE ON [%s] " \
+                       "BEGIN " \
+                               "DELETE FROM " USED_ID_TABLE " WHERE (jobId = OLD.jobId); " \
+                       "END;",
+                       tableName, tableName, tableName, tableName, tableName);
 
        __database->execute(query, NULL);
 
@@ -62,9 +79,11 @@ static bool __open(uid_t uid)
                        _E("DB open failed");
                        return false;
                }
+
+               __create_used_id_table();
        }
 
-       __init_database(uid);
+       __create_job_info_table(uid);
 
        ++__numDBConnection;
        return true;
@@ -157,3 +176,12 @@ std::vector<std::pair<std::string, JobInfo*>> JobInfoDatabase::getAll()
 
        return jobInfos;
 }
+
+bool JobInfoDatabase::getUsedIds(std::vector<std::shared_ptr<Tuple>>* usedIds)
+{
+       std::vector<std::string> columns = {"jobId"};
+
+       return __database->execute(
+                       "SELECT jobId FROM " USED_ID_TABLE " ORDER BY jobID ASC",
+                       COL_INT64, &columns, usedIds);
+}
index 8900c0bc5056f803deaf272eb3e15e3fa962e17d..46e1232fa166f870f5e1780d14ea6334a218e9d9 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <vector>
 #include <JobInfo.h>
+#include <Tuple.h>
 
 namespace ctx {
 
@@ -32,6 +33,8 @@ namespace ctx {
                void setStarted(int jobId, bool started);
                std::vector<std::pair<std::string, JobInfo*>> getAll();
 
+               bool getUsedIds(std::vector<std::shared_ptr<Tuple>>* usedIds);
+
        private:
                uid_t __uid;
        };
index 9967d1f455342002f6dd849fb7a7d45fecc0c4e3..afeadcd990e78b85f881df689d00a4f6096e489d 100644 (file)
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <deque>
 #include <ServerUtil.h>
 #include <JobAction.h>
 #include "SchedTimer.h"
 
 using namespace ctx;
 
-static int __lastJobId = 0;
+namespace {
+       class JobIdGenerator {
+       public:
+               void init(JobInfoDatabase& database);
+               int pop();
+       private:
+               void __push(int id);
+               std::deque<int> __usedIds;
+       };
+}
+
+void JobIdGenerator::init(JobInfoDatabase& database)
+{
+       IF_FAIL_VOID(__usedIds.empty());
+
+       int64_t id = 0;
+       std::vector<std::shared_ptr<Tuple>> usedIds;
+       database.getUsedIds(&usedIds);
+       __usedIds.push_back(0);
+
+       for (auto& tuple : usedIds) {
+               if (tuple->getAt(0, &id))
+                       __push(static_cast<int>(id));
+       }
+}
+
+int JobIdGenerator::pop()
+{
+       int nextId = ++(__usedIds.front());
+
+       while (__usedIds[1] == __usedIds[0] + 1) {
+               __usedIds.pop_front();
+       }
+
+       return nextId;
+}
+
+void JobIdGenerator::__push(int id)
+{
+       __usedIds.push_back(id);
+
+       if (__usedIds[1] == __usedIds[0] + 1)
+               __usedIds.pop_front();
+}
+
+static JobIdGenerator __jobIdGenerator;
 
 JobManager::JobManager(uid_t uid) :
        __uid(uid),
        __jobInfoDatabase(uid)
 {
        _I("Initialize JobManager-%u", static_cast<unsigned>(__uid));
+       __jobIdGenerator.init(__jobInfoDatabase);
        __restore();
 }
 
@@ -82,7 +129,7 @@ int JobManager::__addPeriodicJob(PeriodicJobInfo* jobInfo, IClient* owner)
 {
        __verifyPeriodicJob(jobInfo, owner);
 
-       jobInfo->setId(__generateJobId());
+       jobInfo->setId(__jobIdGenerator.pop());
 
        unsigned int cnt = __addRunner(new PeriodicJobRunner(this, owner->getName(), jobInfo));
        _D("%u jobs have been registered", cnt);
@@ -94,7 +141,7 @@ int JobManager::__addOnDemandJob(OnDemandJobInfo* jobInfo, IClient* owner)
 {
        __verifyOnDemandJob(jobInfo, owner);
 
-       jobInfo->setId(__generateJobId());
+       jobInfo->setId(__jobIdGenerator.pop());
 
        unsigned int cnt = __addRunner(new OnDemandJobRunner(this, owner->getName(), jobInfo));
        _D("%u jobs have been registered", cnt);
@@ -284,16 +331,6 @@ void JobManager::__verifyAction(JobInfo* jobInfo, IClient* owner)
        throw static_cast<int>(E_PARAM);
 }
 
-
-
-int JobManager::__generateJobId()
-{
-       if (++__lastJobId < 0)
-               __lastJobId = 1;
-
-       return __lastJobId;
-}
-
 unsigned int JobManager::__addRunner(JobRunner* runner)
 {
        __jobRunners.push_back(runner);
@@ -319,7 +356,6 @@ JobRunner* JobManager::__getRunner(const std::string& ownerId, int jobId)
 
 void JobManager::__restore()
 {
-       int maxJobId = 0;
        auto storedJobs = __jobInfoDatabase.getAll();
 
        _I("Restoring %u jobs", storedJobs.size());
@@ -330,8 +366,6 @@ void JobManager::__restore()
                const std::string& owner = storedJob.first;
                JobInfo* jobInfo = storedJob.second;
 
-               maxJobId = MAX(maxJobId, jobInfo->getId());
-
                JobRunner* runner = NULL;
                if (jobInfo->getType() == JobInfo::Type::PERIODIC)
                        runner = new PeriodicJobRunner(this, owner, jobInfo);
@@ -345,8 +379,6 @@ void JobManager::__restore()
        }
 
        SchedTimer::resume();
-
-       __lastJobId = maxJobId;
 }
 
 void JobManager::__release()
index 31815a78802c52189f4794eec72ebaa9499ea101..324b94cc5ab0939033de34d6928c33ebe6443bfa 100644 (file)
@@ -59,8 +59,6 @@ namespace ctx {
                void __verifyRequirements(JobInfo* jobInfo, IClient* owner);
                void __verifyAction(JobInfo* jobInfo, IClient* owner);
 
-               int __generateJobId();
-
                unsigned int __addRunner(JobRunner* runner);
                void __removeRunner(JobRunner* runner);
                JobRunner* __getRunner(const std::string& ownerId, int jobId);