Open Kilda Java Documentation
NetworkCache.java
Go to the documentation of this file.
1 /* Copyright 2017 Telstra Open Source
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package org.openkilda.pce.cache;
17 
24 
25 import com.google.common.annotations.VisibleForTesting;
26 import com.google.common.base.MoreObjects;
27 import com.google.common.graph.EndpointPair;
28 import com.google.common.graph.MutableNetwork;
29 import com.google.common.graph.NetworkBuilder;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32 
33 import java.util.HashSet;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.concurrent.ConcurrentHashMap;
37 import java.util.stream.Collectors;
38 
39 public class NetworkCache extends Cache {
43  private static final Logger logger = LoggerFactory.getLogger(NetworkCache.class);
44 
48  private final MutableNetwork<SwitchInfoData, IslInfoData> network = NetworkBuilder
49  .directed()
50  .allowsSelfLoops(false)
51  .allowsParallelEdges(true)
52  .build();
53 
57  private final Map<SwitchId, SwitchInfoData> switchPool = new ConcurrentHashMap<>();
58 
62  private final Map<String, IslInfoData> islPool = new ConcurrentHashMap<>();
63 
70  public void load(Set<SwitchInfoData> switches, Set<IslInfoData> isls) {
71  logger.debug("Switches: {}", switches);
72  switches.forEach(this::createSwitch);
73 
74  logger.debug("Isls: {}", isls);
75  isls.forEach(this::createIsl);
76  }
77 
85  public Set<IslInfoData> getIslsBySource(SwitchId switchId) {
86  logger.debug("Get all isls by source switch {}", switchId);
87 
88  SwitchInfoData startNode = getSwitch(switchId);
89 
90  return network.outEdges(startNode);
91  }
92 
100  public Set<IslInfoData> getIslsByDestination(SwitchId switchId) {
101  logger.debug("Get all isls by destination switch {}", switchId);
102 
103  SwitchInfoData endNode = getSwitch(switchId);
104 
105  return network.inEdges(endNode);
106  }
107 
115  public Set<IslInfoData> getIslsBySwitch(SwitchId switchId) throws CacheException {
116  logger.debug("Get all isls incident switch {}", switchId);
117 
118  SwitchInfoData node = getSwitch(switchId);
119 
120  return network.incidentEdges(node);
121  }
122 
129  public Set<SwitchInfoData> getStateSwitches(SwitchState state) {
130  logger.debug("Get all switches in {} state", state);
131 
132  return network.nodes().stream()
133  .filter(sw -> sw.getState() == state)
134  .collect(Collectors.toSet());
135  }
136 
143  public Set<SwitchInfoData> getControllerSwitches(String controller) {
144  logger.debug("Get all switches connected to {} controller", controller);
145 
146  return network.nodes().stream()
147  .filter(sw -> sw.getController().equals(controller))
148  .collect(Collectors.toSet());
149  }
150 
158  public Set<SwitchInfoData> getDirectlyConnectedSwitches(SwitchId switchId) throws CacheException {
159  logger.debug("Get all switches directly connected to {} switch ", switchId);
160 
161  SwitchInfoData node = getSwitch(switchId);
162 
163  return network.adjacentNodes(node);
164  }
165 
169  public void clear() {
170  islPool.values().forEach(network::removeEdge);
171  islPool.clear();
172 
173  switchPool.values().forEach(network::removeNode);
174  switchPool.clear();
175  }
176 
185  logger.debug("Get {} switch", switchId);
186 
187  SwitchInfoData node = switchPool.get(switchId);
188  if (node == null) {
189  throw new CacheException(ErrorType.NOT_FOUND, "Can not get switch",
190  String.format("SimpleSwitch %s not found", switchId));
191  }
192 
193  return node;
194  }
195 
204  SwitchId switchId = newSwitch.getSwitchId();
205 
206  logger.debug("Create {} switch with {} parameters", switchId, newSwitch);
207 
208  SwitchInfoData oldSwitch = switchPool.get(switchId);
209  if (oldSwitch != null) {
210  throw new CacheException(ErrorType.ALREADY_EXISTS, "Can not create switch",
211  String.format("SimpleSwitch %s already exists", switchId));
212  }
213 
214  newSwitch.setCreatedInCacheNow();
215 
216  network.addNode(newSwitch);
217  switchPool.put(switchId, newSwitch);
218 
219  return newSwitch;
220  }
221 
230  SwitchId switchId = newSwitch.getSwitchId();
231  logger.debug("Update {} switch with {} parameters", switchId, newSwitch);
232 
233  SwitchInfoData oldSwitch = switchPool.remove(switchId);
234  if (oldSwitch == null) {
235  throw new CacheException(ErrorType.NOT_FOUND, "Can not update switch",
236  String.format("SimpleSwitch %s not found", switchId));
237  }
238 
239  newSwitch.copyTimeTag(oldSwitch);
240  newSwitch.setUpdatedInCacheNow();
241 
242  network.removeNode(oldSwitch);
243  network.addNode(newSwitch);
244  switchPool.put(switchId, newSwitch);
245 
246  return newSwitch;
247  }
248 
257  logger.debug("Create Or Update {} switch with {} parameters", newSwitch);
258 
259  if (newSwitch == null) {
260  throw new IllegalArgumentException("SimpleSwitch can't be null in createOrUpdateSwitch");
261  }
262 
263  if (cacheContainsSwitch(newSwitch.getSwitchId())) {
264  return updateSwitch(newSwitch);
265  } else {
266  return createSwitch(newSwitch);
267  }
268  }
269 
278  logger.debug("Delete {} switch", switchId);
279 
280  SwitchInfoData node = switchPool.remove(switchId);
281  if (node == null) {
282  throw new CacheException(ErrorType.NOT_FOUND, "Can not delete switch",
283  String.format("SimpleSwitch %s not found", switchId));
284  }
285 
286  network.removeNode(node);
287 
288  return node;
289  }
290 
296  public Set<SwitchInfoData> dumpSwitches() {
297  logger.debug("Get all switches");
298 
299  return new HashSet<>(network.nodes());
300  }
301 
308  public boolean cacheContainsSwitch(SwitchId switchId) {
309  logger.debug("Is switch {} in cache", switchId);
310 
311  return switchPool.containsKey(switchId);
312  }
313 
320  public boolean switchIsOperable(SwitchId switchId) {
321  if (cacheContainsSwitch(switchId)) {
322  SwitchState switchState = switchPool.get(switchId).getState();
323  if (SwitchState.ADDED == switchState || SwitchState.ACTIVATED == switchState) {
324  return true;
325  }
326  }
327  return false;
328  }
329 
337  public IslInfoData getIsl(String islId) throws CacheException {
338  logger.debug("Get {} isl", islId);
339 
340  IslInfoData isl = islPool.get(islId);
341  if (isl == null) {
342  throw new CacheException(ErrorType.NOT_FOUND, "Can not get isl",
343  String.format("SimpleIsl %s not found", islId));
344  }
345 
346  return islPool.get(islId);
347  }
348 
357  String islId = isl.getId();
358  logger.debug("Create {} isl with {} parameters", islId, isl);
359 
360  isl.setCreatedInCacheNow();
361 
362  EndpointPair<SwitchInfoData> nodes = getIslSwitches(isl);
363  network.addEdge(nodes.source(), nodes.target(), isl);
364 
365  return islPool.put(islId, isl);
366  }
367 
376  String islId = isl.getId();
377  logger.debug("Update {} isl with {} parameters", islId, isl);
378 
379  IslInfoData oldIsl = islPool.get(islId);
380  network.removeEdge(oldIsl);
381 
382  isl.copyTimeTag(oldIsl);
383  isl.setUpdatedInCacheNow();
384 
385  EndpointPair<SwitchInfoData> nodes = getIslSwitches(isl);
386  network.addEdge(nodes.source(), nodes.target(), isl);
387 
388  return islPool.put(islId, isl);
389  }
390 
399  logger.debug("Create or Update {} isl with {} parameters", isl);
400 
401  if (isl == null) {
402  throw new IllegalArgumentException("ISL can't be null in createOrUpdateIsl");
403  }
404 
405  if (cacheContainsIsl(isl.getId())) {
406  return updateIsl(isl);
407  } else {
408  return createIsl(isl);
409  }
410  }
411 
419  public IslInfoData deleteIsl(String islId) throws CacheException {
420  logger.debug("Delete {} isl", islId);
421 
422  IslInfoData isl = islPool.remove(islId);
423  if (isl == null) {
424  throw new CacheException(ErrorType.NOT_FOUND, "Can not delete isl",
425  String.format("SimpleIsl %s not found", islId));
426  }
427 
428  network.removeEdge(isl);
429 
430  return isl;
431  }
432 
438  public Set<IslInfoData> dumpIsls() {
439  logger.debug("Get all isls");
440 
441  return new HashSet<>(network.edges());
442  }
443 
450  public boolean cacheContainsIsl(String islId) {
451  logger.debug("Is isl {} in cache", islId);
452 
453  return islPool.containsKey(islId);
454  }
455 
461  @VisibleForTesting
462  MutableNetwork<SwitchInfoData, IslInfoData> getNetwork() {
463  return network;
464  }
465 
473  private EndpointPair<SwitchInfoData> getIslSwitches(IslInfoData isl) throws CacheException {
474  SwitchId srcSwitch = isl.getPath().get(0).getSwitchId();
475  if (srcSwitch == null) {
476  throw new CacheException(ErrorType.PARAMETERS_INVALID, "Can not get isl nodes",
477  "Source switch not specified");
478  }
479 
480  SwitchInfoData startNode = getSwitch(srcSwitch);
481 
482  SwitchId dstSwitch = isl.getPath().get(1).getSwitchId();
483  if (dstSwitch == null) {
484  throw new CacheException(ErrorType.PARAMETERS_INVALID, "Can not get isl nodes",
485  "Destination switch not specified");
486  }
487 
488  SwitchInfoData endNode = getSwitch(dstSwitch);
489 
490  return EndpointPair.ordered(startNode, endNode);
491  }
492 
493  @Override
494  public String toString() {
495  return MoreObjects.toStringHelper(this)
496  .add("switches", switchPool)
497  .add("isls", islPool)
498  .toString();
499  }
500 }
IslInfoData deleteIsl(String islId)
IslInfoData updateIsl(IslInfoData isl)
Set< SwitchInfoData > getControllerSwitches(String controller)
Set< SwitchInfoData > getStateSwitches(SwitchState state)
boolean cacheContainsIsl(String islId)
SwitchInfoData updateSwitch(SwitchInfoData newSwitch)
Set< IslInfoData > getIslsBySource(SwitchId switchId)
IslInfoData createOrUpdateIsl(IslInfoData isl)
IslInfoData createIsl(IslInfoData isl)
Set< SwitchInfoData > getDirectlyConnectedSwitches(SwitchId switchId)
Set< IslInfoData > getIslsByDestination(SwitchId switchId)
SwitchInfoData deleteSwitch(SwitchId switchId)
Definition: nodes.py:1
SwitchInfoData createSwitch(SwitchInfoData newSwitch)
Set< IslInfoData > getIslsBySwitch(SwitchId switchId)
boolean switchIsOperable(SwitchId switchId)
Set< SwitchInfoData > dumpSwitches()
void load(Set< SwitchInfoData > switches, Set< IslInfoData > isls)
IslInfoData getIsl(String islId)
SwitchInfoData getSwitch(SwitchId switchId)
SwitchInfoData createOrUpdateSwitch(SwitchInfoData newSwitch)
boolean cacheContainsSwitch(SwitchId switchId)