2 * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.vpnmanager;
10 import com.google.common.collect.ImmutableMap;
11 import com.google.common.util.concurrent.ThreadFactoryBuilder;
12 import java.util.ArrayList;
13 import java.util.Iterator;
14 import java.util.List;
16 import java.util.concurrent.ConcurrentHashMap;
17 import java.util.concurrent.ExecutorService;
18 import java.util.concurrent.Executors;
19 import java.util.concurrent.ThreadFactory;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
24 * Aims to provide a common synchronization point for all those classes that
25 * want to know when certain type of Operational data is ready for a given VPN,
26 * and those others that can notify that the Operational data is ready.
28 public class VpnOpDataSyncer {
30 static final Logger LOG = LoggerFactory.getLogger(VpnOpDataSyncer.class);
32 public enum VpnOpDataType {
37 // Maps a VpnName with a list of Task to be executed once the the Vpn is fully ready.
38 private final ConcurrentHashMap<String, List<Runnable>> vpnInst2IdSynchronizerMap = new ConcurrentHashMap<>();
39 private final ConcurrentHashMap<String, List<Runnable>> vpnInst2OpDataSynchronizerMap = new ConcurrentHashMap<>();
41 // The only purpose of this map is being able to reuse code
42 private final Map<VpnOpDataType, ConcurrentHashMap<String, List<Runnable>>> mapOfMaps =
43 ImmutableMap.<VpnOpDataType, ConcurrentHashMap<String, List<Runnable>>>builder()
44 .put(VpnOpDataType.vpnInstanceToId, vpnInst2IdSynchronizerMap)
45 .put(VpnOpDataType.vpnOpData, vpnInst2OpDataSynchronizerMap)
49 private static final ThreadFactory THREAD_FACTORY =
50 new ThreadFactoryBuilder().setNameFormat("NV-VpnMgr-%d").build();
51 private final ExecutorService executorService = Executors.newSingleThreadExecutor(THREAD_FACTORY);
54 public boolean waitForVpnDataReady(VpnOpDataType vpnOpDataType, String vpnName, long maxWaitMillis,
57 boolean isDataReady = false;
60 isDataReady = waitForVpnDataReady(vpnOpDataType, vpnName, maxWaitMillis);
62 while (!isDataReady && attempts < maxAttempts);
67 public boolean waitForVpnDataReady(VpnOpDataType dataType, String vpnName, long maxWaitMillis) {
68 //TODO(vivek) This waiting business to be removed in carbon
69 boolean dataReady = false;
70 ConcurrentHashMap<String, List<Runnable>> listenerMap = mapOfMaps.get(dataType);
71 Runnable notifyTask = new VpnNotifyTask();
72 List<Runnable> notifieeList = null;
74 synchronized (listenerMap) {
75 listenerMap.computeIfAbsent(vpnName, k -> new ArrayList<>()).add(notifyTask);
78 synchronized (notifyTask) {
79 long t0 = System.nanoTime();
80 long elapsedTimeNs = t0;
83 notifyTask.wait(maxWaitMillis);
84 elapsedTimeNs = System.nanoTime() - t0;
86 if (elapsedTimeNs < (maxWaitMillis * 1000000)) {
87 // Thread woken up before timeout
88 LOG.debug("Its been reported that VPN {} is now ready", vpnName);
92 LOG.debug("Vpn {} OpData not ready after {}ms", vpnName, maxWaitMillis);
95 } catch (InterruptedException e) {
100 synchronized (listenerMap) {
101 notifieeList = listenerMap.get(vpnName);
102 if (notifieeList != null) {
103 notifieeList.remove(notifyTask);
104 if (notifieeList.isEmpty()) {
105 listenerMap.remove(vpnName);
113 public void notifyVpnOpDataReady(VpnOpDataType dataType, String vpnName) {
114 LOG.debug("Reporting that vpn {} is ready", vpnName);
115 ConcurrentHashMap<String, List<Runnable>> listenerMap = mapOfMaps.get(dataType);
116 synchronized (listenerMap) {
117 List<Runnable> notifieeList = listenerMap.remove(vpnName);
118 if (notifieeList == null) {
119 LOG.trace(" No notify tasks found for vpnName {}", vpnName);
122 Iterator<Runnable> notifieeIter = notifieeList.iterator();
123 while (notifieeIter.hasNext()) {
124 Runnable notifyTask = notifieeIter.next();
125 executorService.execute(notifyTask);
126 notifieeIter.remove();