All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oracle.kv.impl.async.NullDialogStart Maven / Gradle / Ivy

Go to download

NoSQL Database Server - supplies build and runtime support for the server (store) side of the Oracle NoSQL Database.

The newest version!
/*-
 * Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle NoSQL
 * Database made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle NoSQL Database for a copy of the license and
 * additional information.
 */

package oracle.kv.impl.async;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import oracle.kv.impl.util.ObjectUtil;
/**
 * Helper class to quickly fail a dialog upon its start.
 */
public class NullDialogStart {

    private static final ScheduledExecutorService nullExecutor =
        new NullExecutor();
    private static final NullContext nullContext = new NullContext();

    /**
     * A thread local flag to indicate a fail dialog procedure is in progress.
     *
     * This is necessary to prevent too much recursion, i.e., upper layer can
     * start new dialogs in onAbort which will likely to fail again.
     */
    private static final ThreadLocal failingDialog =
        ThreadLocal.withInitial(() -> false);

    /**
     * Fails the dialog.
     *
     * @param handler the dialog handler
     * @param cause the cause of the fail
     * @param executor an executor to do the failing task if the upper layer
     * starts new dialog in onAbort
     */
    public static void fail(final DialogHandler handler,
                            final Throwable cause,
                            final ExecutorService executor) {
        ObjectUtil.checkNull("executor", executor);
        if (!failingDialog.get()) {
            doFail(handler, cause);
            return;
        }
        if (executor != null) {
            try {
                executor.submit(() -> doFail(handler, cause));
                return;
            } catch(RejectedExecutionException e) {
            }
        }
        /*
         * That didn't work, which probably means there is a race condition
         * during store shutdown. We cannot create a separate new thread due to
         * the promise that DialogHandler callbacks are run in the same thread.
         * Plus, the caller should not recurse when we are shutting down.
         * Therefore, just throw an exception.
         */
        throw new IllegalStateException(
                      String.format("Detected recursion inside " +
                                    "the onAbort method of handler [%s] " +
                                    "for cause [%s] " +
                                    "when the executor is unavailable",
                                    handler, cause));
    }

    private static void doFail(DialogHandler handler,
                               Throwable cause) {
        failingDialog.set(true);
        try {
            handler.onStart(nullContext, true);
        } finally {
            try {
                handler.onAbort(nullContext, cause);
            } catch (Throwable t) {
                /*
                 * There is nothing we can do here. If the problem is
                 * persistent, it will be logged when the dialog is actually
                 * started.
                 */
            }
            failingDialog.set(false);
        }
    }

    /**
     * A null context provided to the failed dialog.
     */
    private static class NullContext implements DialogContext {

        @Override
        public boolean write(MessageOutput mesg, boolean finished) {
            return false;
        }

        @Override
        public MessageInput read() {
            return null;
        }

        @Override
        public long getDialogId() {
            return 0;
        }

        @Override
        public long getConnectionId() {
            return 0;
        }

        @Override
        public NetworkAddress getRemoteAddress() {
            return null;
        }

        @Override
        public ScheduledExecutorService getSchedExecService() {
            return nullExecutor;
        }

        @Override
        public String toString() {
            return "NullContext";
        }
    }

    /**
     * A null scheduled executor service provided to the null context.
     */
    private static class NullExecutor
            extends AbstractExecutorService
            implements ScheduledExecutorService {

        @Override
        public boolean awaitTermination(long timeout, TimeUnit unit) {
            return true;
        }

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

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

        @Override
        public void shutdown() {
            return;
        }

        @Override
        public List shutdownNow() {
            return Collections.emptyList();
        }

        @Override
        public void execute(Runnable command) {
            throw new RejectedExecutionException();
        }

        @Override
        public  ScheduledFuture schedule(Callable callable,
                                               long delay,
                                               TimeUnit unit) {
            throw new RejectedExecutionException();
        }

        @Override
        public ScheduledFuture schedule(Runnable command,
                                           long delay,
                                           TimeUnit unit) {
            throw new RejectedExecutionException();
        }

        @Override
        public ScheduledFuture scheduleAtFixedRate(Runnable command,
                                                      long initialDelay,
                                                      long period,
                                                      TimeUnit unit) {
            throw new RejectedExecutionException();
        }

        @Override
        public ScheduledFuture scheduleWithFixedDelay(Runnable command,
                                                         long initialDelay,
                                                         long delay,
                                                         TimeUnit unit) {
            throw new RejectedExecutionException();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy