hydra/
pid.rs

1use std::fmt::Debug;
2use std::net::SocketAddr;
3use std::num::NonZeroU64;
4
5use serde::Deserialize;
6use serde::Serialize;
7
8use crate::INVALID_NODE_ID;
9use crate::LOCAL_NODE_ID;
10use crate::Node;
11use crate::node_lookup_local;
12use crate::node_lookup_remote;
13use crate::node_register;
14
15/// The representation of a [Pid] serialized for the wire.
16#[derive(Serialize, Deserialize)]
17enum PidWire {
18    WithNode(NonZeroU64, String, SocketAddr),
19    NodeUnavailable(NonZeroU64),
20}
21
22/// A unique identifier of a process in hydra.
23#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
24pub enum Pid {
25    Local(NonZeroU64),
26    Remote(NonZeroU64, u64),
27}
28
29impl Pid {
30    /// Constructs a new [Pid] from the given process id, assigning it to the local node.
31    pub(crate) fn local(id: u64) -> Self {
32        Self::Local(NonZeroU64::new(id).unwrap())
33    }
34
35    /// Constructs a new [Pid] from the given process id, assigning it to the remote node.
36    pub(crate) fn remote(id: u64, node: u64) -> Self {
37        Self::Remote(NonZeroU64::new(id).unwrap(), node)
38    }
39
40    /// Returns `true` if this [Pid] is a local process.
41    pub const fn is_local(&self) -> bool {
42        matches!(self, Self::Local(_))
43    }
44
45    /// Returns `true` if this [Pid] is a remote process.
46    pub const fn is_remote(&self) -> bool {
47        matches!(self, Self::Remote(_, _))
48    }
49
50    /// Gets the id part of the [Pid].
51    pub(crate) const fn id(&self) -> u64 {
52        match self {
53            Self::Local(id) => id.get(),
54            Self::Remote(id, _) => id.get(),
55        }
56    }
57
58    /// Gets the node part of the [Pid].
59    pub(crate) const fn node(&self) -> u64 {
60        match self {
61            Self::Local(_) => LOCAL_NODE_ID,
62            Self::Remote(_, node) => *node,
63        }
64    }
65}
66
67impl Debug for Pid {
68    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69        match self {
70            Self::Local(id) => write!(f, "Pid<0, {}>", id),
71            Self::Remote(id, node) => write!(f, "Pid<{}, {}>", node, id),
72        }
73    }
74}
75
76impl Serialize for Pid {
77    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78    where
79        S: serde::Serializer,
80    {
81        let pid: PidWire = match self {
82            Self::Local(id) => match node_lookup_local() {
83                Some((name, address)) => PidWire::WithNode(*id, name, address),
84                None => PidWire::NodeUnavailable(*id),
85            },
86            Self::Remote(id, node) => match node_lookup_remote(*node) {
87                Some((name, address)) => PidWire::WithNode(*id, name, address),
88                None => PidWire::NodeUnavailable(*id),
89            },
90        };
91
92        pid.serialize(serializer)
93    }
94}
95
96impl<'de> Deserialize<'de> for Pid {
97    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
98    where
99        D: serde::Deserializer<'de>,
100    {
101        let node: PidWire = PidWire::deserialize(deserializer)?;
102
103        match node {
104            PidWire::WithNode(id, node_name, node_address) => match node_lookup_local() {
105                Some((name, address)) => {
106                    if name == node_name && address == node_address {
107                        Ok(Pid::Local(id))
108                    } else {
109                        let node = node_register(Node::from((node_name, node_address)), false);
110
111                        Ok(Pid::Remote(id, node))
112                    }
113                }
114                None => Ok(Pid::Remote(id, INVALID_NODE_ID)),
115            },
116            PidWire::NodeUnavailable(id) => Ok(Self::Remote(id, INVALID_NODE_ID)),
117        }
118    }
119}