Adding l2gw related cache changes
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / internal / ElanGroupCache.java
1 /*
2  * Copyright (c) 2019 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.netvirt.elan.internal;
10
11 import com.google.common.base.Optional;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.Map;
15 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.concurrent.TimeUnit;
17
18 import javax.inject.Inject;
19 import javax.inject.Singleton;
20
21 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
22 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
25 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
26 import org.opendaylight.netvirt.elan.utils.Scheduler;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
31 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 @Singleton
36 public class ElanGroupCache extends AsyncClusteredDataTreeChangeListenerBase<Group, ElanGroupCache> {
37     private static final Logger LOG = LoggerFactory.getLogger(ElanGroupCache.class);
38     private final DataBroker dataBroker;
39     private final Scheduler scheduler;
40     private final Map<InstanceIdentifier<Group>, Group> groupsById = new ConcurrentHashMap<>();
41     private final Map<InstanceIdentifier<Group>, Collection<Runnable>> waitingJobs = new ConcurrentHashMap<>();
42     private volatile boolean initialized = false;
43
44     @Inject
45     public ElanGroupCache(final DataBroker dataBroker, final Scheduler scheduler) {
46         super(Group.class, ElanGroupCache.class);
47         this.dataBroker = dataBroker;
48         this.scheduler = scheduler;
49     }
50
51     public synchronized void init() {
52         if (!initialized) {
53             initialized = true;
54             this.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
55         }
56     }
57
58     @Override
59     protected InstanceIdentifier<Group> getWildCardPath() {
60         return InstanceIdentifier.builder(Nodes.class)
61                 .child(Node.class).augmentation(FlowCapableNode.class)
62                 .child(Group.class).build();
63     }
64
65     public synchronized void addJobToWaitList(InstanceIdentifier<Group> key,
66                                               Runnable job) {
67         if (groupsById.containsKey(key)) {
68             job.run();
69         } else {
70             waitingJobs.putIfAbsent(key, new ArrayList<>());
71             waitingJobs.get(key).add(job);
72         }
73     }
74
75     @Override
76     protected ElanGroupCache getDataTreeChangeListener() {
77         return ElanGroupCache.this;
78     }
79
80     @Override
81     protected synchronized void remove(InstanceIdentifier<Group> key, Group deleted) {
82         groupsById.remove(key);
83     }
84
85     @Override
86     protected void update(InstanceIdentifier<Group> key, Group old, Group updated) {
87         add(key, updated);
88     }
89
90     @Override
91     protected synchronized void add(InstanceIdentifier<Group> key, Group added) {
92         if (groupsById.containsKey(key)) {
93             groupsById.put(key, added);
94             return;
95         }
96         scheduler.getScheduledExecutorService().schedule(() -> {
97             groupsById.put(key, added);
98             Collection<Runnable> jobs = waitingJobs.remove(key);
99             if (jobs == null) {
100                 return;
101             }
102             for (Runnable job : jobs) {
103                 job.run();
104             }
105         }, ElanInterfaceManager.WAIT_TIME_FOR_SYNC_INSTALL, TimeUnit.MILLISECONDS);
106     }
107
108     public Optional<Group> getGroup(InstanceIdentifier<Group> key) throws ReadFailedException {
109         if (groupsById.containsKey(key)) {
110             return Optional.of(groupsById.get(key));
111         }
112         ReadOnlyTransaction transaction = dataBroker.newReadOnlyTransaction();
113         Optional<Group> optional = transaction.read(LogicalDatastoreType.CONFIGURATION, key).checkedGet();
114         transaction.close();
115         return optional;
116     }
117 }