• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2024 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 use std::{option::Option, path::PathBuf, result::Result::Ok, str::FromStr};
16 
17 use argh::FromArgs;
18 use serde::Deserialize;
19 
20 use crate::args::DEFAULT_EXIT_ON_ERROR;
21 use crate::args::DEFAULT_IO_DEPTH;
22 use crate::args::DEFAULT_MAX_FDS;
23 use crate::Error;
24 
25 /// prefetch-rs
26 #[derive(Eq, PartialEq, Debug, Default, FromArgs)]
27 pub struct MainArgs {
28     /// subcommands
29     #[argh(subcommand)]
30     pub nested: SubCommands,
31 }
32 
33 /// Sub commands for prefetch functions
34 #[derive(Eq, PartialEq, Debug, FromArgs)]
35 #[argh(subcommand)]
36 pub enum SubCommands {
37     /// Records prefetch data.
38     Record(RecordArgs),
39     /// Replays from prefetch data
40     Replay(ReplayArgs),
41     /// Dump prefetch data in human readable format
42     Dump(DumpArgs),
43 }
44 
45 #[cfg(target_os = "android")]
default_ready_path() -> PathBuf46 fn default_ready_path() -> PathBuf {
47     PathBuf::from("/metadata/prefetch/prefetch_ready")
48 }
49 
50 #[cfg(target_os = "android")]
default_build_finger_print_path() -> PathBuf51 fn default_build_finger_print_path() -> PathBuf {
52     PathBuf::from("/metadata/prefetch/build_finger_print")
53 }
54 
55 impl Default for SubCommands {
default() -> Self56     fn default() -> Self {
57         Self::Dump(DumpArgs::default())
58     }
59 }
60 
default_path() -> PathBuf61 fn default_path() -> PathBuf {
62     PathBuf::from("/metadata/prefetch/prefetch.pack")
63 }
64 
parse_tracing_instance(value: &str) -> Result<Option<String>, String>65 fn parse_tracing_instance(value: &str) -> Result<Option<String>, String> {
66     Ok(Some(value.to_string()))
67 }
68 
69 #[derive(Eq, PartialEq, Debug, Default, FromArgs)]
70 /// Records prefect data.
71 #[argh(subcommand, name = "record")]
72 pub struct RecordArgs {
73     /// duration in seconds to record the data
74     ///
75     /// On Android, if duration count is set to zero, recording
76     /// will continue until the property sys.boot_completed = 1.
77     #[argh(option)]
78     pub duration: u16,
79 
80     /// file path where the records will be written to
81     ///
82     /// A new file is created at the given path. If the path exists, it
83     /// will be overwritten
84     #[argh(option, default = "default_path()")]
85     pub path: PathBuf,
86 
87     /// when set an intermediate file will be created that provides more information
88     /// about collected data.
89     #[argh(option, default = "false")]
90     pub debug: bool,
91 
92     /// file path where the intermediate file will be written to
93     ///
94     /// A new file is created at the given path. Errors out if the file
95     /// already exists.
96     #[argh(option)]
97     pub int_path: Option<PathBuf>,
98 
99     /// size of the trace buffer which holds trace events. We need larger
100     /// buffer on a system that has faster disks or has large number of events
101     /// enabled. Defaults to TRACE_BUFFER_SIZE_KIB KiB.
102     #[argh(option, long = "trace-buffer-size")]
103     pub trace_buffer_size_kib: Option<u64>,
104 
105     /// trace subsystem to use. "mem" subsystem is set by default.
106     #[argh(option, default = "Default::default()")]
107     pub tracing_subsystem: TracerType,
108 
109     /// if true enables all the needed trace events. And at the end it restores
110     /// the values of those events.
111     /// If false, assumes that user has setup the needed trace events.
112     #[argh(option, default = "true")]
113     pub setup_tracing: bool,
114 
115     /// if specified, works on a tracing instance (like /sys/kernel/tracing/instance/my_instance)
116     /// rather than using on shared global instance (i.e. /sys/kernel/tracing)."
117     #[argh(
118         option,
119         default = "Some(\"prefetch\".to_string())",
120         from_str_fn(parse_tracing_instance)
121     )]
122     pub tracing_instance: Option<String>,
123 
124     #[cfg(target_os = "android")]
125     /// store build_finger_print to tie the pack format
126     #[argh(option, default = "default_build_finger_print_path()")]
127     pub build_fingerprint_path: PathBuf,
128 
129     #[cfg(target_os = "android")]
130     /// file path to check if prefetch_ready is present.
131     ///
132     /// A new file is created at the given path if it's not present.
133     #[argh(option, default = "default_ready_path()")]
134     pub ready_path: PathBuf,
135 }
136 
137 /// Type of tracing subsystem to use.
138 #[derive(Deserialize, Clone, Eq, PartialEq, Debug)]
139 pub enum TracerType {
140     /// mem tracing subsystem relies on when a file's in-memory page gets added to the fs cache.
141     Mem,
142 }
143 
144 impl FromStr for TracerType {
145     type Err = Error;
from_str(s: &str) -> std::result::Result<Self, Self::Err>146     fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
147         Ok(match s.to_lowercase().as_str() {
148             "mem" => Self::Mem,
149             _ => {
150                 return Err(Error::InvalidArgs {
151                     arg_name: "tracing_subsystem".to_owned(),
152                     arg_value: s.to_owned(),
153                     error: "unknown value".to_owned(),
154                 })
155             }
156         })
157     }
158 }
159 
160 impl Default for TracerType {
default() -> Self161     fn default() -> Self {
162         Self::Mem
163     }
164 }
165 
166 #[derive(Eq, PartialEq, Debug, Default, FromArgs)]
167 /// Prefetch data from the recorded file.
168 #[argh(subcommand, name = "replay")]
169 pub struct ReplayArgs {
170     /// file path from where the records will be read
171     #[argh(option, default = "default_path()")]
172     pub path: PathBuf,
173 
174     /// IO depth. Number of IO that can go in parallel.
175     #[argh(option, long = "io-depth", default = "DEFAULT_IO_DEPTH")]
176     pub io_depth: u16,
177 
178     /// max number of open fds to cache
179     #[argh(option, arg_name = "max-fds", default = "DEFAULT_MAX_FDS")]
180     pub max_fds: u16,
181 
182     /// if true, command exits on encountering any error.
183     ///
184     /// This defaults to false as there is not harm prefetching if we encounter
185     /// non-fatal errors.
186     #[argh(option, default = "DEFAULT_EXIT_ON_ERROR")]
187     pub exit_on_error: bool,
188 
189     /// file path from where the prefetch config file will be read
190     #[argh(option, default = "PathBuf::new()")]
191     pub config_path: PathBuf,
192 
193     #[cfg(target_os = "android")]
194     /// store build_finger_print to tie the pack format
195     #[argh(option, default = "default_build_finger_print_path()")]
196     pub build_fingerprint_path: PathBuf,
197 }
198 
199 /// dump records file in given format
200 #[derive(Eq, PartialEq, Debug, Default, FromArgs)]
201 #[argh(subcommand, name = "dump")]
202 pub struct DumpArgs {
203     /// file path from where the records will be read
204     #[argh(option)]
205     pub path: PathBuf,
206     /// output format. One of json or csv.
207     /// Note: In csv format, few fields are excluded from the output.
208     #[argh(option)]
209     pub format: OutputFormat,
210 }
211 
212 #[derive(Deserialize, Eq, PartialEq, Debug)]
213 pub enum OutputFormat {
214     Json,
215     Csv,
216 }
217 
218 impl FromStr for OutputFormat {
219     type Err = Error;
from_str(s: &str) -> std::result::Result<Self, Self::Err>220     fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
221         Ok(match s.to_lowercase().as_str() {
222             "csv" => Self::Csv,
223             "json" => Self::Json,
224             _ => {
225                 return Err(Error::InvalidArgs {
226                     arg_name: "format".to_owned(),
227                     arg_value: s.to_owned(),
228                     error: "unknown value".to_owned(),
229                 })
230             }
231         })
232     }
233 }
234 
235 impl Default for OutputFormat {
default() -> Self236     fn default() -> Self {
237         Self::Json
238     }
239 }
240 
241 /// Build args struct from command line arguments
args_from_env() -> MainArgs242 pub fn args_from_env() -> MainArgs {
243     argh::from_env()
244 }
245