gridool.tools.GridTaskMover.java Source code

Java tutorial

Introduction

Here is the source code for gridool.tools.GridTaskMover.java

Source

/*
 * @(#)$Id$
 *
 * Copyright 2006-2008 Makoto YUI
 *
 * 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.
 * 
 * Contributors:
 *     Makoto YUI - initial implementation
 */
package gridool.tools;

import gridool.Grid;
import gridool.GridConfiguration;
import gridool.GridException;
import gridool.GridNode;
import gridool.GridResourceRegistry;
import gridool.GridTask;
import gridool.GridTaskResult;
import gridool.GridTaskResultPolicy;
import gridool.annotation.GridConfigResource;
import gridool.annotation.GridRegistryResource;
import gridool.communication.GridCommunicationManager;
import gridool.construct.GridJobBase;
import gridool.loadblancing.workstealing.GridTaskStealingTask;
import gridool.routing.GridNodeSelector;
import gridool.routing.GridRouter;
import gridool.taskqueue.sender.SenderResponseTaskQueue;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 
 * <DIV lang="en"></DIV>
 * <DIV lang="ja"></DIV>
 * 
 * @author Makoto YUI (yuin405@gmail.com)
 */
public final class GridTaskMover {
    private static final Log LOG = LogFactory.getLog(GridTaskMover.class);

    @Nonnull
    private final Grid grid;

    public GridTaskMover(@CheckForNull Grid grid) {
        if (grid == null) {
            throw new IllegalArgumentException();
        }
        this.grid = grid;
    }

    /**
     * Attempt work stealing.
     */
    public boolean moveTask(@Nonnegative int tasks, @Nonnull GridNode fromNode, @Nonnull List<GridNode> destNodes,
            boolean async) {
        assert (tasks >= 0);
        if (tasks == 0) {
            return true;
        }
        if (destNodes.isEmpty()) {
            return false;
        }
        final TaskMoveOperation ops = new TaskMoveOperation(tasks, fromNode, destNodes, async);
        try {
            return grid.execute(GridTaskStealJob.class, ops);
        } catch (RemoteException e) {
            LOG.error("failed to move tasks: " + e.getMessage(), e);
            return false;
        }
    }

    public boolean moveTask(@Nonnull List<GridTask> tasks, @Nonnull List<GridNode> destNodes, boolean async) {
        if (tasks.isEmpty()) {
            return true;
        }
        if (destNodes.isEmpty()) {
            return false;
        }
        final TaskMoveOperation ops = new TaskMoveOperation(tasks, destNodes, async);
        try {
            return grid.execute(GridLocalTaskMoveJob.class, ops);
        } catch (RemoteException e) {
            LOG.error("failed to move tasks: " + e.getMessage(), e);
            return false;
        }
    }

    private static final class TaskMoveOperation implements Serializable {
        private static final long serialVersionUID = -9102771449534398177L;

        @Nullable
        private final List<GridTask> tasks;
        private final int numberOfMoveTasks;
        @Nonnull
        private final GridNode destNode;
        @Nullable
        private final List<GridNode> toNodes;
        private final boolean isAsyncOps;

        TaskMoveOperation(int tasks, GridNode fromNode, List<GridNode> toNodes, boolean isAsyncOps) {
            this.tasks = null;
            this.numberOfMoveTasks = tasks;
            this.destNode = fromNode;
            this.toNodes = toNodes;
            this.isAsyncOps = isAsyncOps;
        }

        TaskMoveOperation(List<GridTask> tasks, List<GridNode> toNodes, boolean isAsyncOps) {
            this.tasks = tasks;
            this.numberOfMoveTasks = tasks.size();
            this.destNode = null;
            this.toNodes = toNodes;
            this.isAsyncOps = isAsyncOps;
        }

        boolean isAsyncOps() {
            return isAsyncOps;
        }

        List<GridTask> getTasks() {
            return tasks;
        }

        int getNumberOfMoveTasks() {
            return numberOfMoveTasks;
        }

        GridNode getFromNode() {
            return destNode;
        }

        List<GridNode> getDestinationNodes() {
            return toNodes;
        }
    }

    private static final class GridLocalTaskMoveJob extends GridJobBase<TaskMoveOperation, Boolean> {
        private static final long serialVersionUID = 8663230291630251507L;

        private boolean isAsync = false;
        private transient boolean suceed = true;

        @GridConfigResource
        private GridConfiguration config;

        @SuppressWarnings("unused")
        public GridLocalTaskMoveJob() {
            super();
        }

        @Override
        public boolean injectResources() {
            return true;
        }

        @Override
        public boolean isAsyncOps() {
            return isAsync;
        }

