1use crate::collections::{HashMap, HashSet};
4use crate::prelude::*;
5use alloc::sync::Arc;
6
7use bacnet_types::enums::{ErrorClass, ErrorCode, ObjectType};
8use bacnet_types::error::Error;
9use bacnet_types::primitives::ObjectIdentifier;
10
11use crate::clock::{ClockFrame, ClockReader};
12use crate::event_enrollment::EventEnrollmentMonitoredSource;
13use crate::traits::{BACnetObject, DeadlineWaker, MonotonicClock};
14
15mod averaging_sampling;
16mod event_algorithm_inhibit;
17mod event_log;
18mod input_references;
19mod local_device;
20mod membership;
21mod network_port;
22mod trend_poll;
23pub use local_device::LocalDevice;
24#[doc(hidden)]
25pub use membership::{MembershipWaker, MembershipWork};
26use trend_poll::TrendPollSchedule;
27
28pub struct ObjectDatabase {
33 audit_owner: Option<alloc::sync::Weak<AuditOwnership>>,
34 network_port: Option<network_port::NetworkPortRegistration>,
35 objects: HashMap<ObjectIdentifier, Box<dyn BACnetObject>>,
36 trend_poll: TrendPollSchedule,
37 clock: Option<Arc<dyn ClockReader>>,
39 monotonic_clock: Option<Arc<MonotonicClock>>,
40 deadline_waker: Option<Arc<DeadlineWaker>>,
42 event_sequence: Arc<EventSequence>,
44 name_index: HashMap<String, ObjectIdentifier>,
46 type_index: HashMap<ObjectType, Vec<ObjectIdentifier>>,
48 invalid_enrollment_eval_state: HashSet<ObjectIdentifier>,
51 enrollment_eval_sources: HashMap<ObjectIdentifier, EventEnrollmentMonitoredSource>,
54 membership: membership::MembershipQueue,
56}
57
58#[doc(hidden)]
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub struct EventSequenceReservation {
62 number: u16,
63}
64
65impl EventSequenceReservation {
66 #[doc(hidden)]
68 pub fn number(self) -> u16 {
69 self.number
70 }
71}
72
73mod audit_ownership;
74mod event_sequence;
75pub use audit_ownership::AuditOwnership;
76pub use event_sequence::EventSequence;
77
78impl Default for ObjectDatabase {
79 fn default() -> Self {
80 Self::new()
81 }
82}
83
84impl ObjectDatabase {
85 pub fn new() -> Self {
87 Self {
88 objects: HashMap::new(),
89 trend_poll: TrendPollSchedule::default(),
90 clock: None,
91 monotonic_clock: None,
92 deadline_waker: None,
93 event_sequence: Arc::default(),
94 audit_owner: None,
95 network_port: None,
96 name_index: HashMap::new(),
97 type_index: HashMap::new(),
98 invalid_enrollment_eval_state: HashSet::new(),
99 enrollment_eval_sources: HashMap::new(),
100 membership: membership::MembershipQueue::default(),
101 }
102 }
103
104 pub fn add(&mut self, mut object: Box<dyn BACnetObject>) -> Result<(), Error> {
119 self.check_network_port_membership(&object.object_identifier())?;
120 self.check_audit_membership(&object.object_identifier(), true)?;
121 object.bind_clock_internal(self.clock.clone());
122 object.bind_monotonic_clock_internal(self.monotonic_clock.clone());
123 object.bind_deadline_waker_internal(self.deadline_waker.clone());
124 let oid = object.object_identifier();
125 let name = object.object_name().to_string();
126
127 self.check_name_available(&oid, &name)?;
129
130 if let Some(old) = self.objects.get(&oid) {
133 if let Some(reporter) = old.audit_reporter_internal() {
134 reporter.status_internal().configuration_changed();
135 }
136 let old_name = old.object_name().to_string();
137 self.name_index.remove(&old_name);
138 self.invalidate_enrollments_monitoring(&oid);
139 }
140
141 self.name_index.insert(name, oid);
142 let is_new = !self.objects.contains_key(&oid);
143 self.enrollment_eval_sources.remove(&oid);
144 self.trend_poll.retire(&oid);
145 self.objects.insert(oid, object);
146 self.audit_membership_changed(oid, true);
147 if is_new {
148 self.type_index
149 .entry(oid.object_type())
150 .or_default()
151 .push(oid);
152 }
153 self.membership_changed(oid, true);
154 Ok(())
155 }
156
157 pub fn find_by_name(&self, name: &str) -> Option<&dyn BACnetObject> {
159 let oid = self.name_index.get(name)?;
160 self.objects.get(oid).map(|o| o.as_ref())
161 }
162
163 pub fn check_name_available(
172 &self,
173 oid: &ObjectIdentifier,
174 new_name: &str,
175 ) -> Result<(), Error> {
176 if let Some(&owner) = self.name_index.get(new_name)
177 && owner != *oid
178 {
179 return Err(Error::protocol(
180 ErrorClass::PROPERTY,
181 ErrorCode::DUPLICATE_NAME,
182 ));
183 }
184 Ok(())
185 }
186
187 pub fn update_name_index(&mut self, oid: &ObjectIdentifier) {
191 if let Some(obj) = self.objects.get(oid) {
192 self.name_index.retain(|_, v| v != oid);
194 self.name_index.insert(obj.object_name().to_string(), *oid);
196 }
197 }
198
199 pub fn get(&self, oid: &ObjectIdentifier) -> Option<&dyn BACnetObject> {
201 self.objects.get(oid).map(|o| o.as_ref())
202 }
203
204 pub fn get_mut(&mut self, oid: &ObjectIdentifier) -> Option<&mut (dyn BACnetObject + '_)> {
206 if let Some(object) = self.objects.get_mut(oid) {
207 Some(object.as_mut())
208 } else {
209 None
210 }
211 }
212
213 pub fn with_object_adapter<R, F>(
231 &mut self,
232 oid: &ObjectIdentifier,
233 adapt: F,
234 ) -> Result<Option<R>, Error>
235 where
236 F: for<'slot> FnOnce(&'slot mut Box<dyn BACnetObject>) -> R,
237 {
238 self.check_network_port_membership(oid)?;
239 self.check_audit_membership(oid, false)?;
240 self.trend_poll.retire(oid);
241 Ok(self.objects.get_mut(oid).map(adapt))
242 }
243
244 pub fn enrollment_eval_state_invalidated(&self, oid: &ObjectIdentifier) -> bool {
247 self.invalid_enrollment_eval_state.contains(oid)
248 }
249
250 pub fn set_enrollment_eval_state_invalidated(
252 &mut self,
253 oid: ObjectIdentifier,
254 invalidated: bool,
255 ) {
256 if invalidated {
257 self.invalid_enrollment_eval_state.insert(oid);
258 } else {
259 self.invalid_enrollment_eval_state.remove(&oid);
260 }
261 }
262
263 pub fn enrollment_eval_source(
266 &self,
267 oid: &ObjectIdentifier,
268 ) -> Option<EventEnrollmentMonitoredSource> {
269 self.enrollment_eval_sources.get(oid).copied()
270 }
271
272 pub fn set_enrollment_eval_source(
275 &mut self,
276 oid: ObjectIdentifier,
277 source: Option<EventEnrollmentMonitoredSource>,
278 ) {
279 if let Some(source) = source {
280 self.enrollment_eval_sources.insert(oid, source);
281 } else {
282 self.enrollment_eval_sources.remove(&oid);
283 }
284 }
285
286 fn invalidate_enrollments_monitoring(&mut self, monitored_oid: &ObjectIdentifier) {
287 let affected = self
288 .objects
289 .iter()
290 .filter_map(|(oid, object)| {
291 let source = object
292 .enrollment_eval_source_internal()
293 .flatten()
294 .or_else(|| self.enrollment_eval_sources.get(oid).copied());
295 source
296 .is_some_and(|source| source.0 == *monitored_oid)
297 .then_some(*oid)
298 })
299 .collect::<Vec<_>>();
300 self.invalid_enrollment_eval_state.extend(affected);
301 }
302
303 pub fn remove(
308 &mut self,
309 oid: &ObjectIdentifier,
310 ) -> Result<Option<Box<dyn BACnetObject>>, Error> {
311 self.check_network_port_membership(oid)?;
312 self.check_audit_membership(oid, false)?;
313 self.trend_poll.retire(oid);
314 if self.objects.contains_key(oid) {
315 self.invalidate_enrollments_monitoring(oid);
316 }
317 match self.objects.remove(oid) {
318 Some(mut obj) => {
319 if let Some(reporter) = obj.audit_reporter_internal() {
320 reporter.status_internal().configuration_changed();
321 }
322 self.enrollment_eval_sources.remove(oid);
323 if obj.enrollment_eval_state_internal().is_some() {
324 if obj
325 .set_enrollment_eval_state_internal(Default::default())
326 .is_err()
327 {
328 self.invalid_enrollment_eval_state.insert(*oid);
329 } else {
330 self.invalid_enrollment_eval_state.remove(oid);
331 }
332 let _ = obj.set_enrollment_eval_source_internal(None);
333 } else {
334 self.invalid_enrollment_eval_state.remove(oid);
335 }
336 self.name_index.remove(obj.object_name());
337 if let Some(type_set) = self.type_index.get_mut(&oid.object_type()) {
338 type_set.retain(|o| o != oid);
339 }
340 self.audit_membership_changed(*oid, false);
341 self.membership_changed(*oid, false);
342 Ok(Some(obj))
343 }
344 _ => Ok(None),
345 }
346 }
347
348 pub fn list_objects(&self) -> Vec<ObjectIdentifier> {
350 self.objects.keys().copied().collect()
351 }
352
353 pub fn find_by_type(&self, object_type: ObjectType) -> Vec<ObjectIdentifier> {
358 self.type_index
359 .get(&object_type)
360 .cloned()
361 .unwrap_or_default()
362 }
363
364 pub fn iter_objects(&self) -> impl Iterator<Item = (ObjectIdentifier, &dyn BACnetObject)> {
368 self.objects.iter().map(|(&oid, obj)| (oid, obj.as_ref()))
369 }
370
371 pub fn set_clock_reader(&mut self, clock: Option<Arc<dyn ClockReader>>) {
375 self.clock = clock;
376 for object in self.objects.values_mut() {
377 object.bind_clock_internal(self.clock.clone());
378 }
379 }
380
381 #[doc(hidden)]
383 pub fn set_monotonic_clock_internal(&mut self, clock: Option<Arc<MonotonicClock>>) {
384 self.trend_poll.clear();
385 self.monotonic_clock = clock;
386 for object in self.objects.values_mut() {
387 object.bind_monotonic_clock_internal(self.monotonic_clock.clone());
388 }
389 }
390
391 #[doc(hidden)]
394 pub fn set_deadline_waker_internal(&mut self, waker: Option<Arc<DeadlineWaker>>) {
395 self.deadline_waker = waker;
396 for object in self.objects.values_mut() {
397 object.bind_deadline_waker_internal(self.deadline_waker.clone());
398 }
399 }
400
401 pub fn clock_frame(&self) -> Option<ClockFrame> {
403 self.clock.as_ref()?.read_clock()
404 }
405
406 #[doc(hidden)]
407 pub fn event_sequence_internal(&self) -> Arc<EventSequence> {
408 Arc::clone(&self.event_sequence)
409 }
410
411 #[doc(hidden)]
415 pub fn next_event_sequence_number(&mut self) -> u16 {
416 let reservation = self.reserve_event_sequence_number();
417 let number = reservation.number();
418 let confirmed = self.confirm_event_sequence_number(reservation);
419 debug_assert!(
420 confirmed,
421 "a reservation cannot become stale without mutation"
422 );
423 number
424 }
425
426 #[doc(hidden)]
428 pub fn reserve_event_sequence_number(&self) -> EventSequenceReservation {
429 EventSequenceReservation {
430 number: self.event_sequence.current(),
431 }
432 }
433
434 #[doc(hidden)]
436 pub fn confirm_event_sequence_number(&mut self, reservation: EventSequenceReservation) -> bool {
437 self.event_sequence.confirm(reservation.number)
438 }
439
440 pub fn for_each_object_mut<F>(&mut self, mut f: F)
447 where
448 F: FnMut(ObjectIdentifier, &mut dyn BACnetObject),
449 {
450 for (&oid, obj) in self.objects.iter_mut() {
451 f(oid, obj.as_mut());
452 }
453 }
454
455 pub fn len(&self) -> usize {
457 self.objects.len()
458 }
459
460 pub fn is_empty(&self) -> bool {
462 self.objects.is_empty()
463 }
464}
465
466#[cfg(test)]
467mod tests;
468
469#[cfg(test)]
470mod network_port_tests;