use of org.redisson.connection.MasterSlaveEntry in project redisson by redisson.
the class CommandAsyncService method evalAllAsync.
public <T, R> RFuture<R> evalAllAsync(boolean readOnlyMode, RedisCommand<T> command, final SlotCallback<T, R> callback, String script, List<Object> keys, Object... params) {
final RPromise<R> mainPromise = connectionManager.newPromise();
final Set<MasterSlaveEntry> entries = connectionManager.getEntrySet();
final AtomicInteger counter = new AtomicInteger(entries.size());
FutureListener<T> listener = new FutureListener<T>() {
@Override
public void operationComplete(Future<T> future) throws Exception {
if (!future.isSuccess()) {
mainPromise.tryFailure(future.cause());
return;
}
callback.onSlotResult(future.getNow());
if (counter.decrementAndGet() == 0 && !mainPromise.isDone()) {
mainPromise.trySuccess(callback.onFinish());
}
}
};
List<Object> args = new ArrayList<Object>(2 + keys.size() + params.length);
args.add(script);
args.add(keys.size());
args.addAll(keys);
args.addAll(Arrays.asList(params));
for (MasterSlaveEntry entry : entries) {
RPromise<T> promise = connectionManager.newPromise();
promise.addListener(listener);
async(readOnlyMode, new NodeSource(entry), connectionManager.getCodec(), command, args.toArray(), promise, 0);
}
return mainPromise;
}
use of org.redisson.connection.MasterSlaveEntry in project redisson by redisson.
the class ClusterConnectionManager method addMasterEntry.
private RFuture<Collection<RFuture<Void>>> addMasterEntry(final ClusterPartition partition, final ClusterServersConfig cfg) {
if (partition.isMasterFail()) {
RedisException e = new RedisException("Failed to add master: " + partition.getMasterAddress() + " for slot ranges: " + partition.getSlotRanges() + ". Reason - server has FAIL flag");
if (partition.getSlotRanges().isEmpty()) {
e = new RedisException("Failed to add master: " + partition.getMasterAddress() + ". Reason - server has FAIL flag");
}
return newFailedFuture(e);
}
final RPromise<Collection<RFuture<Void>>> result = newPromise();
RFuture<RedisConnection> connectionFuture = connect(cfg, partition.getMasterAddress());
connectionFuture.addListener(new FutureListener<RedisConnection>() {
@Override
public void operationComplete(Future<RedisConnection> future) throws Exception {
if (!future.isSuccess()) {
log.error("Can't connect to master: {} with slot ranges: {}", partition.getMasterAddress(), partition.getSlotRanges());
result.tryFailure(future.cause());
return;
}
final RedisConnection connection = future.getNow();
RFuture<Map<String, String>> clusterFuture = connection.async(RedisCommands.CLUSTER_INFO);
clusterFuture.addListener(new FutureListener<Map<String, String>>() {
@Override
public void operationComplete(Future<Map<String, String>> future) throws Exception {
if (!future.isSuccess()) {
log.error("Can't execute CLUSTER_INFO for " + connection.getRedisClient().getAddr(), future.cause());
result.tryFailure(future.cause());
return;
}
Map<String, String> params = future.getNow();
if ("fail".equals(params.get("cluster_state"))) {
RedisException e = new RedisException("Failed to add master: " + partition.getMasterAddress() + " for slot ranges: " + partition.getSlotRanges() + ". Reason - cluster_state:fail");
log.error("cluster_state:fail for " + connection.getRedisClient().getAddr());
result.tryFailure(e);
return;
}
MasterSlaveServersConfig config = create(cfg);
config.setMasterAddress(partition.getMasterAddress());
final MasterSlaveEntry e;
List<RFuture<Void>> futures = new ArrayList<RFuture<Void>>();
if (config.getReadMode() == ReadMode.MASTER) {
e = new SingleEntry(partition.getSlotRanges(), ClusterConnectionManager.this, config);
} else {
config.setSlaveAddresses(partition.getSlaveAddresses());
e = new MasterSlaveEntry(partition.getSlotRanges(), ClusterConnectionManager.this, config);
List<RFuture<Void>> fs = e.initSlaveBalancer(partition.getFailedSlaveAddresses());
futures.addAll(fs);
if (!partition.getSlaveAddresses().isEmpty()) {
log.info("slaves: {} added for slot ranges: {}", partition.getSlaveAddresses(), partition.getSlotRanges());
if (!partition.getFailedSlaveAddresses().isEmpty()) {
log.warn("slaves: {} is down for slot ranges: {}", partition.getFailedSlaveAddresses(), partition.getSlotRanges());
}
}
}
RFuture<Void> f = e.setupMasterEntry(config.getMasterAddress().getHost(), config.getMasterAddress().getPort());
final RPromise<Void> initFuture = newPromise();
futures.add(initFuture);
f.addListener(new FutureListener<Void>() {
@Override
public void operationComplete(Future<Void> future) throws Exception {
if (!future.isSuccess()) {
log.error("Can't add master: {} for slot ranges: {}", partition.getMasterAddress(), partition.getSlotRanges());
initFuture.tryFailure(future.cause());
return;
}
for (Integer slot : partition.getSlots()) {
addEntry(slot, e);
lastPartitions.put(slot, partition);
}
log.info("master: {} added for slot ranges: {}", partition.getMasterAddress(), partition.getSlotRanges());
if (!initFuture.trySuccess(null)) {
throw new IllegalStateException();
}
}
});
if (!result.trySuccess(futures)) {
throw new IllegalStateException();
}
}
});
}
});
return result;
}
use of org.redisson.connection.MasterSlaveEntry in project redisson by redisson.
the class ClusterConnectionManager method checkSlaveNodesChange.
private void checkSlaveNodesChange(Collection<ClusterPartition> newPartitions) {
for (ClusterPartition newPart : newPartitions) {
for (ClusterPartition currentPart : getLastPartitions()) {
if (!newPart.getMasterAddress().equals(currentPart.getMasterAddress())) {
continue;
}
MasterSlaveEntry entry = getEntry(currentPart.getMasterAddr());
// should be invoked first in order to remove stale failedSlaveAddresses
Set<URL> addedSlaves = addRemoveSlaves(entry, currentPart, newPart);
// Do some slaves have changed state from failed to alive?
upDownSlaves(entry, currentPart, newPart, addedSlaves);
break;
}
}
}
use of org.redisson.connection.MasterSlaveEntry in project redisson by redisson.
the class ClusterConnectionManager method checkSlotsChange.
private void checkSlotsChange(ClusterServersConfig cfg, Collection<ClusterPartition> newPartitions, String nodes) {
Collection<Integer> newPartitionsSlots = slots(newPartitions);
if (newPartitionsSlots.size() == lastPartitions.size() && lastPartitions.size() == MAX_SLOT) {
return;
}
Set<Integer> removedSlots = new HashSet<Integer>(lastPartitions.keySet());
removedSlots.removeAll(newPartitionsSlots);
lastPartitions.keySet().removeAll(removedSlots);
if (!removedSlots.isEmpty()) {
log.info("{} slots found to remove", removedSlots.size());
}
for (Integer slot : removedSlots) {
MasterSlaveEntry entry = removeMaster(slot);
entry.removeSlotRange(slot);
if (entry.getSlotRanges().isEmpty()) {
entry.shutdownMasterAsync();
log.info("{} master and slaves for it removed", entry.getClient().getAddr());
}
}
Set<Integer> addedSlots = new HashSet<Integer>(newPartitionsSlots);
addedSlots.removeAll(lastPartitions.keySet());
if (!addedSlots.isEmpty()) {
log.info("{} slots found to add", addedSlots.size());
}
for (final Integer slot : addedSlots) {
ClusterPartition partition = find(newPartitions, slot);
for (MasterSlaveEntry entry : getEntrySet()) {
if (entry.getClient().getAddr().equals(partition.getMasterAddr())) {
addEntry(slot, entry);
lastPartitions.put(slot, partition);
break;
}
}
}
}
use of org.redisson.connection.MasterSlaveEntry in project redisson by redisson.
the class RedissonKeys method deleteByPatternAsync.
@Override
public RFuture<Long> deleteByPatternAsync(String pattern) {
if (!commandExecutor.getConnectionManager().isClusterMode()) {
return commandExecutor.evalWriteAsync((String) null, null, RedisCommands.EVAL_LONG, "local keys = redis.call('keys', ARGV[1]) " + "local n = 0 " + "for i=1, #keys,5000 do " + "n = n + redis.call('del', unpack(keys, i, math.min(i+4999, table.getn(keys)))) " + "end " + "return n;", Collections.emptyList(), pattern);
}
final RPromise<Long> result = commandExecutor.getConnectionManager().newPromise();
final AtomicReference<Throwable> failed = new AtomicReference<Throwable>();
final AtomicLong count = new AtomicLong();
Set<MasterSlaveEntry> entries = commandExecutor.getConnectionManager().getEntrySet();
final AtomicLong executed = new AtomicLong(entries.size());
final FutureListener<Long> listener = new FutureListener<Long>() {
@Override
public void operationComplete(Future<Long> future) throws Exception {
if (future.isSuccess()) {
count.addAndGet(future.getNow());
} else {
failed.set(future.cause());
}
checkExecution(result, failed, count, executed);
}
};
for (MasterSlaveEntry entry : entries) {
RFuture<Collection<String>> findFuture = commandExecutor.readAsync(entry, null, RedisCommands.KEYS, pattern);
findFuture.addListener(new FutureListener<Collection<String>>() {
@Override
public void operationComplete(Future<Collection<String>> future) throws Exception {
if (!future.isSuccess()) {
failed.set(future.cause());
checkExecution(result, failed, count, executed);
return;
}
Collection<String> keys = future.getNow();
if (keys.isEmpty()) {
checkExecution(result, failed, count, executed);
return;
}
RFuture<Long> deleteFuture = deleteAsync(keys.toArray(new String[keys.size()]));
deleteFuture.addListener(listener);
}
});
}
return result;
}
Aggregations