cyfs_util/storage/
sqlite_storage.rs1use async_trait::async_trait;
2use cyfs_base::BuckyError;
3use crate::get_cyfs_root_path;
4use rusqlite::Connection;
5use std::error::Error;
6use std::path::PathBuf;
7
8const TABLE_NAME: &str = "profile";
9
10pub struct SqliteStorage {
11 inited: bool,
12 path: PathBuf,
13 dirty: bool,
14 }
16
17impl SqliteStorage {
18 pub fn new() -> SqliteStorage {
19 SqliteStorage {
20 inited: false,
21 path: PathBuf::from(""),
22 dirty: false,
23 }
25 }
26
27 pub async fn init(&mut self, service_name: &str) -> Result<(), Box<dyn Error>> {
28 assert!(!self.inited);
29 self.inited = true;
30
31 let dir = get_cyfs_root_path().join("profile").join(service_name);
32 if !dir.is_dir() {
33 if let Err(e) = std::fs::create_dir_all(&dir) {
34 let msg = format!("create profile dir error! dir={}, err={}", dir.display(), e);
35 error!("{}", msg);
36
37 return Err(Box::<dyn Error>::from(msg));
38 }
39 }
40
41 let file = dir.join("profile.db");
42 self.path = file;
43 debug!(
44 "sqlite storage service: {}, file path: {}",
45 service_name,
46 self.path.display()
47 );
48 if !self.path.exists() {
49 info!("sqlite storage file not exists! db={}", self.path.display());
50 self.create_db()?;
51 }
52 Ok(())
59 }
60
61 fn create_db(&mut self) -> Result<(), Box<dyn Error>> {
62 let conn = Connection::open(self.path.as_path()).map_err(|e| {
63 warn!("open db failed, db={}, e={}", self.path.display(), e);
64 e
65 })?;
66 let sql = format!(
67 "CREATE TABLE IF NOT EXISTS {} (
68 key TEXT PRIMARY KEY NOT NULL UNIQUE,
69 value BLOB NOT NULL
70 );",
71 TABLE_NAME
72 );
73 conn.execute(&sql, []).map_err(|e| e)?;
74 Ok(())
75 }
76}
77
78#[async_trait]
79impl super::AsyncStorage for SqliteStorage {
80 async fn set_item(&mut self, key: &str, value: String) -> Result<(), BuckyError> {
81 assert!(self.inited);
82 let conn = Connection::open(self.path.as_path()).map_err(|e| {
84 warn!("open db failed, db={}, e={}", self.path.display(), e);
85 e
86 })?;
87 let sql = format!("REPLACE INTO {} (key, value) VALUES (?1, ?2)", TABLE_NAME);
88 conn.execute(&sql, rusqlite::params![key, value])
89 .map_err(|e| {
90 warn!("[sqlite] set item failed, e={}", e);
91 e
92 })?;
93 Ok(())
94 }
95
96 async fn get_item(&self, key: &str) -> Option<String> {
97 assert!(self.inited);
98 let conn = Connection::open(self.path.as_path())
99 .map_err(|e| {
100 warn!("open db failed, db={}, e={}", self.path.display(), e);
101 e
102 })
103 .ok()?;
104 let sql = format!("SELECT value FROM {} WHERE key=?1", TABLE_NAME);
105 match conn.query_row(&sql, rusqlite::params![key], |row| {
106 let value: String = row.get(0)?;
107 Ok(value)
108 }) {
109 Ok(value) => Some(value),
110 Err(_e) => None,
111 }
112 }
113
114 async fn remove_item(&mut self, key: &str) -> Option<()> {
115 assert!(self.inited);
116 let conn = Connection::open(self.path.as_path())
117 .map_err(|e| {
118 warn!("open db failed, db={}, e={}", self.path.display(), e);
119 e
120 })
121 .ok()?;
122 let sql = format!("DELETE FROM {} WHERE key=?1", TABLE_NAME);
123 let r = conn.execute(&sql, rusqlite::params![key]).map_err(|e| {
124 warn!("[sqlite] remove item failed, key={}, e={}", key, e);
125 });
126 debug!("remove item return: {:?}", r);
127
128 if r.unwrap() > 0 {
129 Some(())
130 } else {
131 None
132 }
133 }
134
135 async fn clear(&mut self) {
136 assert!(self.inited);
137 if let Ok(conn) = Connection::open(self.path.as_path()) {
138 let sql = format!("DELETE FROM {}", TABLE_NAME);
139 let _r = conn.execute(&sql, []).map_err(|e| {
140 warn!("[sqlite] clear failed e={}", e);
141 });
142 }
143 }
144
145 async fn clear_with_prefix(&mut self, prefix: &str) {
146 assert!(self.inited);
147 if let Ok(conn) = Connection::open(self.path.as_path()) {
148 let sql = format!("DELETE FROM {} WHERE key LIKE ?1", TABLE_NAME);
149 let _r = conn
150 .execute(&sql, rusqlite::params![format!("{}%", prefix)])
151 .map_err(|e| {
152 warn!(
153 "[sqlite] clear with prefix failed, prefix={}, e={}",
154 prefix, e
155 );
156 });
157 }
158 }
159}