co.paralleluniverse.galaxy.core.NodeDeathLayer.java Source code

Java tutorial

Introduction

Here is the source code for co.paralleluniverse.galaxy.core.NodeDeathLayer.java

Source

/*
 * Galaxy
 * Copyright (c) 2012-2014, Parallel Universe Software Co. All rights reserved.
 * 
 * This program and the accompanying materials are dual-licensed under
 * either the terms of the Eclipse Public License v1.0 as published by
 * the Eclipse Foundation
 *  
 *   or (per the licensee's choosing)
 *  
 * under the terms of the GNU Lesser General Public License version 3.0
 * as published by the Free Software Foundation.
 */
package co.paralleluniverse.galaxy.core;

import co.paralleluniverse.common.collection.ConcurrentMapComplex;
import co.paralleluniverse.galaxy.Cluster;
import co.paralleluniverse.galaxy.cluster.NodeChangeListener;
import co.paralleluniverse.galaxy.core.Message.LineMessage;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import java.util.Iterator;
import java.util.Set;

/**
 * This class is unused as it's insufficient to invalidate S lines whose owner has died.
 * @author pron
 */
class NodeDeathLayer implements Comm, NodeChangeListener, MessageReceiver {
    private final Comm comm;
    private final Cluster cluster;
    private MessageReceiver cache;
    private final ConcurrentMapComplex<Short, SetMultimap<Long, LineMessage>> pending = new ConcurrentMapComplex<Short, SetMultimap<Long, LineMessage>>() {

        @Override
        protected SetMultimap<Long, LineMessage> allocateElement() {
            SetMultimap<Long, LineMessage> mm = HashMultimap.create();
            return Multimaps.synchronizedSetMultimap(mm);
        }

        @Override
        protected SetMultimap<Long, LineMessage> emptyElement() {
            return ImmutableSetMultimap.of();
        }
    };

    public NodeDeathLayer(Comm comm, Cluster cluster) {
        this.comm = comm;
        this.cluster = cluster;

        comm.setReceiver(this);
        cluster.addNodeChangeListener(this);
    }

    @Override
    public void setReceiver(MessageReceiver receiver) {
        cache = receiver;
    }

    public void addPending(LineMessage message) {
        short node = message.getNode();
        if (node != -1)
            pending.getOrAllocate(node).put(message.getLine(), message);
    }

    public void removePending(LineMessage message) {
        Set<LineMessage> msgs = pending.get(message.getNode()).get(message.getLine());
        for (Iterator<LineMessage> it = msgs.iterator(); it.hasNext();) {
            Message msg = it.next();
            if (message.getType() == Message.Type.INVACK && msg.getType() == Message.Type.INV)
                it.remove();
            else if (message.getType() == Message.Type.PUTX
                    && (msg.getType() == Message.Type.GETX || msg.getType() == Message.Type.GET))
                it.remove();
            else if (message.getType() == Message.Type.PUT && msg.getType() == Message.Type.GET)
                it.remove();
        }
    }

    @Override
    public void receive(Message message) {
        removePending((LineMessage) message);
        cache.receive(message);
    }

    @Override
    public void send(Message message) {
        try {
            comm.send(message);
        } catch (NodeNotFoundException e) {
            final Message response = genResponse((LineMessage) message);
            if (response != null)
                cache.receive(shortCircuitMessage(message.getNode(), response));
        }
    }

    @Override
    public void nodeRemoved(short node) {
        final Multimap<Long, LineMessage> mm = pending.get(node);
        for (LineMessage m : mm.values()) {
            final Message response = genResponse(m);
            if (response != null)
                cache.receive(shortCircuitMessage(m.getNode(), response));
        }
        pending.remove(node);
    }

    private Message genResponse(Message message) {
        switch (message.getType()) {
        case INV:
            return Message.INVACK((Message.INV) message);
        case GET:
        case GETX:
            return Message.CHNGD_OWNR((LineMessage) message, ((LineMessage) message).getLine(), (short) -1, false);
        default:
            return null;
        // don't send message
        }
    }

    @Override
    public void nodeAdded(short node) {
    }

    private Message shortCircuitMessage(short node, Message message) {
        message.setIncoming();
        message.setNode(node);
        return message;
    }

    @Override
    public void nodeSwitched(short id) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}