
oracle.kv.impl.async.NullDialogStart Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of oracle-nosql-server Show documentation
Show all versions of oracle-nosql-server Show documentation
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