cfxstore/accounts_dir/
memory.rs

1// Copyright 2015-2019 Parity Technologies (UK) Ltd.
2// This file is part of Parity Ethereum.
3
4// Parity Ethereum is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Ethereum is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Ethereum.  If not, see <http://www.gnu.org/licenses/>.
16
17use cfxkey::Address;
18use parking_lot::RwLock;
19use std::collections::HashMap;
20
21use super::KeyDirectory;
22use crate::{Error, SafeAccount};
23
24/// Accounts in-memory storage.
25#[derive(Default)]
26pub struct MemoryDirectory {
27    accounts: RwLock<HashMap<Address, Vec<SafeAccount>>>,
28}
29
30impl KeyDirectory for MemoryDirectory {
31    fn load(&self) -> Result<Vec<SafeAccount>, Error> {
32        Ok(self.accounts.read().values().flatten().cloned().collect())
33    }
34
35    fn update(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
36        let mut lock = self.accounts.write();
37        let accounts = lock.entry(account.address).or_default();
38        // If the filename is the same we just need to replace the entry
39        accounts.retain(|acc| acc.filename != account.filename);
40        accounts.push(account.clone());
41        Ok(account)
42    }
43
44    fn insert(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
45        let mut lock = self.accounts.write();
46        let accounts = lock.entry(account.address).or_default();
47        accounts.push(account.clone());
48        Ok(account)
49    }
50
51    fn remove(&self, account: &SafeAccount) -> Result<(), Error> {
52        let mut accounts = self.accounts.write();
53        let is_empty =
54            if let Some(accounts) = accounts.get_mut(&account.address) {
55                if let Some(position) =
56                    accounts.iter().position(|acc| acc == account)
57                {
58                    accounts.remove(position);
59                }
60                accounts.is_empty()
61            } else {
62                false
63            };
64        if is_empty {
65            accounts.remove(&account.address);
66        }
67        Ok(())
68    }
69
70    fn unique_repr(&self) -> Result<u64, Error> {
71        let mut val = 0u64;
72        let accounts = self.accounts.read();
73        for acc in accounts.keys() {
74            val ^= acc.to_low_u64_be()
75        }
76        Ok(val)
77    }
78}