1 // Copyright (C) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 use std::cmp;
15 use std::collections::HashSet;
16 use std::ops::Deref;
17
18 use crate::manage::database::{RequestDb, TaskQosInfo};
19 use crate::task::config::{Action, Mode};
20
21 /// List of sorted apps.
22 pub(crate) struct SortedApps {
23 inner: Vec<App>,
24 }
25
26 impl SortedApps {
init() -> Self27 pub(crate) fn init() -> Self {
28 Self {
29 inner: reload_all_app_from_database(),
30 }
31 }
32
sort(&mut self, top_uid: Option<u64>, top_user: u64)33 pub(crate) fn sort(&mut self, top_uid: Option<u64>, top_user: u64) {
34 self.inner.sort_by(|a, b| {
35 (a.uid / 200000 == top_user)
36 .cmp(&(b.uid / 200000 == top_user))
37 .then((Some(a.uid) == top_uid).cmp(&(Some(b.uid) == top_uid)))
38 })
39 }
40
reload_all_tasks(&mut self)41 pub(crate) fn reload_all_tasks(&mut self) {
42 self.inner = reload_all_app_from_database();
43 }
44
insert_task(&mut self, uid: u64, task: TaskQosInfo)45 pub(crate) fn insert_task(&mut self, uid: u64, task: TaskQosInfo) {
46 let task = Task {
47 uid,
48 task_id: task.task_id,
49 mode: Mode::from(task.mode),
50 action: Action::from(task.action),
51 priority: task.priority,
52 };
53
54 if let Some(app) = self.inner.iter_mut().find(|app| app.uid == uid) {
55 app.insert(task);
56 return;
57 }
58
59 let mut app = App::new(uid);
60 app.insert(task);
61 self.inner.push(app);
62 }
63
remove_task(&mut self, uid: u64, task_id: u32) -> bool64 pub(crate) fn remove_task(&mut self, uid: u64, task_id: u32) -> bool {
65 // Remove target task in target app.
66 if let Some(app) = self.inner.iter_mut().find(|app| app.uid == uid) {
67 app.remove(task_id)
68 } else {
69 false
70 }
71 }
72 }
73
74 impl Deref for SortedApps {
75 type Target = Vec<App>;
76
deref(&self) -> &Self::Target77 fn deref(&self) -> &Self::Target {
78 &self.inner
79 }
80 }
81
82 /// An independent app.
83 pub(crate) struct App {
84 pub(crate) uid: u64,
85 tasks: Vec<Task>,
86 }
87
88 impl App {
new(uid: u64) -> Self89 fn new(uid: u64) -> Self {
90 Self {
91 uid,
92 tasks: Vec::new(),
93 }
94 }
95
from_raw(uid: u64, tasks: Vec<Task>) -> Self96 fn from_raw(uid: u64, tasks: Vec<Task>) -> Self {
97 Self { uid, tasks }
98 }
99
is_empty(&self) -> bool100 pub(crate) fn is_empty(&self) -> bool {
101 self.tasks.is_empty()
102 }
103
insert(&mut self, task: Task)104 fn insert(&mut self, task: Task) {
105 self.tasks.binary_insert(task)
106 }
107
remove(&mut self, task_id: u32) -> bool108 fn remove(&mut self, task_id: u32) -> bool {
109 if let Some((i, _)) = self
110 .tasks
111 .iter()
112 .enumerate()
113 .find(|(_, task)| task.task_id == task_id)
114 {
115 self.tasks.remove(i);
116 true
117 } else {
118 false
119 }
120 }
121 }
122
123 impl Deref for App {
124 type Target = Vec<Task>;
125
deref(&self) -> &Self::Target126 fn deref(&self) -> &Self::Target {
127 &self.tasks
128 }
129 }
130
131 pub(crate) struct Task {
132 uid: u64,
133 task_id: u32,
134 mode: Mode,
135 action: Action,
136 priority: u32,
137 }
138
139 impl Task {
uid(&self) -> u64140 pub(crate) fn uid(&self) -> u64 {
141 self.uid
142 }
143
task_id(&self) -> u32144 pub(crate) fn task_id(&self) -> u32 {
145 self.task_id
146 }
147
action(&self) -> Action148 pub(crate) fn action(&self) -> Action {
149 self.action
150 }
151 }
152
153 impl Eq for Task {}
154
155 impl Ord for Task {
cmp(&self, other: &Self) -> cmp::Ordering156 fn cmp(&self, other: &Self) -> cmp::Ordering {
157 self.mode
158 .cmp(&other.mode)
159 .then(self.priority.cmp(&other.priority))
160 }
161 }
162
163 impl PartialEq for Task {
eq(&self, other: &Self) -> bool164 fn eq(&self, other: &Self) -> bool {
165 self.mode == other.mode && self.priority == other.priority
166 }
167 }
168
169 impl PartialOrd for Task {
partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>170 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
171 Some(self.cmp(other))
172 }
173 }
174
175 trait Binary<T: Ord> {
binary_insert(&mut self, value: T)176 fn binary_insert(&mut self, value: T);
177 }
178
179 impl<T: Ord> Binary<T> for Vec<T> {
binary_insert(&mut self, value: T)180 fn binary_insert(&mut self, value: T) {
181 match self.binary_search(&value) {
182 Ok(n) => self.insert(n, value),
183 Err(n) => self.insert(n, value),
184 }
185 }
186 }
187
reload_all_app_from_database() -> Vec<App>188 fn reload_all_app_from_database() -> Vec<App> {
189 let mut inner = Vec::new();
190 for uid in reload_app_list_from_database() {
191 let mut tasks = reload_tasks_of_app_from_database(uid);
192 // Ensure that tasks are arranged in order
193 tasks.sort();
194 inner.push(App::from_raw(uid, tasks));
195 }
196 inner
197 }
198
reload_tasks_of_app_from_database(uid: u64) -> Vec<Task>199 fn reload_tasks_of_app_from_database(uid: u64) -> Vec<Task> {
200 RequestDb::get_instance()
201 .get_app_task_qos_infos(uid)
202 .iter()
203 .map(|info| Task {
204 uid,
205 task_id: info.task_id,
206 mode: Mode::from(info.mode),
207 action: Action::from(info.action),
208 priority: info.priority,
209 })
210 .collect()
211 }
212
reload_app_list_from_database() -> HashSet<u64>213 fn reload_app_list_from_database() -> HashSet<u64> {
214 RequestDb::get_instance()
215 .get_app_infos()
216 .into_iter()
217 .collect()
218 }
219
220 impl RequestDb {
get_app_infos(&self) -> Vec<u64>221 fn get_app_infos(&self) -> Vec<u64> {
222 let sql = "SELECT DISTINCT uid FROM request_task";
223 self.query_integer(sql)
224 }
225 }
226
227 #[cfg(feature = "oh")]
228 #[cfg(test)]
229 mod ut_manage_scheduler_qos_apps {
230 use super::{App, Task};
231 use crate::manage::database::RequestDb;
232 use crate::task::config::Mode;
233 use crate::tests::{lock_database, test_init};
234 use crate::utils::get_current_timestamp;
235 use crate::utils::task_id_generator::TaskIdGenerator;
236 impl Task {
new(task_id: u32, mode: Mode, priority: u32) -> Self237 fn new(task_id: u32, mode: Mode, priority: u32) -> Self {
238 Self {
239 uid: 0,
240 action: crate::task::config::Action::Any,
241 task_id,
242 mode,
243 priority,
244 }
245 }
246 }
247
248 #[test]
ut_app_insert()249 fn ut_app_insert() {
250 let mut app = App::new(1);
251 assert!(app.tasks.is_empty());
252 assert_eq!(app.uid, 1);
253
254 app.insert(Task::new(1, Mode::FrontEnd, 0));
255 assert_eq!(app.tasks[0].task_id, 1);
256 assert_eq!(app.tasks[0].mode, Mode::FrontEnd);
257 assert_eq!(app.tasks[0].priority, 0);
258
259 app.insert(Task::new(2, Mode::FrontEnd, 100));
260 assert_eq!(app.tasks[0].task_id, 1);
261 assert_eq!(app.tasks[1].task_id, 2);
262
263 app.insert(Task::new(3, Mode::FrontEnd, 50));
264 assert_eq!(app.tasks[0].task_id, 1);
265 assert_eq!(app.tasks[1].task_id, 3);
266 assert_eq!(app.tasks[2].task_id, 2);
267
268 app.insert(Task::new(4, Mode::BackGround, 0));
269 assert_eq!(app.tasks[0].task_id, 1);
270 assert_eq!(app.tasks[1].task_id, 3);
271 assert_eq!(app.tasks[2].task_id, 2);
272 assert_eq!(app.tasks[3].task_id, 4);
273
274 app.insert(Task::new(5, Mode::BackGround, 100));
275 assert_eq!(app.tasks[0].task_id, 1);
276 assert_eq!(app.tasks[1].task_id, 3);
277 assert_eq!(app.tasks[2].task_id, 2);
278 assert_eq!(app.tasks[3].task_id, 4);
279 assert_eq!(app.tasks[4].task_id, 5);
280
281 app.insert(Task::new(6, Mode::BackGround, 50));
282 assert_eq!(app.tasks[0].task_id, 1);
283 assert_eq!(app.tasks[1].task_id, 3);
284 assert_eq!(app.tasks[2].task_id, 2);
285 assert_eq!(app.tasks[3].task_id, 4);
286 assert_eq!(app.tasks[4].task_id, 6);
287 assert_eq!(app.tasks[5].task_id, 5);
288 }
289
290 #[test]
ut_app_remove()291 fn ut_app_remove() {
292 let mut app = App::new(1);
293 for i in 0..5 {
294 app.insert(Task::new(i, Mode::FrontEnd, i));
295 }
296 assert_eq!(app.tasks[0].task_id, 0);
297 assert_eq!(app.tasks[1].task_id, 1);
298 assert_eq!(app.tasks[2].task_id, 2);
299 assert_eq!(app.tasks[3].task_id, 3);
300 assert_eq!(app.tasks[4].task_id, 4);
301
302 app.remove(3);
303 assert_eq!(app.tasks[0].task_id, 0);
304 assert_eq!(app.tasks[1].task_id, 1);
305 assert_eq!(app.tasks[2].task_id, 2);
306 assert_eq!(app.tasks[3].task_id, 4);
307
308 app.remove(1);
309 assert_eq!(app.tasks[0].task_id, 0);
310 assert_eq!(app.tasks[1].task_id, 2);
311 assert_eq!(app.tasks[2].task_id, 4);
312
313 app.remove(4);
314 assert_eq!(app.tasks[0].task_id, 0);
315 assert_eq!(app.tasks[1].task_id, 2);
316
317 app.remove(0);
318 assert_eq!(app.tasks[0].task_id, 2);
319 }
320
321 #[test]
ut_task_partial_ord()322 fn ut_task_partial_ord() {
323 let task1 = Task::new(1, Mode::FrontEnd, 0);
324 let task2 = Task::new(2, Mode::FrontEnd, 1);
325 let task3 = Task::new(3, Mode::BackGround, 0);
326 let task4 = Task::new(4, Mode::BackGround, 1);
327 assert!(task1 < task2);
328 assert!(task1 < task3);
329 assert!(task1 < task4);
330 assert!(task2 < task3);
331 assert!(task2 < task4);
332 assert!(task3 < task4);
333 }
334
335 #[test]
ut_database_app_info()336 fn ut_database_app_info() {
337 test_init();
338 let db = RequestDb::get_instance();
339 let _lock = lock_database();
340 let uid = get_current_timestamp();
341
342 for i in 0..10 {
343 db.execute(&format!(
344 "INSERT INTO request_task (task_id, uid, bundle) VALUES ({}, {}, '{}')",
345 TaskIdGenerator::generate(),
346 uid + i / 5,
347 "test_bundle",
348 ))
349 .unwrap();
350 }
351 let v = db.get_app_infos();
352 assert_eq!(v.iter().filter(|a| **a == uid).count(), 1);
353 assert_eq!(v.iter().filter(|a| **a == uid + 1).count(), 1);
354 }
355 }
356