Magnesium platform upgrade
[lispflowmapping.git] / mappingservice / mapcache / src / main / java / org / opendaylight / lispflowmapping / mapcache / SimpleMapCache.java
index e8226fa4cbcfd2ad637a8206867459a70bbd492f..7823d7fa3aecb62befb2ec1b0f91603544b6ea08 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2015, 2017 Cisco Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -10,8 +10,8 @@ package org.opendaylight.lispflowmapping.mapcache;
 
 import java.util.AbstractMap.SimpleImmutableEntry;
 import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashSet;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -19,16 +19,12 @@ 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.interfaces.mapcache.IMapCache;
+import org.opendaylight.lispflowmapping.interfaces.mapcache.ILispMapCache;
 import org.opendaylight.lispflowmapping.lisp.util.MaskUtil;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.lisp.address.types.rev151105.lisp.address.address.SourceDestKey;
+import org.opendaylight.lispflowmapping.mapcache.lisp.LispMapCacheStringifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.IpAddressBinary;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.authkey.container.MappingAuthkey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Simple map-cache that works with 'simple' addresses (see lisp-proto.yang). It can do longest prefix matching for IP
@@ -38,31 +34,31 @@ import org.slf4j.LoggerFactory;
  * @author Lorand Jakab
  *
  */
-public class SimpleMapCache implements IMapCache {
-    private static final Logger LOG = LoggerFactory.getLogger(SimpleMapCache.class);
+public class SimpleMapCache implements ILispMapCache {
     private ILispDAO dao;
 
     public SimpleMapCache(ILispDAO dao) {
         this.dao = dao;
     }
 
-    private ILispDAO getVniTable(Eid eid) {
-        long vni = 0;
+    private long getVni(Eid eid) {
         if (eid.getVirtualNetworkId() == null) {
-            vni = 0;
+            return 0;
         } else {
-            vni = eid.getVirtualNetworkId().getValue();
+            return eid.getVirtualNetworkId().getValue().toJava();
         }
-        return (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
+    }
+
+    private ILispDAO getVniTable(Eid eid) {
+        return (ILispDAO) dao.getSpecific(getVni(eid), SubKeys.VNI);
+    }
+
+    private void removeVniTable(Eid eid) {
+        dao.removeSpecific(getVni(eid), SubKeys.VNI);
     }
 
     private ILispDAO getOrInstantiateVniTable(Eid eid) {
-        long vni = 0;
-        if (eid.getVirtualNetworkId() == null) {
-            vni = 0;
-        } else {
-            vni = eid.getVirtualNetworkId().getValue();
-        }
+        long vni = getVni(eid);
         ILispDAO table = (ILispDAO) dao.getSpecific(vni, SubKeys.VNI);
         if (table == null) {
             table = dao.putNestedTable(vni, SubKeys.VNI);
@@ -70,140 +66,97 @@ public class SimpleMapCache implements IMapCache {
         return table;
     }
 
-    private ILispDAO getXtrIdTable(Eid eid, ILispDAO dao) {
-        return (ILispDAO) dao.getSpecific(eid, SubKeys.XTRID_RECORDS);
-    }
-
-    private ILispDAO getOrInstantiateXtrIdTable(Eid eid, ILispDAO dao) {
-        ILispDAO table = (ILispDAO) dao.getSpecific(eid, SubKeys.XTRID_RECORDS);
+    private ILispDAO getOrInstantiateXtrIdTable(Eid eid, ILispDAO lispDAO) {
+        ILispDAO table = (ILispDAO) lispDAO.getSpecific(eid, SubKeys.XTRID_RECORDS);
         if (table == null) {
-            table = dao.putNestedTable(eid, SubKeys.XTRID_RECORDS);
+            table = lispDAO.putNestedTable(eid, SubKeys.XTRID_RECORDS);
         }
         return table;
     }
 
-    private void removeExpiredXtrIdTableEntries(ILispDAO xtrIdDao, List<XtrId> expiredMappings) {
-        for (XtrId xtrId : expiredMappings) {
-            xtrIdDao.removeSpecific(xtrId, SubKeys.EXT_RECORD);
-        }
+    @Override
+    public void addMapping(Eid key, Object value) {
+        addMapping(key, value, null);
     }
 
-    public void addMapping(Eid key, Object value, boolean shouldOverwrite, boolean shouldMerge) {
-        if (value == null) {
-            LOG.warn("addMapping() called with null 'value', ignoring");
-            return;
-        }
-
-        if (!(value instanceof MappingRecord)) {
-            LOG.warn("addMapping() called with a 'value' that is not a 'MappingRecord', ignoring");
-            return;
-        }
-
-        MappingRecord record = (MappingRecord) value;
-        if (record.getXtrId() == null && !shouldOverwrite && shouldMerge) {
-            LOG.warn("addMapping() called will null xTR-ID in MappingRecord, while merge is set, ignoring");
-            return;
-        }
-
-        Date regdate = new Date(System.currentTimeMillis());
+    @Override
+    public void addMapping(Eid key, Object value, Set<IpAddressBinary> sourceRlocs) {
         Eid eid = MaskUtil.normalize(key);
         ILispDAO table = getOrInstantiateVniTable(key);
-
-        ILispDAO xtrIdDao = null;
-        if (!shouldOverwrite && record.getXtrId() != null) {
-            xtrIdDao = getOrInstantiateXtrIdTable(eid, table);
-            xtrIdDao.put(record.getXtrId(), new MappingEntry<>(SubKeys.EXT_RECORD,
-                    new ExtendedMappingRecord(record, regdate)));
-        }
-
-        if (shouldMerge) {
-            List<XtrId> expiredMappings = new ArrayList<>();
-            Set<IpAddressBinary> sourceRlocs = new HashSet<>();
-            ExtendedMappingRecord mergedEntry = MappingMergeUtil.mergeXtrIdMappings(getXtrIdMappingList(xtrIdDao),
-                    expiredMappings, sourceRlocs);
-            removeExpiredXtrIdTableEntries(xtrIdDao, expiredMappings);
-            if (mergedEntry == null) {
-                return;
-            }
-            regdate = mergedEntry.getTimestamp();
-            table.put(eid, new MappingEntry<>(SubKeys.REGDATE, regdate));
-            table.put(eid, new MappingEntry<>(SubKeys.RECORD, mergedEntry.getRecord()));
+        table.put(eid, new MappingEntry<>(SubKeys.RECORD, value));
+        if (sourceRlocs != null) {
             table.put(eid, new MappingEntry<>(SubKeys.SRC_RLOCS, sourceRlocs));
-        } else {
-            table.put(eid, new MappingEntry<>(SubKeys.REGDATE, regdate));
-            table.put(eid, new MappingEntry<>(SubKeys.RECORD, value));
         }
     }
 
-    // Returns the list of mappings stored in an xTR-ID DAO
-    private List<Object> getXtrIdMappingList(ILispDAO dao) {
-        if (dao != null) {
-            final List<Object> records = new ArrayList<>();
-            dao.getAll(new IRowVisitor() {
-                public void visitRow(Object keyId, String valueKey, Object value) {
-                    if (valueKey.equals(SubKeys.EXT_RECORD)) {
-                        records.add(value);
-                    }
-                }
-            });
-            return records;
-        }
-        return null;
+    @Override
+    public void addMapping(Eid key, XtrId xtrId, Object value) {
+        Eid eid = MaskUtil.normalize(key);
+        ILispDAO table = getOrInstantiateVniTable(key);
+        ILispDAO xtrIdDao = getOrInstantiateXtrIdTable(eid, table);
+        xtrIdDao.put(xtrId, new MappingEntry<>(SubKeys.RECORD, value));
     }
 
     // Returns the mapping corresponding to the longest prefix match for eid. eid must be a simple (maskable or not)
     // address
-    private Object getMappingLpmEid(Eid eid, byte[] xtrId, ILispDAO dao) {
-        SimpleImmutableEntry<Eid, Map<String, ?>> daoEntry = dao.getBestPair(MaskUtil.normalize(eid));
+    private Object getMappingLpmEid(Eid eid, XtrId xtrId, ILispDAO lispDAO) {
+        SimpleImmutableEntry<Eid, Map<String, ?>> daoEntry = lispDAO.getBestPair(MaskUtil.normalize(eid));
         if (daoEntry != null) {
             if (xtrId != null) {
-                ILispDAO xtrIdTable = getXtrIdTable(eid, (ILispDAO) daoEntry.getValue().get(SubKeys.XTRID_RECORDS));
+                ILispDAO xtrIdTable = (ILispDAO) daoEntry.getValue().get(SubKeys.XTRID_RECORDS);
                 if (xtrIdTable != null) {
-                    ExtendedMappingRecord xtrIdRecord = (ExtendedMappingRecord) xtrIdTable.getSpecific(xtrId,
-                            SubKeys.EXT_RECORD);
-                    if (xtrIdRecord.getTimestamp() != null
-                            && MappingMergeUtil.timestampIsExpired(xtrIdRecord.getTimestamp())) {
-                        xtrIdTable.removeSpecific(xtrId, SubKeys.EXT_RECORD);
-                        return null;
-                    } else {
-                        return xtrIdRecord.getRecord();
-                    }
-                } else {
-                    return null;
+                    return xtrIdTable.getSpecific(xtrId, SubKeys.RECORD);
                 }
             } else {
-                Date timestamp = (Date) daoEntry.getValue().get(SubKeys.REGDATE);
-                if (timestamp != null && MappingMergeUtil.timestampIsExpired(timestamp)) {
-                    dao.removeSpecific(daoEntry.getKey(), SubKeys.REGDATE);
-                    dao.removeSpecific(daoEntry.getKey(), SubKeys.RECORD);
-                }
                 return daoEntry.getValue().get(SubKeys.RECORD);
             }
-        } else {
-            return null;
         }
+        return null;
+    }
+
+    @Override
+    public Object getMapping(Eid srcEid, Eid dstEid) {
+        return getMapping(dstEid, (XtrId) null);
     }
 
-    public Object getMapping(Eid srcEid, Eid dstEid, byte[] xtrId) {
-        if (dstEid == null) {
+    @Override
+    public Object getMapping(Eid eid, XtrId xtrId) {
+        if (eid == null) {
             return null;
         }
 
-        ILispDAO table = getVniTable(dstEid);
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
             return null;
         }
-        return getMappingLpmEid(dstEid, xtrId, table);
+        return getMappingLpmEid(eid, xtrId, table);
     }
 
-    public Object getMapping(Eid srcEid, Eid dstEid) {
-        return getMapping(srcEid, dstEid, null);
+    // Returns the list of mappings stored in an xTR-ID DAO
+    private List<Object> getXtrIdMappingList(ILispDAO lispDAO) {
+        if (lispDAO != null) {
+            final List<Object> records = new ArrayList<>();
+            lispDAO.getAll(new IRowVisitor() {
+                public void visitRow(Object keyId, String valueKey, Object value) {
+                    if (valueKey.equals(SubKeys.RECORD)) {
+                        records.add(value);
+                    }
+                }
+            });
+            return records;
+        }
+        return null;
     }
 
+    @Override
     public List<Object> getAllXtrIdMappings(Eid eid) {
-        Map<String, ?> daoEntry = dao.getBest(MaskUtil.normalize(eid));
+        ILispDAO table = getVniTable(eid);
+        if (table == null) {
+            return null;
+        }
+        Map<String, ?> daoEntry = table.getBest(MaskUtil.normalize(eid));
         if (daoEntry != null) {
-            ILispDAO xtrIdTable = getXtrIdTable(eid, (ILispDAO) daoEntry.get(SubKeys.XTRID_RECORDS));
+            ILispDAO xtrIdTable = (ILispDAO) daoEntry.get(SubKeys.XTRID_RECORDS);
             if (xtrIdTable != null) {
                 return getXtrIdMappingList(xtrIdTable);
             }
@@ -211,153 +164,113 @@ public class SimpleMapCache implements IMapCache {
         return null;
     }
 
-    public Eid getWidestNegativeMapping(Eid key) {
-        ILispDAO table = getVniTable(key);
+    // Returns null for positive mappings, and 0/0 for empty cache.
+    @Override
+    public Eid getWidestNegativeMapping(Eid eid) {
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
-            return null;
+            return MaskUtil.normalize(eid, (short) 0);
         }
-        return table.getWidestNegativePrefix(MaskUtil.normalize(key));
+        return table.getWidestNegativePrefix(MaskUtil.normalize(eid));
     }
 
-    public void removeMapping(Eid eid, boolean overwrite) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getVniTable(key);
+    @Override
+    public Eid getCoveringLessSpecific(Eid eid) {
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
-            return;
-        }
-
-        table.removeSpecific(key, SubKeys.RECORD);
-        table.removeSpecific(key, SubKeys.REGDATE);
-
-        if (!overwrite) {
-            ILispDAO xtrIdTable = getXtrIdTable(key, table);
-            if (xtrIdTable != null) {
-                xtrIdTable.removeSpecific(key, SubKeys.RECORD);
-            }
+            return null;
         }
+        return table.getCoveringLessSpecific(MaskUtil.normalize(eid));
     }
 
-    public void addAuthenticationKey(Eid eid, MappingAuthkey authKey) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getOrInstantiateVniTable(key);
-        table.put(key, new MappingEntry<>(SubKeys.AUTH_KEY, authKey));
+    @Override
+    public Eid getParentPrefix(Eid eid) {
+        ILispDAO table = getVniTable(eid);
+        if (table == null) {
+            return null;
+        }
+        return table.getParentPrefix(MaskUtil.normalize(eid));
     }
 
-    private MappingAuthkey getAuthKeyLpm(Eid prefix, ILispDAO db) {
-        short maskLength = MaskUtil.getMaskForAddress(prefix.getAddress());
-        while (maskLength >= 0) {
-            Eid key = MaskUtil.normalize(prefix, maskLength);
-            Object password = db.getSpecific(key, SubKeys.AUTH_KEY);
-            if (password != null && password instanceof MappingAuthkey) {
-                return (MappingAuthkey) password;
-            }
-            maskLength -= 1;
+    @Override
+    public Eid getSiblingPrefix(Eid eid) {
+        ILispDAO table = getVniTable(eid);
+        if (table == null) {
+            return null;
         }
-        return null;
+        return table.getSiblingPrefix(MaskUtil.normalize(eid));
     }
 
-    public MappingAuthkey getAuthenticationKey(Eid eid) {
+    @Override
+    public Eid getVirtualParentSiblingPrefix(Eid eid) {
         ILispDAO table = getVniTable(eid);
         if (table == null) {
             return null;
         }
-        if (MaskUtil.isMaskable(eid.getAddress()) && !(eid.getAddress() instanceof SourceDestKey)) {
-            return getAuthKeyLpm(eid, table);
-        } else {
-            Eid key = MaskUtil.normalize(eid);
-            Object password = table.getSpecific(key, SubKeys.AUTH_KEY);
-            if (password != null && password instanceof MappingAuthkey) {
-                return (MappingAuthkey) password;
-            } else {
-                LOG.warn("Failed to find password!");
-                return null;
-            }
-        }
+        return table.getVirtualParentSiblingPrefix(MaskUtil.normalize(eid));
     }
 
-    public void removeAuthenticationKey(Eid eid) {
-        Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getVniTable(key);
+    @Override
+    public Set<Eid> getSubtree(Eid eid) {
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
-            return;
+            return Collections.emptySet();
         }
-        table.removeSpecific(key, SubKeys.AUTH_KEY);
+        return table.getSubtree(eid);
     }
 
-    public String printMappings() {
-        final StringBuffer sb = new StringBuffer();
-        sb.append("Keys\tValues\n");
-
-        final IRowVisitor innerVisitor = (new IRowVisitor() {
-            String lastKey = "";
-
-            public void visitRow(Object keyId, String valueKey, Object value) {
-                String key = keyId.getClass().getSimpleName() + "#" + keyId;
-                if (!lastKey.equals(key)) {
-                    sb.append("\n" + key + "\t");
-                }
-                sb.append(valueKey + "=" + value + "\t");
-                lastKey = key;
-            }
-        });
+    @Override
+    public void removeMapping(Eid eid) {
+        ILispDAO table = getVniTable(eid);
+        if (table == null) {
+            return;
+        }
 
-        dao.getAll(new IRowVisitor() {
-            String lastKey = "";
+        Eid key = MaskUtil.normalize(eid);
+        table.remove(key);
+        if (table.isEmpty()) {
+            removeVniTable(eid);
+        }
+    }
 
-            public void visitRow(Object keyId, String valueKey, Object value) {
-                String key = keyId.getClass().getSimpleName() + "#" + keyId;
-                if (!lastKey.equals(key)) {
-                    sb.append("\n" + key + "\t");
-                }
-                if (valueKey.equals(SubKeys.VNI)) {
-                    sb.append(valueKey + "= { ");
-                    ((ILispDAO)value).getAll(innerVisitor);
-                    sb.append("}\t");
-                } else {
-                    sb.append(valueKey + "=" + value + "\t");
-                }
-                lastKey = key;
-            }
-        });
-        sb.append("\n");
-        return sb.toString();
+    @Override
+    public void removeMapping(Eid eid, XtrId xtrId) {
+        List<XtrId> xtrIds = Arrays.asList(xtrId);
+        removeXtrIdMappings(eid, xtrIds);
     }
 
     @Override
-    public void updateMappingRegistration(Eid eid, Long timestamp) {
+    public void removeXtrIdMappings(Eid eid, List<XtrId> xtrIds) {
         ILispDAO table = getVniTable(eid);
         if (table == null) {
             return;
         }
-        if (timestamp == null) {
-            timestamp = System.currentTimeMillis();
+        Eid key = MaskUtil.normalize(eid);
+        ILispDAO xtrIdTable = (ILispDAO) table.getSpecific(key, SubKeys.XTRID_RECORDS);
+        if (xtrIdTable == null) {
+            return;
         }
-        Map<String, Object> daoEntry = table.getBest(MaskUtil.normalize(eid));
-        if (daoEntry != null) {
-            daoEntry.put(SubKeys.REGDATE, new Date(timestamp));
+        for (XtrId xtrId : xtrIds) {
+            xtrIdTable.removeSpecific(xtrId, SubKeys.RECORD);
         }
-
-        XtrId xtrId = ((MappingRecord) daoEntry.get(SubKeys.RECORD)).getXtrId();
-        if (xtrId != null) {
-            ILispDAO xtrIdTable = getXtrIdTable(eid, (ILispDAO) daoEntry.get(SubKeys.XTRID_RECORDS));
-            ExtendedMappingRecord extRecord = (ExtendedMappingRecord) xtrIdTable.getSpecific(xtrId,
-                    SubKeys.EXT_RECORD);
-            if (extRecord != null) {
-                extRecord.setTimestamp(new Date(timestamp));
+        if (xtrIdTable.isEmpty()) {
+            table.removeSpecific(key, SubKeys.XTRID_RECORDS);
+            if (table.isEmpty()) {
+                removeVniTable(eid);
             }
         }
     }
 
     @Override
     public void addData(Eid eid, String subKey, Object data) {
+        ILispDAO table = getOrInstantiateVniTable(eid);
         Eid key = MaskUtil.normalize(eid);
-        ILispDAO table = getOrInstantiateVniTable(key);
         table.put(key, new MappingEntry<>(subKey, data));
     }
 
     @Override
     public Object getData(Eid eid, String subKey) {
-        ILispDAO table = getOrInstantiateVniTable(eid);
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
             return null;
         }
@@ -367,11 +280,24 @@ public class SimpleMapCache implements IMapCache {
 
     @Override
     public void removeData(Eid eid, String subKey) {
-        ILispDAO table = getOrInstantiateVniTable(eid);
+        ILispDAO table = getVniTable(eid);
         if (table == null) {
             return;
         }
         Eid key = MaskUtil.normalize(eid);
         table.removeSpecific(key, subKey);
+        if (table.isEmpty()) {
+            removeVniTable(eid);
+        }
+    }
+
+    @Override
+    public String printMappings() {
+        return LispMapCacheStringifier.printSMCMappings(dao);
+    }
+
+    @Override
+    public String prettyPrintMappings() {
+        return LispMapCacheStringifier.prettyPrintSMCMappings(dao);
     }
 }