Package com.sun.sgs.impl.service.nodemap.affinity.dgb

Source Code of com.sun.sgs.impl.service.nodemap.affinity.dgb.DistGraphBuilderServerImpl$GetNodeIdTask

/*
* Copyright 2007-2010 Sun Microsystems, Inc.
*
* This file is part of Project Darkstar Server.
*
* Project Darkstar Server is free software: you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation and
* distributed hereunder to you.
*
* Project Darkstar Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* --
*/

package com.sun.sgs.impl.service.nodemap.affinity.dgb;

import com.sun.sgs.auth.Identity;
import com.sun.sgs.impl.service.nodemap.affinity.AffinityGroup;
import com.sun.sgs.impl.service.nodemap.affinity.LPAAffinityGroupFinder;
import
   com.sun.sgs.impl.service.nodemap.affinity.AffinityGroupFinderFailedException;
import com.sun.sgs.impl.service.nodemap.affinity.AffinityGroupFinderStats;
import com.sun.sgs.impl.service.nodemap.affinity.RelocatingAffinityGroup;
import
   com.sun.sgs.impl.service.nodemap.affinity.graph.AbstractAffinityGraphBuilder;
import com.sun.sgs.impl.service.nodemap.affinity.graph.AffinityGraphBuilder;
import
    com.sun.sgs.impl.service.nodemap.affinity.graph.AffinityGraphBuilderStats;
import com.sun.sgs.impl.service.nodemap.affinity.graph.LabelVertex;
import com.sun.sgs.impl.service.nodemap.affinity.graph.WeightedEdge;
import com.sun.sgs.impl.service.nodemap.affinity.single.SingleGraphBuilder;
import com.sun.sgs.impl.service.nodemap.affinity.single.SingleLabelPropagation;
import com.sun.sgs.impl.util.AbstractKernelRunnable;
import com.sun.sgs.impl.util.Exporter;
import com.sun.sgs.kernel.ComponentRegistry;
import com.sun.sgs.kernel.KernelRunnable;
import com.sun.sgs.kernel.TransactionScheduler;
import com.sun.sgs.management.AffinityGraphBuilderMXBean;
import com.sun.sgs.management.AffinityGroupFinderMXBean;
import com.sun.sgs.profile.AccessedObjectsDetail;
import com.sun.sgs.profile.ProfileCollector;
import com.sun.sgs.service.NodeMappingService;
import com.sun.sgs.service.TransactionProxy;
import com.sun.sgs.service.UnknownIdentityException;
import edu.uci.ics.jung.graph.UndirectedGraph;
import java.util.HashMap;
import java.util.Map;
import java.util.NavigableSet;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.Level;
import javax.management.JMException;

