├── .github ├── actions-rs │ └── grcov.yml └── workflows │ └── ci.yml ├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── examples └── chat.rs └── src ├── codec ├── hyparview.rs ├── mod.rs ├── net.rs ├── node.rs └── plumtree.rs ├── error.rs ├── lib.rs ├── message.rs ├── metrics.rs ├── misc.rs ├── node.rs ├── node_id.rs ├── node_id_generator.rs ├── rpc ├── hyparview.rs ├── mod.rs └── plumtree.rs └── service.rs /.github/actions-rs/grcov.yml: -------------------------------------------------------------------------------- 1 | ignore-not-existing: true 2 | ignore: 3 | - "../*" 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # Based on https://github.com/actions-rs/meta/blob/master/recipes/quickstart.md 2 | 3 | name: CI 4 | 5 | on: [push, pull_request] 6 | 7 | jobs: 8 | check: 9 | name: Check 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | toolchain: [stable, beta, nightly] 14 | steps: 15 | - name: Checkout sources 16 | uses: actions/checkout@v2 17 | 18 | - name: Install ${{ matrix.toolchain }} toolchain 19 | uses: actions-rs/toolchain@v1 20 | with: 21 | profile: minimal 22 | toolchain: ${{ matrix.toolchain }} 23 | override: true 24 | 25 | - name: Run cargo check 26 | uses: actions-rs/cargo@v1 27 | with: 28 | command: check 29 | args: --all 30 | 31 | test: 32 | name: Test Suite 33 | runs-on: ubuntu-latest 34 | strategy: 35 | matrix: 36 | toolchain: [stable, beta, nightly] 37 | steps: 38 | - name: Checkout sources 39 | uses: actions/checkout@v2 40 | 41 | - name: Install ${{ matrix.toolchain }} toolchain 42 | uses: actions-rs/toolchain@v1 43 | with: 44 | profile: minimal 45 | toolchain: ${{ matrix.toolchain }} 46 | override: true 47 | 48 | - name: Run cargo test 49 | uses: actions-rs/cargo@v1 50 | with: 51 | command: test 52 | args: --all 53 | 54 | lints: 55 | name: Lints 56 | runs-on: ubuntu-latest 57 | strategy: 58 | matrix: 59 | toolchain: [stable, beta, nightly] 60 | steps: 61 | - name: Checkout sources 62 | uses: actions/checkout@v2 63 | 64 | - name: Install ${{ matrix.toolchain }} toolchain 65 | uses: actions-rs/toolchain@v1 66 | with: 67 | profile: minimal 68 | toolchain: ${{ matrix.toolchain }} 69 | override: true 70 | components: rustfmt, clippy 71 | 72 | - name: Run cargo fmt 73 | uses: actions-rs/cargo@v1 74 | with: 75 | command: fmt 76 | args: --all -- --check 77 | 78 | - name: Run cargo clippy 79 | uses: actions-rs/cargo@v1 80 | with: 81 | command: clippy 82 | args: --all -- -D warnings 83 | 84 | grcov: 85 | name: Coverage 86 | runs-on: ubuntu-latest 87 | steps: 88 | - uses: actions/checkout@v2 89 | 90 | - name: Install toolchain 91 | uses: actions-rs/toolchain@v1 92 | with: 93 | toolchain: nightly 94 | override: true 95 | 96 | - name: Execute tests 97 | uses: actions-rs/cargo@v1 98 | with: 99 | command: test 100 | args: --all 101 | env: 102 | CARGO_INCREMENTAL: 0 103 | RUSTFLAGS: "-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort" 104 | RUSTDOCFLAGS: "-Cpanic=abort" 105 | 106 | - name: Gather coverage data 107 | id: coverage 108 | uses: actions-rs/grcov@v0.1 109 | 110 | - name: Coveralls upload 111 | uses: coverallsapp/github-action@master 112 | with: 113 | github-token: ${{ secrets.GITHUB_TOKEN }} 114 | parallel: true 115 | path-to-lcov: ${{ steps.coverage.outputs.report }} 116 | 117 | grcov_finalize: 118 | runs-on: ubuntu-latest 119 | needs: grcov 120 | steps: 121 | - name: Coveralls finalization 122 | uses: coverallsapp/github-action@master 123 | with: 124 | github-token: ${{ secrets.GITHUB_TOKEN }} 125 | parallel-finished: true 126 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "plumcast" 3 | version = "0.1.5" 4 | authors = ["Takeru Ohta "] 5 | description = "A message broadcasting library based on the Plumtree/HyParView algorithms" 6 | homepage = "https://github.com/sile/plumcast" 7 | repository = "https://github.com/sile/plumcast" 8 | readme = "README.md" 9 | license = "MIT" 10 | edition = "2018" 11 | 12 | [badges] 13 | coveralls = {repository = "sile/plumcast"} 14 | 15 | [features] 16 | serialize = ["serde", "serde_derive"] 17 | 18 | [dependencies] 19 | atomic_immut = "0.1" 20 | bytecodec = "0.4" 21 | fibers = "0.1" 22 | fibers_rpc = "0.3" 23 | futures = "0.1" 24 | hyparview = "0.1" 25 | slog = "2" 26 | plumtree = "0.1" 27 | prometrics = "0.1" 28 | rand = "0.6" 29 | serde = { version = "1", optional = true } 30 | serde_derive = { version = "1", optional = true } 31 | trackable = "0.2" 32 | 33 | [dev-dependencies] 34 | clap = "2" 35 | fibers_global = "0.1" 36 | sloggers = "0.3" 37 | 38 | [package.metadata.docs.rs] 39 | all-features = true 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2018 Takeru Ohta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | plumcast 2 | ======== 3 | 4 | [![plumcast](https://img.shields.io/crates/v/plumcast.svg)](https://crates.io/crates/plumcast) 5 | [![Documentation](https://docs.rs/plumcast/badge.svg)](https://docs.rs/plumcast) 6 | [![Actions Status](https://github.com/sile/plumcast/workflows/CI/badge.svg)](https://github.com/sile/plumcast/actions) 7 | [![Coverage Status](https://coveralls.io/repos/github/sile/plumcast/badge.svg?branch=master)](https://coveralls.io/github/sile/plumcast?branch=master) 8 | [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 9 | 10 | A message broadcasting library based on the Plumtree/HyParView algorithms. 11 | 12 | [Documentation](https://docs.rs/plumcast) 13 | 14 | 15 | Properties 16 | ---------- 17 | 18 | ### Pros 19 | 20 | - Nearly optimal message transmitting count 21 | - Usually messages are broadcasted via a spanning tree 22 | - Only the nodes interested in the same messages belong to the same cluster 23 | - Scalable 24 | - Theoretically, it can handle ten-thousand of nodes or more 25 | - High fault tolerance 26 | - Spanning trees are automatically repaired if there are crashed nodes 27 | - Dynamic membership 28 | - Nodes can be added to (removed from) a cluster at any time 29 | 30 | 31 | ### Cons 32 | 33 | - No strong guarantee about connectivity of the nodes in a cluster 34 | - No strong guarantee about delivery count of a message 35 | - No guarantee about messages delivery order 36 | 37 | If some of the above guarantees are mandatory for your application, 38 | it is need to be provided by upper layers. 39 | 40 | 41 | References 42 | ---------- 43 | 44 | - [HyParView: a membership protocol for reliable gossip-based broadcast][HyParView] 45 | - [Plumtree: Epidemic Broadcast Trees][Plumtree] 46 | 47 | [HyParView]: http://asc.di.fct.unl.pt/~jleitao/pdf/dsn07-leitao.pdf 48 | [Plumtree]: http://www.gsd.inesc-id.pt/~ler/reports/srds07.pdf 49 | -------------------------------------------------------------------------------- /examples/chat.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate clap; 3 | #[macro_use] 4 | extern crate trackable; 5 | 6 | use clap::Arg; 7 | use fibers::sync::mpsc; 8 | use fibers::{Executor, Spawn, ThreadPoolExecutor}; 9 | use futures::{Async, Future, Poll, Stream}; 10 | use plumcast::node::{LocalNodeId, Node, NodeBuilder, NodeId, SerialLocalNodeIdGenerator}; 11 | use plumcast::service::ServiceBuilder; 12 | use sloggers::terminal::{Destination, TerminalLoggerBuilder}; 13 | use sloggers::Build; 14 | use std::net::SocketAddr; 15 | use trackable::error::MainError; 16 | 17 | fn main() -> Result<(), MainError> { 18 | let matches = app_from_crate!() 19 | .arg(Arg::with_name("PORT").index(1).required(true)) 20 | .arg( 21 | Arg::with_name("CONTACT_SERVER") 22 | .long("contact-server") 23 | .takes_value(true), 24 | ) 25 | .arg( 26 | Arg::with_name("LOG_LEVEL") 27 | .long("log-level") 28 | .takes_value(true) 29 | .default_value("info") 30 | .possible_values(&["debug", "info"]), 31 | ) 32 | .get_matches(); 33 | let log_level = track_any_err!(matches.value_of("LOG_LEVEL").unwrap().parse())?; 34 | let logger = track!(TerminalLoggerBuilder::new() 35 | .destination(Destination::Stderr) 36 | .level(log_level) 37 | .build())?; 38 | let port = matches.value_of("PORT").unwrap(); 39 | let addr: SocketAddr = track_any_err!(format!("127.0.0.1:{}", port).parse())?; 40 | 41 | let executor = track_any_err!(ThreadPoolExecutor::new())?; 42 | let service = ServiceBuilder::new(addr) 43 | .logger(logger.clone()) 44 | .finish(executor.handle(), SerialLocalNodeIdGenerator::new()); 45 | 46 | let mut node = NodeBuilder::new().logger(logger).finish(service.handle()); 47 | if let Some(contact) = matches.value_of("CONTACT_SERVER") { 48 | let contact: SocketAddr = track_any_err!(contact.parse())?; 49 | node.join(NodeId::new(contact, LocalNodeId::new(0))); 50 | } 51 | 52 | let (message_tx, message_rx) = mpsc::channel(); 53 | let node = ChatNode { 54 | inner: node, 55 | message_rx, 56 | }; 57 | executor.spawn(service.map_err(|e| panic!("{}", e))); 58 | executor.spawn(node); 59 | 60 | std::thread::spawn(move || { 61 | use std::io::BufRead; 62 | let stdin = std::io::stdin(); 63 | for line in stdin.lock().lines() { 64 | let line = if let Ok(line) = line { 65 | line 66 | } else { 67 | break; 68 | }; 69 | if message_tx.send(line).is_err() { 70 | break; 71 | } 72 | } 73 | }); 74 | 75 | track_any_err!(executor.run())?; 76 | Ok(()) 77 | } 78 | 79 | struct ChatNode { 80 | inner: Node, 81 | message_rx: mpsc::Receiver, 82 | } 83 | impl Future for ChatNode { 84 | type Item = (); 85 | type Error = (); 86 | 87 | fn poll(&mut self) -> Poll { 88 | let mut did_something = true; 89 | while did_something { 90 | did_something = false; 91 | 92 | while let Async::Ready(Some(m)) = track_try_unwrap!(self.inner.poll()) { 93 | println!("# MESSAGE: {:?}", m); 94 | did_something = true; 95 | } 96 | while let Async::Ready(Some(m)) = self.message_rx.poll().expect("Never fails") { 97 | self.inner.broadcast(m); 98 | did_something = true; 99 | } 100 | } 101 | Ok(Async::NotReady) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/codec/hyparview.rs: -------------------------------------------------------------------------------- 1 | use super::node::{LocalNodeIdDecoder, LocalNodeIdEncoder, NodeIdDecoder, NodeIdEncoder}; 2 | use crate::misc::{ 3 | DisconnectMessage, ForwardJoinMessage, JoinMessage, NeighborMessage, ShuffleMessage, 4 | ShuffleReplyMessage, 5 | }; 6 | use crate::node::{LocalNodeId, NodeId}; 7 | use bytecodec::combinator::{Collect, Repeat}; 8 | use bytecodec::fixnum::{U8Decoder, U8Encoder}; 9 | use bytecodec::{ByteCount, Decode, Encode, Eos, Result, SizedEncode}; 10 | use hyparview::TimeToLive; 11 | use std; 12 | 13 | #[derive(Debug, Default)] 14 | pub struct JoinMessageDecoder { 15 | destination: LocalNodeIdDecoder, 16 | sender: NodeIdDecoder, 17 | } 18 | impl Decode for JoinMessageDecoder { 19 | type Item = (LocalNodeId, JoinMessage); 20 | 21 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 22 | let mut offset = 0; 23 | bytecodec_try_decode!(self.destination, offset, buf, eos); 24 | bytecodec_try_decode!(self.sender, offset, buf, eos); 25 | Ok(offset) 26 | } 27 | 28 | fn finish_decoding(&mut self) -> Result { 29 | let destination = track!(self.destination.finish_decoding())?; 30 | let sender = track!(self.sender.finish_decoding())?; 31 | Ok((destination, JoinMessage { sender })) 32 | } 33 | 34 | fn requiring_bytes(&self) -> ByteCount { 35 | self.destination 36 | .requiring_bytes() 37 | .add_for_decoding(self.sender.requiring_bytes()) 38 | } 39 | 40 | fn is_idle(&self) -> bool { 41 | self.sender.is_idle() 42 | } 43 | } 44 | 45 | #[derive(Debug, Default)] 46 | pub struct JoinMessageEncoder { 47 | destination: LocalNodeIdEncoder, 48 | sender: NodeIdEncoder, 49 | } 50 | impl Encode for JoinMessageEncoder { 51 | type Item = (LocalNodeId, JoinMessage); 52 | 53 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 54 | let mut offset = 0; 55 | bytecodec_try_encode!(self.destination, offset, buf, eos); 56 | bytecodec_try_encode!(self.sender, offset, buf, eos); 57 | Ok(offset) 58 | } 59 | 60 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 61 | track!(self.destination.start_encoding(item.0))?; 62 | track!(self.sender.start_encoding(item.1.sender))?; 63 | Ok(()) 64 | } 65 | 66 | fn requiring_bytes(&self) -> ByteCount { 67 | ByteCount::Finite(self.exact_requiring_bytes()) 68 | } 69 | 70 | fn is_idle(&self) -> bool { 71 | self.sender.is_idle() 72 | } 73 | } 74 | impl SizedEncode for JoinMessageEncoder { 75 | fn exact_requiring_bytes(&self) -> u64 { 76 | self.destination.exact_requiring_bytes() + self.sender.exact_requiring_bytes() 77 | } 78 | } 79 | 80 | #[derive(Debug, Default)] 81 | pub struct ForwardJoinMessageDecoder { 82 | destination: LocalNodeIdDecoder, 83 | sender: NodeIdDecoder, 84 | new_node: NodeIdDecoder, 85 | ttl: U8Decoder, 86 | } 87 | impl Decode for ForwardJoinMessageDecoder { 88 | type Item = (LocalNodeId, ForwardJoinMessage); 89 | 90 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 91 | let mut offset = 0; 92 | bytecodec_try_decode!(self.destination, offset, buf, eos); 93 | bytecodec_try_decode!(self.sender, offset, buf, eos); 94 | bytecodec_try_decode!(self.new_node, offset, buf, eos); 95 | bytecodec_try_decode!(self.ttl, offset, buf, eos); 96 | Ok(offset) 97 | } 98 | 99 | fn finish_decoding(&mut self) -> Result { 100 | let destination = track!(self.destination.finish_decoding())?; 101 | let sender = track!(self.sender.finish_decoding())?; 102 | let new_node = track!(self.new_node.finish_decoding())?; 103 | let ttl = track!(self.ttl.finish_decoding())?; 104 | let message = ForwardJoinMessage { 105 | sender, 106 | new_node, 107 | ttl: TimeToLive::new(ttl), 108 | }; 109 | Ok((destination, message)) 110 | } 111 | 112 | fn requiring_bytes(&self) -> ByteCount { 113 | self.destination 114 | .requiring_bytes() 115 | .add_for_decoding(self.sender.requiring_bytes()) 116 | .add_for_decoding(self.new_node.requiring_bytes()) 117 | .add_for_decoding(self.ttl.requiring_bytes()) 118 | } 119 | 120 | fn is_idle(&self) -> bool { 121 | self.ttl.is_idle() 122 | } 123 | } 124 | 125 | #[derive(Debug, Default)] 126 | pub struct ForwardJoinMessageEncoder { 127 | destination: LocalNodeIdEncoder, 128 | sender: NodeIdEncoder, 129 | new_node: NodeIdEncoder, 130 | ttl: U8Encoder, 131 | } 132 | impl Encode for ForwardJoinMessageEncoder { 133 | type Item = (LocalNodeId, ForwardJoinMessage); 134 | 135 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 136 | let mut offset = 0; 137 | bytecodec_try_encode!(self.destination, offset, buf, eos); 138 | bytecodec_try_encode!(self.sender, offset, buf, eos); 139 | bytecodec_try_encode!(self.new_node, offset, buf, eos); 140 | bytecodec_try_encode!(self.ttl, offset, buf, eos); 141 | Ok(offset) 142 | } 143 | 144 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 145 | track!(self.destination.start_encoding(item.0))?; 146 | track!(self.sender.start_encoding(item.1.sender))?; 147 | track!(self.new_node.start_encoding(item.1.new_node))?; 148 | track!(self.ttl.start_encoding(item.1.ttl.as_u8()))?; 149 | Ok(()) 150 | } 151 | 152 | fn requiring_bytes(&self) -> ByteCount { 153 | ByteCount::Finite(self.exact_requiring_bytes()) 154 | } 155 | 156 | fn is_idle(&self) -> bool { 157 | self.ttl.is_idle() 158 | } 159 | } 160 | impl SizedEncode for ForwardJoinMessageEncoder { 161 | fn exact_requiring_bytes(&self) -> u64 { 162 | self.destination.exact_requiring_bytes() 163 | + self.sender.exact_requiring_bytes() 164 | + self.new_node.exact_requiring_bytes() 165 | + self.ttl.exact_requiring_bytes() 166 | } 167 | } 168 | 169 | #[derive(Debug, Default)] 170 | pub struct NeighborMessageDecoder { 171 | destination: LocalNodeIdDecoder, 172 | sender: NodeIdDecoder, 173 | high_priority: U8Decoder, 174 | } 175 | impl Decode for NeighborMessageDecoder { 176 | type Item = (LocalNodeId, NeighborMessage); 177 | 178 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 179 | let mut offset = 0; 180 | bytecodec_try_decode!(self.destination, offset, buf, eos); 181 | bytecodec_try_decode!(self.sender, offset, buf, eos); 182 | bytecodec_try_decode!(self.high_priority, offset, buf, eos); 183 | Ok(offset) 184 | } 185 | 186 | fn finish_decoding(&mut self) -> Result { 187 | let destination = track!(self.destination.finish_decoding())?; 188 | let sender = track!(self.sender.finish_decoding())?; 189 | let high_priority = track!(self.high_priority.finish_decoding())? != 0; 190 | let message = NeighborMessage { 191 | sender, 192 | high_priority, 193 | }; 194 | Ok((destination, message)) 195 | } 196 | 197 | fn requiring_bytes(&self) -> ByteCount { 198 | self.destination 199 | .requiring_bytes() 200 | .add_for_decoding(self.sender.requiring_bytes()) 201 | .add_for_decoding(self.high_priority.requiring_bytes()) 202 | } 203 | 204 | fn is_idle(&self) -> bool { 205 | self.high_priority.is_idle() 206 | } 207 | } 208 | 209 | #[derive(Debug, Default)] 210 | pub struct NeighborMessageEncoder { 211 | destination: LocalNodeIdEncoder, 212 | sender: NodeIdEncoder, 213 | high_priority: U8Encoder, 214 | } 215 | impl Encode for NeighborMessageEncoder { 216 | type Item = (LocalNodeId, NeighborMessage); 217 | 218 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 219 | let mut offset = 0; 220 | bytecodec_try_encode!(self.destination, offset, buf, eos); 221 | bytecodec_try_encode!(self.sender, offset, buf, eos); 222 | bytecodec_try_encode!(self.high_priority, offset, buf, eos); 223 | Ok(offset) 224 | } 225 | 226 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 227 | track!(self.destination.start_encoding(item.0))?; 228 | track!(self.sender.start_encoding(item.1.sender))?; 229 | track!(self 230 | .high_priority 231 | .start_encoding(item.1.high_priority as u8))?; 232 | Ok(()) 233 | } 234 | 235 | fn requiring_bytes(&self) -> ByteCount { 236 | ByteCount::Finite(self.exact_requiring_bytes()) 237 | } 238 | 239 | fn is_idle(&self) -> bool { 240 | self.high_priority.is_idle() 241 | } 242 | } 243 | impl SizedEncode for NeighborMessageEncoder { 244 | fn exact_requiring_bytes(&self) -> u64 { 245 | self.destination.exact_requiring_bytes() 246 | + self.sender.exact_requiring_bytes() 247 | + self.high_priority.exact_requiring_bytes() 248 | } 249 | } 250 | 251 | #[derive(Debug, Default)] 252 | pub struct ShuffleMessageDecoder { 253 | destination: LocalNodeIdDecoder, 254 | sender: NodeIdDecoder, 255 | origin: NodeIdDecoder, 256 | ttl: U8Decoder, 257 | nodes: Collect>, 258 | } 259 | impl Decode for ShuffleMessageDecoder { 260 | type Item = (LocalNodeId, ShuffleMessage); 261 | 262 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 263 | let mut offset = 0; 264 | bytecodec_try_decode!(self.destination, offset, buf, eos); 265 | bytecodec_try_decode!(self.sender, offset, buf, eos); 266 | bytecodec_try_decode!(self.origin, offset, buf, eos); 267 | bytecodec_try_decode!(self.ttl, offset, buf, eos); 268 | bytecodec_try_decode!(self.nodes, offset, buf, eos); 269 | Ok(offset) 270 | } 271 | 272 | fn finish_decoding(&mut self) -> Result { 273 | let destination = track!(self.destination.finish_decoding())?; 274 | let sender = track!(self.sender.finish_decoding())?; 275 | let origin = track!(self.origin.finish_decoding())?; 276 | let ttl = track!(self.ttl.finish_decoding())?; 277 | let nodes = track!(self.nodes.finish_decoding())?; 278 | 279 | let message = ShuffleMessage { 280 | sender, 281 | origin, 282 | ttl: TimeToLive::new(ttl), 283 | nodes, 284 | }; 285 | Ok((destination, message)) 286 | } 287 | 288 | fn requiring_bytes(&self) -> ByteCount { 289 | self.destination 290 | .requiring_bytes() 291 | .add_for_decoding(self.sender.requiring_bytes()) 292 | .add_for_decoding(self.origin.requiring_bytes()) 293 | .add_for_decoding(self.ttl.requiring_bytes()) 294 | .add_for_decoding(self.nodes.requiring_bytes()) 295 | } 296 | 297 | fn is_idle(&self) -> bool { 298 | self.nodes.is_idle() 299 | } 300 | } 301 | 302 | #[derive(Debug, Default)] 303 | pub struct ShuffleMessageEncoder { 304 | destination: LocalNodeIdEncoder, 305 | sender: NodeIdEncoder, 306 | origin: NodeIdEncoder, 307 | ttl: U8Encoder, 308 | nodes: Repeat>, 309 | } 310 | impl Encode for ShuffleMessageEncoder { 311 | type Item = (LocalNodeId, ShuffleMessage); 312 | 313 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 314 | let mut offset = 0; 315 | bytecodec_try_encode!(self.destination, offset, buf, eos); 316 | bytecodec_try_encode!(self.sender, offset, buf, eos); 317 | bytecodec_try_encode!(self.origin, offset, buf, eos); 318 | bytecodec_try_encode!(self.ttl, offset, buf, eos); 319 | bytecodec_try_encode!(self.nodes, offset, buf, eos); 320 | Ok(offset) 321 | } 322 | 323 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 324 | track!(self.destination.start_encoding(item.0))?; 325 | track!(self.sender.start_encoding(item.1.sender))?; 326 | track!(self.origin.start_encoding(item.1.origin))?; 327 | track!(self.ttl.start_encoding(item.1.ttl.as_u8()))?; 328 | track!(self.nodes.start_encoding(item.1.nodes.into_iter()))?; 329 | Ok(()) 330 | } 331 | 332 | fn requiring_bytes(&self) -> ByteCount { 333 | self.destination 334 | .requiring_bytes() 335 | .add_for_encoding(self.sender.requiring_bytes()) 336 | .add_for_encoding(self.origin.requiring_bytes()) 337 | .add_for_encoding(self.ttl.requiring_bytes()) 338 | .add_for_encoding(self.nodes.requiring_bytes()) 339 | } 340 | 341 | fn is_idle(&self) -> bool { 342 | self.nodes.is_idle() 343 | } 344 | } 345 | 346 | #[derive(Debug, Default)] 347 | pub struct ShuffleReplyMessageDecoder { 348 | destination: LocalNodeIdDecoder, 349 | sender: NodeIdDecoder, 350 | nodes: Collect>, 351 | } 352 | impl Decode for ShuffleReplyMessageDecoder { 353 | type Item = (LocalNodeId, ShuffleReplyMessage); 354 | 355 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 356 | let mut offset = 0; 357 | bytecodec_try_decode!(self.destination, offset, buf, eos); 358 | bytecodec_try_decode!(self.sender, offset, buf, eos); 359 | bytecodec_try_decode!(self.nodes, offset, buf, eos); 360 | Ok(offset) 361 | } 362 | 363 | fn finish_decoding(&mut self) -> Result { 364 | let destination = track!(self.destination.finish_decoding())?; 365 | let sender = track!(self.sender.finish_decoding())?; 366 | let nodes = track!(self.nodes.finish_decoding())?; 367 | 368 | let message = ShuffleReplyMessage { sender, nodes }; 369 | Ok((destination, message)) 370 | } 371 | 372 | fn requiring_bytes(&self) -> ByteCount { 373 | self.destination 374 | .requiring_bytes() 375 | .add_for_decoding(self.sender.requiring_bytes()) 376 | .add_for_decoding(self.nodes.requiring_bytes()) 377 | } 378 | 379 | fn is_idle(&self) -> bool { 380 | self.nodes.is_idle() 381 | } 382 | } 383 | 384 | #[derive(Debug, Default)] 385 | pub struct ShuffleReplyMessageEncoder { 386 | destination: LocalNodeIdEncoder, 387 | sender: NodeIdEncoder, 388 | nodes: Repeat>, 389 | } 390 | impl Encode for ShuffleReplyMessageEncoder { 391 | type Item = (LocalNodeId, ShuffleReplyMessage); 392 | 393 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 394 | let mut offset = 0; 395 | bytecodec_try_encode!(self.destination, offset, buf, eos); 396 | bytecodec_try_encode!(self.sender, offset, buf, eos); 397 | bytecodec_try_encode!(self.nodes, offset, buf, eos); 398 | Ok(offset) 399 | } 400 | 401 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 402 | track!(self.destination.start_encoding(item.0))?; 403 | track!(self.sender.start_encoding(item.1.sender))?; 404 | track!(self.nodes.start_encoding(item.1.nodes.into_iter()))?; 405 | Ok(()) 406 | } 407 | 408 | fn requiring_bytes(&self) -> ByteCount { 409 | self.destination 410 | .requiring_bytes() 411 | .add_for_encoding(self.sender.requiring_bytes()) 412 | .add_for_encoding(self.nodes.requiring_bytes()) 413 | } 414 | 415 | fn is_idle(&self) -> bool { 416 | self.nodes.is_idle() 417 | } 418 | } 419 | 420 | #[derive(Debug, Default)] 421 | pub struct DisconnectMessageDecoder { 422 | destination: LocalNodeIdDecoder, 423 | sender: NodeIdDecoder, 424 | alive: U8Decoder, 425 | } 426 | impl Decode for DisconnectMessageDecoder { 427 | type Item = (LocalNodeId, DisconnectMessage); 428 | 429 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 430 | let mut offset = 0; 431 | bytecodec_try_decode!(self.destination, offset, buf, eos); 432 | bytecodec_try_decode!(self.sender, offset, buf, eos); 433 | bytecodec_try_decode!(self.alive, offset, buf, eos); 434 | Ok(offset) 435 | } 436 | 437 | fn finish_decoding(&mut self) -> Result { 438 | let destination = track!(self.destination.finish_decoding())?; 439 | let sender = track!(self.sender.finish_decoding())?; 440 | let alive = track!(self.alive.finish_decoding())? != 0; 441 | Ok((destination, DisconnectMessage { sender, alive })) 442 | } 443 | 444 | fn requiring_bytes(&self) -> ByteCount { 445 | self.destination 446 | .requiring_bytes() 447 | .add_for_decoding(self.sender.requiring_bytes()) 448 | .add_for_decoding(self.alive.requiring_bytes()) 449 | } 450 | 451 | fn is_idle(&self) -> bool { 452 | self.alive.is_idle() 453 | } 454 | } 455 | 456 | #[derive(Debug, Default)] 457 | pub struct DisconnectMessageEncoder { 458 | destination: LocalNodeIdEncoder, 459 | sender: NodeIdEncoder, 460 | alive: U8Encoder, 461 | } 462 | impl Encode for DisconnectMessageEncoder { 463 | type Item = (LocalNodeId, DisconnectMessage); 464 | 465 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 466 | let mut offset = 0; 467 | bytecodec_try_encode!(self.destination, offset, buf, eos); 468 | bytecodec_try_encode!(self.sender, offset, buf, eos); 469 | bytecodec_try_encode!(self.alive, offset, buf, eos); 470 | Ok(offset) 471 | } 472 | 473 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 474 | track!(self.destination.start_encoding(item.0))?; 475 | track!(self.sender.start_encoding(item.1.sender))?; 476 | track!(self.alive.start_encoding(item.1.alive as u8))?; 477 | Ok(()) 478 | } 479 | 480 | fn requiring_bytes(&self) -> ByteCount { 481 | ByteCount::Finite(self.exact_requiring_bytes()) 482 | } 483 | 484 | fn is_idle(&self) -> bool { 485 | self.alive.is_idle() 486 | } 487 | } 488 | impl SizedEncode for DisconnectMessageEncoder { 489 | fn exact_requiring_bytes(&self) -> u64 { 490 | self.destination.exact_requiring_bytes() 491 | + self.sender.exact_requiring_bytes() 492 | + self.alive.exact_requiring_bytes() 493 | } 494 | } 495 | -------------------------------------------------------------------------------- /src/codec/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod hyparview; 2 | pub mod net; 3 | pub mod node; 4 | pub mod plumtree; 5 | -------------------------------------------------------------------------------- /src/codec/net.rs: -------------------------------------------------------------------------------- 1 | use bytecodec::bytes::{BytesEncoder, CopyableBytesDecoder}; 2 | use bytecodec::combinator::Peekable; 3 | use bytecodec::fixnum::{ 4 | U16beDecoder, U16beEncoder, U32beDecoder, U32beEncoder, U8Decoder, U8Encoder, 5 | }; 6 | use bytecodec::{ByteCount, Decode, Encode, Eos, ErrorKind, Result, SizedEncode}; 7 | use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; 8 | 9 | #[derive(Debug, Default)] 10 | pub struct SocketAddrDecoder { 11 | version: Peekable, 12 | v4: SocketAddrV4Decoder, 13 | v6: SocketAddrV6Decoder, 14 | } 15 | impl Decode for SocketAddrDecoder { 16 | type Item = SocketAddr; 17 | 18 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 19 | let mut offset = 0; 20 | bytecodec_try_decode!(self.version, offset, buf, eos); 21 | match self.version.peek().cloned().expect("Never fails") { 22 | 4 => bytecodec_try_decode!(self.v4, offset, buf, eos), 23 | 6 => bytecodec_try_decode!(self.v6, offset, buf, eos), 24 | v => track_panic!(ErrorKind::InvalidInput, "Unknown IP version: {}", v), 25 | } 26 | Ok(offset) 27 | } 28 | 29 | fn finish_decoding(&mut self) -> Result { 30 | let v = track!(self.version.finish_decoding())?; 31 | match v { 32 | 4 => track!(self.v4.finish_decoding()).map(SocketAddr::V4), 33 | 6 => track!(self.v6.finish_decoding()).map(SocketAddr::V6), 34 | _ => track_panic!(ErrorKind::InvalidInput, "Unknown IP version: {}", v), 35 | } 36 | } 37 | 38 | fn requiring_bytes(&self) -> ByteCount { 39 | match self.version.peek().cloned() { 40 | None => self.version.requiring_bytes(), 41 | Some(4) => self.v4.requiring_bytes(), 42 | Some(6) => self.v6.requiring_bytes(), 43 | Some(_) => ByteCount::Unknown, 44 | } 45 | } 46 | 47 | fn is_idle(&self) -> bool { 48 | match self.version.peek().cloned() { 49 | Some(4) => self.v4.is_idle(), 50 | Some(6) => self.v6.is_idle(), 51 | _ => false, 52 | } 53 | } 54 | } 55 | 56 | #[derive(Debug, Default)] 57 | struct SocketAddrV4Decoder { 58 | ip: CopyableBytesDecoder<[u8; 4]>, 59 | port: U16beDecoder, 60 | } 61 | impl Decode for SocketAddrV4Decoder { 62 | type Item = SocketAddrV4; 63 | 64 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 65 | let mut offset = 0; 66 | bytecodec_try_decode!(self.ip, offset, buf, eos); 67 | bytecodec_try_decode!(self.port, offset, buf, eos); 68 | Ok(offset) 69 | } 70 | 71 | fn finish_decoding(&mut self) -> Result { 72 | let ip = track!(self.ip.finish_decoding())?.into(); 73 | let port = track!(self.port.finish_decoding())?; 74 | Ok(SocketAddrV4::new(ip, port)) 75 | } 76 | 77 | fn requiring_bytes(&self) -> ByteCount { 78 | self.ip 79 | .requiring_bytes() 80 | .add_for_decoding(self.port.requiring_bytes()) 81 | } 82 | 83 | fn is_idle(&self) -> bool { 84 | self.port.is_idle() 85 | } 86 | } 87 | 88 | #[derive(Debug, Default)] 89 | struct SocketAddrV6Decoder { 90 | ip: CopyableBytesDecoder<[u8; 16]>, 91 | port: U16beDecoder, 92 | flowinfo: U32beDecoder, 93 | scope_id: U32beDecoder, 94 | } 95 | impl Decode for SocketAddrV6Decoder { 96 | type Item = SocketAddrV6; 97 | 98 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 99 | let mut offset = 0; 100 | bytecodec_try_decode!(self.ip, offset, buf, eos); 101 | bytecodec_try_decode!(self.port, offset, buf, eos); 102 | bytecodec_try_decode!(self.flowinfo, offset, buf, eos); 103 | bytecodec_try_decode!(self.scope_id, offset, buf, eos); 104 | Ok(offset) 105 | } 106 | 107 | fn finish_decoding(&mut self) -> Result { 108 | let ip = track!(self.ip.finish_decoding())?.into(); 109 | let port = track!(self.port.finish_decoding())?; 110 | let flowinfo = track!(self.flowinfo.finish_decoding())?; 111 | let scope_id = track!(self.scope_id.finish_decoding())?; 112 | Ok(SocketAddrV6::new(ip, port, flowinfo, scope_id)) 113 | } 114 | 115 | fn requiring_bytes(&self) -> ByteCount { 116 | self.ip 117 | .requiring_bytes() 118 | .add_for_decoding(self.port.requiring_bytes()) 119 | .add_for_decoding(self.flowinfo.requiring_bytes()) 120 | .add_for_decoding(self.scope_id.requiring_bytes()) 121 | } 122 | 123 | fn is_idle(&self) -> bool { 124 | self.scope_id.is_idle() 125 | } 126 | } 127 | 128 | #[derive(Debug, Default)] 129 | pub struct SocketAddrEncoder { 130 | version: U8Encoder, 131 | v4: SocketAddrV4Encoder, 132 | v6: SocketAddrV6Encoder, 133 | } 134 | impl Encode for SocketAddrEncoder { 135 | type Item = SocketAddr; 136 | 137 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 138 | let mut offset = 0; 139 | bytecodec_try_encode!(self.version, offset, buf, eos); 140 | bytecodec_try_encode!(self.v4, offset, buf, eos); 141 | bytecodec_try_encode!(self.v6, offset, buf, eos); 142 | Ok(offset) 143 | } 144 | 145 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 146 | match item { 147 | SocketAddr::V4(x) => { 148 | track!(self.version.start_encoding(4))?; 149 | track!(self.v4.start_encoding(x))?; 150 | } 151 | SocketAddr::V6(x) => { 152 | track!(self.version.start_encoding(6))?; 153 | track!(self.v6.start_encoding(x))?; 154 | } 155 | } 156 | Ok(()) 157 | } 158 | 159 | fn requiring_bytes(&self) -> ByteCount { 160 | ByteCount::Finite(self.exact_requiring_bytes()) 161 | } 162 | 163 | fn is_idle(&self) -> bool { 164 | self.version.is_idle() && self.v4.is_idle() && self.v6.is_idle() 165 | } 166 | } 167 | impl SizedEncode for SocketAddrEncoder { 168 | fn exact_requiring_bytes(&self) -> u64 { 169 | self.version.exact_requiring_bytes() 170 | + self.v4.exact_requiring_bytes() 171 | + self.v6.exact_requiring_bytes() 172 | } 173 | } 174 | 175 | #[derive(Debug, Default)] 176 | struct SocketAddrV4Encoder { 177 | ip: BytesEncoder<[u8; 4]>, 178 | port: U16beEncoder, 179 | } 180 | impl Encode for SocketAddrV4Encoder { 181 | type Item = SocketAddrV4; 182 | 183 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 184 | let mut offset = 0; 185 | bytecodec_try_encode!(self.ip, offset, buf, eos); 186 | bytecodec_try_encode!(self.port, offset, buf, eos); 187 | Ok(offset) 188 | } 189 | 190 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 191 | track!(self.ip.start_encoding(item.ip().octets()))?; 192 | track!(self.port.start_encoding(item.port()))?; 193 | Ok(()) 194 | } 195 | 196 | fn requiring_bytes(&self) -> ByteCount { 197 | ByteCount::Finite(self.exact_requiring_bytes()) 198 | } 199 | 200 | fn is_idle(&self) -> bool { 201 | self.ip.is_idle() && self.port.is_idle() 202 | } 203 | } 204 | impl SizedEncode for SocketAddrV4Encoder { 205 | fn exact_requiring_bytes(&self) -> u64 { 206 | self.ip.exact_requiring_bytes() + self.port.exact_requiring_bytes() 207 | } 208 | } 209 | 210 | #[derive(Debug, Default)] 211 | struct SocketAddrV6Encoder { 212 | ip: BytesEncoder<[u8; 16]>, 213 | port: U16beEncoder, 214 | flowinfo: U32beEncoder, 215 | scope_id: U32beEncoder, 216 | } 217 | impl Encode for SocketAddrV6Encoder { 218 | type Item = SocketAddrV6; 219 | 220 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 221 | let mut offset = 0; 222 | bytecodec_try_encode!(self.ip, offset, buf, eos); 223 | bytecodec_try_encode!(self.port, offset, buf, eos); 224 | bytecodec_try_encode!(self.flowinfo, offset, buf, eos); 225 | bytecodec_try_encode!(self.scope_id, offset, buf, eos); 226 | Ok(offset) 227 | } 228 | 229 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 230 | track!(self.ip.start_encoding(item.ip().octets()))?; 231 | track!(self.port.start_encoding(item.port()))?; 232 | track!(self.flowinfo.start_encoding(item.flowinfo()))?; 233 | track!(self.scope_id.start_encoding(item.scope_id()))?; 234 | Ok(()) 235 | } 236 | 237 | fn requiring_bytes(&self) -> ByteCount { 238 | ByteCount::Finite(self.exact_requiring_bytes()) 239 | } 240 | 241 | fn is_idle(&self) -> bool { 242 | self.ip.is_idle() 243 | && self.port.is_idle() 244 | && self.flowinfo.is_idle() 245 | && self.scope_id.is_idle() 246 | } 247 | } 248 | impl SizedEncode for SocketAddrV6Encoder { 249 | fn exact_requiring_bytes(&self) -> u64 { 250 | self.ip.exact_requiring_bytes() 251 | + self.port.exact_requiring_bytes() 252 | + self.flowinfo.exact_requiring_bytes() 253 | + self.scope_id.exact_requiring_bytes() 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /src/codec/node.rs: -------------------------------------------------------------------------------- 1 | use super::net::{SocketAddrDecoder, SocketAddrEncoder}; 2 | use crate::node::{LocalNodeId, NodeId}; 3 | use bytecodec::fixnum::{U64beDecoder, U64beEncoder}; 4 | use bytecodec::{ByteCount, Decode, Encode, Eos, Result, SizedEncode}; 5 | 6 | #[derive(Debug, Default)] 7 | pub struct LocalNodeIdDecoder(U64beDecoder); 8 | impl Decode for LocalNodeIdDecoder { 9 | type Item = LocalNodeId; 10 | 11 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 12 | track!(self.0.decode(buf, eos)) 13 | } 14 | 15 | fn finish_decoding(&mut self) -> Result { 16 | track!(self.0.finish_decoding()).map(LocalNodeId::new) 17 | } 18 | 19 | fn requiring_bytes(&self) -> ByteCount { 20 | self.0.requiring_bytes() 21 | } 22 | 23 | fn is_idle(&self) -> bool { 24 | self.0.is_idle() 25 | } 26 | } 27 | 28 | #[derive(Debug, Default)] 29 | pub struct NodeIdDecoder { 30 | addr: SocketAddrDecoder, 31 | local_id: LocalNodeIdDecoder, 32 | } 33 | impl Decode for NodeIdDecoder { 34 | type Item = NodeId; 35 | 36 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 37 | let mut offset = 0; 38 | bytecodec_try_decode!(self.addr, offset, buf, eos); 39 | bytecodec_try_decode!(self.local_id, offset, buf, eos); 40 | Ok(offset) 41 | } 42 | 43 | fn finish_decoding(&mut self) -> Result { 44 | let addr = track!(self.addr.finish_decoding())?; 45 | let local_id = track!(self.local_id.finish_decoding())?; 46 | Ok(NodeId::new(addr, local_id)) 47 | } 48 | 49 | fn requiring_bytes(&self) -> ByteCount { 50 | self.addr 51 | .requiring_bytes() 52 | .add_for_decoding(self.local_id.requiring_bytes()) 53 | } 54 | 55 | fn is_idle(&self) -> bool { 56 | self.addr.is_idle() && self.local_id.is_idle() 57 | } 58 | } 59 | 60 | #[derive(Debug, Default)] 61 | pub struct LocalNodeIdEncoder(U64beEncoder); 62 | impl Encode for LocalNodeIdEncoder { 63 | type Item = LocalNodeId; 64 | 65 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 66 | track!(self.0.encode(buf, eos)) 67 | } 68 | 69 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 70 | track!(self.0.start_encoding(item.value())) 71 | } 72 | 73 | fn requiring_bytes(&self) -> ByteCount { 74 | self.0.requiring_bytes() 75 | } 76 | 77 | fn is_idle(&self) -> bool { 78 | self.0.is_idle() 79 | } 80 | } 81 | impl SizedEncode for LocalNodeIdEncoder { 82 | fn exact_requiring_bytes(&self) -> u64 { 83 | self.0.exact_requiring_bytes() 84 | } 85 | } 86 | 87 | #[derive(Debug, Default)] 88 | pub struct NodeIdEncoder { 89 | addr: SocketAddrEncoder, 90 | local_id: LocalNodeIdEncoder, 91 | } 92 | impl Encode for NodeIdEncoder { 93 | type Item = NodeId; 94 | 95 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 96 | let mut offset = 0; 97 | bytecodec_try_encode!(self.addr, offset, buf, eos); 98 | bytecodec_try_encode!(self.local_id, offset, buf, eos); 99 | Ok(offset) 100 | } 101 | 102 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 103 | track!(self.addr.start_encoding(item.address()))?; 104 | track!(self.local_id.start_encoding(item.local_id()))?; 105 | Ok(()) 106 | } 107 | 108 | fn requiring_bytes(&self) -> ByteCount { 109 | ByteCount::Finite(self.exact_requiring_bytes()) 110 | } 111 | 112 | fn is_idle(&self) -> bool { 113 | self.addr.is_idle() && self.local_id.is_idle() 114 | } 115 | } 116 | impl SizedEncode for NodeIdEncoder { 117 | fn exact_requiring_bytes(&self) -> u64 { 118 | self.addr.exact_requiring_bytes() + self.local_id.exact_requiring_bytes() 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/codec/plumtree.rs: -------------------------------------------------------------------------------- 1 | use super::node::{LocalNodeIdDecoder, LocalNodeIdEncoder, NodeIdDecoder, NodeIdEncoder}; 2 | use crate::message::{MessageId, MessagePayload}; 3 | use crate::misc::{GossipMessage, GraftMessage, IhaveMessage, PlumtreeAppMessage, PruneMessage}; 4 | use crate::node::LocalNodeId; 5 | use bytecodec::bytes::{BytesDecoder, BytesEncoder}; 6 | use bytecodec::combinator::Peekable; 7 | use bytecodec::fixnum::{ 8 | U16beDecoder, U16beEncoder, U32beDecoder, U32beEncoder, U64beDecoder, U64beEncoder, U8Decoder, 9 | U8Encoder, 10 | }; 11 | use bytecodec::{ByteCount, Decode, Encode, Eos, ErrorKind, Result, SizedEncode}; 12 | use std::fmt; 13 | use std::marker::PhantomData; 14 | 15 | pub struct GossipMessageDecoder { 16 | destination: LocalNodeIdDecoder, 17 | sender: NodeIdDecoder, 18 | round: U16beDecoder, 19 | message: MessageDecoder, 20 | } 21 | impl Default for GossipMessageDecoder { 22 | fn default() -> Self { 23 | GossipMessageDecoder { 24 | destination: Default::default(), 25 | sender: Default::default(), 26 | round: Default::default(), 27 | message: Default::default(), 28 | } 29 | } 30 | } 31 | impl fmt::Debug for GossipMessageDecoder 32 | where 33 | M::Decoder: fmt::Debug, 34 | { 35 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 36 | write!( 37 | f, 38 | "GossipMessageDecoder {{ destination: {:?}, sender: {:?}, \ 39 | round: {:?}, message: {:?} }}", 40 | self.destination, self.sender, self.round, self.message 41 | ) 42 | } 43 | } 44 | impl Decode for GossipMessageDecoder { 45 | type Item = (LocalNodeId, GossipMessage); 46 | 47 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 48 | let mut offset = 0; 49 | bytecodec_try_decode!(self.destination, offset, buf, eos); 50 | bytecodec_try_decode!(self.sender, offset, buf, eos); 51 | bytecodec_try_decode!(self.round, offset, buf, eos); 52 | bytecodec_try_decode!(self.message, offset, buf, eos); 53 | Ok(offset) 54 | } 55 | 56 | fn finish_decoding(&mut self) -> Result { 57 | let destination = track!(self.destination.finish_decoding())?; 58 | let sender = track!(self.sender.finish_decoding())?; 59 | let round = track!(self.round.finish_decoding())?; 60 | let message = track!(self.message.finish_decoding())?; 61 | let gossip = GossipMessage { 62 | sender, 63 | round, 64 | message, 65 | }; 66 | Ok((destination, gossip)) 67 | } 68 | 69 | fn requiring_bytes(&self) -> ByteCount { 70 | self.destination 71 | .requiring_bytes() 72 | .add_for_decoding(self.sender.requiring_bytes()) 73 | .add_for_decoding(self.round.requiring_bytes()) 74 | .add_for_decoding(self.message.requiring_bytes()) 75 | } 76 | 77 | fn is_idle(&self) -> bool { 78 | self.round.is_idle() && self.message.is_idle() 79 | } 80 | } 81 | 82 | struct MessageDecoder { 83 | id: MessageIdDecoder, 84 | payload: M::Decoder, 85 | } 86 | impl Default for MessageDecoder { 87 | fn default() -> Self { 88 | MessageDecoder { 89 | id: Default::default(), 90 | payload: Default::default(), 91 | } 92 | } 93 | } 94 | impl fmt::Debug for MessageDecoder 95 | where 96 | M::Decoder: fmt::Debug, 97 | { 98 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 99 | write!( 100 | f, 101 | "MessageDecoder {{ id: {:?}, payload: {:?} }}", 102 | self.id, self.payload 103 | ) 104 | } 105 | } 106 | impl Decode for MessageDecoder { 107 | type Item = PlumtreeAppMessage; 108 | 109 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 110 | let mut offset = 0; 111 | bytecodec_try_decode!(self.id, offset, buf, eos); 112 | bytecodec_try_decode!(self.payload, offset, buf, eos); 113 | Ok(offset) 114 | } 115 | 116 | fn finish_decoding(&mut self) -> Result { 117 | let id = track!(self.id.finish_decoding())?; 118 | let payload = track!(self.payload.finish_decoding())?; 119 | Ok(PlumtreeAppMessage { id, payload }) 120 | } 121 | 122 | fn requiring_bytes(&self) -> ByteCount { 123 | self.id 124 | .requiring_bytes() 125 | .add_for_decoding(self.payload.requiring_bytes()) 126 | } 127 | 128 | fn is_idle(&self) -> bool { 129 | self.id.is_idle() && self.payload.is_idle() 130 | } 131 | } 132 | 133 | #[derive(Debug, Default)] 134 | struct MessageIdDecoder { 135 | node: NodeIdDecoder, 136 | seqno: U64beDecoder, 137 | } 138 | impl Decode for MessageIdDecoder { 139 | type Item = MessageId; 140 | 141 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 142 | let mut offset = 0; 143 | bytecodec_try_decode!(self.node, offset, buf, eos); 144 | bytecodec_try_decode!(self.seqno, offset, buf, eos); 145 | Ok(offset) 146 | } 147 | 148 | fn finish_decoding(&mut self) -> Result { 149 | let node = track!(self.node.finish_decoding())?; 150 | let seqno = track!(self.seqno.finish_decoding())?; 151 | Ok(MessageId::new(node, seqno)) 152 | } 153 | 154 | fn requiring_bytes(&self) -> ByteCount { 155 | self.node 156 | .requiring_bytes() 157 | .add_for_decoding(self.seqno.requiring_bytes()) 158 | } 159 | 160 | fn is_idle(&self) -> bool { 161 | self.seqno.is_idle() 162 | } 163 | } 164 | 165 | #[derive(Debug, Default)] 166 | struct MessagePayloadDecoder { 167 | size: Peekable, 168 | data: BytesDecoder>, 169 | } 170 | impl Decode for MessagePayloadDecoder { 171 | type Item = Vec; 172 | 173 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 174 | let mut offset = 0; 175 | if !self.size.is_idle() { 176 | bytecodec_try_decode!(self.size, offset, buf, eos); 177 | 178 | let size = self.size.peek().cloned().expect("Never fails"); 179 | let buf = vec![0; size as usize]; 180 | self.data.set_bytes(buf); 181 | } 182 | bytecodec_try_decode!(self.data, offset, buf, eos); 183 | Ok(offset) 184 | } 185 | 186 | fn finish_decoding(&mut self) -> Result { 187 | let _ = track!(self.size.finish_decoding())?; 188 | let data = track!(self.data.finish_decoding())?; 189 | Ok(data) 190 | } 191 | 192 | fn requiring_bytes(&self) -> ByteCount { 193 | self.size 194 | .requiring_bytes() 195 | .add_for_decoding(self.data.requiring_bytes()) 196 | } 197 | 198 | fn is_idle(&self) -> bool { 199 | self.size.is_idle() && self.data.is_idle() 200 | } 201 | } 202 | 203 | pub struct GossipMessageEncoder { 204 | destination: LocalNodeIdEncoder, 205 | sender: NodeIdEncoder, 206 | round: U16beEncoder, 207 | message: MessageEncoder, 208 | } 209 | impl Default for GossipMessageEncoder { 210 | fn default() -> Self { 211 | GossipMessageEncoder { 212 | destination: Default::default(), 213 | sender: Default::default(), 214 | round: Default::default(), 215 | message: Default::default(), 216 | } 217 | } 218 | } 219 | impl fmt::Debug for GossipMessageEncoder 220 | where 221 | M::Encoder: fmt::Debug, 222 | { 223 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 224 | write!( 225 | f, 226 | "GossipMessageEncoder {{ destination: {:?}, sender: {:?}, \ 227 | round: {:?}, message: {:?} }}", 228 | self.destination, self.sender, self.round, self.message 229 | ) 230 | } 231 | } 232 | impl Encode for GossipMessageEncoder { 233 | type Item = (LocalNodeId, GossipMessage); 234 | 235 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 236 | let mut offset = 0; 237 | bytecodec_try_encode!(self.destination, offset, buf, eos); 238 | bytecodec_try_encode!(self.sender, offset, buf, eos); 239 | bytecodec_try_encode!(self.round, offset, buf, eos); 240 | bytecodec_try_encode!(self.message, offset, buf, eos); 241 | Ok(offset) 242 | } 243 | 244 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 245 | track!(self.destination.start_encoding(item.0))?; 246 | track!(self.sender.start_encoding(item.1.sender))?; 247 | track!(self.round.start_encoding(item.1.round))?; 248 | track!(self.message.start_encoding(item.1.message))?; 249 | Ok(()) 250 | } 251 | 252 | fn requiring_bytes(&self) -> ByteCount { 253 | self.destination 254 | .requiring_bytes() 255 | .add_for_encoding(self.sender.requiring_bytes()) 256 | .add_for_encoding(self.round.requiring_bytes()) 257 | .add_for_encoding(self.message.requiring_bytes()) 258 | } 259 | 260 | fn is_idle(&self) -> bool { 261 | self.round.is_idle() && self.message.is_idle() 262 | } 263 | } 264 | impl SizedEncode for GossipMessageEncoder 265 | where 266 | M::Encoder: SizedEncode, 267 | { 268 | fn exact_requiring_bytes(&self) -> u64 { 269 | self.destination.exact_requiring_bytes() 270 | + self.sender.exact_requiring_bytes() 271 | + self.round.exact_requiring_bytes() 272 | + self.message.exact_requiring_bytes() 273 | } 274 | } 275 | 276 | struct MessageEncoder { 277 | id: MessageIdEncoder, 278 | payload: M::Encoder, 279 | } 280 | impl Default for MessageEncoder { 281 | fn default() -> Self { 282 | MessageEncoder { 283 | id: Default::default(), 284 | payload: Default::default(), 285 | } 286 | } 287 | } 288 | impl fmt::Debug for MessageEncoder 289 | where 290 | M::Encoder: fmt::Debug, 291 | { 292 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 293 | write!( 294 | f, 295 | "MessageEncoder {{ id: {:?}, payload: {:?} }}", 296 | self.id, self.payload 297 | ) 298 | } 299 | } 300 | impl Encode for MessageEncoder { 301 | type Item = PlumtreeAppMessage; 302 | 303 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 304 | let mut offset = 0; 305 | bytecodec_try_encode!(self.id, offset, buf, eos); 306 | bytecodec_try_encode!(self.payload, offset, buf, eos); 307 | Ok(offset) 308 | } 309 | 310 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 311 | track!(self.id.start_encoding(item.id))?; 312 | track!(self.payload.start_encoding(item.payload))?; 313 | Ok(()) 314 | } 315 | 316 | fn requiring_bytes(&self) -> ByteCount { 317 | self.id 318 | .requiring_bytes() 319 | .add_for_encoding(self.payload.requiring_bytes()) 320 | } 321 | 322 | fn is_idle(&self) -> bool { 323 | self.id.is_idle() && self.payload.is_idle() 324 | } 325 | } 326 | impl SizedEncode for MessageEncoder 327 | where 328 | M::Encoder: SizedEncode, 329 | { 330 | fn exact_requiring_bytes(&self) -> u64 { 331 | self.id.exact_requiring_bytes() + self.payload.exact_requiring_bytes() 332 | } 333 | } 334 | 335 | #[derive(Debug, Default)] 336 | struct MessageIdEncoder { 337 | node: NodeIdEncoder, 338 | seqno: U64beEncoder, 339 | } 340 | impl Encode for MessageIdEncoder { 341 | type Item = MessageId; 342 | 343 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 344 | let mut offset = 0; 345 | bytecodec_try_encode!(self.node, offset, buf, eos); 346 | bytecodec_try_encode!(self.seqno, offset, buf, eos); 347 | Ok(offset) 348 | } 349 | 350 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 351 | track!(self.node.start_encoding(item.node()))?; 352 | track!(self.seqno.start_encoding(item.seqno()))?; 353 | Ok(()) 354 | } 355 | 356 | fn requiring_bytes(&self) -> ByteCount { 357 | self.node 358 | .requiring_bytes() 359 | .add_for_encoding(self.seqno.requiring_bytes()) 360 | } 361 | 362 | fn is_idle(&self) -> bool { 363 | self.seqno.is_idle() 364 | } 365 | } 366 | impl SizedEncode for MessageIdEncoder { 367 | fn exact_requiring_bytes(&self) -> u64 { 368 | self.node.exact_requiring_bytes() + self.seqno.exact_requiring_bytes() 369 | } 370 | } 371 | 372 | #[derive(Debug, Default)] 373 | struct MessagePayloadEncoder { 374 | size: U32beEncoder, 375 | data: BytesEncoder>, 376 | } 377 | impl Encode for MessagePayloadEncoder { 378 | type Item = Vec; 379 | 380 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 381 | let mut offset = 0; 382 | bytecodec_try_encode!(self.size, offset, buf, eos); 383 | bytecodec_try_encode!(self.data, offset, buf, eos); 384 | Ok(offset) 385 | } 386 | 387 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 388 | track!(self.size.start_encoding(item.len() as u32))?; 389 | track!(self.data.start_encoding(item))?; 390 | Ok(()) 391 | } 392 | 393 | fn requiring_bytes(&self) -> ByteCount { 394 | self.size 395 | .requiring_bytes() 396 | .add_for_encoding(self.data.requiring_bytes()) 397 | } 398 | 399 | fn is_idle(&self) -> bool { 400 | self.size.is_idle() && self.data.is_idle() 401 | } 402 | } 403 | impl SizedEncode for MessagePayloadEncoder { 404 | fn exact_requiring_bytes(&self) -> u64 { 405 | self.size.exact_requiring_bytes() + self.data.exact_requiring_bytes() 406 | } 407 | } 408 | 409 | #[derive(Debug)] 410 | pub struct IhaveMessageDecoder { 411 | destination: LocalNodeIdDecoder, 412 | sender: NodeIdDecoder, 413 | round: U16beDecoder, 414 | message_id: MessageIdDecoder, 415 | realtime: U8Decoder, 416 | _phantom: PhantomData, 417 | } 418 | impl Default for IhaveMessageDecoder { 419 | fn default() -> Self { 420 | IhaveMessageDecoder { 421 | destination: Default::default(), 422 | sender: Default::default(), 423 | round: Default::default(), 424 | message_id: Default::default(), 425 | realtime: Default::default(), 426 | _phantom: PhantomData, 427 | } 428 | } 429 | } 430 | impl Decode for IhaveMessageDecoder { 431 | type Item = (LocalNodeId, IhaveMessage); 432 | 433 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 434 | let mut offset = 0; 435 | bytecodec_try_decode!(self.destination, offset, buf, eos); 436 | bytecodec_try_decode!(self.sender, offset, buf, eos); 437 | bytecodec_try_decode!(self.round, offset, buf, eos); 438 | bytecodec_try_decode!(self.message_id, offset, buf, eos); 439 | bytecodec_try_decode!(self.realtime, offset, buf, eos); 440 | Ok(offset) 441 | } 442 | 443 | fn finish_decoding(&mut self) -> Result { 444 | let destination = track!(self.destination.finish_decoding())?; 445 | let sender = track!(self.sender.finish_decoding())?; 446 | let round = track!(self.round.finish_decoding())?; 447 | let message_id = track!(self.message_id.finish_decoding())?; 448 | let realtime = track!(self.realtime.finish_decoding())?; 449 | 450 | let message = IhaveMessage { 451 | sender, 452 | round, 453 | message_id, 454 | realtime: realtime != 0, 455 | }; 456 | Ok((destination, message)) 457 | } 458 | 459 | fn requiring_bytes(&self) -> ByteCount { 460 | self.destination 461 | .requiring_bytes() 462 | .add_for_decoding(self.sender.requiring_bytes()) 463 | .add_for_decoding(self.round.requiring_bytes()) 464 | .add_for_decoding(self.message_id.requiring_bytes()) 465 | .add_for_decoding(self.realtime.requiring_bytes()) 466 | } 467 | 468 | fn is_idle(&self) -> bool { 469 | self.realtime.is_idle() 470 | } 471 | } 472 | 473 | #[derive(Debug)] 474 | pub struct IhaveMessageEncoder { 475 | destination: LocalNodeIdEncoder, 476 | sender: NodeIdEncoder, 477 | round: U16beEncoder, 478 | message_id: MessageIdEncoder, 479 | realtime: U8Encoder, 480 | _phantom: PhantomData, 481 | } 482 | impl Default for IhaveMessageEncoder { 483 | fn default() -> Self { 484 | IhaveMessageEncoder { 485 | destination: Default::default(), 486 | sender: Default::default(), 487 | round: Default::default(), 488 | message_id: Default::default(), 489 | realtime: Default::default(), 490 | _phantom: PhantomData, 491 | } 492 | } 493 | } 494 | impl Encode for IhaveMessageEncoder { 495 | type Item = (LocalNodeId, IhaveMessage); 496 | 497 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 498 | let mut offset = 0; 499 | bytecodec_try_encode!(self.destination, offset, buf, eos); 500 | bytecodec_try_encode!(self.sender, offset, buf, eos); 501 | bytecodec_try_encode!(self.round, offset, buf, eos); 502 | bytecodec_try_encode!(self.message_id, offset, buf, eos); 503 | bytecodec_try_encode!(self.realtime, offset, buf, eos); 504 | Ok(offset) 505 | } 506 | 507 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 508 | track!(self.destination.start_encoding(item.0))?; 509 | track!(self.sender.start_encoding(item.1.sender))?; 510 | track!(self.round.start_encoding(item.1.round))?; 511 | track!(self.message_id.start_encoding(item.1.message_id))?; 512 | track!(self.realtime.start_encoding(item.1.realtime as u8))?; 513 | Ok(()) 514 | } 515 | 516 | fn requiring_bytes(&self) -> ByteCount { 517 | ByteCount::Finite(self.exact_requiring_bytes()) 518 | } 519 | 520 | fn is_idle(&self) -> bool { 521 | self.realtime.is_idle() 522 | } 523 | } 524 | impl SizedEncode for IhaveMessageEncoder { 525 | fn exact_requiring_bytes(&self) -> u64 { 526 | self.destination.exact_requiring_bytes() 527 | + self.sender.exact_requiring_bytes() 528 | + self.round.exact_requiring_bytes() 529 | + self.message_id.exact_requiring_bytes() 530 | + self.realtime.exact_requiring_bytes() 531 | } 532 | } 533 | 534 | #[derive(Debug)] 535 | pub struct GraftMessageDecoder { 536 | destination: LocalNodeIdDecoder, 537 | sender: NodeIdDecoder, 538 | round: U16beDecoder, 539 | message_id: MessageIdDecoder, 540 | _phantom: PhantomData, 541 | } 542 | impl Default for GraftMessageDecoder { 543 | fn default() -> Self { 544 | GraftMessageDecoder { 545 | destination: Default::default(), 546 | sender: Default::default(), 547 | round: Default::default(), 548 | message_id: Default::default(), 549 | _phantom: PhantomData, 550 | } 551 | } 552 | } 553 | impl Decode for GraftMessageDecoder { 554 | type Item = (LocalNodeId, GraftMessage); 555 | 556 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 557 | let mut offset = 0; 558 | bytecodec_try_decode!(self.destination, offset, buf, eos); 559 | bytecodec_try_decode!(self.sender, offset, buf, eos); 560 | bytecodec_try_decode!(self.round, offset, buf, eos); 561 | bytecodec_try_decode!(self.message_id, offset, buf, eos); 562 | Ok(offset) 563 | } 564 | 565 | fn finish_decoding(&mut self) -> Result { 566 | let destination = track!(self.destination.finish_decoding())?; 567 | let sender = track!(self.sender.finish_decoding())?; 568 | let round = track!(self.round.finish_decoding())?; 569 | let message_id = track!(self.message_id.finish_decoding())?; 570 | 571 | let message = GraftMessage { 572 | sender, 573 | round, 574 | message_id: Some(message_id), 575 | }; 576 | Ok((destination, message)) 577 | } 578 | 579 | fn requiring_bytes(&self) -> ByteCount { 580 | self.destination 581 | .requiring_bytes() 582 | .add_for_decoding(self.sender.requiring_bytes()) 583 | .add_for_decoding(self.round.requiring_bytes()) 584 | .add_for_decoding(self.message_id.requiring_bytes()) 585 | } 586 | 587 | fn is_idle(&self) -> bool { 588 | self.message_id.is_idle() 589 | } 590 | } 591 | 592 | #[derive(Debug)] 593 | pub struct GraftMessageEncoder { 594 | destination: LocalNodeIdEncoder, 595 | sender: NodeIdEncoder, 596 | round: U16beEncoder, 597 | message_id: MessageIdEncoder, 598 | _phantom: PhantomData, 599 | } 600 | impl Default for GraftMessageEncoder { 601 | fn default() -> Self { 602 | GraftMessageEncoder { 603 | destination: Default::default(), 604 | sender: Default::default(), 605 | round: Default::default(), 606 | message_id: Default::default(), 607 | _phantom: PhantomData, 608 | } 609 | } 610 | } 611 | impl Encode for GraftMessageEncoder { 612 | type Item = (LocalNodeId, GraftMessage); 613 | 614 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 615 | let mut offset = 0; 616 | bytecodec_try_encode!(self.destination, offset, buf, eos); 617 | bytecodec_try_encode!(self.sender, offset, buf, eos); 618 | bytecodec_try_encode!(self.round, offset, buf, eos); 619 | bytecodec_try_encode!(self.message_id, offset, buf, eos); 620 | Ok(offset) 621 | } 622 | 623 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 624 | track!(self.destination.start_encoding(item.0))?; 625 | track!(self.sender.start_encoding(item.1.sender))?; 626 | track!(self.round.start_encoding(item.1.round))?; 627 | 628 | let message_id = track_assert_some!(item.1.message_id, ErrorKind::InconsistentState); 629 | track!(self.message_id.start_encoding(message_id))?; 630 | Ok(()) 631 | } 632 | 633 | fn requiring_bytes(&self) -> ByteCount { 634 | ByteCount::Finite(self.exact_requiring_bytes()) 635 | } 636 | 637 | fn is_idle(&self) -> bool { 638 | self.message_id.is_idle() 639 | } 640 | } 641 | impl SizedEncode for GraftMessageEncoder { 642 | fn exact_requiring_bytes(&self) -> u64 { 643 | self.destination.exact_requiring_bytes() 644 | + self.sender.exact_requiring_bytes() 645 | + self.round.exact_requiring_bytes() 646 | + self.message_id.exact_requiring_bytes() 647 | } 648 | } 649 | 650 | #[derive(Debug)] 651 | pub struct GraftOptimizeMessageDecoder { 652 | destination: LocalNodeIdDecoder, 653 | sender: NodeIdDecoder, 654 | round: U16beDecoder, 655 | _phantom: PhantomData, 656 | } 657 | impl Default for GraftOptimizeMessageDecoder { 658 | fn default() -> Self { 659 | GraftOptimizeMessageDecoder { 660 | destination: Default::default(), 661 | sender: Default::default(), 662 | round: Default::default(), 663 | _phantom: PhantomData, 664 | } 665 | } 666 | } 667 | impl Decode for GraftOptimizeMessageDecoder { 668 | type Item = (LocalNodeId, GraftMessage); 669 | 670 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 671 | let mut offset = 0; 672 | bytecodec_try_decode!(self.destination, offset, buf, eos); 673 | bytecodec_try_decode!(self.sender, offset, buf, eos); 674 | bytecodec_try_decode!(self.round, offset, buf, eos); 675 | Ok(offset) 676 | } 677 | 678 | fn finish_decoding(&mut self) -> Result { 679 | let destination = track!(self.destination.finish_decoding())?; 680 | let sender = track!(self.sender.finish_decoding())?; 681 | let round = track!(self.round.finish_decoding())?; 682 | 683 | let message = GraftMessage { 684 | sender, 685 | round, 686 | message_id: None, 687 | }; 688 | Ok((destination, message)) 689 | } 690 | 691 | fn requiring_bytes(&self) -> ByteCount { 692 | self.destination 693 | .requiring_bytes() 694 | .add_for_decoding(self.sender.requiring_bytes()) 695 | .add_for_decoding(self.round.requiring_bytes()) 696 | } 697 | 698 | fn is_idle(&self) -> bool { 699 | self.round.is_idle() 700 | } 701 | } 702 | 703 | #[derive(Debug)] 704 | pub struct GraftOptimizeMessageEncoder { 705 | destination: LocalNodeIdEncoder, 706 | sender: NodeIdEncoder, 707 | round: U16beEncoder, 708 | _phantom: PhantomData, 709 | } 710 | impl Default for GraftOptimizeMessageEncoder { 711 | fn default() -> Self { 712 | GraftOptimizeMessageEncoder { 713 | destination: Default::default(), 714 | sender: Default::default(), 715 | round: Default::default(), 716 | _phantom: PhantomData, 717 | } 718 | } 719 | } 720 | impl Encode for GraftOptimizeMessageEncoder { 721 | type Item = (LocalNodeId, GraftMessage); 722 | 723 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 724 | let mut offset = 0; 725 | bytecodec_try_encode!(self.destination, offset, buf, eos); 726 | bytecodec_try_encode!(self.sender, offset, buf, eos); 727 | bytecodec_try_encode!(self.round, offset, buf, eos); 728 | Ok(offset) 729 | } 730 | 731 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 732 | track!(self.destination.start_encoding(item.0))?; 733 | track!(self.sender.start_encoding(item.1.sender))?; 734 | track!(self.round.start_encoding(item.1.round))?; 735 | track_assert_eq!(item.1.message_id, None, ErrorKind::InconsistentState); 736 | Ok(()) 737 | } 738 | 739 | fn requiring_bytes(&self) -> ByteCount { 740 | ByteCount::Finite(self.exact_requiring_bytes()) 741 | } 742 | 743 | fn is_idle(&self) -> bool { 744 | self.round.is_idle() 745 | } 746 | } 747 | impl SizedEncode for GraftOptimizeMessageEncoder { 748 | fn exact_requiring_bytes(&self) -> u64 { 749 | self.destination.exact_requiring_bytes() 750 | + self.sender.exact_requiring_bytes() 751 | + self.round.exact_requiring_bytes() 752 | } 753 | } 754 | 755 | #[derive(Debug)] 756 | pub struct PruneMessageDecoder { 757 | destination: LocalNodeIdDecoder, 758 | sender: NodeIdDecoder, 759 | _phantom: PhantomData, 760 | } 761 | impl Default for PruneMessageDecoder { 762 | fn default() -> Self { 763 | PruneMessageDecoder { 764 | destination: Default::default(), 765 | sender: Default::default(), 766 | _phantom: PhantomData, 767 | } 768 | } 769 | } 770 | impl Decode for PruneMessageDecoder { 771 | type Item = (LocalNodeId, PruneMessage); 772 | 773 | fn decode(&mut self, buf: &[u8], eos: Eos) -> Result { 774 | let mut offset = 0; 775 | bytecodec_try_decode!(self.destination, offset, buf, eos); 776 | bytecodec_try_decode!(self.sender, offset, buf, eos); 777 | Ok(offset) 778 | } 779 | 780 | fn finish_decoding(&mut self) -> Result { 781 | let destination = track!(self.destination.finish_decoding())?; 782 | let sender = track!(self.sender.finish_decoding())?; 783 | 784 | let message = PruneMessage { sender }; 785 | Ok((destination, message)) 786 | } 787 | 788 | fn requiring_bytes(&self) -> ByteCount { 789 | self.destination 790 | .requiring_bytes() 791 | .add_for_decoding(self.sender.requiring_bytes()) 792 | } 793 | 794 | fn is_idle(&self) -> bool { 795 | self.sender.is_idle() 796 | } 797 | } 798 | 799 | #[derive(Debug)] 800 | pub struct PruneMessageEncoder { 801 | destination: LocalNodeIdEncoder, 802 | sender: NodeIdEncoder, 803 | _phantom: PhantomData, 804 | } 805 | impl Default for PruneMessageEncoder { 806 | fn default() -> Self { 807 | PruneMessageEncoder { 808 | destination: Default::default(), 809 | sender: Default::default(), 810 | _phantom: PhantomData, 811 | } 812 | } 813 | } 814 | impl Encode for PruneMessageEncoder { 815 | type Item = (LocalNodeId, PruneMessage); 816 | 817 | fn encode(&mut self, buf: &mut [u8], eos: Eos) -> Result { 818 | let mut offset = 0; 819 | bytecodec_try_encode!(self.destination, offset, buf, eos); 820 | bytecodec_try_encode!(self.sender, offset, buf, eos); 821 | Ok(offset) 822 | } 823 | 824 | fn start_encoding(&mut self, item: Self::Item) -> Result<()> { 825 | track!(self.destination.start_encoding(item.0))?; 826 | track!(self.sender.start_encoding(item.1.sender))?; 827 | Ok(()) 828 | } 829 | 830 | fn requiring_bytes(&self) -> ByteCount { 831 | ByteCount::Finite(self.exact_requiring_bytes()) 832 | } 833 | 834 | fn is_idle(&self) -> bool { 835 | self.sender.is_idle() 836 | } 837 | } 838 | impl SizedEncode for PruneMessageEncoder { 839 | fn exact_requiring_bytes(&self) -> u64 { 840 | self.destination.exact_requiring_bytes() + self.sender.exact_requiring_bytes() 841 | } 842 | } 843 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use trackable::error::{ErrorKind as TrackableErrorKind, ErrorKindExt, TrackableError}; 2 | 3 | /// This crate specific `Error` type. 4 | #[derive(Debug, Clone, TrackableError)] 5 | pub struct Error(TrackableError); 6 | impl From for Error { 7 | fn from(f: std::sync::mpsc::RecvError) -> Self { 8 | ErrorKind::Other.cause(f).into() 9 | } 10 | } 11 | impl From for Error { 12 | fn from(f: fibers_rpc::Error) -> Self { 13 | let kind = match f.kind() { 14 | fibers_rpc::ErrorKind::InvalidInput => ErrorKind::InvalidInput, 15 | fibers_rpc::ErrorKind::Timeout 16 | | fibers_rpc::ErrorKind::Unavailable 17 | | fibers_rpc::ErrorKind::Other => ErrorKind::Other, 18 | }; 19 | let rpc_error_kind = *f.kind(); 20 | track!(kind.takes_over(f); rpc_error_kind).into() 21 | } 22 | } 23 | 24 | /// Possible error kinds. 25 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 26 | pub enum ErrorKind { 27 | /// Input is invalid. 28 | InvalidInput, 29 | 30 | /// Inconsistent state. 31 | /// 32 | /// There are probably bugs in the program. 33 | InconsistentState, 34 | 35 | /// Other errors. 36 | Other, 37 | } 38 | impl TrackableErrorKind for ErrorKind {} 39 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A message broadcasting library based on the Plumtree/HyParView algorithms. 2 | //! 3 | //! # Properties 4 | //! 5 | //! ## Pros 6 | //! 7 | //! - Nearly optimal message transmitting count 8 | //! - Usually messages are broadcasted via a spanning tree 9 | //! - Only the nodes interested in the same messages belong to the same cluster 10 | //! - Scalable 11 | //! - Theoretically, it can handle ten-thousand of nodes or more 12 | //! - High fault tolerance 13 | //! - Spanning trees are automatically repaired if there are crashed nodes 14 | //! - Dynamic membership 15 | //! - Nodes can be added to (removed from) a cluster at any time 16 | //! 17 | //! ## Cons 18 | //! 19 | //! - No strong guarantee about connectivity of the nodes in a cluster 20 | //! - No strong guarantee about delivery count of a message 21 | //! - No guarantee about messages delivery order 22 | //! 23 | //! If some of the above guarantees are mandatory for your application, 24 | //! it is need to be provided by upper layers. 25 | //! 26 | //! # References 27 | //! 28 | //! - [HyParView: a membership protocol for reliable gossip-based broadcast][HyParView] 29 | //! - [Plumtree: Epidemic Broadcast Trees][Plumtree] 30 | //! 31 | //! [HyParView]: http://asc.di.fct.unl.pt/~jleitao/pdf/dsn07-leitao.pdf 32 | //! [Plumtree]: http://www.gsd.inesc-id.pt/~ler/reports/srds07.pdf 33 | #![warn(missing_docs)] 34 | #[macro_use] 35 | extern crate bytecodec; 36 | #[macro_use] 37 | extern crate slog; 38 | #[macro_use] 39 | extern crate trackable; 40 | 41 | pub use error::{Error, ErrorKind}; 42 | 43 | mod codec; 44 | mod error; 45 | mod node_id; 46 | mod node_id_generator; 47 | mod rpc; 48 | 49 | pub mod message; 50 | pub mod metrics; 51 | pub mod misc; 52 | pub mod node; 53 | pub mod service; 54 | 55 | /// This crate specific `Result` type. 56 | pub type Result = std::result::Result; 57 | 58 | #[cfg(test)] 59 | mod tests { 60 | use crate::node::{Node, SerialLocalNodeIdGenerator}; 61 | use crate::service::Service; 62 | use fibers::Spawn; 63 | use futures::{Future, Stream}; 64 | 65 | #[test] 66 | fn it_works() { 67 | let server_addr = "127.0.0.1:12121".parse().unwrap(); 68 | let service = Service::::new( 69 | server_addr, 70 | fibers_global::handle(), 71 | SerialLocalNodeIdGenerator::new(), 72 | ); 73 | let service_handle = service.handle(); 74 | fibers_global::spawn(service.map_err(|e| panic!("{}", e))); 75 | 76 | let mut fibers = Vec::new(); 77 | let mut first_node_id = None; 78 | for i in 0..100 { 79 | let mut node = Node::new(service_handle.clone()); 80 | if let Some(id) = first_node_id { 81 | node.join(id); 82 | } else { 83 | first_node_id = Some(node.id()); 84 | } 85 | if i == 99 { 86 | node.broadcast("hello".to_owned()); 87 | } 88 | let spawner = fibers_global::handle(); 89 | let fiber = fibers_global::spawn_monitor( 90 | node.into_future() 91 | .map(move |(message, stream)| { 92 | spawner.spawn(stream.for_each(|_| Ok(())).map_err(|_| ())); 93 | message.map(|m| m.into_payload()) 94 | }) 95 | .map_err(|(e, _)| e), 96 | ); 97 | fibers.push(fiber); 98 | } 99 | 100 | for fiber in fibers { 101 | match fibers_global::execute(fiber) { 102 | Err(e) => panic!("{}", e), 103 | Ok(message) => { 104 | assert_eq!(message, Some("hello".to_owned())); 105 | } 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/message.rs: -------------------------------------------------------------------------------- 1 | //! [`Message`] and related components. 2 | //! 3 | //! [`Message`]: ./struct.Message.html 4 | use crate::misc::PlumtreeAppMessage; 5 | use crate::node::NodeId; 6 | use bytecodec::bytes::{BytesEncoder, RemainingBytesDecoder, Utf8Decoder, Utf8Encoder}; 7 | use bytecodec::{Decode, Encode}; 8 | 9 | /// Broadcasted application message. 10 | #[derive(Debug, Clone)] 11 | pub struct Message(PlumtreeAppMessage); 12 | impl Message { 13 | /// Returns a reference to the identifier of the message. 14 | pub fn id(&self) -> &MessageId { 15 | &self.0.id 16 | } 17 | 18 | /// Returns a reference to the payload of the message. 19 | pub fn payload(&self) -> &T { 20 | &self.0.payload 21 | } 22 | 23 | /// Returns a mutable reference to the payload of the message. 24 | pub fn payload_mut(&mut self) -> &mut T { 25 | &mut self.0.payload 26 | } 27 | 28 | /// Takes the ownership of the message, and returns its payload. 29 | pub fn into_payload(self) -> T { 30 | self.0.payload 31 | } 32 | 33 | pub(crate) fn new(message: PlumtreeAppMessage) -> Self { 34 | Message(message) 35 | } 36 | } 37 | 38 | /// Message identifier. 39 | /// 40 | /// An identifier consists of the node identifier part and the sequence number part. 41 | /// The node identifier part which type is [`NodeId`] indicates the sender (origin) of the message. 42 | /// The sequence number part indicates the number of messages broadcasted by the sender so far. 43 | /// 44 | /// Identifiers are assigned automatically when broadcasting messages. 45 | /// 46 | /// It is guaranteed that the identifiers are unique in a cluster 47 | /// unless the OS processes executing plumcast nodes are restarted. 48 | /// Practically confliction of identifiers is extremely rare 49 | /// even if OS processes are frequently restarted. 50 | /// 51 | /// [`NodeId`]: ../node/struct.NodeId.html 52 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 53 | pub struct MessageId { 54 | node: NodeId, 55 | seqno: u64, 56 | } 57 | impl MessageId { 58 | /// Returns the node identifier part of the message identifier. 59 | pub fn node(&self) -> NodeId { 60 | self.node 61 | } 62 | 63 | /// Returns the sequence number part of the message identifier. 64 | pub fn seqno(&self) -> u64 { 65 | self.seqno 66 | } 67 | 68 | pub(crate) fn new(node: NodeId, seqno: u64) -> Self { 69 | MessageId { node, seqno } 70 | } 71 | } 72 | 73 | /// This trait allows the implementations to be used as the payload of broadcasting messages. 74 | pub trait MessagePayload: Sized + Clone + Send + 'static { 75 | /// Payload encoder. 76 | /// 77 | /// This is used to serialize payload for transmitting to remote nodes. 78 | type Encoder: Encode + Default + Send + 'static; 79 | 80 | /// Payload decoder. 81 | /// 82 | /// This is used to deserialize payload from octets received from remote nodes. 83 | type Decoder: Decode + Default + Send + 'static; 84 | } 85 | impl MessagePayload for Vec { 86 | type Encoder = BytesEncoder>; 87 | type Decoder = RemainingBytesDecoder; 88 | } 89 | impl MessagePayload for String { 90 | type Encoder = Utf8Encoder; 91 | type Decoder = Utf8Decoder; 92 | } 93 | -------------------------------------------------------------------------------- /src/metrics.rs: -------------------------------------------------------------------------------- 1 | //! [Prometheus][prometheus] metrics. 2 | //! 3 | //! Note that you can also use [fibers_rpc's metrics] in addition to the metrics defined in this module. 4 | //! 5 | //! [prometheus]: https://prometheus.io/ 6 | //! [fibers_rpc's metrics]: https://docs.rs/fibers_rpc/0.2/fibers_rpc/metrics/index.html 7 | use prometrics::metrics::{Counter, MetricBuilder}; 8 | 9 | /// Metrics of a [`Service`]. 10 | /// 11 | /// [`Service`]: ../service/struct.Service.html 12 | #[derive(Debug, Clone)] 13 | pub struct ServiceMetrics { 14 | pub(crate) registered_nodes: Counter, 15 | pub(crate) deregistered_nodes: Counter, 16 | pub(crate) destination_unknown_messages: Counter, 17 | } 18 | impl ServiceMetrics { 19 | /// Metric: `plumcast_service_registered_nodes_total ` 20 | pub fn registered_nodes(&self) -> u64 { 21 | self.registered_nodes.value() as u64 22 | } 23 | 24 | /// Metric: `plumcast_service_deregistered_nodes_total ` 25 | pub fn deregistered_nodes(&self) -> u64 { 26 | self.deregistered_nodes.value() as u64 27 | } 28 | 29 | /// Metric: `plumcast_service_destination_unknown_messages_total ` 30 | pub fn destination_unknown_messages(&self) -> u64 { 31 | self.destination_unknown_messages.value() as u64 32 | } 33 | 34 | pub(crate) fn new(mut builder: MetricBuilder) -> Self { 35 | builder.namespace("plumcast").subsystem("service"); 36 | ServiceMetrics { 37 | registered_nodes: builder 38 | .counter("registered_nodes_total") 39 | .help("Number of nodes registered so far") 40 | .finish() 41 | .expect("Never fails"), 42 | deregistered_nodes: builder 43 | .counter("deregistered_nodes_total") 44 | .help("Number of nodes deregistered so far") 45 | .finish() 46 | .expect("Never fails"), 47 | destination_unknown_messages: builder 48 | .counter("destination_unknown_messages_total") 49 | .help("Number of RPC messages received but the destination node is missing") 50 | .finish() 51 | .expect("Never fails"), 52 | } 53 | } 54 | } 55 | 56 | /// Metrics of a [`Node`]. 57 | /// 58 | /// [`Node`]: ../node/struct.Node.html 59 | #[derive(Debug, Clone)] 60 | pub struct NodeMetrics { 61 | pub(crate) broadcasted_messages: Counter, 62 | pub(crate) forgot_messages: Counter, 63 | pub(crate) delivered_messages: Counter, 64 | pub(crate) connected_neighbors: Counter, 65 | pub(crate) disconnected_neighbors: Counter, 66 | pub(crate) isolated_times: Counter, 67 | pub(crate) deisolated_times: Counter, 68 | pub(crate) forget_unknown_message_errors: Counter, 69 | pub(crate) cannot_send_hyparview_message_errors: Counter, 70 | pub(crate) cannot_send_plumtree_message_errors: Counter, 71 | pub(crate) unknown_plumtree_node_errors: Counter, 72 | } 73 | impl NodeMetrics { 74 | /// Metric: `plumcast_node_broadcasted_messages_total ` 75 | pub fn broadcasted_messages(&self) -> u64 { 76 | self.broadcasted_messages.value() as u64 77 | } 78 | 79 | /// Metric: `plumcast_node_forgot_messages_total ` 80 | pub fn forgot_messages(&self) -> u64 { 81 | self.forgot_messages.value() as u64 82 | } 83 | 84 | /// Metric: `plumcast_node_delivered_messages_total ` 85 | pub fn delivered_messages(&self) -> u64 { 86 | self.delivered_messages.value() as u64 87 | } 88 | 89 | /// Metric: `plumcast_node_connected_neighbors_total ` 90 | pub fn connected_neighbors(&self) -> u64 { 91 | self.connected_neighbors.value() as u64 92 | } 93 | 94 | /// Metric: `plumcast_node_disconnected_neighbors_total ` 95 | pub fn disconnected_neighbors(&self) -> u64 { 96 | self.disconnected_neighbors.value() as u64 97 | } 98 | 99 | /// Metric: `plumcast_node_isolated_times_total ` 100 | pub fn isolated_times(&self) -> u64 { 101 | self.isolated_times.value() as u64 102 | } 103 | 104 | /// Metric: `plumcast_node_deisolated_times_total ` 105 | pub fn deisolated_times(&self) -> u64 { 106 | self.deisolated_times.value() as u64 107 | } 108 | 109 | /// Metric: `plumcast_node_errors_total { kind="forget_unknown_message" } ` 110 | pub fn forget_unknown_message_errors(&self) -> u64 { 111 | self.forget_unknown_message_errors.value() as u64 112 | } 113 | 114 | /// Metric: `plumcast_node_errors_total { kind="cannot_send_hyparview_message" } ` 115 | pub fn cannot_send_hyparview_message_errors(&self) -> u64 { 116 | self.cannot_send_hyparview_message_errors.value() as u64 117 | } 118 | 119 | /// Metric: `plumcast_node_errors_total { kind="cannot_send_plumtree_message" } ` 120 | pub fn cannot_send_plumtree_message_errors(&self) -> u64 { 121 | self.cannot_send_plumtree_message_errors.value() as u64 122 | } 123 | 124 | /// Metric: `plumcast_node_errors_total { kind="unknown_plumtree_node" } ` 125 | pub fn unknown_plumtree_node_errors(&self) -> u64 { 126 | self.unknown_plumtree_node_errors.value() as u64 127 | } 128 | 129 | pub(crate) fn new(mut builder: MetricBuilder) -> Self { 130 | builder.namespace("plumcast").subsystem("node"); 131 | NodeMetrics { 132 | broadcasted_messages: builder 133 | .counter("broadcasted_messages_total") 134 | .help("Number of messages broadcasted so far") 135 | .finish() 136 | .expect("Never fails"), 137 | forgot_messages: builder 138 | .counter("forgot_messages_total") 139 | .help("Number of messages forgot so far") 140 | .finish() 141 | .expect("Never fails"), 142 | delivered_messages: builder 143 | .counter("delivered_messages_total") 144 | .help("Number of messages delivered so far") 145 | .finish() 146 | .expect("Never fails"), 147 | connected_neighbors: builder 148 | .counter("connected_neighbors_total") 149 | .help("Number of neighbors connected so far") 150 | .finish() 151 | .expect("Never fails"), 152 | disconnected_neighbors: builder 153 | .counter("disconnected_neighbors_total") 154 | .help("Number of neighbors disconnected so far") 155 | .finish() 156 | .expect("Never fails"), 157 | isolated_times: builder 158 | .counter("isolated_times_total") 159 | .help("Number of times the node was isolated so far") 160 | .finish() 161 | .expect("Never fails"), 162 | deisolated_times: builder 163 | .counter("deisolated_times_total") 164 | .help("Number of times the node was de-isolated so far") 165 | .finish() 166 | .expect("Never fails"), 167 | forget_unknown_message_errors: builder 168 | .counter("errors_total") 169 | .help("Number of errors happened so far") 170 | .label("kind", "forget_unknown_message") 171 | .finish() 172 | .expect("Never fails"), 173 | cannot_send_hyparview_message_errors: builder 174 | .counter("errors_total") 175 | .help("Number of errors happened so far") 176 | .label("kind", "cannot_send_hyparview_message") 177 | .finish() 178 | .expect("Never fails"), 179 | cannot_send_plumtree_message_errors: builder 180 | .counter("errors_total") 181 | .help("Number of errors happened so far") 182 | .label("kind", "cannot_send_plumtree_message") 183 | .finish() 184 | .expect("Never fails"), 185 | unknown_plumtree_node_errors: builder 186 | .counter("errors_total") 187 | .help("Number of errors happened so far") 188 | .label("kind", "unknown_plumtree_node") 189 | .finish() 190 | .expect("Never fails"), 191 | } 192 | } 193 | 194 | pub(crate) fn add(&self, other: &Self) { 195 | self.broadcasted_messages 196 | .add_u64(other.broadcasted_messages()); 197 | self.forgot_messages.add_u64(other.forgot_messages()); 198 | self.delivered_messages.add_u64(other.delivered_messages()); 199 | self.connected_neighbors 200 | .add_u64(other.connected_neighbors()); 201 | self.disconnected_neighbors 202 | .add_u64(other.disconnected_neighbors()); 203 | self.isolated_times.add_u64(other.isolated_times()); 204 | self.deisolated_times.add_u64(other.deisolated_times()); 205 | self.forget_unknown_message_errors 206 | .add_u64(other.forget_unknown_message_errors()); 207 | self.cannot_send_hyparview_message_errors 208 | .add_u64(other.cannot_send_hyparview_message_errors()); 209 | self.cannot_send_plumtree_message_errors 210 | .add_u64(other.cannot_send_plumtree_message_errors()); 211 | self.unknown_plumtree_node_errors 212 | .add_u64(other.unknown_plumtree_node_errors()); 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /src/misc.rs: -------------------------------------------------------------------------------- 1 | //! Miscellaneous components. 2 | use crate::message::{MessageId, MessagePayload}; 3 | use crate::node::NodeId; 4 | use fibers::Spawn; 5 | use futures::Future; 6 | use hyparview; 7 | use plumtree; 8 | use rand::rngs::StdRng; 9 | use std::fmt; 10 | use std::marker::PhantomData; 11 | use std::sync::Arc; 12 | 13 | type ArcFn = Arc + Send>) + Send + Sync + 'static>; 14 | 15 | /// Sharable [`Spawn`]. 16 | /// 17 | /// [`Spawn`]: https://docs.rs/fibers/0.1/fibers/trait.Spawn.html 18 | #[derive(Clone)] 19 | pub struct ArcSpawn(ArcFn); 20 | impl ArcSpawn { 21 | pub(crate) fn new(inner: S) -> Self 22 | where 23 | S: Spawn + Send + Sync + 'static, 24 | { 25 | ArcSpawn(Arc::new(move |fiber| inner.spawn_boxed(fiber))) 26 | } 27 | } 28 | impl Spawn for ArcSpawn { 29 | fn spawn_boxed(&self, fiber: Box + Send>) { 30 | (self.0)(fiber); 31 | } 32 | } 33 | impl fmt::Debug for ArcSpawn { 34 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 35 | write!(f, "ArcSpawn(_)") 36 | } 37 | } 38 | 39 | /// HyParView node. 40 | pub type HyparviewNode = hyparview::Node; 41 | 42 | /// Options for HyParView nodes. 43 | pub type HyparviewNodeOptions = hyparview::NodeOptions; 44 | 45 | pub(crate) type HyparviewAction = hyparview::Action; 46 | 47 | pub(crate) type HyparviewMessage = hyparview::message::ProtocolMessage; 48 | pub(crate) type DisconnectMessage = hyparview::message::DisconnectMessage; 49 | pub(crate) type ForwardJoinMessage = hyparview::message::ForwardJoinMessage; 50 | pub(crate) type JoinMessage = hyparview::message::JoinMessage; 51 | pub(crate) type NeighborMessage = hyparview::message::NeighborMessage; 52 | pub(crate) type ShuffleMessage = hyparview::message::ShuffleMessage; 53 | pub(crate) type ShuffleReplyMessage = hyparview::message::ShuffleReplyMessage; 54 | 55 | /// Plumtree node. 56 | pub type PlumtreeNode = plumtree::Node>; 57 | 58 | /// Options for Plumtree nodes. 59 | pub type PlumtreeNodeOptions = plumtree::NodeOptions; 60 | 61 | pub(crate) type PlumtreeAction = plumtree::Action>; 62 | pub(crate) type PlumtreeAppMessage = plumtree::message::Message>; 63 | pub(crate) type PlumtreeMessage = plumtree::message::ProtocolMessage>; 64 | pub(crate) type GossipMessage = plumtree::message::GossipMessage>; 65 | pub(crate) type GraftMessage = plumtree::message::GraftMessage>; 66 | pub(crate) type IhaveMessage = plumtree::message::IhaveMessage>; 67 | pub(crate) type PruneMessage = plumtree::message::PruneMessage>; 68 | 69 | /// An implementation of [`plumtree::System`] trait specialised to this crate. 70 | /// 71 | /// [`plumtree::System`]: https://docs.rs/plumtree/0.1/plumtree/trait.System.html 72 | #[derive(Debug)] 73 | pub struct PlumtreeSystem(PhantomData); 74 | impl plumtree::System for PlumtreeSystem { 75 | type NodeId = NodeId; 76 | type MessageId = MessageId; 77 | type MessagePayload = M; 78 | } 79 | -------------------------------------------------------------------------------- /src/node.rs: -------------------------------------------------------------------------------- 1 | //! [`Node`] and related components. 2 | //! 3 | //! [`Node`]: ./node/struct.Node.html 4 | use crate::message::{Message, MessageId, MessagePayload}; 5 | use crate::metrics::NodeMetrics; 6 | use crate::misc::{ 7 | HyparviewAction, HyparviewNode, HyparviewNodeOptions, PlumtreeAction, PlumtreeNode, 8 | PlumtreeNodeOptions, 9 | }; 10 | use crate::rpc::RpcMessage; 11 | use crate::service::ServiceHandle; 12 | use crate::{Error, ErrorKind}; 13 | use fibers::sync::mpsc; 14 | use fibers::time::timer::{self, Timeout}; 15 | use futures::{Async, Future, Poll, Stream}; 16 | use plumtree::message::Message as PlumtreeAppMessage; 17 | use plumtree::time::{Clock, NodeTime}; 18 | use rand::rngs::StdRng; 19 | use rand::{self, Rng, SeedableRng}; 20 | use slog::{Discard, Logger}; 21 | use std::fmt; 22 | use std::time::Duration; 23 | 24 | pub use crate::node_id::{LocalNodeId, NodeId}; 25 | pub use crate::node_id_generator::{ 26 | GenerateLocalNodeId, SerialLocalNodeIdGenerator, UnixtimeLocalNodeIdGenerator, 27 | }; 28 | 29 | /// The builder of [`Node`]. 30 | /// 31 | /// [`Node`]: ./struct.Node.html 32 | #[derive(Debug, Clone)] 33 | pub struct NodeBuilder { 34 | logger: Logger, 35 | hyparview_options: HyparviewNodeOptions, 36 | plumtree_options: PlumtreeNodeOptions, 37 | params: Parameters, 38 | } 39 | impl NodeBuilder { 40 | /// Makes a new `NodeBuilder` instance with the default settings. 41 | pub fn new() -> Self { 42 | let params = Parameters { 43 | tick_interval: Duration::from_millis(200), 44 | hyparview_shuffle_interval: Duration::from_secs(300), 45 | hyparview_sync_active_view_interval: Duration::from_secs(60), 46 | hyparview_fill_active_view_interval: Duration::from_secs(30), 47 | }; 48 | NodeBuilder { 49 | logger: Logger::root(Discard, o!()), 50 | hyparview_options: HyparviewNodeOptions::default(), 51 | plumtree_options: PlumtreeNodeOptions::default(), 52 | params, 53 | } 54 | } 55 | 56 | /// Sets the logger used by the node. 57 | /// 58 | /// The default value is `Logger::root(Discard, o!())`. 59 | pub fn logger(&mut self, logger: Logger) -> &mut Self { 60 | self.logger = logger; 61 | self 62 | } 63 | 64 | /// Sets the unit of the node local [`Clock`]. 65 | /// 66 | /// The default value is `Duration::from_millis(200)`. 67 | pub fn tick_interval(&mut self, interval: Duration) -> &mut Self { 68 | self.params.tick_interval = interval; 69 | self 70 | } 71 | 72 | /// Sets the execution interval of `HyparviewNode::shuffle_passive_view()` method. 73 | /// 74 | /// The default value is `Duration::from_secs(300)`. 75 | pub fn hyparview_shuffle_interval(&mut self, interval: Duration) -> &mut Self { 76 | self.params.hyparview_shuffle_interval = interval; 77 | self 78 | } 79 | 80 | /// Sets the execution interval of `HyparviewNode::shuffle_passive_view()` method. 81 | /// 82 | /// The default value is `Duration::from_secs(60)`. 83 | pub fn hyparview_sync_active_view_interval(&mut self, interval: Duration) -> &mut Self { 84 | self.params.hyparview_sync_active_view_interval = interval; 85 | self 86 | } 87 | 88 | /// Sets the execution interval of `HyparviewNode::shuffle_passive_view()` method. 89 | /// 90 | /// The default value is `Duration::from_secs(30)`. 91 | pub fn hyparview_fill_active_view_interval(&mut self, interval: Duration) -> &mut Self { 92 | self.params.hyparview_fill_active_view_interval = interval; 93 | self 94 | } 95 | 96 | /// Sets the options for the underlying HyParView node. 97 | /// 98 | /// The default value is `HyparviewNodeOptions::default()`. 99 | pub fn hyparview_options(&mut self, options: HyparviewNodeOptions) -> &mut Self { 100 | self.hyparview_options = options; 101 | self 102 | } 103 | 104 | /// Sets the options for the underlying Plumtree node. 105 | /// 106 | /// The default value is `PlumtreeNodeOptions::default()`. 107 | pub fn plumtree_options(&mut self, options: PlumtreeNodeOptions) -> &mut Self { 108 | self.plumtree_options = options; 109 | self 110 | } 111 | 112 | /// Builds a [`Node`] instance with the specified settings. 113 | /// 114 | /// [`Node`]: ./struct.Node.html 115 | pub fn finish(&self, service: ServiceHandle) -> Node { 116 | let id = service.generate_node_id(); 117 | let logger = self.logger.new(o! {"node_id" => id.to_string()}); 118 | let metrics = NodeMetrics::new(service.metric_builder()); 119 | let (message_tx, message_rx) = mpsc::channel(); 120 | let handle = NodeHandle { 121 | local_id: id.local_id(), 122 | message_tx, 123 | metrics: metrics.clone(), 124 | }; 125 | let rng = StdRng::from_seed(rand::thread_rng().gen()); 126 | service.register_local_node(handle); 127 | 128 | let plumtree_node = PlumtreeNode::with_options(id, self.plumtree_options.clone()); 129 | let now = plumtree_node.clock().now(); 130 | let hyparview_shuffle_time = now + gen_interval(self.params.hyparview_shuffle_interval); 131 | let hyparview_sync_active_view_time = 132 | now + gen_interval(self.params.hyparview_sync_active_view_interval); 133 | let hyparview_fill_active_view_time = 134 | now + gen_interval(self.params.hyparview_fill_active_view_interval); 135 | Node { 136 | logger, 137 | service, 138 | message_rx, 139 | hyparview_node: HyparviewNode::with_options(id, rng, self.hyparview_options.clone()), 140 | plumtree_node, 141 | message_seqno: 0, 142 | hyparview_shuffle_time, 143 | hyparview_sync_active_view_time, 144 | hyparview_fill_active_view_time, 145 | tick_timeout: timer::timeout(self.params.tick_interval), 146 | params: self.params.clone(), 147 | metrics, 148 | } 149 | } 150 | } 151 | impl Default for NodeBuilder { 152 | fn default() -> Self { 153 | Self::new() 154 | } 155 | } 156 | 157 | /// Node that broadcasts and receives messages. 158 | #[derive(Debug)] 159 | #[must_use = "streams do nothing unless polled"] 160 | pub struct Node { 161 | logger: Logger, 162 | service: ServiceHandle, 163 | message_rx: mpsc::Receiver>, 164 | hyparview_node: HyparviewNode, 165 | plumtree_node: PlumtreeNode, 166 | message_seqno: u64, 167 | hyparview_shuffle_time: NodeTime, 168 | hyparview_sync_active_view_time: NodeTime, 169 | hyparview_fill_active_view_time: NodeTime, 170 | tick_timeout: Timeout, 171 | params: Parameters, 172 | metrics: NodeMetrics, 173 | } 174 | impl Node { 175 | /// Makes a new `Node` instance with the default settings. 176 | /// 177 | /// If you want to customize settings, please use [`NodeBuilder`] instead. 178 | /// 179 | /// [`NodeBuilder`]: ./struct.NodeBuilder.html 180 | pub fn new(service: ServiceHandle) -> Self { 181 | NodeBuilder::new().finish(service) 182 | } 183 | 184 | /// Returns the identifier of the node. 185 | pub fn id(&self) -> NodeId { 186 | *self.plumtree_node().id() 187 | } 188 | 189 | /// Joins the cluster to which the given contact node belongs. 190 | pub fn join(&mut self, contact_node: NodeId) { 191 | info!( 192 | self.logger, 193 | "Joins a cluster by contacting to {:?}", contact_node 194 | ); 195 | self.hyparview_node.join(contact_node); 196 | } 197 | 198 | /// Broadcasts a message. 199 | /// 200 | /// Note that the message will also be delivered to the sender node. 201 | pub fn broadcast(&mut self, message_payload: M) -> MessageId { 202 | let id = MessageId::new(self.id(), self.message_seqno); 203 | self.message_seqno += 1; 204 | debug!(self.logger, "Starts broadcasting a message: {:?}", id); 205 | 206 | let m = PlumtreeAppMessage { 207 | id, 208 | payload: message_payload, 209 | }; 210 | self.plumtree_node.broadcast_message(m); 211 | self.metrics.broadcasted_messages.increment(); 212 | id 213 | } 214 | 215 | /// Forgets the specified message. 216 | /// 217 | /// For preventing memory shortage, this method needs to be called appropriately. 218 | pub fn forget_message(&mut self, message_id: &MessageId) { 219 | if self.plumtree_node.forget_message(message_id) { 220 | self.metrics.forgot_messages.increment(); 221 | } else { 222 | self.metrics.forget_unknown_message_errors.increment(); 223 | } 224 | } 225 | 226 | /// Returns a reference to the underlying HyParView node. 227 | pub fn hyparview_node(&self) -> &HyparviewNode { 228 | &self.hyparview_node 229 | } 230 | 231 | /// Returns a reference to the underlying Plumtree node. 232 | pub fn plumtree_node(&self) -> &PlumtreeNode { 233 | &self.plumtree_node 234 | } 235 | 236 | /// Returns the clock of the node. 237 | pub fn clock(&self) -> &Clock { 238 | self.plumtree_node.clock() 239 | } 240 | 241 | /// Returns the metrics of the service. 242 | pub fn metrics(&self) -> &NodeMetrics { 243 | &self.metrics 244 | } 245 | 246 | fn handle_hyparview_action(&mut self, action: HyparviewAction) { 247 | use hyparview::{Action, Event}; 248 | 249 | match action { 250 | Action::Send { 251 | destination, 252 | message, 253 | } => { 254 | debug!( 255 | self.logger, 256 | "Sends a HyParView message to {:?}: {:?}", destination, message 257 | ); 258 | let message = RpcMessage::Hyparview(message); 259 | if let Err(e) = self.service.send_message(destination, message) { 260 | warn!( 261 | self.logger, 262 | "Cannot send a HyParView message to {:?}: {}", destination, e 263 | ); 264 | self.metrics 265 | .cannot_send_hyparview_message_errors 266 | .increment(); 267 | self.hyparview_node.disconnect(&destination, false); 268 | } 269 | } 270 | Action::Notify { event } => match event { 271 | Event::NeighborUp { node } => { 272 | info!( 273 | self.logger, 274 | "Neighbor up: {:?} (active_view={:?})", 275 | node, 276 | self.hyparview_node.active_view() 277 | ); 278 | self.metrics.connected_neighbors.increment(); 279 | self.plumtree_node.handle_neighbor_up(&node); 280 | if self.hyparview_node.active_view().len() == 1 { 281 | self.metrics.deisolated_times.increment(); 282 | } 283 | } 284 | Event::NeighborDown { node } => { 285 | info!( 286 | self.logger, 287 | "Neighbor down: {:?} (active_view={:?})", 288 | node, 289 | self.hyparview_node.active_view() 290 | ); 291 | self.metrics.disconnected_neighbors.increment(); 292 | self.plumtree_node.handle_neighbor_down(&node); 293 | if self.hyparview_node.active_view().is_empty() { 294 | self.metrics.isolated_times.increment(); 295 | } 296 | } 297 | }, 298 | Action::Disconnect { node } => { 299 | info!(self.logger, "Disconnected: {:?}", node); 300 | } 301 | } 302 | } 303 | 304 | fn handle_plumtree_action(&mut self, action: PlumtreeAction) -> Option> { 305 | use plumtree::Action; 306 | 307 | match action { 308 | Action::Send { 309 | destination, 310 | message, 311 | } => { 312 | debug!(self.logger, "Sends a Plumtree message to {:?}", destination,); 313 | let message = RpcMessage::Plumtree(message); 314 | if let Err(e) = self.service.send_message(destination, message) { 315 | warn!( 316 | self.logger, 317 | "Cannot send a Plumtree message to {:?}: {}", destination, e 318 | ); 319 | self.metrics.cannot_send_plumtree_message_errors.increment(); 320 | self.hyparview_node.disconnect(&destination, false); 321 | } 322 | None 323 | } 324 | Action::Deliver { message } => { 325 | debug!( 326 | self.logger, 327 | "Delivers an application message: {:?}", message.id 328 | ); 329 | self.metrics.delivered_messages.increment(); 330 | Some(Message::new(message)) 331 | } 332 | } 333 | } 334 | 335 | fn handle_rpc_message(&mut self, message: RpcMessage) -> bool { 336 | match message { 337 | RpcMessage::Hyparview(m) => { 338 | debug!(self.logger, "Received a HyParView message: {:?}", m); 339 | self.hyparview_node.handle_protocol_message(m); 340 | true 341 | } 342 | RpcMessage::Plumtree(m) => { 343 | debug!(self.logger, "Received a Plumtree message"); 344 | if !self.plumtree_node.handle_protocol_message(m) { 345 | self.metrics.unknown_plumtree_node_errors.increment(); 346 | } 347 | false 348 | } 349 | } 350 | } 351 | 352 | fn handle_tick(&mut self) { 353 | self.plumtree_node 354 | .clock_mut() 355 | .tick(self.params.tick_interval); 356 | 357 | let now = self.plumtree_node.clock().now(); 358 | if now >= self.hyparview_shuffle_time { 359 | self.hyparview_node.shuffle_passive_view(); 360 | self.hyparview_shuffle_time = 361 | now + gen_interval(self.params.hyparview_shuffle_interval); 362 | } 363 | if now >= self.hyparview_sync_active_view_time { 364 | self.hyparview_node.sync_active_view(); 365 | self.hyparview_sync_active_view_time = 366 | now + gen_interval(self.params.hyparview_sync_active_view_interval); 367 | } 368 | if now >= self.hyparview_fill_active_view_time { 369 | self.hyparview_node.fill_active_view(); 370 | self.hyparview_fill_active_view_time = 371 | now + gen_interval(self.params.hyparview_fill_active_view_interval); 372 | } 373 | } 374 | 375 | fn leave(&self) { 376 | use hyparview::message::{DisconnectMessage, ProtocolMessage}; 377 | 378 | info!( 379 | self.logger, 380 | "Leaves the current cluster: active_view={:?}", 381 | self.hyparview_node.active_view() 382 | ); 383 | for peer in self.hyparview_node.active_view().iter().cloned() { 384 | let message = DisconnectMessage { 385 | sender: self.id(), 386 | alive: false, 387 | }; 388 | let message = ProtocolMessage::Disconnect(message); 389 | let message = RpcMessage::Hyparview(message); 390 | let _ = self.service.send_message(peer, message); 391 | } 392 | } 393 | } 394 | impl Stream for Node { 395 | type Item = Message; 396 | type Error = Error; 397 | 398 | fn poll(&mut self) -> Poll, Self::Error> { 399 | while track!(self.tick_timeout.poll().map_err(Error::from))?.is_ready() { 400 | self.handle_tick(); 401 | self.tick_timeout = timer::timeout(self.params.tick_interval); 402 | } 403 | 404 | let mut did_something = true; 405 | while did_something { 406 | did_something = false; 407 | 408 | while let Some(action) = self.hyparview_node.poll_action() { 409 | self.handle_hyparview_action(action); 410 | did_something = true; 411 | } 412 | while let Some(action) = self.plumtree_node.poll_action() { 413 | if let Some(message) = self.handle_plumtree_action(action) { 414 | return Ok(Async::Ready(Some(message))); 415 | } 416 | did_something = true; 417 | } 418 | while let Async::Ready(message) = self.message_rx.poll().expect("Never fails") { 419 | did_something = true; 420 | let message = track_assert_some!(message, ErrorKind::Other, "Service down"); 421 | if self.handle_rpc_message(message) { 422 | break; 423 | } 424 | } 425 | } 426 | Ok(Async::NotReady) 427 | } 428 | } 429 | impl Drop for Node { 430 | fn drop(&mut self) { 431 | self.service.deregister_local_node(self.id().local_id()); 432 | 433 | let messages = self.metrics.delivered_messages() - self.metrics.forgot_messages(); 434 | self.metrics.forgot_messages.add_u64(messages); 435 | 436 | self.leave(); 437 | } 438 | } 439 | 440 | #[derive(Clone)] 441 | pub(crate) struct NodeHandle { 442 | local_id: LocalNodeId, 443 | message_tx: mpsc::Sender>, 444 | metrics: NodeMetrics, 445 | } 446 | impl fmt::Debug for NodeHandle { 447 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 448 | write!(f, "NodeHandle {{ local_id: {:?}, .. }}", self.local_id) 449 | } 450 | } 451 | impl NodeHandle { 452 | pub(crate) fn local_id(&self) -> LocalNodeId { 453 | self.local_id 454 | } 455 | 456 | pub(crate) fn send_rpc_message(&self, message: RpcMessage) { 457 | let _ = self.message_tx.send(message); 458 | } 459 | 460 | pub(crate) fn metrics(&self) -> &NodeMetrics { 461 | &self.metrics 462 | } 463 | } 464 | 465 | #[derive(Debug, Clone)] 466 | struct Parameters { 467 | tick_interval: Duration, 468 | hyparview_shuffle_interval: Duration, 469 | hyparview_sync_active_view_interval: Duration, 470 | hyparview_fill_active_view_interval: Duration, 471 | } 472 | 473 | fn gen_interval(base: Duration) -> Duration { 474 | let millis = base.as_secs() * 1000 + u64::from(base.subsec_millis()); 475 | let jitter = rand::random::() % (millis / 10); 476 | base + Duration::from_millis(jitter) 477 | } 478 | -------------------------------------------------------------------------------- /src/node_id.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "serialize")] 2 | use serde_derive::{Deserialize, Serialize}; 3 | use std::cmp::Ordering; 4 | use std::fmt; 5 | use std::net::SocketAddr; 6 | 7 | /// Identifier used for distinguish local nodes in a process. 8 | /// 9 | /// An identifier is assigned automatically to a new [`Node`] when it is created. 10 | /// 11 | /// [`Node`]: ./struct.Node.html 12 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 13 | #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))] 14 | pub struct LocalNodeId(u64); 15 | impl LocalNodeId { 16 | /// Makes a new `LocalNodeId` instance. 17 | pub fn new(id: u64) -> Self { 18 | LocalNodeId(id) 19 | } 20 | 21 | /// Returns the value of the identifier. 22 | pub fn value(self) -> u64 { 23 | self.0 24 | } 25 | } 26 | 27 | /// Identifier used for distinguish nodes in a cluster. 28 | /// 29 | /// The identifier of a [`Node`] consists of [`LocalNodeId`] of the node and 30 | /// the socket address of the RPC server used for communicating with the node. 31 | /// 32 | /// [`Node`]: ./struct.Node.html 33 | /// [`LocalNodeId`]: ./struct.LocalNodeId.html 34 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] 35 | #[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))] 36 | pub struct NodeId { 37 | address: SocketAddr, 38 | local_id: LocalNodeId, 39 | } 40 | impl NodeId { 41 | /// Makes a new `NodeId` instance. 42 | pub fn new(address: SocketAddr, local_id: LocalNodeId) -> Self { 43 | NodeId { address, local_id } 44 | } 45 | 46 | /// Returns the RPC server address part of the identifier. 47 | pub fn address(&self) -> SocketAddr { 48 | self.address 49 | } 50 | 51 | /// Returns the local node identifier part of the identifier. 52 | pub fn local_id(&self) -> LocalNodeId { 53 | self.local_id 54 | } 55 | } 56 | impl fmt::Debug for NodeId { 57 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 58 | write!(f, "NodeId({:?})", self.to_string()) 59 | } 60 | } 61 | impl fmt::Display for NodeId { 62 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 63 | write!(f, "{:08x}@{}", self.local_id.0, self.address) 64 | } 65 | } 66 | impl PartialOrd for NodeId { 67 | fn partial_cmp(&self, other: &Self) -> Option { 68 | Some(self.cmp(other)) 69 | } 70 | } 71 | impl Ord for NodeId { 72 | fn cmp(&self, other: &Self) -> Ordering { 73 | self.address 74 | .ip() 75 | .cmp(&other.address.ip()) 76 | .then_with(|| self.address.port().cmp(&other.address.port())) 77 | .then_with(|| self.local_id.cmp(&other.local_id)) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/node_id_generator.rs: -------------------------------------------------------------------------------- 1 | use crate::node::LocalNodeId; 2 | use std::fmt; 3 | use std::sync::atomic::{AtomicUsize, Ordering}; 4 | use std::sync::Arc; 5 | use std::time::UNIX_EPOCH; 6 | 7 | /// This trait allows for generating the identifiers of the local nodes that belong to a [`Service`]. 8 | /// 9 | /// [`Service`]: ../service/struct.Service.html 10 | pub trait GenerateLocalNodeId: Send + Sync + 'static { 11 | /// Generates an identifier that will be assigned to a new local node that belongs to a [`Service`]. 12 | /// 13 | /// [`Service`]: ../service/struct.Service.html 14 | fn generate_local_node_id(&self) -> LocalNodeId; 15 | } 16 | 17 | #[derive(Clone)] 18 | pub(crate) struct ArcLocalNodeIdGenerator(Arc); 19 | impl ArcLocalNodeIdGenerator { 20 | pub(crate) fn new(inner: T) -> Self { 21 | ArcLocalNodeIdGenerator(Arc::new(inner)) 22 | } 23 | } 24 | impl fmt::Debug for ArcLocalNodeIdGenerator { 25 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 26 | write!(f, "ArcLocalNodeIdGenerator(_)") 27 | } 28 | } 29 | impl GenerateLocalNodeId for ArcLocalNodeIdGenerator { 30 | fn generate_local_node_id(&self) -> LocalNodeId { 31 | self.0.generate_local_node_id() 32 | } 33 | } 34 | 35 | /// An implementation of [`GenerateLocalNodeId`] that generates serial number identifiers. 36 | /// 37 | /// [`GenerateLocalNodeId`]: ./trait.GenerateLocalNodeId.html 38 | #[derive(Debug, Default)] 39 | pub struct SerialLocalNodeIdGenerator { 40 | next_id: AtomicUsize, 41 | } 42 | impl SerialLocalNodeIdGenerator { 43 | /// Makes a new `SerialLocalNodeIdGenerator` instance. 44 | /// 45 | /// # Examples 46 | /// 47 | /// ``` 48 | /// use plumcast::node::{GenerateLocalNodeId, SerialLocalNodeIdGenerator}; 49 | /// 50 | /// let mut generator = SerialLocalNodeIdGenerator::new(); 51 | /// assert_eq!(generator.generate_local_node_id().value(), 0); 52 | /// assert_eq!(generator.generate_local_node_id().value(), 1); 53 | /// assert_eq!(generator.generate_local_node_id().value(), 2); 54 | /// ``` 55 | pub fn new() -> Self { 56 | Self::default() 57 | } 58 | 59 | /// Makes a new `SerialLocalNodeIdGenerator` instance with the given start number. 60 | /// 61 | /// # Examples 62 | /// 63 | /// ``` 64 | /// use plumcast::node::{GenerateLocalNodeId, SerialLocalNodeIdGenerator}; 65 | /// 66 | /// let mut generator = SerialLocalNodeIdGenerator::with_offset(std::u64::MAX); 67 | /// assert_eq!(generator.generate_local_node_id().value(), std::u64::MAX); 68 | /// assert_eq!(generator.generate_local_node_id().value(), 0); 69 | /// assert_eq!(generator.generate_local_node_id().value(), 1); 70 | /// ``` 71 | pub fn with_offset(start_number: u64) -> Self { 72 | SerialLocalNodeIdGenerator { 73 | next_id: AtomicUsize::new(start_number as usize), 74 | } 75 | } 76 | } 77 | impl GenerateLocalNodeId for SerialLocalNodeIdGenerator { 78 | fn generate_local_node_id(&self) -> LocalNodeId { 79 | let id = self.next_id.fetch_add(1, Ordering::SeqCst); 80 | LocalNodeId::new(id as u64) 81 | } 82 | } 83 | 84 | /// An implementation of [`GenerateLocalNodeId`] that generates identifiers based on UNIX time in nanoseconds. 85 | /// 86 | /// [`GenerateLocalNodeId`]: ./trait.GenerateLocalNodeId.html 87 | #[derive(Debug, Default)] 88 | pub struct UnixtimeLocalNodeIdGenerator { 89 | nanos: AtomicUsize, 90 | } 91 | impl UnixtimeLocalNodeIdGenerator { 92 | /// Makes a new `UnixtimeLocalNodeIdGenerator` instance. 93 | pub fn new() -> Self { 94 | Self::default() 95 | } 96 | } 97 | impl GenerateLocalNodeId for UnixtimeLocalNodeIdGenerator { 98 | fn generate_local_node_id(&self) -> LocalNodeId { 99 | match UNIX_EPOCH.elapsed() { 100 | Err(e) => panic!("{}", e), 101 | Ok(d) => { 102 | let nanos = self.nanos.fetch_add(1, Ordering::SeqCst) as u64 % 1_000; 103 | let micros = u64::from(d.subsec_micros()) * 1_000; 104 | let id = d.as_secs() * 1_000_000_000 + micros + nanos; 105 | LocalNodeId::new(id) 106 | } 107 | } 108 | } 109 | } 110 | 111 | #[cfg(test)] 112 | mod tests { 113 | use std; 114 | 115 | use super::*; 116 | 117 | #[test] 118 | fn serial_id_generator_works() { 119 | let generator = SerialLocalNodeIdGenerator::new(); 120 | assert_eq!(generator.generate_local_node_id().value(), 0); 121 | assert_eq!(generator.generate_local_node_id().value(), 1); 122 | assert_eq!(generator.generate_local_node_id().value(), 2); 123 | 124 | let generator = SerialLocalNodeIdGenerator::with_offset(std::u64::MAX); 125 | assert_eq!(generator.generate_local_node_id().value(), std::u64::MAX); 126 | assert_eq!(generator.generate_local_node_id().value(), 0); 127 | assert_eq!(generator.generate_local_node_id().value(), 1); 128 | } 129 | 130 | #[test] 131 | fn unixtime_id_generator_works() { 132 | let generator = UnixtimeLocalNodeIdGenerator::new(); 133 | let id0 = generator.generate_local_node_id(); 134 | std::thread::sleep(std::time::Duration::from_millis(1)); 135 | let id1 = generator.generate_local_node_id(); 136 | assert_ne!(id0, id1); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/rpc/hyparview.rs: -------------------------------------------------------------------------------- 1 | use super::RpcMessage; 2 | use crate::codec::hyparview::{ 3 | DisconnectMessageDecoder, DisconnectMessageEncoder, ForwardJoinMessageDecoder, 4 | ForwardJoinMessageEncoder, JoinMessageDecoder, JoinMessageEncoder, NeighborMessageDecoder, 5 | NeighborMessageEncoder, ShuffleMessageDecoder, ShuffleMessageEncoder, 6 | ShuffleReplyMessageDecoder, ShuffleReplyMessageEncoder, 7 | }; 8 | use crate::message::MessagePayload; 9 | use crate::misc::{ 10 | DisconnectMessage, ForwardJoinMessage, JoinMessage, NeighborMessage, ShuffleMessage, 11 | ShuffleReplyMessage, 12 | }; 13 | use crate::node::{LocalNodeId, NodeId}; 14 | use crate::service::ServiceHandle; 15 | use crate::Result; 16 | use fibers_rpc::client::ClientServiceHandle; 17 | use fibers_rpc::server::{HandleCast, NoReply, ServerBuilder}; 18 | use fibers_rpc::{Cast, ProcedureId}; 19 | 20 | pub fn register_handlers(rpc: &mut ServerBuilder, service: &ServiceHandle) { 21 | rpc.add_cast_handler(JoinHandler(service.clone())); 22 | rpc.add_cast_handler(ForwardJoinHandler(service.clone())); 23 | rpc.add_cast_handler(NeighborHandler(service.clone())); 24 | rpc.add_cast_handler(ShuffleHandler(service.clone())); 25 | rpc.add_cast_handler(ShuffleReplyHandler(service.clone())); 26 | rpc.add_cast_handler(DisconnectHandler(service.clone())); 27 | } 28 | 29 | #[derive(Debug)] 30 | pub struct JoinCast; 31 | impl Cast for JoinCast { 32 | const ID: ProcedureId = ProcedureId(0x17CC_0000); 33 | const NAME: &'static str = "hyparview.join"; 34 | 35 | type Notification = (LocalNodeId, JoinMessage); 36 | type Decoder = JoinMessageDecoder; 37 | type Encoder = JoinMessageEncoder; 38 | } 39 | 40 | pub fn join_cast(peer: NodeId, m: JoinMessage, service: &ClientServiceHandle) -> Result<()> { 41 | let mut client = JoinCast::client(service); 42 | client.options_mut().force_wakeup = true; 43 | client.options_mut().priority = 100; 44 | track!(client.cast(peer.address(), (peer.local_id(), m)))?; 45 | Ok(()) 46 | } 47 | 48 | #[derive(Debug)] 49 | struct JoinHandler(ServiceHandle); 50 | impl HandleCast for JoinHandler { 51 | fn handle_cast(&self, (id, m): (LocalNodeId, JoinMessage)) -> NoReply { 52 | if let Some(node) = self.0.get_local_node_or_disconnect(id, &m.sender) { 53 | node.send_rpc_message(RpcMessage::Hyparview(m.into())); 54 | } 55 | NoReply::done() 56 | } 57 | } 58 | 59 | #[derive(Debug)] 60 | pub struct ForwardJoinCast; 61 | impl Cast for ForwardJoinCast { 62 | const ID: ProcedureId = ProcedureId(0x17CC_0001); 63 | const NAME: &'static str = "hyparview.forward_join"; 64 | 65 | type Notification = (LocalNodeId, ForwardJoinMessage); 66 | type Decoder = ForwardJoinMessageDecoder; 67 | type Encoder = ForwardJoinMessageEncoder; 68 | } 69 | 70 | pub fn forward_join_cast( 71 | peer: NodeId, 72 | m: ForwardJoinMessage, 73 | service: &ClientServiceHandle, 74 | ) -> Result<()> { 75 | let mut client = ForwardJoinCast::client(service); 76 | client.options_mut().force_wakeup = true; 77 | client.options_mut().priority = 100; 78 | track!(client.cast(peer.address(), (peer.local_id(), m)))?; 79 | Ok(()) 80 | } 81 | 82 | #[derive(Debug)] 83 | struct ForwardJoinHandler(ServiceHandle); 84 | impl HandleCast for ForwardJoinHandler { 85 | fn handle_cast(&self, (id, m): (LocalNodeId, ForwardJoinMessage)) -> NoReply { 86 | if let Some(node) = self.0.get_local_node_or_disconnect(id, &m.sender) { 87 | node.send_rpc_message(RpcMessage::Hyparview(m.into())); 88 | } 89 | NoReply::done() 90 | } 91 | } 92 | 93 | #[derive(Debug)] 94 | pub struct NeighborCast; 95 | impl Cast for NeighborCast { 96 | const ID: ProcedureId = ProcedureId(0x17CC_0002); 97 | const NAME: &'static str = "hyparview.neighbor"; 98 | 99 | type Notification = (LocalNodeId, NeighborMessage); 100 | type Decoder = NeighborMessageDecoder; 101 | type Encoder = NeighborMessageEncoder; 102 | } 103 | 104 | pub fn neighbor_cast( 105 | peer: NodeId, 106 | m: NeighborMessage, 107 | service: &ClientServiceHandle, 108 | ) -> Result<()> { 109 | let mut client = NeighborCast::client(service); 110 | client.options_mut().force_wakeup = true; 111 | client.options_mut().priority = 100; 112 | track!(client.cast(peer.address(), (peer.local_id(), m)))?; 113 | Ok(()) 114 | } 115 | 116 | #[derive(Debug)] 117 | struct NeighborHandler(ServiceHandle); 118 | impl HandleCast for NeighborHandler { 119 | fn handle_cast(&self, (id, m): (LocalNodeId, NeighborMessage)) -> NoReply { 120 | if let Some(node) = self.0.get_local_node_or_disconnect(id, &m.sender) { 121 | node.send_rpc_message(RpcMessage::Hyparview(m.into())); 122 | } 123 | NoReply::done() 124 | } 125 | } 126 | 127 | #[derive(Debug)] 128 | pub struct ShuffleCast; 129 | impl Cast for ShuffleCast { 130 | const ID: ProcedureId = ProcedureId(0x17CC_0003); 131 | const NAME: &'static str = "hyparview.shuffle"; 132 | 133 | type Notification = (LocalNodeId, ShuffleMessage); 134 | type Decoder = ShuffleMessageDecoder; 135 | type Encoder = ShuffleMessageEncoder; 136 | } 137 | 138 | pub fn shuffle_cast(peer: NodeId, m: ShuffleMessage, service: &ClientServiceHandle) -> Result<()> { 139 | let mut client = ShuffleCast::client(service); 140 | client.options_mut().priority = 200; 141 | track!(client.cast(peer.address(), (peer.local_id(), m)))?; 142 | Ok(()) 143 | } 144 | 145 | #[derive(Debug)] 146 | struct ShuffleHandler(ServiceHandle); 147 | impl HandleCast for ShuffleHandler { 148 | fn handle_cast(&self, (id, m): (LocalNodeId, ShuffleMessage)) -> NoReply { 149 | if let Some(node) = self.0.get_local_node_or_disconnect(id, &m.sender) { 150 | node.send_rpc_message(RpcMessage::Hyparview(m.into())); 151 | } 152 | NoReply::done() 153 | } 154 | } 155 | 156 | #[derive(Debug)] 157 | pub struct ShuffleReplyCast; 158 | impl Cast for ShuffleReplyCast { 159 | const ID: ProcedureId = ProcedureId(0x17CC_0004); 160 | const NAME: &'static str = "hyparview.shuffle_reply"; 161 | 162 | type Notification = (LocalNodeId, ShuffleReplyMessage); 163 | type Decoder = ShuffleReplyMessageDecoder; 164 | type Encoder = ShuffleReplyMessageEncoder; 165 | } 166 | 167 | pub fn shuffle_reply_cast( 168 | peer: NodeId, 169 | m: ShuffleReplyMessage, 170 | service: &ClientServiceHandle, 171 | ) -> Result<()> { 172 | let mut client = ShuffleReplyCast::client(service); 173 | client.options_mut().priority = 200; 174 | track!(client.cast(peer.address(), (peer.local_id(), m)))?; 175 | Ok(()) 176 | } 177 | 178 | #[derive(Debug)] 179 | struct ShuffleReplyHandler(ServiceHandle); 180 | impl HandleCast for ShuffleReplyHandler { 181 | fn handle_cast(&self, (id, m): (LocalNodeId, ShuffleReplyMessage)) -> NoReply { 182 | if let Some(node) = self.0.get_local_node_or_disconnect(id, &m.sender) { 183 | node.send_rpc_message(RpcMessage::Hyparview(m.into())); 184 | } 185 | NoReply::done() 186 | } 187 | } 188 | 189 | #[derive(Debug)] 190 | pub struct DisconnectCast; 191 | impl Cast for DisconnectCast { 192 | const ID: ProcedureId = ProcedureId(0x17CC_0005); 193 | const NAME: &'static str = "hyparview.disconnect"; 194 | 195 | type Notification = (LocalNodeId, DisconnectMessage); 196 | type Decoder = DisconnectMessageDecoder; 197 | type Encoder = DisconnectMessageEncoder; 198 | } 199 | 200 | pub fn disconnect_cast( 201 | peer: NodeId, 202 | m: DisconnectMessage, 203 | service: &ClientServiceHandle, 204 | ) -> Result<()> { 205 | let client = DisconnectCast::client(service); 206 | track!(client.cast(peer.address(), (peer.local_id(), m)))?; 207 | Ok(()) 208 | } 209 | 210 | #[derive(Debug)] 211 | struct DisconnectHandler(ServiceHandle); 212 | impl HandleCast for DisconnectHandler { 213 | fn handle_cast(&self, (id, m): (LocalNodeId, DisconnectMessage)) -> NoReply { 214 | if let Some(node) = self.0.get_local_node(id) { 215 | node.send_rpc_message(RpcMessage::Hyparview(m.into())); 216 | } 217 | NoReply::done() 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /src/rpc/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::message::MessagePayload; 2 | use crate::misc::{HyparviewMessage, PlumtreeMessage}; 3 | 4 | pub mod hyparview; 5 | pub mod plumtree; 6 | 7 | #[derive(Debug)] 8 | pub enum RpcMessage { 9 | Hyparview(HyparviewMessage), 10 | Plumtree(PlumtreeMessage), 11 | } 12 | -------------------------------------------------------------------------------- /src/rpc/plumtree.rs: -------------------------------------------------------------------------------- 1 | use super::RpcMessage; 2 | use crate::codec::plumtree::{ 3 | GossipMessageDecoder, GossipMessageEncoder, GraftMessageDecoder, GraftMessageEncoder, 4 | GraftOptimizeMessageDecoder, GraftOptimizeMessageEncoder, IhaveMessageDecoder, 5 | IhaveMessageEncoder, PruneMessageDecoder, PruneMessageEncoder, 6 | }; 7 | use crate::message::MessagePayload; 8 | use crate::misc::{GossipMessage, GraftMessage, IhaveMessage, PruneMessage}; 9 | use crate::node::{LocalNodeId, NodeId}; 10 | use crate::service::ServiceHandle; 11 | use crate::Result; 12 | use fibers_rpc::client::ClientServiceHandle; 13 | use fibers_rpc::server::{HandleCast, NoReply, ServerBuilder}; 14 | use fibers_rpc::{Cast, ProcedureId}; 15 | use std::marker::PhantomData; 16 | 17 | const MAX_QUEUE_LEN: u64 = 4096; // FIXME: parameterize 18 | 19 | pub fn register_handlers(rpc: &mut ServerBuilder, service: &ServiceHandle) { 20 | rpc.add_cast_handler(GossipHandler(service.clone())); 21 | rpc.add_cast_handler(IhaveHandler(service.clone())); 22 | rpc.add_cast_handler(GraftHandler(service.clone())); 23 | rpc.add_cast_handler(GraftOptimizeHandler(service.clone())); 24 | rpc.add_cast_handler(PruneHandler(service.clone())); 25 | } 26 | 27 | #[derive(Debug)] 28 | pub struct GossipCast(PhantomData); 29 | unsafe impl Sync for GossipCast {} 30 | impl Cast for GossipCast { 31 | const ID: ProcedureId = ProcedureId(0x17CD_0000); 32 | const NAME: &'static str = "plumtree.gossip"; 33 | 34 | type Notification = (LocalNodeId, GossipMessage); 35 | type Decoder = GossipMessageDecoder; 36 | type Encoder = GossipMessageEncoder; 37 | } 38 | 39 | pub fn gossip_cast( 40 | peer: NodeId, 41 | m: GossipMessage, 42 | service: &ClientServiceHandle, 43 | ) -> Result<()> { 44 | let mut client = GossipCast::client(service); 45 | client.options_mut().max_queue_len = Some(MAX_QUEUE_LEN); 46 | track!(client.cast(peer.address(), (peer.local_id(), m)))?; 47 | Ok(()) 48 | } 49 | 50 | #[derive(Debug)] 51 | struct GossipHandler(ServiceHandle); 52 | impl HandleCast> for GossipHandler { 53 | fn handle_cast(&self, (id, m): (LocalNodeId, GossipMessage)) -> NoReply { 54 | if let Some(node) = self.0.get_local_node_or_disconnect(id, &m.sender) { 55 | node.send_rpc_message(RpcMessage::Plumtree(m.into())); 56 | } 57 | NoReply::done() 58 | } 59 | } 60 | 61 | #[derive(Debug)] 62 | pub struct IhaveCast(PhantomData); 63 | unsafe impl Sync for IhaveCast {} 64 | impl Cast for IhaveCast { 65 | const ID: ProcedureId = ProcedureId(0x17CD_0001); 66 | const NAME: &'static str = "plumtree.ihave"; 67 | 68 | type Notification = (LocalNodeId, IhaveMessage); 69 | type Decoder = IhaveMessageDecoder; 70 | type Encoder = IhaveMessageEncoder; 71 | } 72 | 73 | pub fn ihave_cast( 74 | peer: NodeId, 75 | m: IhaveMessage, 76 | service: &ClientServiceHandle, 77 | ) -> Result<()> { 78 | let mut client = IhaveCast::client(service); 79 | client.options_mut().priority = 200; 80 | client.options_mut().max_queue_len = Some(MAX_QUEUE_LEN); 81 | track!(client.cast(peer.address(), (peer.local_id(), m)))?; 82 | Ok(()) 83 | } 84 | 85 | #[derive(Debug)] 86 | struct IhaveHandler(ServiceHandle); 87 | impl HandleCast> for IhaveHandler { 88 | fn handle_cast(&self, (id, m): (LocalNodeId, IhaveMessage)) -> NoReply { 89 | if let Some(node) = self.0.get_local_node_or_disconnect(id, &m.sender) { 90 | node.send_rpc_message(RpcMessage::Plumtree(m.into())); 91 | } 92 | NoReply::done() 93 | } 94 | } 95 | 96 | #[derive(Debug)] 97 | pub struct GraftCast(PhantomData); 98 | unsafe impl Sync for GraftCast {} 99 | impl Cast for GraftCast { 100 | const ID: ProcedureId = ProcedureId(0x17CD_0002); 101 | const NAME: &'static str = "plumtree.graft"; 102 | 103 | type Notification = (LocalNodeId, GraftMessage); 104 | type Decoder = GraftMessageDecoder; 105 | type Encoder = GraftMessageEncoder; 106 | } 107 | 108 | pub fn graft_cast( 109 | peer: NodeId, 110 | m: GraftMessage, 111 | service: &ClientServiceHandle, 112 | ) -> Result<()> { 113 | if m.message_id.is_some() { 114 | let client = GraftCast::client(service); 115 | track!(client.cast(peer.address(), (peer.local_id(), m)))?; 116 | } else { 117 | let client = GraftOptimizeCast::client(service); 118 | track!(client.cast(peer.address(), (peer.local_id(), m)))?; 119 | } 120 | Ok(()) 121 | } 122 | 123 | #[derive(Debug)] 124 | struct GraftHandler(ServiceHandle); 125 | impl HandleCast> for GraftHandler { 126 | fn handle_cast(&self, (id, m): (LocalNodeId, GraftMessage)) -> NoReply { 127 | if let Some(node) = self.0.get_local_node_or_disconnect(id, &m.sender) { 128 | let m = RpcMessage::Plumtree(m.into()); 129 | node.send_rpc_message(m); 130 | } 131 | NoReply::done() 132 | } 133 | } 134 | 135 | #[derive(Debug)] 136 | pub struct GraftOptimizeCast(PhantomData); 137 | unsafe impl Sync for GraftOptimizeCast {} 138 | impl Cast for GraftOptimizeCast { 139 | const ID: ProcedureId = ProcedureId(0x17CD_0003); 140 | const NAME: &'static str = "plumtree.graft.optimize"; 141 | 142 | type Notification = (LocalNodeId, GraftMessage); 143 | type Decoder = GraftOptimizeMessageDecoder; 144 | type Encoder = GraftOptimizeMessageEncoder; 145 | } 146 | 147 | #[derive(Debug)] 148 | struct GraftOptimizeHandler(ServiceHandle); 149 | impl HandleCast> for GraftOptimizeHandler { 150 | fn handle_cast(&self, (id, m): (LocalNodeId, GraftMessage)) -> NoReply { 151 | if let Some(node) = self.0.get_local_node_or_disconnect(id, &m.sender) { 152 | let m = RpcMessage::Plumtree(m.into()); 153 | node.send_rpc_message(m); 154 | } 155 | NoReply::done() 156 | } 157 | } 158 | 159 | #[derive(Debug)] 160 | pub struct PruneCast(PhantomData); 161 | unsafe impl Sync for PruneCast {} 162 | impl Cast for PruneCast { 163 | const ID: ProcedureId = ProcedureId(0x17CD_0004); 164 | const NAME: &'static str = "plumtree.prune"; 165 | 166 | type Notification = (LocalNodeId, PruneMessage); 167 | type Decoder = PruneMessageDecoder; 168 | type Encoder = PruneMessageEncoder; 169 | } 170 | 171 | pub fn prune_cast( 172 | peer: NodeId, 173 | m: PruneMessage, 174 | service: &ClientServiceHandle, 175 | ) -> Result<()> { 176 | let client = PruneCast::client(service); 177 | track!(client.cast(peer.address(), (peer.local_id(), m)))?; 178 | Ok(()) 179 | } 180 | 181 | #[derive(Debug)] 182 | struct PruneHandler(ServiceHandle); 183 | impl HandleCast> for PruneHandler { 184 | fn handle_cast(&self, (id, m): (LocalNodeId, PruneMessage)) -> NoReply { 185 | if let Some(node) = self.0.get_local_node_or_disconnect(id, &m.sender) { 186 | node.send_rpc_message(RpcMessage::Plumtree(m.into())); 187 | } 188 | NoReply::done() 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/service.rs: -------------------------------------------------------------------------------- 1 | //! [`Service`] and related components. 2 | //! 3 | //! [`Service`]: ./struct.Service.html 4 | use crate::message::MessagePayload; 5 | use crate::metrics::{NodeMetrics, ServiceMetrics}; 6 | use crate::misc::ArcSpawn; 7 | use crate::node::{GenerateLocalNodeId, LocalNodeId, NodeHandle, NodeId}; 8 | use crate::node_id_generator::ArcLocalNodeIdGenerator; 9 | use crate::rpc::{self, RpcMessage}; 10 | use crate::{Error, ErrorKind, Result}; 11 | use atomic_immut::AtomicImmut; 12 | use fibers::sync::mpsc; 13 | use fibers::Spawn; 14 | use fibers_rpc::client::{ 15 | ClientService as RpcClientService, ClientServiceBuilder as RpcClientServiceBuilder, 16 | ClientServiceHandle as RpcClientServiceHandle, 17 | }; 18 | use fibers_rpc::server::{Server as RpcServer, ServerBuilder as RpcServerBuilder}; 19 | use futures::{Async, Future, Poll, Stream}; 20 | use prometrics::metrics::MetricBuilder; 21 | use slog::{Discard, Logger}; 22 | use std::collections::HashMap; 23 | use std::net::SocketAddr; 24 | use std::sync::{Arc, Mutex}; 25 | 26 | type LocalNodes = Arc>>>; 27 | 28 | /// The builder of [`Service`]. 29 | /// 30 | /// [`Service`]: ./struct.Service.html 31 | #[derive(Debug)] 32 | pub struct ServiceBuilder { 33 | logger: Logger, 34 | server_addr: SocketAddr, 35 | rpc_server_builder: RpcServerBuilder, 36 | rpc_client_service_builder: RpcClientServiceBuilder, 37 | metrics: MetricBuilder, 38 | } 39 | impl ServiceBuilder { 40 | /// Makes a new `ServiceBuilder` instance with the default settings. 41 | pub fn new(rpc_server_bind_addr: SocketAddr) -> Self { 42 | ServiceBuilder { 43 | logger: Logger::root(Discard, o!()), 44 | server_addr: rpc_server_bind_addr, 45 | rpc_server_builder: RpcServerBuilder::new(rpc_server_bind_addr), 46 | rpc_client_service_builder: RpcClientServiceBuilder::new(), 47 | metrics: MetricBuilder::new(), 48 | } 49 | } 50 | 51 | /// Sets the logger used by the service. 52 | /// 53 | /// The default value is `Logger::root(Discard, o!())`. 54 | pub fn logger(mut self, logger: Logger) -> Self { 55 | self.rpc_server_builder.logger(logger.clone()); 56 | self.rpc_client_service_builder.logger(logger.clone()); 57 | self.logger = logger; 58 | self 59 | } 60 | 61 | /// Sets the metrics settings of the service. 62 | /// 63 | /// The default value is `MetricBuilder::new()`. 64 | pub fn metrics(mut self, metrics: MetricBuilder) -> Self { 65 | self.metrics = metrics; 66 | self 67 | } 68 | 69 | /// Returns a mutable reference to the RPC server builder. 70 | pub fn rpc_server_builder_mut(&mut self) -> &mut RpcServerBuilder { 71 | &mut self.rpc_server_builder 72 | } 73 | 74 | /// Builds a [`Service`] with the given settings. 75 | /// 76 | /// [`Service`]: ./struct.Service.html 77 | pub fn finish(mut self, spawner: S, local_id_gen: G) -> Service 78 | where 79 | S: Spawn + Send + Sync + 'static, 80 | M: MessagePayload, 81 | G: GenerateLocalNodeId, 82 | { 83 | let spawner = ArcSpawn::new(spawner); 84 | let (command_tx, command_rx) = mpsc::channel(); 85 | let rpc_client_service = self.rpc_client_service_builder.finish(spawner.clone()); 86 | 87 | let metrics = ServiceMetrics::new(self.metrics.clone()); 88 | let removed_nodes_metrics = NodeMetrics::new(self.metrics.clone()); 89 | let handle = ServiceHandle { 90 | server_addr: self.server_addr, 91 | command_tx, 92 | rpc_service: rpc_client_service.handle(), 93 | local_nodes: Default::default(), 94 | local_id_gen: ArcLocalNodeIdGenerator::new(local_id_gen), 95 | metrics: metrics.clone(), 96 | metric_builder: Arc::new(Mutex::new(self.metrics)), 97 | }; 98 | 99 | rpc::hyparview::register_handlers(&mut self.rpc_server_builder, &handle); 100 | rpc::plumtree::register_handlers(&mut self.rpc_server_builder, &handle); 101 | let rpc_server = self.rpc_server_builder.finish(spawner); 102 | 103 | Service { 104 | logger: self.logger.clone(), 105 | command_rx, 106 | rpc_server, 107 | rpc_client_service, 108 | handle, 109 | metrics, 110 | removed_nodes_metrics, 111 | } 112 | } 113 | } 114 | 115 | /// A [`Future`] that executes management tasks needed for running a plumcast system. 116 | /// 117 | /// This has mainly two responsibilities: 118 | /// - The management of the RPC server and client used for inter node communication by Plumtree/HyParView 119 | /// - [`Node`] registry 120 | /// 121 | /// [`Future`]: https://docs.rs/futures/0.1/futures/future/trait.Future.html 122 | /// [`Node`]: ../node/struct.Node.html 123 | #[derive(Debug)] 124 | #[must_use = "futures do nothing unless polled"] 125 | pub struct Service { 126 | logger: Logger, 127 | command_rx: mpsc::Receiver>, // NOTE: infinite stream 128 | rpc_server: RpcServer, 129 | rpc_client_service: RpcClientService, 130 | handle: ServiceHandle, 131 | metrics: ServiceMetrics, 132 | removed_nodes_metrics: NodeMetrics, 133 | } 134 | impl Service 135 | where 136 | M: MessagePayload, 137 | { 138 | /// Makes a new `Service` instance with the default settings. 139 | /// 140 | /// If you want to customize settings, please use [`ServiceBuilder`] instead. 141 | /// 142 | /// [`ServiceBuilder`]: ./struct.ServiceBuilder.html 143 | pub fn new(rpc_server_bind_addr: SocketAddr, spawner: S, local_id_gen: G) -> Self 144 | where 145 | S: Spawn + Send + Sync + 'static, 146 | G: GenerateLocalNodeId, 147 | { 148 | ServiceBuilder::new(rpc_server_bind_addr).finish(spawner, local_id_gen) 149 | } 150 | 151 | /// Returns the handle of the service. 152 | pub fn handle(&self) -> ServiceHandle { 153 | self.handle.clone() 154 | } 155 | 156 | /// Returns a reference to the RPC server of the service. 157 | pub fn rpc_server(&self) -> &RpcServer { 158 | &self.rpc_server 159 | } 160 | 161 | /// Returns a reference to the RPC client service of the service. 162 | pub fn rpc_client_service(&self) -> &RpcClientService { 163 | &self.rpc_client_service 164 | } 165 | 166 | fn handle_command(&mut self, command: Command) -> Result<()> { 167 | match command { 168 | Command::Register(node) => { 169 | info!(self.logger, "Registers a local node: {:?}", node); 170 | track_assert!( 171 | !self.handle 172 | .local_nodes 173 | .load() 174 | .contains_key(&node.local_id()), 175 | ErrorKind::InconsistentState; node 176 | ); 177 | 178 | self.metrics.registered_nodes.increment(); 179 | self.handle.local_nodes.update(|nodes| { 180 | let mut nodes = (*nodes).clone(); 181 | nodes.insert(node.local_id(), node.clone()); 182 | nodes 183 | }); 184 | } 185 | Command::Deregister(node) => { 186 | info!(self.logger, "Deregisters a local node: {:?}", node); 187 | track_assert!( 188 | self.handle.local_nodes.load().contains_key(&node), 189 | ErrorKind::InconsistentState; node 190 | ); 191 | 192 | self.metrics.deregistered_nodes.increment(); 193 | self.handle.local_nodes.update(|nodes| { 194 | let mut nodes = (*nodes).clone(); 195 | if let Some(n) = nodes.remove(&node) { 196 | self.removed_nodes_metrics.add(n.metrics()); 197 | } 198 | nodes 199 | }); 200 | } 201 | } 202 | Ok(()) 203 | } 204 | } 205 | impl Future for Service 206 | where 207 | M: MessagePayload, 208 | { 209 | type Item = (); 210 | type Error = Error; 211 | 212 | fn poll(&mut self) -> Poll { 213 | if let Async::Ready(()) = track!(self.rpc_client_service.poll())? { 214 | track_panic!( 215 | ErrorKind::Other, 216 | "Unexpected termination of RPC client service" 217 | ); 218 | } 219 | if let Async::Ready(()) = track!(self.rpc_server.poll())? { 220 | track_panic!(ErrorKind::Other, "Unexpected termination of RPC server"); 221 | } 222 | while let Async::Ready(Some(command)) = self.command_rx.poll().expect("Never fails") { 223 | track!(self.handle_command(command))?; 224 | } 225 | Ok(Async::NotReady) 226 | } 227 | } 228 | impl Drop for Service { 229 | fn drop(&mut self) { 230 | let old = self.handle.local_nodes.swap(HashMap::new()); 231 | self.metrics.deregistered_nodes.add_u64(old.len() as u64); 232 | for node in old.values() { 233 | self.removed_nodes_metrics.add(node.metrics()); 234 | } 235 | } 236 | } 237 | 238 | /// A handle of a [`Service`] instance. 239 | /// 240 | /// [`Service`]: ./struct.Service.html 241 | #[derive(Debug, Clone)] 242 | pub struct ServiceHandle { 243 | server_addr: SocketAddr, 244 | command_tx: mpsc::Sender>, 245 | rpc_service: RpcClientServiceHandle, 246 | local_nodes: LocalNodes, 247 | local_id_gen: ArcLocalNodeIdGenerator, 248 | metrics: ServiceMetrics, 249 | metric_builder: Arc>, 250 | } 251 | impl ServiceHandle { 252 | /// Returns the address of the RPC server used for inter node communications. 253 | pub fn rpc_server_addr(&self) -> SocketAddr { 254 | self.server_addr 255 | } 256 | 257 | /// Returns the metrics of the service. 258 | pub fn metrics(&self) -> &ServiceMetrics { 259 | &self.metrics 260 | } 261 | 262 | /// Returns the identifiers of the nodes registered in the service. 263 | pub fn local_nodes(&self) -> Vec { 264 | self.local_nodes.load().keys().cloned().collect() 265 | } 266 | 267 | pub(crate) fn metric_builder(&self) -> MetricBuilder { 268 | if let Ok(m) = self.metric_builder.lock() { 269 | m.clone() 270 | } else { 271 | MetricBuilder::new() 272 | } 273 | } 274 | 275 | pub(crate) fn generate_node_id(&self) -> NodeId { 276 | let local_id = self.local_id_gen.generate_local_node_id(); 277 | NodeId::new(self.server_addr, local_id) 278 | } 279 | 280 | pub(crate) fn get_local_node(&self, local_id: LocalNodeId) -> Option> { 281 | self.local_nodes.load().get(&local_id).cloned() 282 | } 283 | 284 | pub(crate) fn get_local_node_or_disconnect( 285 | &self, 286 | id: LocalNodeId, 287 | sender: &NodeId, 288 | ) -> Option> { 289 | if let Some(node) = self.local_nodes.load().get(&id).cloned() { 290 | Some(node) 291 | } else { 292 | use hyparview::message::{DisconnectMessage, ProtocolMessage}; 293 | 294 | self.metrics.destination_unknown_messages.increment(); 295 | let missing = NodeId::new(self.server_addr, id); 296 | let message = DisconnectMessage { 297 | sender: missing, 298 | alive: false, 299 | }; 300 | let message = ProtocolMessage::Disconnect(message); 301 | let _ = self.send_message(*sender, RpcMessage::Hyparview(message)); 302 | None 303 | } 304 | } 305 | 306 | pub(crate) fn register_local_node(&self, node: NodeHandle) { 307 | let command = Command::Register(node); 308 | let _ = self.command_tx.send(command); 309 | } 310 | 311 | pub(crate) fn deregister_local_node(&self, node: LocalNodeId) { 312 | let command = Command::Deregister(node); 313 | let _ = self.command_tx.send(command); 314 | } 315 | 316 | pub(crate) fn send_message(&self, peer: NodeId, message: RpcMessage) -> Result<()> { 317 | match message { 318 | RpcMessage::Hyparview(m) => { 319 | use crate::rpc::hyparview as hv; 320 | use hyparview::message::ProtocolMessage; 321 | 322 | match m { 323 | ProtocolMessage::Join(m) => { 324 | track!(hv::join_cast(peer, m, &self.rpc_service))?; 325 | } 326 | ProtocolMessage::ForwardJoin(m) => { 327 | track!(hv::forward_join_cast(peer, m, &self.rpc_service))?; 328 | } 329 | ProtocolMessage::Neighbor(m) => { 330 | track!(hv::neighbor_cast(peer, m, &self.rpc_service))?; 331 | } 332 | ProtocolMessage::Shuffle(m) => { 333 | track!(hv::shuffle_cast(peer, m, &self.rpc_service))?; 334 | } 335 | ProtocolMessage::ShuffleReply(m) => { 336 | track!(hv::shuffle_reply_cast(peer, m, &self.rpc_service))?; 337 | } 338 | ProtocolMessage::Disconnect(m) => { 339 | track!(hv::disconnect_cast(peer, m, &self.rpc_service))?; 340 | } 341 | } 342 | } 343 | RpcMessage::Plumtree(m) => { 344 | use crate::rpc::plumtree as pt; 345 | use plumtree::message::ProtocolMessage; 346 | 347 | match m { 348 | ProtocolMessage::Gossip(m) => { 349 | track!(pt::gossip_cast(peer, m, &self.rpc_service))?; 350 | } 351 | ProtocolMessage::Ihave(m) => { 352 | track!(pt::ihave_cast(peer, m, &self.rpc_service))?; 353 | } 354 | ProtocolMessage::Graft(m) => { 355 | track!(pt::graft_cast(peer, m, &self.rpc_service))?; 356 | } 357 | ProtocolMessage::Prune(m) => { 358 | track!(pt::prune_cast(peer, m, &self.rpc_service))?; 359 | } 360 | } 361 | } 362 | } 363 | Ok(()) 364 | } 365 | } 366 | 367 | #[derive(Debug)] 368 | enum Command { 369 | Register(NodeHandle), 370 | Deregister(LocalNodeId), 371 | } 372 | --------------------------------------------------------------------------------