1use crate::model::descriptor::{
16 FlattenDataFlowDescriptor, InputDescriptor, LinkDescriptor, OutputDescriptor,
17};
18use crate::model::record::connector::{ZFConnectorKind, ZFConnectorRecord};
19use crate::model::record::{LinkRecord, OperatorRecord, PortRecord, SinkRecord, SourceRecord};
20use crate::types::{NodeId, PortId, RuntimeId};
21use crate::zferror;
22use crate::zfresult::ErrorKind;
23use crate::Result as ZFResult;
24use serde::{Deserialize, Serialize};
25use std::collections::HashMap;
26use std::convert::TryFrom;
27use std::hash::{Hash, Hasher};
28use uuid::Uuid;
29
30#[derive(Serialize, Deserialize, Debug, Clone)]
32pub struct DataFlowRecord {
33 pub uuid: Uuid,
34 pub flow: String,
35 pub operators: HashMap<NodeId, OperatorRecord>,
36 pub sinks: HashMap<NodeId, SinkRecord>,
37 pub sources: HashMap<NodeId, SourceRecord>,
38 pub connectors: HashMap<NodeId, ZFConnectorRecord>,
39 pub links: Vec<LinkRecord>,
40 pub counter: u32,
41}
42
43impl DataFlowRecord {
44 pub fn from_yaml(data: &str) -> ZFResult<Self> {
49 serde_yaml::from_str::<DataFlowRecord>(data)
50 .map_err(|e| zferror!(ErrorKind::ParsingError, e).into())
51 }
52
53 pub fn from_json(data: &str) -> ZFResult<Self> {
58 serde_json::from_str::<DataFlowRecord>(data)
59 .map_err(|e| zferror!(ErrorKind::ParsingError, e).into())
60 }
61
62 pub fn to_json(&self) -> ZFResult<String> {
67 serde_json::to_string(&self).map_err(|e| zferror!(ErrorKind::SerializationError, e).into())
68 }
69
70 pub fn to_yaml(&self) -> ZFResult<String> {
75 serde_yaml::to_string(&self).map_err(|e| zferror!(ErrorKind::SerializationError, e).into())
76 }
77
78 pub fn find_node_runtime(&self, id: &str) -> Option<RuntimeId> {
80 match self.operators.get(id) {
81 Some(o) => Some(o.runtime.clone()),
82 None => match self.sources.get(id) {
83 Some(s) => Some(s.runtime.clone()),
84 None => self.sinks.get(id).map(|s| s.runtime.clone()),
85 },
86 }
87 }
88
89 fn find_node_uid_by_id(&self, id: &NodeId) -> Option<u32> {
91 if let Some(o) = self.operators.get(id) {
92 return Some(o.uid);
93 }
94 if let Some(s) = self.sources.get(id) {
95 return Some(s.uid);
96 }
97 if let Some(s) = self.sinks.get(id) {
98 return Some(s.uid);
99 }
100 None
101 }
102
103 fn find_port_id_in_node(&self, node_id: &NodeId, port_id: &PortId) -> Option<u32> {
105 let (inputs, outputs) = if let Some(op) = self.operators.get(node_id) {
106 (Some(&op.inputs), Some(&op.outputs))
107 } else if let Some(source) = self.sources.get(node_id) {
108 (None, Some(&source.outputs))
109 } else if let Some(sink) = self.sinks.get(node_id) {
110 (Some(&sink.inputs), None)
111 } else {
112 (None, None)
113 };
114
115 if let Some(outputs) = outputs {
116 if let Some(port_record) = outputs.iter().find(|&output| output.port_id == *port_id) {
117 return Some(port_record.uid);
118 }
119 }
120
121 if let Some(inputs) = inputs {
122 if let Some(port_record) = inputs.iter().find(|&input| input.port_id == *port_id) {
123 return Some(port_record.uid);
124 }
125 }
126
127 None
128 }
129
130 fn add_links(&mut self, links: &[LinkDescriptor]) -> ZFResult<()> {
139 for l in links.iter() {
140 log::debug!("Adding link: {:?}…", l);
141 let from_runtime = match self.find_node_runtime(&l.from.node) {
142 Some(rt) => rt,
143 None => {
144 log::error!("Could not find runtime for: {:?}", &l.from.node);
145 return Err(zferror!(
146 ErrorKind::Uncompleted,
147 "Unable to find runtime for {}",
148 &l.from.node
149 )
150 .into());
151 }
152 };
153
154 let to_runtime = match self.find_node_runtime(&l.to.node) {
155 Some(rt) => rt,
156 None => {
157 log::error!("Could not find runtime for: {:?}", &l.to.node);
158 return Err(zferror!(
159 ErrorKind::Uncompleted,
160 "Unable to find runtime for {}",
161 &l.to.node
162 )
163 .into());
164 }
165 };
166
167 if from_runtime == to_runtime {
168 log::debug!("Adding link: {:?}… OK", l);
169 self.links.push((l.clone(), self.counter).into());
171 self.counter += 1;
172 } else {
173 let from_uid = self
178 .find_node_uid_by_id(&l.from.node)
179 .ok_or_else(|| zferror!(ErrorKind::NotFound))?;
180 let from_port_uid = self
181 .find_port_id_in_node(&l.from.node, &l.from.output)
182 .ok_or_else(|| zferror!(ErrorKind::NotFound))?;
183
184 let z_resource_name = format!(
186 "zf/data/{}/{}/{}/{}",
187 &self.flow, &self.uuid, &from_uid, &from_port_uid
188 );
189
190 if !self.connectors.iter().any(|(_id, c)| {
194 c.kind == ZFConnectorKind::Sender && c.resource == z_resource_name
195 }) {
196 let sender_id: NodeId = format!(
198 "sender-{}-{}-{}-{}",
199 &self.flow, &self.uuid, &l.from.node, &l.from.output
200 )
201 .into();
202 let sender = ZFConnectorRecord {
203 kind: ZFConnectorKind::Sender,
204 id: sender_id.clone(),
205 resource: z_resource_name.clone(),
206 link_id: PortRecord {
207 uid: self.counter,
208 port_id: l.from.output.clone(),
209 },
210 shared_memory_element_size: l.shared_memory_element_size,
211 shared_memory_elements: l.shared_memory_elements,
212 shared_memory_backoff: l.shared_memory_backoff,
213 runtime: from_runtime,
214 };
215 self.counter += 1;
216
217 let link_sender = LinkDescriptor {
219 from: l.from.clone(),
220 to: InputDescriptor {
221 node: sender_id.clone(),
222 input: l.from.output.clone(),
223 },
224 shared_memory_element_size: l.shared_memory_element_size,
225 shared_memory_elements: l.shared_memory_elements,
226 shared_memory_backoff: l.shared_memory_backoff,
227 };
228
229 self.connectors.insert(sender_id, sender);
231 self.links.push((link_sender, self.counter).into());
232 self.counter += 1;
233 }
234
235 let receiver_id: NodeId = format!(
237 "receiver-{}-{}-{}-{}",
238 &self.flow, &self.uuid, &l.to.node, &l.to.input
239 )
240 .into();
241 let receiver = ZFConnectorRecord {
242 kind: ZFConnectorKind::Receiver,
243 id: receiver_id.clone(),
244 resource: z_resource_name.clone(),
245 link_id: PortRecord {
246 uid: self.counter,
247 port_id: l.to.input.clone(),
248 },
249 shared_memory_element_size: l.shared_memory_element_size,
250 shared_memory_elements: l.shared_memory_elements,
251 shared_memory_backoff: l.shared_memory_backoff,
252 runtime: to_runtime,
253 };
254 self.counter += 1;
255
256 let link_receiver = LinkDescriptor {
258 from: OutputDescriptor {
259 node: receiver_id.clone(),
260 output: l.to.input.clone(),
261 },
262 to: l.to.clone(),
263 shared_memory_element_size: l.shared_memory_element_size,
264 shared_memory_elements: l.shared_memory_elements,
265 shared_memory_backoff: l.shared_memory_backoff,
266 };
267
268 self.connectors.insert(receiver_id, receiver);
270 self.links.push((link_receiver, self.counter).into());
271 self.counter += 1;
272 }
273 }
274
275 Ok(())
276 }
277}
278
279impl TryFrom<(FlattenDataFlowDescriptor, Uuid)> for DataFlowRecord {
280 type Error = crate::zfresult::Error;
281
282 fn try_from(d: (FlattenDataFlowDescriptor, Uuid)) -> Result<Self, Self::Error> {
283 let (dataflow, id) = d;
284
285 let FlattenDataFlowDescriptor {
286 flow,
287 operators,
288 sources,
289 sinks,
290 links,
291 mapping,
292 global_configuration: _,
293 } = dataflow;
294
295 let mapping = mapping.map_or(HashMap::new(), |m| m);
296
297 let mut dfr = DataFlowRecord {
298 uuid: id,
299 flow,
300 operators: HashMap::with_capacity(operators.len()),
301 sinks: HashMap::with_capacity(sinks.len()),
302 sources: HashMap::with_capacity(sources.len()),
303 connectors: HashMap::new(),
304 links: Vec::new(),
305 counter: 0,
306 };
307
308 for o in operators.into_iter() {
309 let mut inputs: Vec<PortRecord> = vec![];
311 for i in o.inputs {
312 inputs.push((i, dfr.counter).into());
313 dfr.counter += 1;
314 }
315
316 let mut outputs: Vec<PortRecord> = vec![];
318 for o in o.outputs {
319 outputs.push((o, dfr.counter).into());
320 dfr.counter += 1;
321 }
322
323 let or = OperatorRecord {
324 id: o.id.clone(),
325 uid: dfr.counter,
326 inputs,
327 outputs,
328 uri: o.uri,
329 configuration: o.configuration,
330 runtime: mapping
331 .get(&o.id)
332 .ok_or_else(|| zferror!(ErrorKind::MissingConfiguration))
333 .cloned()?,
334 };
335 dfr.operators.insert(o.id, or);
336 dfr.counter += 1;
337 }
338
339 for s in sources.into_iter() {
340 let mut outputs: Vec<PortRecord> = vec![];
341 for o in s.outputs {
342 outputs.push((o, dfr.counter).into());
343 dfr.counter += 1;
344 }
345
346 let sr = SourceRecord {
347 id: s.id.clone(),
348 uid: dfr.counter,
349 outputs,
350 uri: s.uri,
351 configuration: s.configuration,
352 runtime: mapping
353 .get(&s.id)
354 .ok_or_else(|| zferror!(ErrorKind::MissingConfiguration))
355 .cloned()?,
356 };
357 dfr.sources.insert(s.id, sr);
358 dfr.counter += 1;
359 }
360
361 for s in sinks.into_iter() {
362 let mut inputs: Vec<PortRecord> = Vec::with_capacity(s.inputs.len());
363 for i in s.inputs {
364 inputs.push((i, dfr.counter).into());
365 dfr.counter += 1;
366 }
367
368 let sr = SinkRecord {
369 id: s.id.clone(),
370 uid: dfr.counter,
371 inputs,
372 uri: s.uri,
373 configuration: s.configuration,
374 runtime: mapping
375 .get(&s.id)
376 .ok_or_else(|| zferror!(ErrorKind::MissingConfiguration))
377 .cloned()?,
378 };
379 dfr.sinks.insert(s.id, sr);
380 dfr.counter += 1;
381 }
382
383 dfr.add_links(&links)?;
384
385 Ok(dfr)
386 }
387}
388
389impl Hash for DataFlowRecord {
390 fn hash<H: Hasher>(&self, state: &mut H) {
391 self.uuid.hash(state);
392 self.flow.hash(state);
393 }
394}
395
396impl PartialEq for DataFlowRecord {
397 fn eq(&self, other: &DataFlowRecord) -> bool {
398 self.uuid == other.uuid && self.flow == other.flow
399 }
400}
401
402impl Eq for DataFlowRecord {}