xref: /DADK/dadk-user/src/context.rs (revision eaa67f3cf8881c221a744937c6318444b068a801)
1 use std::{
2     path::PathBuf,
3     process::exit,
4     sync::{Arc, Mutex, Weak},
5 };
6 
7 use dadk_config::{common::target_arch::TargetArch, user::UserCleanLevel};
8 use derive_builder::Builder;
9 use log::error;
10 #[cfg(test)]
11 use test_base::{global::BaseGlobalTestContext, test_context::TestContext};
12 
13 use crate::{executor::cache::cache_root_init, scheduler::task_deque::TASK_DEQUE};
14 
15 #[derive(Debug, Builder)]
16 #[builder(setter(into))]
17 pub struct DadkUserExecuteContext {
18     /// DragonOS sysroot在主机上的路径
19     sysroot_dir: Option<PathBuf>,
20     /// DADK任务配置文件所在目录
21     config_dir: Option<PathBuf>,
22     /// 要执行的操作
23     action: Action,
24     /// 并行线程数量
25     thread_num: Option<usize>,
26     /// dadk缓存根目录
27     cache_dir: Option<PathBuf>,
28 
29     /// 目标架构
30     #[builder(default = "crate::DADKTask::default_target_arch()")]
31     target_arch: TargetArch,
32 
33     #[cfg(test)]
34     base_test_context: Option<BaseGlobalTestContext>,
35 
36     #[builder(setter(skip), default = "Mutex::new(Weak::new())")]
37     self_ref: Mutex<Weak<Self>>,
38 }
39 
40 impl DadkUserExecuteContext {
init(&self, self_arc: Arc<Self>)41     pub fn init(&self, self_arc: Arc<Self>) {
42         self.set_self_ref(Arc::downgrade(&self_arc));
43 
44         // 初始化缓存目录
45         let r: Result<(), crate::executor::ExecutorError> =
46             cache_root_init(self.cache_dir().cloned());
47         if r.is_err() {
48             error!("Failed to init cache root: {:?}", r.unwrap_err());
49             exit(1);
50         }
51 
52         if let Some(thread) = self.thread_num() {
53             TASK_DEQUE.lock().unwrap().set_thread(thread);
54         }
55 
56         if self.config_dir().is_none() {
57             error!("Config dir is required for action: {:?}", self.action());
58             exit(1);
59         }
60 
61         if self.sysroot_dir().is_none() {
62             error!(
63                 "dragonos sysroot dir is required for action: {:?}",
64                 self.action()
65             );
66             exit(1);
67         }
68     }
69 
70     #[allow(dead_code)]
self_ref(&self) -> Option<Arc<Self>>71     pub fn self_ref(&self) -> Option<Arc<Self>> {
72         self.self_ref.lock().unwrap().upgrade()
73     }
74 
set_self_ref(&self, self_ref: Weak<Self>)75     fn set_self_ref(&self, self_ref: Weak<Self>) {
76         *self.self_ref.lock().unwrap() = self_ref;
77     }
78 
target_arch(&self) -> &TargetArch79     pub fn target_arch(&self) -> &TargetArch {
80         &self.target_arch
81     }
82 
sysroot_dir(&self) -> Option<&PathBuf>83     pub fn sysroot_dir(&self) -> Option<&PathBuf> {
84         self.sysroot_dir.as_ref()
85     }
86 
config_dir(&self) -> Option<&PathBuf>87     pub fn config_dir(&self) -> Option<&PathBuf> {
88         self.config_dir.as_ref()
89     }
90 
action(&self) -> &Action91     pub fn action(&self) -> &Action {
92         &self.action
93     }
94 
thread_num(&self) -> Option<usize>95     pub fn thread_num(&self) -> Option<usize> {
96         self.thread_num
97     }
98 
cache_dir(&self) -> Option<&PathBuf>99     pub fn cache_dir(&self) -> Option<&PathBuf> {
100         self.cache_dir.as_ref()
101     }
102 }
103 
104 #[cfg(test)]
105 pub trait TestContextExt: TestContext {
base_context(&self) -> &BaseGlobalTestContext106     fn base_context(&self) -> &BaseGlobalTestContext;
107 
execute_context(&self) -> &DadkUserExecuteContext108     fn execute_context(&self) -> &DadkUserExecuteContext;
109 }
110 
111 impl DadkUserExecuteContextBuilder {
112     /// 用于测试的默认构建器
113     #[cfg(test)]
default_test_execute_context_builder(base_context: &BaseGlobalTestContext) -> Self114     fn default_test_execute_context_builder(base_context: &BaseGlobalTestContext) -> Self {
115         Self::default()
116             .sysroot_dir(Some(base_context.fake_dragonos_sysroot()))
117             .action(Action::Build)
118             .thread_num(None)
119             .cache_dir(Some(base_context.fake_dadk_cache_root()))
120             .base_test_context(Some(base_context.clone()))
121             .clone()
122     }
123 }
124 
125 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
126 pub enum Action {
127     /// 构建所有项目
128     Build,
129     /// 清理缓存
130     Clean(UserCleanLevel),
131     /// 安装到DragonOS sysroot
132     Install,
133 }
134 
135 #[cfg(test)]
136 pub struct DadkExecuteContextTestBuildX86_64V1 {
137     context: Arc<DadkUserExecuteContext>,
138 }
139 
140 #[cfg(test)]
141 impl TestContext for DadkExecuteContextTestBuildX86_64V1 {
setup() -> Self142     fn setup() -> Self {
143         let base_context = BaseGlobalTestContext::setup();
144         let context =
145             DadkUserExecuteContextBuilder::default_test_execute_context_builder(&base_context)
146                 .target_arch(TargetArch::X86_64)
147                 .config_dir(Some(base_context.config_v1_dir()))
148                 .build()
149                 .expect("Failed to build DadkExecuteContextTestBuildX86_64V1");
150         let context = Arc::new(context);
151         context.init(context.clone());
152         DadkExecuteContextTestBuildX86_64V1 { context }
153     }
154 }
155 
156 #[cfg(test)]
157 pub struct DadkExecuteContextTestBuildRiscV64V1 {
158     context: Arc<DadkUserExecuteContext>,
159 }
160 
161 #[cfg(test)]
162 impl TestContext for DadkExecuteContextTestBuildRiscV64V1 {
setup() -> Self163     fn setup() -> Self {
164         let base_context = BaseGlobalTestContext::setup();
165         let context =
166             DadkUserExecuteContextBuilder::default_test_execute_context_builder(&base_context)
167                 .target_arch(TargetArch::RiscV64)
168                 .config_dir(Some(base_context.config_v1_dir()))
169                 .build()
170                 .expect("Failed to build DadkExecuteContextTestBuildRiscV64V1");
171         let context = Arc::new(context);
172         context.init(context.clone());
173         DadkExecuteContextTestBuildRiscV64V1 { context }
174     }
175 }
176 
177 macro_rules! impl_for_test_context {
178     ($context:ty) => {
179         #[cfg(test)]
180         impl std::ops::Deref for $context {
181             type Target = DadkUserExecuteContext;
182 
183             fn deref(&self) -> &Self::Target {
184                 &self.context
185             }
186         }
187 
188         #[cfg(test)]
189         impl TestContextExt for $context {
190             fn base_context(&self) -> &BaseGlobalTestContext {
191                 self.base_test_context.as_ref().unwrap()
192             }
193 
194             fn execute_context(&self) -> &DadkUserExecuteContext {
195                 &self.context
196             }
197         }
198     };
199 }
200 
201 impl_for_test_context!(DadkExecuteContextTestBuildX86_64V1);
202 impl_for_test_context!(DadkExecuteContextTestBuildRiscV64V1);
203