query_runtime/runtime/context/
admitted.rs1use std::sync::{Arc, Mutex, PoisonError};
4
5use query_planning::{
6 admission::{AttemptCapabilityEvidence, AttemptProducerOccurrence},
7 error::{QueryError, QueryErrorCode, Result},
8 plan::{QueryPlan, SchemaFingerprint},
9};
10
11use super::{
12 super::{
13 MemoryGrant,
14 resident::{GpuResidentInputMap, GpuResultHandle},
15 },
16 ActivatedDeferredResidentInput, ActivatedDeferredResidentPhase, DeferredResidentFacts, ExecutionContext,
17};
18use crate::observability::AttemptComposedScheduleProjection;
19
20#[derive(Debug, Default)]
26pub(in crate::runtime) struct AdmittedPlanIdentities {
27 evidence: Mutex<Option<Arc<AttemptCapabilityEvidence>>>,
30}
31
32impl AdmittedPlanIdentities {
33 pub(in crate::runtime) fn new(evidence: Option<AttemptCapabilityEvidence>) -> Self {
34 Self { evidence: Mutex::new(evidence.map(Arc::new)) }
35 }
36
37 pub(in crate::runtime) fn current(&self) -> Option<Arc<AttemptCapabilityEvidence>> {
39 self.evidence.lock().unwrap_or_else(PoisonError::into_inner).clone()
40 }
41
42 pub(in crate::runtime) fn join(&self, fragment: &AttemptCapabilityEvidence) -> Result<()> {
45 let mut evidence = self.evidence.lock().unwrap_or_else(PoisonError::into_inner);
46 let mut joined = evidence.as_deref().cloned().unwrap_or_default();
47 joined.join(fragment)?;
48 *evidence = Some(Arc::new(joined));
49 Ok(())
50 }
51}
52
53impl ExecutionContext {
54 fn validated_admitted_identity(
60 &self,
61 plan: &QueryPlan,
62 ) -> Result<Option<(Arc<AttemptCapabilityEvidence>, MemoryGrant)>> {
63 let Some(attempt) = self.admitted() else {
64 return Ok(None);
65 };
66 let evidence = attempt.plan_identities.current().ok_or_else(|| {
67 QueryError::new(
68 QueryErrorCode::InternalInvariantViolation,
69 "query_engine.runtime.context",
70 "a query-service context requires its admitted capability evidence",
71 )
72 .with_fact("reason", "admitted_capability_evidence_missing")
73 .with_fact("plan_scope", plan.execution_fingerprint())
74 })?;
75 let immutable_grant = self.admitted_memory_grant(attempt, "query_engine.runtime.context.memory_grant")?;
76 Ok(Some((evidence, immutable_grant)))
77 }
78
79 fn validate_admitted_capability_evidence(
80 &self,
81 evidence: &AttemptCapabilityEvidence,
82 plan: &QueryPlan,
83 ) -> Result<()> {
84 evidence.validate_covers_plan(plan)?;
85 let execution_scope = plan.execution_fingerprint();
86 let expected_schema = SchemaFingerprint::of(plan.caller_visible_output_schema());
87 let scope_matches = evidence.execution_scopes().iter().filter(|shape| shape.matches(plan)).collect::<Vec<_>>();
88 let matching_shapes = scope_matches
89 .iter()
90 .copied()
91 .filter(|shape| shape.output_schema_fingerprint() == expected_schema)
92 .collect::<Vec<_>>();
93 if matching_shapes.is_empty() {
94 if evidence.producer_occurrence_scope_count_for_plan(plan) > 0 {
99 return Ok(());
100 }
101 if evidence.execution_manifest().and_then(|manifest| manifest.occurrence_for_plan(plan)).is_some() {
102 return Ok(());
103 }
104 return Err(QueryError::new(
105 QueryErrorCode::InternalInvariantViolation,
106 "query_engine.runtime.context",
107 "the admitted capability evidence output schema differs from the native plan",
108 )
109 .with_fact("reason", "admitted_capability_schema_mismatch")
110 .with_fact("plan_scope", execution_scope)
111 .with_fact("matching_shape_count", scope_matches.len()));
112 }
113 for shape in matching_shapes {
114 shape.validate_manifest_core()?;
115 }
116 Ok(())
117 }
118
119 fn validate_admitted_occurrences(
120 &self,
121 evidence: &AttemptCapabilityEvidence,
122 plan: &QueryPlan,
123 occurrence_ids: &[String],
124 ) -> Result<()> {
125 evidence.validate_composed_occurrences(plan, occurrence_ids)
126 }
127
128 fn validate_admitted_evidence(
129 &self,
130 plan: &QueryPlan,
131 occurrence_ids: Option<&[String]>,
132 ) -> Result<Option<AttemptComposedScheduleProjection>> {
133 let Some((submitted_evidence, immutable_grant)) = self.validated_admitted_identity(plan)? else {
134 return Ok(None);
135 };
136 let evidence = match &self.plan.activated_deferred_resident_phase {
141 Some(activated) if activated.consumer_execution_scope_fingerprint == plan.execution_fingerprint() => {
142 if activated.grant_identity != immutable_grant.identity() {
143 return Err(QueryError::new(
144 QueryErrorCode::InternalInvariantViolation,
145 "query_engine.runtime.context",
146 "the activated deferred phase differs from the admitted plan or immutable grant",
147 )
148 .with_fact("reason", "deferred_resident_phase_identity_mismatch"));
149 }
150 &activated.capability_evidence
151 },
152 _ => submitted_evidence.as_ref(),
153 };
154 self.validate_admitted_capability_evidence(evidence, plan)?;
155 if let Some(occurrence_ids) = occurrence_ids {
156 self.validate_admitted_occurrences(evidence, plan, occurrence_ids)?;
157 }
158 Ok(None)
159 }
160
161 pub fn validate_admitted_plan_capabilities(&self, plan: &QueryPlan) -> Result<()> {
164 let Some((evidence, _)) = self.validated_admitted_identity(plan)? else {
165 return Ok(());
166 };
167 self.validate_admitted_capability_evidence(&evidence, plan)
168 }
169
170 pub fn with_admitted_gpu_inputs(&self, plan: &QueryPlan, gpu_inputs: &GpuResidentInputMap) -> Result<Self> {
177 let Some((submitted_evidence, immutable_grant)) = self.validated_admitted_identity(plan)? else {
178 return Ok(self.clone());
179 };
180 if gpu_inputs.is_empty() {
181 return Ok(self.clone());
182 }
183 if let Some(activated) = &self.plan.activated_deferred_resident_phase
188 && activated.consumer_execution_scope_fingerprint == plan.execution_fingerprint()
189 && activated.grant_identity != immutable_grant.identity()
190 {
191 return Err(QueryError::new(
192 QueryErrorCode::InternalInvariantViolation,
193 "query_engine.runtime.context",
194 "the activated deferred phase differs from the admitted immutable grant",
195 )
196 .with_fact("reason", "deferred_resident_phase_identity_mismatch"));
197 }
198 submitted_evidence.validate_covers_plan(plan)?;
199 let expected_scopes = submitted_evidence
200 .execution_scopes()
201 .iter()
202 .filter(|scope| scope.matches(plan) && !scope.producer_occurrences().is_empty())
203 .collect::<Vec<_>>();
204 if expected_scopes.is_empty() {
205 return Ok(self.clone());
206 }
207 for scope in &expected_scopes {
208 scope.validate_manifest_core()?;
209 }
210 let expected_scope = expected_scopes
211 .iter()
212 .copied()
213 .find(|scope| {
214 scope.producer_occurrences().iter().all(|expected| {
215 gpu_inputs.get(expected.occurrence_id()).is_some_and(|input| {
216 DeferredResidentFacts::read(expected.occurrence_id(), input)
217 .is_ok_and(|facts| facts_match_occurrence(&facts, input, expected))
218 })
219 })
220 })
221 .unwrap_or(expected_scopes[0]);
222 let mut capability_evidence = submitted_evidence.as_ref().clone();
223 capability_evidence.attest_cugraph_graph_execution_scope(plan);
224 let inputs = expected_scope
225 .producer_occurrences()
226 .iter()
227 .map(|expected| {
228 let input_name = expected.occurrence_id();
229 let input = gpu_inputs.get(input_name).ok_or_else(|| {
230 QueryError::new(
231 QueryErrorCode::InternalInvariantViolation,
232 "query_engine.runtime.context",
233 "the admitted deferred resident occurrence is missing",
234 )
235 .with_fact("reason", "deferred_resident_input_missing")
236 .with_fact("input_name", input_name)
237 })?;
238 let facts = DeferredResidentFacts::read(input_name, input)?;
239 if !facts_match_occurrence(&facts, input, expected) {
240 return Err(QueryError::new(
241 QueryErrorCode::InternalInvariantViolation,
242 "query_engine.runtime.context",
243 "a deferred resident input differs from its admitted producer binding",
244 )
245 .with_fact("reason", "deferred_resident_producer_binding_mismatch")
246 .with_fact("input_name", input_name)
247 .with_fact("expected_producer_scope", expected.execution_scope_fingerprint())
248 .with_fact("actual_producer_scope", facts.producer_execution_scope_fingerprint())
249 .with_fact("expected_schema", expected.output_schema_fingerprint())
250 .with_fact("actual_schema", SchemaFingerprint::of(facts.schema())));
251 }
252 ActivatedDeferredResidentInput::bind(input_name.to_owned(), facts, input, &immutable_grant)
253 })
254 .collect::<Result<Vec<_>>>()?;
255 let activated = ActivatedDeferredResidentPhase {
256 consumer_execution_scope_fingerprint: plan.execution_fingerprint(),
257 inputs,
258 capability_evidence,
259 grant_identity: immutable_grant.identity(),
260 };
261 activated.validate_inputs(gpu_inputs, &immutable_grant)?;
262 Ok(self.with_plan(|plan| plan.activated_deferred_resident_phase = Some(Arc::new(activated))))
263 }
264
265 #[doc(hidden)]
266 pub fn validate_admitted_plan_capabilities_with_gpu_inputs(
267 &self,
268 plan: &QueryPlan,
269 gpu_inputs: &GpuResidentInputMap,
270 ) -> Result<()> {
271 self.validate_admitted_plan_capabilities(plan)?;
272 let Some(activated) = self
273 .plan
274 .activated_deferred_resident_phase
275 .as_ref()
276 .filter(|activated| activated.consumer_execution_scope_fingerprint == plan.execution_fingerprint())
277 else {
278 return Ok(());
279 };
280 let immutable_grant = self.memory_grant()?.ok_or_else(|| {
281 QueryError::new(
282 QueryErrorCode::InternalInvariantViolation,
283 "query_engine.runtime.context",
284 "the activated deferred phase lost its immutable grant",
285 )
286 .with_fact("reason", "deferred_resident_grant_missing")
287 })?;
288 activated.validate_inputs(gpu_inputs, &immutable_grant)
289 }
290
291 pub fn validate_admitted_composed_attempt(
295 &self,
296 consumer_plan: &QueryPlan,
297 occurrence_ids: &[String],
298 ) -> Result<Option<AttemptComposedScheduleProjection>> {
299 self.validate_admitted_evidence(consumer_plan, Some(occurrence_ids))
300 }
301}
302
303fn facts_match_occurrence(
307 facts: &DeferredResidentFacts,
308 input: &GpuResultHandle,
309 expected: &AttemptProducerOccurrence,
310) -> bool {
311 (facts.producer_execution_scope_fingerprint() == expected.execution_scope_fingerprint()
312 || input.producer_execution_plan().is_some_and(|plan| expected.matches_execution_plan(plan)))
313 && SchemaFingerprint::of(facts.schema()) == expected.output_schema_fingerprint()
314}