[Refactoring] Improve SAM score through DC and GV improvement
[platform/core/dotnet/launcher.git] / NativeLauncher / tool / tac_common.cc
index 185aaf0..f7fb9ef 100644 (file)
  */
 
 #include <fstream>
+#include <json/json.h>
 #include <pkgmgr-info.h>
 #include <pkgmgr_installer_info.h>
-#include <json/json.h>
 
 #include "log.h"
 #include "utils.h"
-#include "ni_common.h"
 #include "tac_common.h"
 #include "db_manager.h"
 
 
 #define __XSTR(x) #x
 #define __STR(x) __XSTR(x)
-static const char* __TAC_DIR = __STR(TAC_DIR);
+static const char* __DOTNET_DIR = __STR(DOTNET_DIR);
+static const char* __READ_ONLY_APP_UPDATE_DIR = __STR(READ_ONLY_APP_UPDATE_DIR);
 #undef __STR
 #undef __XSTR
 
 static sqlite3 *tac_db = NULL;
-std::vector<std::string> restoreNuget;
-std::vector<std::string> enableNuget;
+static sqlite3 *tlc_db = NULL;
+static std::vector<std::string> restore_nuget;
+static std::vector<std::string> restore_library;
 
-void cleanupDirectory()
+static void cleanupDirectory()
 {
        std::vector<std::string> removeNuget;
-       for (auto& nuget : bf::recursive_directory_iterator(__TAC_DIR)) {
-               bool isExist = false;
-               for (auto& restore : restoreNuget) {
-                       if (!bf::is_directory(nuget.path())) {
-                               isExist = true;
-                       }
-                       if (strstr(nuget.path().c_str(), restore.c_str()) != NULL) {
-                               isExist = true;
-                               break;
+       try {
+               for (auto& nuget : bf::recursive_directory_iterator(__DOTNET_DIR)) {
+                       std::string nugetPath = nuget.path().string();
+                       if (!bf::is_directory(nugetPath) ||
+                               nugetPath.find(TLC_LIBRARIES_DIR) != std::string::npos ||
+                               nugetPath.find(__READ_ONLY_APP_UPDATE_DIR) != std::string::npos) {
+                               continue;
                        }
-               }
-               if (!isExist) {
-                       removeNuget.push_back(nuget.path().string());
-               }
-       }
 
-       for (auto& rm : removeNuget) {
-               if (!removeAll(rm)) {
-                       _ERR("Failed to remove of %s", rm.c_str());
+                       bool isExist = false;
+                       for (auto& restore : restore_nuget) {
+                               if (nugetPath == restore || nugetPath == getBaseName(restore)) {
+                                       isExist = true;
+                                       break;
+                               }
+                       }
+                       if (!isExist) {
+                               removeNuget.push_back(nugetPath);
+                       }
                }
-       }
-       removeNuget.clear();
-}
 
-void depsJsonParser(std::string pkgId, std::string depsJsonPath, std::string execName, bool isRestore)
-{
-       std::ifstream ifs(depsJsonPath);
-       Json::CharReaderBuilder reader;
-       Json::Value root;
-       std::string error;
-       if (ifs.is_open()) {
-               if (!Json::parseFromStream(reader, ifs, &root, &error)) {
-                       _INFO("Failed to parse of deps.json");
-                       ifs.close();
-                       return;
-               }
-               const Json::Value runtimeTargetName = root["runtimeTarget"]["name"];
-               const Json::Value nugetPackages = root["targets"][runtimeTargetName.asString().c_str()];
-               for (auto& nuget : nugetPackages.getMemberNames()) {
-                       if (strstr(nuget.c_str(), TIZEN_DOTNET_NUGET) != NULL ||
-                               strstr(nuget.c_str(), TIZEN_DOTNET_SDK_NUGET) != NULL ||
-                               strstr(nuget.c_str(), (execName.substr(0, execName.find(".Tizen."))).c_str()) != NULL ||
-                               strstr(nuget.c_str(), (execName.substr(0, execName.find(".dll"))).c_str()) != NULL) {
-                               continue;
-                       } else {
-                               const Json::Value assemblies = nugetPackages[nuget.c_str()]["runtime"];
-                               if (assemblies != Json::nullValue) {
-                                       const Json::Value dependencies = nugetPackages[nuget.c_str()]["dependencies"];
-                                       bool isDependency = false;
-                                       for (auto& dependency : dependencies.getMemberNames()) {
-                                               if (strstr(dependency.c_str(), TIZEN_DOTNET_NUGET) != NULL ||
-                                                       strstr(dependency.c_str(), NET_STANDARD_LIBRARY_NUGET) != NULL) {
-                                                       continue;
-                                               } else {
-                                                       isDependency = true;
-                                               }
-                                       }
-                                       if (!isDependency) {
-                                               _INFO("PackageId : [%s] / Nuget package : [%s]", pkgId.c_str(), nuget.c_str());
-                                               std::string name = nuget.substr(0, nuget.find('/'));
-                                               std::string version = nuget.substr(nuget.rfind('/') + 1);
-                                               std::string sql = "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
-                                                               "VALUES ('" + pkgId + "', '" + nuget + "', '" + name + "', '" + version + "');";
-                                               if (isRestore) {
-                                                       if (tac_db) {
-                                                               dbInsert(tac_db, TAC_APP_LIST_RESTORE_DB, sql);
-                                                               restoreNuget.push_back(concatPath(__TAC_DIR, name));
-                                                       }
-                                               } else {
-                                                       std::string nugetPath = concatPath(__TAC_DIR, nuget);
-                                                       if (bf::exists(nugetPath)) {
-                                                               for (auto& assembly : assemblies.getMemberNames()) {
-                                                                       std::string assemblyName = assembly.substr(assembly.rfind('/') + 1);
-                                                                       std::string originPath = concatPath(nugetPath, assemblyName);
-                                                                       if (bf::exists(originPath)) {
-                                                                               enableNuget.push_back(originPath);
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
+               for (auto& rm : removeNuget) {
+                       if (!removeAll(rm)) {
+                               _SERR("Failed to remove of %s", rm.c_str());
                        }
                }
-               ifs.close();
+               removeNuget.clear();
+       } catch (const bf::filesystem_error& error) {
+               _SERR("Failed to recursive directory: %s", error.what());
+               return;
        }
 }
 
 // callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach"
-static int restoreDBCb(pkgmgrinfo_appinfo_h handle, void *userData)
+static int tac_restoreDBCb(pkgmgrinfo_appinfo_h handle, void *userData)
 {
        char *pkgId = NULL;
        char *root = NULL;
        char *exec = NULL;
-       std::string rootPath;
-       std::string execName;
 
        int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId);
        if (ret != PMINFO_R_OK) {
-               fprintf(stderr, "Failed to get pkgid\n");
+               _SERR("Failed to get pkgid");
                return -1;
        }
 
        ret = pkgmgrinfo_appinfo_get_root_path(handle, &root);
        if (ret != PMINFO_R_OK) {
-               fprintf(stderr, "Failed to get root path\n");
+               _SERR("Failed to get root path");
                return -1;
        }
-       rootPath = root;
+       std::string rootPath = std::string(root);
 
        ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
        if (ret != PMINFO_R_OK) {
-               fprintf(stderr, "Failed to get exec name\n");
+               _SERR("Failed to get exec name");
                return -1;
        }
-       execName = std::string(exec).substr(std::string(exec).rfind('/') + 1);
+       std::string execName = std::string(exec).substr(std::string(exec).rfind('/') + 1);
 
-       std::string depsJsonName = execName.substr(0, execName.rfind(".dll")) + ".deps.json";
-       std::string depsJsonPath = concatPath(rootPath, depsJsonName);
-       if (bf::exists(depsJsonPath)) {
-               depsJsonParser(pkgId, depsJsonPath, execName, true);
+       enableTACPackage(std::string(pkgId));
+
+       std::vector<std::string> parserData;
+       std::string binDir = concatPath(rootPath, "bin");
+       std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
+       for (auto& npAssembly : depsJsonParser(rootPath, execName)) {
+               std::string nugetPackage = npAssembly.substr(0, npAssembly.rfind(':'));
+               std::string assemblyName = npAssembly.substr(npAssembly.rfind(':') + 1);
+               if (exist(tacDir) && exist(concatPath(tacDir, assemblyName))) {
+                       parserData.push_back(nugetPackage);
+               }
+       }
+       std::sort(parserData.begin(), parserData.end());
+       parserData.erase(unique(parserData.begin(), parserData.end()), parserData.end());
+
+       for (auto& nuget : parserData) {
+               if (tac_db) {
+                       std::string name = nuget.substr(0, nuget.find('/'));
+                       std::string version = nuget.substr(nuget.rfind('/') + 1);
+                       char *sql = sqlite3_mprintf(
+                               "INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
+                               "VALUES (%Q, %Q, %Q, %Q);",     pkgId, nuget.c_str(), name.c_str(), version.c_str());
+                       insertDB(tac_db, sql);
+                       restore_nuget.push_back(concatPath(__DOTNET_DIR, nuget));
+                       sqlite3_free(sql);
+               }
        }
+       parserData.clear();
+
        return 0;
 }
 
-tac_error_e restoreTACDB()
+tac_error_e tac_restoreDB()
 {
        if (!removeFile(TAC_APP_LIST_RESTORE_DB)) {
-               fprintf(stderr, "Failed to remove of %s", TAC_APP_LIST_RESTORE_DB);
+               _SERR("Failed to remove of %s", TAC_APP_LIST_RESTORE_DB);
                return TAC_ERROR_UNKNOWN;
        }
 
        std::string dbRestoreJournal = TAC_APP_LIST_RESTORE_DB + std::string("-journal");
        if (!removeFile(dbRestoreJournal)) {
-               fprintf(stderr, "Failed to remove of %s", dbRestoreJournal.c_str());
+               _SERR("Failed to remove of %s", dbRestoreJournal.c_str());
                return TAC_ERROR_UNKNOWN;
        }
 
-       tac_db = dbCreate(TAC_APP_LIST_RESTORE_DB);
-       if (tac_db) {
-               if (!dbOpen(tac_db, TAC_APP_LIST_RESTORE_DB)) {
-                       return TAC_ERROR_UNKNOWN;
-               }
-       } else {
+       tac_db = createDB(TAC_APP_LIST_RESTORE_DB, CREATE_TAC_DB_TABLE);
+       if (!tac_db) {
+               _SERR("Sqlite create error");
                return TAC_ERROR_UNKNOWN;
        }
+       sqlite3_exec(tac_db, "BEGIN;", NULL, NULL, NULL);
 
        pkgmgrinfo_appinfo_metadata_filter_h handle;
        int ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle);
@@ -196,249 +162,376 @@ tac_error_e restoreTACDB()
                return TAC_ERROR_UNKNOWN;
        }
 
-       ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, TAC_METADATA_KEY, METADATA_VALUE);
+       ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, TAC_METADATA_KEY, METADATA_VALUE_TRUE);
        if (ret != PMINFO_R_OK) {
                pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
                return TAC_ERROR_UNKNOWN;
        }
 
-       ret = pkgmgrinfo_appinfo_metadata_filter_foreach(handle, restoreDBCb, NULL);
-       if (ret != PMINFO_R_OK) {
-               fprintf(stderr, "Failed pkgmgrinfo_appinfo_metadata_filter_foreach\n");
+       ret = pkgmgrMDFilterForeach(handle, tac_restoreDBCb, NULL);
+       if (ret != 0) {
                pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
                return TAC_ERROR_UNKNOWN;
        }
-       fprintf(stderr, "Success pkgmgrinfo_appinfo_metadata_filter_foreach\n");
 
        pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
 
        if (tac_db) {
-               dbClose(tac_db);
+               closeDB(tac_db);
                tac_db = NULL;
        }
 
        if (!copyFile(TAC_APP_LIST_RESTORE_DB, TAC_APP_LIST_DB)) {
-               fprintf(stderr, "Failed to move of %s", TAC_APP_LIST_DB);
+               _SERR("Failed to copy of %s", TAC_APP_LIST_DB);
                return TAC_ERROR_UNKNOWN;
        }
        if (!removeFile(TAC_APP_LIST_RESTORE_DB)) {
-               fprintf(stderr, "Failed to remove of %s", TAC_APP_LIST_RESTORE_DB);
+               _SERR("Failed to remove of %s", TAC_APP_LIST_RESTORE_DB);
                return TAC_ERROR_UNKNOWN;
        }
 
        std::string dbJournal = TAC_APP_LIST_DB + std::string("-journal");
        if (!copyFile(dbRestoreJournal, dbJournal)) {
-               fprintf(stderr, "Failed to move of %s", dbJournal.c_str());
+               _SERR("Failed to copy of %s", dbJournal.c_str());
                return TAC_ERROR_UNKNOWN;
        }
        if (!removeFile(dbRestoreJournal)) {
-               fprintf(stderr, "Failed to remove of %s", dbRestoreJournal.c_str());
+               _SERR("Failed to remove of %s", dbRestoreJournal.c_str());
                return TAC_ERROR_UNKNOWN;
        }
 
        cleanupDirectory();
+
        return TAC_ERROR_NONE;
 }
 
-tac_error_e resetTACPackage(const std::string& pkgId)
+tac_error_e disableTACPackage(const std::string& pkgId)
 {
-       std::string pkgRoot;
-       if (getRootPath(pkgId, pkgRoot) < 0) {
+       std::string rootPath = getRootPath(pkgId);
+       if (rootPath.empty()) {
+               _SERR("Failed to get root path from [%s]", pkgId.c_str());
                return TAC_ERROR_INVALID_PACKAGE;
        }
 
-       std::vector<std::string> tacNativeImage;
-       std::string binDir = concatPath(pkgRoot, "bin");
+       std::string binDir = concatPath(rootPath, "bin");
        std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
-       if (bf::exists(tacDir)) {
-               for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) {
-                       std::string symPath = symlinkAssembly.path().string();
-                       if (bf::is_symlink(symPath)) {
-                               if (isNativeImage(symPath)) {
-                                       tacNativeImage.push_back(symPath);
+       std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
+       if (exist(tacDir)) {
+               try {
+                       for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) {
+                               std::string symPath = symlinkAssembly.path().string();
+                               std::string fileName = symlinkAssembly.path().filename().string();
+                               if (isSymlinkFile(symPath)) {
+                                       std::string originPath = bf::read_symlink(symPath).string();
+                                       if (!isNativeImage(symPath)) {
+                                               std::string dllPath = concatPath(binDir, fileName);
+                                               if (!copyFile(originPath, dllPath)) {
+                                                       _SERR("Failed to copy of %s", dllPath.c_str());
+                                                       return TAC_ERROR_UNKNOWN;
+                                               }
+                                               copySmackAndOwnership(binDir.c_str(), concatPath(binDir, fileName).c_str());
+                                       } else {
+                                               std::string niPath = concatPath(binNIDir, fileName);
+                                               if (!copyFile(originPath, niPath)) {
+                                                       _SERR("Failed to copy of %s", niPath.c_str());
+                                                       return TAC_ERROR_UNKNOWN;
+                                               }
+                                               copySmackAndOwnership(binDir.c_str(), niPath.c_str());
+                                       }
                                }
                        }
-               }
-               for (auto& path : tacNativeImage) {
-                       if (!removeFile(path)) {
-                               fprintf(stderr, "Failed to remove of %s", path.c_str());
+                       if (!removeAll(tacDir)) {
+                               _SERR("Failed to remove of %s", tacDir.c_str());
                                return TAC_ERROR_UNKNOWN;
                        }
+               } catch (const bf::filesystem_error& error) {
+                       _SERR("Failed to recursive directory: %s", error.what());
+                       return TAC_ERROR_UNKNOWN;
                }
        }
-       tacNativeImage.clear();
        return TAC_ERROR_NONE;
 }
 
-tac_error_e createTACPackage(const std::string& pkgId)
+static tac_error_e createSymlinkFile(const std::string& tacDir, const std::string& binDir, const std::string& from, const std::string& to)
 {
-       std::string pkgRoot;
-       if (getRootPath(pkgId, pkgRoot) < 0) {
+       bs::error_code error;
+       bf::create_symlink(from, concatPath(tacDir, to), error);
+       if (error) {
+               _SERR("Failed to create symlink %s file", concatPath(tacDir, to).c_str());
+               return TAC_ERROR_UNKNOWN;
+       }
+       _SOUT("%s symbolic link file generated successfully.", concatPath(tacDir, to).c_str());
+       copySmackAndOwnership(tacDir.c_str(), concatPath(tacDir, to).c_str(), true);
+
+       if (!removeFile(concatPath(binDir, to))) {
+               _SERR("Failed to remove of %s", concatPath(binDir, to).c_str());
+               return TAC_ERROR_UNKNOWN;
+       }
+       return TAC_ERROR_NONE;
+}
+
+tac_error_e enableTACPackage(const std::string& pkgId)
+{
+       std::string rootPath = getRootPath(pkgId);
+       if (rootPath.empty()) {
+               _SERR("Failed to get root path from [%s]", pkgId.c_str());
                return TAC_ERROR_INVALID_PACKAGE;
        }
 
-       std::string binDir = concatPath(pkgRoot, "bin");
+       std::string binDir = concatPath(rootPath, "bin");
+       if (exist(concatPath(binDir, PRE_COMPILED_PACKAGE_FILE))) {
+               _INFO("The %s is a Pre-Compiled package. So, skip the TAC", pkgId.c_str());
+               return TAC_ERROR_NONE;
+       }
+
+       std::string execName = getExecName(pkgId);
+       if (execName.empty()) {
+               _SERR("Failed to get exec name from [%s]", pkgId.c_str());
+               return TAC_ERROR_INVALID_PACKAGE;
+       }
+
+       std::string metaValue = getMetadataValue(pkgId, TAC_METADATA_KEY);
+       if (metaValue.empty()) {
+               _SERR("Failed to get metadata from [%s]", pkgId.c_str());
+               return TAC_ERROR_INVALID_PACKAGE;
+       }
+
+       if (strcmp(metaValue.c_str(), METADATA_VALUE_TRUE)) {
+               _SERR("The metadata key is missing or the metadata value is false of [%s]", pkgId.c_str());
+               return TAC_ERROR_NONE;
+       }
+
        std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
        std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
-       if (bf::exists(tacDir)) {
-               for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) {
-                       std::string symPath = symlinkAssembly.path().string();
-                       if (bf::is_symlink(symPath)) {
-                               if (!isNativeImage(symPath)) {
-                                       std::string originPath = bf::read_symlink(symPath).string();
-                                       std::string originNiPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll";
-                                       if (!bf::exists(originNiPath)) {
-                                               if(createNiDll(originPath, false) != NI_ERROR_NONE) {
-                                                       fprintf(stderr, "Failed to create NI file [%s]\n", originPath.c_str());
-                                                       return TAC_ERROR_UNKNOWN;
-                                               }
+       if (exist(tacDir)) {
+               return TAC_ERROR_NONE;
+       }
+
+       if (!createDir(tacDir)) {
+               _SERR("Cannot create directory: %s", tacDir.c_str());
+               return TAC_ERROR_UNKNOWN;
+       }
+       copySmackAndOwnership(binDir.c_str(), tacDir.c_str());
+
+       std::vector<std::string> enableNuget;
+       for (auto& npAssembly : depsJsonParser(rootPath, execName)) {
+               std::string nugetPackage = npAssembly.substr(0, npAssembly.rfind(':'));
+               std::string assemblyName = npAssembly.substr(npAssembly.rfind(':') + 1);
+               std::string nugetPath = concatPath(__DOTNET_DIR, nugetPackage);
+               if (exist(nugetPath)) {
+                       std::string originPath = concatPath(nugetPath, assemblyName);
+                       if (exist(originPath)) {
+                               enableNuget.push_back(originPath);
+                       }
+               }
+       }
+
+       if (enableNuget.empty()) {
+               if (!removeAll(tacDir)) {
+                       _SERR("Failed to remove of %s", tacDir.c_str());
+               }
+               return TAC_ERROR_NONE;
+       }
+
+       for (auto& originPath : enableNuget) {
+               if (exist(originPath)) {
+                       std::string fileName = originPath.substr(originPath.rfind('/') + 1);
+                       if (exist(binNIDir)) {
+                               std::string originNIPath = changeExtension(originPath, "dll", "ni.dll");
+                               if (exist(originNIPath)) {
+                                       if (createSymlinkFile(tacDir, binNIDir, originNIPath, changeExtension(fileName, "dll", "ni.dll")) != TAC_ERROR_NONE) {
+                                               return TAC_ERROR_UNKNOWN;
                                        }
-                                       std::string symNIPath = symPath.substr(0, symPath.rfind(".dll")) + ".ni.dll";
-                                       if (!bf::exists(symNIPath)) {
-                                               bf::create_symlink(originNiPath, symNIPath);
-                                               fprintf(stderr, "%s symbolic link file generated successfully.\n", symNIPath.c_str());
-                                               updateAssemblyInfo(tacDir.c_str(), symNIPath.c_str(), true);
-
-                                               std::string NIFileName = symNIPath.substr(symNIPath.rfind('/') + 1);
-                                               if (!removeFile(concatPath(binNIDir, NIFileName))) {
-                                                       fprintf(stderr, "Failed to remove of %s\n", concatPath(binNIDir, NIFileName).c_str());
-                                                       return TAC_ERROR_UNKNOWN;
+                               }
+                       }
+                       if (createSymlinkFile(tacDir, binDir, originPath, fileName) != TAC_ERROR_NONE) {
+                               return TAC_ERROR_UNKNOWN;
+                       }
+               }
+       }
+       enableNuget.clear();
+
+       return TAC_ERROR_NONE;
+}
+
+//Parser the .deps.json file to get nuget information.
+std::vector<std::string> depsJsonParser(const std::string& rootPath, const std::string& execName)
+{
+       std::vector<std::string> parserData;
+       std::string depsJsonName = changeExtension(execName, "dll", "deps.json");
+       std::string depsJsonPath = concatPath(rootPath, depsJsonName);
+       try {
+               if (exist(depsJsonPath)) {
+                       std::ifstream ifs(depsJsonPath);
+                       Json::CharReaderBuilder reader;
+                       Json::Value root;
+                       std::string error;
+                       if (ifs.is_open()) {
+                               if (!Json::parseFromStream(reader, ifs, &root, &error)) {
+                                       _ERR("Failed to parse of deps.json");
+                                       ifs.close();
+                                       return parserData;
+                               }
+                               const Json::Value runtimeTargetName = root["runtimeTarget"]["name"];
+                               const Json::Value nugetPackages = root["targets"][runtimeTargetName.asString().c_str()];
+                               for (auto& nuget : nugetPackages.getMemberNames()) {
+                                       //Skip the nuget package related to Tizen
+                                       if (strstr(nuget.c_str(), TIZEN_DOTNET_NUGET) == NULL &&
+                                               strstr(nuget.c_str(), TIZEN_DOTNET_SDK_NUGET) == NULL &&
+                                               strstr(nuget.c_str(), (execName.substr(0, execName.find(".Tizen."))).c_str()) == NULL &&
+                                               strstr(nuget.c_str(), (execName.substr(0, execName.find(".dll"))).c_str()) == NULL) {
+                                               const Json::Value assemblies = nugetPackages[nuget.c_str()]["runtime"];
+                                               if (assemblies != Json::nullValue) {
+                                                       // handle assembly even though that is included in the TPA.
+                                                       for (auto& assembly : assemblies.getMemberNames()) {
+                                                               std::string assemblyName = assembly.substr(assembly.rfind('/') + 1);
+                                                               parserData.push_back(nuget + ":" + assemblyName);
+                                                               _INFO("Nuget : [%s] / Assembly : [%s]", nuget.c_str(), assemblyName.c_str());
+                                                       }
                                                }
                                        }
                                }
+                               ifs.close();
                        }
                }
+       } catch (const Json::Exception& error) {
+               _ERR("Failed to parse Json: %s", error.what());
        }
-       return TAC_ERROR_NONE;
+       return parserData;
 }
 
-tac_error_e regenerateTAC()
+std::vector<std::string> getLibrariesInfo(const std::string& rootPath)
 {
-       const std::string tacDir[] = {__TAC_DIR};
-       removeNiUnderDirs(tacDir, 1);
-
-       auto convert = [](const std::string& path, std::string name) {
-               if (strstr(path.c_str(), TAC_APP_LIST_DB) != NULL ||
-                       strstr(path.c_str(), TAC_APP_LIST_RESTORE_DB) != NULL ||
-                       strstr(path.c_str(), TAC_SHA_256_INFO) != NULL)
-                       return;
-               if(createNiDll(path, false) != NI_ERROR_NONE) {
-                       fprintf(stderr, "Failed to create NI file [%s]\n", path.c_str());
-                       return;
+       std::vector<std::string> LibrariesInfo;
+       std::string binDir = concatPath(rootPath, "bin");
+       if (!exist(binDir))
+               return LibrariesInfo;
+
+       auto convert = [&LibrariesInfo](const std::string& filepath, const std::string& filename) {
+               if (filename.find(".so", filename.size() - 3) != std::string::npos || filepath.rfind(".so.") != std::string::npos) {
+                       std::string buffer = SHA256(filepath);
+                       LibrariesInfo.push_back(filepath + ":" + buffer);
+                       _INFO("Library : [%s] / SHA256 : [%s]", filename.c_str(), buffer.c_str());
                }
        };
-       scanFilesInDir(tacDir[0], convert, -1);
-       return TAC_ERROR_NONE;
+       scanFilesInDirectory(binDir, convert, -1);
+
+       return LibrariesInfo;
 }
 
-tac_error_e disableTACPackage(const std::string& pkgId)
+// callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach"
+static int tlc_restoreDBCb(pkgmgrinfo_appinfo_h handle, void *userData)
 {
-       std::string pkgRoot;
-       if (getRootPath(pkgId, pkgRoot) < 0) {
-               return TAC_ERROR_INVALID_PACKAGE;
+       char *pkgId = NULL;
+       char *root = NULL;
+       std::string rootPath;
+
+       int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId);
+       if (ret != PMINFO_R_OK) {
+               _SERR("Failed to get pkgid");
+               return -1;
        }
 
-       std::string binDir = concatPath(pkgRoot, "bin");
-       std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
-       std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
-       if (bf::exists(tacDir)) {
-               for (auto& symlinkAssembly : bf::recursive_directory_iterator(tacDir)) {
-                       std::string symPath = symlinkAssembly.path().string();
-                       std::string fileName = symlinkAssembly.path().filename().string();
-                       if (bf::is_symlink(symPath)) {
-                               std::string originPath = bf::read_symlink(symPath).string();
-                               if (!isNativeImage(symPath)) {
-                                       if (!copyFile(originPath, concatPath(binDir, fileName))) {
-                                               fprintf(stderr, "Failed to copy of %s\n", concatPath(binDir, fileName).c_str());
-                                               return TAC_ERROR_UNKNOWN;
-                                       }
-                                       updateAssemblyInfo(binDir.c_str(), concatPath(binDir, fileName).c_str());
-                               } else {
-                                       if (!copyFile(originPath, concatPath(binNIDir, fileName))) {
-                                               fprintf(stderr, "Failed to copy of %s\n", concatPath(binNIDir, fileName).c_str());
-                                               return TAC_ERROR_UNKNOWN;
-                                       }
-                                       updateAssemblyInfo(binDir.c_str(), concatPath(binNIDir, fileName).c_str());
-                               }
-                       }
-               }
+       ret = pkgmgrinfo_appinfo_get_root_path(handle, &root);
+       if (ret != PMINFO_R_OK) {
+               _SERR("Failed to get root path");
+               return -1;
        }
-       if (!removeAll(tacDir)) {
-               fprintf(stderr, "Failed to remove of %s\n", tacDir.c_str());
-               return TAC_ERROR_UNKNOWN;
+       rootPath = std::string(root);
+
+       for (auto& librarySha : getLibrariesInfo(rootPath)) {
+               std::string library = librarySha.substr(0, librarySha.find(':'));
+               if (exist(library)) {
+                       std::string fileSha = library.substr(library.rfind('/') + 1) + ".." + librarySha.substr(librarySha.find(':') + 1);
+                       char *sql = sqlite3_mprintf("INSERT INTO TLC (PKGID, LIBRARY) VALUES (%Q, %Q);", pkgId, fileSha.c_str());
+                       insertDB(tlc_db, sql);
+                       restore_library.push_back(fileSha);
+                       sqlite3_free(sql);
+               }
        }
-       return TAC_ERROR_NONE;
+       return 0;
 }
 
-tac_error_e enableTACPackage(const std::string& pkgId)
+tac_error_e tlc_restoreDB()
 {
-       std::string pkgRoot;
-       if (getRootPath(pkgId, pkgRoot) < 0) {
-               return TAC_ERROR_INVALID_PACKAGE;
+       if (!removeFile(TLC_APP_LIST_RESTORE_DB)) {
+               _SERR("Failed to remove of %s", TLC_APP_LIST_RESTORE_DB);
+               return TAC_ERROR_UNKNOWN;
        }
 
-       std::string execName;
-       if (getExecName(pkgId, execName) < 0) {
-               return TAC_ERROR_INVALID_PACKAGE;
+       std::string dbRestoreJournal = TLC_APP_LIST_RESTORE_DB + std::string("-journal");
+       if (!removeFile(dbRestoreJournal)) {
+               _SERR("Failed to remove of %s", dbRestoreJournal.c_str());
+               return TAC_ERROR_UNKNOWN;
        }
 
-       std::string metaValue;
-       if (getMetadataValue(pkgId, TAC_METADATA_KEY, metaValue) < 0) {
-               return TAC_ERROR_INVALID_PACKAGE;
+       tlc_db = createDB(TLC_APP_LIST_RESTORE_DB, CREATE_TLC_DB_TABLE);
+       if (!tlc_db) {
+               _SERR("Sqlite create error");
+               return TAC_ERROR_UNKNOWN;
        }
+       sqlite3_exec(tlc_db, "BEGIN;", NULL, NULL, NULL);
 
-       if (!strcmp(metaValue.c_str(), "true")) {
-               std::string binDir = concatPath(pkgRoot, "bin");
-               std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
-               std::string binNIDir = concatPath(binDir, APP_NI_SUB_DIR);
-               if (!bf::exists(tacDir)) {
-                       if (!createDir(tacDir)) {
-                               fprintf(stderr, "Cannot create directory: %s\n", tacDir.c_str());
-                               return TAC_ERROR_UNKNOWN;
-                       }
-                       updateAssemblyInfo(binDir.c_str(), tacDir.c_str());
+       pkgmgrinfo_appinfo_metadata_filter_h handle;
+       int ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle);
+       if (ret != PMINFO_R_OK) {
+               return TAC_ERROR_UNKNOWN;
+       }
 
-                       std::string depsJsonName = execName.substr(0, execName.rfind(".dll")) + ".deps.json";
-                       std::string depsJsonPath = concatPath(pkgRoot, depsJsonName);
-                       if (bf::exists(depsJsonPath)) {
-                               depsJsonParser(pkgId, depsJsonPath, execName, false);
-                       }
+       ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, TAC_METADATA_KEY, METADATA_VALUE_TRUE);
+       if (ret != PMINFO_R_OK) {
+               pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
+               return TAC_ERROR_UNKNOWN;
+       }
 
-                       for (auto& originPath : enableNuget) {
-                               if (bf::exists(originPath)) {
-                                       std::string fileName = originPath.substr(originPath.rfind('/') + 1);
-                                       std::string NIFileName = fileName.substr(0, fileName.rfind(".dll")) + ".ni.dll";
-                                       if (bf::exists(binNIDir)) {
-                                               std::string originNIPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll";
-                                               if (bf::exists(originNIPath)) {
-                                                       bf::create_symlink(originNIPath, concatPath(tacDir, NIFileName));
-                                                       fprintf(stderr, "%s symbolic link file generated successfully.\n", concatPath(tacDir, NIFileName).c_str());
-                                                       updateAssemblyInfo(tacDir.c_str(), concatPath(tacDir, NIFileName).c_str(), true);
-
-                                                       if (!removeFile(concatPath(binNIDir, NIFileName))) {
-                                                               fprintf(stderr, "Failed to remove of %s\n", concatPath(binNIDir, NIFileName).c_str());
-                                                               return TAC_ERROR_UNKNOWN;
-                                                       }
-                                               }
-                                       }
-                                       bf::create_symlink(originPath, concatPath(tacDir, fileName));
-                                       fprintf(stderr, "%s symbolic link file generated successfully.\n", concatPath(tacDir, fileName).c_str());
-                                       updateAssemblyInfo(tacDir.c_str(), concatPath(tacDir, fileName).c_str(), true);
+       ret = pkgmgrMDFilterForeach(handle, tlc_restoreDBCb, NULL);
+       if (ret != 0) {
+               pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
+               return TAC_ERROR_UNKNOWN;
+       }
 
-                                       if (!removeFile(concatPath(binDir, fileName))) {
-                                               fprintf(stderr, "Failed to remove of %s\n", concatPath(binDir, fileName).c_str());
-                                               return TAC_ERROR_UNKNOWN;
-                                       }
-                               }
+       pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
+
+       if (tlc_db) {
+               closeDB(tlc_db);
+               tlc_db = NULL;
+       }
+
+       if (!copyFile(TLC_APP_LIST_RESTORE_DB, TLC_APP_LIST_DB)) {
+               _SERR("Failed to copy of %s", TLC_APP_LIST_DB);
+               return TAC_ERROR_UNKNOWN;
+       }
+       if (!removeFile(TLC_APP_LIST_RESTORE_DB)) {
+               _SERR("Failed to remove of %s", TLC_APP_LIST_RESTORE_DB);
+               return TAC_ERROR_UNKNOWN;
+       }
+
+       std::string dbJournal = TLC_APP_LIST_DB + std::string("-journal");
+       if (!copyFile(dbRestoreJournal, dbJournal)) {
+               _SERR("Failed to copy of %s", dbJournal.c_str());
+               return TAC_ERROR_UNKNOWN;
+       }
+       if (!removeFile(dbRestoreJournal)) {
+               _SERR("Failed to remove of %s", dbRestoreJournal.c_str());
+               return TAC_ERROR_UNKNOWN;
+       }
+
+       auto convert = [](const std::string& path, const std::string& filename) {
+               bool isExist = false;
+               for (auto& library : restore_library) {
+                       if (!strcmp(filename.c_str(), library.c_str())) {
+                               isExist = true;
+                               break;
                        }
-                       if (enableNuget.empty()) {
-                               if (!removeAll(tacDir)) {
-                                       _ERR("Failed to remove of %s", tacDir.c_str());
-                               }
+               }
+               if (!isExist) {
+                       if (!removeFile(path)) {
+                               _ERR("Failed to remove of %s", path.c_str());
                        }
                }
-       } else {
-               fprintf(stderr, "The metadata key is missing or the metadata value is false of [%s]\n", pkgId.c_str());
-       }
+       };
+
+       scanFilesInDirectory(TLC_LIBRARIES_DIR, convert, 0);
+
        return TAC_ERROR_NONE;
 }