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

org.opendaylight.jsonrpc.provider.cluster.impl.SlavePeerContext Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2020 Lumina Networks, Inc. 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.jsonrpc.provider.cluster.impl;

import static akka.pattern.Patterns.ask;
import static org.opendaylight.jsonrpc.provider.cluster.impl.ClusterUtil.DEFAULT_ASK_TIMEOUT;
import static org.opendaylight.jsonrpc.provider.cluster.impl.ClusterUtil.createActorPath;
import static org.opendaylight.jsonrpc.provider.cluster.impl.ClusterUtil.createMasterActorName;
import static org.opendaylight.jsonrpc.provider.cluster.impl.ClusterUtil.durationFromUint16seconds;
import static org.opendaylight.jsonrpc.provider.cluster.impl.ClusterUtil.getPeerOpstateIdentifier;

import akka.actor.ActorRef;
import akka.actor.ActorSelection;
import akka.actor.PoisonPill;
import akka.dispatch.OnComplete;
import akka.util.Timeout;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.opendaylight.jsonrpc.provider.cluster.api.JsonRpcPeerSingletonService;
import org.opendaylight.jsonrpc.provider.cluster.messages.MountPointRequest;
import org.opendaylight.jsonrpc.provider.cluster.messages.UnregisterMountPoint;
import org.opendaylight.mdsal.binding.api.DataObjectModification;
import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
import org.opendaylight.mdsal.binding.api.DataTreeModification;
import org.opendaylight.yang.gen.v1.urn.opendaylight.jsonrpc.rev161201.MountStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.jsonrpc.rev161201.Peer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.jsonrpc.rev161201.config.ActualEndpoints;
import org.opendaylight.yangtools.concepts.Registration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import scala.concurrent.duration.Duration;

final class SlavePeerContext
        implements DataTreeChangeListener, JsonRpcPeerSingletonService, AutoCloseable {
    private static final Logger LOG = LoggerFactory.getLogger(SlavePeerContext.class);
    private final AtomicBoolean closed = new AtomicBoolean(false);
    private final Registration dtclRegistration;
    private ActorRef slaveActorRef;
    private final Timeout askTimeout;
    private final Peer peer;
    private final ClusterDependencies dependencies;

    SlavePeerContext(Peer peer, ClusterDependencies dependencies) {
        this.peer = peer;
        this.dependencies = dependencies;
        dtclRegistration = dependencies.getDataBroker()
                .registerTreeChangeListener(getPeerOpstateIdentifier(peer.getName()), this);
        final Duration askDuration = dependencies.getConfig() == null ? DEFAULT_ASK_TIMEOUT
                : durationFromUint16seconds(dependencies.getConfig().getActorResponseWaitTime(), DEFAULT_ASK_TIMEOUT);
        askTimeout = Timeout.apply(askDuration.toSeconds(), TimeUnit.SECONDS);
        LOG.debug("[{}] Created {}", peer.getName(), this);
    }

    @Override
    public void onDataTreeChanged(List> changes) {
        for (final DataTreeModification change : changes) {
            final DataObjectModification rootNode = change.getRootNode();
            LOG.debug("[{}] OP DTC [{}] : {} => {}", peer.getName(), rootNode.modificationType(),
                    rootNode.dataBefore(), rootNode.dataAfter());
            switch (rootNode.modificationType()) {
                case SUBTREE_MODIFIED:
                case WRITE:
                    onMountpointUpdated(rootNode.dataAfter());
                    break;
                case DELETE:
                    deleteMountpoint();
                    break;
                default:
                    LOG.warn("[{}] Unhandled modification {}", peer.getName(), rootNode.modificationType());
            }
        }
    }

    @Override
    public void close() {
        if (!closed.compareAndSet(false, true)) {
            return;
        }
        LOG.info("[{}] Closing {}", peer.getName(), this);
        dtclRegistration.close();
        if (slaveActorRef != null) {
            LOG.debug("[{}] Sending poison pill to {}", peer.getName(), slaveActorRef);
            slaveActorRef.tell(PoisonPill.getInstance(), ActorRef.noSender());
            slaveActorRef = null;
        }
    }

    private synchronized void onMountpointUpdated(ActualEndpoints opState) {
        if (MountStatus.Mounted.equals(opState.getMountStatus())) {
            ensureSlaveActor();
            final String masterAddress = opState.getManagedBy();
            final String actorPath = createActorPath(masterAddress,
                    createMasterActorName(peer.getName(), masterAddress));
            final ActorSelection masterRef = dependencies.getActorSystem().actorSelection(actorPath);
            LOG.debug("Sending MountPointRequest to {}", masterRef);
            ask(masterRef, new MountPointRequest(slaveActorRef), askTimeout).onComplete(new OnComplete<>() {
                @Override
                public void onComplete(final Throwable failure, final Object response) {
                    final boolean failed = failure != null;
                    LOG.debug("[{}] MountPointRequest {}", peer.getName(), failed ? "failed" : "succeeded");
                    if (closed.get()) {
                        return;
                    }
                    if (failed) {
                        LOG.error("[{}] MountPointRequest failed", peer.getName(), failure);
                    }
                }
            }, dependencies.getActorSystem().dispatcher());
        } else {
            deleteMountpoint();
        }
    }

    private synchronized void deleteMountpoint() {
        if (slaveActorRef != null) {
            LOG.debug("[{}] Sending UnregisterMountPoint to {}", peer.getName(), slaveActorRef);
            slaveActorRef.tell(new UnregisterMountPoint(), ActorRef.noSender());
        }
    }

    private synchronized void ensureSlaveActor() {
        if (slaveActorRef == null) {
            slaveActorRef = dependencies.getActorSystem().actorOf(RemotePeerActor.props(peer, dependencies));
            LOG.debug("[{}] Slave actor created with name {}", peer.getName(), slaveActorRef);
        }
    }

    @Override
    public String toString() {
        return "SlavePeerContext [closed=" + closed + ", peer=" + peer.getName() + "]";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy