use std::sync::{
Arc,
atomic::{AtomicU64, Ordering},
};
use cudf::{QueryMemoryDomain, Runtime as CudfRuntime, StreamReservationLease};
use query_planning::{
capability::AggregateStrategyExecutionOptions,
chunk::SourceChunkPlanningOptions,
correlation::{QueryId, TraceId},
error::{QueryError, QueryErrorCode, Result},
execution_contracts::{MemoryControlPolicy, SourceChunkPlanningMode},
mode::StatisticalAggregateExecutionMode,
policy::PlanningPolicy,
};
use tokio::runtime::Runtime as TokioRuntime;
#[cfg(feature = "cugraph")]
use super::super::{
allocator_correlation::AttemptCacheScopeAllocatorCorrelation, cache::resident_graph::GpuResidentGraphCache,
};
use super::{
super::{
CacheFillByteBudget, GpuExecutionPool, LakehouseCacheFillConfig, MemoryGrant, ServiceStreamPool,
SourceSchedulerPolicy, StreamLease,
attempt_domain::{AttemptAllocationDomain, AttemptStreamProviderRoute},
cache::local_parquet::GpuLocalParquetSourceCache,
cache_fill::CacheFillConcurrencyGate,
io_lifecycle::IoLifecycle,
object_store::SourceObjectStoreRegistry,
},
ActivatedDeferredResidentPhase, AdmittedPlanIdentities, AttemptAuxiliaryPermit, AttemptAuxiliarySlots,
ExecutionCancellation, QueryResourceAnchor, QueryResourceEpoch, QueryServiceEpoch,
};
use crate::{
attempt::AttemptHandle,
native_error::cudf_query_error,
observability::{
AttemptId, RuntimeExecutionObservationScope, RuntimeObservationHandle, RuntimeObservationOwner,
RuntimeStreamLeaseScope,
},
};
#[derive(Debug)]
pub(in crate::runtime) struct DeviceRuntime {
pub(in crate::runtime) gpu_execution_pool: GpuExecutionPool,
pub(in crate::runtime) service_stream_pool: ServiceStreamPool,
pub(in crate::runtime) resident_source_cache: Option<GpuLocalParquetSourceCache>,
#[cfg(feature = "cugraph")]
pub(in crate::runtime) resident_graph_cache: Option<GpuResidentGraphCache>,
pub(in crate::runtime) lakehouse_cache_fill_config: LakehouseCacheFillConfig,
pub(in crate::runtime) lakehouse_cache_fill_budget: CacheFillByteBudget,
pub(in crate::runtime) lakehouse_cache_fill_concurrency: CacheFillConcurrencyGate,
pub(in crate::runtime) object_store_control_runtime: Arc<TokioRuntime>,
pub(in crate::runtime) source_object_stores: Arc<SourceObjectStoreRegistry>,
pub(in crate::runtime) source_scheduler_policy: SourceSchedulerPolicy,
pub(in crate::runtime) source_chunk_planning_mode: SourceChunkPlanningMode,
pub(in crate::runtime) source_chunk_planning_options: SourceChunkPlanningOptions,
pub(in crate::runtime) statistical_aggregate_execution_mode: StatisticalAggregateExecutionMode,
pub(in crate::runtime) aggregate_strategy_execution_options: AggregateStrategyExecutionOptions,
pub(in crate::runtime) planning_policy: PlanningPolicy,
}
#[derive(Debug, Clone)]
pub(super) enum QueryScope {
#[cfg_attr(
not(any(test, feature = "test-hooks")),
expect(dead_code, reason = "standalone contexts are built only under test-hooks")
)]
Standalone(Arc<StandaloneQuery>),
Admitted(Arc<AdmittedAttempt>),
}
#[derive(Debug)]
pub(super) struct StandaloneQuery {
pub(super) allocation_domain: QueryMemoryDomain,
pub(super) next_member_id: AtomicU64,
pub(super) memory_control_policy: MemoryControlPolicy,
pub(super) cancellation: ExecutionCancellation,
pub(super) observation_owner: Option<RuntimeObservationOwner>,
}
impl StandaloneQuery {
#[cfg(any(test, feature = "test-hooks"))]
pub(super) fn bind_root(&self, runtime: Arc<CudfRuntime>) -> Result<StreamBinding> {
let (member, derived) = self.attach_member(&runtime)?;
let derived = derived
.with_retained_lifetime(Arc::new(member.clone()))
.map_err(|error| cudf_query_error(STANDALONE_BIND, "failed to retain standalone root member", error))?;
Ok(StreamBinding::Standalone { member, runtime: Arc::new(derived) })
}
pub(super) fn bind_work(&self, runtime: Arc<CudfRuntime>) -> Result<StreamBinding> {
let (member, derived) = self.attach_member(&runtime)?;
Ok(StreamBinding::Standalone { member, runtime: Arc::new(derived) })
}
fn attach_member(&self, runtime: &CudfRuntime) -> Result<(StreamReservationLease, CudfRuntime)> {
let limit = usize::try_from(self.memory_control_policy.device_budget_bytes).map_err(|_| {
QueryError::new(QueryErrorCode::InvalidPlan, STANDALONE_BIND, "standalone member limit exceeds usize")
})?;
let member = self
.allocation_domain
.reserve_stream(runtime.stream(), self.next_member_id.fetch_add(1, Ordering::Relaxed), limit)
.map_err(|error| cudf_query_error(STANDALONE_BIND, "failed to attach standalone stream member", error))?;
let derived = runtime
.with_memory_resource_override(member.manager().resource(), STANDALONE_BIND)
.map_err(|error| cudf_query_error(STANDALONE_BIND, "failed to route standalone stream member", error))?;
Ok((member, derived))
}
}
const STANDALONE_BIND: &str = "query_engine.runtime.standalone.bind_stream";
#[derive(Debug)]
pub(in crate::runtime) struct AdmittedAttempt {
pub(in crate::runtime) attempt_id: AttemptId,
pub(in crate::runtime) service_epoch: QueryServiceEpoch,
pub(in crate::runtime) query_epoch: QueryResourceEpoch,
pub(in crate::runtime) cancellation: ExecutionCancellation,
pub(in crate::runtime) attempt: AttemptHandle,
#[cfg(feature = "cugraph")]
pub(in crate::runtime) cache_scope_allocator_correlation: AttemptCacheScopeAllocatorCorrelation,
pub(in crate::runtime) plan_identities: Arc<AdmittedPlanIdentities>,
pub(in crate::runtime) memory_control_policy: MemoryControlPolicy,
pub(in crate::runtime) auxiliary_slots: Arc<AttemptAuxiliarySlots>,
pub(in crate::runtime) allocation_domain: AttemptAllocationDomain,
pub(in crate::runtime) memory_grant: MemoryGrant,
}
#[derive(Debug)]
pub(in crate::runtime) enum StreamBinding {
Standalone { member: StreamReservationLease, runtime: Arc<CudfRuntime> },
AttemptRoot {
runtime: Arc<CudfRuntime>,
member: StreamReservationLease,
route: Arc<AttemptStreamProviderRoute>,
lease: StreamLease,
},
AttemptWork {
runtime: Arc<CudfRuntime>,
alias: Arc<cudf::AttemptStreamProviderAlias>,
member: StreamReservationLease,
route: Arc<AttemptStreamProviderRoute>,
owned: Option<(StreamLease, AttemptAuxiliaryPermit)>,
},
}
impl StreamBinding {
pub(super) fn runtime(&self) -> &Arc<CudfRuntime> {
match self {
Self::Standalone { runtime, .. }
| Self::AttemptRoot { runtime, .. }
| Self::AttemptWork { runtime, .. } => runtime,
}
}
pub(super) fn member(&self) -> &StreamReservationLease {
match self {
Self::Standalone { member, .. } | Self::AttemptRoot { member, .. } | Self::AttemptWork { member, .. } => {
member
},
}
}
pub(super) fn route(&self) -> Option<&Arc<AttemptStreamProviderRoute>> {
match self {
Self::Standalone { .. } => None,
Self::AttemptRoot { route, .. } | Self::AttemptWork { route, .. } => Some(route),
}
}
}
#[derive(Debug, Clone)]
pub(in crate::runtime) struct PlanScope {
pub(super) query_anchor: Option<Arc<QueryResourceAnchor>>,
pub(super) query_id: Option<QueryId>,
pub(super) trace_id: Option<TraceId>,
pub(super) io_lifecycle: Option<IoLifecycle>,
pub(super) runtime_observation: RuntimeObservationHandle,
pub(super) runtime_execution_scope: Option<RuntimeExecutionObservationScope>,
pub(super) runtime_stream_lease_scope: RuntimeStreamLeaseScope,
pub(super) datafusion_order_tracking: bool,
pub(super) activated_deferred_resident_phase: Option<Arc<ActivatedDeferredResidentPhase>>,
}
impl PlanScope {
pub(in crate::runtime) fn root(
query_id: Option<QueryId>,
trace_id: Option<TraceId>,
runtime_observation: RuntimeObservationHandle,
runtime_stream_lease_scope: RuntimeStreamLeaseScope,
) -> Self {
Self {
query_anchor: None,
query_id,
trace_id,
io_lifecycle: None,
runtime_observation,
runtime_execution_scope: None,
runtime_stream_lease_scope,
datafusion_order_tracking: false,
activated_deferred_resident_phase: None,
}
}
}