com.seovic.coherence.util.concurrent.ClusteredExecutorService.java Source code

Java tutorial

Introduction

Here is the source code for com.seovic.coherence.util.concurrent.ClusteredExecutorService.java

Source

/*
 * Copyright 2009 Aleksandar Seovic
 *
 * 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 com.seovic.coherence.util.concurrent;

import org.springframework.core.task.TaskExecutor;

import com.tangosol.net.InvocationService;
import com.tangosol.net.CacheFactory;
import com.tangosol.net.MemberListener;
import com.tangosol.net.Member;
import com.tangosol.net.AbstractInvocable;
import com.tangosol.net.MemberEvent;
import com.tangosol.net.InvocationObserver;

import com.tangosol.util.Base;

import java.util.concurrent.Executor;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.CountDownLatch;

import java.util.Set;
import java.util.Iterator;
import java.util.Collections;
import java.util.List;

import java.io.Serializable;

/**
 * ExecutorService implementation that parallelizes task execution across the
 * cluster nodes using Invocation Service.
 * 
 * @author Aleksandar Seovic  2009.11.02
 */
@SuppressWarnings({ "unchecked" })
public class ClusteredExecutorService extends AbstractExecutorService
        implements TaskExecutor, Executor, MemberListener {
    // ---- constructors and initializers -----------------------------------

    /**
     * Construct <tt>ClusteredExecutorService</tt> instance using default
     * invocation service ("InvocationService").
     */
    public ClusteredExecutorService() {
        this("InvocationService");
    }

    /**
     * Construct <tt>ClusteredExecutorService</tt> instance.
     *
     * @param invocationServiceName  the name of the invocation service to use
     */
    public ClusteredExecutorService(String invocationServiceName) {
        m_invocationServiceName = invocationServiceName;
        initialize();
    }

    /**
     * Initialize this executor service.
     */
    protected synchronized void initialize() {
        String invocationServiceName = m_invocationServiceName;
        m_invocationService = (InvocationService) CacheFactory.getService(invocationServiceName);
        if (m_invocationService == null) {
            throw new IllegalArgumentException(
                    "Invocation service [" + invocationServiceName + "] is not defined.");
        }

        m_serviceMembers = m_invocationService.getInfo().getServiceMembers();
        m_memberIterator = m_serviceMembers.iterator();
        m_invocationService.addMemberListener(this);
    }

    // ---- Executor implementation -----------------------------------------

    /**
     * Executes the given command at some time in the future.
     *
     * @param command  the runnable task
     */
    public void execute(Runnable command) {
        if (!(command instanceof ClusteredFutureTask)) {
            command = new ClusteredFutureTask<Object>(command, null);
        }
        command.run();
    }

    // ---- ExecutorService implementation ----------------------------------

    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new ClusteredFutureTask<T>(runnable, value);
    }

    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new ClusteredFutureTask<T>(callable);
    }

    public void shutdown() {
    }

    public List<Runnable> shutdownNow() {
        return null;
    }

    public boolean isShutdown() {
        return false;
    }

    public boolean isTerminated() {
        return false;
    }

    public boolean awaitTermination(long l, TimeUnit timeUnit) throws InterruptedException {
        return false;
    }

    // ---- MemberListener implementation -----------------------------------

    public void memberJoined(MemberEvent memberEvent) {
        addMember(memberEvent.getMember());
    }

    public void memberLeaving(MemberEvent memberEvent) {
        removeMember(memberEvent.getMember());
    }

    public void memberLeft(MemberEvent memberEvent) {
        removeMember(memberEvent.getMember());
    }

    // ---- helper methods --------------------------------------------------

    /**
     * Return the member that should execute submitted command.
     *
     * @return the member to execute submitted command on
     */
    protected synchronized Member getExecutionMember() {
        Iterator<Member> it = m_memberIterator;
        if (it == null || !it.hasNext()) {
            m_memberIterator = it = m_serviceMembers.iterator();
        }
        return it.next();
    }

    /**
     * Add member.
     *
     * @param member  member to add
     */
    protected synchronized void addMember(Member member) {
        m_serviceMembers.add(member);
        m_memberIterator = m_serviceMembers.iterator();
    }

    /**
     * Remove member.
     * 
     * @param member  member to remove
     */
    protected synchronized void removeMember(Member member) {
        m_serviceMembers.remove(member);
        m_memberIterator = m_serviceMembers.iterator();
    }

    // ---- inner class: CallableAdapter ------------------------------------

    private static class CallableAdapter<T> implements Callable<T>, Serializable {
        // ---- constructors --------------------------------------------

        private CallableAdapter(Runnable runnable, T result) {
            m_runnable = runnable;
            m_result = result;
        }

        // ---- Callable implementation ---------------------------------

        public T call() throws Exception {
            m_runnable.run();
            return m_result;
        }

        // ---- data members --------------------------------------------

        private final Runnable m_runnable;
        private final T m_result;
    }

    // ---- inner class: InvocableAdapter -----------------------------------

    private static class InvocableAdapter<T> extends AbstractInvocable implements Serializable {
        public InvocableAdapter(Callable<T> callable) {
            m_callable = callable;
        }

        public void run() {
            try {
                m_result = m_callable.call();
            } catch (Exception e) {
                throw Base.ensureRuntimeException(e);
            }
        }

        public Object getResult() {
            return m_result;
        }

        private final Callable<T> m_callable;
        private volatile T m_result;
    }

    // ---- inner class: InvocableAdapter -----------------------------------

    private class ClusteredFutureTask<T> implements RunnableFuture<T>, InvocationObserver {
        // ---- constructors --------------------------------------------

        public ClusteredFutureTask(Callable<T> callable) {
            m_callable = callable;
            m_latch = new CountDownLatch(1);
        }

        public ClusteredFutureTask(Runnable runnable, T result) {
            this(new CallableAdapter<T>(runnable, result));
        }

        // ---- RunnableFuture implementation ---------------------------

        public void run() {
            m_invocationService.execute(new InvocableAdapter(m_callable),
                    Collections.singleton(getExecutionMember()), this);
        }

        public boolean cancel(boolean b) {
            return false;
        }

        public boolean isCancelled() {
            return false;
        }

        public boolean isDone() {
            return m_fDone;
        }

        public T get() throws InterruptedException, ExecutionException {
            m_latch.await();
            return getInternal();
        }

        public T get(long l, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
            if (!m_latch.await(l, timeUnit)) {
                throw new TimeoutException();
            }

            return getInternal();
        }

        protected T getInternal() throws ExecutionException {
            if (m_exception != null) {
                throw new ExecutionException(m_exception);
            }
            return m_result;
        }

        // ---- InvocationObserver implementation -----------------------

        public void memberCompleted(Member member, Object result) {
            m_result = (T) result;
            m_fDone = true;
            m_latch.countDown();
        }

        public void memberFailed(Member member, Throwable throwable) {
            m_exception = throwable;
            m_fDone = true;
            m_latch.countDown();
        }

        public void memberLeft(Member member) {
            m_exception = new MemberLeftException(member);
            m_fDone = true;
            m_latch.countDown();
        }

        public void invocationCompleted() {
        }

        // ---- data members --------------------------------------------

        private final Callable<T> m_callable;
        private final CountDownLatch m_latch;
        private volatile T m_result;
        private volatile Throwable m_exception;
        private volatile boolean m_fDone;
    }

    // ---- data members ----------------------------------------------------

    /**
     * The name of the invocation service to use.
     */
    private final String m_invocationServiceName;

    /**
     * The invocation service to use.
     */
    private volatile InvocationService m_invocationService;

    /**
     * A set of members that can be used to execute tasks.
     */
    private volatile Set<Member> m_serviceMembers;

    /**
     * Member set iterator.
     */
    private volatile Iterator<Member> m_memberIterator;
}