e04aa1a8c6386dd6750530bb6d11a9968ef6f7bf
[groupbasedpolicy.git] / sxp-integration / sxp-ep-provider / src / main / java / org / opendaylight / groupbasedpolicy / sxp / ep / provider / impl / dao / SimpleCachedDaoEPForwardingTemplateImpl.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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.groupbasedpolicy.sxp.ep.provider.impl.dao;
10
11 import com.google.common.base.Optional;
12 import com.google.common.collect.Iterables;
13 import java.util.Map;
14 import java.util.concurrent.ConcurrentHashMap;
15 import java.util.concurrent.ConcurrentMap;
16 import java.util.regex.Pattern;
17 import javax.annotation.Nonnull;
18 import javax.annotation.Nullable;
19 import org.apache.commons.net.util.SubnetUtils;
20 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
21 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.EPTemplateUtil;
22 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.util.SubnetInfoKeyDecorator;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointForwardingTemplateBySubnet;
25
26 /**
27  * Purpose: generic implementation of {@link SimpleCachedDao}
28  */
29 public class SimpleCachedDaoEPForwardingTemplateImpl implements SimpleCachedDao<IpPrefix, EndpointForwardingTemplateBySubnet> {
30
31     private final ConcurrentMap<IpPrefix, EndpointForwardingTemplateBySubnet> plainCache;
32     private final ConcurrentMap<SubnetInfoKeyDecorator, EndpointForwardingTemplateBySubnet> subnetCache;
33     private final Pattern IP_MASK_EATER_RE = Pattern.compile("/[0-9]+");
34
35     public SimpleCachedDaoEPForwardingTemplateImpl() {
36         plainCache = new ConcurrentHashMap<>();
37         subnetCache = new ConcurrentHashMap<>();
38     }
39
40     @Override
41     public EndpointForwardingTemplateBySubnet update(@Nonnull final IpPrefix key, @Nullable final EndpointForwardingTemplateBySubnet value) {
42         final EndpointForwardingTemplateBySubnet previousValue;
43         if (EPTemplateUtil.isPlain(key)) {
44             previousValue = updatePlainCache(key, value);
45         } else {
46             previousValue = updateSubnetCache(key, value);
47         }
48
49         return previousValue;
50     }
51
52     private EndpointForwardingTemplateBySubnet updateSubnetCache(final IpPrefix key, final EndpointForwardingTemplateBySubnet value) {
53         final EndpointForwardingTemplateBySubnet previousValue;
54         final SubnetInfoKeyDecorator subnetKey = EPTemplateUtil.buildSubnetInfoKey(key);
55         if (value != null) {
56             previousValue = subnetCache.put(subnetKey, value);
57         } else {
58             previousValue = subnetCache.remove(subnetKey);
59         }
60         return previousValue;
61     }
62
63     private EndpointForwardingTemplateBySubnet updatePlainCache(final @Nonnull IpPrefix key, final @Nullable EndpointForwardingTemplateBySubnet value) {
64         final EndpointForwardingTemplateBySubnet previousValue;
65         if (value != null) {
66             previousValue = plainCache.put(key, value);
67         } else {
68             previousValue = plainCache.remove(key);
69         }
70         return previousValue;
71     }
72
73     @Override
74     public Optional<EndpointForwardingTemplateBySubnet> find(@Nonnull final IpPrefix key) {
75         final Optional<EndpointForwardingTemplateBySubnet> template;
76         if (EPTemplateUtil.isPlain(key)) {
77             final Optional<EndpointForwardingTemplateBySubnet> fastPlain = Optional.fromNullable(plainCache.get(key));
78             if (fastPlain.isPresent()) {
79                 template = fastPlain;
80             } else {
81                 template = lookupSlowSubnet(key.getIpv4Prefix().getValue());
82             }
83         } else {
84             final SubnetInfoKeyDecorator keyDecorator = EPTemplateUtil.buildSubnetInfoKey(key);
85             final Optional<EndpointForwardingTemplateBySubnet> fastSubnet =
86                     Optional.fromNullable(subnetCache.get(keyDecorator));
87             if (fastSubnet.isPresent()) {
88                 template = fastSubnet;
89             } else {
90                 template = Optional.absent();
91             }
92         }
93         return template;
94     }
95
96     private Optional<EndpointForwardingTemplateBySubnet> lookupSlowSubnet(final String value) {
97         final String plainIp = IP_MASK_EATER_RE.matcher(value).replaceFirst("");
98         EndpointForwardingTemplateBySubnet valueCandidate = null;
99         int addressCount = 0;
100         for (Map.Entry<SubnetInfoKeyDecorator, EndpointForwardingTemplateBySubnet> entry : subnetCache.entrySet()) {
101             final SubnetUtils.SubnetInfo subnetInfo = entry.getKey().getDelegate();
102             if (subnetInfo.isInRange(plainIp)) {
103                 final int addressCountTmp = subnetInfo.getAddressCount();
104                 if (valueCandidate == null || addressCount > addressCountTmp) {
105                     valueCandidate = entry.getValue();
106                     addressCount = addressCountTmp;
107                 }
108             }
109         }
110         return Optional.fromNullable(valueCandidate);
111     }
112
113     @Override
114     public void invalidateCache() {
115         plainCache.clear();
116         subnetCache.clear();
117     }
118
119     @Override
120     public boolean isEmpty() {
121         return plainCache.isEmpty() && subnetCache.isEmpty();
122     }
123
124     @Override
125     public Iterable<EndpointForwardingTemplateBySubnet> values() {
126         return Iterables.unmodifiableIterable(Iterables.concat(plainCache.values(), subnetCache.values()));
127     }
128 }