com.arangodb.shaded.vertx.core.shareddata.impl.SharedDataImpl Maven / Gradle / Ivy
/*
* Copyright (c) 2011-2022 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package com.arangodb.shaded.vertx.core.shareddata.impl;
import com.arangodb.shaded.vertx.core.AsyncResult;
import com.arangodb.shaded.vertx.core.Future;
import com.arangodb.shaded.vertx.core.Handler;
import com.arangodb.shaded.vertx.core.Promise;
import com.arangodb.shaded.vertx.core.impl.Arguments;
import com.arangodb.shaded.vertx.core.impl.ContextInternal;
import com.arangodb.shaded.vertx.core.impl.VertxInternal;
import com.arangodb.shaded.vertx.core.shareddata.*;
import com.arangodb.shaded.vertx.core.spi.cluster.ClusterManager;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @author Tim Fox
*/
public class SharedDataImpl implements SharedData {
private static final long DEFAULT_LOCK_TIMEOUT = 10 * 1000;
private final VertxInternal vertx;
private final ClusterManager clusterManager;
private final LocalAsyncLocks localAsyncLocks;
private final ConcurrentMap> localAsyncMaps = new ConcurrentHashMap<>();
private final ConcurrentMap localCounters = new ConcurrentHashMap<>();
private final ConcurrentMap> localMaps = new ConcurrentHashMap<>();
public SharedDataImpl(VertxInternal vertx, ClusterManager clusterManager) {
this.vertx = vertx;
this.clusterManager = clusterManager;
localAsyncLocks = new LocalAsyncLocks();
}
@Override
public void getClusterWideMap(String name, Handler>> resultHandler) {
Objects.requireNonNull(resultHandler, "resultHandler");
this.getClusterWideMap(name).onComplete(resultHandler);
}
@Override
public Future> getClusterWideMap(String name) {
Objects.requireNonNull(name, "name");
if (clusterManager == null) {
throw new IllegalStateException("Can't get cluster wide map if not clustered");
}
Promise> promise = vertx.promise();
clusterManager.getAsyncMap(name, promise);
return promise.future().map(WrappedAsyncMap::new);
}
@Override
public void getAsyncMap(String name, Handler>> resultHandler) {
Objects.requireNonNull(resultHandler, "resultHandler");
this.getAsyncMap(name).onComplete(resultHandler);
}
@Override
public Future> getAsyncMap(String name) {
Objects.requireNonNull(name, "name");
if (clusterManager == null) {
return getLocalAsyncMap(name);
} else {
Promise> promise = vertx.promise();
clusterManager.getAsyncMap(name, promise);
return promise.future().map(WrappedAsyncMap::new);
}
}
@Override
public void getLock(String name, Handler> resultHandler) {
getLockWithTimeout(name, DEFAULT_LOCK_TIMEOUT, resultHandler);
}
@Override
public Future getLock(String name) {
return getLockWithTimeout(name, DEFAULT_LOCK_TIMEOUT);
}
@Override
public void getLockWithTimeout(String name, long timeout, Handler> resultHandler) {
Objects.requireNonNull(resultHandler, "resultHandler");
getLockWithTimeout(name, timeout).onComplete(resultHandler);
}
@Override
public Future getLockWithTimeout(String name, long timeout) {
Objects.requireNonNull(name, "name");
Arguments.require(timeout >= 0, "timeout must be >= 0");
if (clusterManager == null) {
return getLocalLockWithTimeout(name, timeout);
} else {
Promise promise = vertx.promise();
clusterManager.getLockWithTimeout(name, timeout, promise);
return promise.future();
}
}
@Override
public void getLocalLock(String name, Handler> resultHandler) {
getLocalLockWithTimeout(name, DEFAULT_LOCK_TIMEOUT, resultHandler);
}
@Override
public Future getLocalLock(String name) {
return getLocalLockWithTimeout(name, DEFAULT_LOCK_TIMEOUT);
}
@Override
public void getLocalLockWithTimeout(String name, long timeout, Handler> resultHandler) {
Objects.requireNonNull(resultHandler, "resultHandler");
getLocalLockWithTimeout(name, timeout).onComplete(resultHandler);
}
@Override
public Future getLocalLockWithTimeout(String name, long timeout) {
Objects.requireNonNull(name, "name");
Arguments.require(timeout >= 0, "timeout must be >= 0");
return localAsyncLocks.acquire(vertx.getOrCreateContext(), name, timeout);
}
@Override
public Future getCounter(String name) {
Objects.requireNonNull(name, "name");
if (clusterManager == null) {
return getLocalCounter(name);
} else {
Promise promise = vertx.promise();
clusterManager.getCounter(name, promise);
return promise.future();
}
}
@Override
public void getCounter(String name, Handler> resultHandler) {
Objects.requireNonNull(resultHandler, "resultHandler");
getCounter(name).onComplete(resultHandler);
}
/**
* Return a {@code Map} with the specific {@code name}. All invocations of this method with the same value of {@code name}
* are guaranteed to return the same {@code Map} instance.
*/
@SuppressWarnings("unchecked")
@Override
public LocalMap getLocalMap(String name) {
return (LocalMap) localMaps.computeIfAbsent(name, n -> new LocalMapImpl<>(n, localMaps));
}
@Override
public void getLocalAsyncMap(String name, Handler>> resultHandler) {
Objects.requireNonNull(resultHandler, "resultHandler");
this.getLocalAsyncMap(name).onComplete(resultHandler);
}
@SuppressWarnings("unchecked")
@Override
public Future> getLocalAsyncMap(String name) {
LocalAsyncMapImpl asyncMap = (LocalAsyncMapImpl) localAsyncMaps.computeIfAbsent(name, n -> new LocalAsyncMapImpl<>(vertx));
ContextInternal context = vertx.getOrCreateContext();
return context.succeededFuture(new WrappedAsyncMap<>(asyncMap));
}
@Override
public void getLocalCounter(String name, Handler> resultHandler) {
Objects.requireNonNull(resultHandler, "resultHandler");
getLocalCounter(name).onComplete(resultHandler);
}
@Override
public Future getLocalCounter(String name) {
Counter counter = localCounters.computeIfAbsent(name, n -> new AsynchronousCounter(vertx));
ContextInternal context = vertx.getOrCreateContext();
return context.succeededFuture(counter);
}
private static void checkType(Object obj) {
if (obj == null) {
throw new IllegalArgumentException("Cannot put null in key or value of async map");
}
// All immutables and byte arrays are Serializable by the platform
if (!(obj instanceof Serializable || obj instanceof ClusterSerializable)) {
throw new IllegalArgumentException("Invalid type: " + obj.getClass().getName() + " to put in async map");
}
}
public static final class WrappedAsyncMap implements AsyncMap {
private final AsyncMap delegate;
WrappedAsyncMap(AsyncMap other) {
this.delegate = other;
}
@Override
public Future get(K k) {
checkType(k);
return delegate.get(k);
}
@Override
public Future put(K k, V v) {
checkType(k);
checkType(v);
return delegate.put(k, v);
}
@Override
public Future put(K k, V v, long ttl) {
checkType(k);
checkType(v);
return delegate.put(k, v, ttl);
}
@Override
public Future putIfAbsent(K k, V v) {
checkType(k);
checkType(v);
return delegate.putIfAbsent(k, v);
}
@Override
public Future putIfAbsent(K k, V v, long ttl) {
checkType(k);
checkType(v);
return delegate.putIfAbsent(k, v, ttl);
}
@Override
public Future remove(K k) {
checkType(k);
return delegate.remove(k);
}
@Override
public Future removeIfPresent(K k, V v) {
checkType(k);
checkType(v);
return delegate.removeIfPresent(k, v);
}
@Override
public Future replace(K k, V v) {
checkType(k);
checkType(v);
return delegate.replace(k, v);
}
@Override
public Future replace(K k, V v, long ttl) {
checkType(k);
checkType(v);
return delegate.replace(k, v, ttl);
}
@Override
public Future replaceIfPresent(K k, V oldValue, V newValue) {
checkType(k);
checkType(oldValue);
checkType(newValue);
return delegate.replaceIfPresent(k, oldValue, newValue);
}
@Override
public Future replaceIfPresent(K k, V oldValue, V newValue, long ttl) {
checkType(k);
checkType(oldValue);
checkType(newValue);
return delegate.replaceIfPresent(k, oldValue, newValue, ttl);
}
@Override
public Future clear() {
return delegate.clear();
}
@Override
public Future size() {
return delegate.size();
}
@Override
public Future> keys() {
return delegate.keys();
}
@Override
public Future> values() {
return delegate.values();
}
@Override
public Future