1use crate::error::PluginError;
13use crate::main_engine::{PluginInfo, PluginState};
14use crate::service::ServiceDesc;
15use ek_event::{Event, HandlerId};
16use std::any::Any;
17use std::collections::{HashMap, VecDeque};
18use std::sync::atomic::{AtomicBool, AtomicU8, AtomicU64, Ordering};
19use std::sync::{Arc, Mutex, RwLock};
20use std::thread::JoinHandle;
21
22use crossbeam_channel::Sender;
23
24#[derive(Default)]
26pub(crate) struct EntryStats {
27 pub spilled: AtomicU64,
29 pub panics: AtomicU64,
31 pub done: AtomicBool,
33}
34
35pub(crate) struct PluginEntry {
37 pub name: String,
38 pub plugin: Arc<dyn crate::plugin::Plugin>,
40 pub any: Arc<dyn Any + Send + Sync>,
42 pub state: PluginStateCell,
43 pub mailbox_cap: usize,
44 pub deps: Vec<String>,
45 pub mailbox: Mutex<Option<Sender<Event>>>,
47 pub forwarder_ids: Mutex<Vec<HandlerId>>,
49 pub worker: Mutex<Option<JoinHandle<()>>>,
51 pub stats: Arc<EntryStats>,
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub enum PluginStateCode {
57 Ready = 0,
58 Running = 1,
59 Stopping = 2,
60 Exited = 3,
61 Quarantined = 4,
62}
63
64#[derive(Clone)]
66pub(crate) struct PluginStateCell(Arc<AtomicU8>);
67
68impl PluginStateCell {
69 pub fn new(s: PluginStateCode) -> Self {
70 Self(Arc::new(AtomicU8::new(s as u8)))
71 }
72 pub fn get(&self) -> PluginState {
73 PluginState::from_code(self.0.load(Ordering::Acquire))
74 }
75 pub(crate) fn cas(&self, from: PluginStateCode, to: PluginStateCode) -> bool {
76 self.0
77 .compare_exchange(from as u8, to as u8, Ordering::AcqRel, Ordering::Acquire)
78 .is_ok()
79 }
80 pub(crate) fn finish(&self) -> bool {
82 self.cas(PluginStateCode::Running, PluginStateCode::Exited)
83 || self.cas(PluginStateCode::Stopping, PluginStateCode::Exited)
84 }
85}
86
87pub(crate) struct RegistryInner {
89 pub entries: HashMap<String, Arc<PluginEntry>>,
90 pub order: Vec<String>,
92}
93
94type SvcCacheEntry = (u64, Arc<Vec<ServiceDesc>>);
96
97pub(crate) struct Registry {
98 pub state_of: RwLock<RegistryInner>,
99 pub(crate) svc_index: RwLock<HashMap<String, Vec<String>>>,
101 revision: AtomicU64,
103 svc_cache: Mutex<HashMap<String, SvcCacheEntry>>,
105}
106
107impl Registry {
108 pub fn new() -> Self {
109 Self {
110 state_of: RwLock::new(RegistryInner {
111 entries: HashMap::new(),
112 order: Vec::new(),
113 }),
114 svc_index: RwLock::new(HashMap::new()),
115 revision: AtomicU64::new(1),
116 svc_cache: Mutex::new(HashMap::new()),
117 }
118 }
119
120 pub fn revision(&self) -> u64 {
121 self.revision.load(Ordering::Acquire)
122 }
123
124 pub fn bump(&self) {
125 self.revision.fetch_add(1, Ordering::AcqRel);
126 }
127
128 pub fn index_put(&self, name: &str, ids: &[String]) {
130 let mut w = self.svc_index.write().unwrap();
131 for list in w.values_mut() {
132 list.retain(|n| n != name);
133 }
134 w.retain(|_, l| !l.is_empty());
135 for id in ids {
136 let entry = w.entry(id.clone()).or_default();
137 if !entry.iter().any(|n| n == name) {
138 entry.push(name.to_string());
139 }
140 }
141 }
142
143 pub fn index_remove(&self, name: &str) {
145 let mut w = self.svc_index.write().unwrap();
146 for list in w.values_mut() {
147 list.retain(|n| n != name);
148 }
149 w.retain(|_, l| !l.is_empty());
150 }
151
152 pub fn index_providers(&self, svc: &str) -> Vec<String> {
154 self.svc_index
155 .read()
156 .unwrap()
157 .get(svc)
158 .cloned()
159 .unwrap_or_default()
160 }
161
162 pub(crate) fn publish(&self, name: &str, list: Vec<ServiceDesc>) -> String {
165 let Some(entry) = self.get(name) else {
166 return String::new();
167 };
168 let mut ids: Vec<String> = Vec::with_capacity(list.len());
169 for d in &list {
170 if !ids.contains(&d.id) {
171 ids.push(d.id.clone());
172 }
173 }
174 self.index_put(name, &ids);
175 self.invalidate(name);
176 entry.plugin.version().into_owned()
177 }
178
179 pub fn services_of(&self, name: &str) -> Option<Arc<Vec<ServiceDesc>>> {
181 let entry = self.get(name)?;
182 let revision = self.revision();
183 if let Some((rev, list)) = self.svc_cache.lock().unwrap().get(name) {
184 if *rev == revision {
185 return Some(Arc::clone(list));
186 }
187 }
188 let list = Arc::new(entry.plugin.services());
189 self.svc_cache
190 .lock()
191 .unwrap()
192 .insert(name.to_string(), (revision, Arc::clone(&list)));
193 Some(list)
194 }
195
196 pub(crate) fn info_of(&self, name: &str) -> Option<PluginInfo> {
198 self.get(name).map(|e| PluginInfo {
199 name: e.name.clone(),
200 version: e.plugin.version().into_owned(),
201 state: e.state.get(),
202 deps: e.deps.clone(),
203 })
204 }
205
206 pub fn get(&self, name: &str) -> Option<Arc<PluginEntry>> {
207 self.state_of.read().unwrap().entries.get(name).cloned()
208 }
209
210 pub fn remove(&self, name: &str) -> Option<Arc<PluginEntry>> {
211 let mut w = self.state_of.write().unwrap();
212 w.entries.remove(name).inspect(|_| {
213 if let Some(i) = w.order.iter().position(|n| n == name) {
214 w.order.remove(i);
215 }
216 })
217 }
218
219 pub fn names(&self) -> Vec<String> {
220 self.state_of.read().unwrap().order.clone()
221 }
222
223 pub fn any_depends_on(&self, target: &str) -> Vec<String> {
224 let r = self.state_of.read().unwrap();
225 r.order
226 .iter()
227 .filter_map(|n| r.entries.get(n))
228 .filter(|e| e.deps.iter().any(|d| d == target))
229 .map(|e| e.name.clone())
230 .collect()
231 }
232
233 pub fn clear(&self) {
234 let mut w = self.state_of.write().unwrap();
235 w.entries.clear();
236 w.order.clear();
237 drop(w);
238 self.svc_index.write().unwrap().clear();
239 self.svc_cache.lock().unwrap().clear();
240 self.bump();
241 }
242
243 pub fn invalidate(&self, name: &str) {
245 self.svc_cache.lock().unwrap().remove(name);
246 self.bump();
247 }
248
249 pub fn topo_order(&self) -> Result<Vec<Arc<PluginEntry>>, PluginError> {
252 let r = self.state_of.read().unwrap();
253 let mut indeg: HashMap<String, usize> = HashMap::new();
254 let mut dependents: HashMap<String, Vec<String>> = HashMap::new();
255 for name in &r.order {
256 indeg.entry(name.clone()).or_insert(0);
257 }
258 for name in &r.order {
259 let e = &r.entries[name];
260 for d in &e.deps {
261 if !r.entries.contains_key(d) {
262 return Err(PluginError::UnknownDep(d.clone()));
263 }
264 *indeg.entry(name.clone()).or_insert(0) += 1;
265 dependents.entry(d.clone()).or_default().push(name.clone());
266 }
267 }
268 let mut queue: VecDeque<String> =
269 r.order.iter().filter(|n| indeg[*n] == 0).cloned().collect();
270 let mut out = Vec::with_capacity(r.order.len());
271 while let Some(n) = queue.pop_front() {
272 let e = Arc::clone(&r.entries[&n]);
273 out.push(e);
274 if let Some(deps_list) = dependents.get(&n) {
275 for dep_name in deps_list {
276 let d = indeg.get_mut(dep_name).unwrap();
277 *d -= 1;
278 if *d == 0 {
279 queue.push_back(dep_name.clone());
280 }
281 }
282 }
283 }
284 if out.len() < r.order.len() {
285 let cycle: Vec<String> = r.order.iter().filter(|n| indeg[*n] > 0).cloned().collect();
286 return Err(PluginError::DepCycle(cycle));
287 }
288 Ok(out)
289 }
290}