tango/server/server.rs
1//! The server itself: what owns the classes, the devices and the backend serving them.
2//!
3//! Ownership is a tree rooted at the [`ServerHandle`], which alone owns the `Core` of its
4//! server: its classes, its devices and its backend. The [`Server`] the classes and the
5//! devices hold is only the context they share, which reaches its core weakly, so that a
6//! handler reaches its class and its server as plain field access, without any cycle.
7
8use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
9use std::collections::hash_map::Entry;
10use std::sync::{Arc, Mutex, Weak};
11use std::task::{Context, Poll};
12use std::collections::HashMap;
13use std::ops::{Deref, RangeBounds};
14use std::pin::{pin, Pin};
15use std::time::Duration;
16use std::borrow::Cow;
17use std::mem;
18
19use futures::stream::{BoxStream, Stream, StreamExt};
20use futures::future::{self, Either};
21use futures::executor::block_on;
22use tracing::{debug, info, warn};
23
24use crate::backend::{default_backend, Backend, BackendServer, BackendServerConfig};
25use crate::database::{DatabaseProxy, ExportDevInfo};
26use crate::dev::{AttrInfo, AttrRead, AttrReady, AttrValueEvent};
27use crate::error::{Error, ErrorKind, Result, reason};
28use crate::name::{self, ArcName, Name};
29use crate::future::block_on_timeout;
30use crate::testing::TestContext;
31use crate::value::Value;
32use crate::future::Slot;
33
34use super::class::{AnyClass, Class};
35use super::admin::{self, Admin};
36use super::def::ClassDef;
37use super::Model;
38use super::dev::{AnyDev, Dev};
39use super::polling::Poller;
40use super::terminate;
41
42#[cfg(feature = "cli")]
43use super::cli::{self, ServerArgs};
44
45
46/// What the name of the admin device of a server is its `exe/inst` name prefixed with.
47const ADMIN_DEV_PREFIX: &str = "dserver/";
48
49/// How long a server is given to boot by default, see [`ServerBuilder::boot_timeout`].
50const DEFAULT_BOOT_TIMEOUT: Duration = Duration::from_secs(30);
51
52/// The context shared by the classes and the devices of a server, which every class of it
53/// owns, and which reaches what owns them, its `Core`, weakly.
54///
55/// # Ownership
56///
57/// ```text
58/// ┌───────────────────────────┐ ┌─────────────────┐
59/// │ ServerHandle │ │ DevProxy │
60/// └─────────────┬─────────────┘ └─────┬───────────┘
61/// │ │
62/// │core │backend: BackendDev
63/// │1 │0..1
64/// ┌─────────────────────┴─────────────────────┐ 1┌───────────────────┐ │
65/// │ Core ├───────┤ dyn BackendServer │ │
66/// └─┬──────┬──┬───┬──────┬────┬─────┬─────────┘backend└─────────┬──────┬──┘ │
67/// │ name │ │ │ name │ │ ╎1 │ name │ │
68/// ╰──┬───╯ │ ╰──┬───╯ │ ╎core ╰──┬───╯ │
69/// │ │ │ server│ ╎ │ │
70/// │ │ │ 1│ ╎ │ │
71/// │ │ │ ┌───┴─────┴───────┐ │ │
72/// │ │ │ │ Server │ │ │
73/// │ │ │ └───────────────┬─┘ │ │
74/// │ │ │classes: AnyClass │1 │ │
75/// │ │ │0..1 │server │ │
76/// │ │ ┌────┴────────────────────┴───────┐ │ │
77/// │ │ │ Class<M> │ │ │
78/// │ │ └─────────────────────────┬───────┘ │ │
79/// │ │ │1 │ │
80/// │ │ │class │ │
81/// devs: AnyDev│ │pending: AnyDev │ devs: BackendDev│ │
82/// 0..1│ │* │ 0..1│ │
83/// ┌─────┴──────┴───────────────────────────┴────────────────────────┴──────────────┴─────────┐
84/// │ Dev<M> │
85/// └─┬──────┬─┬──────┬──┬────────────┬─────────────┬─────────────────────┬───────────┬────────┘
86/// │ name │ │ name │ │ │ │ 0..1╎ ╎0..1
87/// ╰──┬───╯ ╰─┬────╯ │ │ │ dev: BackendDev╎ ╎dev: BackendDev
88/// │ │ │ │ │ ╎ ╎
89/// commands│ │attrs │state_attr │status_attr │ ╎ ╎
90/// 0..1│ │0..1 │1 │1 │ ╎ ╎
91/// ┌───────────┴┐ ┌───┴───────┴────────────┴────────┐ │ ╎ ╎
92/// │ Command<M> │ │ Attr<M> │ │ ╎ ╎
93/// └────────────┘ └─────────────────────────────────┘ │local_handle ╭───┴───╮ ╭─────┴──────╮
94/// │0..1 │ itr │ │ port, name │
95/// ┌───────┴────────┐ 1┌─┴───────┴─┴────────────┴─┐
96/// │ LocalDevHandle ├╌╌╌╌╌╌┤ local registry │
97/// └────────────────┘ keys└──────────────────────────┘
98/// ```
99///
100/// A solid line is an [`Arc`], a dashed one a [`Weak`]. An end of a line has a
101/// multiplicity, and the name of the field holding it, only when the class at the other end
102/// reaches it: an end without one is not reached through that line. A field holding the
103/// other end as a trait object is written `field: Trait`. A rounded box is the key of a map
104/// of the class it hangs from, which holds at most one of the other end per key.
105/// `LocalDevHandle` holds the keys of the entries of its device, which it takes out of the
106/// registry when dropped, and a weak reference to the device, not drawn, which only tells
107/// its entries from those of a device registered since.
108///
109/// The backend is given each device as a `dyn BackendDev`, which is the `DevImpl<M>`
110/// wrapper of a [`Dev<M>`]. A [`DevProxy`](crate::dev::DevProxy) holds the backend it
111/// reaches its device through as a `dyn BackendDev` too, which is the device itself when it
112/// is served by this process and found in the registry, and a client of the protocol of the
113/// backend otherwise.
114///
115/// The commands and attributes of a device, kept in its `mutable` field, each hold their
116/// definition, not drawn, which is shared with the [`ClassDef`] of its class.
117///
118/// Every solid line points down from the handle: the only links going back up are the weak
119/// `core` field and those of the local registry. Dropping the handle stops the backend, and
120/// frees everything once nothing else holds the core, which a request running a
121/// [`Self::sync_async`] or a [`Self::stop_async`] does until it ends, see [`ServerHandle`].
122///
123/// The local registry only ever holds devices weakly, so it never keeps one alive, while a
124/// client of this process holds the device it found for as long as it is connected to it,
125/// which refuses its requests once withdrawn, see [`Dev::is_withdrawn`]. A device is taken
126/// out of the registry, by dropping its `LocalDevHandle`, before it is removed from the
127/// backend, so that local clients stop finding it first.
128#[derive(Debug)]
129pub struct Server {
130 /// What owns the classes, the devices and the backend of that server, which is only
131 /// there for as long as it is served, see [`Self::core`].
132 core: Weak<Core>,
133 /// The `dserver/exe/inst` name of the admin device of that server, which is where its
134 /// own `exe/inst` name is taken from, see [`Self::name`].
135 pub(super) admin_dev_name: Arc<str>,
136 /// The database proxy used for that server.
137 database: DatabaseProxy,
138 /// The subscriptions to the events of the attributes of the devices of that server, by
139 /// device and attribute name.
140 ///
141 /// They are the server's and not the devices': a device restarted, or a whole server
142 /// restarted, is made anew under the same name, and so are its attributes on every
143 /// Init, while its subscribers are kept, the way cppTango keeps them. A client of a
144 /// server that is still running sees nothing of a restart, so nothing would make it
145 /// subscribe again.
146 ///
147 /// The streams handed out end, after an [`ErrorKind::DevNotConnected`], once the device
148 /// is gone for good, see [`Self::sync_async`], or the server stops, see
149 /// [`Self::stop_async`]: the end of a subscription of a backend, see
150 /// [`crate::backend::BackendDev`].
151 events: Mutex<HashMap<ArcName, HashMap<ArcName, AttrEvents>>>,
152 /// Whether the devices of that server are reached directly by the clients of this
153 /// process, see [`ServerBuilder::local`].
154 pub(super) local: bool,
155}
156
157/// The owner of the classes, the devices and the backend of a server, which only its
158/// [`ServerHandle`] holds and which is never handed out: the [`Server`] reaches it weakly,
159/// see [`Server::core`], which is what keeps the ownership of a server a tree.
160///
161/// The methods of the server reaching what it owns hold it for the time of their call,
162/// across the whole of it for [`Server::sync_async`], [`Server::stop_async`] and
163/// [`Server::wait_async`], so that a call started is finished before the devices go.
164#[derive(Debug)]
165pub(super) struct Core {
166 /// The server, which the handle derefs to.
167 server: Arc<Server>,
168 /// The backend serving the devices of that server.
169 backend: Arc<dyn BackendServer>,
170 /// The classes of that server.
171 classes: Mutex<HashMap<ArcName, Arc<dyn AnyClass>>>,
172 /// The number of classes made for that server so far, which is the index of the next
173 /// one, see [`AnyClass::index`].
174 class_count: AtomicUsize,
175 /// Every device of that server, device names being unique server-wide. This is the
176 /// lock every addition of a device is made under, see [`Class::add_dev`].
177 pub(super) devs: Mutex<HashMap<ArcName, Arc<dyn AnyDev>>>,
178 /// What the next [`Server::sync_async`] applies, which is never locked with any other lock.
179 pub(super) pending: Mutex<Pending>,
180 /// Held for the whole of a [`Server::sync_async`], so that two of them never interleave, and
181 /// for the whole of a [`Server::stop_async`], which [`Server::wait`] waits for through it.
182 sync_lock: async_lock::Mutex<()>,
183 /// Whether that server was stopped, which is only ever done once.
184 stopped: AtomicBool,
185 /// The polling of the devices of that server, see [`Poller`], which ends with it.
186 poller: Poller,
187}
188
189impl Drop for Core {
190
191 /// Stop the backend, which the handle did already unless this outlived it: a backend
192 /// stops for good once nothing holds its server anymore, whatever it was serving.
193 ///
194 /// Every device left is marked withdrawn and taken out of the local registry, which a
195 /// stopped server has none of, see [`Server::stop_async`]: a server that ended without
196 /// being stopped never withdraws them, while its devices may still be held, by a thread
197 /// of their own or a client of this process in particular.
198 fn drop(&mut self) {
199 self.backend.stop();
200 self.poller.shutdown();
201 let removed = &self.pending.get_mut().unwrap().removed;
202 for dev in self.devs.get_mut().unwrap().values().chain(removed) {
203 dev.withdraw_now();
204 }
205 }
206
207}
208
209/// The subscribers of the events of an attribute, see [`Server::events`].
210#[derive(Debug, Default)]
211struct AttrEvents {
212 values: HashMap<AttrValueEvent, Subscribers<AttrRead<Value>>>,
213 ready: Subscribers<AttrReady>,
214 conf: Subscribers<AttrInfo>,
215}
216
217/// The subscribers of an event, which only hold their slot weakly: a subscriber dropping
218/// its stream is what unsubscribes it, its slot being pruned the next time the event is
219/// pushed or subscribed to.
220type Subscribers<T> = Vec<Weak<Slot<Result<T>>>>;
221
222/// The operations on the devices of a server that wait for its next [`Server::sync_async`].
223#[derive(Debug, Default)]
224pub struct Pending {
225 /// The devices added and not initialized yet, in the order they were added.
226 pub added: Vec<Arc<dyn AnyDev>>,
227 /// The devices initialized and not exported yet, either because they were just
228 /// initialized or because serving or exporting them failed, along with the reference
229 /// the backend serves them at once it does.
230 pub unexported: Vec<(Arc<dyn AnyDev>, Option<Arc<str>>)>,
231 /// The devices removed and still served, possibly still exported.
232 pub removed: Vec<Arc<dyn AnyDev>>,
233}
234
235impl Server {
236
237 /// The `exe/inst` name of that server, under which it is registered in the database.
238 #[inline]
239 pub fn name(&self) -> &str {
240 &self.admin_dev_name[ADMIN_DEV_PREFIX.len()..]
241 }
242
243 /// The name of the admin device of that server, `dserver/exe/inst`.
244 #[inline]
245 pub fn admin_dev_name(&self) -> &str {
246 &self.admin_dev_name
247 }
248
249 /// The database that server is registered in.
250 #[inline]
251 pub fn database(&self) -> &DatabaseProxy {
252 &self.database
253 }
254
255 /// What owns the classes, the devices and the backend of that server, failing once it
256 /// is gone, which is once its handle is dropped and nothing else holds it, see
257 /// [`ServerHandle`].
258 pub(super) fn core_checked(&self) -> Result<Arc<Core>> {
259 self.core.upgrade().ok_or_else(|| Error::new(ErrorKind::Reason(reason::API_ServerNotRunning))
260 .with_description(format!("Server {:?} is not served anymore", self.name())))
261 }
262
263 /// The polling of the devices of that server, absent once it is not served anymore,
264 /// see [`Self::core`].
265 pub(super) fn poller(&self) -> Option<Poller> {
266 self.core.upgrade().map(|core| core.poller.clone())
267 }
268
269 /// The backend serving the devices of that server, failing once it is not served
270 /// anymore, see [`Self::core`].
271 pub(super) fn backend_checked(&self) -> Result<Arc<dyn BackendServer>> {
272 Ok(Arc::clone(&self.core_checked()?.backend))
273 }
274
275 /// The backend serving the devices of that server, [`None`] once it is not served
276 /// anymore, see [`ServerHandle`].
277 #[inline]
278 pub fn backend(&self) -> Option<Arc<dyn BackendServer>> {
279 self.core.upgrade().map(|core| Arc::clone(&core.backend))
280 }
281
282 /// Register a new class in this server, from its definition.
283 pub fn add_class<M: Model>(&self, def: ClassDef<M>) -> Result<Arc<Class<M>>> {
284
285 if !name::check_tango_class_name(&def.name) {
286 return Err(Error::new(ErrorKind::ClassNameInvalid)
287 .with_description(format!("Class {:?} has an invalid name, it should be made of \
288 letters, digits, '_' and '-'", def.name)));
289 }
290
291 let core = self.core_checked()?;
292 let def = Arc::new(def);
293 let mut classes = core.classes.lock().unwrap();
294 let name = ArcName::from(&*def.name);
295
296 let Entry::Vacant(entry) = classes.entry(name) else {
297 return Err(Error::new(ErrorKind::ClassAlreadyDefined)
298 .with_description(format!("Class {:?} is already defined on the server", def.name)));
299 };
300
301 let index = core.class_count.fetch_add(1, Ordering::Relaxed);
302 let class = Class::new(Arc::clone(&core.server), def, index);
303 entry.insert(Arc::clone(&class) as Arc<dyn AnyClass>);
304 Ok(class)
305
306 }
307
308 /// Get a class of this server from its name, if it is one of that model.
309 pub fn get_class<M: Model>(&self, name: &str) -> Option<Arc<Class<M>>> {
310 self.any_class(name)?.into_any().downcast().ok()
311 }
312
313 /// Get a class of this server from its name, whatever its model.
314 pub(super) fn any_class(&self, name: &str) -> Option<Arc<dyn AnyClass>> {
315 let core = self.core.upgrade()?;
316 core.classes.lock().unwrap().get(Name::new(name)).map(Arc::clone)
317 }
318
319 /// Add a device to this server, as an instance of the class of that name, which is how
320 /// the devices listed by the database are added, the database giving the class of each
321 /// by its name. See [`Class::add_dev`] for the typed form.
322 ///
323 /// The device is only registered: it is initialized, served and exported by the next
324 /// [`Self::sync_async`].
325 pub fn add_dev(&self, class: &str, name: &str) -> Result<()> {
326
327 let class = self.core_checked()?.classes.lock().unwrap()
328 .get(Name::new(class))
329 .map(Arc::clone)
330 .ok_or_else(|| Error::new(ErrorKind::ClassNotFound)
331 .with_description(format!("Class {class:?} is not defined on the server")))?;
332
333 class.add_dev(name).map(drop)
334
335 }
336
337 /// Remove the device of that name from this server, giving back whether it had one.
338 ///
339 /// Its name is free again right away, but the device itself is only unexported, no
340 /// longer served and deleted by the next [`Self::sync_async`]. A device removed before any
341 /// synchronization reached it is simply dropped.
342 pub fn remove_dev(&self, name: &str) -> bool {
343
344 let Some(core) = self.core.upgrade() else {
345 return false;
346 };
347
348 let Some(dev) = core.devs.lock().unwrap().remove(Name::new(name)) else {
349 return false;
350 };
351
352 // If the device was still pending to be added, then we just remove it, otherwise
353 // we also remove its unexported state and then add it to the devices to be
354 // removed.
355 let mut pending = core.pending.lock().unwrap();
356 if let Some(index) = pending.added.iter().position(|added| Arc::ptr_eq(added, &dev)) {
357 pending.added.remove(index);
358 } else {
359 pending.unexported.retain(|(unexported, _)| !Arc::ptr_eq(unexported, &dev));
360 pending.removed.push(dev);
361 }
362
363 true
364
365 }
366
367 /// Apply what was done to the devices of this server since the last synchronization:
368 /// the devices removed are unexported, no longer served and deleted, then the devices
369 /// added are initialized, served and exported, which is what makes them reachable.
370 ///
371 /// The devices added are initialized one after the other, class by class in the order
372 /// the classes were made, and in the order they were added within a class. A device
373 /// whose initialization adds devices has them initialized by this same
374 /// synchronization, which is how the admin device boots a server. Each device is then
375 /// served and exported on its own, which is what a Tango server always tells the
376 /// database.
377 ///
378 /// A device whose initialization failed is still served and exported, in FAULT, so
379 /// that a client can ask it what went wrong. A device that could not be served or
380 /// exported is retried by the next synchronization, and the first such error is given
381 /// back once every other device is done.
382 ///
383 /// Synchronizations never interleave: one waits for the one running to be done, so
384 /// that everything done before calling it is applied once it returns. This is also why
385 /// an init function must never call it, since it would wait for itself.
386 pub async fn sync_async(&self) -> Result<()> {
387
388 let Some(core) = self.core.upgrade() else {
389 return Ok(());
390 };
391
392 let _sync = core.sync_lock.lock().await;
393 if core.stopped.load(Ordering::Acquire) {
394 return Ok(());
395 }
396
397 let mut first_err = None;
398
399 // Begin with pending removal of devices, they are first unexported and then
400 // withdrawn from the backend.
401 let removed = mem::take(&mut core.pending.lock().unwrap().removed);
402 for dev in removed {
403
404 if let Err(err) = self.database.unexport_dev_async(dev.name()).await {
405 warn!(dev = %dev.name(), %err, "Failed to unexport the removed device");
406 first_err.get_or_insert(err);
407 }
408
409 if let Err(err) = dev.withdraw().await {
410 warn!(dev = %dev.name(), %err, "Failed to delete the removed device");
411 first_err.get_or_insert(err);
412 }
413
414 // A device added again under the same name, which is what a restart is, keeps
415 // the subscriptions of the one it replaces.
416 if !core.devs.lock().unwrap().contains_key(Name::new(dev.name())) {
417 self.end_dev_events(dev.name());
418 }
419
420 debug!(dev = %dev.name(), "Removed the device");
421
422 }
423
424 // Then we loop through added devices, we init their model and then we add them to
425 // the unexported list, which tells that they should be exported next!
426 loop {
427
428 let mut added = mem::take(&mut core.pending.lock().unwrap().added);
429 if added.is_empty() {
430 break;
431 }
432
433 added.sort_by_key(|dev| dev.class().index());
434 for dev in added {
435 // Only a panic of its init function ends here, a failed initialization
436 // being kept by the device itself: it is exported all the same.
437 if let Err(err) = dev.init().await {
438 warn!(dev = %dev.name(), %err, "Failed to complete the initialization of the device, its init function panicked");
439 }
440 core.pending.lock().unwrap().unexported.push((dev, None));
441 }
442
443 }
444
445 // Finally we process all the unexported devices by exporting them to the database.
446 let unexported = mem::take(&mut core.pending.lock().unwrap().unexported);
447 let mut failed = Vec::new();
448 for (dev, itr) in unexported {
449
450 let served = match itr {
451 Some(itr) => Ok(itr),
452 None => dev.serve(),
453 };
454
455 let itr = match served {
456 Ok(itr) => itr,
457 Err(err) => {
458 warn!(dev = %dev.name(), %err, "Failed to serve the device");
459 first_err.get_or_insert(err);
460 failed.push((dev, None));
461 continue;
462 }
463 };
464
465 if let Err(err) = self.export_dev(&*core.backend, &*dev, &itr).await {
466 warn!(dev = %dev.name(), %err, "Failed to export the device");
467 first_err.get_or_insert(err);
468 failed.push((dev, Some(itr)));
469 continue;
470 }
471
472 debug!(dev = %dev.name(), "Exported the device");
473
474 }
475
476 core.pending.lock().unwrap().unexported.extend(failed);
477 first_err.map_or(Ok(()), Err)
478
479 }
480
481 /// The blocking form of [`Self::sync_async`], which must therefore never run on the
482 /// executor of a backend, in an asynchronous handler in particular.
483 pub fn sync(&self) -> Result<()> {
484 block_on(self.sync_async())
485 }
486
487 /// Export a device served at that reference in the database, which is what a client
488 /// looks it up in.
489 async fn export_dev(&self, backend: &dyn BackendServer, dev: &dyn AnyDev, itr: &str) -> Result<()> {
490 self.database.export_dev_async(ExportDevInfo {
491 name: Cow::Borrowed(dev.name()),
492 itr: Cow::Borrowed(itr),
493 host: Cow::Borrowed(&backend.host()),
494 version: Cow::Owned(backend.version().to_string()),
495 pid: std::process::id() as i32,
496 }).await
497 }
498
499 /// The names of every class of this server, in the order they were made, the admin
500 /// one first.
501 pub fn class_names(&self) -> Vec<Arc<str>> {
502 self.any_classes().iter().map(|class| Arc::clone(class.name())).collect()
503 }
504
505 /// Every class of this server, whatever its model, see [`Self::class_names`].
506 pub(super) fn any_classes(&self) -> Vec<Arc<dyn AnyClass>> {
507 let Some(core) = self.core.upgrade() else {
508 return Vec::new();
509 };
510 let mut classes = core.classes.lock().unwrap().values().map(Arc::clone).collect::<Vec<_>>();
511 classes.sort_by_key(|class| class.index());
512 classes
513 }
514
515 /// The names of every device of this server, class by class in the order of
516 /// [`Self::class_names`], and by name within a class.
517 pub fn dev_names(&self) -> Vec<Arc<str>> {
518 self.any_devs().iter().map(|dev| Arc::clone(dev.name())).collect()
519 }
520
521 /// Every device of this server, whatever its model, see [`Self::dev_names`].
522 pub(super) fn any_devs(&self) -> Vec<Arc<dyn AnyDev>> {
523 let Some(core) = self.core.upgrade() else {
524 return Vec::new();
525 };
526 let mut devs = core.devs.lock().unwrap().values().map(Arc::clone).collect::<Vec<_>>();
527 devs.sort_by(|a, b| a.class().index().cmp(&b.class().index()).then_with(|| a.name().cmp(b.name())));
528 devs
529 }
530
531 /// Whether this server has a device of that name.
532 pub fn has_dev(&self, name: &str) -> bool {
533 self.core.upgrade().is_some_and(|core| core.devs.lock().unwrap().contains_key(Name::new(name)))
534 }
535
536 /// Get a device of this server from its name, if its class is one of that model.
537 pub fn get_dev<M: Model>(&self, name: &str) -> Option<Arc<Dev<M>>> {
538 self.any_dev(name)?.into_any().downcast().ok()
539 }
540
541 /// Get a device of this server from its name, whatever its model.
542 pub(super) fn any_dev(&self, name: &str) -> Option<Arc<dyn AnyDev>> {
543 let core = self.core.upgrade()?;
544 core.devs.lock().unwrap().get(Name::new(name)).map(Arc::clone)
545 }
546
547 /// Stop this server, which is only ever done once: it is unexported as a whole, so
548 /// that clients stop finding it, then its backend is stopped, the requests in flight
549 /// still being answered, and its devices are deleted, see [`Self::wait`] for what waits
550 /// for the backend to be through. No synchronization runs after this, the devices
551 /// still waiting for one never being served.
552 ///
553 /// The devices are deleted one after the other, the classes in the reverse of their
554 /// order, the admin device last, each once the requests still running on it are
555 /// through, see [`Dev::is_withdrawn`]: a request that never ends therefore keeps this
556 /// from ever returning. This is also why a request handler must never call it, since
557 /// it would wait for itself; the `Kill` command of the admin device stops its server
558 /// from the pool instead.
559 ///
560 /// The backend is stopped and the devices deleted even if the server could not be
561 /// unexported, and the first error met is given back.
562 pub async fn stop_async(&self) -> Result<()> {
563
564 let Some(core) = self.core.upgrade() else {
565 return Ok(());
566 };
567
568 let _sync = core.sync_lock.lock().await;
569 if core.stopped.swap(true, Ordering::AcqRel) {
570 return Ok(());
571 }
572
573 info!(server = %self.name(), "Stopping the server");
574
575 let unexported = self.database.unexport_server_async(self.name()).await;
576 if let Err(err) = &unexported {
577 warn!(server = %self.name(), %err, "Failed to unexport the server");
578 }
579
580 core.backend.stop();
581 core.poller.shutdown();
582 self.end_events();
583
584 // The devices removed and not synchronized yet first, as the next synchronization
585 // would have, then the others, the classes in the reverse of their order, the admin
586 // device last.
587 let removed = mem::take(&mut *core.pending.lock().unwrap()).removed;
588 let mut devs = mem::take(&mut *core.devs.lock().unwrap())
589 .into_values()
590 .collect::<Vec<_>>();
591
592 devs.sort_by_key(|dev| std::cmp::Reverse(dev.class().index()));
593
594 let mut first_err = unexported.err();
595 for dev in removed.into_iter().chain(devs) {
596 if let Err(err) = dev.withdraw().await {
597 warn!(dev = %dev.name(), %err, "Failed to delete the device");
598 first_err.get_or_insert(err);
599 }
600 }
601
602 info!(server = %self.name(), "Stopped the server");
603 first_err.map_or(Ok(()), Err)
604
605 }
606
607 /// The blocking form of [`Self::stop_async`], which must therefore never run on the
608 /// executor of a backend, in an asynchronous handler in particular.
609 pub fn stop(&self) -> Result<()> {
610 block_on(self.stop_async())
611 }
612
613 /// Wait for this server to be stopped, see [`Self::stop_async`], which is what the
614 /// thread running a server spends its life in: for its backend to be through with
615 /// every request, and for its devices to be deleted. A server that is not served
616 /// anymore, see [`ServerHandle`], is not waited for.
617 ///
618 /// The backend is waited for first, which is only through once stopped, see
619 /// [`BackendServer::wait`], then the stop itself, which deletes the devices under the
620 /// lock of the synchronizations. This waits for every request in flight, and must
621 /// therefore never be called from a request handler, which would wait for itself.
622 pub async fn wait_async(&self) {
623 let Some(core) = self.core.upgrade() else {
624 return;
625 };
626 core.backend.wait().await;
627 drop(core.sync_lock.lock().await);
628 }
629
630 /// The blocking form of [`Self::wait_async`], which must therefore never run on the
631 /// executor of a backend, in an asynchronous handler in particular. See
632 /// [`Self::wait_timeout`] for a wait that gives up.
633 pub fn wait(&self) {
634 block_on(self.wait_async())
635 }
636
637 /// Wait for this server to be stopped, see [`Self::wait_async`], giving up with
638 /// [`ErrorKind::TimedOut`] if the backend is still answering requests once the timeout
639 /// has run out, which a request that never ends makes it, or a server never stopped.
640 ///
641 /// The timeout only bounds the backend: once it is through, the deletion of the
642 /// devices is waited for, however long that takes.
643 pub fn wait_timeout(&self, timeout: Duration) -> Result<()> {
644 let Some(core) = self.core.upgrade() else {
645 return Ok(());
646 };
647 block_on_timeout(core.backend.wait(), timeout)
648 .map_err(|err| err.with_description(format!("Server {:?} is still answering requests after {timeout:?}", self.name())))?;
649 block_on(core.sync_lock.lock());
650 Ok(())
651 }
652
653 /// Subscribe to the readings of an attribute of a device, pushed for that event. Nothing
654 /// checks here that the device has the attribute, which is the device's to check.
655 pub(super) fn subscribe_attr_value(&self, dev: &str, attr: &str, event: AttrValueEvent) -> BoxStream<'static, Result<AttrRead<Value>>> {
656 self.subscribe_event(dev, attr, |events| events.values.entry(event).or_default()).boxed()
657 }
658
659 /// Subscribe to an attribute of a device being ready to be read.
660 pub(super) fn subscribe_attr_ready(&self, dev: &str, attr: &str) -> BoxStream<'static, Result<AttrReady>> {
661 self.subscribe_event(dev, attr, |events| &mut events.ready).boxed()
662 }
663
664 /// Subscribe to the configuration of an attribute of a device.
665 pub(super) fn subscribe_attr_config(&self, dev: &str, attr: &str) -> BoxStream<'static, Result<AttrInfo>> {
666 self.subscribe_event(dev, attr, |events| &mut events.conf).boxed()
667 }
668
669 /// Push a reading of an attribute of a device, for that event.
670 pub(super) fn push_attr_value(&self, dev: &str, attr: &str, event: AttrValueEvent, read: Result<AttrRead<Value>>) {
671 self.push_event(dev, attr, |events| events.values.entry(event).or_default(), read);
672 }
673
674 /// Push an attribute of a device being ready to be read.
675 pub(super) fn push_attr_ready(&self, dev: &str, attr: &str, ready: Result<AttrReady>) {
676 self.push_event(dev, attr, |events| &mut events.ready, ready);
677 }
678
679 /// Push the configuration of an attribute of a device.
680 pub(super) fn push_attr_config(&self, dev: &str, attr: &str, info: Result<AttrInfo>) {
681 self.push_event(dev, attr, |events| &mut events.conf, info);
682 }
683
684 fn subscribe_event<T>(&self, dev: &str, attr: &str, select: impl FnOnce(&mut AttrEvents) -> &mut Subscribers<T>) -> EventStream<T> {
685
686 let slot = Arc::new(Slot::new());
687
688 let dev = Arc::<str>::from(dev);
689 let mut devs = self.events.lock().unwrap();
690 let attrs = devs.entry(ArcName::from(Arc::clone(&dev))).or_default();
691 let events = attrs.entry(ArcName::from(attr)).or_default();
692 let subscribers = select(events);
693 subscribers.retain(|slot| slot.strong_count() != 0);
694 subscribers.push(Arc::downgrade(&slot));
695
696 EventStream {
697 dev,
698 slot,
699 ended: false,
700 }
701
702 }
703
704 fn push_event<T: Clone>(&self, dev: &str, attr: &str, select: impl FnOnce(&mut AttrEvents) -> &mut Subscribers<T>, event: Result<T>) {
705
706 let mut devs = self.events.lock().unwrap();
707 let Some(attrs) = devs.get_mut(Name::new(dev)) else { return };
708 let Some(events) = attrs.get_mut(Name::new(attr)) else { return };
709
710 // Pushed to under the lock, a slot only waking its subscriber.
711 let subscribers = select(events);
712 subscribers.retain(|slot| slot.strong_count() != 0);
713
714 // Each subscriber has its own copy of the event, the last one taking it as it is.
715 if let Some((last, others)) = subscribers.split_last() {
716
717 for slot in others.iter().filter_map(Weak::upgrade) {
718 slot.push(event.clone());
719 }
720
721 if let Some(slot) = last.upgrade() {
722 slot.push(event);
723 }
724
725 }
726
727 // What is left with no subscriber at all is removed, all the way up.
728 events.values.retain(|_, subscribers| !subscribers.is_empty());
729 if events.values.is_empty() && events.ready.is_empty() && events.conf.is_empty() {
730 attrs.remove(Name::new(attr));
731 if attrs.is_empty() {
732 devs.remove(Name::new(dev));
733 }
734 }
735
736 }
737
738 /// End the subscriptions to the events of that device, which is gone for good.
739 fn end_dev_events(&self, dev: &str) {
740 let attrs = self.events.lock().unwrap().remove(Name::new(dev));
741 for events in attrs.into_iter().flat_map(HashMap::into_values) {
742 events.end();
743 }
744 }
745
746 /// End every subscription, the server having stopped.
747 fn end_events(&self) {
748 let devs = mem::take(&mut *self.events.lock().unwrap());
749 for events in devs.into_values().flat_map(HashMap::into_values) {
750 events.end();
751 }
752 }
753
754}
755
756impl AttrEvents {
757
758 /// End the subscriptions of every subscriber still there.
759 fn end(self) {
760 for subscribers in self.values.into_values() {
761 end_subscribers(subscribers);
762 }
763 end_subscribers(self.ready);
764 end_subscribers(self.conf);
765 }
766
767}
768
769fn end_subscribers<T>(subscribers: Subscribers<T>) {
770 for slot in subscribers.iter().filter_map(Weak::upgrade) {
771 slot.end();
772 }
773}
774
775/// The events of one subscriber, which unsubscribes by being dropped, see [`Subscribers`].
776struct EventStream<T> {
777 /// The name of the device the events are of, which the end of the subscription names.
778 dev: Arc<str>,
779 slot: Arc<Slot<Result<T>>>,
780 /// Set once the end of the subscription was given.
781 ended: bool,
782}
783
784impl<T> Stream for EventStream<T> {
785
786 type Item = Result<T>;
787
788 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
789
790 let this = self.get_mut();
791 if this.ended {
792 return Poll::Ready(None);
793 }
794
795 // The end of the slot is given as the end of the subscription, once.
796 this.slot.poll_take(cx).map(|event| event.or_else(|| {
797 this.ended = true;
798 Some(Err(Error::new(ErrorKind::DevNotConnected)
799 .with_description(format!("Device {:?} is no longer served", this.dev))))
800 }))
801
802 }
803
804}
805
806/// What a server is built with, and served by, see [`Self::serve`].
807pub struct ServerBuilder {
808 exe: String,
809 inst: String,
810 backend: Option<Arc<dyn Backend>>,
811 database: Option<DatabaseProxy>,
812 /// How the backend serves, see [`Self::host`] and [`Self::port`].
813 config: BackendServerConfig,
814 /// See [`Self::local`].
815 local: bool,
816 /// See [`Self::stop_on_terminate`].
817 stop_on_terminate: bool,
818 /// See [`Self::terminate_on_signals`].
819 #[cfg(feature = "cli")]
820 terminate_on_signals: bool,
821 /// See [`Self::boot_timeout`].
822 boot_timeout: Duration,
823 /// The database for testing the server is registered in, which the server owns for
824 /// as long as it runs, see [`ServerHandle`].
825 test_context: Option<TestContext>,
826 /// The definitions of the classes of that server, each made a class once the server
827 /// exists, which is only once it is served: a class owns the server it is in. Kept in
828 /// the order they were defined, which is the order their devices are initialized in.
829 classes: Vec<(ArcName, Arc<dyn AnyClassDef>)>,
830}
831
832/// A class definition of any model, which is how a [`ServerBuilder`] holds them.
833trait AnyClassDef: Send + Sync {
834 fn new_class(self: Arc<Self>, server: Arc<Server>, index: usize) -> Arc<dyn AnyClass>;
835}
836
837impl<M: Model> AnyClassDef for ClassDef<M> {
838 fn new_class(self: Arc<Self>, server: Arc<Server>, index: usize) -> Arc<dyn AnyClass> {
839 Class::new(server, self, index)
840 }
841}
842
843impl ServerBuilder {
844
845 /// Build a server named `exe/inst`, after the executable running it and the name of
846 /// the instance of that executable, which is how it is registered in the database.
847 pub fn new(exe: &str, inst: &str) -> Self {
848 Self {
849 exe: exe.to_string(),
850 inst: inst.to_string(),
851 backend: None,
852 database: None,
853 config: BackendServerConfig::default(),
854 local: true,
855 stop_on_terminate: false,
856 #[cfg(feature = "cli")]
857 terminate_on_signals: false,
858 boot_timeout: DEFAULT_BOOT_TIMEOUT,
859 test_context: None,
860 classes: Vec::new(),
861 }
862 }
863
864 /// The backend to serve with, the default one if none is given, see
865 /// [`default_backend`].
866 pub fn backend(mut self, backend: Arc<dyn Backend>) -> Self {
867 self.backend = Some(backend);
868 self
869 }
870
871 /// The database to register in, the one of the environment if none is given.
872 pub fn database(mut self, database: DatabaseProxy) -> Self {
873 self.database = Some(database);
874 self
875 }
876
877 /// The host to listen at, see [`BackendServerConfig::host`].
878 pub fn host(mut self, host: &str) -> Self {
879 self.config = self.config.host(host);
880 self
881 }
882
883 /// The port to listen at, see [`BackendServerConfig::port`].
884 pub fn port<R: RangeBounds<u16>>(mut self, port: R) -> Self {
885 self.config = self.config.port(port);
886 self
887 }
888
889 /// Make ZMQ listen at this port for its heartbeat, see
890 /// [`BackendServerConfig::zmq_heartbeat_port`].
891 pub fn zmq_heartbeat_port<R: RangeBounds<u16>>(mut self, port: R) -> Self {
892 self.config = self.config.zmq_heartbeat_port(port);
893 self
894 }
895
896 /// Make ZMQ listen at this port for its events, see
897 /// [`BackendServerConfig::zmq_event_port`].
898 pub fn zmq_event_port<R: RangeBounds<u16>>(mut self, port: R) -> Self {
899 self.config = self.config.zmq_event_port(port);
900 self
901 }
902
903 /// Enable or disable registration of this server's devices into the local registry,
904 /// which allows a [`DevProxy`](crate::dev::DevProxy) created in this same process to
905 /// access the device directly without going through the backend's wire protocol.
906 /// Enabled by default.
907 pub fn local(mut self, local: bool) -> Self {
908 self.local = local;
909 self
910 }
911
912 /// Define a class in that server, whose devices the database can then list.
913 ///
914 /// # Panics
915 ///
916 /// If the name of the class is invalid, see [`name::check_tango_class_name`], if it is
917 /// the one of the admin class, or if the server already defines a class of that name.
918 #[track_caller]
919 pub fn class<M: Model>(mut self, def: ClassDef<M>) -> Self {
920
921 if !name::check_tango_class_name(&def.name) {
922 panic!("the class name {:?} is invalid", def.name);
923 }
924
925 if def.name.eq_ignore_ascii_case(admin::CLASS_NAME) {
926 panic!("the class name {:?} is reserved to the admin device", def.name);
927 }
928
929 if self.classes.iter().any(|(name, _)| **name == *Name::new(&def.name)) {
930 panic!("the class {:?} is already defined", def.name);
931 }
932
933 self.classes.push((ArcName::from(&*def.name), Arc::new(def)));
934 self
935
936 }
937
938 /// Stop the server when the process terminates, see [`terminate`], which is not the
939 /// default unless built from the command line, see [`Self::terminate_on_signals`]. The
940 /// server is then stopped as the `Kill` command of its admin device does, which deletes
941 /// its devices, see [`Server::stop_async`], and the thread waiting on it returns, see
942 /// [`Server::wait`]. A server still booting gives up its boot, see [`Self::serve`].
943 ///
944 /// [`terminate`]: super::terminate()
945 pub fn stop_on_terminate(mut self, stop_on_terminate: bool) -> Self {
946 self.stop_on_terminate = stop_on_terminate;
947 self
948 }
949
950 /// How long the server is given to boot when served blocking, 30 seconds by default,
951 /// see [`Self::serve`]: the database being reached, every device initialized and every
952 /// one of them exported. An asynchronous caller bounds [`Self::serve_async`] itself.
953 pub fn boot_timeout(mut self, boot_timeout: Duration) -> Self {
954 self.boot_timeout = boot_timeout;
955 self
956 }
957
958 /// Boot the server, see [`Self::serve_async`].
959 async fn boot(self) -> Result<ServerHandle> {
960
961 let backend = self.backend.unwrap_or_else(default_backend);
962 let database = self.database
963 .unwrap_or_else(|| DatabaseProxy::new_from_env_with_backend(Arc::clone(&backend)));
964
965 // The backend names the events of the server after the server and its database,
966 // which is therefore reached before anything is served.
967 let admin_dev_name = Arc::<str>::from(format!("{ADMIN_DEV_PREFIX}{}/{}", self.exe, self.inst));
968 let (tango_host, tango_port) = database.host_and_port_async().await?;
969 let config = self.config.clone()
970 .admin_name(Arc::clone(&admin_dev_name))
971 .tango_host(tango_host, tango_port);
972
973 let backend = backend.serve(&config).await?;
974 let poller = Poller::spawn()?;
975
976 let core = Arc::new_cyclic(|core| Core {
977 server: Arc::new(Server {
978 core: core.clone(),
979 admin_dev_name,
980 database,
981 events: Mutex::new(HashMap::new()),
982 local: self.local,
983 }),
984 backend,
985 classes: Mutex::new(HashMap::new()),
986 class_count: AtomicUsize::new(1 + self.classes.len()),
987 devs: Mutex::new(HashMap::new()),
988 pending: Mutex::new(Pending::default()),
989 sync_lock: async_lock::Mutex::new(()),
990 stopped: AtomicBool::new(false),
991 poller,
992 });
993
994 // The admin class is made first, its device being the one booting the others, and
995 // is kept typed, which is what its device is added through.
996 let admin = Class::new(Arc::clone(&core.server), Arc::new(Admin::def()), 0);
997 let mut classes = HashMap::new();
998 classes.insert(ArcName::from(admin::CLASS_NAME), Arc::clone(&admin) as Arc<dyn AnyClass>);
999 for (index, (name, def)) in self.classes.into_iter().enumerate() {
1000 classes.insert(name, def.new_class(Arc::clone(&core.server), 1 + index));
1001 }
1002 *core.classes.lock().unwrap() = classes;
1003
1004 // From here the handle owns the server, which it stops if anything fails.
1005 let handle = ServerHandle { core, _test_context: self.test_context };
1006 let admin_dev = admin.add_dev(handle.admin_dev_name())?;
1007
1008 let booted = match handle.sync_async().await {
1009 Ok(()) => admin_dev.check_model().await,
1010 Err(err) => Err(err),
1011 };
1012
1013 if let Err(err) = booted {
1014 // The admin device may have been exported in FAULT, which is undone here at
1015 // best: a server failing to boot usually has no database to tell anything.
1016 let _ = handle.stop_async().await;
1017 handle.wait_async().await;
1018 return Err(err);
1019 }
1020
1021 drop(admin_dev);
1022
1023 info!(server = %handle.name(),
1024 host = %handle.core.backend.host(),
1025 port = handle.core.backend.port(),
1026 devs = handle.core.devs.lock().unwrap().len() - 1, "Started the server");
1027
1028 Ok(handle)
1029
1030 }
1031
1032 /// Start serving: the backend is acquired, every class is made from its definition,
1033 /// and the admin device is added and synchronized, which boots the whole server.
1034 ///
1035 /// This fails if the admin device fails to initialize, which is what a server that
1036 /// cannot reach its database does: it would have nothing to serve.
1037 ///
1038 /// This blocks, see [`Self::serve_async`] for what does not, and fails once the server
1039 /// did not boot within its timeout, see [`Self::boot_timeout`], or once the process
1040 /// terminates while it boots, see [`Self::stop_on_terminate`]. The boot is then given
1041 /// up wherever it was, so devices it had exported already stay exported in the
1042 /// database until the server is served again.
1043 pub fn serve(self) -> Result<ServerHandle> {
1044 let boot_timeout = self.boot_timeout;
1045 let server_name = format!("{}/{}", self.exe, self.inst);
1046 block_on_timeout(self.serve_async(), boot_timeout)
1047 .map_err(|err| err.with_description(format!("Server {server_name:?} did not boot within {boot_timeout:?}")))?
1048 }
1049
1050 /// Start serving, see [`Self::serve`], resolving once the whole server is booted.
1051 pub async fn serve_async(self) -> Result<ServerHandle> {
1052
1053 let server_name = format!("{}/{}", self.exe, self.inst);
1054 if !name::check_tango_server_part_name(&self.exe)
1055 || !name::check_tango_server_part_name(&self.inst) {
1056 return Err(Error::new(ErrorKind::ServerNameInvalid)
1057 .with_description(format!("Server {server_name:?} has an invalid name, it should be \
1058 exe/inst, each part made of letters, digits, '_' and '-'")));
1059 }
1060
1061 // Before anything is served, which a handler that cannot be installed then spares.
1062 #[cfg(feature = "cli")]
1063 if self.terminate_on_signals {
1064 cli::install_signal_handler()?;
1065 }
1066
1067 let stop_on_terminate = self.stop_on_terminate;
1068 let boot = pin!(self.boot());
1069 if !stop_on_terminate {
1070 return boot.await;
1071 }
1072
1073 let handle = match future::select(boot, pin!(terminate::terminating())).await {
1074 Either::Left((booted, _)) => booted?,
1075 Either::Right(((), _)) => return Err(Error::new(ErrorKind::Aborted)
1076 .with_description(format!("Server {server_name:?} did not finish booting, the process is terminating"))),
1077 };
1078
1079 // The process may have terminated right after the boot, the server being missed.
1080 if terminate::register(&handle.core.server) {
1081 let _ = handle.stop_async().await;
1082 }
1083
1084 Ok(handle)
1085
1086 }
1087
1088 /// Serve until the server is stopped, by [`terminate`](super::terminate()) (on a signal
1089 /// when [`Self::terminate_on_signals`] is set) or by the `Kill` command of its admin
1090 /// device, which deletes its devices: this is [`Self::serve`] then [`Server::wait`],
1091 /// which is all the main thread of most servers does.
1092 pub fn run(self) -> Result<()> {
1093 self.serve()?.wait();
1094 Ok(())
1095 }
1096
1097 /// Serve until the server is stopped, see [`Self::run`].
1098 pub async fn run_async(self) -> Result<()> {
1099 self.serve_async().await?.wait_async().await;
1100 Ok(())
1101 }
1102
1103}
1104
1105#[cfg(feature = "cli")]
1106impl ServerBuilder {
1107
1108 /// Terminate the process on the signals it is asked to terminate with, see
1109 /// [`terminate::terminate`], which a server built from the command line does: Ctrl-C, and SIGTERM
1110 /// and SIGHUP on Unix, the console being closed on Windows. Handling them also stops
1111 /// the server on termination, see [`Self::stop_on_terminate`].
1112 ///
1113 /// There is a single handler of these signals per process, which serving fails to
1114 /// install if the application installed one of its own: this is then disabled, and
1115 /// the application calls [`terminate::terminate`] from its own handler.
1116 pub fn terminate_on_signals(mut self, terminate_on_signals: bool) -> Self {
1117 self.terminate_on_signals = terminate_on_signals;
1118 if terminate_on_signals {
1119 self = self.stop_on_terminate(true);
1120 }
1121 self
1122 }
1123
1124 /// Build the server from the command line of this process, see [`ServerArgs`], which
1125 /// is what launching a server usually takes. The process exits with its usage when
1126 /// the command line is invalid or asks for help.
1127 ///
1128 /// See [`Self::from_raw_args`] for what the server is named after.
1129 pub fn from_args() -> Self {
1130 Self::from_raw_args(None, None)
1131 }
1132
1133 /// Build the server named after that executable and the instance of that command
1134 /// line, see [`ServerArgs`], which is also where it listens. The logs of the process
1135 /// are printed at the level it asks for.
1136 ///
1137 /// With no executable given, the server is named after the one of this process, as
1138 /// cppTango names it: the name the process was run under, without its directory nor
1139 /// the suffix of the platform's executables, which is what the Starter of a host runs
1140 /// a server by. Giving one keeps the name of the server whatever its file is called.
1141 ///
1142 /// With no command line given, the one of this process is parsed, as
1143 /// [`Self::from_args`] does; a server with options of its own parses it itself and
1144 /// gives what it flattened, see [`ServerArgs`].
1145 pub fn from_raw_args(exec: Option<&str>, args: Option<&ServerArgs>) -> Self {
1146
1147 use std::process;
1148
1149 use clap::{Args, Command, FromArgMatches};
1150 use tracing_subscriber::filter::LevelFilter;
1151 use tracing_subscriber::EnvFilter;
1152
1153 let exec = exec.map(Cow::Borrowed).unwrap_or_else(|| Cow::Owned(cli::exe()));
1154
1155 let args = match args {
1156 Some(args) => Cow::Borrowed(args),
1157 None => {
1158 let matches = ServerArgs::augment_args(Command::new(exec.to_string())).get_matches();
1159 let args = ServerArgs::from_arg_matches(&matches).unwrap_or_else(|err| err.exit());
1160 Cow::Owned(args)
1161 }
1162 };
1163
1164 // The subscriber printing the logs of the process, at the level asked for unless
1165 // `RUST_LOG` says otherwise. An application that installed one of its own keeps it.
1166 let level = match args.verbose {
1167 0 => LevelFilter::INFO,
1168 1 => LevelFilter::DEBUG,
1169 _ => LevelFilter::TRACE,
1170 };
1171
1172 let _ = tracing_subscriber::fmt()
1173 .with_env_filter(EnvFilter::builder()
1174 .with_default_directive(level.into())
1175 .from_env_lossy())
1176 .try_init();
1177
1178 let mut builder = Self::new(&exec, &args.inst)
1179 .terminate_on_signals(true);
1180
1181 if let Some(host) = &args.host {
1182 builder = builder.host(host);
1183 }
1184
1185 if let Some((start, end)) = args.port {
1186 builder = builder.port(start..=end);
1187 }
1188
1189 if let Some((start, end)) = args.zmq_heartbeat_port {
1190 builder = builder.zmq_heartbeat_port(start..=end);
1191 }
1192
1193 if let Some((start, end)) = args.zmq_event_port {
1194 builder = builder.zmq_event_port(start..=end);
1195 }
1196
1197 // The database for testing, served from now on, which the server is registered in
1198 // and owns: failing to serve it is failing to launch the server at all.
1199 if !args.devs.is_empty() {
1200 let ctx = cli::test_context(&exec, &args).unwrap_or_else(|err| {
1201 eprintln!("Error: {err:#}");
1202 process::exit(1)
1203 });
1204 builder = builder.database(ctx.database().clone());
1205 builder.test_context = Some(ctx);
1206 }
1207
1208 builder
1209
1210 }
1211
1212}
1213
1214/// The handle to a server being served, which is what owns it on behalf of its caller, and
1215/// derefs to it.
1216///
1217/// A server ends by being stopped, see [`Server::stop_async`], which deletes its devices, by its
1218/// owner or by a client through the `Kill` command of its admin device, and is waited for
1219/// by its owner, see [`Server::wait`]. A server is always stopped: dropping the handle of a
1220/// server that was not only stops its backend, with no other side effect, see [`Drop`].
1221#[derive(Debug)]
1222pub struct ServerHandle {
1223 /// What owns the server, which only the handle holds for good.
1224 core: Arc<Core>,
1225 /// The database for testing the server is registered in, if any, which is dropped
1226 /// after it, the server being unregistered from it once it is waited for.
1227 _test_context: Option<TestContext>,
1228}
1229
1230impl ServerHandle {
1231
1232 /// The server this handle serves.
1233 #[inline]
1234 pub fn server(&self) -> &Server {
1235 &self.core.server
1236 }
1237
1238 /// The server, shared, which does not keep it served: once the handle is dropped, see
1239 /// [`Drop`], it is not served anymore.
1240 pub(crate) fn server_arc(&self) -> Arc<Server> {
1241 Arc::clone(&self.core.server)
1242 }
1243
1244}
1245
1246impl Deref for ServerHandle {
1247
1248 type Target = Server;
1249
1250 #[inline]
1251 fn deref(&self) -> &Server {
1252 &self.core.server
1253 }
1254
1255}
1256
1257impl Drop for ServerHandle {
1258
1259 /// Stop the backend and end the subscriptions, with no other side effect: a server
1260 /// that was not stopped, see [`Server::stop_async`], is not unexported, and its models are
1261 /// not deleted. The requests in flight are not waited for, and everything of the server
1262 /// is let go of once they end, see [`BackendServer`], a request still holding it for
1263 /// the time of a [`Server::sync_async`] or a [`Server::stop_async`] it runs.
1264 fn drop(&mut self) {
1265 self.core.backend.stop();
1266 self.core.server.end_events();
1267 }
1268
1269}
1270
1271#[cfg(test)]
1272mod tests {
1273
1274 use futures::executor::block_on;
1275 use futures::FutureExt;
1276
1277 use crate::dev::{AttrQuality, DevState};
1278 use crate::value::AttrDataKind;
1279 use crate::testing::TestContext;
1280
1281 use super::super::def::ClassDef;
1282 use super::*;
1283
1284
1285 /// A server with a device `a/b/c` of a class `A`, served and synchronized.
1286 fn serve() -> (TestContext, Arc<Server>) {
1287
1288 let ctx = TestContext::new().unwrap();
1289 ctx.database().add_server("Test/test", &[("a/b/c", "A")]).unwrap();
1290
1291 let server = ctx.serve(ServerBuilder::new("Test", "test")
1292 .class(ClassDef::<()>::new_default("A")))
1293 .unwrap();
1294
1295 (ctx, server)
1296
1297 }
1298
1299 fn read(value: f64) -> AttrRead<Value> {
1300 AttrRead {
1301 value: Some(Value::from(value)),
1302 w_value: None,
1303 quality: AttrQuality::Valid,
1304 time: std::time::SystemTime::UNIX_EPOCH + Duration::from_secs(1),
1305 }
1306 }
1307
1308 /// The next item of a stream, if there is one already.
1309 fn now<T>(stream: &mut BoxStream<'static, T>) -> Option<Option<T>> {
1310 stream.next().now_or_never()
1311 }
1312
1313 #[test]
1314 fn latest_only() {
1315
1316 let (_ctx, server) = serve();
1317 let mut sub = server.subscribe_attr_value("a/b/c", "Attr", AttrValueEvent::Change);
1318
1319 assert!(now(&mut sub).is_none());
1320
1321 server.push_attr_value("a/b/c", "attr", AttrValueEvent::Change, Ok(read(1.0)));
1322 server.push_attr_value("A/B/C", "ATTR", AttrValueEvent::Change, Ok(read(2.0)));
1323
1324 // Another event, or another attribute, reaches nothing.
1325 server.push_attr_value("a/b/c", "attr", AttrValueEvent::Archive, Ok(read(3.0)));
1326 server.push_attr_value("a/b/c", "other", AttrValueEvent::Change, Ok(read(4.0)));
1327
1328 assert_eq!(now(&mut sub).unwrap().unwrap().unwrap(), read(2.0));
1329 assert!(now(&mut sub).is_none());
1330
1331 }
1332
1333 #[test]
1334 fn every_subscriber() {
1335
1336 let (_ctx, server) = serve();
1337 let mut first = server.subscribe_attr_value("a/b/c", "attr", AttrValueEvent::Change);
1338 let mut second = server.subscribe_attr_value("a/b/c", "attr", AttrValueEvent::Change);
1339
1340 server.push_attr_value("a/b/c", "attr", AttrValueEvent::Change, Err(Error::new(ErrorKind::Reason(reason::API_AttrNotAllowed))));
1341
1342 for sub in [&mut first, &mut second] {
1343 let err = now(sub).unwrap().unwrap().unwrap_err();
1344 assert_eq!(err.kind(), ErrorKind::Reason(reason::API_AttrNotAllowed));
1345 }
1346
1347 }
1348
1349 #[test]
1350 fn unsubscribe() {
1351
1352 let (_ctx, server) = serve();
1353 let sub = server.subscribe_attr_ready("a/b/c", "attr");
1354 drop(sub);
1355
1356 // The push finds nothing to hand the event to, and forgets the attribute.
1357 server.push_attr_ready("a/b/c", "attr", Ok(AttrReady { data_kind: AttrDataKind::Long, counter: 1 }));
1358 assert!(server.events.lock().unwrap().is_empty());
1359
1360 }
1361
1362 #[test]
1363 fn restart() {
1364
1365 let (_ctx, server) = serve();
1366 let mut sub = server.subscribe_attr_config("a/b/c", "attr");
1367
1368 // Removed and added again under the same name, as a restart does.
1369 assert!(server.remove_dev("a/b/c"));
1370 server.add_dev("A", "a/b/c").unwrap();
1371 server.sync().unwrap();
1372 assert!(now(&mut sub).is_none());
1373
1374 // Removed for good.
1375 assert!(server.remove_dev("a/b/c"));
1376 server.sync().unwrap();
1377 assert_eq!(now(&mut sub).unwrap().unwrap().unwrap_err().kind(), ErrorKind::DevNotConnected);
1378 assert!(now(&mut sub).unwrap().is_none());
1379
1380 }
1381
1382 #[test]
1383 fn stop() {
1384
1385 let (_ctx, server) = serve();
1386 let mut sub = server.subscribe_attr_ready("a/b/c", "attr");
1387
1388 // The event pushed before the end is taken first.
1389 server.push_attr_ready("a/b/c", "attr", Ok(AttrReady { data_kind: AttrDataKind::Long, counter: 1 }));
1390 server.stop().unwrap();
1391
1392 assert!(now(&mut sub).unwrap().unwrap().is_ok());
1393 assert_eq!(now(&mut sub).unwrap().unwrap().unwrap_err().kind(), ErrorKind::DevNotConnected);
1394 assert!(now(&mut sub).unwrap().is_none());
1395
1396 }
1397
1398 #[test]
1399 fn weak() {
1400
1401 let (_ctx, server) = serve();
1402 let weak = Arc::downgrade(&server.any_dev("a/b/c").unwrap());
1403 assert_eq!(&**weak.upgrade().unwrap().name(), "a/b/c");
1404
1405 // Restarted under the same name, the weak reference is to the device that was.
1406 assert!(server.remove_dev("a/b/c"));
1407 server.add_dev("A", "a/b/c").unwrap();
1408 server.sync().unwrap();
1409 assert!(weak.upgrade().is_none());
1410
1411 }
1412
1413 #[test]
1414 fn dropped() {
1415
1416 let (ctx, server) = serve();
1417 let mut sub = server.subscribe_attr_ready("a/b/c", "attr");
1418 drop(ctx);
1419
1420 assert_eq!(block_on(sub.next()).unwrap().unwrap_err().kind(), ErrorKind::DevNotConnected);
1421
1422 }
1423
1424 #[test]
1425 fn freed() {
1426
1427 let (ctx, server) = serve();
1428 server.add_dev("A", "a/b/d").unwrap();
1429 let served = Arc::downgrade(&server.any_dev("a/b/c").unwrap());
1430 let pending = Arc::downgrade(&server.any_dev("a/b/d").unwrap());
1431 drop(ctx);
1432
1433 // Every device is let go of, those still waiting for a synchronization included,
1434 // while the server itself, still held, is not served anymore.
1435 assert!(served.upgrade().is_none());
1436 assert!(pending.upgrade().is_none());
1437 assert!(!server.has_dev("a/b/c"));
1438 assert_eq!(server.add_dev("A", "a/b/e").unwrap_err().kind(), ErrorKind::Reason(reason::API_ServerNotRunning));
1439 server.wait();
1440
1441 }
1442
1443 #[test]
1444 fn withdrawn() {
1445
1446 let (ctx, server) = serve();
1447 let dev = server.get_dev::<()>("a/b/c").unwrap();
1448 assert!(!dev.is_withdrawn());
1449 dev.push_user_event("state", DevState::On).unwrap();
1450
1451 // Restarted under the same name, the device held is not the one served anymore.
1452 assert!(server.remove_dev("a/b/c"));
1453 server.add_dev("A", "a/b/c").unwrap();
1454 server.sync().unwrap();
1455 assert!(dev.is_withdrawn());
1456 assert_eq!(dev.push_user_event("state", DevState::On).unwrap_err().kind(), ErrorKind::DevNotConnected);
1457
1458 // Nor is any once the server is not served anymore.
1459 let restarted = server.get_dev::<()>("a/b/c").unwrap();
1460 assert!(!restarted.is_withdrawn());
1461 drop(ctx);
1462 assert!(restarted.is_withdrawn());
1463
1464 }
1465
1466 #[test]
1467 fn withdrawn_local() {
1468
1469 let (ctx, server) = serve();
1470 let client = ctx.dev("a/b/c");
1471 client.ping().unwrap();
1472 assert!(ctx.is_local("a/b/c").unwrap());
1473
1474 // The proxy reaches the device itself, which is kept alive here once removed: it
1475 // is refused all the same, rather than answered as an uninitialized device, which
1476 // makes the proxy look it up again on its next request, and find it unexported.
1477 let dev = server.get_dev::<()>("a/b/c").unwrap();
1478 assert!(server.remove_dev("a/b/c"));
1479 server.sync().unwrap();
1480 assert!(dev.is_withdrawn());
1481 assert_eq!(client.ping().unwrap_err().kind(), ErrorKind::DevNotConnected);
1482 assert_eq!(client.state().unwrap_err().kind(), ErrorKind::DevNotExported);
1483
1484 }
1485
1486 #[test]
1487 fn wait_twice() {
1488
1489 let (_ctx, server) = serve();
1490 server.stop().unwrap();
1491 server.wait();
1492 server.wait();
1493 assert!(server.dev_names().is_empty());
1494
1495 }
1496
1497}