4817cbd922b0685fb095138bd36b174ba6edb9d4
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / main / java / org / opendaylight / ovsdb / hwvtepsouthbound / HwvtepDeviceInfo.java
1 /*
2  * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. 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
9 package org.opendaylight.ovsdb.hwvtepsouthbound;
10
11 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependencyQueue;
12 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependentJob;
13 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.TransactCommand;
14 import org.opendaylight.ovsdb.lib.notation.UUID;
15 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
16 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
17 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalSwitch;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
19 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
20 import org.opendaylight.yangtools.yang.binding.Identifiable;
21 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.Map;
28 import java.util.concurrent.ConcurrentHashMap;
29
30 /*
31  * HwvtepDeviceInfo is used to store some of the table entries received
32  * in updates from a Hwvtep device. There will be one instance of this per
33  * Hwvtep device connected. Table entries are stored in a map keyed by
34  * uuids of respective rows.
35  *
36  * Purpose of this class is to provide data present in tables which
37  * were updated in a previous transaction and are not available in
38  * current updatedRows. This allows us to handle updates for Tables
39  * which reference other tables and need information in those tables
40  * to add data to Operational data store.
41  *
42  * e.g. Mac-entries in data store use logical-switch-ref as one of the
43  * keys. Mac-entry updates from switch rarely contain Logical_Switch
44  * table entries. To add mac-entries we need table entries from
45  * Logical_Switch table which were created in an earlier update.
46  *
47  */
48 public class HwvtepDeviceInfo {
49
50     private static final Logger LOG = LoggerFactory.getLogger(HwvtepDeviceInfo.class);
51
52     public enum DeviceDataStatus {
53         IN_TRANSIT,
54         UNAVAILABLE,
55         AVAILABLE
56     }
57
58     public static class DeviceData {
59         private final InstanceIdentifier key;
60         private final UUID uuid;
61         private final Object data;
62         private final DeviceDataStatus status;
63
64         DeviceData(InstanceIdentifier key, UUID uuid, Object data, DeviceDataStatus status) {
65             this.data = data;
66             this.key = key;
67             this.status = status;
68             this.uuid = uuid;
69         }
70
71         public Object getData() {
72             return data;
73         }
74
75         public DeviceDataStatus getStatus() {
76             return status;
77         }
78
79         public UUID getUuid() {
80             return uuid;
81         }
82     }
83
84     //TODO remove this
85     private Map<UUID, LogicalSwitch> logicalSwitches = null;
86     private Map<UUID, PhysicalSwitch> physicalSwitches = null;
87     private Map<UUID, PhysicalLocator> physicalLocators = null;
88     private Map<UUID, UUID> mapTunnelToPhysicalSwitch = null;
89
90     private HwvtepConnectionInstance connectionInstance;
91
92     private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> configKeyVsData = new ConcurrentHashMap<>();
93     private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> opKeyVsData = new ConcurrentHashMap<>();
94     private Map<Class<? extends Identifiable>, Map<UUID, Object>> uuidVsData = new ConcurrentHashMap<>();
95     private DependencyQueue dependencyQueue;
96
97     public HwvtepDeviceInfo(HwvtepConnectionInstance hwvtepConnectionInstance) {
98         this.connectionInstance = hwvtepConnectionInstance;
99         this.logicalSwitches = new HashMap<>();
100         this.physicalSwitches = new HashMap<>();
101         this.physicalLocators = new HashMap<>();
102         this.mapTunnelToPhysicalSwitch = new HashMap<>();
103         this.dependencyQueue = new DependencyQueue(this);
104     }
105
106     public LogicalSwitch getLogicalSwitch(UUID uuid) {
107         return (LogicalSwitch) getDeviceOperData(LogicalSwitches.class, uuid);
108     }
109
110     public Map<UUID, LogicalSwitch> getLogicalSwitches() {
111         Map<UUID, Object> switches = uuidVsData.get(LogicalSwitches.class);
112         Map<UUID, LogicalSwitch> result = new HashMap<>();
113         if (switches != null) {
114             for (Map.Entry<UUID, Object> entry : switches.entrySet()) {
115                 result.put(entry.getKey(), (LogicalSwitch) entry.getValue());
116             }
117         }
118         return result;
119     }
120
121     public void putPhysicalSwitch(UUID uuid, PhysicalSwitch pSwitch) {
122         physicalSwitches.put(uuid, pSwitch);
123     }
124
125     public PhysicalSwitch getPhysicalSwitch(UUID uuid) {
126         return physicalSwitches.get(uuid);
127     }
128
129     public PhysicalSwitch removePhysicalSwitch(UUID uuid) {
130         return physicalSwitches.remove(uuid);
131     }
132
133     public Map<UUID, PhysicalSwitch> getPhysicalSwitches() {
134         return physicalSwitches;
135     }
136
137     public PhysicalLocator getPhysicalLocator(UUID uuid) {
138         return (PhysicalLocator) getDeviceOperData(TerminationPoint.class, uuid);
139     }
140
141     public Map<UUID, PhysicalLocator> getPhysicalLocators() {
142         Map<UUID, Object> locators = uuidVsData.get(LogicalSwitches.class);
143         Map<UUID, PhysicalLocator> result = new HashMap<>();
144         if (locators != null) {
145             for (Map.Entry<UUID, Object> entry : locators.entrySet()) {
146                 result.put(entry.getKey(), (PhysicalLocator) entry.getValue());
147             }
148         }
149         return result;
150     }
151
152     public void putPhysicalSwitchForTunnel(UUID uuid, UUID psUUID) {
153         mapTunnelToPhysicalSwitch.put(uuid, psUUID);
154     }
155
156     public PhysicalSwitch getPhysicalSwitchForTunnel(UUID uuid) {
157         return physicalSwitches.get(mapTunnelToPhysicalSwitch.get(uuid));
158     }
159
160     public void removePhysicalSwitchForTunnel(UUID uuid) {
161         mapTunnelToPhysicalSwitch.remove(uuid);
162     }
163
164     public Map<UUID, UUID> getPhysicalSwitchesForTunnels() {
165         return mapTunnelToPhysicalSwitch;
166     }
167
168     public boolean isKeyInTransit(Class<? extends Identifiable> cls, InstanceIdentifier key) {
169         DeviceData deviceData = HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
170         return deviceData != null && DeviceDataStatus.IN_TRANSIT == deviceData.status;
171     }
172
173     public boolean isConfigDataAvailable(Class<? extends Identifiable> cls, InstanceIdentifier key) {
174         return HwvtepSouthboundUtil.getData(configKeyVsData, cls, key) != null;
175     }
176
177     public void updateConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key, Object data) {
178         HwvtepSouthboundUtil.updateData(configKeyVsData, cls, key,
179                 new DeviceData(key, null, data, DeviceDataStatus.AVAILABLE));
180     }
181
182     public Object getConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
183         return HwvtepSouthboundUtil.getData(configKeyVsData, cls, key);
184     }
185
186     public void clearConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
187         HwvtepSouthboundUtil.clearData(configKeyVsData, cls, key);
188     }
189
190     public void markKeyAsInTransit(Class<? extends Identifiable> cls, InstanceIdentifier key) {
191         LOG.debug("Marking device data as intransit {}", key);
192         DeviceData deviceData = getDeviceOperData(cls, key);
193         UUID uuid = null;
194         Object data = null;
195         if (deviceData != null) {
196             uuid = deviceData.getUuid();
197             data = deviceData.getData();
198         }
199         HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key,
200                 new DeviceData(key, uuid, data, DeviceDataStatus.IN_TRANSIT));
201     }
202
203     public void updateDeviceOperData(Class<? extends Identifiable> cls, InstanceIdentifier key, UUID uuid, Object data) {
204         LOG.debug("Updating device data {}", key);
205         HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key,
206                 new DeviceData(key, uuid, data, DeviceDataStatus.AVAILABLE));
207         HwvtepSouthboundUtil.updateData(uuidVsData, cls, uuid, data);
208     }
209
210     public void clearDeviceOperData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
211         DeviceData deviceData = HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
212         if (deviceData != null && deviceData.uuid != null) {
213             HwvtepSouthboundUtil.clearData(uuidVsData, cls, deviceData.uuid);
214         }
215         HwvtepSouthboundUtil.clearData(opKeyVsData, cls, key);
216     }
217
218     public Object getDeviceOperData(Class<? extends Identifiable> cls, UUID uuid) {
219         return HwvtepSouthboundUtil.getData(uuidVsData, cls, uuid);
220     }
221
222     public DeviceData getDeviceOperData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
223         return HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
224     }
225
226     public UUID getUUID(Class<? extends Identifiable> cls, InstanceIdentifier key) {
227         DeviceData data = HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
228         if (data != null) {
229             return data.uuid;
230         }
231         return null;
232     }
233
234     public <T extends Identifiable> void addJobToQueue(DependentJob<T> job) {
235         dependencyQueue.addToQueue(job);
236     }
237
238     public void onConfigDataAvailable() {
239         dependencyQueue.processReadyJobsFromConfigQueue(connectionInstance);
240     }
241
242     public void onOperDataAvailable() {
243         dependencyQueue.processReadyJobsFromOpQueue(connectionInstance);
244     }
245
246     public void scheduleTransaction(final TransactCommand transactCommand) {
247         dependencyQueue.submit(() -> connectionInstance.transact(transactCommand));
248     }
249
250     public void clearInTransitData() {
251         //TODO restore old data
252         for (Map<InstanceIdentifier, DeviceData> map : opKeyVsData.values()) {
253             Iterator<Map.Entry<InstanceIdentifier, DeviceData>> iterator = map.entrySet().iterator();
254             while ( iterator.hasNext() ) {
255                 Map.Entry<InstanceIdentifier, DeviceData> entry = iterator.next();
256                 if (entry.getValue().getStatus() == DeviceDataStatus.IN_TRANSIT) {
257                     iterator.remove();
258                 }
259             }
260         }
261         onOperDataAvailable();
262     }
263 }