cyfs_util/storage/
sqlite_storage.rs

1use 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    //conn: Option<Connection>,
15}
16
17impl SqliteStorage {
18    pub fn new() -> SqliteStorage {
19        SqliteStorage {
20            inited: false,
21            path: PathBuf::from(""),
22            dirty: false,
23            //conn: None,
24        }
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        // let conn = Connection::open(self.path.as_path()).map_err(|e| {
53        //     warn!("open db failed, db={}, e={}", self.path.display(), e);
54        //     e
55        // })?;
56        //self.conn = Some(conn);
57
58        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 = self.conn.as_ref().unwrap();
83        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}