Restore data_version usage from db schema 09/76809/2
authorKyungwook Tak <k.tak@samsung.com>
Mon, 27 Jun 2016 10:05:54 +0000 (19:05 +0900)
committerKyungwook Tak <k.tak@samsung.com>
Tue, 28 Jun 2016 00:55:03 +0000 (09:55 +0900)
Change-Id: I6677a821eb1ecf545b902f4f872790d76807e728
Signed-off-by: Kyungwook Tak <k.tak@samsung.com>
data/scripts/create_schema.sql
src/framework/db/manager.cpp
src/framework/db/manager.h
src/framework/db/query.h
src/framework/db/row.h
src/framework/service/cs-logic.cpp
test/internals/test-db.cpp

index 2755b7b..f690928 100644 (file)
@@ -36,6 +36,7 @@ CREATE TABLE IF NOT EXISTS ENGINE_STATE (
 CREATE TABLE IF NOT EXISTS SCAN_REQUEST (
        dir TEXT NOT NULL,
        last_scan INTEGER NOT NULL,
+       data_version TEXT NOT NULL,
 
        PRIMARY KEY(dir)
 );
@@ -52,6 +53,7 @@ CREATE TABLE IF NOT EXISTS DETECTED_MALWARE (
        filepath_idx INTEGER PRIMARY KEY AUTOINCREMENT,
        file_path TEXT NOT NULL,
        idx INTEGER NOT NULL,
+       data_version TEXT NOT NULL,
        malware_name TEXT NOT NULL,
        detailed_url TEXT NOT NULL,
        severity INTEGER NOT NULL,
@@ -64,6 +66,7 @@ CREATE TABLE IF NOT EXISTS DETECTED_MALWARE (
 CREATE TABLE IF NOT EXISTS DETECTED_MALWARE_CLOUD (
        idx INTEGER NOT NULL,
        pkg_id TEXT NOT NULL,
+       data_version TEXT NOT NULL,
        malware_name TEXT NOT NULL,
        detailed_url TEXT NOT NULL,
        severity INTEGER NOT NULL,
@@ -83,32 +86,32 @@ CREATE TABLE IF NOT EXISTS PACKAGE_INFO (
 );
 
 CREATE VIEW IF NOT EXISTS [join_detecteds_cloud_by_name] AS
-       SELECT N.name, D.malware_name, D.detailed_url, D.severity,
+       SELECT N.name, D.data_version, D.malware_name, D.detailed_url, D.severity,
                        D.detected_time, D.pkg_id, N.is_ignored
                FROM NAMES AS N INNER JOIN DETECTED_MALWARE_CLOUD AS D ON N.idx = D.idx;
 
 CREATE VIEW IF NOT EXISTS [join_p_d] AS
-       SELECT N.idx, N.name, D.file_path, D.malware_name, D.detailed_url,
+       SELECT N.idx, N.name, D.file_path, D.data_version, D.malware_name, D.detailed_url,
                        D.severity, D.detected_time, P.pkg_id
                FROM (PACKAGE_INFO AS P INNER JOIN DETECTED_MALWARE AS D ON P.worst_filepath_idx = D.filepath_idx)
                        AS J INNER JOIN NAMES AS N ON J.idx = N.idx;
 
 CREATE VIEW IF NOT EXISTS [join_detecteds_by_name] AS
-       SELECT N.name, J.file_path, J.malware_name, J.detailed_url,
+       SELECT N.name, J.file_path, J.data_version, J.malware_name, J.detailed_url,
                        J.severity, J.detected_time, J.pkg_id, N.is_ignored
                FROM (
-                       SELECT D.idx, D.file_path, D.malware_name, D.detailed_url,
+                       SELECT D.idx, D.file_path, D.data_version, D.malware_name, D.detailed_url,
                                        D.severity, D.detected_time, P.pkg_id
                                FROM DETECTED_MALWARE AS D LEFT JOIN PACKAGE_INFO AS P ON D.idx = P.idx
                                WHERE NOT EXISTS (SELECT * FROM join_p_d WHERE idx = D.idx)
                        UNION
-                       SELECT idx, file_path, malware_name, detailed_url,
+                       SELECT idx, file_path, data_version, malware_name, detailed_url,
                                        severity, detected_time, pkg_id
                                FROM join_p_d)
                        AS J INNER JOIN NAMES AS N ON J.idx = N.idx;
 
 CREATE VIEW IF NOT EXISTS [join_detecteds_by_file_path] AS
-       SELECT N.name, D.file_path, D.malware_name, D.detailed_url,
+       SELECT N.name, D.file_path, D.data_version, D.malware_name, D.detailed_url,
                        D.severity, D.detected_time, P.pkg_id, N.is_ignored
                FROM (DETECTED_MALWARE AS D LEFT JOIN PACKAGE_INFO AS P ON D.idx = P.idx)
                        AS J INNER JOIN NAMES AS N ON J.idx = N.idx;
index e9b3a6c..f2b81ba 100644 (file)
@@ -53,6 +53,7 @@ RowShPtr extractRow(Statement &stmt)
 
        row->targetName = stmt.getText(); // name.
        row->fileInAppPath = stmt.getText(); // file_path
+       row->dataVersion = stmt.getText(); // data_version
        row->malwareName = stmt.getText(); // malware_name
        row->detailedUrl = stmt.getText(); // detailed_url
        row->severity = static_cast<csr_cs_severity_level_e>(stmt.getInt()); // severity
@@ -70,6 +71,7 @@ RowShPtr extractRowCloud(Statement &stmt)
 
        row->targetName = stmt.getText(); // name.
        row->fileInAppPath.clear();
+       row->dataVersion = stmt.getText(); // data_version
        row->malwareName = stmt.getText(); // malware_name
        row->detailedUrl = stmt.getText(); // detailed_url
        row->severity = static_cast<csr_cs_severity_level_e>(stmt.getInt()); // severity
@@ -266,7 +268,8 @@ time_t Manager::getLastScanTime(const std::string &dir, time_t since)
        return latest;
 }
 
-void Manager::insertLastScanTime(const std::string &dir, time_t scanTime)
+void Manager::insertLastScanTime(const std::string &dir, const std::string &dataVersion,
+                                                                time_t scanTime)
 {
        std::lock_guard<std::mutex> l(this->m_mutex);
 
@@ -274,6 +277,7 @@ void Manager::insertLastScanTime(const std::string &dir, time_t scanTime)
 
        stmt.bind(dir);
        stmt.bind(static_cast<sqlite3_int64>(scanTime));
+       stmt.bind(dataVersion);
        stmt.exec();
 }
 
@@ -299,12 +303,11 @@ void Manager::cleanLastScanTime()
 //===========================================================================
 // DETECTED_MALWARE_FILE table
 //===========================================================================
-RowShPtr Manager::getDetectedByNameOnPath(const std::string &path)
+RowShPtr Manager::getDetectedByNameOnPath(const std::string &path, time_t since)
 {
-       std::lock_guard<std::mutex> l(this->m_mutex);
-
        Statement stmt(this->m_conn, Query::SEL_DETECTED_BY_NAME_ON_PATH);
        stmt.bind(path);
+       stmt.bind(static_cast<sqlite3_int64>(since));
 
        if (!stmt.step())
                return nullptr;
@@ -312,12 +315,11 @@ RowShPtr Manager::getDetectedByNameOnPath(const std::string &path)
        return extractRow(stmt);
 }
 
-RowShPtr Manager::getDetectedCloudByNameOnPath(const std::string &path)
+RowShPtr Manager::getDetectedCloudByNameOnPath(const std::string &path, time_t since)
 {
-       std::lock_guard<std::mutex> l(this->m_mutex);
-
        Statement stmt(this->m_conn, Query::SEL_DETECTED_CLOUD_BY_NAME_ON_PATH);
        stmt.bind(path);
+       stmt.bind(static_cast<sqlite3_int64>(since));
 
        if (!stmt.step())
                return nullptr;
@@ -325,35 +327,31 @@ RowShPtr Manager::getDetectedCloudByNameOnPath(const std::string &path)
        return extractRowCloud(stmt);
 }
 
-RowShPtr Manager::getDetectedAllByNameOnPath(const std::string &path, bool *isByCloud)
+RowShPtr Manager::getDetectedAllByNameOnPath(const std::string &path, time_t since, bool *isByCloud)
 {
        std::lock_guard<std::mutex> l(this->m_mutex);
-
-       Statement stmt(this->m_conn, Query::SEL_DETECTED_BY_NAME_ON_PATH);
-       stmt.bind(path);
-
-       if (stmt.step()) {
+       auto row = this->getDetectedByNameOnPath(path, since);
+       if (row) {
                if (isByCloud)
                        *isByCloud = false;
-               return extractRow(stmt);
+               return row;
        }
 
-       Statement stmt2(this->m_conn, Query::SEL_DETECTED_CLOUD_BY_NAME_ON_PATH);
-       stmt.bind(path);
-
-       if (stmt2.step()) {
+       row = this->getDetectedCloudByNameOnPath(path, since);
+       if (row) {
                if (isByCloud)
                        *isByCloud = true;
-               return extractRow(stmt);
+               return row;
        }
 
        return nullptr;
 }
 
-RowShPtrs Manager::getDetectedByNameOnDir(const std::string &dir)
+RowShPtrs Manager::getDetectedByNameOnDir(const std::string &dir, time_t since)
 {
        Statement stmt(this->m_conn, Query::SEL_DETECTED_BY_NAME_ON_DIR);
        stmt.bind(dir);
+       stmt.bind(static_cast<sqlite3_int64>(since));
 
        RowShPtrs rows;
 
@@ -363,10 +361,11 @@ RowShPtrs Manager::getDetectedByNameOnDir(const std::string &dir)
        return rows;
 }
 
-RowShPtrs Manager::getDetectedCloudByNameOnDir(const std::string &dir)
+RowShPtrs Manager::getDetectedCloudByNameOnDir(const std::string &dir, time_t since)
 {
        Statement stmt(this->m_conn, Query::SEL_DETECTED_CLOUD_BY_NAME_ON_DIR);
        stmt.bind(dir);
+       stmt.bind(static_cast<sqlite3_int64>(since));
 
        RowShPtrs rows;
        while (stmt.step())
@@ -375,15 +374,15 @@ RowShPtrs Manager::getDetectedCloudByNameOnDir(const std::string &dir)
        return rows;
 }
 
-RowShPtrs Manager::getDetectedAllByNameOnDir(const std::string &dir)
+RowShPtrs Manager::getDetectedAllByNameOnDir(const std::string &dir, time_t since)
 {
        RowShPtrs normals;
        RowShPtrs clouds;
 
        {
                std::lock_guard<std::mutex> l(this->m_mutex);
-               normals = this->getDetectedByNameOnDir(dir);
-               clouds = this->getDetectedCloudByNameOnDir(dir);
+               normals = this->getDetectedByNameOnDir(dir, since);
+               clouds = this->getDetectedCloudByNameOnDir(dir, since);
        }
 
        if (clouds.empty())
@@ -416,12 +415,13 @@ RowShPtrs Manager::getDetectedAllByNameOnDir(const std::string &dir)
        return rows;
 }
 
-RowShPtrs Manager::getDetectedByFilepathOnDir(const std::string &dir)
+RowShPtrs Manager::getDetectedByFilepathOnDir(const std::string &dir, time_t since)
 {
        std::lock_guard<std::mutex> l(this->m_mutex);
 
        Statement stmt(this->m_conn, Query::SEL_DETECTED_BY_FILEPATH_ON_DIR);
        stmt.bind(dir);
+       stmt.bind(static_cast<sqlite3_int64>(since));
 
        RowShPtrs rows;
 
@@ -431,12 +431,13 @@ RowShPtrs Manager::getDetectedByFilepathOnDir(const std::string &dir)
        return rows;
 }
 
-RowShPtr Manager::getWorstByPkgPath(const std::string &pkgPath)
+RowShPtr Manager::getWorstByPkgPath(const std::string &pkgPath, time_t since)
 {
        std::lock_guard<std::mutex> l(this->m_mutex);
 
        Statement stmt(this->m_conn, Query::SEL_WORST_BY_PKGPATH);
        stmt.bind(pkgPath);
+       stmt.bind(static_cast<sqlite3_int64>(since));
 
        if (!stmt.step())
                return nullptr;
@@ -445,6 +446,7 @@ RowShPtr Manager::getWorstByPkgPath(const std::string &pkgPath)
 
        row->targetName = stmt.getText(); // name
        row->fileInAppPath = stmt.getText(); // file_path
+       row->dataVersion = stmt.getText(); // data_version
        row->malwareName = stmt.getText(); // malware_name
        row->detailedUrl = stmt.getText(); // detailed_url
        row->severity = static_cast<csr_cs_severity_level_e>(stmt.getInt()); // severity
@@ -455,30 +457,31 @@ RowShPtr Manager::getWorstByPkgPath(const std::string &pkgPath)
        return row;
 }
 
-void Manager::insertDetectedFile(const std::string &filepath, const CsDetected &d)
+void Manager::insertDetectedFile(const std::string &filepath, const CsDetected &d,
+                                                                const std::string &dataVersion)
 {
        std::lock_guard<std::mutex> l(this->m_mutex);
 
        this->insertName(filepath);
-       this->insertDetected(d, filepath);
+       this->insertDetected(d, filepath, dataVersion);
 }
 
 void Manager::insertDetectedFileInApp(const std::string &pkgpath, const std::string &filepath,
-                                                                         const CsDetected &d)
+                                                                         const CsDetected &d, const std::string &dataVersion)
 {
        std::lock_guard<std::mutex> l(this->m_mutex);
 
        this->insertName(pkgpath);
-       this->insertDetected(d, filepath);
+       this->insertDetected(d, filepath, dataVersion);
 }
 
 void Manager::insertDetectedAppByCloud(const std::string &name, const std::string &pkgId,
-                                                                          const CsDetected &d)
+                                                                          const CsDetected &d, const std::string &dataVersion)
 {
        std::lock_guard<std::mutex> l(this->m_mutex);
 
        this->insertName(name);
-       this->insertDetectedCloud(d, pkgId, name);
+       this->insertDetectedCloud(d, pkgId, name, dataVersion);
 }
 
 void Manager::insertName(const std::string &name)
@@ -489,12 +492,14 @@ void Manager::insertName(const std::string &name)
        stmt.exec();
 }
 
-void Manager::insertDetected(const CsDetected &d, const std::string &filepath)
+void Manager::insertDetected(const CsDetected &d, const std::string &filepath,
+                                                        const std::string &dataVersion)
 {
        Statement stmt(this->m_conn, Query::INS_DETECTED);
 
        stmt.bind(filepath);
        stmt.bind(d.targetName);
+       stmt.bind(dataVersion);
        stmt.bind(d.malwareName);
        stmt.bind(d.detailedUrl);
        stmt.bind(static_cast<int>(d.severity));
@@ -503,12 +508,13 @@ void Manager::insertDetected(const CsDetected &d, const std::string &filepath)
 }
 
 void Manager::insertDetectedCloud(const CsDetected &d, const std::string &pkgId,
-                                                                 const std::string &name)
+                                                                 const std::string &name, const std::string &dataVersion)
 {
        Statement stmt(this->m_conn, Query::INS_DETECTED_CLOUD);
 
        stmt.bind(name);
        stmt.bind(pkgId);
+       stmt.bind(dataVersion);
        stmt.bind(d.malwareName);
        stmt.bind(d.detailedUrl);
        stmt.bind(static_cast<int>(d.severity));
@@ -560,18 +566,18 @@ void Manager::deleteDetectedByFilepathOnPath(const std::string &path)
        stmt.exec();
 }
 
-void Manager::deleteDetectedDeprecated(time_t t)
+void Manager::deleteDetectedDeprecated(time_t since)
 {
        std::lock_guard<std::mutex> l(this->m_mutex);
 
        Statement stmt(this->m_conn, Query::DEL_DETECTED_DEPRECATED);
 
-       stmt.bind(static_cast<sqlite3_int64>(t));
+       stmt.bind(static_cast<sqlite3_int64>(since));
        stmt.exec();
 
        Statement stmt2(this->m_conn, Query::DEL_DETECTED_DEPRECATED_CLOUD);
 
-       stmt2.bind(static_cast<sqlite3_int64>(t));
+       stmt2.bind(static_cast<sqlite3_int64>(since));
        stmt2.exec();
 }
 
index 8a4a00c..d63e05b 100644 (file)
@@ -26,7 +26,6 @@
 #include <memory>
 #include <map>
 #include <mutex>
-#include <ctime>
 
 #include "db/connection.h"
 #include "db/row.h"
@@ -56,39 +55,42 @@ public:
 
        // SCAN_REQUEST
        time_t getLastScanTime(const std::string &dir, time_t since);
-       void insertLastScanTime(const std::string &dir, time_t scanTime);
+       void insertLastScanTime(const std::string &dir, const std::string &dataVersion,
+                                                       time_t scanTime);
        void deleteLastScanTime(const std::string &dir);
        void cleanLastScanTime();
 
        // DETECTED_MALWARE_FILE & USER_RESPONSE
-       RowShPtr getDetectedAllByNameOnPath(const std::string &path, bool *isByCloud = nullptr);
-       RowShPtr getDetectedByNameOnPath(const std::string &path);
-       RowShPtr getDetectedCloudByNameOnPath(const std::string &path);
-       RowShPtrs getDetectedAllByNameOnDir(const std::string &dir);
-       RowShPtrs getDetectedByFilepathOnDir(const std::string &dir);
-       RowShPtr getWorstByPkgPath(const std::string &pkgPath);
-
-       void insertDetectedFile(const std::string &filepath, const CsDetected &d);
+       RowShPtr getDetectedAllByNameOnPath(const std::string &path, time_t since, bool *isByCloud = nullptr);
+       RowShPtrs getDetectedAllByNameOnDir(const std::string &dir, time_t since);
+       RowShPtrs getDetectedByFilepathOnDir(const std::string &dir, time_t since);
+       RowShPtr getWorstByPkgPath(const std::string &pkgPath, time_t since);
+
+       void insertDetectedFile(const std::string &filepath, const CsDetected &d,
+                                                       const std::string &dataVersion);
        void insertDetectedFileInApp(const std::string &pkgpath, const std::string &filepath,
-                                                                const CsDetected &d);
+                                                                const CsDetected &d, const std::string &dataVersion);
        void insertDetectedAppByCloud(const std::string &name, const std::string &pkgId,
-                                                        const CsDetected &d);
+                                                        const CsDetected &d, const std::string &dataVersion);
        void insertWorst(const std::string &pkgId, const std::string &name,
                                         const std::string &filepath);
 
        void updateIgnoreFlag(const std::string &name, bool flag);
        void deleteDetectedByNameOnPath(const std::string &path);
        void deleteDetectedByFilepathOnPath(const std::string &path);
