• 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::sync::LazyLock;
15 use std::time::{SystemTime, UNIX_EPOCH};
16 
17 use rdb::config::SecurityLevel;
18 use rdb::{OpenConfig, RdbStore};
19 
20 use crate::service::notification_bar::NotificationDispatcher;
21 
22 const DB_PATH: &str = if cfg!(test) {
23     "/data/test/notification.db"
24 } else {
25     "/data/service/el1/public/database/request/request.db"
26 };
27 
28 const MILLIS_IN_A_WEEK: u64 = 7 * 24 * 60 * 60 * 1000;
29 
30 pub(crate) static REQUEST_DB: LazyLock<RdbStore<'static>> = LazyLock::new(|| {
31     let mut config = OpenConfig::new(DB_PATH);
32     config.security_level(SecurityLevel::S1);
33     if cfg!(test) {
34         config.encrypt_status(false);
35         config.bundle_name("Test");
36     } else {
37         config.encrypt_status(true);
38     }
39     RdbStore::open(config).unwrap()
40 });
41 
clear_database()42 pub(crate) fn clear_database() {
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;
49         }
50     }
51     .as_millis() as u64;
52 
53     let task_ids = match REQUEST_DB.query::<u32>(
54         "SELECT task_id from request_task WHERE mtime < ?",
55         current_time - MILLIS_IN_A_WEEK,
56     ) {
57         Ok(rows) => rows,
58         Err(e) => {
59             error!("Failed to clear database: {}", e);
60             return;
61         }
62     };
63 
64     for task_id in task_ids {
65         info!(
66             "clear {} info for have been overdue for more than a week.",
67             task_id
68         );
69         if let Err(e) = REQUEST_DB.execute("DELETE from request_task WHERE task_id = ?", task_id) {
70             error!("Failed to clear task {} info: {}", task_id, e);
71         }
72         NotificationDispatcher::get_instance().clear_task_info(task_id);
73     }
74     NotificationDispatcher::get_instance().clear_group_info();
75 }
76 
77 #[test]
clear_database_test()78 fn clear_database_test() {
79     use request_utils::fastrand::fast_random;
80 
81     let current_time = SystemTime::now()
82         .duration_since(UNIX_EPOCH)
83         .unwrap()
84         .as_millis() as u64;
85     let a_week_ago = current_time - MILLIS_IN_A_WEEK;
86 
87     REQUEST_DB
88         .execute(
89             "CREATE TABLE IF NOT EXISTS request_task (task_id INTEGER PRIMARY KEY, mtime INTEGER)",
90             (),
91         )
92         .unwrap();
93     let mut task_ids = [
94         fast_random() as u32,
95         fast_random() as u32,
96         fast_random() as u32,
97     ];
98 
99     task_ids.sort();
100     let sql = "INSERT INTO request_task (task_id, mtime) VALUES (?, ?)";
101     for task_id in task_ids.iter().take(2) {
102         REQUEST_DB.execute(sql, (*task_id, a_week_ago)).unwrap();
103     }
104     REQUEST_DB
105         .execute(sql, (task_ids[2], a_week_ago + 20000))
106         .unwrap();
107     let query: Vec<_> = REQUEST_DB
108         .query::<u32>("SELECT task_id from request_task", ())
109         .unwrap()
110         .collect();
111     for task_id in task_ids.iter() {
112         assert!(query.contains(task_id));
113     }
114 
115     clear_database();
116     let query: Vec<_> = REQUEST_DB
117         .query::<u32>("SELECT task_id from request_task", ())
118         .unwrap()
119         .collect();
120     for task_id in task_ids.iter().take(2) {
121         assert!(!query.contains(task_id));
122     }
123     assert!(query.contains(&task_ids[2]));
124 }
125