1 //
2 // Copyright RIME Developers
3 // Distributed under the BSD License
4 //
5 // 2011-12-01 GONG Chen <chen.sst@gmail.com>
6 //
7 #include <chrono>
8 #include <utility>
9 #include <boost/date_time/posix_time/posix_time_types.hpp>
10 #include <boost/filesystem.hpp>
11 #include <rime/deployer.h>
12
13 namespace rime {
14
Deployer()15 Deployer::Deployer() : shared_data_dir("."),
16 user_data_dir("."),
17 prebuilt_data_dir("build"),
18 staging_dir("build"),
19 sync_dir("sync"),
20 user_id("unknown") {
21 }
22
~Deployer()23 Deployer::~Deployer() {
24 JoinWorkThread();
25 }
26
RunTask(const string & task_name,TaskInitializer arg)27 bool Deployer::RunTask(const string& task_name, TaskInitializer arg) {
28 auto c = DeploymentTask::Require(task_name);
29 if (!c) {
30 LOG(ERROR) << "unknown deployment task: " << task_name;
31 return false;
32 }
33 the<DeploymentTask> t(c->Create(arg));
34 if (!t) {
35 LOG(ERROR) << "error creating deployment task: " << task_name;
36 return false;
37 }
38 return t->Run(this);
39 }
40
ScheduleTask(const string & task_name,TaskInitializer arg)41 bool Deployer::ScheduleTask(const string& task_name, TaskInitializer arg) {
42 auto c = DeploymentTask::Require(task_name);
43 if (!c) {
44 LOG(ERROR) << "unknown deployment task: " << task_name;
45 return false;
46 }
47 an<DeploymentTask> t(c->Create(arg));
48 if (!t) {
49 LOG(ERROR) << "error creating deployment task: " << task_name;
50 return false;
51 }
52 ScheduleTask(t);
53 return true;
54 }
55
ScheduleTask(an<DeploymentTask> task)56 void Deployer::ScheduleTask(an<DeploymentTask> task) {
57 std::lock_guard<std::mutex> lock(mutex_);
58 pending_tasks_.push(task);
59 }
60
NextTask()61 an<DeploymentTask> Deployer::NextTask() {
62 std::lock_guard<std::mutex> lock(mutex_);
63 if (!pending_tasks_.empty()) {
64 auto result = pending_tasks_.front();
65 pending_tasks_.pop();
66 return result;
67 }
68 // there is still chance that a task is added by another thread
69 // right after this call... careful.
70 return nullptr;
71 }
72
HasPendingTasks()73 bool Deployer::HasPendingTasks() {
74 std::lock_guard<std::mutex> lock(mutex_);
75 return !pending_tasks_.empty();
76 }
77
Run()78 bool Deployer::Run() {
79 LOG(INFO) << "running deployment tasks:";
80 message_sink_("deploy", "start");
81 int success = 0;
82 int failure = 0;
83 do {
84 while (auto task = NextTask()) {
85 if (task->Run(this))
86 ++success;
87 else
88 ++failure;
89 //boost::this_thread::interruption_point();
90 }
91 LOG(INFO) << success + failure << " tasks ran: "
92 << success << " success, " << failure << " failure.";
93 message_sink_("deploy", !failure ? "success" : "failure");
94 // new tasks could have been enqueued while we were sending the message.
95 // before quitting, double check if there is nothing left to do.
96 }
97 while (HasPendingTasks());
98 return !failure;
99 }
100
StartWork(bool maintenance_mode)101 bool Deployer::StartWork(bool maintenance_mode) {
102 if (IsWorking()) {
103 LOG(WARNING) << "a work thread is already running.";
104 return false;
105 }
106 maintenance_mode_ = maintenance_mode;
107 if (pending_tasks_.empty()) {
108 return false;
109 }
110 LOG(INFO) << "starting work thread for "
111 << pending_tasks_.size() << " tasks.";
112 work_ = std::async(std::launch::async, [this] { Run(); });
113 return work_.valid();
114 }
115
StartMaintenance()116 bool Deployer::StartMaintenance() {
117 return StartWork(true);
118 }
119
IsWorking()120 bool Deployer::IsWorking() {
121 if (!work_.valid())
122 return false;
123 auto status = work_.wait_for(std::chrono::milliseconds(0));
124 return status != std::future_status::ready;
125 }
126
IsMaintenanceMode()127 bool Deployer::IsMaintenanceMode() {
128 return maintenance_mode_ && IsWorking();
129 }
130
JoinWorkThread()131 void Deployer::JoinWorkThread() {
132 if (work_.valid())
133 work_.get();
134 }
135
JoinMaintenanceThread()136 void Deployer::JoinMaintenanceThread() {
137 JoinWorkThread();
138 }
139
user_data_sync_dir() const140 string Deployer::user_data_sync_dir() const {
141 return (boost::filesystem::path(sync_dir) / user_id).string();
142 }
143
144 } // namespace rime
145