-       void deleteDetectedDeprecated(time_t t);
+       void deleteDetectedDeprecated(time_t since);
 
 private:
-       RowShPtrs getDetectedByNameOnDir(const std::string &dir);
-       RowShPtrs getDetectedCloudByNameOnDir(const std::string &dir);
+       RowShPtr getDetectedByNameOnPath(const std::string &path, time_t since);
+       RowShPtr getDetectedCloudByNameOnPath(const std::string &path, time_t since);
+       RowShPtrs getDetectedByNameOnDir(const std::string &dir, time_t since);
+       RowShPtrs getDetectedCloudByNameOnDir(const std::string &dir, time_t since);
 
        void insertName(const std::string &name);
-       void insertDetected(const CsDetected &d, const std::string &filename);
+       void insertDetected(const CsDetected &d, const std::string &filename,
+                                               const std::string &dataVersion);
        void insertDetectedCloud(const CsDetected &d, const std::string &pkgId,
-                                                        const std::string &name);
+                                                        const std::string &name, const std::string &dataVersion);
 
        void resetDatabase();
        bool isTableExist(const std::string &name);
index d782452..049434d 100644 (file)
@@ -41,8 +41,8 @@ const std::string SEL_SCAN_REQUEST =
        "select last_scan from SCAN_REQUEST where dir = ?";
 
 const std::string INS_SCAN_REQUEST =
