• 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 "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