Send pkgmgr signal always 99/34399/3
authorTomasz Iwanek <t.iwanek@samsung.com>
Wed, 4 Feb 2015 12:22:44 +0000 (13:22 +0100)
committerPawel Sikorski <p.sikorski@samsung.com>
Tue, 10 Feb 2015 15:03:35 +0000 (07:03 -0800)
Zip or config.xml can be malformed.
This fixes handling signalling in those cases.

Code which handles pkgmgr signal was extracted into
 - src/common/pkgmgr_signal.*

Change-Id: I46b96f6ba8cd2c41110f2fefbceb6dc1b2969216

src/common/CMakeLists.txt
src/common/app_installer.cc
src/common/app_installer.h
src/common/context_installer.h
src/common/pkgmgr_signal.cc [new file with mode: 0644]
src/common/pkgmgr_signal.h [new file with mode: 0644]
src/common/step/step_signal.cc
src/common/step/step_signal.h

index 9c8dea8..8b2ef6b 100644 (file)
@@ -2,6 +2,7 @@
 SET(SRCS
   app_installer.cc
   context_installer.cc
+  pkgmgr_signal.cc
   security_registration.cc
   step/step_unzip.cc
   step/step_signature.cc
index 8bfb153..cef0eb1 100644 (file)
@@ -5,13 +5,14 @@
 
 #include "common/app_installer.h"
 #include "common/context_installer.h"
+#include "common/pkgmgr_signal.h"
 
 namespace common_installer {
 
-AppInstaller::AppInstaller(pkgmgr_installer *pi) {
-  context_.reset(new ContextInstaller());
+AppInstaller::AppInstaller(pkgmgr_installer *pi)
+    : context_(new ContextInstaller()) {
   int request_type = pkgmgr_installer_get_request_type(pi);
-  context_->set_pi(pi);
+  context_->set_pi(std::unique_ptr<PkgmgrSignal>(new PkgmgrSignal(pi)));
   context_->set_request_type(request_type);
   switch (request_type) {
     case PKGMGR_REQ_INSTALL:
@@ -28,6 +29,14 @@ AppInstaller::AppInstaller(pkgmgr_installer *pi) {
 AppInstaller::~AppInstaller() {
 }
 
+void AppInstaller::EnsureSignalSend() {
+  if (!context_->pi()->IsFinished()) {
+    // if signal was not sent during normal step execution
+    // then this will sent any signal about failure
+    (void) context_->pi()->sendStarted();
+    (void) context_->pi()->sendFinished(PkgmgrSignal::Result::FAILED);
+  }
+}
 
 int AppInstaller::Run() {
   std::list<std::unique_ptr<Step>>::iterator it(steps_.begin());
@@ -59,6 +68,9 @@ int AppInstaller::Run() {
       }
     }
   }
+
+  EnsureSignalSend();
+
   return ret;
 }
 
index d5cb2ae..760d16c 100644 (file)
@@ -9,7 +9,6 @@
 
 #include "common/step/step.h"
 
-
 namespace common_installer {
 
 class AppInstaller {
@@ -28,14 +27,14 @@ class AppInstaller {
 
   int Run();
 
- protected:
-  std::unique_ptr<ContextInstaller> context_;
-
  private:
   AppInstaller(const AppInstaller& /*other*/) = delete;
   AppInstaller& operator=(const AppInstaller& /*other*/) = delete;
 
+  void EnsureSignalSend();
+
   std::list<std::unique_ptr<Step>> steps_;
+  std::unique_ptr<ContextInstaller> context_;
 };
 
 }  // namespace common_installer
index 99ec0ce..bef7764 100644 (file)
@@ -4,7 +4,6 @@
 #define COMMON_CONTEXT_INSTALLER_H_
 
 #include <pkgmgr_parser.h>
-#include <pkgmgr_installer.h>
 
 #include <unistd.h>
 #include <sys/types.h>
@@ -12,6 +11,8 @@
 #include <memory>
 #include <string>
 
+#include "common/pkgmgr_signal.h"
+
 namespace common_installer {
 
 class ConfigData;
@@ -76,8 +77,8 @@ class ContextInstaller {
     file_path_ = file_path;
   }
 
-  void set_pi(pkgmgr_installer* pi) {
-    pi_ = pi;
+  void set_pi(std::unique_ptr<PkgmgrSignal> pi) {
+    pi_ = std::move(pi);
   }
 
   uid_t uid() const { return uid_; }
@@ -89,7 +90,7 @@ class ContextInstaller {
 
   ConfigData* config_data() const { return config_data_.get(); }
 
-  pkgmgr_installer* pi() const { return pi_; }
+  PkgmgrSignal* pi() const { return pi_.get(); }
 
   const char* GetApplicationPath() const;
   const char* GetRootApplicationPath() const;
@@ -123,7 +124,7 @@ class ContextInstaller {
   ConfigDataPtr config_data_;
 
   // data used to send signal
-  pkgmgr_installer *pi_;
+  std::unique_ptr<PkgmgrSignal> pi_;
 };
 
 }  // namespace common_installer
diff --git a/src/common/pkgmgr_signal.cc b/src/common/pkgmgr_signal.cc
new file mode 100644 (file)
index 0000000..e3e64ff
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "common/pkgmgr_signal.h"
+
+#include <cassert>
+#include <iostream>
+
+#define DBG(msg) std::cout << "[PkgmgrSignal] " << msg << std::endl;
+#define ERR(msg) std::cout << "[ERROR: PkgmgrSignal] " << msg << std::endl;
+
+namespace common_installer {
+
+PkgmgrSignal::PkgmgrSignal(pkgmgr_installer* pi)
+    : pi_(pi),
+      state_(State::NOT_SENT) {
+}
+
+bool PkgmgrSignal::sendStarted(
+    const std::string& type, const std::string& pkgid) {
+  if (state_ != State::NOT_SENT) {
+    return false;
+  }
+
+  if (!SendSignal(PKGMGR_INSTALLER_START_KEY_STR,
+      (pkgmgr_installer_get_request_type(pi_) != PKGMGR_REQ_UNINSTALL)
+      ? PKGMGR_INSTALLER_INSTALL_EVENT_STR
+      : PKGMGR_INSTALLER_UNINSTALL_EVENT_STR,
+      type, pkgid)) {
+    return false;
+  }
+  state_ = State::STARTED;
+  return true;
+}
+
+bool PkgmgrSignal::sendFinished(
+    Result result, const std::string& type, const std::string& pkgid) {
+  if (state_ != State::STARTED) {
+    return false;
+  }
+  if (!SendSignal(
+        PKGMGR_INSTALLER_END_KEY_STR, GetResultKey(result), type, pkgid)) {
+    return false;
+  }
+  state_ = State::FINISHED;
+  return true;
+}
+
+bool PkgmgrSignal::IsFinished() const {
+  return state_ == State::FINISHED;
+}
+
+bool PkgmgrSignal::SendSignal(
+    const char* key,
+    const char* value,
+    const std::string& type,
+    const std::string& pkgid) const {
+  // send pkgmgr signal
+  if (pkgmgr_installer_send_signal(
+        pi_,
+        !type.empty() ?  type.c_str(): "",
+        !pkgid.empty() ? pkgid.c_str() : "",
+        key,
+        value)) {
+    ERR("Fail to send pkgmgr signal");
+    return false;
+  }
+
+  DBG("Success to send pkgmgr signal PKGID=" << pkgid
+                                << " KEY=" << key
+                                << " VALUE=" << value);
+  return true;
+}
+
+const char* PkgmgrSignal::GetResultKey(Result result) const {
+  switch (result) {
+    case Result::SUCCESS:
+      return PKGMGR_INSTALLER_OK_EVENT_STR;
+    case Result::FAILED:
+      return PKGMGR_INSTALLER_FAIL_EVENT_STR;
+    default:
+      assert(false && "Not Reached");
+  }
+}
+
+}  // namespace common_installer
diff --git a/src/common/pkgmgr_signal.h b/src/common/pkgmgr_signal.h
new file mode 100644 (file)
index 0000000..f32db2d
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_PKGMGR_SIGNAL_H_
+#define COMMON_PKGMGR_SIGNAL_H_
+
+#include <pkgmgr_installer.h>
+
+#include <memory>
+#include <string>
+
+namespace common_installer {
+
+//
+// Utility for sending signal to pkgmgr
+//
+// One installation process should not create more than one instance of this
+// class. Object contains state of signaling and will report error if
+// used in wrong way.
+//
+class PkgmgrSignal {
+ public:
+  enum class Result {
+    SUCCESS,
+    FAILED
+  };
+
+  explicit PkgmgrSignal(pkgmgr_installer* pi);
+
+  bool sendStarted(
+      const std::string& type = std::string(),
+      const std::string& pkgid = std::string());
+  bool sendFinished(
+      Result result,
+      const std::string& type = std::string(),
+      const std::string& pkgid = std::string());
+  bool IsFinished() const;
+
+ private:
+  enum class State {
+    NOT_SENT,
+    STARTED,
+    FINISHED
+  };
+
+  bool SendSignal(
+      const char* key,
+      const char* value,
+      const std::string& type = std::string(),
+      const std::string& pkgid = std::string()) const;
+  const char* GetResultKey(Result result) const;
+
+  pkgmgr_installer* pi_;
+  State state_;
+
+  // TODO(t.iwanek): use DISALLOW_COPY_AND_ASSIGN
+  PkgmgrSignal(const PkgmgrSignal&) = delete;
+  PkgmgrSignal& operator=(const PkgmgrSignal&) = delete;
+};
+
+}  // namespace common_installer
+
+#endif  // COMMON_PKGMGR_SIGNAL_H_
index 7ce189f..209552d 100644 (file)
@@ -2,9 +2,6 @@
 
 #include "common/step/step_signal.h"
 
-#include <pkgmgr-info.h>
-#include <unistd.h>
-
 #include <iostream>
 
 #include "common/utils.h"
 namespace common_installer {
 namespace signal {
 
-bool StepSignal::sendSignal(ContextInstaller* context, const std::string& key,
-                              const std::string& value) {
-    if (!context->pi()) {
-        ERR("PkgmgrSingal not yet intialized");
-        return false;
-    }
-
-    if (key.empty() || value.empty()) {
-        DBG("key or value is empty");
-        return false;
-    }
-
-    // send pkgmgr signal
-    if (pkgmgr_installer_send_signal(
-            context->pi(), context->manifest_data()->type,
-            context->pkgid().c_str(),
-            key.c_str(), value.c_str())) {
-        ERR("Fail to send pkgmgr signal");
-        return false;
-    }
-
-    DBG("Success to send pkgmgr signal");
-    return true;
-}
-
 Step::Status StepSignal::process() {
-  sendSignal(context_, PKGMGR_INSTALLER_START_KEY_STR,
-      PKGMGR_INSTALLER_INSTALL_EVENT_STR);
+  if (!context_->pi()->sendStarted(
+      context_->manifest_data()->type, context_->pkgid())) {
+    return Status::ERROR;
+  }
   DBG("Send Start");
   return Status::OK;
 }
 
 Step::Status StepSignal::clean() {
-  sendSignal(context_, PKGMGR_INSTALLER_END_KEY_STR,
-      PKGMGR_INSTALLER_OK_EVENT_STR);
+  if (!context_->pi()->sendFinished(
+        PkgmgrSignal::Result::SUCCESS,
+        context_->manifest_data()->type, context_->pkgid())) {
+    return Status::ERROR;
+  }
   DBG("Send Success");
   return Status::OK;
 }
 
 Step::Status StepSignal::undo() {
-  sendSignal(context_, PKGMGR_INSTALLER_END_KEY_STR,
-      PKGMGR_INSTALLER_FAIL_EVENT_STR);
+  if (!context_->pi()->sendFinished(
+        PkgmgrSignal::Result::FAILED,
+        context_->manifest_data()->type, context_->pkgid())) {
+    return Status::ERROR;
+  }
   DBG("Send Error");
   return Status::OK;
 }
 
-
-
-
-
 }  // namespace signal
 }  // namespace common_installer
index 8198360..5843294 100644 (file)
@@ -19,10 +19,6 @@ class StepSignal : public Step {
   Status process() override;
   Status clean() override;
   Status undo() override;
-
- private:
-  bool sendSignal(ContextInstaller* data, const std::string& key,
-      const std::string& value);
 };
 
 }  // namespace signal