-       "insert or replace into SCAN_REQUEST (dir, last_scan)"
-       " values (?, ?)";
+       "insert or replace into SCAN_REQUEST (dir, last_scan, data_version)"
+       " values (?, ?, ?)";
 
 const std::string DEL_SCAN_REQUEST_BY_DIR =
        "delete from SCAN_REQUEST where dir = ?";
@@ -51,54 +51,54 @@ const std::string DEL_SCAN_REQUEST =
        "delete from SCAN_REQUEST";
 
 const std::string SEL_DETECTED_CLOUD_BY_NAME_ON_PATH =
-       "select name, malware_name, detailed_url, severity, detected_time,"
+       "select name, data_version, malware_name, detailed_url, severity, detected_time,"
        "       pkg_id, is_ignored"
        " from join_detecteds_cloud_by_name"
-       " where name = ?";
+       " where name = ? and detected_time >= ?";
 
 const std::string SEL_DETECTED_BY_NAME_ON_PATH =
-       "select name, file_path, malware_name, detailed_url, severity,"
+       "select name, file_path, data_version, malware_name, detailed_url, severity,"
        "       detected_time, pkg_id, is_ignored"
        " from join_detecteds_by_name"
-       " where name = ?";
+       " where name = ? and detected_time >= ?";
 
 const std::string SEL_DETECTED_CLOUD_BY_NAME_ON_DIR =
