ferrum_interfaces/vnext/resource/
runtime_driver.rs1use super::{
2 Arc, BufferRequest, DeviceAllocationError, DeviceAllocationReceipt, DeviceId, DeviceRuntime,
3 FailureDomain, FailureEnvelope, ResourceCommitView, ResourceDriverFailure,
4 ResourceOwnershipTransferFailure, ResourcePoolOwnership, ResourceReservation,
5 ResourceTransactionContext, ResourceTransactionDriver, VNextError,
6};
7
8pub struct RuntimeResourceDriver<R>
15where
16 R: DeviceRuntime,
17{
18 runtime: Arc<R>,
19 retained_ownership: Vec<ResourcePoolOwnership<R>>,
20}
21
22impl<R> RuntimeResourceDriver<R>
23where
24 R: DeviceRuntime,
25{
26 pub fn new(runtime: Arc<R>) -> Result<Self, VNextError> {
27 runtime.descriptor().validate()?;
28 Ok(Self {
29 runtime,
30 retained_ownership: Vec::new(),
31 })
32 }
33
34 pub fn runtime(&self) -> &Arc<R> {
35 &self.runtime
36 }
37
38 pub fn retained_pool_count(&self) -> usize {
41 self.retained_ownership.len()
42 }
43
44 fn failure(
45 code: &'static str,
46 message: impl std::fmt::Display,
47 retryable: bool,
48 ) -> ResourceDriverFailure {
49 let message = message
50 .to_string()
51 .chars()
52 .filter(|character| !character.is_control() || matches!(character, '\n' | '\t'))
53 .take(1024)
54 .collect::<String>();
55 ResourceDriverFailure::new(
56 FailureEnvelope::new(FailureDomain::Resource, code, message, retryable)
57 .expect("runtime resource driver failures use bounded static metadata"),
58 )
59 .expect("runtime resource driver failures use the resource domain")
60 }
61
62 fn allocation_failure(&self, error: DeviceAllocationError<R::Error>) -> ResourceDriverFailure {
63 match error {
64 DeviceAllocationError::Contract(error) => {
65 Self::failure("allocation_contract", error, false)
66 }
67 DeviceAllocationError::Runtime(error) => match self.runtime.describe_error(&error) {
68 Ok(report) => {
69 Self::failure("device_allocation", report.message(), report.retryable())
70 }
71 Err(classification_error) => Self::failure(
72 "device_allocation_unclassified",
73 format!("{error}; classification failed: {classification_error}"),
74 false,
75 ),
76 },
77 }
78 }
79}
80
81impl<R> ResourceTransactionDriver for RuntimeResourceDriver<R>
82where
83 R: DeviceRuntime,
84{
85 type Buffer = R::Buffer;
86 type Runtime = R;
87
88 fn runtime(&self) -> &Arc<Self::Runtime> {
89 &self.runtime
90 }
91
92 fn device_id(&self) -> &DeviceId {
93 &self.runtime.descriptor().id
94 }
95
96 fn device_runtime_implementation_fingerprint(&self) -> &str {
97 &self.runtime.descriptor().runtime_implementation_fingerprint
98 }
99
100 fn device_capacity_bytes(&self) -> u64 {
101 self.runtime.descriptor().total_memory_bytes
102 }
103
104 fn reserve_resource(
105 &mut self,
106 _context: &ResourceTransactionContext<'_, Self::Runtime>,
107 _reservation: &ResourceReservation,
108 ) -> Result<(), ResourceDriverFailure> {
109 Ok(())
110 }
111
112 fn commit_resource<'commit>(
113 &mut self,
114 context: &'commit ResourceTransactionContext<'_, Self::Runtime>,
115 reservation: &ResourceReservation,
116 ) -> Result<DeviceAllocationReceipt<'commit>, ResourceDriverFailure> {
117 let request = BufferRequest::new(
118 reservation.resource_id().clone(),
119 reservation.size_bytes(),
120 reservation.alignment_bytes(),
121 reservation.usage(),
122 reservation.element_type(),
123 )
124 .map_err(|error| Self::failure("buffer_request", error, false))?;
125 context
126 .allocate(&request)
127 .map_err(|error| self.allocation_failure(error))
128 }
129
130 fn compensate_reserve_resource(
131 &mut self,
132 _context: &ResourceTransactionContext<'_, Self::Runtime>,
133 _reservation: &ResourceReservation,
134 ) -> Result<(), ResourceDriverFailure> {
135 Ok(())
136 }
137
138 fn compensate_commit_resource(
139 &mut self,
140 _context: &ResourceTransactionContext<'_, Self::Runtime>,
141 _reservation: &ResourceReservation,
142 _buffer: &Self::Buffer,
143 ) -> Result<(), ResourceDriverFailure> {
144 Ok(())
145 }
146
147 fn rollback_resource(
148 &mut self,
149 _context: &ResourceTransactionContext<'_, Self::Runtime>,
150 _reservation: &ResourceReservation,
151 ) -> Result<(), ResourceDriverFailure> {
152 Ok(())
153 }
154
155 fn release_resource(
156 &mut self,
157 _context: &ResourceTransactionContext<'_, Self::Runtime>,
158 _reservation: &ResourceReservation,
159 _buffer: &Self::Buffer,
160 ) -> Result<(), ResourceDriverFailure> {
161 Ok(())
162 }
163
164 fn reconcile_commit_outcome(
165 &mut self,
166 _context: &ResourceTransactionContext<'_, Self::Runtime>,
167 _expected: &ResourceReservation,
168 _actual: ResourceCommitView<'_, Self::Buffer>,
169 ) -> Result<(), ResourceDriverFailure> {
170 Ok(())
171 }
172
173 fn quarantine_transaction(
174 &mut self,
175 _context: &ResourceTransactionContext<'_, Self::Runtime>,
176 ownership: ResourcePoolOwnership<Self::Runtime>,
177 ) -> Result<(), ResourceOwnershipTransferFailure<Self::Runtime>> {
178 self.retained_ownership.push(ownership);
179 Ok(())
180 }
181
182 fn abandon_transaction(&mut self, ownership: ResourcePoolOwnership<Self::Runtime>) {
183 self.retained_ownership.push(ownership);
184 }
185}