[ProcessPool]
NumberOfProcesses=1
-NumberOfLoaderProcesses=1
\ No newline at end of file
+NumberOfLoaderProcesses=1
+
+## Mode=Previous_Operation
+## - If the loader proces is not prepared, the application will be executed using fork() & execv().
+## Mode=Default_Operation
+## - If the loader process is not prepared and is running, the application will be executed using the loader process.
+## - If the loader process is not running, the application will be executed using fork() & execv().
+## Mode=Always_Loader
+## - If the loader process is not executed, the launchpad executes a new loader process when getting the launch request.
+## - And then, the launch request will be delivered after the loader process is prepared.
+## - After processing the launch request, the launchpad executes the loader process when the pending request exists.
+## Mode=Always_Loader_Without_CPUChecker
+## - This mode is the modified version of "Mode=Always_Loader".
+## - After processing the launch request, the launchpad executes a new loader process without CPU Checker.
+[LaunchMode]
+Mode=Default_Operation
#include <utility>
#include "launchpad-process-pool/log_private.hh"
+#include "launchpad-process-pool/util.hh"
namespace launchpad {
namespace {
constexpr const char kKeyProcessPoolNumberOfLoaderProcesses[] =
"NumberOfLoaderProcesses";
+constexpr const char kTagLaunchMode[] = "LaunchMode";
+constexpr const char kKeyMode[] = "Mode";
+constexpr const char kValueModePreviousOperation[] = "PREVIOUS_OPERATION";
+constexpr const char kValueModeDefaultOperation[] = "DEFAULT_OPERATION";
+constexpr const char kValueModeAlwaysLoader[] = "ALWAYS_LOADER";
+constexpr const char kValueModeAlwaysLoaderWithoutCPUChecker[] =
+ "ALWAYS_LOADER_WITHOUT_CPUCHECKER";
+
} // namespace
const std::string& Config::MemoryStatus::GetLowKey() const {
return number_of_loader_processes_;
}
+Config::LaunchMode::LaunchMode(const IniParser& parser) {
+ auto mode = parser.Get(kTagLaunchMode, kKeyMode);
+ if (!mode.empty()) {
+ mode = ToUpper(mode);
+ if (mode == kValueModePreviousOperation)
+ mode_ = LaunchMode::Mode::PreviousOperation;
+ else if (mode == kValueModeDefaultOperation)
+ mode_ = LaunchMode::Mode::DefaultOperation;
+ else if (mode == kValueModeAlwaysLoader)
+ mode_ = LaunchMode::Mode::AlwaysLoader;
+ else if (mode == kValueModeAlwaysLoaderWithoutCPUChecker)
+ mode_ = LaunchMode::Mode::AlwaysLoaderWithoutCPUChecker;
+ }
+
+ _W("[LaunchMode] mode: %d(%s)", static_cast<int>(mode_), mode.c_str());
+}
+
+const Config::LaunchMode::Mode Config::LaunchMode::GetMode() const {
+ return mode_;
+}
+
Config& Config::GetInst() {
static Config inst;
return inst;
memory_monitor_(Config::MemoryMonitor(parser_)),
cpu_checker_(Config::CPUChecker(parser_)),
logger_(Config::Logger(parser_)),
- process_pool_(Config::ProcessPool(parser_)) {
+ process_pool_(Config::ProcessPool(parser_)),
+ launch_mode_(Config::LaunchMode(parser_)) {
}
const Config::MemoryStatus& Config::GetMemoryStatus() const {
return process_pool_;
}
+const Config::LaunchMode& Config::GetLaunchMode() const {
+ return launch_mode_;
+}
+
} // namespace launchpad
int number_of_loader_processes_ = 1;
};
+ class LaunchMode {
+ public:
+ enum class Mode : int {
+ PreviousOperation = 0,
+ DefaultOperation = 1,
+ AlwaysLoader = 2,
+ AlwaysLoaderWithoutCPUChecker = 3,
+ };
+
+ explicit LaunchMode(const IniParser& parser);
+
+ const Mode GetMode() const;
+
+ private:
+ Mode mode_ = Mode::DefaultOperation;
+ };
+
Config(const Config&) = delete;
Config& operator = (const Config&) = delete;
Config(Config&&) = delete;
const CPUChecker& GetCPUChecker() const;
const Logger& GetLogger() const;
const ProcessPool& GetProcessPool() const;
+ const LaunchMode& GetLaunchMode() const;
private:
Config();
CPUChecker cpu_checker_;
Logger logger_;
ProcessPool process_pool_;
+ LaunchMode launch_mode_;
};
} // namespace launchpad
_W("Candidate process: %d", pid);
if (pid > 0) {
SetPid(pid);
- if (IsPending()) {
+ if (RefCount() > 0) {
CPUBoostController::DoBoost(pid, CPUBoostController::Level::Strong,
10000);
}
return std::stoi(loader_id);
}
-inline bool CanUseLoaderContext(const std::shared_ptr<LoaderContext>& context) {
- return (context->IsHydraMode() || context->GetPid() > 0) &&
- !context->IsPending();
-}
-
-inline void CheckAndPrepareLoaderContext(LoaderContext* context) {
- if (!context->IsLaunchable())
- return;
-
- auto* hydra_loader_context = dynamic_cast<HydraLoaderContext*>(context);
- if (hydra_loader_context != nullptr)
- hydra_loader_context->Prepare();
-}
-
} // namespace
Launchpad::Launchpad(int argc, char** argv)
CPUBoostController::Clear(getpid());
return G_SOURCE_REMOVE;
}, this);
+ mode_ = Config::GetInst().GetLaunchMode().GetMode();
}
Launchpad::~Launchpad() {
_D("[PAD_CMD_CONNECT] client fd: %d", client_socket_->GetFd());
}
+bool Launchpad::CanUseLoaderContext(
+ const std::shared_ptr<LoaderContext>& context) {
+ if (context->IsPrepared())
+ return true;
+
+ if (mode_ == Config::LaunchMode::Mode::PreviousOperation)
+ return false;
+
+ if (mode_ == Config::LaunchMode::Mode::DefaultOperation) {
+ if (context->IsHydraMode())
+ return true;
+
+ return context->GetPid() > 0 && context->RefCount() == 0;
+ }
+
+ // Config::LaunchMode::Mode::AlwaysLoader
+ // Config::LaunchMode::Mode::AlwaysLoaderWithoutCPUChecker
+ if (context->GetPid() > 0)
+ return true;
+
+ return context->IsLaunchable();
+}
+
Launchpad::LaunchResult Launchpad::LaunchRequestPrepare(
std::shared_ptr<Request> request) {
auto* app_info = AppInfo::Create(request->GetBundle());
return LaunchResult::Success;
}
+Launchpad::LaunchResult Launchpad::LaunchRequestPend(
+ std::shared_ptr<Request> request) {
+ auto loader_context = request->GetAvailableLoaderContext();
+ if (loader_context->IsPrepared())
+ return LaunchResult::Continue;
+
+ _W("Loader context is not prepared");
+ loader_context->Ref();
+ if (loader_context->GetPid() <= 0)
+ loader_context->Prepare();
+
+ if (loader_context->GetPid() > 0) {
+ CPUBoostController::DoBoost(loader_context->GetPid(),
+ CPUBoostController::Level::Strong, 10000);
+ request->SendResult(loader_context->GetPid());
+ }
+
+ pending_requests_.push_back(std::move(request));
+ return LaunchResult::Pending;
+}
+
Launchpad::LaunchResult Launchpad::LaunchRequestDo(
std::shared_ptr<Request> request) {
auto loader_context = request->GetAvailableLoaderContext();
return ForkProcessing(request);
}
- if (!loader_context->IsPrepared()) {
- _W("Loader context is not prepared");
- loader_context->SetPending(true);
- CheckAndPrepareLoaderContext(loader_context.get());
- if (loader_context->GetPid() > 0) {
- CPUBoostController::DoBoost(loader_context->GetPid(),
- CPUBoostController::Level::Strong, 10000);
- request->SendResult(loader_context->GetPid());
- }
-
- pending_requests_.push_back(std::move(request));
+ if (LaunchRequestPend(request) == LaunchResult::Pending)
return LaunchResult::Pending;
- }
auto* app_info = request->GetAppInfo();
_W("Launch %d type process. appid: %s",
static_cast<int>(loader_context->GetType()),
app_info->GetAppId().c_str());
request->SetPid(loader_context->Deploy(app_info));
+
+ if ((mode_ == Config::LaunchMode::Mode::AlwaysLoaderWithoutCPUChecker) ||
+ (mode_ == Config::LaunchMode::Mode::AlwaysLoader &&
+ loader_context->RefCount() > 0))
+ loader_context->Prepare();
+
return LaunchResult::Success;
}
void Launchpad::OnLoaderPrepared(LoaderContext* loader_context) {
_W("Loader is prepared. name(%s), pid(%d)",
loader_context->GetLoaderName().c_str(), loader_context->GetPid());
- loader_context->SetPending(false);
+ loader_context->Unref();
auto iter = pending_requests_.begin();
while (iter != pending_requests_.end()) {
void Launchpad::OnLoaderLaunched(LoaderContext* loader_context) {
_W("Loader is launched. name(%s), pid(%d)",
loader_context->GetLoaderName().c_str(), loader_context->GetPid());
- if (!loader_context->IsPending())
+ if (loader_context->RefCount() == 0)
return;
for (auto& request : pending_requests_) {
#include <server_socket.hh>
#include "launchpad-process-pool/app_executor.hh"
+#include "launchpad-process-pool/config.hh"
+#include "launchpad-process-pool/loader_manager.hh"
#include "launchpad-process-pool/request.hh"
#include "launchpad-process-pool/signal_manager.hh"
-#include "launchpad-process-pool/loader_manager.hh"
namespace launchpad {
Fail = -1,
Success = 0,
Pending = 1,
+ Continue = 2,
};
Launchpad(int argc, char** argv);
void HandleConnectRequest(std::shared_ptr<Request> request);
void HandleLaunchRequest(std::shared_ptr<Request> request);
+ bool CanUseLoaderContext(const std::shared_ptr<LoaderContext>& context);
LaunchResult ForkProcessing(std::shared_ptr<Request> request);
LaunchResult LaunchRequestPrepare(std::shared_ptr<Request> request);
LaunchResult LaunchRequestDo(std::shared_ptr<Request> request);
+ LaunchResult LaunchRequestPend(std::shared_ptr<Request> request);
void LaunchRequestComplete(std::shared_ptr<Request> request);
void OnIOEventReceived(int fd, int condition) override;
std::unique_ptr<RegionFormatConfig> region_format_config_;
std::unique_ptr<Worker> cleaner_;
std::vector<std::shared_ptr<Request>> pending_requests_;
+ Config::LaunchMode::Mode mode_;
};
} // namespace launchpad
return true;
}
-void LoaderContext::SetPending(bool pending) {
- pending_ = pending;
+void LoaderContext::SetEventListener(IEvent* listener) {
+ listener_ = listener;
}
-bool LoaderContext::IsPending() const {
- return pending_;
+void LoaderContext::Ref() {
+ ref_count_++;
}
-void LoaderContext::SetEventListener(IEvent* listener) {
- listener_ = listener;
+void LoaderContext::Unref() {
+ ref_count_--;
+}
+
+uint32_t LoaderContext::RefCount() const {
+ return ref_count_;
}
void LoaderContext::SetLiveTimer() {
bool CanActivate(LoaderMethod method) const;
void UpdateState(LoaderMethod method, bool force);
bool IsLaunchable();
- void SetPending(bool pending);
- bool IsPending() const;
void SetEventListener(IEvent* listener);
+ void Ref();
+ void Unref();
+ uint32_t RefCount() const;
protected:
void SetPrepared(bool prepared);
private:
bool prepared_ = false;
- bool pending_ = false;
std::shared_ptr<LoaderInfo> loader_info_;
int loader_id_;
pid_t caller_pid_;
guint on_boot_timer_ = 0;
std::vector<std::string> condition_path_exists_;
IEvent* listener_ = nullptr;
+ uint32_t ref_count_ = 0;
};
} // namespace launchpad