Package org.apache.marmotta.platform.core.services.task

Source Code of org.apache.marmotta.platform.core.services.task.TaskManagerServiceImpl$ThreadWatchdog

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.marmotta.platform.core.services.task;

import org.apache.marmotta.platform.core.api.task.Task;
import org.apache.marmotta.platform.core.api.task.TaskInfo;
import org.apache.marmotta.platform.core.api.task.TaskManagerService;

import org.apache.marmotta.commons.util.HashUtils;
import org.slf4j.Logger;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.WeakHashMap;

@ApplicationScoped
public class TaskManagerServiceImpl implements TaskManagerService {

    private static final String                        DEFAULT_GROUP = "default";

    private final WeakHashMap<Thread, Stack<TaskImpl>> tasks;

    private final ThreadWatchdog watchdog;

    @Inject
    private Logger                                     log;

    @Inject
    public TaskManagerServiceImpl() {
        tasks = new WeakHashMap<Thread, Stack<TaskImpl>>();
        watchdog = new ThreadWatchdog(15000);
    }

    @PostConstruct
    public void startup() {
        watchdog.start();
    }

    /* (non-Javadoc)
     * @see xx.test.taks.TaskManagerService#endTask(xx.test.taks.TaskInfo)
     */
    @Override
    public void endTask(TaskInfo task) {
        final Stack<TaskImpl> stack = getStack();
        if (stack.contains(task)) {
            while (!stack.isEmpty()) {
                Task t = stack.pop();
                if (t.equals(task)) {
                    log.debug("Ending task {}.{}", t.getGroup(), t.getName());
                    break;
                } else {
                    log.debug("Ending task {}.{} because it's a sub-task", t.getGroup(), t.getName());
                    t.endTask();
                }
            }
            if (!stack.isEmpty()) {
                stack.peek().subTaskEnded();
            }
        } else {
            log.debug("Not ending task {} because thread {} is not the owner", task.getName(), Thread.currentThread().getName());
        }
        if (stack.isEmpty()) {
            tasks.remove(Thread.currentThread());
        }
    }

    /* (non-Javadoc)
     * @see xx.test.taks.TaskManagerService#getTasks()
     */
    @Override
    public List<TaskInfo> getTasks() {
        LinkedList<TaskInfo> ts = new LinkedList<TaskInfo>();
        for (Stack<TaskImpl> stack : tasks.values()) {
            ts.addAll(stack);
        }
        return Collections.unmodifiableList(ts);
    }

    /* (non-Javadoc)
     * @see xx.test.taks.TaskManagerService#getTask()
     */
    @Override
    public Task getTask() {
        return createTask(Thread.currentThread().getName());
    }

    /* (non-Javadoc)
     * @see xx.test.taks.TaskManagerService#createTask(java.lang.String)
     */
    @Override
    public Task createTask(String name, String group) {
        final Stack<TaskImpl> stack = getStack();
        final Task task;
        if (stack.isEmpty())
            return createSubTask(name, group);
        else {
            task = stack.peek();
            task.updateName(name);
            if (group != null) {
                task.updateGroup(group);
            }
        }
        return task;
    }

    @Override
    public Task createTask(String string) {
        return createTask(string, null);
    }

    /* (non-Javadoc)
     * @see xx.test.taks.TaskManagerService#createSubTask(java.lang.String)
     */
    @Override
    public Task createSubTask(String name) {
        return createSubTask(name, null);
    }

    @Override
    public Task createSubTask(String name, String group) {
        final Stack<TaskImpl> stack = getStack();
        final TaskImpl task;
        synchronized (stack) {
            task = new TaskImpl(this, createUUID(), name, group != null ? group : DEFAULT_GROUP);
            if (!stack.isEmpty()) {
                stack.peek().subTastStarting(task);
            }
            stack.push(task);
        }
        return task;
    }

    private String createUUID() {
        final Thread t = Thread.currentThread();
        String string = String.format("%d: %s %tR", t.getId(), t.getName(), new Date());
        return HashUtils.md5sum(string);
    }

    private Stack<TaskImpl> getStack() {
        final Thread key = Thread.currentThread();
        Stack<TaskImpl> stack = tasks.get(key);
        if (stack == null) {
            stack = new Stack<TaskImpl>();
            tasks.put(key, stack);
        }
        return stack;
    }

    /* (non-Javadoc)
     * @see xx.test.taks.TaskManagerService#getTasksByGroup()
     */
    @Override
    public Map<String, List<TaskInfo>> getTasksByGroup() {
        Map<String, List<TaskInfo>> result = new LinkedHashMap<String, List<TaskInfo>>();

        for (TaskInfo task : getTasks()) {
            final String group = task.getGroup();
            List<TaskInfo> list = result.get(group);
            if (list == null) {
                list = new LinkedList<TaskInfo>();
                result.put(group, list);
            }
            list.add(task);
        }

        return result;
    }

    /* (non-Javadoc)
     * @see xx.test.taks.TaskManagerService#getTasksByThread()
     */
    @Override
    public Map<WeakReference<Thread>, Stack<TaskInfo>> getTasksByThread() {
        Map<WeakReference<Thread>, Stack<TaskInfo>> result = new LinkedHashMap<WeakReference<Thread>, Stack<TaskInfo>>();

        for (Map.Entry<Thread, Stack<TaskImpl>> e : tasks.entrySet()) {
            Stack<TaskInfo> list = new Stack<TaskInfo>();
            list.addAll(e.getValue());
            result.put(new WeakReference<Thread>(e.getKey()), list);
        }

        return result;
    }

    private class ThreadWatchdog extends Thread {

        private final long millis;
        private boolean running;

        public ThreadWatchdog(long millis) {
            super("TaskThreadWatchdog");
            this.millis = millis;
        }

        @Override
        public void run() {
            running = true;
            log.trace("Watchdog: starting up");
            final Task task = getTask();
            int count = 0;
            while (running) {
                task.updateMessage("cleaning up");
                task.updateProgress(++count);
                try {
                    HashSet<Thread> dead = new HashSet<Thread>();
                    for (Thread t : tasks.keySet()) {
                        if (!t.isAlive()) {
                            dead.add(t);
                        }
                    }
                    for (Thread t : dead) {
                        log.debug("Watchdog: cleaning up dead thread " + t.getName());
                        tasks.remove(t);
                        t = null;
                    }
                    dead.clear();
                    dead = null;
                    task.updateMessage("sleeping");
                    synchronized (ThreadWatchdog.this) {
                        this.wait(millis);
                    }
                } catch (InterruptedException e) {
                    // ignore
                }
            }
            task.endTask();
            log.trace("Watchdog: shutdown");
        }

        public void shutdown() {
            running = false;
            synchronized (this) {
                this.notify();
            }
        }

    }

    @PreDestroy
    public void shutdown() {
        watchdog.shutdown();
    }

}
TOP

Related Classes of org.apache.marmotta.platform.core.services.task.TaskManagerServiceImpl$ThreadWatchdog

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.