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::sync::LazyLock;
15 use std::time::{SystemTime, UNIX_EPOCH};
16
17 use rdb::{OpenConfig, RdbStore, SecurityLevel};
18
19 use crate::service::notification_bar::NotificationDispatcher;
20
21 const DB_PATH: &str = if cfg!(test) {
22 "/data/test/notification.db"
23 } else {
24 "/data/service/el1/public/database/request/request.db"
25 };
26
27 const MILLIS_IN_A_WEEK: u64 = 7 * 24 * 60 * 60 * 1000;
28
29 pub(crate) static REQUEST_DB: LazyLock<RdbStore<'static>> = LazyLock::new(|| {
30 let mut config = OpenConfig::new(DB_PATH);
31 config.security_level(SecurityLevel::S1);
32 if cfg!(test) {
33 config.encrypt_status(false);
34 config.bundle_name("Test");
35 } else {
36 config.encrypt_status(true);
37 }
38 RdbStore::open(config).unwrap()
39 });
40
clear_database_part(pre_count: usize) -> Result<bool, ()>41 pub(crate) fn clear_database_part(pre_count: usize) -> Result<bool, ()> {
42 let mut remain = true;
43 // rdb not support RETURNING expr.
44 let current_time = match SystemTime::now().duration_since(UNIX_EPOCH) {
45 Ok(duration) => duration,
46 Err(e) => {
47 error!("Failed to get current time: {}", e);
48 return Err(());
49 }
50 }
51 .as_millis() as u64;
52
53 let task_ids: Vec<_> = match REQUEST_DB.query::<u32>(
54 "SELECT task_id from request_task WHERE mtime < ? LIMIT ?",
55 (current_time - MILLIS_IN_A_WEEK, pre_count as u64),
56 ) {
57 Ok(rows) => rows.collect(),
58 Err(e) => {
59 error!("Failed to clear database: {}", e);
60 return Err(());
61 }
62 };
63
64 if task_ids.len() < pre_count {
65 remain = false;
66 }
67
68 for task_id in task_ids {
69 debug!(
70 "clear {} info for have been overdue for more than a week.",
71 task_id
72 );
73 if let Err(e) = REQUEST_DB.execute("DELETE from request_task WHERE task_id = ?", task_id) {
74 error!("Failed to clear task {} info: {}", task_id, e);
75 }
76 NotificationDispatcher::get_instance().clear_task_info(task_id);
77 }
78 Ok(remain)
79 }
80
81 #[cfg(test)]
82 mod ut_database {
83 include!("../tests/ut/ut_database.rs");
84 }
85