-       "select name, malware_name, detailed_url, severity, detected_time,"
+       "select name, data_version, malware_name, detailed_url, severity, detected_time,"
        "       pkg_id, is_ignored"
        " from join_detecteds_cloud_by_name"
-       " where name like ? || '%'";
+       " where name like ? || '%' and detected_time >= ?";
 
 const std::string SEL_DETECTED_BY_NAME_ON_DIR =
-       "select name, file_path, malware_name, detailed_url, severity,"
+       "select name, file_path, data_version, malware_name, detailed_url, severity,"
        "       detected_time, pkg_id, is_ignored"
        " from join_detecteds_by_name"
-       " where name like ? || '%'";
+       " where name like ? || '%' and detected_time >= ?";
 
 const std::string SEL_DETECTED_BY_FILEPATH_ON_DIR =
-       "select name, file_path, malware_name, detailed_url, severity,"
+       "select name, file_path, data_version, malware_name, detailed_url, severity,"
        "       detected_time, pkg_id, is_ignored"
        " from join_detecteds_by_file_path"
-       " where file_path like ? || '%'";
+       " where file_path like ? || '%' and detected_time >= ?";
 
 const std::string SEL_WORST_BY_PKGPATH =
-       "select name, file_path, malware_name, detailed_url, severity,"
+       "select name, file_path, data_version, malware_name, detailed_url, severity,"
        "       detected_time, pkg_id"
        " from join_p_d"
