Package net.tomp2p.task

Source Code of net.tomp2p.task.TaskManager$Task

/*
* Copyright 2012 Thomas Bocek
*
* 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.
*/

package net.tomp2p.task;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import net.tomp2p.connection2.ConnectionBean;
import net.tomp2p.futures.BaseFutureAdapter;
import net.tomp2p.futures.FutureChannelCreator;
import net.tomp2p.futures.FutureResponse;
import net.tomp2p.p2p.Peer;
import net.tomp2p.peers.Number160;
import net.tomp2p.peers.Number320;
import net.tomp2p.peers.PeerAddress;
import net.tomp2p.rpc.DigestInfo;
import net.tomp2p.rpc.TaskRPC;
import net.tomp2p.storage.Data;
import net.tomp2p.task.TaskStatus.Status;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TaskManager {
    final private static Logger logger = LoggerFactory.getLogger(TaskManager.class);

    final private ConnectionBean connectionBean;

    final private Object lock = new Object();

    final private ThreadPoolExecutor executor;

    // may grow
    final private Map<Number320, Status> status = new HashMap<Number320, Status>();

    final private Map<Number320, String> exceptions = new HashMap<Number320, String>();

    final private Collection<TaskResultListener> listeners = new ArrayList<TaskResultListener>();

    private TaskRPC taskRPC;

    private class Task implements Runnable {
        private final Number160 taskId;

        private final Worker mapper;

        private final Map<Number160, Data> inputData;

        private final PeerAddress senderAddress;

        private final boolean sign;

        private final Peer peer;

        final Number320 taskKey;

        public Task(Peer peer, Number160 taskId, Worker mapper, Map<Number160, Data> inputData,
                PeerAddress senderAddress, boolean sign) {
            this.peer = peer;
            this.taskId = taskId;
            this.mapper = mapper;
            this.inputData = inputData;
            this.senderAddress = senderAddress;
            this.sign = sign;
            this.taskKey = new Number320(taskId, peer.getPeerID());
        }

        @Override
        public void run() {
            Thread.currentThread().setName("task-manager " + taskId);
            if (logger.isDebugEnabled()) {
                logger.debug("started task " + taskId + " which came from " + senderAddress);
            }

            synchronized (lock) {
                status.put(taskKey, Status.STARTED);
            }
            Map<Number160, Data> outputData = null;
            try {
                outputData = mapper.execute(peer, taskId, inputData);
            } catch (Exception e) {
                outputData = null;
                registerException(taskKey, e.toString());
            }
            synchronized (lock) {
                status.put(taskKey, Status.SUCCESS_RESULT_NOT_SENT);
            }
            final Map<Number160, Data> outputData2 = outputData;
            FutureChannelCreator futureChannelCreator = connectionBean.getConnectionReservation().reserve(1);
            futureChannelCreator.addListener(new BaseFutureAdapter<FutureChannelCreator>() {
                @Override
                public void operationComplete(final FutureChannelCreator futureChannelCreator) throws Exception {
                    if (futureChannelCreator.isSuccess()) {
                        FutureResponse futureResponse = getTaskRPC().sendResult(senderAddress,
                                futureChannelCreator.getChannelCreator(), taskId, outputData2,
                                peer.getPeerBean().getKeyPair(), false, sign);
                        futureResponse.addListener(new BaseFutureAdapter<FutureResponse>() {
                            @Override
                            public void operationComplete(FutureResponse future) throws Exception {
                                if (future.isSuccess()) {
                                    synchronized (lock) {
                                        status.put(taskKey, Status.SUCCESS_RESULT_SENT);
                                    }
                                } else {
                                    registerException(taskKey, "could not send result back");
                                }
                                connectionBean.getConnectionReservation().release(
                                        futureChannelCreator.getChannelCreator());
                            }
                        });
                    } else {
                        registerException(taskKey, "could not reserve connection");
                    }
                }
            });
        }
    }

    public TaskManager(ConnectionBean connectionBean, int threads) {
        this.connectionBean = connectionBean;
        this.executor = new ThreadPoolExecutor(threads, threads, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
    }

    public void addListener(TaskResultListener taskResultListener) {
        listeners.add(taskResultListener);
    }

    public void removeListener(TaskResultListener taskResultListener) {
        listeners.remove(taskResultListener);
    }

    public void notifyListeners(Number320 taskKey, Map<Number160, Data> dataMap) {
        for (TaskResultListener taskResultListener : listeners) {
            taskResultListener.taskReceived(taskKey, dataMap);
        }
    }

    public void init(TaskRPC taskRPC) {
        this.taskRPC = taskRPC;
    }

    public TaskRPC getTaskRPC() {
        if (taskRPC == null) {
            throw new IllegalStateException("init() was not called yet");
        }
        return taskRPC;
    }

    public TaskStatus taskStatus(Number320 taskKey) {
        TaskStatus statusResult = new TaskStatus();
        String exception;
        synchronized (lock) {
            exception = exceptions.get(taskKey);
        }
        if (exception != null) {
            statusResult.setFaildeReason(exception);
            statusResult.setStatus(TaskStatus.Status.FAILED);
            if (logger.isDebugEnabled()) {
                logger.debug("finished task failed for task with ID " + taskKey);
            }
            return statusResult;
        }

        int pos = 0;
        Task taskFound = null;
        for (Runnable runnable : executor.getQueue()) {
            Task task = (Task) runnable;
            if (task.taskKey.equals(taskKey)) {
                taskFound = task;
                break;
            }
            pos++;
        }
        if (taskFound != null) {
            statusResult.setQueuePosition(pos);
            statusResult.setStatus(TaskStatus.Status.QUEUE);
            if (logger.isDebugEnabled()) {
                logger.debug("finished task queue for task with ID " + taskKey);
            }
            return statusResult;
        }
        synchronized (lock) {
            statusResult.setStatus(status.get(taskKey));
        }
        if (logger.isDebugEnabled()) {
            logger.debug("finished task status for task with ID " + taskKey);
        }
        return statusResult;
    }

    public int submitTask(Peer peer, Number160 taskId, Worker mapper, Map<Number160, Data> data,
            PeerAddress senderAddress, boolean sign) {
        final Number320 taskKey = new Number320(taskId, peer.getPeerID());
        synchronized (lock) {
            status.put(taskKey, TaskStatus.Status.QUEUE);
        }
        Task task = new Task(peer, taskId, mapper, data, senderAddress, sign);
        executor.execute(task);
        return executor.getQueue().size();
    }

    private void registerException(Number320 taskKey, String string) {
        synchronized (lock) {
            exceptions.put(taskKey, string);
        }
    }

    public DigestInfo digest() {
        return new DigestInfo(executor.getQueue().size());
    }

    public void shutdown() {
        List<Runnable> jobs = executor.shutdownNow();
        if (jobs.size() > 0 && logger.isWarnEnabled()) {
            logger.warn("shutting down and not executing " + jobs.size() + " jobs");
        }
    }
}
TOP

Related Classes of net.tomp2p.task.TaskManager$Task

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.