• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 "common/debug.h"
16 #include "common/loggers.h"
17 #include "db/app_component_name.h"
18 #include "db/models.h"
19 
20 #include <android-base/parseint.h>
21 #include <android-base/logging.h>
22 
23 #include <iostream>
24 #include <optional>
25 #include <string_view>
26 #include <string>
27 #include <vector>
28 
29 #include <sqlite3.h>
30 
31 #include <signal.h>
32 
33 namespace iorap::db {
34 
35 void Usage(char** argv) {
36   std::cerr << "Usage: " << argv[0] << " <path-to-sqlite.db>" << std::endl;
37   std::cerr << "" << std::endl;
38   std::cerr << "  Interface with the iorap sqlite database and issue commands." << std::endl;
39   std::cerr << "" << std::endl;
40   std::cerr << "  Optional flags:" << std::endl;
41   std::cerr << "    --help,-h                  Print this Usage." << std::endl;
42   std::cerr << "    --register-raw-trace,-rrt  Register raw trace file path." << std::endl;
43   std::cerr << "    --register-compiled-trace,-rct  Register compiled trace file path." << std::endl;
44   std::cerr << "    --insert-component,-ic     Add component if it doesn't exist." << std::endl;
45   std::cerr << "    --initialize,-i            Initialize new database." << std::endl;
46   std::cerr << "    --rescan,-rs               Update all from canonical directories." << std::endl;
47   std::cerr << "    --prune,-pr                Remove any stale file paths." << std::endl;
48   std::cerr << "    --verbose,-v               Set verbosity (default off)." << std::endl;
49   std::cerr << "    --wait,-w                  Wait for key stroke before continuing (default off)." << std::endl;
50   exit(1);
51 }
52 
53 void error_log_sqlite_callback(void *pArg, int iErrCode, const char *zMsg) {
54   LOG(ERROR) << "SQLite error (" << iErrCode << "): " << zMsg;
55 }
56 
57 const constexpr int64_t kNoVersion = -1;
58 
59 int Main(int argc, char** argv) {
60   // Go to system logcat + stderr when running from command line.
61   android::base::InitLogging(argv, iorap::common::StderrAndLogdLogger{android::base::SYSTEM});
62 
63   bool wait_for_keystroke = false;
64   bool enable_verbose = false;
65 
66   bool command_format_text = false; // false = binary.
67 
68   int arg_input_fd = -1;
69   int arg_output_fd = -1;
70 
71   std::vector<std::string> arg_input_filenames;
72   bool arg_use_sockets = false;
73 
74   std::vector<std::pair<std::string,std::string>> arg_register_raw_trace;
75   std::vector<std::pair<std::string,std::string>> arg_register_compiled_trace;
76 
77   std::vector<std::string> arg_insert_component;
78 
79   bool arg_initialize = false;
80   bool arg_rescan = false;
81   bool arg_prune = false;
82 
83   LOG(VERBOSE) << "argparse: argc=" << argc;
84 
85   for (int arg = 1; arg < argc; ++arg) {
86     std::string argstr = argv[arg];
87     bool has_arg_next = (arg+1)<argc;
88     std::string arg_next = has_arg_next ? argv[arg+1] : "";
89 
90     bool has_arg_next_next = (arg+2)<argc;
91     std::string arg_next_next = has_arg_next_next ? argv[arg+2] : "";
92 
93     LOG(VERBOSE) << "argparse: argv[" << arg << "]=" << argstr;
94 
95     if (argstr == "--help" || argstr == "-h") {
96       Usage(argv);
97     } else if (argstr == "--register-raw-trace" || argstr == "-rrt") {
98       if (!has_arg_next_next) {
99         LOG(ERROR) << "--register-raw-trace <component/name> <filepath>";
100         Usage(argv);
101       }
102       arg_register_raw_trace.push_back({arg_next, arg_next_next});
103     } else if (argstr == "--register-compiled-trace" || argstr == "-rct") {
104       if (!has_arg_next_next) {
105         LOG(ERROR) << "--register-compiled-trace <component/name> <filepath>";
106         Usage(argv);
107       }
108       arg_register_compiled_trace.push_back({arg_next, arg_next_next});
109     } else if (argstr == "--insert-component" || argstr == "-ic") {
110       if (!has_arg_next) {
111         LOG(ERROR) << "--insert-component <component/name>";
112         Usage(argv);
113       }
114       arg_insert_component.push_back(arg_next);
115     } else if (argstr == "--initialize" || argstr == "-i") {
116       arg_initialize = true;
117     } else if (argstr == "--rescan" || argstr == "-rs") {
118       arg_rescan = true;
119     } else if (argstr == "--prune" || argstr == "-pr") {
120       arg_prune = true;
121     } else if (argstr == "--verbose" || argstr == "-v") {
122       enable_verbose = true;
123     } else if (argstr == "--wait" || argstr == "-w") {
124       wait_for_keystroke = true;
125     } else {
126       arg_input_filenames.push_back(argstr);
127     }
128   }
129 
130   if (arg_input_filenames.empty()) {
131     LOG(ERROR) << "Missing positional filename to a sqlite database.";
132     Usage(argv);
133   }
134 
135   if (enable_verbose) {
136     android::base::SetMinimumLogSeverity(android::base::VERBOSE);
137 
138     LOG(VERBOSE) << "Verbose check";
139     LOG(VERBOSE) << "Debug check: " << ::iorap::kIsDebugBuild;
140   } else {
141     android::base::SetMinimumLogSeverity(android::base::DEBUG);
142   }
143 
144   LOG(VERBOSE) << "argparse: argc=" << argc;
145 
146   for (int arg = 1; arg < argc; ++arg) {
147     std::string argstr = argv[arg];
148 
149     LOG(VERBOSE) << "argparse: argv[" << arg << "]=" << argstr;
150   }
151 
152   // Useful to attach a debugger...
153   // 1) $> iorap.cmd.readahead -w <args>
154   // 2) $> gdbclient <pid>
155   if (wait_for_keystroke) {
156     LOG(INFO) << "Self pid: " << getpid();
157 
158     raise(SIGSTOP);
159     // LOG(INFO) << "Press any key to continue...";
160     // std::cin >> wait_for_keystroke;
161   }
162 
163   // auto system_call = std::make_unique<SystemCallImpl>();
164   // TODO: mock readahead calls?
165   //
166   // Uncomment this if we want to leave the process around to inspect it from adb shell.
167   // sleep(100000);
168 
169   int return_code = 0;
170 
171   LOG(VERBOSE) << "Hello world";
172 
173 
174   do {
175     SchemaModel schema_model = SchemaModel::GetOrCreate(arg_input_filenames[0]);
176     DbHandle db = schema_model.db();
177     if (arg_initialize) {
178       // Drop tables and restart from scratch. All rows are effectively dropped.
179       schema_model.Reinitialize();
180     }
181 
182     for (const auto& component_and_file_name : arg_register_raw_trace) {
183       AppComponentName component_name = AppComponentName::FromString(component_and_file_name.first);
184       const std::string& file_path = component_and_file_name.second;
185 
186       LOG(VERBOSE) << "--register-raw-trace " << component_name << ", file_path: " << file_path;
187 
188       std::optional<ActivityModel> activity =
189           ActivityModel::SelectOrInsert(db,
190                                         component_name.package,
191                                         kNoVersion,
192                                         component_name.activity_name);
193       DCHECK(activity.has_value());
194       LOG(DEBUG) << "Component selected/inserted: " << *activity;
195     }
196 
197     for (const std::string& component : arg_insert_component) {
198       AppComponentName component_name = AppComponentName::FromString(component);
199 
200       LOG(VERBOSE) << "raw component: " << component;
201       LOG(VERBOSE) << "package: " << component_name.package;
202       LOG(VERBOSE) << "activity name: " << component_name.activity_name;
203 
204       LOG(VERBOSE) << "--insert-component " << component_name;
205 
206       std::optional<ActivityModel> activity =
207           ActivityModel::SelectOrInsert(db,
208                                         component_name.package,
209                                         kNoVersion,
210                                         component_name.activity_name);
211 
212       DCHECK(activity.has_value());
213       LOG(DEBUG) << "Component selected/inserted: " << *activity;
214     }
215   } while (false);
216 
217   LOG(VERBOSE) << "main: Terminating";
218 
219   // 0 -> successfully executed all commands.
220   // 1 -> failed along the way (#on_error and also see the error logs).
221   return return_code;
222 }
223 
224 }  // namespace iorap::db
225 
226 #if defined(IORAP_DB_MAIN)
227 int main(int argc, char** argv) {
228   return ::iorap::db::Main(argc, argv);
229 }
230 #endif  // IORAP_DB_MAIN
231