byteflow/scheduler/
registry.rs1use std::collections::HashMap;
12
13use crate::bytecode::CapId;
14use super::error::{LifecycleError, RuntimeError};
15use super::process::FlowId;
16use super::sync_lock;
17
18#[derive(Debug, Clone, PartialEq, Eq, Hash)]
21pub struct RegistryName(Box<str>);
22
23impl RegistryName {
24 pub fn new(name: impl Into<Box<str>>) -> Self {
25 Self(name.into())
26 }
27
28 pub fn as_str(&self) -> &str {
29 &self.0
30 }
31}
32
33impl From<&str> for RegistryName {
34 fn from(name: &str) -> Self {
35 Self(name.into())
36 }
37}
38
39struct Entry {
40 cap: CapId,
41 flow: FlowId,
42}
43
44pub struct Registry {
45 by_name: HashMap<RegistryName, Entry>,
46 by_flow: HashMap<FlowId, Vec<RegistryName>>,
47}
48
49impl Registry {
50 pub fn new() -> Self {
51 Self {
52 by_name: HashMap::new(),
53 by_flow: HashMap::new(),
54 }
55 }
56
57 pub fn register(
58 &mut self,
59 name: RegistryName,
60 cap: CapId,
61 flow: FlowId,
62 ) -> Result<(), LifecycleError> {
63 if name.as_str().is_empty() {
64 return Err(LifecycleError::EmptyName);
65 }
66 if self.by_name.contains_key(&name) {
67 return Err(LifecycleError::AlreadyRegistered);
68 }
69 self.by_flow
70 .entry(flow)
71 .or_default()
72 .push(name.clone());
73 self.by_name.insert(name, Entry { cap, flow });
74 Ok(())
75 }
76
77 pub fn whereis(&self, name: &str) -> Option<CapId> {
78 self.by_name.get(&RegistryName::from(name)).map(|e| e.cap)
79 }
80
81 pub fn target(&self, name: &str) -> Option<FlowId> {
82 self.by_name.get(&RegistryName::from(name)).map(|e| e.flow)
83 }
84
85 pub fn unregister(&mut self, name: &str) -> bool {
86 let key = RegistryName::from(name);
87 match self.by_name.remove(&key) {
88 Some(entry) => {
89 if let Some(names) = self.by_flow.get_mut(&entry.flow) {
90 names.retain(|n| n != &key);
91 if names.is_empty() {
92 self.by_flow.remove(&entry.flow);
93 }
94 }
95 true
96 }
97 None => false,
98 }
99 }
100
101 pub fn unregister_flow(&mut self, flow: FlowId) {
103 if let Some(names) = self.by_flow.remove(&flow) {
104 for name in names {
105 self.by_name.remove(&name);
106 }
107 }
108 }
109}
110
111impl Default for Registry {
112 fn default() -> Self {
113 Self::new()
114 }
115}
116
117pub struct RegistryStore {
118 inner: std::sync::Mutex<Registry>,
119}
120
121impl RegistryStore {
122 pub fn new() -> Self {
123 Self {
124 inner: std::sync::Mutex::new(Registry::new()),
125 }
126 }
127
128 pub fn register(
129 &self,
130 name: RegistryName,
131 cap: CapId,
132 flow: FlowId,
133 ) -> Result<Result<(), LifecycleError>, RuntimeError> {
134 Ok(sync_lock::lock(&self.inner, "RegistryStore::register")?.register(name, cap, flow))
135 }
136
137 pub fn whereis(&self, name: &str) -> Result<Option<CapId>, RuntimeError> {
138 Ok(sync_lock::lock(&self.inner, "RegistryStore::whereis")?.whereis(name))
139 }
140
141 pub fn target(&self, name: &str) -> Result<Option<FlowId>, RuntimeError> {
142 Ok(sync_lock::lock(&self.inner, "RegistryStore::target")?.target(name))
143 }
144
145 pub fn unregister(&self, name: &str) -> Result<bool, RuntimeError> {
146 Ok(sync_lock::lock(&self.inner, "RegistryStore::unregister")?.unregister(name))
147 }
148
149 pub fn unregister_flow(&self, flow: FlowId) -> Result<(), RuntimeError> {
150 sync_lock::lock(&self.inner, "RegistryStore::unregister_flow")?.unregister_flow(flow);
151 Ok(())
152 }
153}
154
155impl Default for RegistryStore {
156 fn default() -> Self {
157 Self::new()
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164 use crate::bytecode::CapId;
165 use crate::scheduler::process::next_flow_id;
166
167 #[test]
168 fn unregister_flow_clears_names() {
169 let mut reg = Registry::new();
170 let flow = next_flow_id();
171 let cap = CapId::from_raw(42);
172 assert!(reg.register(RegistryName::from("svc"), cap, flow).is_ok());
173 assert_eq!(reg.whereis("svc"), Some(cap));
174 reg.unregister_flow(flow);
175 assert_eq!(reg.whereis("svc"), None);
176 }
177
178 #[test]
179 fn duplicate_name_is_rejected() {
180 let mut reg = Registry::new();
181 let flow = next_flow_id();
182 assert!(reg
183 .register(RegistryName::from("svc"), CapId::from_raw(1), flow)
184 .is_ok());
185 assert_eq!(
186 reg.register(RegistryName::from("svc"), CapId::from_raw(2), flow),
187 Err(LifecycleError::AlreadyRegistered)
188 );
189 }
190
191 #[test]
192 fn empty_name_is_rejected() {
193 let mut reg = Registry::new();
194 let flow = next_flow_id();
195 assert_eq!(
196 reg.register(RegistryName::from(""), CapId::from_raw(1), flow),
197 Err(LifecycleError::EmptyName)
198 );
199 }
200}