418b20bf1947b6275b2b0fd56f933215ad1ef5f6
[transportpce.git] / networkmodel / src / main / java / org / opendaylight / transportpce / networkmodel / service / FrequenciesServiceImpl.java
1 /*
2  * Copyright © 2017 AT&T and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.transportpce.networkmodel.service;
9
10 import java.util.Arrays;
11 import java.util.BitSet;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Objects;
16 import java.util.Optional;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
20 import java.util.stream.Collectors;
21 import org.opendaylight.mdsal.binding.api.DataBroker;
22 import org.opendaylight.mdsal.binding.api.ReadTransaction;
23 import org.opendaylight.mdsal.binding.api.WriteTransaction;
24 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
25 import org.opendaylight.transportpce.common.InstanceIdentifiers;
26 import org.opendaylight.transportpce.common.NetworkUtils;
27 import org.opendaylight.transportpce.common.NodeIdPair;
28 import org.opendaylight.transportpce.common.Timeouts;
29 import org.opendaylight.transportpce.common.fixedflex.GridConstant;
30 import org.opendaylight.transportpce.common.fixedflex.GridUtils;
31 import org.opendaylight.transportpce.networkmodel.util.OpenRoadmTopology;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev181019.ModulationFormat;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.Node1;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.Node1Builder;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.TerminationPoint1;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.TerminationPoint1Builder;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.DegreeAttributes;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.DegreeAttributesBuilder;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.SrgAttributes;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.SrgAttributesBuilder;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.CpAttributes;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.CpAttributesBuilder;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.CtpAttributes;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.CtpAttributesBuilder;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.PpAttributes;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.PpAttributesBuilder;
47 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.RxTtpAttributes;
48 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.RxTtpAttributesBuilder;
49 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.TxTtpAttributes;
50 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.TxTtpAttributesBuilder;
51 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.XpdrNetworkAttributes;
52 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.XpdrNetworkAttributesBuilder;
53 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.XpdrPortAttributes;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.topology.rev211210.networks.network.node.termination.point.XpdrPortAttributesBuilder;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev211210.available.freq.map.AvailFreqMaps;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev211210.available.freq.map.AvailFreqMapsBuilder;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.network.types.rev211210.available.freq.map.AvailFreqMapsKey;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.xponder.rev211210.xpdr.port.connection.attributes.WavelengthBuilder;
59 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.AToZDirection;
60 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.path.description.ZToADirection;
61 import org.opendaylight.yang.gen.v1.http.org.transportpce.b.c._interface.pathdescription.rev210705.pce.resource.resource.resource.TerminationPoint;
62 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
63 import org.opendaylight.yangtools.yang.common.Decimal64;
64 import org.opendaylight.yangtools.yang.common.Uint32;
65 import org.osgi.service.component.annotations.Activate;
66 import org.osgi.service.component.annotations.Component;
67 import org.osgi.service.component.annotations.Reference;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71 @Component
72 public class FrequenciesServiceImpl implements FrequenciesService {
73
74     private static final Logger LOG = LoggerFactory.getLogger(FrequenciesServiceImpl.class);
75     private final DataBroker dataBroker;
76     private final AvailFreqMapsKey availFreqMapKey = new AvailFreqMapsKey(GridConstant.C_BAND);
77
78     @Activate
79     public FrequenciesServiceImpl(@Reference DataBroker dataBroker) {
80         this.dataBroker = dataBroker;
81     }
82
83     @Override
84     public void allocateFrequencies(AToZDirection atoZDirection, ZToADirection ztoADirection) {
85         updateFrequencies(atoZDirection, ztoADirection, true);
86     }
87
88
89     @Override
90     public void releaseFrequencies(AToZDirection atoZDirection, ZToADirection ztoADirection) {
91         updateFrequencies(atoZDirection, ztoADirection, false);
92     }
93
94     /**
95      * Update frequency map for nodes and tp in atozDirection and ztoadirection.
96      * @param atoZDirection AToZDirection
97      * @param ztoADirection ZToADirection
98      * @param used used boolean true if frequencies are used, false otherwise.
99      */
100     private void updateFrequencies(AToZDirection atoZDirection, ZToADirection ztoADirection, boolean used) {
101         if (atoZDirection != null && atoZDirection.getAToZMinFrequency() != null) {
102             LOG.info("Update frequencies for a to z direction {}, used {}", atoZDirection, used);
103             List<NodeIdPair> atozTpIds = getAToZTpList(atoZDirection);
104             Decimal64 atozMinFrequency = atoZDirection.getAToZMinFrequency().getValue();
105             Decimal64 atozMaxFrequency = atoZDirection.getAToZMaxFrequency().getValue();
106             ModulationFormat modulationFormat = ModulationFormat.forName(atoZDirection.getModulationFormat());
107             if (modulationFormat == null) {
108                 LOG.error("Unknown modulation format {} for a to z direction, frequencies not updated",
109                         atoZDirection.getModulationFormat());
110                 return;
111             }
112             setFrequencies4Tps(
113                     atozMinFrequency, atozMaxFrequency,
114                     atoZDirection.getRate(), modulationFormat, atozTpIds,
115                     used);
116             setFrequencies4Nodes(
117                     atozMinFrequency, atozMaxFrequency,
118                     atozTpIds.stream().map(NodeIdPair::getNodeID).distinct().collect(Collectors.toList()),
119                     used);
120         }
121         if (ztoADirection != null && ztoADirection.getZToAMinFrequency() != null) {
122             LOG.info("Update frequencies for z to a direction {}, used {}", ztoADirection, used);
123             List<NodeIdPair> ztoaTpIds = getZToATpList(ztoADirection);
124             Decimal64 ztoaMinFrequency = ztoADirection.getZToAMinFrequency().getValue();
125             Decimal64 ztoaMaxFrequency = ztoADirection.getZToAMaxFrequency().getValue();
126             ModulationFormat modulationFormat = ModulationFormat.forName(ztoADirection.getModulationFormat());
127             if (modulationFormat == null) {
128                 LOG.error("Unknown modulation format {} for z to a direction, frequencies not updated",
129                         ztoADirection.getModulationFormat());
130                 return;
131             }
132             setFrequencies4Tps(
133                     ztoaMinFrequency, ztoaMaxFrequency,
134                     ztoADirection.getRate(), modulationFormat, ztoaTpIds,
135                     used);
136             setFrequencies4Nodes(
137                     ztoaMinFrequency, ztoaMaxFrequency,
138                     ztoaTpIds.stream().map(NodeIdPair::getNodeID).distinct().collect(Collectors.toList()),
139                     used);
140         }
141     }
142
143     /**
144      * Get network node with nodeId from datastore.
145      * @param nodeId String
146      * @return Node1, null otherwise.
147      */
148     private Node1 getNetworkNodeFromDatastore(String nodeId) {
149         InstanceIdentifier<Node1> nodeIID = OpenRoadmTopology.createNetworkNodeIID(nodeId);
150         try (ReadTransaction nodeReadTx = this.dataBroker.newReadOnlyTransaction()) {
151             Optional<Node1> optionalNode = nodeReadTx
152                 .read(LogicalDatastoreType.CONFIGURATION, nodeIID)
153                 .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
154             if (optionalNode.isEmpty()) {
155                 LOG.warn("Unable to get network node for node id {} from topology {}",
156                      nodeId, NetworkUtils.OVERLAY_NETWORK_ID);
157                 return null;
158             }
159             return optionalNode.orElseThrow();
160         } catch (ExecutionException | TimeoutException e) {
161             LOG.warn("Exception while getting network node for node id {} from {} topology",
162                     nodeId, NetworkUtils.OVERLAY_NETWORK_ID, e);
163             return null;
164         } catch (InterruptedException e) {
165             LOG.warn("Getting network node for node id {} from {} topology was interrupted",
166                     nodeId, NetworkUtils.OVERLAY_NETWORK_ID, e);
167             Thread.currentThread().interrupt();
168             return null;
169         }
170     }
171
172     /**
173      * Get common network node with nodeId from datastore.
174      * @param nodeId String
175      * @return Node1, null otherwise.
176      */
177     private org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1
178             getCommonNetworkNodeFromDatastore(String nodeId) {
179         InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1> nodeIID =
180             OpenRoadmTopology.createCommonNetworkNodeIID(nodeId);
181         try (ReadTransaction nodeReadTx = this.dataBroker.newReadOnlyTransaction()) {
182             Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1> optionalNode =
183                 nodeReadTx
184                     .read(LogicalDatastoreType.CONFIGURATION, nodeIID)
185                     .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
186             if (optionalNode.isEmpty()) {
187                 LOG.error("Unable to get common network node for node id {} from topology {}",
188                         nodeId, NetworkUtils.OVERLAY_NETWORK_ID);
189                 return null;
190             }
191             return optionalNode.orElseThrow();
192         } catch (ExecutionException | TimeoutException e) {
193             LOG.warn("Exception while getting common network node for node id {} from {} topology",
194                     nodeId, NetworkUtils.OVERLAY_NETWORK_ID, e);
195             return null;
196         } catch (InterruptedException e) {
197             LOG.warn("Getting common network node for node id {} from {} topology was interrupted",
198                     nodeId, NetworkUtils.OVERLAY_NETWORK_ID, e);
199             Thread.currentThread().interrupt();
200             return null;
201         }
202     }
203
204     /**
205      * Set frequency map for nodes in nodeIds.
206      * @param atozMinFrequency BigDecimal
207      * @param atozMaxFrequency BigDecimal
208      * @param nodeIds List of node id
209      * @param used boolean true if min and max frequencies are used, false otherwise.
210      */
211     private void setFrequencies4Nodes(Decimal64 atozMinFrequency, Decimal64 atozMaxFrequency,
212             List<String> nodeIds, boolean used) {
213         updateFreqMaps4Nodes(nodeIds, atozMinFrequency, atozMaxFrequency, used);
214     }
215
216
217     /**
218      * Get a network termination point for nodeId and tpId.
219      * @param nodeId String
220      * @param tpId String
221      * @return network termination point, null otherwise
222      */
223     private TerminationPoint1 getNetworkTerminationPointFromDatastore(String nodeId, String tpId) {
224         InstanceIdentifier<TerminationPoint1> tpIID =
225             InstanceIdentifiers.createNetworkTerminationPoint1IIDBuilder(nodeId, tpId);
226         try (ReadTransaction readTx = this.dataBroker.newReadOnlyTransaction()) {
227             Optional<TerminationPoint1> optionalTerminationPoint = readTx
228                     .read(LogicalDatastoreType.CONFIGURATION, tpIID)
229                     .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
230             return optionalTerminationPoint.isEmpty() ? null : optionalTerminationPoint.orElseThrow();
231         } catch (ExecutionException | TimeoutException e) {
232             LOG.warn("Exception while getting termination {} for node id {} point from {} topology",
233                     tpId, nodeId, NetworkUtils.OVERLAY_NETWORK_ID, e);
234             return null;
235         } catch (InterruptedException e) {
236             LOG.warn("Getting termination {} for node id {} point from {} topology was interrupted",
237                     tpId, nodeId, NetworkUtils.OVERLAY_NETWORK_ID, e);
238             Thread.currentThread().interrupt();
239             return null;
240         }
241     }
242
243     /**
244      * Get a common network termination point for nodeId and tpId.
245      * @param nodeId String
246      * @param tpId String
247      * @return common network termination point, null otherwise
248      */
249     private org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.TerminationPoint1
250             getCommonNetworkTerminationPointFromDatastore(String nodeId, String tpId) {
251         InstanceIdentifier<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.TerminationPoint1>
252             tpIID = OpenRoadmTopology.createCommonNetworkTerminationPointIIDBuilder(nodeId, tpId).build();
253         try (ReadTransaction readTx = this.dataBroker.newReadOnlyTransaction()) {
254             Optional<org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.TerminationPoint1>
255                 optionalTerminationPoint = readTx
256                     .read(LogicalDatastoreType.CONFIGURATION, tpIID)
257                     .get(Timeouts.DATASTORE_READ, TimeUnit.MILLISECONDS);
258             if (optionalTerminationPoint.isEmpty()) {
259                 LOG.error("Unable to get common-network termination point {} for node id {}from topology {}",
260                         tpId, nodeId, NetworkUtils.OVERLAY_NETWORK_ID);
261                 return null;
262             }
263             return optionalTerminationPoint.orElseThrow();
264         } catch (ExecutionException | TimeoutException e) {
265             LOG.warn("Exception while getting common-network termination {} for node id {} point from {} topology",
266                     tpId, nodeId, NetworkUtils.OVERLAY_NETWORK_ID, e);
267             return null;
268         } catch (InterruptedException e) {
269             LOG.warn("Getting common-network termination {} for node id {} point from {} topology was interrupted",
270                     tpId, nodeId, NetworkUtils.OVERLAY_NETWORK_ID, e);
271             Thread.currentThread().interrupt();
272             return null;
273         }
274     }
275
276     /**
277      * Update availFreqMapsMap for min and max frequencies for termination point in tpIds.
278      * @param atozMinFrequency BigDecimal
279      * @param atozMaxFrequency BigDecimal
280      * @param rate Uint32
281      * @param modulationFormat ModulationFormat
282      * @param tpIds List of NodeIdPair
283      * @param sed boolean true if min and max frequencies are used, false otherwise.
284      */
285     private void setFrequencies4Tps(Decimal64 atozMinFrequency, Decimal64 atozMaxFrequency, Uint32 rate,
286             ModulationFormat modulationFormat, List<NodeIdPair> tpIds, boolean used) {
287         String strTpIdsList = String.join(", ", tpIds.stream().map(NodeIdPair::toString).collect(Collectors.toList()));
288         LOG.debug(
289             "Update frequencies for termination points {}, rate {}, modulation format {},"
290                 + " min frequency {}, max frequency {}, used {}",
291             strTpIdsList, rate, modulationFormat, atozMinFrequency, atozMaxFrequency, used);
292         WriteTransaction updateFrequenciesTransaction = this.dataBroker.newWriteOnlyTransaction();
293         for (NodeIdPair idPair : tpIds) {
294             org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.TerminationPoint1
295                     commonNetworkTerminationPoint =
296                 getCommonNetworkTerminationPointFromDatastore(idPair.getNodeID(), idPair.getTpID());
297             if (commonNetworkTerminationPoint == null) {
298                 LOG.warn("Cannot update frequencies for termination point {}, node id {}",
299                     idPair.getTpID(), idPair.getNodeID());
300                 continue;
301             }
302             TerminationPoint1 networkTerminationPoint =
303                     getNetworkTerminationPointFromDatastore(idPair.getNodeID(), idPair.getTpID());
304             TerminationPoint1Builder networkTerminationPointBuilder =
305                 networkTerminationPoint == null
306                     ? new TerminationPoint1Builder()
307                     : new TerminationPoint1Builder(networkTerminationPoint);
308             switch (commonNetworkTerminationPoint.getTpType()) {
309                 case DEGREETXTTP:
310                 case DEGREETXRXTTP:
311                     networkTerminationPointBuilder.setTxTtpAttributes(updateTxTtpAttributes(networkTerminationPoint,
312                             atozMinFrequency,atozMaxFrequency,used));
313                     break;
314                 case DEGREERXTTP:
315                     networkTerminationPointBuilder.setRxTtpAttributes(updateRxTtpAttributes(networkTerminationPoint,
316                             atozMinFrequency,atozMaxFrequency,used));
317                     break;
318                 case DEGREETXCTP:
319                 case DEGREERXCTP:
320                 case DEGREETXRXCTP:
321                     networkTerminationPointBuilder.setCtpAttributes(updateCtpAttributes(networkTerminationPoint,
322                             atozMinFrequency,atozMaxFrequency,used));
323                     break;
324                 case SRGTXCP:
325                 case SRGRXCP:
326                 case SRGTXRXCP:
327                     networkTerminationPointBuilder.setCpAttributes(updateCpAttributes(networkTerminationPoint,
328                             atozMinFrequency,atozMaxFrequency,used));
329                     break;
330                 case SRGTXRXPP:
331                 case SRGRXPP:
332                 case SRGTXPP:
333                     networkTerminationPointBuilder.setPpAttributes(updatePpAttributes(networkTerminationPoint,
334                             atozMinFrequency,atozMaxFrequency,used));
335                     break;
336                 case XPONDERNETWORK:
337                     networkTerminationPointBuilder.setXpdrNetworkAttributes(
338                             updateXpdrNetworkAttributes(networkTerminationPoint,
339                                     atozMinFrequency, atozMaxFrequency, rate, modulationFormat, used)).build();
340                     break;
341                 case XPONDERCLIENT:
342                     break;
343                 case XPONDERPORT:
344                     networkTerminationPointBuilder.setXpdrPortAttributes(
345                             updateXpdrPortAttributes(networkTerminationPoint,
346                                     atozMinFrequency, atozMaxFrequency, rate, modulationFormat, used)).build();
347                     break;
348                 default:
349                     LOG.warn("Termination point type {} not managed", commonNetworkTerminationPoint.getTpType());
350                     return;
351             }
352             updateFrequenciesTransaction.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifiers
353                     .createNetworkTerminationPoint1IIDBuilder(idPair.getNodeID(),
354                             idPair.getTpID()), networkTerminationPointBuilder.build());
355         }
356         try {
357             updateFrequenciesTransaction.commit().get(Timeouts.DATASTORE_WRITE, TimeUnit.MILLISECONDS);
358         } catch (ExecutionException | TimeoutException e) {
359             LOG.error(
360                 "Something went wrong for frequencies update (min frequency {}, max frequency {}, used {} for TPs {}",
361                 atozMinFrequency, atozMaxFrequency, used, strTpIdsList, e);
362         } catch (InterruptedException e) {
363             LOG.error("Frequencies update (min frequency {}, max frequency {}, used {} for TPs {} was interrupted",
364                     atozMinFrequency, atozMaxFrequency, used,
365                     strTpIdsList, e);
366             Thread.currentThread().interrupt();
367         }
368     }
369
370     /**
371      * Update availFreqMapsMap for min and max frequencies for nodes in nodeIds.
372      * @param nodeIds  List of node id
373      * @param atozMinFrequency BigDecimal
374      * @param atozMaxFrequency BigDecimal
375      * @param used boolean true if min and max frequencies are used, false otherwise.
376      */
377     private void updateFreqMaps4Nodes(List<String> nodeIds, Decimal64 atozMinFrequency, Decimal64 atozMaxFrequency,
378             boolean used) {
379         String strNodesList = String.join(", ", nodeIds);
380         LOG.debug("Update frequencies for nodes {}, min frequency {}, max frequency {}, used {}",
381                 strNodesList, atozMinFrequency, atozMaxFrequency, used);
382         WriteTransaction updateFrequenciesTransaction = this.dataBroker.newWriteOnlyTransaction();
383         for (String nodeId : nodeIds) {
384             Node1 networkNode = getNetworkNodeFromDatastore(nodeId);
385             org.opendaylight.yang.gen.v1.http.org.openroadm.common.network.rev211210.Node1 commonNetworkNode =
386                     getCommonNetworkNodeFromDatastore(nodeId);
387             if (networkNode == null || commonNetworkNode == null) {
388                 LOG.warn(
389                         "From topology {} for node id {} -> Get common-network : {} "
390                                 + "Get network-topology : {}. Skipping frequencies update for this node.",
391                         NetworkUtils.OVERLAY_NETWORK_ID, nodeId, commonNetworkNode, networkNode);
392                 continue;
393             }
394             Node1Builder networkNodeBuilder = new Node1Builder(networkNode);
395             switch (commonNetworkNode.getNodeType()) {
396                 case DEGREE:
397                     networkNodeBuilder.setDegreeAttributes(
398                             updateDegreeAttributes(networkNode.getDegreeAttributes(), atozMinFrequency,
399                                     atozMaxFrequency, used));
400                     break;
401                 case SRG:
402                     networkNodeBuilder.setSrgAttributes(updateSrgAttributes(
403                             networkNode.getSrgAttributes(), atozMinFrequency, atozMaxFrequency, used));
404                     break;
405                 default:
406                     LOG.warn("Node type not managed {}", commonNetworkNode.getNodeType());
407                     break;
408             }
409             updateFrequenciesTransaction.put(LogicalDatastoreType.CONFIGURATION,
410                     OpenRoadmTopology.createNetworkNodeIID(nodeId), networkNodeBuilder.build());
411         }
412         try {
413             updateFrequenciesTransaction.commit().get(Timeouts.DATASTORE_WRITE, TimeUnit.MILLISECONDS);
414         } catch (ExecutionException | TimeoutException e) {
415             LOG.error("Cannot update frequencies {} {} for nodes {}", atozMinFrequency, atozMaxFrequency,
416                     strNodesList, e);
417         } catch (InterruptedException e) {
418             LOG.error("Update of frequencies {} {} for nodes {} was interrupted", atozMinFrequency, atozMaxFrequency,
419                     strNodesList, e);
420             Thread.currentThread().interrupt();
421         }
422     }
423
424     /**
425      * Get list of NodeIdPair from atoZDirection.
426      * @param atoZDirection AToZDirection
427      * @return List of NodeIdPair
428      */
429     private List<NodeIdPair> getAToZTpList(AToZDirection atoZDirection) {
430         return atoZDirection.nonnullAToZ().values().stream()
431                 .filter(aToZ -> {
432                     if (aToZ.getResource() == null || aToZ.getResource().getResource() == null) {
433                         LOG.warn("Resource of AToZ node {} is null! Skipping this node!", aToZ.getId());
434                         return false;
435                     }
436                     return aToZ.getResource().getResource() instanceof TerminationPoint;
437                 }).map(aToZ -> {
438                     TerminationPoint tp = (TerminationPoint) aToZ.getResource().getResource();
439                     if (tp == null || tp.getTpNodeId() == null || tp.getTpId() == null || tp.getTpId().isEmpty()) {
440                         LOG.warn("Termination point in AToZ node {} contains nulls! Skipping this node!", aToZ.getId());
441                         return null;
442                     }
443                     return new NodeIdPair(tp.getTpNodeId(), tp.getTpId());
444                 }).filter(Objects::nonNull)
445                 .collect(Collectors.toList());
446     }
447
448     /**
449      * Get list of NodeIdPair from ztoADirection.
450      * @param ztoADirection ZToADirection
451      * @return List of NodeIdPair
452      */
453     private List<NodeIdPair> getZToATpList(ZToADirection ztoADirection) {
454         return ztoADirection.nonnullZToA().values().stream()
455                 .filter(zToA -> {
456                     if (zToA.getResource() == null || zToA.getResource().getResource() == null) {
457                         LOG.warn("Resource of ZToA node {} is null! Skipping this node!", zToA.getId());
458                         return false;
459                     }
460                     return zToA.getResource().getResource() instanceof TerminationPoint;
461                 }).map(zToA -> {
462                     TerminationPoint tp = (TerminationPoint) zToA.getResource().getResource();
463                     if (tp == null || tp.getTpNodeId() == null || tp.getTpId() == null || tp.getTpId().isEmpty()) {
464                         LOG.warn("Termination point in ZToA node {} contains nulls! Skipping this node!", zToA.getId());
465                         return null;
466                     }
467                     return new NodeIdPair(tp.getTpNodeId(), tp.getTpId());
468                 }).filter(Objects::nonNull)
469                 .collect(Collectors.toList());
470     }
471
472     /**
473      * Update Wavelength for xpdr port attributes.
474      * @param networkTerminationPoint TerminationPoint1
475      * @param atozMinFrequency BigDecimal
476      * @param atozMaxFrequency BigDecimal
477      * @param rate Uint32
478      * @param modulationFormat ModulationFormat
479      * @param used boolean true if min and max frequencies are used, false otherwise.
480      * @return XpdrPortAttributes with Wavelength updated
481      */
482     private XpdrPortAttributes updateXpdrPortAttributes(TerminationPoint1 networkTerminationPoint,
483             Decimal64 atozMinFrequency, Decimal64 atozMaxFrequency, Uint32 rate, ModulationFormat modulationFormat,
484             boolean used) {
485         LOG.debug("Update xpdr node attributes for termination point {}, min frequency {}, max frequency {}, used {}",
486                 networkTerminationPoint, atozMinFrequency, atozMaxFrequency, used);
487         XpdrPortAttributesBuilder xpdrPortAttributesBuilder =
488             networkTerminationPoint == null
489                 ? new XpdrPortAttributesBuilder()
490                 : new XpdrPortAttributesBuilder(networkTerminationPoint.getXpdrPortAttributes());
491         return xpdrPortAttributesBuilder
492             .setWavelength(
493                 used
494                     ? new WavelengthBuilder()
495                         .setWidth(GridUtils.getWidthFromRateAndModulationFormat(rate, modulationFormat))
496                         .setFrequency(
497                             GridUtils.getCentralFrequency(
498                                 atozMinFrequency.decimalValue(),
499                                 atozMaxFrequency.decimalValue()))
500                         .build()
501                     : new WavelengthBuilder().build())
502             .build();
503     }
504
505     /**
506      * Update Wavelength for xpdr network attributes.
507      * @param networkTerminationPoint TerminationPoint1
508      * @param atozMinFrequency BigDecimal
509      * @param atozMaxFrequency BigDecimal
510      * @param rate Uint32
511      * @param modulationFormat ModulationFormat
512      * @param used boolean true if min and max frequencies are used, false otherwise.
513      * @return XpdrNetworkAttributes with Wavelength updated
514      */
515     private XpdrNetworkAttributes updateXpdrNetworkAttributes(TerminationPoint1 networkTerminationPoint,
516             Decimal64 atozMinFrequency, Decimal64 atozMaxFrequency, Uint32 rate, ModulationFormat modulationFormat,
517             boolean used) {
518         LOG.debug("Update xpdr node attributes for termination point {}, min frequency {}, max frequency {}, used {}",
519                 networkTerminationPoint, atozMinFrequency, atozMaxFrequency, used);
520         XpdrNetworkAttributesBuilder xpdrNetworkAttributesBuilder =
521             networkTerminationPoint == null
522                 ? new XpdrNetworkAttributesBuilder()
523                 : new XpdrNetworkAttributesBuilder(networkTerminationPoint.getXpdrNetworkAttributes());
524         return xpdrNetworkAttributesBuilder
525             .setWavelength(
526                 used
527                     ? new WavelengthBuilder()
528                         .setWidth(GridUtils.getWidthFromRateAndModulationFormat(rate, modulationFormat))
529                         .setFrequency(
530                             GridUtils.getCentralFrequency(
531                                 atozMinFrequency.decimalValue(),
532                                 atozMaxFrequency.decimalValue()))
533                         .build()
534                     : null)
535             .build();
536
537     }
538
539     /**
540      * Update freqMaps for pp attributes.
541      * @param networkTerminationPoint TerminationPoint1
542      * @param atozMinFrequency BigDecimal
543      * @param atozMaxFrequency BigDecimal
544      * @param used boolean true if min and max frequencies are used, false otherwise.
545      * @return PpAttributes with frequency map updated
546      */
547     private PpAttributes updatePpAttributes(TerminationPoint1 networkTerminationPoint, Decimal64 atozMinFrequency,
548             Decimal64 atozMaxFrequency, boolean used) {
549         LOG.debug("Update pp attributes for termination point {}, min frequency {}, max frequency {}, used {}",
550                 networkTerminationPoint, atozMinFrequency, atozMaxFrequency, used);
551         PpAttributesBuilder ppAttributesBuilder =
552             networkTerminationPoint == null
553                 ? new PpAttributesBuilder()
554                 : new PpAttributesBuilder(networkTerminationPoint.getPpAttributes());
555         return ppAttributesBuilder
556             .setAvailFreqMaps(
557                 updateFreqMaps(
558                     atozMinFrequency, atozMaxFrequency,
559                     ppAttributesBuilder.getAvailFreqMaps(),
560                     used))
561             .build();
562     }
563
564     /**
565      * Update freqMaps for cp attributes.
566      * @param networkTerminationPoint TerminationPoint1
567      * @param atozMinFrequency BigDecimal
568      * @param atozMaxFrequency BigDecimal
569      * @param used boolean true if min and max frequencies are used, false otherwise.
570      * @return CpAttributes with frequency map updated
571      */
572     private CpAttributes updateCpAttributes(TerminationPoint1 networkTerminationPoint, Decimal64 atozMinFrequency,
573             Decimal64 atozMaxFrequency, boolean used) {
574         LOG.debug("Update cp attributes for termination point {}, min frequency {}, max frequency {}, used {}",
575                 networkTerminationPoint, atozMinFrequency, atozMaxFrequency, used);
576         CpAttributesBuilder cpAttributesBuilder =
577             networkTerminationPoint == null
578                 ? new CpAttributesBuilder()
579                 : new CpAttributesBuilder(networkTerminationPoint.getCpAttributes());
580         return cpAttributesBuilder
581             .setAvailFreqMaps(
582                 updateFreqMaps(
583                     atozMinFrequency, atozMaxFrequency,
584                     cpAttributesBuilder.getAvailFreqMaps(),
585                     used))
586             .build();
587     }
588
589     /**
590      * Update freqMaps for ctp attributes.
591      * @param networkTerminationPoint TerminationPoint1
592      * @param atozMinFrequency BigDecimal
593      * @param atozMaxFrequency BigDecimal
594      * @param used boolean true if min and max frequencies are used, false otherwise.
595      * @return CtpAttributes with frequency map updated
596      */
597     private CtpAttributes updateCtpAttributes(TerminationPoint1 networkTerminationPoint, Decimal64 atozMinFrequency,
598             Decimal64 atozMaxFrequency, boolean used) {
599         LOG.debug("Update ctp attributes for termination point {}, min frequency {}, max frequency {}, used {}",
600                 networkTerminationPoint, atozMinFrequency, atozMaxFrequency, used);
601         CtpAttributesBuilder ctpAttributesBuilder =
602             networkTerminationPoint == null
603                 ?  new CtpAttributesBuilder()
604                 :  new CtpAttributesBuilder(networkTerminationPoint.getCtpAttributes());
605         return ctpAttributesBuilder
606             .setAvailFreqMaps(
607                 updateFreqMaps(
608                     atozMinFrequency, atozMaxFrequency,
609                     ctpAttributesBuilder.getAvailFreqMaps(),
610                     used))
611             .build();
612     }
613
614     /**
615      * Update freqMaps for rxtp attributes.
616      * @param networkTerminationPoint TerminationPoint1
617      * @param atozMinFrequency BigDecimal
618      * @param atozMaxFrequency BigDecimal
619      * @param used boolean true if min and max frequencies are used, false otherwise.
620      * @return RxTtpAttributes with frequency map updated
621      */
622     private RxTtpAttributes updateRxTtpAttributes(TerminationPoint1 networkTerminationPoint, Decimal64 atozMinFrequency,
623             Decimal64 atozMaxFrequency, boolean used) {
624         LOG.debug("Update rx attributes for termination point {}, min frequency {}, max frequency {}, used {}",
625                 networkTerminationPoint, atozMinFrequency, atozMaxFrequency, used);
626         RxTtpAttributesBuilder rxTtpAttributesBuilder =
627             networkTerminationPoint == null
628                 ? new RxTtpAttributesBuilder()
629                 : new RxTtpAttributesBuilder(networkTerminationPoint.getRxTtpAttributes());
630         return rxTtpAttributesBuilder
631             .setAvailFreqMaps(
632                 updateFreqMaps(
633                     atozMinFrequency, atozMaxFrequency,
634                     rxTtpAttributesBuilder.getAvailFreqMaps(),
635                     used))
636             .build();
637     }
638
639     /**
640      * Update freqMaps for txtp attributes.
641      * @param networkTerminationPoint TerminationPoint1
642      * @param atozMinFrequency BigDecimal
643      * @param atozMaxFrequency BigDecimal
644      * @param used boolean true if min and max frequencies are used, false otherwise.
645      * @return TxTtpAttributes with frequency map updated
646      */
647     private TxTtpAttributes updateTxTtpAttributes(TerminationPoint1 networkTerminationPoint, Decimal64 atozMinFrequency,
648             Decimal64 atozMaxFrequency, boolean used) {
649         LOG.debug("Update tx attributes for termination point {}, min frequency {}, max frequency {}, used {}",
650                 networkTerminationPoint, atozMinFrequency, atozMaxFrequency, used);
651         TxTtpAttributesBuilder txTtpAttributesBuilder =
652             networkTerminationPoint == null
653                 ? new TxTtpAttributesBuilder()
654                 : new TxTtpAttributesBuilder(networkTerminationPoint.getTxTtpAttributes());
655         return txTtpAttributesBuilder
656             .setAvailFreqMaps(
657                 updateFreqMaps(
658                     atozMinFrequency, atozMaxFrequency,
659                     txTtpAttributesBuilder.getAvailFreqMaps(),
660                     used))
661             .build();
662     }
663
664     /**
665      * Update freqMaps for srg attributes of srgAttributes.
666      * @param srgAttributes SrgAttributes
667      * @param atozMinFrequency BigDecimal
668      * @param atozMaxFrequency BigDecimal
669      * @param used boolean true if min and max frequencies are used, false otherwise.
670      * @return SrgAttributes with frequency map updated
671      */
672     private SrgAttributes updateSrgAttributes(SrgAttributes srgAttributes, Decimal64 atozMinFrequency,
673             Decimal64 atozMaxFrequency, boolean used) {
674         SrgAttributesBuilder srgAttributesBuilder =
675             srgAttributes == null
676                 ? new SrgAttributesBuilder()
677                 : new SrgAttributesBuilder(srgAttributes);
678         return srgAttributesBuilder
679             .setAvailFreqMaps(
680                 updateFreqMaps(
681                     atozMinFrequency, atozMaxFrequency,
682                     srgAttributesBuilder.getAvailFreqMaps(),
683                     used))
684             .build();
685     }
686
687     /**
688      * Update freqMaps for degree attributes of degreeAttributes.
689      * @param degreeAttributes DegreeAttributes
690      * @param atozMinFrequency BigDecimal
691      * @param atozMaxFrequency BigDecimal
692      * @param used boolean true if min and max frequencies are used, false otherwise.
693      * @return DegreeAttributes with frequency map updated
694      */
695     private DegreeAttributes updateDegreeAttributes(DegreeAttributes degreeAttributes, Decimal64 atozMinFrequency,
696             Decimal64 atozMaxFrequency, boolean used) {
697         DegreeAttributesBuilder degreeAttributesBuilder =
698             degreeAttributes == null
699                 ? new DegreeAttributesBuilder()
700                 : new DegreeAttributesBuilder(degreeAttributes);
701         return degreeAttributesBuilder
702             .setAvailFreqMaps(
703                 updateFreqMaps(
704                     atozMinFrequency, atozMaxFrequency,
705                     degreeAttributesBuilder.getAvailFreqMaps(),
706                     used))
707             .build();
708     }
709
710     /**
711      * Update availFreqMapsMap for min and max frequencies for cband AvailFreqMaps.
712      * @param atozMinFrequency BigDecimal
713      * @param atozMaxFrequency BigDecimal
714      * @param availFreqMapsMap Map
715      * @param used boolean
716      * @return updated Update availFreqMapsMap for min and max frequencies for cband AvailFreqMaps.
717      */
718     private Map<AvailFreqMapsKey, AvailFreqMaps> updateFreqMaps(Decimal64 atozMinFrequency, Decimal64 atozMaxFrequency,
719             Map<AvailFreqMapsKey, AvailFreqMaps> availFreqMapsMap, boolean used) {
720         int beginIndex = GridUtils.getIndexFromFrequency(atozMinFrequency);
721         int endIndex = GridUtils.getIndexFromFrequency(atozMaxFrequency);
722         if (availFreqMapsMap == null) {
723             availFreqMapsMap = GridUtils.initFreqMaps4FixedGrid2Available();
724         }
725         AvailFreqMaps availFreqMaps = availFreqMapsMap.get(availFreqMapKey);
726         if (availFreqMaps == null || availFreqMaps.getFreqMap() == null) {
727             return availFreqMapsMap;
728         }
729         BitSet bitSetFreq = BitSet.valueOf(availFreqMaps.getFreqMap());
730         LOG.debug(
731              "Update frequency map from index {}, to index {}, min frequency {}, max frequency {}, available {} {}",
732              beginIndex, endIndex, atozMinFrequency, atozMaxFrequency, !used, bitSetFreq);
733         //if used = true then bit must be set to false to indicate the slot is no more available
734         bitSetFreq.set(beginIndex, endIndex, !used);
735         LOG.debug(
736             "Updated frequency map from index {}, to index {}, min frequency {}, max frequency {}, available {} {}",
737             beginIndex, endIndex, atozMinFrequency, atozMaxFrequency, !used, bitSetFreq);
738         AvailFreqMaps updatedAvailFreqMaps = new AvailFreqMapsBuilder(availFreqMaps)
739                 .setFreqMap(Arrays.copyOf(bitSetFreq.toByteArray(), GridConstant.NB_OCTECTS))
740                 .build();
741         return new HashMap<>(Map.of(availFreqMaps.key(), updatedAvailFreqMaps));
742     }
743 }