/**
* The server side of a distributed graph builder for label propagation.
*
* It builds a single graph representing all information for the entire
* system using the single node graph builder, and uses a single node label
* propagation implementation to process the graph.
*
* This LPA implementation is expected to be useful for simple multi-node
* testing.  It may have scalability problems due to the amount of data
* being sent from each node, and the size of the affinity graph and
* related data structures.  It has no dependencies on new multi-node parts
* of the system.
*/
public class DistGraphBuilderServerImpl extends AbstractAffinityGraphBuilder
    implements DistGraphBuilderServer, AffinityGraphBuilder,
               LPAAffinityGroupFinder
{
    /** The property name for the server port. */
    public static final String SERVER_PORT_PROPERTY =
            PROP_BASE + ".server.port";

    /** The default value of the server port. */
    public static final int DEFAULT_SERVER_PORT = 44537;

    /** The name we export ourselves under. */
    public static final String SERVER_EXPORT_NAME =
            "DistributedGraphBuilderServer";

    /** The exporter for this server. */
    private final Exporter<DistGraphBuilderServer> exporter;

    /** Our backing builder. */
    private final SingleGraphBuilder builder;

    /** Our label propagation algorithm. */
    private final SingleLabelPropagation lpa;

    /** The transaction scheduler. */
    private final TransactionScheduler transactionScheduler;

    /** The task owner. */
    private final Identity taskOwner;

    /** Our transaction proxy. */
    private final TransactionProxy txnProxy;

    /** Our JMX exposed information.  The group finder stats is held
     * in {@code lpa}.
     */
    private final AffinityGraphBuilderStats builderStats;

    /**
     * Creates a distributed graph builder server.
     * @param systemRegistry the registry of available system components
     * @param txnProxy the transaction proxy
     * @param properties  application properties
     * @param nodeId the core server node id
     * @throws Exception if an error occurs
     */
    DistGraphBuilderServerImpl(ComponentRegistry systemRegistry,
                               TransactionProxy txnProxy,
                               Properties properties,
                               long nodeId)
            throws Exception
    {
        super(properties);
        transactionScheduler =
      systemRegistry.getComponent(TransactionScheduler.class);
  this.txnProxy = txnProxy;
  taskOwner = txnProxy.getCurrentOwner();

        ProfileCollector col =
                systemRegistry.getComponent(ProfileCollector.class);
        // Create our backing graph builder.  We wrap this object so we
        // can return a different type from findAffinityGroups.
        builder = new SingleGraphBuilder(properties, systemRegistry,
                                         txnProxy, false);
        // Create our group finder and graph builder JMX MBeans
        AffinityGroupFinderStats stats =
                new AffinityGroupFinderStats(this, col, -1);
        builderStats = new AffinityGraphBuilderStats(col,
                                                     builder.getAffinityGraph(),
                                                     periodCount, snapshot);
        // We must set the stats before exporting ourself!
        builder.setStats(builderStats);
        try {
            col.registerMBean(stats, AffinityGroupFinderMXBean.MXBEAN_NAME);
            col.registerMBean(builderStats,
                                     AffinityGraphBuilderMXBean.MXBEAN_NAME);
        } catch (JMException e) {
            // Continue on if we couldn't register this bean, although
            // it's probably a very bad sign
            logger.logThrow(Level.CONFIG, e, "Could not register MBean");
        }
        // Create the LPA algorithm, telling it to use our group finder MBean.
        lpa = new SingleLabelPropagation(this, col, properties, stats);

        int requestedPort = wrappedProps.getIntProperty(
                SERVER_PORT_PROPERTY, DEFAULT_SERVER_PORT, 0, 65535);
        // Export ourself.
        exporter =
            new Exporter<DistGraphBuilderServer>(DistGraphBuilderServer.class);
        exporter.export(this, SERVER_EXPORT_NAME, requestedPort);
    }

    // Implement DistGraphBuilderServer

    /** {@inheritDoc} */
    public void updateGraph(Identity owner, Object[] objIds) {
        checkForShutdownState();
        builder.updateGraph(owner, objIds);
    }

    // Implement LPAAffinityGraphBuilder

    /** {@inheritDoc} */
    public void disable() {
        if (setDisabledState()) {
            // We don't tell our clients, so they will still be sending
            // graph updates via RMI.  But our builder will discard them.
            // A better solution would be to have clients register with this
            // server, so they could be called here -- that's a heavy-weight
            // option.
            // For now, can't entirely disable this variation.
            builder.disable();
            lpa.disable();
        }
    }

    /** {@inheritDoc} */
    public void enable() {
        if (setEnabledState()) {
            builder.enable();
            lpa.enable();
        }
    }
    /** {@inheritDoc} */
    public void shutdown() {
        // This method is in both AffinityGraphBuilder and AffinityGroupFinder
        if (setShutdownState()) {
            builder.shutdown();
            lpa.shutdown();
        }
    }

    /** {@inheritDoc} */
    public LPAAffinityGroupFinder getAffinityGroupFinder() {
        return this;
    }

    /** {@inheritDoc} */
    public void updateGraph(Identity owner, AccessedObjectsDetail detail) {
        throw new UnsupportedOperationException("Unexpected direct update");
    }

    /** {@inheritDoc} */
    public UndirectedGraph<LabelVertex, WeightedEdge> getAffinityGraph() {
        return builder.getAffinityGraph();
    }

    /** {@inheritDoc} */
    public LabelVertex getVertex(Identity id) {
        return builder.getVertex(id);
    }

    /**
     * Get the task which prunes the graph.  This is useful for testing.
     *
     * @return the runnable which prunes the graph.
     * @throws UnsupportedOperationException if this builder does not support
     *    graph pruning.
     */
    public Runnable getPruneTask() {
        return builder.getPruneTask();
    }

    // Implement LPAAffinityGroupFinder

    /**
     * {@inheritDoc}
     * <p>
     * The returned groups contain node assignment information for the
     * identities.  This information is looked up from the node mapping service.
     * Alternatively, we could create a new graph node type and track this
     * information based on which application node called updateGraph.  While
     * this would be some work, it might be worthwhile to implement if we
     * find this LPA implementation is useful in deployed systems.
     */
    public NavigableSet<RelocatingAffinityGroup> findAffinityGroups()
            throws AffinityGroupFinderFailedException
    {
        checkForDisabledOrShutdownState();

        Set<RelocatingAffinityGroup> groups = lpa.findAffinityGroups();
        // Need to translate each group into a relocating affinity group
        // Create our final return values.  This is much like what the
        // single group finder needed to do, but we ask the node mapping
        // service for the real node assignments.
        NavigableSet<RelocatingAffinityGroup> retVal =
                new TreeSet<RelocatingAffinityGroup>();
        for (AffinityGroup ag : groups) {
            long gen = ag.getGeneration();
            Map<Identity, Long> idMap = new HashMap<Identity, Long>();
            for (Identity id : ag.getIdentities()) {
                try {
                    GetNodeIdTask getNodeIdTask = new GetNodeIdTask(id);
                    runTransactionally(getNodeIdTask);
                    idMap.put(id, getNodeIdTask.getNodeId());
                } catch (UnknownIdentityException e) {
                    // just leave this one out
                } catch (Exception e) {
                    // We don't know what the assignment is.
                    logger.log(Level.INFO,
                               "Unknown node assignment for identity {0}", id);
                    idMap.put(id, Long.valueOf(-1));
                }
            }
            retVal.add(new RelocatingAffinityGroup(ag.getId(), idMap, gen));
        }
        return retVal;
    }

    /**
     *  Run the given task synchronously, and transactionally, retrying
     *  if the exception is of type {@code ExceptionRetryStatus}.
     * @param task the task
     */
    private void runTransactionally(KernelRunnable task) throws Exception {
        transactionScheduler.runTask(task, taskOwner);
    }

    /**
     * A transactional task to obtain the node assignment for a given identity.
     */
    private class GetNodeIdTask extends AbstractKernelRunnable {

  private final Identity id;
  private volatile long nodeId = -1;

  GetNodeIdTask(Identity id) {
      super(null);
      this.id = id;
  }

  public void run() throws Exception {
      nodeId = txnProxy.getService(NodeMappingService.class).
                         getNode(id).getId();
  }

  long getNodeId() {
      return nodeId;
  }
    }
}
TOP

Related Classes of com.sun.sgs.impl.service.nodemap.affinity.dgb.DistGraphBuilderServerImpl$GetNodeIdTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.