-       " where name = ?";
+       " where name = ? and detected_time >= ?";
 
 const std::string INS_NAME =
        "insert or replace into NAMES(name) values(?)";
 
 const std::string INS_DETECTED_CLOUD =
-       "insert or replace into DETECTED_MALWARE_CLOUD(idx, pkg_id,"
+       "insert or replace into DETECTED_MALWARE_CLOUD(idx, pkg_id, data_version,"
        "                                              malware_name, detailed_url, severity,"
        "                                              detected_time)"
-       " values((select idx from NAMES where name = ?), ?, ?, ?, ?, ?)";
+       " values((select idx from NAMES where name = ?), ?, ?, ?, ?, ?, ?)";
 
 const std::string INS_DETECTED =
-       "insert or replace into DETECTED_MALWARE(file_path, idx, malware_name,"
+       "insert or replace into DETECTED_MALWARE(file_path, idx, data_version, malware_name,"
        "                                        detailed_url, severity, detected_time)"
-       " values(?, (select idx from NAMES where name = ?), ?, ?, ?, ?)";
+       " values(?, (select idx from NAMES where name = ?), ?, ?, ?, ?, ?)";
 
 const std::string INS_WORST =
        "insert or replace into PACKAGE_INFO(pkg_id, idx, worst_filepath_idx)"
