mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-18 00:11:01 +00:00
Reorganising the repository - external renames and moves (#4074)
* Adding first rough ouline of the repository structure * Remove old CI stuff * add title * formatting fixes * move node-exits job's script to scripts dir * Move docs into subdir * move to bin * move maintainence scripts, configs and helpers into its own dir * add .local to ignore * move core->client * start up 'test' area * move test client * move test runtime * make test move compile * Add dependencies rule enforcement. * Fix indexing. * Update docs to reflect latest changes * Moving /srml->/paint * update docs * move client/sr-* -> primitives/ * clean old readme * remove old broken code in rhd * update lock * Step 1. * starting to untangle client * Fix after merge. * start splitting out client interfaces * move children and blockchain interfaces * Move trie and state-machine to primitives. * Fix WASM builds. * fixing broken imports * more interface moves * move backend and light to interfaces * move CallExecutor * move cli off client * moving around more interfaces * re-add consensus crates into the mix * fix subkey path * relieve client from executor * starting to pull out client from grandpa * move is_decendent_of out of client * grandpa still depends on client directly * lemme tests pass * rename srml->paint * Make it compile. * rename interfaces->client-api * Move keyring to primitives. * fixup libp2p dep * fix broken use * allow dependency enforcement to fail * move fork-tree * Moving wasm-builder * make env * move build-script-utils * fixup broken crate depdencies and names * fix imports for authority discovery * fix typo * update cargo.lock * fixing imports * Fix paths and add missing crates * re-add missing crates
This commit is contained in:
committed by
Bastian Köcher
parent
becc3b0a4f
commit
60e5011c72
@@ -0,0 +1,148 @@
|
||||
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! RocksDB-based offchain workers local storage.
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::columns;
|
||||
use kvdb::KeyValueDB;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
/// Offchain local storage
|
||||
#[derive(Clone)]
|
||||
pub struct LocalStorage {
|
||||
db: Arc<dyn KeyValueDB>,
|
||||
locks: Arc<Mutex<HashMap<Vec<u8>, Arc<Mutex<()>>>>>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for LocalStorage {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fmt.debug_struct("LocalStorage")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalStorage {
|
||||
/// Create new offchain storage for tests (backed by memorydb)
|
||||
#[cfg(any(test, feature = "test-helpers"))]
|
||||
pub fn new_test() -> Self {
|
||||
let db = Arc::new(::kvdb_memorydb::create(crate::utils::NUM_COLUMNS));
|
||||
Self::new(db as _)
|
||||
}
|
||||
|
||||
/// Create offchain local storage with given `KeyValueDB` backend.
|
||||
pub fn new(db: Arc<dyn KeyValueDB>) -> Self {
|
||||
Self {
|
||||
db,
|
||||
locks: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl client_api::OffchainStorage for LocalStorage {
|
||||
fn set(&mut self, prefix: &[u8], key: &[u8], value: &[u8]) {
|
||||
let key: Vec<u8> = prefix.iter().chain(key).cloned().collect();
|
||||
let mut tx = self.db.transaction();
|
||||
tx.put(columns::OFFCHAIN, &key, value);
|
||||
|
||||
if let Err(e) = self.db.write(tx) {
|
||||
log::warn!("Error writing to the offchain DB: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, prefix: &[u8], key: &[u8]) -> Option<Vec<u8>> {
|
||||
let key: Vec<u8> = prefix.iter().chain(key).cloned().collect();
|
||||
self.db.get(columns::OFFCHAIN, &key)
|
||||
.ok()
|
||||
.and_then(|x| x)
|
||||
.map(|v| v.to_vec())
|
||||
}
|
||||
|
||||
fn compare_and_set(
|
||||
&mut self,
|
||||
prefix: &[u8],
|
||||
item_key: &[u8],
|
||||
old_value: Option<&[u8]>,
|
||||
new_value: &[u8],
|
||||
) -> bool {
|
||||
let key: Vec<u8> = prefix.iter().chain(item_key).cloned().collect();
|
||||
let key_lock = {
|
||||
let mut locks = self.locks.lock();
|
||||
locks.entry(key.clone()).or_default().clone()
|
||||
};
|
||||
|
||||
let is_set;
|
||||
{
|
||||
let _key_guard = key_lock.lock();
|
||||
let val = self.db.get(columns::OFFCHAIN, &key)
|
||||
.ok()
|
||||
.and_then(|x| x);
|
||||
is_set = val.as_ref().map(|x| &**x) == old_value;
|
||||
|
||||
if is_set {
|
||||
self.set(prefix, item_key, new_value)
|
||||
}
|
||||
}
|
||||
|
||||
// clean the lock map if we're the only entry
|
||||
let mut locks = self.locks.lock();
|
||||
{
|
||||
drop(key_lock);
|
||||
let key_lock = locks.get_mut(&key);
|
||||
if let Some(_) = key_lock.and_then(Arc::get_mut) {
|
||||
locks.remove(&key);
|
||||
}
|
||||
}
|
||||
is_set
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use client_api::OffchainStorage;
|
||||
|
||||
#[test]
|
||||
fn should_compare_and_set_and_clear_the_locks_map() {
|
||||
let mut storage = LocalStorage::new_test();
|
||||
let prefix = b"prefix";
|
||||
let key = b"key";
|
||||
let value = b"value";
|
||||
|
||||
storage.set(prefix, key, value);
|
||||
assert_eq!(storage.get(prefix, key), Some(value.to_vec()));
|
||||
|
||||
assert_eq!(storage.compare_and_set(prefix, key, Some(value), b"asd"), true);
|
||||
assert_eq!(storage.get(prefix, key), Some(b"asd".to_vec()));
|
||||
assert!(storage.locks.lock().is_empty(), "Locks map should be empty!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_compare_and_set_on_empty_field() {
|
||||
let mut storage = LocalStorage::new_test();
|
||||
let prefix = b"prefix";
|
||||
let key = b"key";
|
||||
|
||||
assert_eq!(storage.compare_and_set(prefix, key, None, b"asd"), true);
|
||||
assert_eq!(storage.get(prefix, key), Some(b"asd".to_vec()));
|
||||
assert!(storage.locks.lock().is_empty(), "Locks map should be empty!");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user