package com.hazelcast.examples.helper;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.instance.HazelcastInstanceProxy;
import com.hazelcast.nio.ConnectionManager;
import com.hazelcast.util.EmptyStatement;
import com.hazelcast.util.ExceptionUtil;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import static com.hazelcast.examples.helper.HazelcastUtils.getNode;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
/**
* Utils class for common methods.
*/
public final class CommonUtils {
private static final Field ORIGINAL_FIELD;
private static final int ASSERT_EVENTUALLY_TIMEOUT = 120;
static {
try {
ORIGINAL_FIELD = HazelcastInstanceProxy.class.getDeclaredField("original");
ORIGINAL_FIELD.setAccessible(true);
} catch (Throwable t) {
throw new IllegalStateException("Unable to get `original` field in `HazelcastInstanceProxy`!", t);
}
}
private CommonUtils() {
}
public static String generateRandomString(int length) {
StringBuilder sb = new StringBuilder(length);
Random random = new Random();
for (int i = 0; i < length; i++) {
char character = (char) (random.nextInt(26) + 'a');
sb.append(character);
}
return sb.toString();
}
public static void assertTrue(String message, boolean condition) {
if (!condition) {
if (message == null) {
throw new AssertionError();
} else {
throw new AssertionError(message);
}
}
}
public static void assertEquals(Object expected, Object actual) {
assertEquals(null, expected, actual);
}
public static void assertEquals(String message, Object expected, Object actual) {
if (!equalsRegardingNull(expected, actual)) {
failNotEquals(message, expected, actual);
}
}
private static boolean equalsRegardingNull(Object expected, Object actual) {
if (expected == null) {
return actual == null;
}
return isEquals(expected, actual);
}
private static boolean isEquals(Object expected, Object actual) {
return expected.equals(actual);
}
private static void failNotEquals(String message, Object expected, Object actual) {
throw new AssertionError(format(message, expected, actual));
}
private static String format(String message, Object expected, Object actual) {
String formatted = "";
if (message != null && !message.equals("")) {
formatted = message + " ";
}
String expectedString = String.valueOf(expected);
String actualString = String.valueOf(actual);
if (expectedString.equals(actualString)) {
return formatted + "expected: "
+ formatClassAndValue(expected, expectedString)
+ " but was: " + formatClassAndValue(actual, actualString);
} else {
return formatted + "expected:<" + expectedString + "> but was:<" + actualString + ">";
}
}
private static String formatClassAndValue(Object value, String valueString) {
String className = value == null ? "null" : value.getClass().getName();
return className + "<" + valueString + ">";
}
public static void sleepSeconds(int seconds) {
try {
SECONDS.sleep(seconds);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public static boolean sleepMillis(int millis) {
try {
MILLISECONDS.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
return true;
}
public static void sleepAtLeastMillis(long sleepFor) {
boolean interrupted = false;
try {
long remainingNanos = MILLISECONDS.toNanos(sleepFor);
long sleepUntil = System.nanoTime() + remainingNanos;
while (remainingNanos > 0) {
try {
NANOSECONDS.sleep(remainingNanos);
} catch (InterruptedException e) {
interrupted = true;
} finally {
remainingNanos = sleepUntil - System.nanoTime();
}
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}
public static void assertClusterSize(int expectedSize, HazelcastInstance instance) {
int clusterSize = instance.getCluster().getMembers().size();
if (expectedSize != clusterSize) {
ConnectionManager connectionManager = getNode(instance).getConnectionManager();
int activeConnectionCount = connectionManager.getActiveConnectionCount();
throw new AssertionError(String.format("Cluster size is not correct. Expected: %d Actual: %d %s",
expectedSize,
clusterSize,
"ActiveConnectionCount: " + activeConnectionCount));
}
}
public static void assertClusterSizeEventually(final int expectedSize, final HazelcastInstance instance) {
assertTrueEventually(new Runnable() {
@Override
public void run() {
assertClusterSize(expectedSize, instance);
}
}, ASSERT_EVENTUALLY_TIMEOUT);
}
public static void assertOpenEventually(CountDownLatch latch) {
assertOpenEventually(null, latch);
}
public static void assertOpenEventually(String message, CountDownLatch latch) {
try {
boolean completed = latch.await(ASSERT_EVENTUALLY_TIMEOUT, SECONDS);
if (message == null) {
assertTrue(String.format("CountDownLatch failed to complete within %d seconds , count left: %d",
ASSERT_EVENTUALLY_TIMEOUT,
latch.getCount()),
completed);
} else {
assertTrue(String.format("%s, failed to complete within %d seconds , count left: %d",
message,
ASSERT_EVENTUALLY_TIMEOUT,
latch.getCount()),
completed);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public static void assertTrueEventually(Runnable task, long timeoutSeconds) {
try {
AssertionError error = null;
// we are going to check 5 times a second
long iterations = timeoutSeconds * 5;
int sleepMillis = 200;
for (int i = 0; i < iterations; i++) {
try {
try {
task.run();
} catch (Exception e) {
throw new RuntimeException(e);
}
return;
} catch (AssertionError e) {
error = e;
}
sleepMillis(sleepMillis);
}
throw error;
} catch (Throwable t) {
throw ExceptionUtil.rethrow(t);
}
}
public static void closeQuietly(Closeable closeable) {
if (closeable == null) {
return;
}
try {
closeable.close();
} catch (IOException ignored) {
EmptyStatement.ignore(ignored);
}
}
}