package org.infinispan.counter.util; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; import org.infinispan.commons.api.functional.Param; import org.infinispan.counter.api.CounterState; import org.infinispan.counter.api.Storage; import org.infinispan.counter.exception.CounterException; /** * Utility methods. * * @author Pedro Ruivo * @since 9.0 */ public final class Utils { private Utils() { } /** * Checks if the value is inside the boundaries. * * @param lowerBound the lower bound. * @param value the value to check. * @param upperBound the upper bound. * @return {@code true} if the value is inside the boundaries, {@code false} otherwise. */ public static boolean isValid(long lowerBound, long value, long upperBound) { return lowerBound > value || value > upperBound; } /** * Calculates the {@link CounterState} to use based on the value and the boundaries. * <p> * If the value is less than the lower bound, {@link CounterState#LOWER_BOUND_REACHED} is returned. On other hand, if * the value is higher than the upper bound, {@link CounterState#UPPER_BOUND_REACHED} is returned. Otherwise, {@link * CounterState#VALID} is returned. * * @param value the value to check. * @param lowerBound the lower bound. * @param upperBound the upper bound. * @return the {@link CounterState}. */ public static CounterState calculateState(long value, long lowerBound, long upperBound) { if (value < lowerBound) { return CounterState.LOWER_BOUND_REACHED; } else if (value > upperBound) { return CounterState.UPPER_BOUND_REACHED; } return CounterState.VALID; } /** * @param number the number of check. It must be positive. * @return the next round-up power of two based on the number. */ public static int nextPowerOfTwo(int number) { return 32 - Integer.numberOfLeadingZeros(number - 1); } /** * Returns a {@link CounterException} with the throwable. */ public static CounterException rethrowAsCounterException(Throwable throwable) { if (throwable instanceof CounterException) { return (CounterException) throwable; } else if (throwable instanceof ExecutionException || throwable instanceof CompletionException) { return rethrowAsCounterException(throwable.getCause()); } else { return new CounterException(throwable); } } /** * Awaits for the counter operation and throws any exception as {@link CounterException}. */ public static <T> T awaitCounterOperation(CompletableFuture<T> future) { try { return future.get(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw rethrowAsCounterException(e); } catch (ExecutionException e) { throw rethrowAsCounterException(e); } } public static Param.PersistenceMode getPersistenceMode(Storage storage) { switch (storage) { case PERSISTENT: return Param.PersistenceMode.PERSIST; case VOLATILE: return Param.PersistenceMode.SKIP; default: throw new IllegalStateException("[should never happen] unknown storage " + storage); } } }