use std::path::{
Path,
PathBuf,
};
use std::sync::Arc;
use std::sync::atomic::{
AtomicU32,
Ordering,
};
use serde::Serialize;
use serde::de::DeserializeOwned;
use tokio::sync::OwnedSemaphorePermit;
use crate::engine::SortSession;
use crate::plan::SortPlan;
#[derive(Debug)]
struct ActiveGuard {
active: Arc<AtomicU32>,
}
impl Drop for ActiveGuard {
fn drop(&mut self) {
self.active.fetch_sub(1, Ordering::Relaxed);
}
}
#[derive(Debug)]
pub struct SortLease {
plan: SortPlan,
scratch_dir: PathBuf,
_fd_permit: Option<OwnedSemaphorePermit>,
_active: Option<ActiveGuard>,
}
impl SortLease {
pub(crate) fn in_memory(plan: SortPlan, scratch_dir: PathBuf) -> Self {
Self {
plan,
scratch_dir,
_fd_permit: None,
_active: None,
}
}
pub(crate) fn external(
plan: SortPlan,
scratch_dir: PathBuf,
fd_permit: OwnedSemaphorePermit,
active: Arc<AtomicU32>,
) -> Self {
Self {
plan,
scratch_dir,
_fd_permit: Some(fd_permit),
_active: Some(ActiveGuard { active }),
}
}
#[must_use]
pub fn plan(&self) -> SortPlan {
self.plan
}
#[must_use]
pub fn scratch_dir(&self) -> &Path {
&self.scratch_dir
}
#[must_use]
pub fn into_session<K, V>(self, dedup: bool) -> SortSession<K, V>
where
K: Ord + Clone + Serialize + DeserializeOwned + Send + 'static,
V: Serialize + DeserializeOwned + Send + 'static,
{
let plan = self.plan;
let dir = self.scratch_dir.clone();
SortSession::new(plan, dir, dedup).hold_resource(Box::new(self))
}
}