Make up recovery file for sudden power loss 44/216744/4
authorJunghyun Yeon <jungh.yeon@samsung.com>
Thu, 31 Oct 2019 11:17:50 +0000 (20:17 +0900)
committerJunghyun Yeon <jungh.yeon@samsung.com>
Thu, 7 Nov 2019 07:48:35 +0000 (16:48 +0900)
- Backup recovery file itself before replace it with new one
- pkg_recovery now determines which recovery file to use :
  backed up one and original one.
  If both backup and original exists, backup will be removed.
  If only backup exists, it renames as original and will be used.
  If only original exists, it will be used directly.

Change-Id: I8a11841b36111decbba6c9091f27a05f4debcb9a
Signed-off-by: Junghyun Yeon <jungh.yeon@samsung.com>
src/common/recovery_file.cc
src/common/recovery_file.h
src/pkg_recovery/pkg_recovery.cc

index 6481475..f28f0f3 100644 (file)
@@ -88,6 +88,7 @@ std::unique_ptr<RecoveryFile> RecoveryFile::OpenRecoveryFile(
 
 RecoveryFile::RecoveryFile(const bf::path& path, RequestType type, bool load)
     : type_(type), path_(path), backup_done_(false), cleanup_(false) {
+  backup_path_ = path_.string() + ".bck";
   if (load) {
     if (!ReadFileContent()) {
       path_.clear();
@@ -106,6 +107,8 @@ RecoveryFile::RecoveryFile(const bf::path& path, RequestType type, bool load)
 RecoveryFile::~RecoveryFile() {
   if (Remove(path_))
     LOG(DEBUG) << "Recovery file " << path_ << " removed";
+  if (Remove(backup_path_))
+    LOG(DEBUG) << "Recovery file " << backup_path_ << " removed";
 }
 
 void RecoveryFile::Detach() {
@@ -208,7 +211,17 @@ bool RecoveryFile::ReadFileContent() {
 }
 
 bool RecoveryFile::WriteAndCommitFileContent() {
-  Remove(path_);
+  if (bf::exists(path_))  {
+    bs::error_code error;
+    bf::rename(path_, backup_path_, error);
+    if (error) {
+      LOG(ERROR) << "Cannot backup recovery file:" << path_ <<
+          ", error: " << error;
+      return false;
+    }
+    sync();
+  }
+
   FILE* handle = fopen(path_.c_str(), "wx");
   if (!handle) {
     LOG(ERROR) << "Cannot write recovery file";
@@ -254,6 +267,8 @@ bool RecoveryFile::WriteAndCommitFileContent() {
   fputs("\n", handle);
   fclose(handle);
   sync();
+
+  Remove(backup_path_);
   return true;
 }
 
index 39face2..93adc3f 100644 (file)
@@ -140,6 +140,7 @@ class RecoveryFile {
   std::string pkgid_;
 
   boost::filesystem::path path_;
+  boost::filesystem::path backup_path_;
   bool backup_done_;
   bool cleanup_;
 };
index 7724c8d..0a8d80f 100644 (file)
@@ -25,7 +25,8 @@ namespace {
 
 typedef std::pair<std::string, std::string> RecoverEntry;
 
-const char kRecoveryFilePattern[] = "^(.*)-recovery-(.*)";
+const char kRecoveryFilePattern[] = "^(.*)-recovery-(.){6}$";
+const char kBackupFilePattern[] = "^(.*)-recovery-(.){6}\.bck$";
 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
 
 class PkgRecoveryService {
@@ -35,6 +36,7 @@ class PkgRecoveryService {
   void Run();
 
  private:
+  void SearchBackupFiles(uid_t uid);
   std::vector<RecoverEntry> SearchRecoveryFiles(uid_t uid);
   void ProcessRecovery(uid_t uid, const std::vector<RecoverEntry>& entries);
   bool RunBackend(uid_t uid, const char* type, const char* file);
@@ -60,6 +62,7 @@ bool PkgRecoveryService::RunBackend(uid_t uid, const char* type,
 
 void PkgRecoveryService::Run() {
   // recover global packages
+  SearchBackupFiles(kGlobalUserUid);
   LOG(INFO) << "Searching recovery files for user " << kGlobalUserUid;
   std::vector<RecoverEntry> globalentries = SearchRecoveryFiles(kGlobalUserUid);
   ProcessRecovery(kGlobalUserUid, globalentries);
@@ -69,11 +72,36 @@ void PkgRecoveryService::Run() {
   for (auto userinfo : list) {
     uid_t uid = std::get<0>(userinfo);
     LOG(INFO) << "Searching recovery files for user " << std::get<0>(userinfo);
+    SearchBackupFiles(uid);
     std::vector<RecoverEntry> entries = SearchRecoveryFiles(uid);
     ProcessRecovery(uid, entries);
   }
 }
 
+void PkgRecoveryService::SearchBackupFiles(uid_t uid) {
+  const bf::path recovery_dir = ci::GetRootAppPath(false, uid);
+  for (bf::directory_iterator iter(recovery_dir);
+      iter != bf::directory_iterator();
+      ++iter) {
+    try {
+      std::string file = iter->path().filename().string();
+      std::regex backup_regex(kBackupFilePattern);
+      std::smatch match;
+      if (std::regex_search(file, match, backup_regex)) {
+        bf::path orig_file(iter->path().parent_path() / iter->path().stem());
+        if (bf::exists(orig_file))
+          bf::remove(iter->path());
+        else
+          bf::rename(iter->path(), orig_file);
+      }
+    } catch (...) {
+      LOG(WARNING) << "Exception occurred: "
+                   << boost::current_exception_diagnostic_information();
+      continue;
+    }
+  }
+}
+
 std::vector<RecoverEntry> PkgRecoveryService::SearchRecoveryFiles(uid_t uid) {
   std::vector<RecoverEntry> list;
   const bf::path recovery_dir = ci::GetRootAppPath(false, uid);