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