org.onosproject.mapping.impl.DistributedMappingStore.java Source code

Java tutorial

Introduction

Here is the source code for org.onosproject.mapping.impl.DistributedMappingStore.java

Source

/*
 * Copyright 2017-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.mapping.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.mapping.DefaultMapping;
import org.onosproject.mapping.DefaultMappingEntry;
import org.onosproject.mapping.Mapping;
import org.onosproject.mapping.MappingEntry;
import org.onosproject.mapping.MappingEvent;
import org.onosproject.mapping.MappingId;
import org.onosproject.mapping.MappingKey;
import org.onosproject.mapping.MappingStore;
import org.onosproject.mapping.MappingStoreDelegate;
import org.onosproject.mapping.MappingTreatment;
import org.onosproject.mapping.MappingValue;
import org.onosproject.mapping.actions.MappingAction;
import org.onosproject.mapping.addresses.MappingAddress;
import org.onosproject.mapping.instructions.MappingInstruction;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.MapEvent;
import org.onosproject.store.service.MapEventListener;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.slf4j.Logger;

import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * Implementation of a distributed store for managing mapping information.
 */
@Component(immediate = true)
@Service
public class DistributedMappingStore extends AbstractStore<MappingEvent, MappingStoreDelegate>
        implements MappingStore {

    private final Logger log = getLogger(getClass());

    private ConsistentMap<MappingId, Mapping> database;
    private ConsistentMap<MappingId, Mapping> cache;

    private Map<MappingId, Mapping> databaseMap;
    private Map<MappingId, Mapping> cacheMap;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected StorageService storageService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    private final MapEventListener<MappingId, Mapping> listener = new InternalListener();

    @Activate
    public void activate() {

        Serializer serializer = Serializer.using(KryoNamespaces.API, Mapping.class, DefaultMapping.class,
                MappingId.class, MappingEvent.Type.class, MappingKey.class, MappingValue.class,
                MappingAddress.class, MappingAddress.Type.class, MappingAction.class, MappingAction.Type.class,
                MappingTreatment.class, MappingInstruction.class, MappingInstruction.Type.class);

        database = storageService.<MappingId, Mapping>consistentMapBuilder().withName("onos-mapping-database")
                .withSerializer(serializer).build();

        cache = storageService.<MappingId, Mapping>consistentMapBuilder().withName("onos-mapping-cache")
                .withSerializer(serializer).build();

        database.addListener(listener);
        cache.addListener(listener);
        databaseMap = database.asJavaMap();
        cacheMap = cache.asJavaMap();
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        database.removeListener(listener);
        cache.removeListener(listener);
        log.info("Stopped");
    }

    /**
     * Obtains map representation of mapping store.
     *
     * @param type mapping store type
     * @return map representation of mapping store
     */
    private Map<MappingId, Mapping> getStoreMap(Type type) {
        switch (type) {
        case MAP_DATABASE:
            return databaseMap;
        case MAP_CACHE:
            return cacheMap;
        default:
            log.warn("Unrecognized map store type {}", type);
            return Maps.newConcurrentMap();
        }
    }

    /**
     * Obtains mapping store.
     *
     * @param type mapping store type
     * @return mapping store
     */
    private ConsistentMap<MappingId, Mapping> getStore(Type type) {
        switch (type) {
        case MAP_DATABASE:
            return database;
        case MAP_CACHE:
            return cache;
        default:
            throw new IllegalArgumentException("Wrong mapping store " + type);
        }
    }

    @Override
    public int getMappingCount(Type type) {
        AtomicInteger sum = new AtomicInteger(0);
        deviceService.getDevices()
                .forEach(device -> sum.addAndGet(Iterables.size(getMappingEntries(type, device.id()))));
        return sum.get();
    }

    @Override
    public Iterable<MappingEntry> getAllMappingEntries(Type type) {

        Map<MappingId, Mapping> storeMap = getStoreMap(type);
        return ImmutableList
                .copyOf(storeMap.values().stream().map(DefaultMappingEntry::new).collect(Collectors.toList()));
    }

    @Override
    public MappingEntry getMappingEntry(Type type, Mapping mapping) {

        return new DefaultMappingEntry(getStoreMap(type).get(mapping.id()));
    }

    @Override
    public Iterable<MappingEntry> getMappingEntries(Type type, DeviceId deviceId) {

        Map<MappingId, Mapping> storeMap = getStoreMap(type);
        return ImmutableList.copyOf(storeMap.values().stream().filter(m -> m.deviceId() == deviceId)
                .map(DefaultMappingEntry::new).collect(Collectors.toList()));
    }

    @Override
    public void storeMapping(Type type, Mapping mapping) {

        getStore(type).put(mapping.id(), mapping);
    }

    @Override
    public MappingEvent removeMapping(Type type, Mapping mapping) {

        getStore(type).remove(mapping.id());
        return null;
    }

    @Override
    public void pendingDeleteMapping(Type type, Mapping mapping) {
        // TODO: this will be implemented when management plane is ready
        log.error("This method will be available when management plane is ready");
    }

    @Override
    public MappingEvent addOrUpdateMappingEntry(Type type, MappingEntry entry) {
        // TODO: this will be implemented when management plane is ready
        log.error("This method will be available when management plane is ready");
        return null;
    }

    @Override
    public MappingEvent pendingMappingEntry(Type type, MappingEntry entry) {
        // TODO: this will be implemented when management plane is ready
        log.error("This method will be available when management plane is ready");
        return null;
    }

    @Override
    public void purgeMappingEntries(Type type) {
        getStore(type).clear();
    }

    /**
     * Event listener to notify delegates about mapping events.
     */
    private class InternalListener implements MapEventListener<MappingId, Mapping> {

        @Override
        public void event(MapEvent<MappingId, Mapping> event) {
            final MappingEvent.Type type;
            final Mapping mapping;

            switch (event.type()) {
            case INSERT:
                type = MappingEvent.Type.MAPPING_ADDED;
                mapping = event.newValue().value();
                break;
            case UPDATE:
                type = MappingEvent.Type.MAPPING_UPDATED;
                mapping = event.newValue().value();
                break;
            case REMOVE:
                type = MappingEvent.Type.MAPPING_REMOVED;
                mapping = event.oldValue().value();
                break;
            default:
                throw new IllegalArgumentException("Wrong event type " + event.type());
            }
            notifyDelegate(new MappingEvent(type, mapping));
        }
    }
}