libp2p_kad/kbucket/
entry.rs

1// Copyright 2019 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21//! The `Entry` API for quering and modifying the entries of a `KBucketsTable`
22//! representing the nodes participating in the Kademlia DHT.
23
24pub use super::bucket::{AppliedPending, InsertResult, Node, NodeStatus, K_VALUE};
25pub use super::key::*;
26
27use super::*;
28
29/// An immutable by-reference view of a bucket entry.
30pub struct EntryRefView<'a, TPeerId, TVal> {
31    /// The node represented by the entry.
32    pub node: NodeRefView<'a, TPeerId, TVal>,
33    /// The status of the node identified by the key.
34    pub status: NodeStatus,
35}
36
37/// An immutable by-reference view of a `Node`.
38pub struct NodeRefView<'a, TKey, TVal> {
39    pub key: &'a TKey,
40    pub value: &'a TVal,
41}
42
43// impl<TKey, TVal> EntryRefView<'_, TKey, TVal> {
44//     pub fn to_owned(&self) -> EntryView<TKey, TVal>
45//     where
46//         TKey: Clone,
47//         TVal: Clone,
48//     {
49//         EntryView {
50//             node: Node {
51//                 key: self.node.key.clone(),
52//                 value: self.node.value.clone(),
53//             },
54//             status: self.status,
55//         }
56//     }
57// }
58
59/// A cloned, immutable view of an entry that is either present in a bucket
60/// or pending insertion.
61#[derive(Clone, Debug)]
62pub struct EntryView<TKey, TVal> {
63    /// The node represented by the entry.
64    pub node: Node<TKey, TVal>,
65    /// The status of the node.
66    pub status: NodeStatus,
67}
68
69impl<TKey: AsRef<KeyBytes>, TVal> AsRef<KeyBytes> for EntryView<TKey, TVal> {
70    fn as_ref(&self) -> &KeyBytes {
71        self.node.key.as_ref()
72    }
73}
74
75/// A reference into a single entry of a `KBucketsTable`.
76#[derive(Debug)]
77pub enum Entry<'a, TPeerId, TVal> {
78    /// The entry is present in a bucket.
79    Present(PresentEntry<'a, TPeerId, TVal>, NodeStatus),
80    /// The entry is pending insertion in a bucket.
81    Pending(PendingEntry<'a, TPeerId, TVal>, NodeStatus),
82    /// The entry is absent and may be inserted.
83    Absent(AbsentEntry<'a, TPeerId, TVal>),
84    /// The entry represents the local node.
85    SelfEntry,
86}
87
88/// The internal representation of the different states of an `Entry`,
89/// referencing the associated key and bucket.
90#[derive(Debug)]
91struct EntryRef<'a, TKey, TVal> {
92    bucket: &'a mut KBucket<TKey, TVal>,
93    key: &'a TKey,
94}
95
96impl<'a, TKey, TVal> Entry<'a, TKey, TVal>
97where
98    TKey: Clone + AsRef<KeyBytes>,
99    TVal: Clone,
100{
101    /// Creates a new `Entry` for a `Key`, encapsulating access to a bucket.
102    pub(super) fn new(bucket: &'a mut KBucket<TKey, TVal>, key: &'a TKey) -> Self {
103        if let Some(status) = bucket.status(key) {
104            Entry::Present(PresentEntry::new(bucket, key), status)
105        } else if let Some(pending) = bucket.pending_ref(key) {
106            let status = pending.status();
107            Entry::Pending(PendingEntry::new(bucket, key), status)
108        } else {
109            Entry::Absent(AbsentEntry::new(bucket, key))
110        }
111    }
112
113    /// Creates an immutable by-reference view of the entry.
114    ///
115    /// Returns `None` if the entry is neither present in a bucket nor
116    /// pending insertion into a bucket.
117    pub fn view(&'a mut self) -> Option<EntryRefView<'a, TKey, TVal>> {
118        match self {
119            Entry::Present(entry, status) => Some(EntryRefView {
120                node: NodeRefView {
121                    key: entry.0.key,
122                    value: entry.value(),
123                },
124                status: *status,
125            }),
126            Entry::Pending(entry, status) => Some(EntryRefView {
127                node: NodeRefView {
128                    key: entry.0.key,
129                    value: entry.value(),
130                },
131                status: *status,
132            }),
133            _ => None,
134        }
135    }
136
137    /// Returns the key of the entry.
138    ///
139    /// Returns `None` if the `Key` used to construct this `Entry` is not a valid
140    /// key for an entry in a bucket, which is the case for the `local_key` of
141    /// the `KBucketsTable` referring to the local node.
142    pub fn key(&self) -> Option<&TKey> {
143        match self {
144            Entry::Present(entry, _) => Some(entry.key()),
145            Entry::Pending(entry, _) => Some(entry.key()),
146            Entry::Absent(entry) => Some(entry.key()),
147            Entry::SelfEntry => None,
148        }
149    }
150
151    /// Returns the value associated with the entry.
152    ///
153    /// Returns `None` if the entry is absent from any bucket or refers to the
154    /// local node.
155    pub fn value(&mut self) -> Option<&mut TVal> {
156        match self {
157            Entry::Present(entry, _) => Some(entry.value()),
158            Entry::Pending(entry, _) => Some(entry.value()),
159            Entry::Absent(_) => None,
160            Entry::SelfEntry => None,
161        }
162    }
163}
164
165/// An entry present in a bucket.
166#[derive(Debug)]
167pub struct PresentEntry<'a, TKey, TVal>(EntryRef<'a, TKey, TVal>);
168
169impl<'a, TKey, TVal> PresentEntry<'a, TKey, TVal>
170where
171    TKey: Clone + AsRef<KeyBytes>,
172    TVal: Clone,
173{
174    fn new(bucket: &'a mut KBucket<TKey, TVal>, key: &'a TKey) -> Self {
175        PresentEntry(EntryRef { bucket, key })
176    }
177
178    /// Returns the key of the entry.
179    pub fn key(&self) -> &TKey {
180        self.0.key
181    }
182
183    /// Returns the value associated with the key.
184    pub fn value(&mut self) -> &mut TVal {
185        &mut self
186            .0
187            .bucket
188            .get_mut(self.0.key)
189            .expect("We can only build a PresentEntry if the entry is in the bucket; QED")
190            .value
191    }
192
193    /// Sets the status of the entry.
194    pub fn update(self, status: NodeStatus) -> Self {
195        self.0.bucket.update(self.0.key, status);
196        Self::new(self.0.bucket, self.0.key)
197    }
198
199    /// Removes the entry from the bucket.
200    pub fn remove(self) -> EntryView<TKey, TVal> {
201        let (node, status, _pos) = self.0.bucket
202            .remove(&self.0.key)
203            .expect("We can only build a PresentEntry if the entry is in the bucket; QED");
204        EntryView { node, status }
205    }
206}
207
208/// An entry waiting for a slot to be available in a bucket.
209#[derive(Debug)]
210pub struct PendingEntry<'a, TKey, TVal>(EntryRef<'a, TKey, TVal>);
211
212impl<'a, TKey, TVal> PendingEntry<'a, TKey, TVal>
213where
214    TKey: Clone + AsRef<KeyBytes>,
215    TVal: Clone,
216{
217    fn new(bucket: &'a mut KBucket<TKey, TVal>, key: &'a TKey) -> Self {
218        PendingEntry(EntryRef { bucket, key })
219    }
220
221    /// Returns the key of the entry.
222    pub fn key(&self) -> &TKey {
223        self.0.key
224    }
225
226    /// Returns the value associated with the key.
227    pub fn value(&mut self) -> &mut TVal {
228        self.0
229            .bucket
230            .pending_mut(self.0.key)
231            .expect("We can only build a PendingEntry if the entry is pending; QED")
232            .value_mut()
233    }
234
235    /// Updates the status of the pending entry.
236    pub fn update(self, status: NodeStatus) -> PendingEntry<'a, TKey, TVal> {
237        self.0.bucket.update_pending(self.0.key, status);
238        PendingEntry::new(self.0.bucket, self.0.key)
239    }
240
241    /// Removes the pending entry from the bucket.
242    pub fn remove(self) -> EntryView<TKey, TVal> {
243        let pending = self.0.bucket
244            .remove_pending(self.0.key)
245            .expect("We can only build a PendingEntry if the entry is pending insertion
246                    into the bucket; QED");
247        let status = pending.status();
248        let node = pending.into_node();
249        EntryView { node, status }
250    }
251}
252
253/// An entry that is not present in any bucket.
254#[derive(Debug)]
255pub struct AbsentEntry<'a, TKey, TVal>(EntryRef<'a, TKey, TVal>);
256
257impl<'a, TKey, TVal> AbsentEntry<'a, TKey, TVal>
258where
259    TKey: Clone + AsRef<KeyBytes>,
260    TVal: Clone,
261{
262    fn new(bucket: &'a mut KBucket<TKey, TVal>, key: &'a TKey) -> Self {
263        AbsentEntry(EntryRef { bucket, key })
264    }
265
266    /// Returns the key of the entry.
267    pub fn key(&self) -> &TKey {
268        self.0.key
269    }
270
271    /// Attempts to insert the entry into a bucket.
272    pub fn insert(self, value: TVal, status: NodeStatus, weight: u32) -> InsertResult<TKey> {
273        self.0.bucket.insert(
274            Node {
275                key: self.0.key.clone(),
276                value,
277                weight,
278            },
279            status,
280        )
281    }
282}