index fa1a521..c6f23ab 100644 (file)
@@ -34,6 +34,7 @@ using RowShPtrs = std::vector<RowShPtr>;
 
 struct Row : public Csr::CsDetected {
        std::string fileInAppPath; // for case of file in app
+       std::string dataVersion; // engine's data version
        bool isIgnored;
 
        Row() : isIgnored(false) {}
index 2a0c4df..1d24873 100644 (file)
@@ -139,8 +139,7 @@ CsLogic::CsLogic(const std::shared_ptr<CsLoader> &loader,
        if (this->m_loader) {
                CsEngineContext csEngineContext(this->m_loader);
                this->m_loader->getEngineDataVersion(csEngineContext.get(), this->m_dataVersion);
-               this->m_db->deleteDetectedDeprecated(
-                               this->m_loader->getEngineLatestUpdateTime(csEngineContext.get()));
+               this->m_db->deleteDetectedDeprecated(this->m_loader->getEngineLatestUpdateTime(csEngineContext.get()));
        }
 }
 
@@ -188,7 +187,7 @@ RawBuffer CsLogic::scanAppOnCloud(const CsContext &context,
        detected.isApp = true;
        detected.pkgId = pkgId;
 
-       this->m_db->insertDetectedAppByCloud(pkgPath, pkgId, detected);
+       this->m_db->insertDetectedAppByCloud(pkgPath, pkgId, detected, this->m_dataVersion);
 
        return this->handleAskUser(context, detected);
 }
@@ -230,7 +229,8 @@ CsDetectedPtr CsLogic::scanAppDelta(const std::string &pkgPath, const std::strin
                candidate.isApp = true;
                candidate.pkgId = pkgId;
 
-               this->m_db->insertDetectedFileInApp(pkgPath, file->getPath(), candidate);
+               this->m_db->insertDetectedFileInApp(pkgPath, file->getPath(), candidate,
+                                                                                       this->m_dataVersion);
 
                if (!riskiest) {
                        riskiest.reset(new CsDetected(std::move(candidate)));
@@ -241,7 +241,7 @@ CsDetectedPtr CsLogic::scanAppDelta(const std::string &pkgPath, const std::strin
                }
        }
 
-       this->m_db->insertLastScanTime(pkgPath, starttime);
+       this->m_db->insertLastScanTime(pkgPath, this->m_dataVersion, starttime);
 
        return riskiest;
 }
@@ -260,15 +260,18 @@ RawBuffer CsLogic::scanApp(const CsContext &context, const std::string &pkgPath)
        if (context.isScanOnCloud && this->m_loader->scanAppOnCloudSupported())
                return this->scanAppOnCloud(context, pkgPath, pkgId);
 
+       CsEngineContext engineContext(this->m_loader);
+       auto since = this->m_loader->getEngineLatestUpdateTime(engineContext.get());
+
        // old history
-       auto history = this->m_db->getWorstByPkgPath(pkgPath);
+       auto history = this->m_db->getWorstByPkgPath(pkgPath, since);
        // riskiest detected among newly scanned files
        std::string riskiestPath;
        auto riskiest = this->scanAppDelta(pkgPath, pkgId, riskiestPath);
        // history after delta scan. if worst file is changed, it's rescanned in scanAppDelta
        // and deleted from db if it's cured. if history != nullptr && after == nullptr,
        // it means worst detected item is cured anyway.
-       auto after = this->m_db->getWorstByPkgPath(pkgPath);
+       auto after = this->m_db->getWorstByPkgPath(pkgPath, since);
        if (history && after && riskiest) {
                if (*history < *riskiest) {
                        INFO("worst case is remained but the more worst newly detected. on pkg[" <<
@@ -298,7 +301,8 @@ RawBuffer CsLogic::scanApp(const CsContext &context, const std::string &pkgPath)
                         "worse case in db and compare it with riskiest first. on pkg[" << pkgPath <<
                         "]");
                Db::RowShPtr worse;
-               for (auto &row : this->m_db->getDetectedByFilepathOnDir(pkgPath))
+               since = this->m_loader->getEngineLatestUpdateTime(engineContext.get());
+               for (auto &row : this->m_db->getDetectedByFilepathOnDir(pkgPath, since))
                        if (!worse || *worse < *row)
                                worse = std::move(row);
 
@@ -334,7 +338,8 @@ RawBuffer CsLogic::scanApp(const CsContext &context, const std::string &pkgPath)
                        return this->handleAskUser(context, *riskiest);
                }
        } else if (history && !after && !riskiest) {
-               auto rows = this->m_db->getDetectedByFilepathOnDir(pkgPath);
+               since = this->m_loader->getEngineLatestUpdateTime(engineContext.get());
+               auto rows = this->m_db->getDetectedByFilepathOnDir(pkgPath, since);
 
                if (!rows.empty()) {
                        INFO("worst case is deleted cascadingly and NO new detected and "
@@ -392,7 +397,7 @@ RawBuffer CsLogic::scanFileWithoutDelta(const CsContext &context,
 
        auto d = this->convert(result, filepath, timestamp);
 
-       this->m_db->insertDetectedFile(d.targetName, d);
+       this->m_db->insertDetectedFile(d.targetName, d, this->m_dataVersion);
 
        return this->handleAskUser(context, d, std::forward<FilePtr>(fileptr));
 }
@@ -411,22 +416,19 @@ RawBuffer CsLogic::scanFile(const CsContext &context, const std::string &filepat
 
        DEBUG("Scan request on file: " << target);
 
-       auto history = this->m_db->getDetectedByNameOnPath(target);
+       CsEngineContext engineContext(this->m_loader);
+       auto since = this->m_loader->getEngineLatestUpdateTime(engineContext.get());
+
+       auto history = this->m_db->getDetectedAllByNameOnPath(target, since);
 
        FilePtr fileptr;
 
        // if history exist, fileptr can be null because of modified since value
        // from history.
-       if (history) {
-               CsEngineContext engineContext(this->m_loader);
-               auto t = this->m_loader->getEngineLatestUpdateTime(engineContext.get());
-               if (t < history->ts)
-                       fileptr = File::createIfModified(target, history->ts);
-               else
-                       fileptr = File::create(target);
-       } else {
+       if (history)
+               fileptr = File::createIfModified(target, static_cast<time_t>(history->ts));
+       else
                fileptr = File::create(target);
-       }
 
        // non-null fileptr means the file is modified since the last history
        // OR there's no history at all.
@@ -482,10 +484,10 @@ RawBuffer CsLogic::getScannableFiles(const std::string &dir, const std::function
        if (this->m_db->getEngineState(CSR_ENGINE_CS) != CSR_STATE_ENABLE)
                ThrowExc(CSR_ERROR_ENGINE_DISABLED, "engine is disabled");
 
-       CsEngineContext engineContext(this->m_loader);
+       CsEngineContext csEngineContext(this->m_loader);
+       auto since = this->m_loader->getEngineLatestUpdateTime(csEngineContext.get());
 
-       auto t = this->m_loader->getEngineLatestUpdateTime(engineContext.get());
-       auto lastScanTime = this->m_db->getLastScanTime(dir, t);
+       auto lastScanTime = this->m_db->getLastScanTime(dir, since);
 
        auto visitor = FsVisitor::create(dir, lastScanTime);
 
@@ -506,8 +508,9 @@ RawBuffer CsLogic::getScannableFiles(const std::string &dir, const std::function
        }
 
        if (lastScanTime != -1) {
+
                // for case: scan history exist and not modified.
-               for (auto &row : this->m_db->getDetectedAllByNameOnDir(File::getPkgPath(dir))) {
+               for (auto &row : this->m_db->getDetectedAllByNameOnDir(File::getPkgPath(dir), since)) {
                        isCancelled();
 
                        try {
@@ -549,7 +552,7 @@ RawBuffer CsLogic::canonicalizePaths(const StrSet &paths)
 
 RawBuffer CsLogic::setDirTimestamp(const std::string &dir, time_t ts)
 {
-       this->m_db->insertLastScanTime(dir, ts);
+       this->m_db->insertLastScanTime(dir, this->m_dataVersion, ts);
 
        return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
 }
@@ -571,9 +574,11 @@ RawBuffer CsLogic::judgeStatus(const std::string &filepath, csr_cs_action_e acti
 
        const auto &targetName = (file->isInApp() ? file->getAppPkgPath() : filepath);
 
-       bool isCloudHistory = false;
+       CsEngineContext csEngineContext(this->m_loader);
+       auto since = this->m_loader->getEngineLatestUpdateTime(csEngineContext.get());
 
-       auto history = this->m_db->getDetectedAllByNameOnPath(targetName, &isCloudHistory);
+       bool isCloudHistory = false;
+       auto history = this->m_db->getDetectedAllByNameOnPath(targetName, since, &isCloudHistory);
 
        if (!history) {
                ERROR("Target to be judged doesn't exist in db. name: " << targetName);
@@ -623,7 +628,9 @@ RawBuffer CsLogic::getDetected(const std::string &filepath)
                return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
        }
 
-       auto row = this->m_db->getDetectedAllByNameOnPath(target);
+       CsEngineContext csEngineContext(this->m_loader);
+       auto row = this->m_db->getDetectedAllByNameOnPath(target,
+                       this->m_loader->getEngineLatestUpdateTime(csEngineContext.get()));
 
        if (row && !row->isIgnored)
                return BinaryQueue::Serialize(CSR_ERROR_NONE, row).pop();
@@ -637,9 +644,11 @@ RawBuffer CsLogic::getDetectedList(const StrSet &_dirSet)
        for (const auto &dir : _dirSet)
                dirSet.emplace(canonicalizePath(dir, false));
 
+       CsEngineContext csEngineContext(this->m_loader);
+       auto since = this->m_loader->getEngineLatestUpdateTime(csEngineContext.get());
        Db::RowShPtrs rows;
        for (const auto &dir : dirSet) {
-               for (auto &row : this->m_db->getDetectedAllByNameOnDir(dir)) {
+               for (auto &row : this->m_db->getDetectedAllByNameOnDir(dir, since)) {
                        if (!row->fileInAppPath.empty() && !isReadable(row->targetName)) {
                                WARN("Exclude not-accessable malware detected file from the list: " <<
                                         row->targetName);
@@ -668,7 +677,9 @@ RawBuffer CsLogic::getIgnored(const std::string &filepath)
                return BinaryQueue::Serialize(CSR_ERROR_NONE).pop();
        }
 
-       auto row = this->m_db->getDetectedByNameOnPath(target);
+       CsEngineContext csEngineContext(this->m_loader);
+       auto row = this->m_db->getDetectedAllByNameOnPath(target,
+                       this->m_loader->getEngineLatestUpdateTime(csEngineContext.get()));
 
        if (row && row->isIgnored)
                return BinaryQueue::Serialize(CSR_ERROR_NONE, row).pop();
@@ -682,9 +693,11 @@ RawBuffer CsLogic::getIgnoredList(const StrSet &_dirSet)
        for (const auto &dir : _dirSet)
                dirSet.emplace(canonicalizePath(dir, false));
 
+       CsEngineContext csEngineContext(this->m_loader);
+       auto since = this->m_loader->getEngineLatestUpdateTime(csEngineContext.get());
        Db::RowShPtrs rows;
        for (const auto &dir : dirSet) {
-               for (auto &row : this->m_db->getDetectedAllByNameOnDir(dir)) {
+               for (auto &row : this->m_db->getDetectedAllByNameOnDir(dir, since)) {
                        if (!row->fileInAppPath.empty() && !isReadable(row->targetName)) {
                                WARN("Exclude not-accessable malware detected file from the list: " <<
                                         row->targetName);
index f09b5ec..4ed8387 100644 (file)
@@ -84,18 +84,25 @@ BOOST_AUTO_TEST_CASE(scan_time)
 
        Db::Manager db(TEST_DB_FILE, TEST_DB_SCRIPTS);
 
-       std::string dir = "/opt";
-       long scantime = 100;
        std::string dataVersion = "1.0.0";
 
+       auto starttime = ::time(nullptr);
+
        db.cleanLastScanTime();
-       ASSERT_IF(db.getLastScanTime(dir, -1), -1);
-       db.insertLastScanTime(dir, scantime);
+       ASSERT_IF(db.getLastScanTime("/opt", starttime - 1), -1);
+
+       db.insertLastScanTime("/opt", dataVersion, starttime + 1);
+       db.insertLastScanTime("/opt/data", dataVersion, starttime + 3);
+       db.insertLastScanTime("/opt/data/etc", dataVersion, starttime + 2);
 
-       db.insertLastScanTime("/opt/data", scantime + 100);
-       db.insertLastScanTime("/opt/data/etc", scantime + 200);
+       ASSERT_IF(db.getLastScanTime("/opt/data/etc", starttime), starttime + 3);
+       ASSERT_IF(db.getLastScanTime("/opt/data", starttime), starttime + 3);
+       ASSERT_IF(db.getLastScanTime("/opt", starttime), starttime + 1);
+
+       ASSERT_IF(db.getLastScanTime("/opt/data/etc", starttime + 4), -1);
+       ASSERT_IF(db.getLastScanTime("/opt/data", starttime + 4), -1);
+       ASSERT_IF(db.getLastScanTime("/opt", starttime + 2), -1);
 
-       ASSERT_IF(db.getLastScanTime(dir, -1), scantime);
        db.cleanLastScanTime();
 
        EXCEPTION_GUARD_END
@@ -134,56 +141,82 @@ BOOST_AUTO_TEST_CASE(detected_malware_file)
        malware3.detailedUrl = "http://detailed3.malware.com";
        malware3.ts = starttime;
 
+       CsDetected malware4;
+       malware4.targetName = "/opt/testmalware4";
+       malware4.severity = CSR_CS_SEVERITY_LOW;
+       malware4.malwareName = "testmalware4";
+       malware4.detailedUrl = "http://detailed4.malware.com";
+       malware4.ts = starttime;
+
        // select test with vacant data
-       auto detected = db.getDetectedByNameOnPath(malware1.targetName);
+       auto detected = db.getDetectedAllByNameOnPath(malware1.targetName, 0);
        CHECK_IS_NULL(detected);
 
-       auto detectedList = db.getDetectedAllByNameOnDir("/opt");
+       auto detectedList = db.getDetectedAllByNameOnDir("/opt", 0);
        ASSERT_IF(detectedList.empty(), true);
 
-       db.insertDetectedFile(malware1.targetName, malware1);
-       detected = db.getDetectedByNameOnPath(malware1.targetName);
+       db.insertDetectedFile(malware1.targetName, malware1, initDataVersion);
+       detected = db.getDetectedAllByNameOnPath(malware1.targetName, 0);
+       CHECK_IS_NOT_NULL(detected);
        checkSameMalware(malware1, *detected);
+       ASSERT_IF(detected->dataVersion, initDataVersion);
        ASSERT_IF(detected->isIgnored, false);
 
-       db.insertDetectedFile(malware2.targetName, malware2);
+       db.insertDetectedFile(malware2.targetName, malware2, initDataVersion);
        db.updateIgnoreFlag(malware2.targetName, true);
-       detected = db.getDetectedByNameOnPath(malware2.targetName);
+       detected = db.getDetectedAllByNameOnPath(malware2.targetName, 0);
+       CHECK_IS_NOT_NULL(detected);
        checkSameMalware(malware2, *detected);
+       ASSERT_IF(detected->dataVersion, initDataVersion);
+       ASSERT_IF(detected->isIgnored, true);
+
+       db.insertDetectedFile(malware3.targetName, malware3, initDataVersion);
+       db.updateIgnoreFlag(malware3.targetName, true);
+       detected = db.getDetectedAllByNameOnPath(malware3.targetName, 0);
+       CHECK_IS_NOT_NULL(detected);
+       checkSameMalware(malware3, *detected);
+       ASSERT_IF(detected->dataVersion, initDataVersion);
        ASSERT_IF(detected->isIgnored, true);
 
        // getDetectedMalwares test
-       detectedList = db.getDetectedAllByNameOnDir("/opt");
-       ASSERT_IF(detectedList.size(), static_cast<size_t>(2));
+       detectedList = db.getDetectedAllByNameOnDir("/opt", 0);
+       ASSERT_IF(detectedList.size(), static_cast<size_t>(3));
 
        for (auto &item : detectedList) {
                if (malware1.targetName == item->targetName)
                        checkSameMalware(malware1, *item);
                else if (malware2.targetName == item->targetName)
                        checkSameMalware(malware2, *item);
+               else if (malware3.targetName == item->targetName)
+                       checkSameMalware(malware3, *item);
                else
                        BOOST_REQUIRE_MESSAGE(false, "Failed. getDetectedMalwares");
        }
 
        // setDetectedMalwareIgnored test
        db.updateIgnoreFlag(malware1.targetName, true);
-       detected = db.getDetectedByNameOnPath(malware1.targetName);
+       detected = db.getDetectedAllByNameOnPath(malware1.targetName, 0);
        checkSameMalware(malware1, *detected);
        ASSERT_IF(detected->isIgnored, true);
 
        // deleteDeprecatedDetectedMalwares test
-       db.insertDetectedFile(malware3.targetName, malware3);
+       db.insertDetectedFile(malware4.targetName, malware4, changedDataVersion);
        db.deleteDetectedDeprecated(3);
-       detected = db.getDetectedByNameOnPath(malware3.targetName);
-       checkSameMalware(malware3, *detected);
+       detected = db.getDetectedAllByNameOnPath(malware4.targetName, 0);
+       CHECK_IS_NOT_NULL(detected);
+       checkSameMalware(malware4, *detected);
+       ASSERT_IF(detected->dataVersion, changedDataVersion);
        ASSERT_IF(detected->isIgnored, false);
 
-       CHECK_IS_NULL(db.getDetectedByNameOnPath(malware1.targetName));
-       CHECK_IS_NULL(db.getDetectedByNameOnPath(malware2.targetName));
+       CHECK_IS_NULL(db.getDetectedAllByNameOnPath(malware1.targetName, 0));
+       CHECK_IS_NULL(db.getDetectedAllByNameOnPath(malware2.targetName, 0));
+       CHECK_IS_NOT_NULL(db.getDetectedAllByNameOnPath(malware3.targetName, 0));
 
        // deleteDetectedMalware test
        db.deleteDetectedByNameOnPath(malware3.targetName);
-       CHECK_IS_NULL(db.getDetectedByNameOnPath(malware3.targetName));
+       db.deleteDetectedByNameOnPath(malware4.targetName);
+       CHECK_IS_NULL(db.getDetectedAllByNameOnPath(malware3.targetName, 0));
+       CHECK_IS_NULL(db.getDetectedAllByNameOnPath(malware4.targetName, 0));
 
        EXCEPTION_GUARD_END
 }