Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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 io.trino.operator;
import com.google.common.collect.Iterators;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.errorprone.annotations.Immutable;
import jakarta.annotation.Nullable;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Optional;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import static java.util.Objects.requireNonNull;
public interface WorkProcessor
{
/**
* Call the method to progress the work.
* When this method returns true then the processor is either finished
* or has a result available via {@link WorkProcessor#getResult()}.
* When this method returns false then the processor is either
* blocked or has yielded.
*/
boolean process();
boolean isBlocked();
/**
* @return a blocked future when {@link WorkProcessor#isBlocked()} returned true.
*/
ListenableFuture getBlockedFuture();
/**
* @return true if the processor is finished. No more results are expected.
*/
boolean isFinished();
/**
* Get the result once the unit of work is done and the processor hasn't finished.
*/
T getResult();
/**
* Makes {@link WorkProcessor} yield when given {@code yieldSignal} is set. The processor is
* guaranteed to progress computations on subsequent {@link WorkProcessor#process()} calls
* even if {@code yieldSignal} is permanently on.
*/
default WorkProcessor yielding(BooleanSupplier yieldSignal)
{
return WorkProcessorUtils.yielding(this, yieldSignal);
}
default WorkProcessor blocking(Supplier> futureSupplier)
{
return WorkProcessorUtils.blocking(this, futureSupplier);
}
default WorkProcessor withProcessEntryMonitor(Runnable monitor)
{
return WorkProcessorUtils.processEntryMonitor(this, monitor);
}
default WorkProcessor withProcessStateMonitor(Consumer> monitor)
{
return WorkProcessorUtils.processStateMonitor(this, monitor);
}
default WorkProcessor finishWhen(BooleanSupplier finishSignal)
{
return WorkProcessorUtils.finishWhen(this, finishSignal);
}
default WorkProcessor flatMap(Function> mapper)
{
return WorkProcessorUtils.flatMap(this, mapper);
}
default WorkProcessor map(Function mapper)
{
return WorkProcessorUtils.map(this, mapper);
}
/**
* Flattens {@link WorkProcessor}s returned by transformation. Each {@link WorkProcessor} produced
* by transformation will be fully consumed before transformation is called again to produce more processors.
*/
default WorkProcessor flatTransform(Transformation> transformation)
{
return WorkProcessorUtils.flatTransform(this, transformation);
}
/**
* Transforms {@link WorkProcessor} using {@link Transformation}. {@link Transformation} instance will be dereferenced immediately after
* {@link WorkProcessor} is exhausted.
*/
default WorkProcessor transform(Transformation transformation)
{
return WorkProcessorUtils.transform(this, transformation);
}
default WorkProcessor transformProcessor(Function, WorkProcessor> transformation)
{
return transformation.apply(this);
}
/**
* Converts {@link WorkProcessor} into an {@link Iterator}. The iterator will throw {@link IllegalStateException} when underlying {@link WorkProcessor}
* yields or becomes blocked. {@link WorkProcessor} instance will be dereferenced immediately after iterator is finished.
*/
default Iterator iterator()
{
return WorkProcessorUtils.iteratorFrom(this);
}
/**
* Converts {@link WorkProcessor} into an yielding {@link Iterator}. The iterator will throw {@link IllegalStateException} when underlying {@link WorkProcessor}
* becomes blocked. {@link WorkProcessor} instance will be dereferenced immediately after iterator is exhausted.
*/
default Iterator> yieldingIterator()
{
return WorkProcessorUtils.yieldingIteratorFrom(this);
}
static WorkProcessor flatten(WorkProcessor> processor)
{
return WorkProcessorUtils.flatten(processor);
}
@SafeVarargs
static WorkProcessor of(T... elements)
{
return fromIterator(Iterators.forArray(elements));
}
static WorkProcessor fromIterable(Iterable iterable)
{
return WorkProcessorUtils.fromIterator(iterable.iterator());
}
static WorkProcessor fromIterator(Iterator iterator)
{
return WorkProcessorUtils.fromIterator(iterator);
}
/**
* Creates {@link WorkProcessor} from {@link Process}. {@link Process} instance will be dereferenced immediately after {@link WorkProcessor} is finished.
*/
static WorkProcessor create(Process process)
{
return WorkProcessorUtils.create(process);
}
static WorkProcessor mergeSorted(Iterable> processorIterable, Comparator comparator)
{
return WorkProcessorUtils.mergeSorted(processorIterable, comparator);
}
interface Transformation
{
/**
* Processes input elements and returns current transformation state.
*
* @param element an element to be transformed. Will be null
* when there are no more elements. In such case transformation should
* finish processing and flush any remaining data.
* @return the current transformation state, optionally bearing a result
* @see TransformationState#needsMoreData()
* @see TransformationState#blocked(ListenableFuture)
* @see TransformationState#yielded()
* @see TransformationState#ofResult(Object)
* @see TransformationState#ofResult(Object, boolean)
* @see TransformationState#finished()
*/
TransformationState process(@Nullable T element);
}
interface Process
{
/**
* Does some work and returns current state.
*
* @return the current state, optionally bearing a result
* @see ProcessState#blocked(ListenableFuture)
* @see ProcessState#yielded()
* @see ProcessState#ofResult(Object)
* @see ProcessState#finished()
*/
ProcessState process();
}
@Immutable
final class TransformationState
{
private static final TransformationState> NEEDS_MORE_DATA_STATE = new TransformationState<>(Type.NEEDS_MORE_DATA, true, null, null);
private static final TransformationState> YIELD_STATE = new TransformationState<>(Type.YIELD, false, null, null);
private static final TransformationState> FINISHED_STATE = new TransformationState<>(Type.FINISHED, false, null, null);
enum Type
{
NEEDS_MORE_DATA,
BLOCKED,
YIELD,
RESULT,
FINISHED
}
private final Type type;
private final boolean needsMoreData;
@Nullable
private final T result;
@Nullable
private final ListenableFuture blocked;
private TransformationState(Type type, boolean needsMoreData, @Nullable T result, @Nullable ListenableFuture blocked)
{
this.type = requireNonNull(type, "type is null");
this.needsMoreData = needsMoreData;
this.result = result;
this.blocked = blocked;
}
/**
* Signals that transformation requires more data in order to continue and no result has been produced.
* {@link #process()} will be called with a new input element or with {@link Optional#empty()} if there
* are no more elements.
*/
@SuppressWarnings("unchecked")
public static TransformationState needsMoreData()
{
return (TransformationState) NEEDS_MORE_DATA_STATE;
}
/**
* Signals that transformation is blocked. {@link #process()} will be called again with the same input
* element after {@code blocked} future is done.
*/
public static TransformationState blocked(ListenableFuture blocked)
{
return new TransformationState<>(Type.BLOCKED, false, null, requireNonNull(blocked, "blocked is null"));
}
/**
* Signals that transformation has yielded. {@link #process()} will be called again with the same input element.
*/
@SuppressWarnings("unchecked")
public static TransformationState yielded()
{
return (TransformationState) YIELD_STATE;
}
/**
* Signals that transformation has produced a result from its input. {@link #process()} will be called again with
* a new element or with {@link Optional#empty()} if there are no more elements.
*/
public static TransformationState ofResult(T result)
{
return ofResult(result, true);
}
/**
* Signals that transformation has produced a result. If {@code needsMoreData}, {@link #process()} will be called again
* with a new element (or with {@link Optional#empty()} if there are no more elements). If not @{code needsMoreData},
* {@link #process()} will be called again with the same element.
*/
public static TransformationState ofResult(T result, boolean needsMoreData)
{
return new TransformationState<>(Type.RESULT, needsMoreData, requireNonNull(result, "result is null"), null);
}
/**
* Signals that transformation has finished. {@link #process()} method will not be called again.
*/
@SuppressWarnings("unchecked")
public static TransformationState finished()
{
return (TransformationState) FINISHED_STATE;
}
Type getType()
{
return type;
}
boolean isNeedsMoreData()
{
return needsMoreData;
}
@Nullable
T getResult()
{
return result;
}
@Nullable
ListenableFuture getBlocked()
{
return blocked;
}
}
@Immutable
final class ProcessState
{
private static final ProcessState> YIELD_STATE = new ProcessState<>(Type.YIELD, null, null);
private static final ProcessState> FINISHED_STATE = new ProcessState<>(Type.FINISHED, null, null);
public enum Type
{
BLOCKED,
YIELD,
RESULT,
FINISHED
}
private final Type type;
@Nullable
private final T result;
@Nullable
private final ListenableFuture blocked;
private ProcessState(Type type, @Nullable T result, @Nullable ListenableFuture blocked)
{
this.type = requireNonNull(type, "type is null");
this.result = result;
this.blocked = blocked;
}
/**
* Signals that process is blocked. {@link #process()} will be called again after {@code blocked} future is done.
*/
public static ProcessState blocked(ListenableFuture blocked)
{
return new ProcessState<>(Type.BLOCKED, null, requireNonNull(blocked, "blocked is null"));
}
/**
* Signals that process has yielded. {@link #process()} will be called again later.
*/
@SuppressWarnings("unchecked")
public static ProcessState yielded()
{
return (ProcessState) YIELD_STATE;
}
/**
* Signals that process has produced a result. {@link #process()} will be called again.
*/
public static ProcessState ofResult(T result)
{
return new ProcessState<>(Type.RESULT, requireNonNull(result, "result is null"), null);
}
/**
* Signals that process has finished. {@link #process()} method will not be called again.
*/
@SuppressWarnings("unchecked")
public static ProcessState finished()
{
return (ProcessState) FINISHED_STATE;
}
public Type getType()
{
return type;
}
@Nullable
public T getResult()
{
return result;
}
@Nullable
public ListenableFuture getBlocked()
{
return blocked;
}
}
}