X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=mappingservice%2Finmemorydb%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Flispflowmapping%2Finmemorydb%2FHashMapDb.java;h=8048cf807a556019f4d492360122ce098d9fb9a7;hb=4a99f1d24037d5b7947658b7360a8c53baeedbf6;hp=1990dbd172727fc1dc1dde0acbac8ee9f9bf4552;hpb=ab93b0a494019299f423ca936132608d0ea71f3a;p=lispflowmapping.git diff --git a/mappingservice/inmemorydb/src/main/java/org/opendaylight/lispflowmapping/inmemorydb/HashMapDb.java b/mappingservice/inmemorydb/src/main/java/org/opendaylight/lispflowmapping/inmemorydb/HashMapDb.java index 1990dbd17..8048cf807 100644 --- a/mappingservice/inmemorydb/src/main/java/org/opendaylight/lispflowmapping/inmemorydb/HashMapDb.java +++ b/mappingservice/inmemorydb/src/main/java/org/opendaylight/lispflowmapping/inmemorydb/HashMapDb.java @@ -8,18 +8,17 @@ package org.opendaylight.lispflowmapping.inmemorydb; -import java.util.Date; -import java.util.Map; import java.util.AbstractMap.SimpleImmutableEntry; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; - import org.opendaylight.lispflowmapping.inmemorydb.radixtrie.RadixTrie; import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO; import org.opendaylight.lispflowmapping.interfaces.dao.IRowVisitor; import org.opendaylight.lispflowmapping.interfaces.dao.MappingEntry; -import org.opendaylight.lispflowmapping.interfaces.dao.SubKeys; import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil; import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv4PrefixBinary; import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.binary.address.types.rev160504.augmented.lisp.address.address.Ipv6PrefixBinary; @@ -31,25 +30,29 @@ public class HashMapDb implements ILispDAO, AutoCloseable { protected static final Logger LOG = LoggerFactory.getLogger(HashMapDb.class); private static final Object TABLES = (Object) "tables"; - private static final int DEFAULT_RECORD_TIMEOUT = 240; // SB registered mapping entries time out after 4 min - private ConcurrentMap> data = new ConcurrentHashMap>(); - private TimeUnit timeUnit = TimeUnit.SECONDS; - private int recordTimeOut = DEFAULT_RECORD_TIMEOUT; + private ConcurrentMap> data = new ConcurrentHashMap<>(); // IPv4 and IPv6 radix tries used for longest prefix matching - private RadixTrie ip4Trie = new RadixTrie(32, true); - private RadixTrie ip6Trie = new RadixTrie(128, true); + private RadixTrie ip4Trie = new RadixTrie<>(32, true); + private RadixTrie ip6Trie = new RadixTrie<>(128, true); + + private enum GetPrefixMethods { + PARENT, + SIBLING, + VIRTUAL_PARENT_SIBLING, + WIDEST_NEGATIVE, + COVERING + } public void tryAddToIpTrie(Object key) { if (key instanceof Eid) { Eid eid = (Eid) key; if (eid.getAddress() instanceof Ipv4PrefixBinary) { Ipv4PrefixBinary prefix = (Ipv4PrefixBinary) eid.getAddress(); - ip4Trie.insert(prefix.getIpv4AddressBinary().getValue(), prefix.getIpv4MaskLength(), key); + ip4Trie.insert(prefix.getIpv4AddressBinary().getValue(), prefix.getIpv4MaskLength().toJava(), key); } else if (eid.getAddress() instanceof Ipv6PrefixBinary) { Ipv6PrefixBinary prefix = (Ipv6PrefixBinary) eid.getAddress(); - ip6Trie.insert(prefix.getIpv6AddressBinary().getValue(), prefix.getIpv6MaskLength(), key); + ip6Trie.insert(prefix.getIpv6AddressBinary().getValue(), prefix.getIpv6MaskLength().toJava(), key); } } } @@ -79,19 +82,22 @@ public class HashMapDb implements ILispDAO, AutoCloseable { return data.get(key); } + private RadixTrie.TrieNode lookupBestNode(Eid eid) { + if (eid.getAddress() instanceof Ipv4PrefixBinary) { + Ipv4PrefixBinary prefix = (Ipv4PrefixBinary) eid.getAddress(); + return ip4Trie.lookupBest(prefix.getIpv4AddressBinary().getValue(), prefix.getIpv4MaskLength().toJava()); + } else if (eid.getAddress() instanceof Ipv6PrefixBinary) { + Ipv6PrefixBinary prefix = (Ipv6PrefixBinary) eid.getAddress(); + return ip6Trie.lookupBest(prefix.getIpv6AddressBinary().getValue(), prefix.getIpv6MaskLength().toJava()); + } + return null; + } + @Override public Map getBest(Object key) { if (key instanceof Eid) { Eid eid = (Eid) key; - RadixTrie.TrieNode node = null; - - if (eid.getAddress() instanceof Ipv4PrefixBinary) { - Ipv4PrefixBinary prefix = (Ipv4PrefixBinary) eid.getAddress(); - node = ip4Trie.lookupBest(prefix.getIpv4AddressBinary().getValue(), prefix.getIpv4MaskLength()); - } else if (eid.getAddress() instanceof Ipv6PrefixBinary) { - Ipv6PrefixBinary prefix = (Ipv6PrefixBinary) eid.getAddress(); - node = ip6Trie.lookupBest(prefix.getIpv6AddressBinary().getValue(), prefix.getIpv6MaskLength()); - } + RadixTrie.TrieNode node = lookupBestNode(eid); if (node == null) { return get(key); } @@ -102,25 +108,17 @@ public class HashMapDb implements ILispDAO, AutoCloseable { @Override public SimpleImmutableEntry> getBestPair(Object key) { - Map data = null; + Map result = null; if (key instanceof Eid) { Eid eid = (Eid) key; - RadixTrie.TrieNode node = null; - - if (eid.getAddress() instanceof Ipv4PrefixBinary) { - Ipv4PrefixBinary prefix = (Ipv4PrefixBinary) eid.getAddress(); - node = ip4Trie.lookupBest(prefix.getIpv4AddressBinary().getValue(), prefix.getIpv4MaskLength()); - } else if (eid.getAddress() instanceof Ipv6PrefixBinary) { - Ipv6PrefixBinary prefix = (Ipv6PrefixBinary) eid.getAddress(); - node = ip6Trie.lookupBest(prefix.getIpv6AddressBinary().getValue(), prefix.getIpv6MaskLength()); - } + RadixTrie.TrieNode node = lookupBestNode(eid); if (node == null) { - data = get(key); - return (data == null) ? null : new SimpleImmutableEntry>((Eid)key, data); + result = get(key); + return (result == null) ? null : new SimpleImmutableEntry<>((Eid)key, result); } - data = get(node.data()); - return (data == null) ? null : new SimpleImmutableEntry>((Eid)node.data(), data); + result = get(node.data()); + return (result == null) ? null : new SimpleImmutableEntry<>((Eid)node.data(), result); } return null; } @@ -133,35 +131,143 @@ public class HashMapDb implements ILispDAO, AutoCloseable { } } } - @Override - public Eid getWidestNegativePrefix(Eid key) { + + private Eid getPrefix(Eid key, GetPrefixMethods method) { RadixTrie.TrieNode node = null; if (key.getAddress() instanceof Ipv4PrefixBinary) { Ipv4PrefixBinary prefix = (Ipv4PrefixBinary) key.getAddress(); - node = ip4Trie.lookupWidestNegative(prefix.getIpv4AddressBinary().getValue(), prefix.getIpv4MaskLength()); - if (node != null) { - return LispAddressUtil.asIpv4PrefixBinaryEid(key, node.prefix(), (short) node.prefixLength()); + switch (method) { + case COVERING: + node = ip4Trie.lookupCoveringLessSpecific(prefix.getIpv4AddressBinary().getValue(), + prefix.getIpv4MaskLength().toJava()); + break; + case PARENT: + node = ip4Trie.lookupParent(prefix.getIpv4AddressBinary().getValue(), + prefix.getIpv4MaskLength().toJava()); + break; + case SIBLING: + node = ip4Trie.lookupSibling(prefix.getIpv4AddressBinary().getValue(), + prefix.getIpv4MaskLength().toJava()); + break; + case VIRTUAL_PARENT_SIBLING: + node = ip4Trie.lookupVirtualParentSibling(prefix.getIpv4AddressBinary().getValue(), + prefix.getIpv4MaskLength().toJava()); + break; + case WIDEST_NEGATIVE: + node = ip4Trie.lookupWidestNegative(prefix.getIpv4AddressBinary().getValue(), + prefix.getIpv4MaskLength().toJava()); + break; + default: + node = null; + break; + } + if (node != null && node.prefix() != null) { + return LispAddressUtil.asIpv4PrefixBinaryEid( + key.getVirtualNetworkId(), node.prefix(), (short) node.prefixLength()); } } else if (key.getAddress() instanceof Ipv6PrefixBinary) { Ipv6PrefixBinary prefix = (Ipv6PrefixBinary) key.getAddress(); - node = ip6Trie.lookupWidestNegative(prefix.getIpv6AddressBinary().getValue(), prefix.getIpv6MaskLength()); - if (node != null) { - return LispAddressUtil.asIpv6PrefixBinaryEid(key, node.prefix(), (short) node.prefixLength()); + switch (method) { + case COVERING: + node = ip6Trie.lookupCoveringLessSpecific(prefix.getIpv6AddressBinary().getValue(), + prefix.getIpv6MaskLength().toJava()); + break; + case PARENT: + node = ip6Trie.lookupParent(prefix.getIpv6AddressBinary().getValue(), + prefix.getIpv6MaskLength().toJava()); + break; + case SIBLING: + node = ip6Trie.lookupSibling(prefix.getIpv6AddressBinary().getValue(), + prefix.getIpv6MaskLength().toJava()); + break; + case VIRTUAL_PARENT_SIBLING: + node = ip6Trie.lookupVirtualParentSibling(prefix.getIpv6AddressBinary().getValue(), + prefix.getIpv6MaskLength().toJava()); + break; + case WIDEST_NEGATIVE: + node = ip6Trie.lookupWidestNegative(prefix.getIpv6AddressBinary().getValue(), + prefix.getIpv6MaskLength().toJava()); + break; + default: + node = null; + break; + } + if (node != null && node.prefix() != null) { + return LispAddressUtil.asIpv6PrefixBinaryEid( + key.getVirtualNetworkId(), node.prefix(), (short) node.prefixLength()); } } return null; } + @Override + public Eid getCoveringLessSpecific(Eid key) { + return getPrefix(key, GetPrefixMethods.COVERING); + } + + @Override + public Eid getParentPrefix(Eid key) { + return getPrefix(key, GetPrefixMethods.PARENT); + } + + @Override + public Eid getSiblingPrefix(Eid key) { + return getPrefix(key, GetPrefixMethods.SIBLING); + } + + @Override + public Eid getVirtualParentSiblingPrefix(Eid key) { + return getPrefix(key, GetPrefixMethods.VIRTUAL_PARENT_SIBLING); + } + + @Override + public Eid getWidestNegativePrefix(Eid key) { + return getPrefix(key, GetPrefixMethods.WIDEST_NEGATIVE); + } + + @Override + public Set getSubtree(Eid key) { + Set.TrieNode> nodes = null; + if (key.getAddress() instanceof Ipv4PrefixBinary) { + Ipv4PrefixBinary prefix = (Ipv4PrefixBinary) key.getAddress(); + nodes = ip4Trie.lookupSubtree(prefix.getIpv4AddressBinary().getValue(), + prefix.getIpv4MaskLength().toJava()); + } else if (key.getAddress() instanceof Ipv6PrefixBinary) { + Ipv6PrefixBinary prefix = (Ipv6PrefixBinary) key.getAddress(); + nodes = ip6Trie.lookupSubtree(prefix.getIpv6AddressBinary().getValue(), + prefix.getIpv6MaskLength().toJava()); + } + return nodesToEids(key, nodes); + } + + private static Set nodesToEids(Eid key, Set.TrieNode> nodes) { + if (nodes == null || nodes.isEmpty()) { + return Collections.emptySet(); + } + + Set children = new HashSet<>(); + for (RadixTrie.TrieNode node : nodes) { + if (key.getAddress() instanceof Ipv4PrefixBinary) { + children.add(LispAddressUtil.asIpv4PrefixBinaryEid( + key.getVirtualNetworkId(), node.prefix(), (short) node.prefixLength())); + } else if (key.getAddress() instanceof Ipv6PrefixBinary) { + children.add(LispAddressUtil.asIpv6PrefixBinaryEid( + key.getVirtualNetworkId(), node.prefix(), (short) node.prefixLength())); + } + } + return children; + } + private void tryRemoveFromTrie(Object key) { if (key instanceof Eid) { Eid eid = (Eid) key; if (eid.getAddress() instanceof Ipv4PrefixBinary) { Ipv4PrefixBinary prefix = (Ipv4PrefixBinary) eid.getAddress(); - ip4Trie.remove(prefix.getIpv4AddressBinary().getValue(), prefix.getIpv4MaskLength()); + ip4Trie.remove(prefix.getIpv4AddressBinary().getValue(), prefix.getIpv4MaskLength().toJava()); } else if (eid.getAddress() instanceof Ipv6PrefixBinary) { Ipv6PrefixBinary prefix = (Ipv6PrefixBinary) eid.getAddress(); - ip6Trie.remove(prefix.getIpv6AddressBinary().getValue(), prefix.getIpv6MaskLength()); + ip6Trie.remove(prefix.getIpv6AddressBinary().getValue(), prefix.getIpv6MaskLength().toJava()); } } } @@ -174,8 +280,18 @@ public class HashMapDb implements ILispDAO, AutoCloseable { @Override public void removeSpecific(Object key, String valueKey) { - if (data.containsKey(key) && data.get(key).containsKey(valueKey)) { - data.get(key).remove(valueKey); + Map keyToValues = data.get(key); + if (keyToValues == null) { + return; + } + + synchronized (keyToValues) { + if (keyToValues.containsKey(valueKey)) { + keyToValues.remove(valueKey); + if (keyToValues.isEmpty()) { + remove(key); + } + } } } @@ -186,41 +302,6 @@ public class HashMapDb implements ILispDAO, AutoCloseable { data.clear(); } - // TODO: this should be moved outside of DAO implementation - public void cleanOld() { - getAll(new IRowVisitor() { - public void visitRow(Object keyId, String valueKey, Object value) { - if (value != null && valueKey instanceof String && ((String) valueKey).equals(SubKeys.REGDATE)) { - Date date = (Date) value; - if (isExpired(date)) { - removeSpecific(keyId, SubKeys.RECORD); - } - } - } - - private boolean isExpired(Date date) { - return System.currentTimeMillis() - date.getTime() - > TimeUnit.MILLISECONDS.convert(recordTimeOut, timeUnit); - } - }); - } - - public TimeUnit getTimeUnit() { - return timeUnit; - } - - public void setRecordTimeOut(int recordTimeOut) { - this.recordTimeOut = recordTimeOut; - } - - public int getRecordTimeOut() { - return recordTimeOut; - } - - public void setTimeUnit(TimeUnit timeUnit) { - this.timeUnit = timeUnit; - } - public void close() throws Exception { data.clear(); } @@ -248,4 +329,9 @@ public class HashMapDb implements ILispDAO, AutoCloseable { put(TABLES, new MappingEntry<>(key, table)); return table; } + + @Override + public boolean isEmpty() { + return data.isEmpty(); + } }