diem_secure_storage/
on_disk.rs1use crate::{CryptoKVStorage, Error, GetResponse, KVStorage};
9use diem_temppath::TempPath;
10use diem_time_service::{TimeService, TimeServiceTrait};
11use serde::{de::DeserializeOwned, Serialize};
12use serde_json::Value;
13use std::{
14 collections::HashMap,
15 fs::{self, File},
16 io::{Read, Write},
17 path::PathBuf,
18};
19
20pub struct OnDiskStorage {
29 file_path: PathBuf,
30 temp_path: TempPath,
31 time_service: TimeService,
32}
33
34impl OnDiskStorage {
35 pub fn new(file_path: PathBuf) -> Self {
36 Self::new_with_time_service(file_path, TimeService::real())
37 }
38
39 fn new_with_time_service(
40 file_path: PathBuf, time_service: TimeService,
41 ) -> Self {
42 if !file_path.exists() {
43 File::create(&file_path).expect("Unable to create storage");
44 }
45
46 let file_dir = file_path
49 .parent()
50 .map_or(PathBuf::new(), |p| p.to_path_buf());
51
52 Self {
53 file_path,
54 temp_path: TempPath::new_with_temp_dir(file_dir),
55 time_service,
56 }
57 }
58
59 fn read(&self) -> Result<HashMap<String, Value>, Error> {
60 let mut file = File::open(&self.file_path)?;
61 let mut contents = String::new();
62 file.read_to_string(&mut contents)?;
63 if contents.is_empty() {
64 return Ok(HashMap::new());
65 }
66 let data = serde_json::from_str(&contents)?;
67 Ok(data)
68 }
69
70 fn write(&self, data: &HashMap<String, Value>) -> Result<(), Error> {
71 let contents = serde_json::to_vec(data)?;
72 let mut file = File::create(self.temp_path.path())?;
73 file.write_all(&contents)?;
74 fs::rename(&self.temp_path, &self.file_path)?;
75 Ok(())
76 }
77
78 pub fn file_path(&self) -> &PathBuf { &self.file_path }
79}
80
81impl KVStorage for OnDiskStorage {
82 fn available(&self) -> Result<(), Error> { Ok(()) }
83
84 fn get<V: DeserializeOwned>(
85 &self, key: &str,
86 ) -> Result<GetResponse<V>, Error> {
87 let mut data = self.read()?;
88 data.remove(key)
89 .ok_or_else(|| Error::KeyNotSet(key.to_string()))
90 .and_then(|value| {
91 serde_json::from_value(value).map_err(|e| e.into())
92 })
93 }
94
95 fn set<V: Serialize>(&mut self, key: &str, value: V) -> Result<(), Error> {
96 let now = self.time_service.now_secs();
97 let mut data = self.read()?;
98 data.insert(
99 key.to_string(),
100 serde_json::to_value(&GetResponse::new(value, now))?,
101 );
102 self.write(&data)
103 }
104
105 #[cfg(any(test, feature = "testing"))]
106 fn reset_and_clear(&mut self) -> Result<(), Error> {
107 self.write(&HashMap::new())
108 }
109}
110
111impl CryptoKVStorage for OnDiskStorage {}