3693e167da3ca1c73e61e42008580fee10c8ad0b
[ovsdb.git] / plugin / src / main / java / org / opendaylight / ovsdb / plugin / impl / InventoryServiceImpl.java
1 /*
2  * Copyright (C) 2013 Red Hat, Inc.
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  * Authors : Madhu Venugopal, Brent Salisbury
9  */
10 package org.opendaylight.ovsdb.plugin.impl;
11
12 import java.net.InetAddress;
13 import java.util.HashMap;
14 import java.util.Map;
15 import java.util.Set;
16 import java.util.concurrent.ConcurrentHashMap;
17 import java.util.concurrent.ConcurrentMap;
18 import java.util.concurrent.ExecutionException;
19 import java.util.concurrent.Executors;
20 import java.util.concurrent.ScheduledExecutorService;
21
22 import org.opendaylight.controller.sal.core.Node;
23 import org.opendaylight.controller.sal.core.NodeConnector;
24 import org.opendaylight.controller.sal.core.Property;
25 import org.opendaylight.controller.sal.core.UpdateType;
26 import org.opendaylight.ovsdb.lib.message.TableUpdate;
27 import org.opendaylight.ovsdb.lib.message.TableUpdates;
28 import org.opendaylight.ovsdb.lib.notation.Row;
29 import org.opendaylight.ovsdb.lib.notation.UUID;
30 import org.opendaylight.ovsdb.plugin.internal.NodeDatabase;
31 import org.opendaylight.ovsdb.plugin.api.OvsVswitchdSchemaConstants;
32 import org.opendaylight.ovsdb.plugin.api.OvsdbConfigurationService;
33 import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryListener;
34 import org.opendaylight.ovsdb.plugin.api.OvsdbInventoryService;
35
36 import com.google.common.collect.Sets;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import com.google.common.collect.Maps;
41
42 /**
43  * Stub Implementation for IPluginInReadService used by SAL
44  *
45  *
46  */
47 public class InventoryServiceImpl implements OvsdbInventoryService {
48     private static final Logger logger = LoggerFactory
49             .getLogger(InventoryServiceImpl.class);
50     private ConcurrentMap<Node, Map<String, Property>> nodeProps = new ConcurrentHashMap<Node, Map<String, Property>>();
51     private ConcurrentMap<Node, NodeDatabase> dbCache = Maps.newConcurrentMap();
52     private ScheduledExecutorService executor;
53     private OvsdbConfigurationService ovsdbConfigurationService;
54
55     private Set<OvsdbInventoryListener> ovsdbInventoryListeners = Sets.newCopyOnWriteArraySet();
56
57     /**
58      * Function called by the dependency manager when all the required
59      * dependencies are satisfied
60      *
61      */
62     public void init() {
63         this.executor = Executors.newSingleThreadScheduledExecutor();
64     }
65
66     /**
67      * Function called by the dependency manager when at least one dependency
68      * become unsatisfied or when the component is shutting down because for
69      * example bundle is being stopped.
70      *
71      */
72     public void destroy() {
73     }
74
75     /**
76      * Function called by dependency manager after "init ()" is called and after
77      * the services provided by the class are registered in the service registry
78      *
79      */
80     public void start() {
81     }
82
83     /**
84      * Function called by the dependency manager before the services exported by
85      * the component are unregistered, this will be followed by a "destroy ()"
86      * calls
87      *
88      */
89     public void stop() {
90         this.executor.shutdownNow();
91     }
92
93     public void setOvsdbConfigurationService(OvsdbConfigurationService service) {
94         ovsdbConfigurationService = service;
95     }
96
97     public void unsetConfigurationService(OvsdbConfigurationService service) {
98         ovsdbConfigurationService = null;
99     }
100
101     @Override
102     public ConcurrentMap<String, ConcurrentMap<String, Row>> getCache(Node n, String databaseName) {
103         NodeDatabase db = dbCache.get(n);
104         if (db == null) return null;
105         return db.getDatabase(databaseName);
106     }
107
108
109     @Override
110     public ConcurrentMap<String, Row> getTableCache(Node n, String databaseName, String tableName) {
111         NodeDatabase db = dbCache.get(n);
112         if (db == null) return null;
113         return db.getTableCache(databaseName, tableName);
114     }
115
116
117     @Override
118     public Row getRow(Node n, String databaseName, String tableName, String uuid) {
119         NodeDatabase db = dbCache.get(n);
120         if (db == null) return null;
121         return db.getRow(databaseName, tableName, uuid);
122     }
123
124     @Override
125     public void updateRow(Node n, String databaseName, String tableName, String uuid, Row row) {
126         NodeDatabase db = dbCache.get(n);
127         if (db == null) {
128             db = new NodeDatabase();
129             dbCache.put(n, db);
130         }
131         db.updateRow(databaseName, tableName, uuid, row);
132     }
133
134     @Override
135     public void removeRow(Node n, String databaseName, String tableName, String uuid) {
136         NodeDatabase db = dbCache.get(n);
137         if (db != null) db.removeRow(databaseName, tableName, uuid);
138     }
139
140     @Override
141     public void processTableUpdates(Node n, String databaseName, TableUpdates tableUpdates) {
142         NodeDatabase db = dbCache.get(n);
143         if (db == null) {
144             db = new NodeDatabase();
145             dbCache.put(n, db);
146         }
147
148         for (String tableName : tableUpdates.getUpdates().keySet()) {
149             Map<String, Row> tCache = db.getTableCache(databaseName, tableName);
150             TableUpdate update = tableUpdates.getUpdates().get(tableName);
151             for (UUID uuid : (Set<UUID>)update.getRows().keySet()) {
152
153             if (update.getNew(uuid) != null) {
154                 boolean isNewRow = (tCache == null || tCache.get(uuid.toString()) == null) ? true : false;
155                 db.updateRow(databaseName, tableName, uuid.toString(), update.getNew(uuid));
156                 if (isNewRow) {
157                     this.handleOpenVSwitchSpecialCase(n, databaseName, tableName, uuid);
158                     if (!ovsdbInventoryListeners.isEmpty()) {
159                         for (OvsdbInventoryListener listener : ovsdbInventoryListeners) {
160                             listener.rowAdded(n, tableName, uuid.toString(), update.getNew(uuid));
161                         }
162                     }
163                 } else {
164                     if (!ovsdbInventoryListeners.isEmpty()) {
165                         for (OvsdbInventoryListener listener : ovsdbInventoryListeners) {
166                             listener.rowUpdated(n, tableName, uuid.toString(), update.getOld(uuid), update.getNew(uuid));
167                         }
168                     }
169                 }
170             } else if (update.getOld(uuid) != null){
171                 if (tCache != null) {
172                     if (!ovsdbInventoryListeners.isEmpty()) {
173                         for (OvsdbInventoryListener listener : ovsdbInventoryListeners) {
174                             listener.rowRemoved(n, tableName, uuid.toString(), update.getOld(uuid), update.getNew(uuid));
175                         }
176                     }
177                 }
178                 db.removeRow(databaseName, tableName, uuid.toString());
179             }
180             }
181         }
182     }
183
184     private void handleOpenVSwitchSpecialCase(final Node node, final String databaseName, final String tableName, final UUID uuid) {
185         if (OvsVswitchdSchemaConstants.shouldConfigureController(databaseName, tableName)) {
186             Runnable updateControllerRunnable = new Runnable() {
187                 @Override
188                 public void run() {
189                     try {
190                         if (ovsdbConfigurationService != null) ovsdbConfigurationService.setOFController(node, uuid.toString());
191                     } catch (InterruptedException | ExecutionException e) {
192                         e.printStackTrace();
193                     }
194                 }
195             };
196             executor.execute(updateControllerRunnable);
197         }
198     }
199
200     @Override
201     public void printCache(Node n) {
202         if ((dbCache != null) && (!dbCache.isEmpty())) {
203             NodeDatabase db = dbCache.get(n);
204             if (db != null) {
205                 db.printTableCache();
206             }
207         }
208     }
209
210     @Override
211     public void addNode(Node node, Set<Property> props) {
212         addNodeProperty(node, UpdateType.ADDED, props);
213     }
214
215     @Override
216     public void notifyNodeAdded(Node node, InetAddress address, int port) {
217         if (!ovsdbInventoryListeners.isEmpty()) {
218             for (OvsdbInventoryListener listener : ovsdbInventoryListeners) {
219                 listener.nodeAdded(node, address, port);
220             }
221         }
222     }
223
224     @Override
225     public void addNodeProperty(Node node, UpdateType type, Set<Property> props) {
226         Map<String, Property> nProp = nodeProps.get(node);
227         if (nProp == null) nProp = new HashMap<String, Property>();
228         for (Property prop : props) {
229             nProp.put(prop.getName(), prop);
230         }
231         nodeProps.put(node, nProp);
232         /*
233          * TODO: Remove following code. It updates to sal about newly added node and
234          * it's property. To move this bundle to MD-SAL we need to store this data in
235          * md-sal config/operational data store.
236         for (IPluginOutInventoryService service : pluginOutInventoryServices) {
237             service.updateNode(node, type, props);
238         }
239         */
240     }
241
242     @Override
243     public void removeNode(Node node) {
244         if (!ovsdbInventoryListeners.isEmpty()) {
245             for (OvsdbInventoryListener listener : ovsdbInventoryListeners) {
246                 listener.nodeRemoved(node);
247             }
248         }
249
250         /*
251          * TODO: Remove following code. It updates to sal about newly added node and
252          * it's property. To move this bundle to MD-SAL we need to store this data in
253          * md-sal config/operational data store.
254          for (IPluginOutInventoryService service : pluginOutInventoryServices) {
255             service.updateNode(node, UpdateType.REMOVED, null);
256         }
257         */
258         nodeProps.remove(node);
259         dbCache.remove(node);
260     }
261
262     private void listenerAdded(OvsdbInventoryListener listener) {
263         this.ovsdbInventoryListeners.add(listener);
264     }
265
266     private void listenerRemoved(OvsdbInventoryListener listener) {
267         this.ovsdbInventoryListeners.remove(listener);
268     }
269 }