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().cloned().flatten().collect())
33    }
34
35    fn update(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
36        let mut lock = self.accounts.write();
37        let accounts =
38            lock.entry(account.address.clone()).or_insert_with(Vec::new);
39        // If the filename is the same we just need to replace the entry
40        accounts.retain(|acc| acc.filename != account.filename);
41        accounts.push(account.clone());
42        Ok(account)
43    }
44
45    fn insert(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
46        let mut lock = self.accounts.write();
47        let accounts =
48            lock.entry(account.address.clone()).or_insert_with(Vec::new);
49        accounts.push(account.clone());
50        Ok(account)
51    }
52
53    fn remove(&self, account: &SafeAccount) -> Result<(), Error> {
54        let mut accounts = self.accounts.write();
55        let is_empty =
56            if let Some(accounts) = accounts.get_mut(&account.address) {
57                if let Some(position) =
58                    accounts.iter().position(|acc| acc == account)
59                {
60                    accounts.remove(position);
61                }
62                accounts.is_empty()
63            } else {
64                false
65            };
66        if is_empty {
67            accounts.remove(&account.address);
68        }
69        Ok(())
70    }
71
72    fn unique_repr(&self) -> Result<u64, Error> {
73        let mut val = 0u64;
74        let accounts = self.accounts.read();
75        for acc in accounts.keys() {
76            val ^= acc.to_low_u64_be()
77        }
78        Ok(val)
79    }
80}