node: Remove `Routing` command

Replaced by direct DB access.
This commit is contained in:
Alexis Sellier 2023-03-15 11:55:55 +01:00
parent 40c58b45ed
commit caaa7581e6
No known key found for this signature in database
8 changed files with 35 additions and 58 deletions

View File

@ -1,7 +1,7 @@
use std::ffi::OsString;
use anyhow::anyhow;
use radicle::node::{Address, Node, NodeId, TRACKING_DB_FILE};
use radicle::node::{Address, Node, NodeId, ROUTING_DB_FILE, TRACKING_DB_FILE};
use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help};
@ -139,8 +139,9 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
control::connect(&mut node, nid, addr)?
}
Operation::Routing => {
let node = Node::new(profile.socket());
routing::run(&node)?;
let store =
radicle::node::routing::Table::reader(profile.home.node().join(ROUTING_DB_FILE))?;
routing::run(&store)?;
}
Operation::Start => control::start()?,
Operation::Status => {

View File

@ -1,12 +1,12 @@
use radicle::{node::Handle as _, Node};
use radicle::node;
use crate::terminal as term;
pub fn run(node: &Node) -> anyhow::Result<()> {
pub fn run<S: node::routing::Store>(routing: &S) -> anyhow::Result<()> {
let mut t = term::Table::new(term::table::TableOptions::default());
t.push(["RID", "NID"]);
t.push(["---", "---"]);
for (id, node) in node.routing()? {
for (id, node) in routing.entries()? {
t.push([
term::format::highlight(id).to_string(),
term::format::node(&node),

View File

@ -187,14 +187,6 @@ fn command<H: Handle<Error = runtime::HandleError>>(
CommandName::Status => {
CommandResult::ok().to_writer(writer).ok();
}
CommandName::Routing => match handle.routing() {
Ok(c) => {
for route in c.into_iter() {
serde_json::to_writer(&mut writer, &route)?;
}
}
Err(e) => return Err(CommandError::Runtime(e)),
},
CommandName::Inventory => match handle.inventory() {
Ok(c) => {
for id in c.iter() {

View File

@ -109,7 +109,6 @@ impl<G: Signer + Ecdh + 'static> Handle<G> {
impl<G: Signer + Ecdh + 'static> radicle::node::Handle for Handle<G> {
type Sessions = Sessions;
type Error = Error;
type Routing = chan::Receiver<(Id, NodeId)>;
fn is_running(&self) -> bool {
true
@ -171,23 +170,6 @@ impl<G: Signer + Ecdh + 'static> radicle::node::Handle for Handle<G> {
receiver.recv().map_err(Error::from)
}
fn routing(&self) -> Result<Self::Routing, Error> {
let (sender, receiver) = chan::unbounded();
let query: Arc<QueryState> = Arc::new(move |state| {
for (id, node) in state.routing().entries()? {
if sender.send((id, node)).is_err() {
break;
}
}
Ok(())
});
let (err_sender, err_receiver) = chan::bounded(1);
self.command(service::Command::QueryState(query, err_sender))?;
err_receiver.recv()??;
Ok(receiver)
}
fn sessions(&self) -> Result<Self::Sessions, Error> {
let (sender, receiver) = chan::unbounded();
let query: Arc<QueryState> = Arc::new(move |state| {

View File

@ -17,6 +17,7 @@ use radicle::crypto::{KeyPair, Seed, Signer};
use radicle::git;
use radicle::git::refname;
use radicle::identity::Id;
use radicle::node::routing::Store;
use radicle::node::Handle as _;
use radicle::profile::Home;
use radicle::profile::Profile;
@ -156,6 +157,14 @@ impl<G: Signer + cyphernet::Ecdh> NodeHandle<G> {
self
}
/// Get routing table entries.
pub fn routing(&self) -> impl Iterator<Item = (Id, NodeId)> {
radicle::node::routing::Table::reader(self.home.node().join(radicle::node::ROUTING_DB_FILE))
.unwrap()
.entries()
.unwrap()
}
/// Wait until this node's routing table matches the remotes.
pub fn converge<'a>(
&'a self,
@ -176,7 +185,7 @@ impl<G: Signer + cyphernet::Ecdh> NodeHandle<G> {
let mut remaining: BTreeSet<_> = routes.iter().collect();
for (rid, nid) in self.handle.routing().unwrap() {
for (rid, nid) in self.routing() {
if !remaining.remove(&(rid, nid)) {
panic!(
"Node::routes_to: unexpected route for {}: ({rid}, {nid})",
@ -347,7 +356,7 @@ pub fn converge<'a, G: Signer + cyphernet::Ecdh + 'static>(
// First build the set of all routes.
for node in &nodes {
// Routes from the routing table.
for (rid, seed_id) in node.handle.routing().unwrap() {
for (rid, seed_id) in node.routing() {
all_routes.insert((rid, seed_id));
}
// Routes from the local inventory.
@ -360,8 +369,8 @@ pub fn converge<'a, G: Signer + cyphernet::Ecdh + 'static>(
// its routing table has all routes. If so, remove it from the remaining nodes.
while !remaining.is_empty() {
remaining.retain(|_, node| {
let routing = node.handle.routing().unwrap();
let routes = BTreeSet::from_iter(routing.try_iter());
let routing = node.routing();
let routes = BTreeSet::from_iter(routing);
if routes == all_routes {
log::debug!(target: "test", "Node {} has converged", node.id);

View File

@ -20,7 +20,6 @@ pub struct Handle {
impl radicle::node::Handle for Handle {
type Error = HandleError;
type Sessions = service::Sessions;
type Routing = Vec<(Id, NodeId)>;
fn is_running(&self) -> bool {
true
@ -68,10 +67,6 @@ impl radicle::node::Handle for Handle {
unimplemented!()
}
fn routing(&self) -> Result<Self::Routing, Self::Error> {
unimplemented!();
}
fn sessions(&self) -> Result<Self::Sessions, Self::Error> {
unimplemented!();
}

View File

@ -141,8 +141,6 @@ pub enum CommandName {
UntrackNode,
/// Get the node's inventory.
Inventory,
/// Get the node's routing table.
Routing,
/// Get the node's status.
Status,
/// Shutdown the node.
@ -385,8 +383,6 @@ pub trait Handle {
/// The error returned by all methods.
type Error: std::error::Error + Send + Sync + 'static;
type Routing: IntoIterator<Item = (Id, NodeId)>;
/// Check if the node is running. to a peer.
fn is_running(&self) -> bool;
/// Connect to a peer.
@ -412,8 +408,6 @@ pub trait Handle {
fn sync_inventory(&mut self) -> Result<bool, Self::Error>;
/// Ask the service to shutdown.
fn shutdown(self) -> Result<(), Self::Error>;
/// Query the routing table entries.
fn routing(&self) -> Result<Self::Routing, Self::Error>;
/// Query the peer session state.
fn sessions(&self) -> Result<Self::Sessions, Self::Error>;
/// Query the inventory.
@ -464,7 +458,6 @@ impl Node {
impl Handle for Node {
type Sessions = ();
type Error = Error;
type Routing = Vec<(Id, NodeId)>;
fn is_running(&self) -> bool {
let Ok(mut lines) = self.call::<&str, CommandResult>(CommandName::Status, []) else {
@ -573,15 +566,6 @@ impl Handle for Node {
response.into()
}
fn routing(&self) -> Result<Self::Routing, Error> {
let mut routes = Vec::new();
for result in self.call::<&str, _>(CommandName::Routing, [])? {
let route = result?;
routes.push(route);
}
Ok(routes)
}
fn sessions(&self) -> Result<Self::Sessions, Error> {
todo!();
}

View File

@ -1,6 +1,6 @@
use std::collections::HashSet;
use std::fmt;
use std::path::Path;
use std::{fmt, time};
use sqlite as sql;
use thiserror::Error;
@ -10,6 +10,9 @@ use crate::{
prelude::{Id, NodeId},
};
/// How long to wait for the database lock to be released before failing a read.
const DB_READ_TIMEOUT: time::Duration = time::Duration::from_secs(1);
/// An error occuring in peer-to-peer networking code.
#[derive(Error, Debug)]
pub enum Error {
@ -44,6 +47,17 @@ impl Table {
Ok(Self { db })
}
/// Same as [`Self::open`], but in read-only mode. This is useful to have multiple
/// open databases, as no locking is required.
pub fn reader<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
let mut db =
sql::Connection::open_with_flags(path, sqlite::OpenFlags::new().set_read_only())?;
db.set_busy_timeout(DB_READ_TIMEOUT.as_millis() as usize)?;
db.execute(Self::SCHEMA)?;
Ok(Self { db })
}
/// Create a new in-memory routing table.
pub fn memory() -> Result<Self, Error> {
let db = sql::Connection::open(":memory:")?;