103 lines
3.3 KiB
Rust
Raw Normal View History

Kademlia Records (#1144) * initial implementation of the records * move to multihash keys * correctly process query results * comments and formatting * correctly return closer_peers in query * checking wrong peer id in test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix changes from suggestions * Send responses to PUT_VALUE requests * Shortcut in get_value * Update protocols/kad/src/behaviour.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Revert "Update protocols/kad/src/behaviour.rs" This reverts commit 579ce742a7f4c94587f1e1f0866d2a3a37418efb. * Remove duplicate insertion * Adds a record to a PUT_VALUE response * Fix a racy put_value test * Store value ourselves only if we are in K closest * Abstract over storage * Revert "Abstract over storage": bad take This reverts commit eaebf5b6d915712eaf3b05929577fdf697f204d8. * Abstract over records storage using hashmap as default * Constructor for custom records * New Record type and its traits * Fix outdated storage name * Fixes returning an event * Change FindNodeReq key type to Multihash * WriteState for a second stage of a PUT_VALUE request * GET_VALUE should not have a record * Refactor a match arm * Add successes and failures counters to PutValueRes * If value is found no need to return closer peers * Remove a custo storage from tests * Rename a test to get_value_not_found * Adds a TODO to change FindNode request key to Multihash Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Move MemoryRecordStorage to record.rs * Return a Cow-ed Record from get * Fix incorrect GET_VALUE parsing * Various fixes with review * Fixes get_value_not_found * Fix peerids names in test * another fix * PutValue correctly distributes values * Simplify the test * Check that results are actually the closest * Reverts changes to tests * Fix the test topology and checking the results * Run put_value test ten times * Adds a get_value test * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Make Record fields public * Moves WriteState to write.rs * A couple of minor fixes * Another few fixes of review * Simplify the put_value test * Dont synchronously return an error from put_value * Formatting fixes and comments * Collect a bunch of results * Take exactly as much elements as neede * Check if the peer is still connected * Adds a multiple GetValueResults results number test * Unnecessary mut iterators in put_value * Ask for num_results in get_value * Dont allocate twice in get_value * Dont count same errored peer multiple times * Apply suggestions from code review Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Fix another review * Apply suggestions from code review Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Bring back FromIterator and improve a panic message * Update protocols/kad/src/behaviour.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com>
2019-06-04 14:44:24 +03:00
// Copyright 2019 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//! Abstracts the Kademlia record store behaviour and provides default in-memory store
use fnv::FnvHashMap;
use multihash::Multihash;
use std::borrow::Cow;
/// The error record store may return
#[derive(Clone, Debug, PartialEq)]
pub enum RecordStorageError {
/// Store reached the capacity limit.
AtCapacity,
/// Value being put is larger than the limit.
ValueTooLarge,
}
/// The records that are kept in the dht.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Record {
/// Key of the record.
pub key: Multihash,
/// Value of the record.
pub value: Vec<u8>,
}
/// Trait for a record store.
pub trait RecordStore {
fn get(&self, k: &Multihash) -> Option<Cow<Record>>;
fn put(&mut self, r: Record) -> Result<(), RecordStorageError>;
}
/// In-memory implementation of the record store.
pub struct MemoryRecordStorage {
/// Maximum number of records we will store.
max_records: usize,
/// Maximum size of the record we will store.
max_record_size: usize,
/// The records.
records: FnvHashMap<Multihash, Record>
}
impl MemoryRecordStorage {
const MAX_RECORDS: usize = 1024;
const MAX_RECORD_SIZE: usize = 65535;
/// Creates a new `MemoryRecordStorage`.
pub fn new(max_records: usize, max_record_size: usize) -> Self {
MemoryRecordStorage{
max_records,
max_record_size,
records: FnvHashMap::default()
}
}
}
impl Default for MemoryRecordStorage {
fn default() -> Self {
MemoryRecordStorage::new(Self::MAX_RECORDS, Self::MAX_RECORD_SIZE)
}
}
impl RecordStore for MemoryRecordStorage {
fn get(&self, k: &Multihash) -> Option<Cow<Record>> {
match self.records.get(k) {
Some(rec) => Some(Cow::Borrowed(rec)),
None => None,
}
}
fn put(&mut self, r: Record) -> Result<(), RecordStorageError> {
if self.records.len() >= self.max_records {
return Err(RecordStorageError::AtCapacity);
}
if r.value.len() >= self.max_record_size {
return Err(RecordStorageError::ValueTooLarge)
}
self.records.insert(r.key.clone(), r);
Ok(())
}
}