• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::collections::HashMap;
15 use std::fmt::Display;
16 use std::mem::MaybeUninit;
17 use std::pin::Pin;
18 use std::sync::{Arc, Mutex, Once};
19 
20 pub(crate) use ffi::*;
21 
22 cfg_oh! {
23     use crate::manage::SystemConfig;
24 }
25 
26 cfg_not_oh! {
27     use rusqlite::Connection;
28     const CREATE_TABLE: &'static str = "CREATE TABLE IF NOT EXISTS request_task (task_id INTEGER PRIMARY KEY, uid INTEGER, token_id INTEGER, action INTEGER, mode INTEGER, cover INTEGER, network INTEGER, metered INTEGER, roaming INTEGER, ctime INTEGER, mtime INTEGER, reason INTEGER, gauge INTEGER, retry INTEGER, redirect INTEGER, tries INTEGER, version INTEGER, config_idx INTEGER, begins INTEGER, ends INTEGER, precise INTEGER, priority INTEGER, background INTEGER, bundle TEXT, url TEXT, data TEXT, token TEXT, title TEXT, description TEXT, method TEXT, headers TEXT, config_extras TEXT, mime_type TEXT, state INTEGER, idx INTEGER, total_processed INTEGER, sizes TEXT, processed TEXT, extras TEXT, form_items BLOB, file_specs BLOB, each_file_status BLOB, body_file_names BLOB, certs_paths BLOB)";
29 }
30 use crate::config::Action;
31 use crate::error::ErrorCode;
32 use crate::service::client::ClientManagerEntry;
33 use crate::task::config::TaskConfig;
34 use crate::task::ffi::{CTaskConfig, CTaskInfo, CUpdateInfo};
35 use crate::task::info::{State, TaskInfo, UpdateInfo};
36 use crate::task::reason::Reason;
37 use crate::task::request_task::RequestTask;
38 use crate::utils::{call_once, get_current_timestamp, hashmap_to_string};
39 
40 pub(crate) struct RequestDb {
41     user_file_tasks: Mutex<HashMap<u32, Arc<RequestTask>>>,
42     #[cfg(feature = "oh")]
43     pub(crate) inner: *mut RequestDataBase,
44     #[cfg(not(feature = "oh"))]
45     pub(crate) inner: Connection,
46 }
47 
48 impl RequestDb {
49     #[cfg(feature = "oh")]
get_instance() -> &'static Self50     pub(crate) fn get_instance() -> &'static Self {
51         static mut DB: MaybeUninit<RequestDb> = MaybeUninit::uninit();
52         static ONCE: Once = Once::new();
53 
54         call_once(&ONCE, || {
55             let (path, encrypt) = if cfg!(test) {
56                 ("/data/test/request.db", false)
57             } else {
58                 ("/data/service/el1/public/database/request/request.db", true)
59             };
60 
61             let inner = GetDatabaseInstance(path, encrypt);
62             unsafe {
63                 DB.write(RequestDb {
64                     inner,
65                     user_file_tasks: Mutex::new(HashMap::new()),
66                 });
67             }
68         });
69         unsafe { DB.assume_init_mut() }
70     }
71 
72     #[cfg(not(feature = "oh"))]
get_instance() -> &'static Self73     pub(crate) fn get_instance() -> &'static Self {
74         static mut DATABASE: MaybeUninit<RequestDb> = MaybeUninit::uninit();
75         static ONCE: Once = Once::new();
76 
77         call_once(&ONCE, || {
78             let inner = Connection::open_in_memory().unwrap();
79             inner.execute(&CREATE_TABLE, ()).unwrap();
80             unsafe {
81                 DATABASE.write(RequestDb {
82                     inner,
83                     user_file_tasks: Mutex::new(HashMap::new()),
84                 })
85             };
86         });
87 
88         unsafe { DATABASE.assume_init_ref() }
89     }
90 
91     #[cfg(feature = "oh")]
execute(&self, sql: &str) -> Result<(), i32>92     pub(crate) fn execute(&self, sql: &str) -> Result<(), i32> {
93         let ret = unsafe { Pin::new_unchecked(&mut *self.inner).ExecuteSql(sql) };
94         if ret == 0 {
95             Ok(())
96         } else {
97             error!("execute sql failed: {}", ret);
98             sys_event!(
99                 ExecFault,
100                 DfxCode::RDB_FAULT_04,
101                 &format!("execute sql failed: {}", ret)
102             );
103             Err(ret)
104         }
105     }
106 
107     #[cfg(not(feature = "oh"))]
execute(&self, sql: &str) -> Result<(), i32>108     pub(crate) fn execute(&self, sql: &str) -> Result<(), i32> {
109         let res = self.inner.execute(sql, ());
110 
111         self.inner.execute(sql, ()).map(|_| ()).map_err(|e| {
112             error!("execute sql failed: {}", e);
113             sys_event!(
114                 ExecFault,
115                 DfxCode::RDB_FAULT_04,
116                 &format!("execute {} failed: {}", sql, ret)
117             );
118             e.sqlite_error_code().unwrap() as u32 as i32
119         })
120     }
121 
122     #[cfg(feature = "oh")]
query_integer<T: TryFrom<i64> + Default>(&self, sql: &str) -> Vec<T> where T::Error: Display,123     pub(crate) fn query_integer<T: TryFrom<i64> + Default>(&self, sql: &str) -> Vec<T>
124     where
125         T::Error: Display,
126     {
127         let mut v = vec![];
128         let ret = unsafe { Pin::new_unchecked(&mut *self.inner).QueryInteger(sql, &mut v) };
129         let v = v
130             .into_iter()
131             .map(|a| {
132                 a.try_into().unwrap_or_else(|e| {
133                     error!("query_integer failed, value: {}", e);
134                     sys_event!(
135                         ExecFault,
136                         DfxCode::RDB_FAULT_06,
137                         &format!("query_integer failed, value: {}", e)
138                     );
139                     Default::default()
140                 })
141             })
142             .collect();
143 
144         if ret != 0 {
145             error!("query integer err:{}", ret);
146             sys_event!(
147                 ExecFault,
148                 DfxCode::RDB_FAULT_06,
149                 &format!("query integer err:{}", ret)
150             );
151         }
152         v
153     }
154 
155     #[cfg(not(feature = "oh"))]
query_integer<T: TryFrom<i64> + Default>(&self, sql: &str) -> Vec<T> where T::Error: Display,156     pub(crate) fn query_integer<T: TryFrom<i64> + Default>(&self, sql: &str) -> Vec<T>
157     where
158         T::Error: Display,
159     {
160         let mut stmt = self.inner.prepare(sql).unwrap();
161         let rows = stmt.query_map([], |row| Ok(row.get(0).unwrap())).unwrap();
162         let v: Vec<i64> = rows.into_iter().map(|a| a.unwrap()).collect();
163         v.into_iter()
164             .map(|a| a.try_into().unwrap_or_else(|_| Default::default()))
165             .collect()
166     }
167 
contains_task(&self, task_id: u32) -> bool168     pub(crate) fn contains_task(&self, task_id: u32) -> bool {
169         let sql = format!(
170             "SELECT COUNT(*) FROM request_task WHERE task_id = {}",
171             task_id
172         );
173         let v = self.query_integer::<u32>(&sql);
174         if v.is_empty() {
175             error!("contains_task check failed, empty result");
176             sys_event!(
177                 ExecFault,
178                 DfxCode::RDB_FAULT_06,
179                 "contains_task check failed, empty result"
180             );
181             false
182         } else {
183             v[0] == 1
184         }
185     }
186 
query_task_token_id(&self, task_id: u32) -> Result<u64, i32>187     pub(crate) fn query_task_token_id(&self, task_id: u32) -> Result<u64, i32> {
188         let sql = format!(
189             "SELECT token_id FROM request_task WHERE task_id = {}",
190             task_id
191         );
192         let v = self.query_integer::<u64>(&sql);
193         if v.is_empty() {
194             error!("query_task_token_id failed, empty result");
195             sys_event!(
196                 ExecFault,
197                 DfxCode::RDB_FAULT_06,
198                 "query_task_token_id failed, empty result"
199             );
200             Err(-1)
201         } else {
202             Ok(v[0])
203         }
204     }
205 
206     #[cfg(feature = "oh")]
insert_task(&self, task: RequestTask) -> bool207     pub(crate) fn insert_task(&self, task: RequestTask) -> bool {
208         let task_id = task.task_id();
209         let uid = task.uid();
210 
211         debug!("Insert task to database, uid: {}, tid: {}", uid, task_id);
212 
213         if self.contains_task(task_id) {
214             return false;
215         }
216 
217         let task_config = task.config();
218         let config_set = task_config.build_config_set();
219         let c_task_config = task_config.to_c_struct(task_id, uid, &config_set);
220 
221         let task_info = &task.info();
222         let info_set = task_info.build_info_set();
223         let c_task_info = task_info.to_c_struct(&info_set);
224 
225         if !unsafe { RecordRequestTask(&c_task_info, &c_task_config) } {
226             info!("task {} insert database fail", task_id);
227         }
228 
229         // For some tasks contains user_file, we must save it to map first.
230         if task.conf.contains_user_file() {
231             self.user_file_tasks
232                 .lock()
233                 .unwrap()
234                 .insert(task.task_id(), Arc::new(task));
235         };
236         true
237     }
238 
239     #[cfg(not(feature = "oh"))]
insert_task(&self, task: RequestTask) -> bool240     pub(crate) fn insert_task(&self, task: RequestTask) -> bool {
241         use crate::task::reason::Reason;
242         use crate::utils::get_current_timestamp;
243 
244         let task_id = task.task_id();
245         let uid = task.uid();
246         info!("insert database, uid {} tid {}", uid, task_id);
247         if self.contains_task(task_id) {
248             return false;
249         }
250 
251         let config = task.config();
252         let sql = format!(
253             "INSERT OR REPLACE INTO request_task (task_id, uid, token_id, action, mode, cover, network, metered, roaming, ctime, gauge, retry, redirect, version, config_idx, begins, ends, precise, priority, background, bundle, url, data, token, title, description, method, headers, config_extras, mtime, reason, tries, state)
254             VALUES ({}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', {}, {}, {}, {})",
255             config.common_data.task_id,
256             config.common_data.uid,
257             config.common_data.token_id,
258             config.common_data.action.repr,
259             config.common_data.mode.repr,
260             config.common_data.cover,
261             config.common_data.network_config as u8,
262             config.common_data.metered as u8,
263             config.common_data.roaming as u8,
264             get_current_timestamp(),
265             config.common_data.gauge,
266             config.common_data.retry,
267             config.common_data.redirect,
268             config.version as u8,
269             config.common_data.index,
270             config.common_data.begins,
271             config.common_data.ends,
272             config.common_data.precise,
273             config.common_data.priority,
274             config.common_data.background as u8,
275             config.bundle,
276             config.url,
277             config.data,
278             config.token,
279             config.title,
280             config.description,
281             config.method,
282             hashmap_to_string(&config.headers),
283             hashmap_to_string(&config.extras),
284             get_current_timestamp(),
285             Reason::Default.repr,
286             0,
287             State::Initialized.repr,
288         );
289         self.execute(&sql).unwrap();
290 
291         // For some tasks contains user_file, we must save it to map first.
292         if task.conf.contains_user_file() {
293             self.user_file_tasks
294                 .lock()
295                 .unwrap()
296                 .insert(task.task_id(), Arc::new(task));
297         };
298         true
299     }
300 
remove_user_file_task(&self, task_id: u32)301     pub(crate) fn remove_user_file_task(&self, task_id: u32) {
302         let mut task_map = self.user_file_tasks.lock().unwrap();
303         task_map.remove(&task_id);
304         debug!("Remove completed user file task, task_id: {}", task_id);
305     }
306 
307     #[cfg(feature = "oh")]
update_task(&self, task_id: u32, update_info: UpdateInfo)308     pub(crate) fn update_task(&self, task_id: u32, update_info: UpdateInfo) {
309         debug!("Update task in database, task_id: {}", task_id);
310         if !self.contains_task(task_id) {
311             return;
312         }
313         let sizes = format!("{:?}", update_info.progress.sizes);
314         let processed = format!("{:?}", update_info.progress.processed);
315         let extras = hashmap_to_string(&update_info.progress.extras);
316         let c_update_info = update_info.to_c_struct(&sizes, &processed, &extras);
317         let ret = unsafe { UpdateRequestTask(task_id, &c_update_info) };
318         debug!("Update task in database, ret is {}", ret);
319     }
320 
update_task_time(&self, task_id: u32, task_time: u64)321     pub(crate) fn update_task_time(&self, task_id: u32, task_time: u64) {
322         let ret = unsafe { UpdateRequestTaskTime(task_id, task_time) };
323         debug!("Update task time in database, ret is {}", ret);
324     }
325 
clear_invalid_records(&self)326     pub(crate) fn clear_invalid_records(&self) {
327         let sql = format!(
328             "UPDATE request_task SET state = {} WHERE state = {} AND reason = {}",
329             State::Failed.repr,
330             State::Waiting.repr,
331             Reason::Default.repr,
332         );
333         let _ = self.execute(&sql);
334     }
335 
query_task_uid(&self, task_id: u32) -> Option<u64>336     pub(crate) fn query_task_uid(&self, task_id: u32) -> Option<u64> {
337         let sql = format!("SELECT uid FROM request_task WHERE task_id = {}", task_id);
338         self.query_integer(&sql).first().copied()
339     }
340 
query_task_action(&self, task_id: u32) -> Option<Action>341     pub(crate) fn query_task_action(&self, task_id: u32) -> Option<Action> {
342         let sql = format!(
343             "SELECT action FROM request_task WHERE task_id = {}",
344             task_id
345         );
346         self.query_integer(&sql).first().map(|action: &i32| Action {
347             repr: *action as u8,
348         })
349     }
350 
351     #[cfg(not(feature = "oh"))]
update_task(&self, task_id: u32, update_info: UpdateInfo)352     pub(crate) fn update_task(&self, task_id: u32, update_info: UpdateInfo) {
353         if !self.contains_task(task_id) {
354             return;
355         }
356         let sql = format!(
357             "UPDATE request_task SET sizes = {:?}, processed = {:?}, extras = {} WHERE task_id = {}",
358             update_info.progress.sizes, update_info.progress.processed, hashmap_to_string(&update_info.progress.extras),
359             task_id,
360         );
361         self.execute(&sql).unwrap();
362     }
363 
update_task_state(&self, task_id: u32, state: State, reason: Reason)364     pub(crate) fn update_task_state(&self, task_id: u32, state: State, reason: Reason) {
365         let sql = format!(
366             "UPDATE request_task SET state = {}, mtime = {}, reason = {} WHERE task_id = {}",
367             state.repr,
368             get_current_timestamp(),
369             reason.repr,
370             task_id
371         );
372         let _ = self.execute(&sql);
373     }
374 
update_task_max_speed(&self, task_id: u32, max_speed: i64)375     pub(crate) fn update_task_max_speed(&self, task_id: u32, max_speed: i64) {
376         let sql = format!(
377             "UPDATE request_task SET max_speed = {} WHERE task_id = {}",
378             max_speed, task_id
379         );
380         let _ = self.execute(&sql);
381     }
382 
update_task_sizes(&self, task_id: u32, sizes: &Vec<i64>)383     pub(crate) fn update_task_sizes(&self, task_id: u32, sizes: &Vec<i64>) {
384         let sql = format!(
385             "UPDATE request_task SET sizes = '{:?}' WHERE task_id = {}",
386             sizes, task_id
387         );
388         let _ = self.execute(&sql);
389     }
390 
391     #[cfg(feature = "oh")]
get_task_info(&self, task_id: u32) -> Option<TaskInfo>392     pub(crate) fn get_task_info(&self, task_id: u32) -> Option<TaskInfo> {
393         debug!("Get task info from database");
394         let c_task_info = unsafe { GetTaskInfo(task_id) };
395         if c_task_info.is_null() {
396             info!("No task found in database");
397             return None;
398         }
399         let c_task_info = unsafe { &*c_task_info };
400         let task_info = TaskInfo::from_c_struct(c_task_info);
401         unsafe { DeleteCTaskInfo(c_task_info) };
402         Some(task_info)
403     }
404 
query_task_total_processed(&self, task_id: u32) -> Option<i64>405     pub(crate) fn query_task_total_processed(&self, task_id: u32) -> Option<i64> {
406         let sql = format!(
407             "SELECT total_processed FROM request_task WHERE task_id = {}",
408             task_id
409         );
410         self.query_integer(&sql).first().copied()
411     }
412 
query_task_state(&self, task_id: u32) -> Option<u8>413     pub(crate) fn query_task_state(&self, task_id: u32) -> Option<u8> {
414         let sql = format!("SELECT state FROM request_task WHERE task_id = {}", task_id);
415         self.query_integer(&sql)
416             .first()
417             .map(|state: &i32| *state as u8)
418     }
419 
420     #[cfg(not(feature = "oh"))]
get_task_info(&self, task_id: u32) -> Option<TaskInfo>421     pub(crate) fn get_task_info(&self, task_id: u32) -> Option<TaskInfo> {
422         use crate::info::CommonTaskInfo;
423         use crate::task::notify::Progress;
424 
425         let sql = format!("SELECT task_id, uid, action, mode, mtime, reason, gauge, retry, version, priority, ctime, tries, url, data, token, state, idx from request_task where task_id = {}", task_id);
426         let mut stmt = self.inner.prepare(&sql).unwrap();
427         let mut row = stmt
428             .query_map([], |row| {
429                 Ok(TaskInfo {
430                     common_data: CommonTaskInfo {
431                         task_id: row.get(0).unwrap(),
432                         uid: row.get(1).unwrap(),
433                         action: row.get(2).unwrap(),
434                         mode: row.get(3).unwrap(),
435                         mtime: row.get(4).unwrap(),
436                         reason: row.get(5).unwrap(),
437                         gauge: row.get(6).unwrap(),
438                         retry: row.get(7).unwrap(),
439                         version: row.get(8).unwrap(),
440                         priority: row.get(9).unwrap(),
441                         ctime: row.get(10).unwrap(),
442                         tries: row.get(11).unwrap(),
443                     },
444                     url: row.get(12).unwrap(),
445                     data: row.get(13).unwrap(),
446                     token: row.get(14).unwrap(),
447                     bundle: "".to_string(),
448                     title: "".to_string(),
449                     description: "".to_string(),
450                     mime_type: "".to_string(),
451                     extras: HashMap::new(),
452                     each_file_status: vec![],
453                     form_items: vec![],
454                     file_specs: vec![],
455                     progress: Progress::new(vec![]),
456                 })
457             })
458             .unwrap();
459         row.next().map(|info| info.unwrap())
460     }
461 
462     #[cfg(feature = "oh")]
get_task_config(&self, task_id: u32) -> Option<TaskConfig>463     pub(crate) fn get_task_config(&self, task_id: u32) -> Option<TaskConfig> {
464         debug!("query single task config in database");
465         let c_task_config = unsafe { QueryTaskConfig(task_id) };
466         if c_task_config.is_null() {
467             error!("can not find task in database, task id: {}", task_id);
468             sys_event!(
469                 ExecFault,
470                 DfxCode::RDB_FAULT_06,
471                 &format!("can not find task in database, task id: {}", task_id)
472             );
473             None
474         } else {
475             let task_config = TaskConfig::from_c_struct(unsafe { &*c_task_config });
476             unsafe { DeleteCTaskConfig(c_task_config) };
477             Some(task_config)
478         }
479     }
480 
481     #[cfg(not(feature = "oh"))]
get_task_config(&self, task_id: u32) -> Option<TaskConfig>482     pub(crate) fn get_task_config(&self, task_id: u32) -> Option<TaskConfig> {
483         use crate::config::{Action, CommonTaskConfig, NetworkConfig};
484 
485         debug!("query single task config in database");
486         let sql = format!("SELECT url, title, description, method, data, token, version from request_task where task_id = {}", task_id);
487         let mut stmt = self.inner.prepare(&sql).unwrap();
488         let mut row = stmt
489             .query_map([], |row| {
490                 let version: u8 = row.get(6).unwrap();
491                 Ok(TaskConfig {
492                     url: row.get(0).unwrap(),
493                     title: row.get(1).unwrap(),
494                     description: row.get(2).unwrap(),
495                     method: row.get(3).unwrap(),
496                     data: row.get(4).unwrap(),
497                     token: row.get(5).unwrap(),
498                     version: version.into(),
499                     common_data: CommonTaskConfig {
500                         task_id,
501                         uid: 0,
502                         token_id: 0,
503                         action: Action::Download,
504                         mode: Mode::BackGround,
505                         cover: true,
506                         network_config: NetworkConfig::Any,
507                         metered: true,
508                         roaming: true,
509                         gauge: true,
510                         retry: true,
511                         redirect: true,
512                         index: 0,
513                         begins: 0,
514                         ends: 0,
515                         precise: true,
516                         priority: 0,
517                         background: true,
518                         multipart: false,
519                     },
520                     headers: Default::default(),
521                     extras: Default::default(),
522                     form_items: Default::default(),
523                     file_specs: Default::default(),
524                     bundle: Default::default(),
525                     bundle_type: 0,
526                     body_file_paths: vec![],
527                     certs_path: vec![],
528                     proxy: Default::default(),
529                     certificate_pins: Default::default(),
530                     atomic_account: Default::default(),
531                 })
532             })
533             .unwrap();
534         row.next().map(|config| config.unwrap())
535     }
536 
537     #[cfg(feature = "oh")]
get_task_qos_info(&self, task_id: u32) -> Option<TaskQosInfo>538     pub(crate) fn get_task_qos_info(&self, task_id: u32) -> Option<TaskQosInfo> {
539         #[cfg(feature = "oh")]
540         {
541             let mut info = TaskQosInfo {
542                 task_id,
543                 action: 0,
544                 mode: 0,
545                 state: 0,
546                 priority: 0,
547             };
548             let sql = format!(
549                 "SELECT action, mode, state, priority FROM request_task WHERE task_id = {}",
550                 task_id
551             );
552             let ret =
553                 unsafe { Pin::new_unchecked(&mut *self.inner).GetTaskQosInfo(&sql, &mut info) };
554             if ret == 0 {
555                 Some(info)
556             } else {
557                 None
558             }
559         }
560     }
561 
562     #[cfg(not(feature = "oh"))]
get_task_qos_info(&self, task_id: u32) -> Option<TaskQosInfo>563     pub(crate) fn get_task_qos_info(&self, task_id: u32) -> Option<TaskQosInfo> {
564         let sql = format!(
565             "SELECT action, mode, state, priority FROM request_task WHERE task_id = {}",
566             task_id,
567         );
568         let mut stmt = self.inner.prepare(&sql).unwrap();
569         let mut rows = stmt
570             .query_map([], |row| {
571                 Ok(TaskQosInfo {
572                     task_id: task_id,
573                     action: row.get::<_, u8>(0).unwrap().into(),
574                     mode: row.get::<_, u8>(1).unwrap().into(),
575                     state: row.get(2).unwrap(),
576                     priority: row.get(3).unwrap(),
577                 })
578             })
579             .unwrap();
580         rows.next().map(|info| info.unwrap())
581     }
582 
get_app_task_qos_infos_inner(&self, sql: &str) -> Vec<TaskQosInfo>583     pub(crate) fn get_app_task_qos_infos_inner(&self, sql: &str) -> Vec<TaskQosInfo> {
584         #[cfg(feature = "oh")]
585         {
586             let mut v = vec![];
587             let _ = unsafe { Pin::new_unchecked(&mut *self.inner).GetAppTaskQosInfos(sql, &mut v) };
588             v
589         }
590         #[cfg(not(feature = "oh"))]
591         {
592             let mut stmt = self.inner.prepare(&sql).unwrap();
593             let rows = stmt
594                 .query_map([], |row| {
595                     Ok(TaskQosInfo {
596                         task_id: row.get(0).unwrap(),
597                         action: row.get::<_, u8>(1).unwrap().into(),
598                         mode: row.get::<_, u8>(2).unwrap().into(),
599                         state: row.get(3).unwrap(),
600                         priority: row.get(4).unwrap(),
601                     })
602                 })
603                 .unwrap();
604             rows.into_iter().map(|info| info.unwrap()).collect()
605         }
606     }
607 
get_app_task_qos_infos(&self, uid: u64) -> Vec<TaskQosInfo>608     pub(crate) fn get_app_task_qos_infos(&self, uid: u64) -> Vec<TaskQosInfo> {
609         let sql = format!(
610             "SELECT task_id, action, mode, state, priority FROM request_task WHERE uid = {} AND ((state = {} AND reason = {}) OR state = {} OR state = {})",
611             uid,
612             State::Waiting.repr,
613             Reason::RunningTaskMeetLimits.repr,
614             State::Running.repr,
615             State::Retrying.repr,
616         );
617         self.get_app_task_qos_infos_inner(&sql)
618     }
619 
get_task( &self, task_id: u32, #[cfg(feature = "oh")] system: SystemConfig, client_manager: &ClientManagerEntry, upload_resume: bool, ) -> Result<Arc<RequestTask>, ErrorCode>620     pub(crate) fn get_task(
621         &self,
622         task_id: u32,
623         #[cfg(feature = "oh")] system: SystemConfig,
624         client_manager: &ClientManagerEntry,
625         upload_resume: bool,
626     ) -> Result<Arc<RequestTask>, ErrorCode> {
627         // If this task exists in `user_file_map`,get it from this map.
628         if let Some(task) = self.user_file_tasks.lock().unwrap().get(&task_id) {
629             return Ok(task.clone());
630         }
631 
632         // 此处需要根据 task_id 从数据库构造指定的任务。
633         let config = match self.get_task_config(task_id) {
634             Some(config) => config,
635             None => return Err(ErrorCode::TaskNotFound),
636         };
637         let task_id = config.common_data.task_id;
638 
639         let task_info = match self.get_task_info(task_id) {
640             Some(info) => info,
641             None => return Err(ErrorCode::TaskNotFound),
642         };
643 
644         let state = State::from(task_info.progress.common_data.state);
645         debug!("get_task {} state is {:?}", task_id, state);
646         if state == State::Removed {
647             error!("get_task state is Removed, {}", task_id);
648             sys_event!(
649                 ExecFault,
650                 DfxCode::RDB_FAULT_06,
651                 &format!("get_task state is Removed, {}", task_id)
652             );
653             return Err(ErrorCode::TaskStateErr);
654         }
655 
656         match RequestTask::new_by_info(
657             config,
658             #[cfg(feature = "oh")]
659             system,
660             task_info,
661             client_manager.clone(),
662             upload_resume,
663         ) {
664             Ok(task) => Ok(Arc::new(task)),
665             Err(e) => {
666                 error!("new RequestTask failed {}, err: {:?}", task_id, e);
667                 sys_event!(
668                     ExecFault,
669                     DfxCode::RDB_FAULT_06,
670                     &format!("new RequestTask failed {}, err: {:?}", task_id, e)
671                 );
672                 Err(e)
673             }
674         }
675     }
676 }
677 
678 unsafe impl Send for RequestDb {}
679 unsafe impl Sync for RequestDb {}
680 
681 #[cfg(feature = "oh")]
682 
683 extern "C" {
DeleteCTaskConfig(ptr: *const CTaskConfig)684     fn DeleteCTaskConfig(ptr: *const CTaskConfig);
DeleteCTaskInfo(ptr: *const CTaskInfo)685     fn DeleteCTaskInfo(ptr: *const CTaskInfo);
GetTaskInfo(task_id: u32) -> *const CTaskInfo686     fn GetTaskInfo(task_id: u32) -> *const CTaskInfo;
QueryTaskConfig(task_id: u32) -> *const CTaskConfig687     fn QueryTaskConfig(task_id: u32) -> *const CTaskConfig;
RecordRequestTask(info: *const CTaskInfo, config: *const CTaskConfig) -> bool688     fn RecordRequestTask(info: *const CTaskInfo, config: *const CTaskConfig) -> bool;
UpdateRequestTask(id: u32, info: *const CUpdateInfo) -> bool689     fn UpdateRequestTask(id: u32, info: *const CUpdateInfo) -> bool;
UpdateRequestTaskTime(task_id: u32, taskTime: u64) -> bool690     fn UpdateRequestTaskTime(task_id: u32, taskTime: u64) -> bool;
691 }
692 
693 #[cxx::bridge(namespace = "OHOS::Request")]
694 mod ffi {
695     #[derive(Clone, Debug, Copy)]
696     pub(crate) struct TaskQosInfo {
697         pub(crate) task_id: u32,
698         pub(crate) action: u8,
699         pub(crate) mode: u8,
700         pub(crate) state: u8,
701         pub(crate) priority: u32,
702     }
703 
704     unsafe extern "C++" {
705         include!("c_request_database.h");
706         type RequestDataBase;
GetDatabaseInstance(path: &str, encrypt: bool) -> *mut RequestDataBase707         fn GetDatabaseInstance(path: &str, encrypt: bool) -> *mut RequestDataBase;
ExecuteSql(self: Pin<&mut RequestDataBase>, sql: &str) -> i32708         fn ExecuteSql(self: Pin<&mut RequestDataBase>, sql: &str) -> i32;
QueryInteger(self: Pin<&mut RequestDataBase>, sql: &str, v: &mut Vec<i64>) -> i32709         fn QueryInteger(self: Pin<&mut RequestDataBase>, sql: &str, v: &mut Vec<i64>) -> i32;
GetAppTaskQosInfos( self: Pin<&mut RequestDataBase>, sql: &str, v: &mut Vec<TaskQosInfo>, ) -> i32710         fn GetAppTaskQosInfos(
711             self: Pin<&mut RequestDataBase>,
712             sql: &str,
713             v: &mut Vec<TaskQosInfo>,
714         ) -> i32;
GetTaskQosInfo(self: Pin<&mut RequestDataBase>, sql: &str, res: &mut TaskQosInfo) -> i32715         fn GetTaskQosInfo(self: Pin<&mut RequestDataBase>, sql: &str, res: &mut TaskQosInfo)
716             -> i32;
717     }
718 }
719 
720 #[cfg(feature = "oh")]
721 #[cfg(test)]
722 mod ut_database {
723     include!("../../tests/ut/manage/ut_database.rs");
724 }
725