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

Source Code of com.sun.sgs.impl.service.nodemap.affinity.dgb.DistGraphBuilder

/*
* 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.kernel.StandardProperties;
import com.sun.sgs.impl.service.nodemap.affinity.LPAAffinityGroupFinder;
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.LabelVertex;
import com.sun.sgs.impl.service.nodemap.affinity.graph.WeightedEdge;
import com.sun.sgs.impl.util.AbstractService;
import com.sun.sgs.impl.util.IoRunnable;
import com.sun.sgs.kernel.AccessedObject;
import com.sun.sgs.kernel.ComponentRegistry;
import com.sun.sgs.kernel.NodeType;
import com.sun.sgs.profile.AccessedObjectsDetail;
import com.sun.sgs.service.DataService;
import com.sun.sgs.service.TransactionProxy;
import com.sun.sgs.service.WatchdogService;
import edu.uci.ics.jung.graph.UndirectedGraph;
import java.io.IOException;
import java.net.InetAddress;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Properties;
import java.util.logging.Level;

/**
* The portion of the distributed affinity graph builder which resides on
* a local node.  This code forwards graph information to its server,
* which builds a single large graph for all information in the system.
* <p>
* If the server cannot be contacted, we report the failure to the watchdog.
* <p>
* The following properties are supported:
* <p>
* <dl style="margin-left: 1em">
*
* <dt>  <i>Property:</i> <code><b>
*  com.sun.sgs.impl.service.nodemap.affinity.server.host
</b></code><br>
<i>Default:</i> the value of the {@code com.sun.sgs.server.host}
*  property, if present, or {@code localhost} if this node is starting the
*      server <br>
*
* <dd style="padding-top: .5em">The name of the host running the {@code
*  NodeMappingServer}. <p>
*
* <dt>  <i>Property:</i> <code><b>
*  com.sun.sgs.impl.service.nodemap.affinity.server.port
</b></code><br>
<i>Default:</i> {@code 44537}
*
* <dd style="padding-top: .5em">The network port for the {@code
*  LabelPropagationServer}.  This value must be no less than {@code 0} and
*      no greater than {@code 65535}. <p>
*
* <dt>  <i>Property:</i> <code><b>
*  com.sun.sgs.impl.service.nodemap.affinity.snapshot.period
</b></code><br>
<i>Default:</i> {@code 300000} (5 minutes)<br>
*
* <dd style="padding-top: .5em">The amount of time, in milliseconds, for
*      each snapshot of retained data.  Older snapshots are discarded as
*      time goes on. A longer snapshot period gives us more history, but
*      also longer compute times to use that history, as more data must
*      be processed.<p>
*
* <dt>  <i>Property:</i> <code><b>
*  com.sun.sgs.impl.service.nodemap.affinity.snapshot.count
</b></code><br>
<i>Default:</i> {@code 1}
*
* <dd style="padding-top: .5em">The number of snapshots to retain.  A
*       larger value means more history will be retained.  Using a smaller
*       snapshot period with a larger count means more total history will be
*       retained, with a smaller amount discarded at the start of each
*       new snapshot.<p>
* </dl>
*/
public class DistGraphBuilder extends AbstractAffinityGraphBuilder
        implements AffinityGraphBuilder
{
    /** The property name for the server host. */
    private static final String SERVER_HOST_PROPERTY =
            PROP_BASE + ".server.host";

    /** The default number of IO task retries **/
    private static final int DEFAULT_MAX_IO_ATTEMPTS = 5;
    /** The default time interval to wait between IO task retries **/
    private static final int DEFAULT_RETRY_WAIT_TIME = 100;

    /** The time (in milliseconds) to wait between retries for IO
     * operations.
     */
    private final int retryWaitTime;

    /** The maximum number of retry attempts for IO operations. */
    private final int maxIoAttempts;

    /** The remote server, or null if we're on the core server node. */
    private final DistGraphBuilderServer server;
    /** The server implementation, or null if we're on an app node. */
    private final DistGraphBuilderServerImpl serverImpl;

    /** The watchdog service. */
    private final WatchdogService watchdogService;
    /** Our local node id. */
    private final long localNodeId;

    /**
     * Creates the client side of a distributed graph builder.
     * @param properties the properties for configuring this builder
     * @param systemRegistry the registry of available system components
     * @param txnProxy the transaction proxy
     * @throws Exception if an error occurs
     */
    public DistGraphBuilder(Properties properties,
                            ComponentRegistry systemRegistry,
                            TransactionProxy txnProxy)
        throws Exception
    {
        super(properties);

        watchdogService = txnProxy.getService(WatchdogService.class);

        retryWaitTime = wrappedProps.getIntProperty(
                AbstractService.IO_TASK_WAIT_TIME_PROPERTY,
                DEFAULT_RETRY_WAIT_TIME, 0, Integer.MAX_VALUE);
        maxIoAttempts = wrappedProps.getIntProperty(
                AbstractService.IO_TASK_RETRIES_PROPERTY,
                DEFAULT_MAX_IO_ATTEMPTS, 0, Integer.MAX_VALUE);

        DataService dataService = txnProxy.getService(DataService.class);
        localNodeId = dataService.getLocalNodeId();

        NodeType nodeType =
                wrappedProps.getEnumProperty(StandardProperties.NODE_TYPE,
                                             NodeType.class,
                                             NodeType.singleNode);
        if (nodeType == NodeType.coreServerNode) {
            serverImpl =
                new DistGraphBuilderServerImpl(systemRegistry, txnProxy,
                                               properties, localNodeId);
            server = null;
        } else {
            String host = wrappedProps.getProperty(SERVER_HOST_PROPERTY,
                            wrappedProps.getProperty(
                                StandardProperties.SERVER_HOST));
            if (host == null) {
                // None specified, use local host
                host = InetAddress.getLocalHost().getHostName();
            }
            int port = wrappedProps.getIntProperty(
                    DistGraphBuilderServerImpl.SERVER_PORT_PROPERTY,
                    DistGraphBuilderServerImpl.DEFAULT_SERVER_PORT, 0, 65535);
            // Look up our server
            Registry registry = LocateRegistry.getRegistry(host, port);
            server = (DistGraphBuilderServer) registry.lookup(
                             DistGraphBuilderServerImpl.SERVER_EXPORT_NAME);
            serverImpl = null;
        }
    }

    /** {@inheritDoc} */
    public void updateGraph(final Identity owner, AccessedObjectsDetail detail)
    {
        checkForShutdownState();
        if (state == State.DISABLED) {
            return;
        }
        final Object[] ids = new Object[detail.getAccessedObjects().size()];
        int index = 0;
        for (AccessedObject access : detail.getAccessedObjects()) {
            ids[index++] = access.getObjectId();
        }
        runIoTask(new IoRunnable() {
                    public void run() throws IOException {
                        server.updateGraph(owner, ids);
                    } }, localNodeId);
    }

    /**
     * {@inheritDoc}
     * <p>
     * This implementation will always throw an
     * {@code UnsupportedOperationException}, because the graph is not
     * held on the local node.
     */
    public UndirectedGraph<LabelVertex, WeightedEdge> getAffinityGraph() {
        throw new UnsupportedOperationException(
                "Cannot obtain the affinity graph from a local node");
    }

    /**
     * {@inheritDoc}
     * <p>
     * This implementation will always throw an
     * {@code UnsupportedOperationException}, because the graph is not
     * held on the local node.
     */
    public LabelVertex getVertex(Identity id) {
        throw new UnsupportedOperationException(
                "Cannot obtain the affinity graph from a local node");
    }


    /** {@inheritDoc} */
    public void enable() {
        if (setEnabledState()) {
            if (serverImpl != null) {
                serverImpl.enable();
            }
        }
    }

    /** {@inheritDoc} */
    public void disable() {
        if (setDisabledState()) {
            if (serverImpl != null) {
                serverImpl.disable();
            }
        }
    }

    /** {@inheritDoc} */
    public void shutdown() {
        if (setShutdownState()) {
            if (serverImpl != null) {
                serverImpl.shutdown();
            }
        }
    }

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

    /**
     * Executes the specified {@code ioTask} by invoking its {@link
     * IoRunnable#run run} method. If the specified task throws an
     * {@code IOException}, this method will retry the task for a fixed
     * number of times. The method will stop retrying if the node with
     * the given {@code nodeId} is no longer alive. The number of retries
     * and the wait time between retries are configurable properties.
     * <p>
     * This is much the same as the like method in AbstractService, except
     * we don't bother to check for a transactional context (we won't be in
     * one), and we use the watchdog's non-transactional call to find out
     * if the local node is alive.  We cannot use the AbstractService version
     * because we are not an AbstractService.  It may be useful to refactor
     * that method into a static method somewhere.
     *
     * @param ioTask a task with IO-related operations
     * @param nodeId the node that is the target of the IO operations
     */
    private void runIoTask(IoRunnable ioTask, long nodeId) {
        int maxAttempts = maxIoAttempts;
        do {
            try {
                ioTask.run();
                return;
            } catch (IOException e) {
                if (logger.isLoggable(Level.FINEST)) {
                    logger.logThrow(Level.FINEST, e,
                            "IoRunnable {0} throws", ioTask);
                }
                if (maxAttempts-- == 0) {
                    logger.logThrow(Level.WARNING, e,
                            "A communication error occured while running an" +
                            "IO task. Reporting node {0} as failed.", nodeId);

                    // Report failure of remote node since are
                    // having trouble contacting it
                    watchdogService.
                            reportFailure(nodeId, this.getClass().toString());

                    break;
                }
                try {
                    // TBD: what back-off policy do we want here?
                    Thread.sleep(retryWaitTime);
                } catch (InterruptedException ie) {
                }
            }
        } while (watchdogService.isLocalNodeAliveNonTransactional());
    }
}
TOP

Related Classes of com.sun.sgs.impl.service.nodemap.affinity.dgb.DistGraphBuilder

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.