use crate::measurement::{Measurement, MeasurementError, SharedMeasurement, error::*};
use parking_lot::{Mutex, RwLock};
use std::{
collections::HashMap,
ops::Deref,
path::Path,
sync::{Arc, LazyLock, Weak},
};
use uuid::Uuid;
pub struct WeakMeasurement(Weak<RwLock<Measurement>>);
impl Deref for WeakMeasurement {
type Target = Weak<RwLock<Measurement>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
static OPEN_MEASUREMENTS: LazyLock<Mutex<HashMap<Uuid, WeakMeasurement>>> =
LazyLock::new(|| Mutex::new(HashMap::new()));
fn cleanup_closed_measurements() {
let mut lck = OPEN_MEASUREMENTS.lock();
lck.retain(|_, measurement| measurement.0.upgrade().is_some());
}
pub fn find_open_measurement_by_uuid(uuid: &Uuid) -> Option<SharedMeasurement> {
cleanup_closed_measurements();
if let Some(measurement) = OPEN_MEASUREMENTS.lock().get(uuid)
&& let Some(shared) = measurement.0.upgrade()
{
return Some(SharedMeasurement(shared));
}
None
}
pub fn find_open_measurement_by_path(path: &Path) -> Option<SharedMeasurement> {
let mut lck = OPEN_MEASUREMENTS.lock();
let mut result = None;
if !path.is_absolute() {
panic!("path must be absolute");
}
lck.retain(|_, meas| {
if let Some(meas) = meas.0.upgrade() {
if meas.read().filepath() == path {
result = Some(SharedMeasurement(meas));
}
true
} else {
false
}
});
result
}
pub fn add_new_open_measurement(
m: &SharedMeasurement,
) -> std::result::Result<Option<SharedMeasurement>, MeasurementError> {
cleanup_closed_measurements();
let m_readlock = m.read();
let uuid = m_readlock.uuid();
let filepath = m_readlock.filepath();
let mut open_meas = OPEN_MEASUREMENTS.lock();
if let Some(existing) = open_meas.get(uuid) {
if let Some(existing) = existing.upgrade() {
if existing.read().filepath() == filepath {
Ok(Some(SharedMeasurement(existing)))
} else {
DuplicateUUIDSnafu {
path1: existing.read().filepath().to_string_lossy(),
path2: m_readlock.filepath().to_string_lossy(),
uuid: uuid.to_string(),
}
.fail()
}
} else {
Ok(None)
}
} else {
open_meas.insert(*uuid, WeakMeasurement(Arc::downgrade(&m.0)));
Ok(None)
}
}