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 "prefetcher/prefetcher_daemon.h" 18 19 #include <android-base/parseint.h> 20 #include <android-base/logging.h> 21 22 #include <iostream> 23 #include <optional> 24 #include <string_view> 25 #include <string> 26 #include <vector> 27 28 #include <signal.h> 29 30 #if defined(IORAP_PREFETCHER_MAIN) 31 32 namespace iorap::prefetcher { 33 34 void Usage(char** argv) { 35 std::cerr << "Usage: " << argv[0] << " [--input-fd=#] [--output-fd=#]" << std::endl; 36 std::cerr << "" << std::endl; 37 std::cerr << " Run the readahead daemon which can prefetch files given a command." << std::endl; 38 std::cerr << "" << std::endl; 39 std::cerr << " Optional flags:" << std::endl; 40 std::cerr << " --help,-h Print this Usage." << std::endl; 41 std::cerr << " --input-fd,-if Input FD (default stdin)." << std::endl; 42 std::cerr << " --output-fd,-of Output FD (default stdout)." << std::endl; 43 std::cerr << " --use-sockets,-us Use AF_UNIX sockets (default off)." << std::endl; 44 std::cerr << " --command-format=[text|binary],-cf (default text)." << std::endl; 45 std::cerr << " --verbose,-v Set verbosity (default off)." << std::endl; 46 std::cerr << " --wait,-w Wait for key stroke before continuing (default off)." << std::endl; 47 exit(1); 48 } 49 50 int Main(int argc, char** argv) { 51 // Go to system logcat + stderr when running from command line. 52 android::base::InitLogging(argv, iorap::common::StderrAndLogdLogger{android::base::SYSTEM}); 53 54 bool wait_for_keystroke = false; 55 bool enable_verbose = false; 56 57 bool command_format_text = false; // false = binary. 58 59 int arg_input_fd = -1; 60 int arg_output_fd = -1; 61 62 std::vector<std::string> arg_input_filenames; 63 bool arg_use_sockets = false; 64 65 LOG(VERBOSE) << "argparse: argc=" << argc; 66 67 for (int arg = 1; arg < argc; ++arg) { 68 std::string argstr = argv[arg]; 69 bool has_arg_next = (arg+1)<argc; 70 std::string arg_next = has_arg_next ? argv[arg+1] : ""; 71 72 LOG(VERBOSE) << "argparse: argv[" << arg << "]=" << argstr; 73 74 if (argstr == "--help" || argstr == "-h") { 75 Usage(argv); 76 } else if (argstr == "--input-fd" || argstr == "-if") { 77 if (!has_arg_next) { 78 LOG(ERROR) << "--input-fd=<numeric-value>"; 79 Usage(argv); 80 } 81 if (!::android::base::ParseInt(arg_next, /*out*/&arg_input_fd)) { 82 LOG(ERROR) << "--input-fd value must be numeric"; 83 Usage(argv); 84 } 85 } else if (argstr == "--output-fd" || argstr == "-of") { 86 if (!has_arg_next) { 87 LOG(ERROR) << "--output-fd=<numeric-value>"; 88 Usage(argv); 89 } 90 if (!::android::base::ParseInt(arg_next, /*out*/&arg_output_fd)) { 91 LOG(ERROR) << "--output-fd value must be numeric"; 92 Usage(argv); 93 } 94 } else if (argstr == "--command-format=" || argstr == "-cf") { 95 if (!has_arg_next) { 96 LOG(ERROR) << "--command-format=text|binary"; 97 Usage(argv); 98 } 99 if (arg_next == "text") { 100 command_format_text = true; 101 } else if (arg_next == "binary") { 102 command_format_text = false; 103 } else { 104 LOG(ERROR) << "--command-format must be one of {text,binary}"; 105 Usage(argv); 106 } 107 } else if (argstr == "--use-sockets" || argstr == "-us") { 108 arg_use_sockets = true; 109 } else if (argstr == "--verbose" || argstr == "-v") { 110 enable_verbose = true; 111 } else if (argstr == "--wait" || argstr == "-w") { 112 wait_for_keystroke = true; 113 } else { 114 arg_input_filenames.push_back(argstr); 115 } 116 } 117 118 if (enable_verbose) { 119 android::base::SetMinimumLogSeverity(android::base::VERBOSE); 120 121 LOG(VERBOSE) << "Verbose check"; 122 LOG(VERBOSE) << "Debug check: " << ::iorap::kIsDebugBuild; 123 } else { 124 android::base::SetMinimumLogSeverity(android::base::DEBUG); 125 } 126 127 LOG(VERBOSE) << "argparse: argc=" << argc; 128 129 for (int arg = 1; arg < argc; ++arg) { 130 std::string argstr = argv[arg]; 131 132 LOG(VERBOSE) << "argparse: argv[" << arg << "]=" << argstr; 133 } 134 135 // Useful to attach a debugger... 136 // 1) $> iorap.cmd.readahead -w <args> 137 // 2) $> gdbclient <pid> 138 if (wait_for_keystroke) { 139 LOG(INFO) << "Self pid: " << getpid(); 140 141 raise(SIGSTOP); 142 // LOG(INFO) << "Press any key to continue..."; 143 // std::cin >> wait_for_keystroke; 144 } 145 146 // auto system_call = std::make_unique<SystemCallImpl>(); 147 // TODO: mock readahead calls? 148 // 149 // Uncomment this if we want to leave the process around to inspect it from adb shell. 150 // sleep(100000); 151 152 int return_code = 0; 153 154 LOG(VERBOSE) << "Hello world"; 155 156 if (arg_input_fd == -1) { 157 arg_input_fd = STDIN_FILENO; 158 } 159 if (arg_output_fd == -1) { 160 arg_output_fd = STDOUT_FILENO; 161 } 162 163 PrefetcherForkParameters params{}; 164 params.input_fd = arg_input_fd; 165 params.output_fd = arg_output_fd; 166 params.format_text = command_format_text; 167 params.use_sockets = arg_use_sockets; 168 169 LOG(VERBOSE) << "main: Starting PrefetcherDaemon: " 170 << "input_fd=" << params.input_fd 171 << ",output_fd=" << params.output_fd; 172 { 173 PrefetcherDaemon daemon; 174 // Blocks until receiving an exit command. 175 daemon.Main(std::move(params)); 176 } 177 LOG(VERBOSE) << "main: Terminating"; 178 179 // 0 -> successfully executed all commands. 180 // 1 -> failed along the way (#on_error and also see the error logs). 181 return return_code; 182 } 183 184 } // namespace iorap::prefetcher 185 186 int main(int argc, char** argv) { 187 return ::iorap::prefetcher::Main(argc, argv); 188 } 189 190 #endif // IORAP_PREFETCHER_MAIN 191