        public Map<GridTask, GridNode> map(GridRouter router, TaskMoveOperation ops) throws GridException {
            this.isAsync = ops.isAsyncOps();

            final List<GridTask> tasks = ops.getTasks();
            final List<GridNode> destNodes = ops.getDestinationNodes();

            final GridConfiguration conf = this.config;
            final GridNodeSelector selector = config.getNodeSelector();

            final Map<GridTask, GridNode> map = new IdentityHashMap<GridTask, GridNode>(tasks.size());
            for (GridTask task : tasks) {
                if (task.isFinished()) {
                    continue;
                }
                if (!task.getRelocatability().isRelocatable()) {
                    continue;
                }
                if (task.cancel()) {
                    GridNode node = selector.selectNode(destNodes, conf);
                    map.put(task, node);
                }
            }
            return map;
        }

        public GridTaskResultPolicy result(GridTaskResult result) throws GridException {
            final GridException error = result.getException();
            if (error != null) {
                if (LOG.isWarnEnabled()) {
                    LOG.warn(error);
                }
                this.suceed = false;
            }
            return GridTaskResultPolicy.CONTINUE;
        }

        public Boolean reduce() throws GridException {
            return suceed;
        }
    }

    public static final class GridTaskStealJob extends GridJobBase<TaskMoveOperation, Boolean> {
        private static final long serialVersionUID = 1293892419517866558L;

        private boolean isAsyncOps;
        private transient boolean suceed = true;

        @GridRegistryResource
        private transient GridResourceRegistry registry;

        public GridTaskStealJob() {
            super();
        }

        @Override
        public boolean isAsyncOps() {
            return isAsyncOps;
        }

        @Override
        public boolean injectResources() {
            return true;
        }

        @Override
        public GridNode getJobNode() {
            GridCommunicationManager communicator = registry.getCommunicationManager();
            GridNode node = communicator.getLocalNode();
            return node;
        }

        public Map<GridTask, GridNode> map(GridRouter router, TaskMoveOperation ops) throws GridException {
            this.isAsyncOps = ops.isAsyncOps();

            final List<GridNode> destNodes = ops.getDestinationNodes();
            final int destSize = destNodes.size();
            if (destSize == 0) {
                LOG.warn("No destination was specified for task-stealing");
                return Collections.emptyMap();
            }

            // step #1
            // steal tasks from the specified node
            GridNode fromNode = ops.getFromNode();
            int tasks = ops.getNumberOfMoveTasks();
            final GridTask[] stealedTasks = stealTasks(fromNode, tasks);

            // steps #2
            // send stealed tasks to destination nodes
            final int totalStealedTasks = stealedTasks.length;
            final int tasksPerNode = totalStealedTasks / destSize;
            final Map<GridTask, GridNode> map = new IdentityHashMap<GridTask, GridNode>(destSize);
            int i = 0;
            for (GridNode node : destNodes) {
                for (int j = 0; j < tasksPerNode; j++) {
                    map.put(stealedTasks[i++], node);
                }
            }
            for (int j = 0; i < totalStealedTasks; i++, j++) {
                GridNode node = destNodes.get(j);
                map.put(stealedTasks[i], node);
            }
            return map;
        }

        @Nullable
        private GridTask[] stealTasks(GridNode fromNode, int tasks) throws GridException {
            final GridCommunicationManager communicator = registry.getCommunicationManager();
            final SenderResponseTaskQueue responseQueue = registry.getTaskManager().getSenderResponseQueue();

            // register result queue
            BlockingQueue<GridTaskResult> resultQueue = new SynchronousQueue<GridTaskResult>();
            String jobId = "gridool_tasksteal" + responseQueue.hashCode();
            responseQueue.addResponseQueue(jobId, resultQueue);

            final GridTaskStealingTask stealTask = new GridTaskStealingTask(this, tasks);
            communicator.sendTaskRequest(stealTask, fromNode);

            // Receive a requested class
            final GridTaskResult result;
            try {
                result = resultQueue.take();
            } catch (InterruptedException e) {
                LOG.error(e);
                throw new GridException(e);
            }
            GridException error = result.getException();
            if (error != null) {
                throw error;
            }
            GridTask[] stealedTasks = result.getResult();
            return stealedTasks;
        }

        public GridTaskResultPolicy result(GridTaskResult result) throws GridException {
            final GridException error = result.getException();
            if (error != null) {
                if (LOG.isWarnEnabled()) {
                    LOG.warn(error);
                }
                this.suceed = false;
            }
            return GridTaskResultPolicy.CONTINUE;
        }

        public Boolean reduce() throws GridException {
            return suceed;
        }
    }

}