blob: e654e92d2e8364e0306ddad05741fed5c01370c7 [file] [log] [blame]
Yan Wangcdb97fa2019-10-18 18:18:48 -07001// Copyright (C) 2019 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "compiler/compiler.h"
16#include "maintenance/controller.h"
17
Yan Wang23d4cc32019-11-13 18:16:59 -080018#include "common/cmd_utils.h"
Yan Wangcdb97fa2019-10-18 18:18:48 -070019#include "common/debug.h"
20#include "common/expected.h"
Igor Murashkin70401f42020-03-04 13:57:12 -080021#include "common/trace.h"
Yan Wangcdb97fa2019-10-18 18:18:48 -070022
23#include "db/models.h"
Yan Wangcdb97fa2019-10-18 18:18:48 -070024#include "inode2filename/inode.h"
25#include "inode2filename/search_directories.h"
Igor Murashkin0a7cb8c2020-03-03 15:57:05 -080026#include "prefetcher/read_ahead.h"
Yan Wangcdb97fa2019-10-18 18:18:48 -070027
28#include <android-base/file.h>
Igor Murashkin0a7cb8c2020-03-03 15:57:05 -080029#include <utils/Printer.h>
Yan Wangcdb97fa2019-10-18 18:18:48 -070030
Yan Wang23a7e3e2020-03-13 14:09:26 -070031#include <chrono>
Igor Murashkin0a7cb8c2020-03-03 15:57:05 -080032#include <ctime>
Yan Wangcdb97fa2019-10-18 18:18:48 -070033#include <iostream>
34#include <filesystem>
35#include <fstream>
36#include <limits>
Igor Murashkin0a7cb8c2020-03-03 15:57:05 -080037#include <mutex>
Yan Wangcdb97fa2019-10-18 18:18:48 -070038#include <optional>
39#include <vector>
40#include <string>
Yan Wang9608f272020-02-21 19:16:28 -080041#include <sys/wait.h>
Yan Wangcdb97fa2019-10-18 18:18:48 -070042
43namespace iorap::maintenance {
44
Yan Wang23a7e3e2020-03-13 14:09:26 -070045const constexpr int64_t kCompilerCheckIntervalMs = 10;
Igor Murashkin0a7cb8c2020-03-03 15:57:05 -080046static constexpr size_t kMinTracesForCompilation = 3;
47
48struct LastJobInfo {
49 time_t last_run_ns_{0};
50 size_t activities_last_compiled_{0};
51};
52
53LastJobInfo last_job_info_;
54std::mutex last_job_info_mutex_;
55
Yan Wang23d4cc32019-11-13 18:16:59 -080056// Gets the path of output compiled trace.
57db::CompiledTraceFileModel CalculateNewestFilePath(
58 const std::string& package_name,
59 const std::string& activity_name,
Yan Wang16b8fce2020-02-20 18:08:33 +000060 int version) {
Yan Wang23d4cc32019-11-13 18:16:59 -080061 db::VersionedComponentName versioned_component_name{
62 package_name, activity_name, version};
63
64 db::CompiledTraceFileModel output_file =
65 db::CompiledTraceFileModel::CalculateNewestFilePath(versioned_component_name);
66
67 return output_file;
68}
69
Yan Wang65e905d2019-11-16 14:49:56 -080070using ArgString = const char*;
71
Yan Wang23d4cc32019-11-13 18:16:59 -080072static constexpr const char kCommandFileName[] = "/system/bin/iorap.cmd.compiler";
73
Yan Wang65e905d2019-11-16 14:49:56 -080074int Exec::Execve(const std::string& pathname,
75 std::vector<std::string>& argv_vec,
76 char *const envp[]) {
77 std::unique_ptr<ArgString[]> argv_ptr =
78 common::VecToArgv(kCommandFileName, argv_vec);
79
80 return execve(pathname.c_str(), (char**)argv_ptr.get(), envp);
81}
82
83pid_t Exec::Fork() {
84 return fork();
85}
86
Yan Wang23d4cc32019-11-13 18:16:59 -080087// Represents the parameters used when fork+exec compiler.
88struct CompilerForkParameters {
89 std::vector<std::string> input_pbs;
90 std::vector<uint64_t> timestamp_limit_ns;
91 std::string output_proto;
92 ControllerParameters controller_params;
93
94 CompilerForkParameters(const std::vector<compiler::CompilationInput>& perfetto_traces,
95 const std::string& output_proto,
96 ControllerParameters controller_params) :
97 output_proto(output_proto), controller_params(controller_params) {
98 for (compiler::CompilationInput perfetto_trace : perfetto_traces) {
99 input_pbs.push_back(perfetto_trace.filename);
100 timestamp_limit_ns.push_back(perfetto_trace.timestamp_limit_ns);
101 }
102 }
103};
104
Yan Wang23d4cc32019-11-13 18:16:59 -0800105std::vector<std::string> MakeCompilerParams(const CompilerForkParameters& params) {
106 std::vector<std::string> argv;
107 ControllerParameters controller_params = params.controller_params;
108
109 common::AppendArgsRepeatedly(argv, params.input_pbs);
110 common::AppendArgsRepeatedly(argv, "--timestamp_limit_ns", params.timestamp_limit_ns);
111
112 if (controller_params.output_text) {
113 argv.push_back("--output-text");
114 }
115
116 common::AppendArgs(argv, "--output-proto", params.output_proto);
117
118 if (controller_params.inode_textcache) {
119 common::AppendArgs(argv, "--inode-textcache", *controller_params.inode_textcache);
120 }
121
122 if (controller_params.verbose) {
123 argv.push_back("--verbose");
124 }
125
126 return argv;
127}
128
Yan Wang23a7e3e2020-03-13 14:09:26 -0700129// Sets a watch dog for the given pid and kill it if timeout.
130std::thread SetTimeoutWatchDog(pid_t pid, int64_t timeout_ms, std::atomic<bool>& cancel_watchdog) {
131 std::thread watchdog_thread{[&]() {
132 std::chrono::time_point start = std::chrono::system_clock::now();
133 std::chrono::milliseconds timeout(timeout_ms);
134 while (!cancel_watchdog) {
135 int status = kill(pid, 0);
136 if (status != 0) {
137 LOG(DEBUG) << "Process (" << pid << ") doesn't exist now.";
138 break;
139 }
140 std::chrono::time_point cur = std::chrono::system_clock::now();
141 if (cur - start > timeout) {
142 LOG(INFO) << "Process (" << pid << ") is timeout!";
143 kill(pid, SIGKILL);
144 break;
145 }
146 usleep(kCompilerCheckIntervalMs * 1000);
147 }
148 }};
149
150 return watchdog_thread;
151}
152
Yan Wang23d4cc32019-11-13 18:16:59 -0800153bool StartViaFork(const CompilerForkParameters& params) {
Yan Wang65e905d2019-11-16 14:49:56 -0800154 const ControllerParameters& controller_params = params.controller_params;
155 pid_t child = controller_params.exec->Fork();
Yan Wang23d4cc32019-11-13 18:16:59 -0800156
157 if (child == -1) {
158 LOG(FATAL) << "Failed to fork a process for compilation";
159 } else if (child > 0) { // we are the caller of this function
160 LOG(DEBUG) << "forked into a process for compilation , pid = " << child;
Yan Wang9608f272020-02-21 19:16:28 -0800161
Yan Wang23a7e3e2020-03-13 14:09:26 -0700162 int64_t compiler_timeout_ms =
163 android::base::GetIntProperty("iorapd.maintenance.compiler_timeout_ms",
164 /*default*/ 10 * 60 * 1000); // 10 min
165 std::atomic<bool> cancel_watchdog(false);
166 std::thread watchdog_thread = SetTimeoutWatchDog(child, compiler_timeout_ms, cancel_watchdog);
Yan Wang9608f272020-02-21 19:16:28 -0800167 int wstatus;
168 waitpid(child, /*out*/&wstatus, /*options*/0);
Yan Wang23a7e3e2020-03-13 14:09:26 -0700169
170 // Terminate the thread after the compiler process is killed or done.
171 LOG(DEBUG) << "Terminate the watch dog thread.";
172 cancel_watchdog = true;
173 watchdog_thread.join();
174
Yan Wang9608f272020-02-21 19:16:28 -0800175 if (!WIFEXITED(wstatus)) {
176 LOG(ERROR) << "Child terminated abnormally, status: " << WEXITSTATUS(wstatus);
177 return false;
178 }
Yan Wang9608f272020-02-21 19:16:28 -0800179
Yan Wang39247542020-05-21 18:23:46 +0000180 int status = WEXITSTATUS(wstatus);
181 LOG(DEBUG) << "Child terminated, status: " << status;
182 if (status == 0) {
183 LOG(DEBUG) << "Iorap compilation succeeded";
184 return true;
185 } else {
186 LOG(ERROR) << "Iorap compilation failed";
187 return false;
188 }
Yan Wang23d4cc32019-11-13 18:16:59 -0800189 } else {
190 // we are the child that was forked.
191 std::vector<std::string> argv_vec = MakeCompilerParams(params);
192 std::unique_ptr<ArgString[]> argv_ptr =
193 common::VecToArgv(kCommandFileName, argv_vec);
194
195 std::stringstream argv; // for debugging.
196 for (std::string arg : argv_vec) {
197 argv << arg << ' ';
198 }
199 LOG(DEBUG) << "fork+exec: " << kCommandFileName << " " << argv.str();
200
Yan Wang65e905d2019-11-16 14:49:56 -0800201 controller_params.exec->Execve(kCommandFileName,
202 argv_vec,
203 /*envp*/nullptr);
Yan Wang23d4cc32019-11-13 18:16:59 -0800204 // This should never return.
Yan Wang23d4cc32019-11-13 18:16:59 -0800205 }
Yan Wang23d4cc32019-11-13 18:16:59 -0800206 return false;
207}
208
Yan Wangcdb97fa2019-10-18 18:18:48 -0700209// Gets the perfetto trace infos in the histories.
210std::vector<compiler::CompilationInput> GetPerfettoTraceInfo(
211 const db::DbHandle& db,
212 const std::vector<db::AppLaunchHistoryModel>& histories) {
213 std::vector<compiler::CompilationInput> perfetto_traces;
214
215 for(db::AppLaunchHistoryModel history : histories) {
216 // Get perfetto trace.
217 std::optional<db::RawTraceModel> raw_trace =
218 db::RawTraceModel::SelectByHistoryId(db, history.id);
219 if (!raw_trace) {
Igor Murashkinbb392252020-03-24 13:44:18 -0700220 // This is normal: non-cold launches do not have traces.
Yan Wangcdb97fa2019-10-18 18:18:48 -0700221 continue;
222 }
223
224 uint64_t timestamp_limit = std::numeric_limits<uint64_t>::max();
225 // Get corresponding timestamp limit.
226 if (history.report_fully_drawn_ns) {
227 timestamp_limit = *history.report_fully_drawn_ns;
228 } else if (history.total_time_ns) {
229 timestamp_limit = *history.total_time_ns;
230 } else {
231 LOG(ERROR) << " No timestamp exists. Using the max value.";
232 }
233 perfetto_traces.push_back({raw_trace->file_path, timestamp_limit});
234 }
235 return perfetto_traces;
236}
237
Yan Wangcdb97fa2019-10-18 18:18:48 -0700238// Helper struct for printing vector.
239template <class T>
240struct VectorPrinter {
241 std::vector<T>& values;
242};
243
244std::ostream& operator<<(std::ostream& os,
245 const struct compiler::CompilationInput& perfetto_trace) {
246 os << "file_path: " << perfetto_trace.filename << " "
247 << "timestamp_limit: " << perfetto_trace.timestamp_limit_ns;
248 return os;
249}
250
251template <class T>
252std::ostream& operator<<(std::ostream& os, const struct VectorPrinter<T>& printer) {
253 os << "[\n";
254 for (T i : printer.values) {
255 os << i << ",\n";
256 }
257 os << "]\n";
258 return os;
259}
260
261// Compiled the perfetto traces for an activity.
262bool CompileActivity(const db::DbHandle& db,
263 int package_id,
264 const std::string& package_name,
265 const std::string& activity_name,
Yan Wang16b8fce2020-02-20 18:08:33 +0000266 int version,
Yan Wang23d4cc32019-11-13 18:16:59 -0800267 const ControllerParameters& params) {
Igor Murashkin70401f42020-03-04 13:57:12 -0800268 ScopedFormatTrace atrace_compile_package(ATRACE_TAG_PACKAGE_MANAGER,
269 "Compile activity %s",
270 activity_name.c_str());
271
Igor Murashkinbb392252020-03-24 13:44:18 -0700272 LOG(DEBUG) << "CompileActivity: " << package_name << "/" << activity_name << "@" << version;
273
Yan Wang65e905d2019-11-16 14:49:56 -0800274 db::CompiledTraceFileModel output_file =
Yan Wang16b8fce2020-02-20 18:08:33 +0000275 CalculateNewestFilePath(package_name, activity_name, version);
Yan Wang23d4cc32019-11-13 18:16:59 -0800276
Yan Wangcdb97fa2019-10-18 18:18:48 -0700277 std::string file_path = output_file.FilePath();
278
Igor Murashkina3bdf6e2020-04-03 15:37:19 -0700279 if (!params.recompile) {
280 if (std::filesystem::exists(file_path)) {
281 LOG(DEBUG) << "compiled trace exists in " << file_path;
282
283 db::VersionedComponentName vcn{package_name, activity_name, version};
284 std::optional<db::PrefetchFileModel> prefetch_file =
285 db::PrefetchFileModel::SelectByVersionedComponentName(db, vcn);
286 if (prefetch_file) {
287 return true;
288 } else {
289 LOG(WARNING) << "Missing corresponding prefetch_file db row for " << vcn;
290 // let it go and compile again. we'll insert the prefetch_file at the bottom.
291 }
292 }
Yan Wangcdb97fa2019-10-18 18:18:48 -0700293 }
294
Yan Wangcdb97fa2019-10-18 18:18:48 -0700295 std::optional<db::ActivityModel> activity =
296 db::ActivityModel::SelectByNameAndPackageId(db, activity_name.c_str(), package_id);
297 if (!activity) {
298 LOG(ERROR) << "Cannot find activity for package_id: " << package_id
299 <<" activity_name: " <<activity_name;
300 return false;
301 }
302
303 int activity_id = activity->id;
304
305 std::vector<db::AppLaunchHistoryModel> histories =
306 db::AppLaunchHistoryModel::SelectActivityHistoryForCompile(db, activity_id);
307
308 {
309 std::vector<compiler::CompilationInput> perfetto_traces =
310 GetPerfettoTraceInfo(db, histories);
311
Yan Wangb5a4b032019-11-14 12:10:04 -0800312 if (perfetto_traces.size() < params.min_traces) {
313 LOG(DEBUG) << "The number of perfetto traces is " << perfetto_traces.size()
314 <<", which is less than " << params.min_traces;
315 return false;
316 }
317
Igor Murashkin0a7cb8c2020-03-03 15:57:05 -0800318 {
319 std::lock_guard<std::mutex> last_job_info_guard{last_job_info_mutex_};
320 last_job_info_.activities_last_compiled_++;
321 }
322
Yan Wangcdb97fa2019-10-18 18:18:48 -0700323 // Show the compilation config.
324 LOG(DEBUG) << "Try to compiled package_id: " << package_id
325 << " package_name: " << package_name
326 << " activity_name: " << activity_name
Yan Wang16b8fce2020-02-20 18:08:33 +0000327 << " version: " << version
Yan Wangcdb97fa2019-10-18 18:18:48 -0700328 << " file_path: " << file_path
Yan Wang23d4cc32019-11-13 18:16:59 -0800329 << " verbose: " << params.verbose
Yan Wangcdb97fa2019-10-18 18:18:48 -0700330 << " perfetto_traces: "
331 << VectorPrinter<compiler::CompilationInput>{perfetto_traces};
Yan Wang23d4cc32019-11-13 18:16:59 -0800332 if (params.inode_textcache) {
333 LOG(DEBUG) << "inode_textcache: " << *params.inode_textcache;
334 }
Yan Wangcdb97fa2019-10-18 18:18:48 -0700335
Yan Wang23d4cc32019-11-13 18:16:59 -0800336 CompilerForkParameters compiler_params{perfetto_traces, file_path, params};
337
Yan Wang65e905d2019-11-16 14:49:56 -0800338 if (!output_file.MkdirWithParents()) {
339 LOG(ERROR) << "Compile activity failed. Failed to mkdirs " << file_path;
340 return false;
341 }
342
Igor Murashkin70401f42020-03-04 13:57:12 -0800343 ScopedFormatTrace atrace_compile_fork(ATRACE_TAG_PACKAGE_MANAGER,
344 "Fork+exec iorap.cmd.compiler",
345 activity_name.c_str());
Yan Wang23d4cc32019-11-13 18:16:59 -0800346 if (!StartViaFork(compiler_params)) {
Yan Wangcdb97fa2019-10-18 18:18:48 -0700347 LOG(ERROR) << "Compilation failed for package_id:" << package_id
Yan Wang39247542020-05-21 18:23:46 +0000348 << " activity_name: " << activity_name;
Yan Wangcdb97fa2019-10-18 18:18:48 -0700349 return false;
350 }
351 }
352
353 std::optional<db::PrefetchFileModel> compiled_trace =
354 db::PrefetchFileModel::Insert(db, activity_id, file_path);
355 if (!compiled_trace) {
356 LOG(ERROR) << "Cannot insert compiled trace activity_id: " << activity_id
357 << " file_path: " << file_path;
358 return false;
359 }
360 return true;
361}
362
363// Compiled the perfetto traces for activities in an package.
364bool CompilePackage(const db::DbHandle& db,
365 const std::string& package_name,
Yan Wang16b8fce2020-02-20 18:08:33 +0000366 int version,
Yan Wang23d4cc32019-11-13 18:16:59 -0800367 const ControllerParameters& params) {
Igor Murashkin70401f42020-03-04 13:57:12 -0800368 ScopedFormatTrace atrace_compile_package(ATRACE_TAG_PACKAGE_MANAGER,
369 "Compile package %s",
370 package_name.c_str());
371
Yan Wangcdb97fa2019-10-18 18:18:48 -0700372 std::optional<db::PackageModel> package =
Yan Wang16b8fce2020-02-20 18:08:33 +0000373 db::PackageModel::SelectByNameAndVersion(db, package_name.c_str(), version);
Yan Wangcdb97fa2019-10-18 18:18:48 -0700374
375 if (!package) {
Yan Wang16b8fce2020-02-20 18:08:33 +0000376 LOG(ERROR) << "Cannot find package for package_name: "
377 << package_name
378 << " and version "
379 << version;
Yan Wangcdb97fa2019-10-18 18:18:48 -0700380 return false;
381 }
382
383 std::vector<db::ActivityModel> activities =
384 db::ActivityModel::SelectByPackageId(db, package->id);
385
386 bool ret = true;
387 for (db::ActivityModel activity : activities) {
Yan Wang16b8fce2020-02-20 18:08:33 +0000388 if (!CompileActivity(db, package->id, package->name, activity.name, version, params)) {
Yan Wangcdb97fa2019-10-18 18:18:48 -0700389 ret = false;
390 }
391 }
392 return ret;
393}
394
395// Compiled the perfetto traces for packages in a device.
Yan Wang23d4cc32019-11-13 18:16:59 -0800396bool CompileAppsOnDevice(const db::DbHandle& db, const ControllerParameters& params) {
Igor Murashkin0a7cb8c2020-03-03 15:57:05 -0800397 {
398 std::lock_guard<std::mutex> last_job_info_guard{last_job_info_mutex_};
399 last_job_info_.activities_last_compiled_ = 0;
400 }
401
Yan Wangcdb97fa2019-10-18 18:18:48 -0700402 std::vector<db::PackageModel> packages = db::PackageModel::SelectAll(db);
403 bool ret = true;
404 for (db::PackageModel package : packages) {
Yan Wang16b8fce2020-02-20 18:08:33 +0000405 if (!CompilePackage(db, package.name, package.version, params)) {
Yan Wangcdb97fa2019-10-18 18:18:48 -0700406 ret = false;
407 }
408 }
409
Igor Murashkin0a7cb8c2020-03-03 15:57:05 -0800410 {
411 std::lock_guard<std::mutex> last_job_info_guard{last_job_info_mutex_};
412 last_job_info_.last_run_ns_ = time(nullptr);
413 }
414
Yan Wangcdb97fa2019-10-18 18:18:48 -0700415 return ret;
416}
417
Igor Murashkin98858642020-04-07 15:21:48 -0700418// Compiled the perfetto traces for a single package in a device.
419bool CompileSingleAppOnDevice(const db::DbHandle& db,
420 const ControllerParameters& params,
421 const std::string& package_name) {
422 std::vector<db::PackageModel> packages = db::PackageModel::SelectByName(db, package_name.c_str());
423 bool ret = true;
424 for (db::PackageModel package : packages) {
425 if (!CompilePackage(db, package.name, package.version, params)) {
426 ret = false;
427 }
428 }
429
430 return ret;
431}
432
Yan Wang23d4cc32019-11-13 18:16:59 -0800433bool Compile(const std::string& db_path, const ControllerParameters& params) {
Yan Wangcdb97fa2019-10-18 18:18:48 -0700434 iorap::db::SchemaModel db_schema = db::SchemaModel::GetOrCreate(db_path);
435 db::DbHandle db{db_schema.db()};
Yan Wang23d4cc32019-11-13 18:16:59 -0800436 return CompileAppsOnDevice(db, params);
Yan Wangcdb97fa2019-10-18 18:18:48 -0700437}
438
439bool Compile(const std::string& db_path,
440 const std::string& package_name,
Yan Wang16b8fce2020-02-20 18:08:33 +0000441 int version,
Yan Wang23d4cc32019-11-13 18:16:59 -0800442 const ControllerParameters& params) {
Yan Wangcdb97fa2019-10-18 18:18:48 -0700443 iorap::db::SchemaModel db_schema = db::SchemaModel::GetOrCreate(db_path);
444 db::DbHandle db{db_schema.db()};
Yan Wang16b8fce2020-02-20 18:08:33 +0000445 return CompilePackage(db, package_name, version, params);
Yan Wangcdb97fa2019-10-18 18:18:48 -0700446}
447
448bool Compile(const std::string& db_path,
449 const std::string& package_name,
450 const std::string& activity_name,
Yan Wang16b8fce2020-02-20 18:08:33 +0000451 int version,
Yan Wang23d4cc32019-11-13 18:16:59 -0800452 const ControllerParameters& params) {
Yan Wangcdb97fa2019-10-18 18:18:48 -0700453 iorap::db::SchemaModel db_schema = db::SchemaModel::GetOrCreate(db_path);
454 db::DbHandle db{db_schema.db()};
455
456 std::optional<db::PackageModel> package =
Yan Wang16b8fce2020-02-20 18:08:33 +0000457 db::PackageModel::SelectByNameAndVersion(db, package_name.c_str(), version);
458
Yan Wangcdb97fa2019-10-18 18:18:48 -0700459 if (!package) {
Yan Wang16b8fce2020-02-20 18:08:33 +0000460 LOG(ERROR) << "Cannot find package with name "
461 << package_name
462 << " and version "
463 << version;
Yan Wangcdb97fa2019-10-18 18:18:48 -0700464 return false;
465 }
Yan Wang16b8fce2020-02-20 18:08:33 +0000466 return CompileActivity(db, package->id, package_name, activity_name, version, params);
Yan Wangcdb97fa2019-10-18 18:18:48 -0700467}
468
Igor Murashkin0a7cb8c2020-03-03 15:57:05 -0800469static std::string TimeToString(time_t the_time) {
470 tm tm_buf{};
471 tm* tm_ptr = localtime_r(&the_time, &tm_buf);
472
473 if (tm_ptr != nullptr) {
474 char time_buffer[256];
475 strftime(time_buffer, sizeof(time_buffer), "%a %b %d %H:%M:%S %Y", tm_ptr);
476 return std::string{time_buffer};
477 } else {
478 return std::string{"(nullptr)"};
479 }
480}
481
482static std::string GetTimestampForPrefetchFile(const db::PrefetchFileModel& prefetch_file) {
483 std::filesystem::path path{prefetch_file.file_path};
484
485 std::error_code ec{};
486 auto last_write_time = std::filesystem::last_write_time(path, /*out*/ec);
487 if (ec) {
488 return std::string("Failed to get last write time: ") + ec.message();
489 }
490
491 time_t time = decltype(last_write_time)::clock::to_time_t(last_write_time);
492
493 std::string time_str = TimeToString(time);
494 return time_str;
495}
496
497void DumpPackageActivity(const db::DbHandle& db,
498 ::android::Printer& printer,
499 const db::PackageModel& package,
500 const db::ActivityModel& activity) {
501 int package_id = package.id;
502 const std::string& package_name = package.name;
503 int package_version = package.version;
504 const std::string& activity_name = activity.name;
505 db::VersionedComponentName vcn{package_name, activity_name, package_version};
506
507 // com.google.Settings/com.google.Settings.ActivityMain@1234567890
508 printer.printFormatLine(" %s/%s@%d",
509 package_name.c_str(),
510 activity_name.c_str(),
511 package_version);
512
513 std::optional<db::PrefetchFileModel> prefetch_file =
514 db::PrefetchFileModel::SelectByVersionedComponentName(db, vcn);
515
516 std::vector<db::AppLaunchHistoryModel> histories =
517 db::AppLaunchHistoryModel::SelectActivityHistoryForCompile(db, activity.id);
518 std::vector<compiler::CompilationInput> perfetto_traces =
519 GetPerfettoTraceInfo(db, histories);
520
521 if (prefetch_file) {
522 bool exists_on_disk = std::filesystem::exists(prefetch_file->file_path);
523
524 std::optional<size_t> prefetch_byte_sum =
525 prefetcher::ReadAhead::PrefetchSizeInBytes(prefetch_file->file_path);
526
527 if (exists_on_disk) {
528 printer.printFormatLine(" Compiled Status: Usable compiled trace");
529 } else {
530 printer.printFormatLine(" Compiled Status: Prefetch file deleted from disk.");
531 }
532
533 if (prefetch_byte_sum) {
534 printer.printFormatLine(" Bytes to be prefetched: %zu", *prefetch_byte_sum);
535 } else {
536 printer.printFormatLine(" Bytes to be prefetched: (bad file path)" );
537 }
538
539 printer.printFormatLine(" Time compiled: %s",
540 GetTimestampForPrefetchFile(*prefetch_file).c_str());
541 printer.printFormatLine(" %s", prefetch_file->file_path.c_str());
542 } else {
543 size_t size = perfetto_traces.size();
544
545 if (size >= kMinTracesForCompilation) {
546 printer.printFormatLine(" Compiled Status: Raw traces pending compilation (%zu)",
547 perfetto_traces.size());
548 } else {
549 size_t remaining = kMinTracesForCompilation - size;
550 printer.printFormatLine(" Compiled Status: Need %zu more traces for compilation",
551 remaining);
552 }
553 }
554
555 printer.printFormatLine(" Raw traces:");
556 printer.printFormatLine(" Trace count: %zu", perfetto_traces.size());
557
558 for (compiler::CompilationInput& compilation_input : perfetto_traces) {
559 std::string& raw_trace_file_name = compilation_input.filename;
560
561 printer.printFormatLine(" %s", raw_trace_file_name.c_str());
562 }
563}
564
565void DumpPackage(const db::DbHandle& db,
566 ::android::Printer& printer,
567 db::PackageModel package) {
568 std::vector<db::ActivityModel> activities =
569 db::ActivityModel::SelectByPackageId(db, package.id);
570
571 for (db::ActivityModel& activity : activities) {
572 DumpPackageActivity(db, printer, package, activity);
573 }
574}
575
576void DumpAllPackages(const db::DbHandle& db, ::android::Printer& printer) {
577 printer.printLine("Package history in database:");
578
579 std::vector<db::PackageModel> packages = db::PackageModel::SelectAll(db);
580 for (db::PackageModel package : packages) {
581 DumpPackage(db, printer, package);
582 }
583
584 printer.printLine("");
585}
586
587void Dump(const db::DbHandle& db, ::android::Printer& printer) {
588 bool locked = last_job_info_mutex_.try_lock();
589
590 LastJobInfo info = last_job_info_;
591
592 printer.printFormatLine("Background job:");
593 if (!locked) {
594 printer.printLine(""""" (possible deadlock)");
595 }
596 if (info.last_run_ns_ != time_t{0}) {
597 std::string time_str = TimeToString(info.last_run_ns_);
598
599 printer.printFormatLine(" Last run at: %s", time_str.c_str());
600 } else {
601 printer.printFormatLine(" Last run at: (None)");
602 }
603 printer.printFormatLine(" Activities last compiled: %zu", info.activities_last_compiled_);
604
605 printer.printLine("");
606
607 if (locked) {
608 last_job_info_mutex_.unlock();
609 }
610
611 DumpAllPackages(db, printer);
612}
613
Yan Wangcdb97fa2019-10-18 18:18:48 -0700614} // namespace iorap::maintenance