All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opendaylight.l2switch.hosttracker.plugin.internal.ConcurrentClusterAwareLinkHashMap Maven / Gradle / Ivy

There is a newer version: 0.7.4
Show newest version
/**
 * Copyright (c) 2016 Brocade Communications 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,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */

package org.opendaylight.l2switch.hosttracker.plugin.internal;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.l2switch.hosttracker.plugin.util.Utilities;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This will (try to) submit all writes and deletes in to the MD-SAL database.
 * The
 * {@link #removeLocally(org.opendaylight.yangtools.yang.binding.InstanceIdentifier)}
 * {@link #removeLocally(java.lang.Object) }
 * {@link #putLocally(org.opendaylight.yangtools.yang.binding.InstanceIdentifier, java.lang.Object)}
 * methods should be used when dataChanges are dealt locally and not update to MD-SAL.
 *
 * @param 
 *            Must be a Link
 * @param 
 *            Must be
 *            org.opendaylight.l2switch.hosttracker.plugin.inventory.Link;
 */

public class ConcurrentClusterAwareLinkHashMap implements
        ConcurrentMap {
    private final OperationProcessor opProcessor;
    private final String topologyId;

    private static final Logger LOG = LoggerFactory
            .getLogger(ConcurrentClusterAwareLinkHashMap.class);

    /**
     * The instance identifiers for each Link submitted to MD-SAL.
     */
    private final ConcurrentHashMap, K> instanceIDs;

    /**
     * The local Links' HashMap.
     */
    private final ConcurrentHashMap linkHashMap;

    public ConcurrentClusterAwareLinkHashMap(OperationProcessor opProcessor,
                                             String topologyId) {
        this.opProcessor = opProcessor;
        this.topologyId = topologyId;
        this.linkHashMap = new ConcurrentHashMap<>();
        this.instanceIDs = new ConcurrentHashMap<>();
    }


    /**
     * Puts the given value (Link) only in this local HashMap. Ideally used for
     * Link data listener events.
     *
     * @param ii the value's (Link's) InstanceIdentifier<Link>
     * @param value the Link to store locally.
     * @return the previous value associated with key, or
     * null if there was no mapping for key
     */
    public synchronized V putLocally(InstanceIdentifier ii, V value) {
        Link l = ((Link) value);
        LOG.trace("Putting locally {}", l.getLinkId());
        this.instanceIDs.put(ii, (K) l.getLinkId());
        return this.linkHashMap.put((K) l.getLinkId(), value);
    }

    /**
     * Copies all of the mappings from the specified map to this local HashMap
     * and into MD-SAL.
     *
     * @param m
     *            mappings to be stored in this local HashMap and into MD-SAL
     */
    @Override
    public synchronized void putAll(Map m) {
        for (Map.Entry e : m.entrySet()) {
            final Link linkNode = ((Link) e.getValue());
            final InstanceIdentifier buildLinkIID = Utilities
                    .buildLinkIID(linkNode.getKey(), topologyId);
            this.opProcessor.enqueueOperation(new HostTrackerOperation() {
                @Override
                public void applyOperation(ReadWriteTransaction tx) {
                    tx.merge(LogicalDatastoreType.OPERATIONAL, buildLinkIID,
                            linkNode, true);
                }
            });
            putLocally(buildLinkIID, e.getValue());
        }
    }

    /**
     * Removes the given links both locally and on MD-SAL database.
     *
     * @param links
     *            the links to remove.
     */
    public synchronized void removeAll(List links) {
        for (final Map.Entry, K> e : this.instanceIDs
                .entrySet()) {
            LOG.debug("Links to remove from local & MD-SAL database", links.toString());
            for (Link l : links) {
                if (e.getValue().equals(l.getLinkId())) {
                    this.opProcessor
                            .enqueueOperation(new HostTrackerOperation() {
                                @Override
                                public void applyOperation(
                                        ReadWriteTransaction tx) {
                                    tx.delete(LogicalDatastoreType.OPERATIONAL,
                                            e.getKey());
                                }
                            });
                    this.linkHashMap.remove(e.getValue());
                    break;
                }
            }
        }
    }

    /**
     *
     * Replaces the entry for a key only if currently mapped to a given value.
     *
     * @param key
     *            key with which the specified value is associated
     * @param oldValue
     *            value expected to be associated with the specified key
     * @param newValue
     *            value to be associated with the specified key
     */
    @Override
    public synchronized boolean replace(K key, V oldValue, V newValue) {
        if (this.linkHashMap.containsKey((K) key)
                && this.linkHashMap.get((K) key).equals(oldValue)) {
            put(key, newValue);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Returns the KeySet from this local HashMap.
     *
     * @return the KeySet from this local HashMap.
     */
    @Override
    public synchronized Set keySet() {
        return this.linkHashMap.keySet();
    }

    /**
     * Removes the entry for a key only if currently mapped to a given value.
     *
     * @param key
     *            key with which the specified value is associated
     * @param value
     *            value expected to be associated with the specified key
     * @return true if the value was removed
     */
    @Override
    public synchronized boolean remove(Object key, Object value) {
        if (this.linkHashMap.containsKey((K) key)
                && this.linkHashMap.get((K) key).equals(value)) {
            remove((K) key);
            return true;
        } else {
            return false;
        }
    }


    /**
     *
     * Replaces the entry for a key only if currently mapped to some value.
     *
     * @param key
     *            key with which the specified value is associated
     * @param value
     *            value to be associated with the specified key
     * @return the previous value associated with the specified key, or
     *         null if there was no mapping for the key. (A
     *         null return can also indicate that the map previously
     *         associated null with the key, if the implementation
     *         supports null values.)
     */
    @Override
    public synchronized V replace(K key, V value) {
        if (this.linkHashMap.containsKey(key)) {
            return put(key, value);
        } else {
            return null;
        }
    }


    /**
     * If it's absent from the this local HashMap, puts the given host in the
     * this local HashMap and into MD-SAL database.
     *
     * @param key
     *            the key for the map
     * @param value
     *            the value for the map
     * @return the old value from the local cache if present, null otherwise.
     */
    @Override
    public synchronized V putIfAbsent(K key, V value) {
        if (!this.linkHashMap.contains(value)) {
            return this.linkHashMap.put(key, value);
        } else {
            return this.linkHashMap.get(key);
        }
    }


    /**
     * Puts the given link in the this local HashMap and into MD-SAL database.
     *
     * @param linkId
     *            the key for the map
     * @param link
     *            the value for the map
     * @return the old value from the local cache if present, null otherwise.
     */
    @Override
    public synchronized V put(K linkId, V link) {
        final Link linkNode = ((Link) link);
        final InstanceIdentifier buildLinkIID = Utilities.buildLinkIID(
                linkNode.getKey(), topologyId);
        this.opProcessor.enqueueOperation(new HostTrackerOperation() {
            @Override
            public void applyOperation(ReadWriteTransaction tx) {
                tx.merge(LogicalDatastoreType.OPERATIONAL, buildLinkIID,
                        linkNode, true);
            }
        });
        LOG.trace("Putting MD-SAL {}", linkNode.getLinkId());
        return putLocally(buildLinkIID, link);
    }

    @Override
    public synchronized int size() {
        return this.linkHashMap.size();
    }

    @Override
    public synchronized Set> entrySet() {
        return this.linkHashMap.entrySet();
    }


    @Override
    public synchronized boolean isEmpty() {
        return this.linkHashMap.isEmpty();
    }

    @Override
    public synchronized boolean containsKey(Object key) {
        return this.linkHashMap.containsKey(key);
    }

    @Override
    public synchronized boolean containsValue(Object value) {
        return this.linkHashMap.contains(value);
    }

    @Override
    public synchronized V get(Object key) {
        return this.linkHashMap.get(key);
    }

    /**
     * Removes the value (Host) with the given linkId from this local HashMap
     * and MD-SAL database.
     *
     * @param linkId
     *            the link's linkId to remove
     * @return the old value from the local cache if present, null otherwise.
     */
    @Override
    public synchronized V remove(Object linkId) {
        V removedValue = this.linkHashMap.remove(linkId);
        if (removedValue != null) {
            Link linkNode = (Link) removedValue;
            final InstanceIdentifier lnIID = Utilities.buildLinkIID(
                    linkNode.getKey(), topologyId);
            this.opProcessor.enqueueOperation(new HostTrackerOperation() {
                @Override
                public void applyOperation(ReadWriteTransaction tx) {
                    tx.delete(LogicalDatastoreType.OPERATIONAL, lnIID);
                }
            });
            this.instanceIDs.remove(lnIID);
        }
        return removedValue;
    }
    /**
     * Returns the Values from this local HashMap.
     *
     * @return the Values from this local HashMap.
     */
    @Override
    public synchronized Collection values() {
        return this.linkHashMap.values();
    }

    /**
     * Removes, if exists, the Link with the given InstanceIdentifier<Link> from
     * this local HashMap. Ideally used for link data listener events.
     *
     * @param iiL
     *            the InstanceIdentifier<Link> of the Link to remove.
     * @return the removed Link if exits, null if it doesn't exist.
     */
    public synchronized V removeLocally(InstanceIdentifier iiL) {
        K linkId = this.instanceIDs.get(iiL);
        if (linkId != null) {
            this.instanceIDs.remove(iiL);
            return this.linkHashMap.remove(linkId);
        }
        return null;
    }

    /**
     * Removes, if exists, the Link with the given Key (LinkId) from this local
     * HashMap. Ideally used for link data listener events.
     *
     * @param key
     *            the key (LinkId) of the Link to remove.
     * @return the removed Link if exits, null if it doesn't exist.
     */
    public synchronized V removeLocally(K key) {
        Iterator, K>> iterator = this.instanceIDs
                .entrySet().iterator();
        while (iterator.hasNext()) {
            if (iterator.next().getValue().equals(key)) {
                iterator.remove();
                break;
            }
        }
        return linkHashMap.remove(key);
    }

    /**
     *
     * Removes all of the mappings from this local HashMap and from MD-SAL. The
     * local HashMap will be empty after this call returns.
     *
     */
    @Override
    public synchronized void clear() {
        for (final Map.Entry, ? extends K> e : this.instanceIDs
                .entrySet()) {
            this.opProcessor.enqueueOperation(new HostTrackerOperation() {
                @Override
                public void applyOperation(ReadWriteTransaction tx) {
                    tx.delete(LogicalDatastoreType.OPERATIONAL, e.getKey());
                }
            });
        }
        this.linkHashMap.clear();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy