
org.redisson.command.CommandBatchService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of redisson Show documentation
Show all versions of redisson Show documentation
Redis Java client with features of In-Memory Data Grid
/**
* Copyright 2014 Nikita Koksharov, Nickolay Borbit
*
* 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 org.redisson.command;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.redisson.client.RedisAskException;
import org.redisson.client.RedisConnection;
import org.redisson.client.RedisLoadingException;
import org.redisson.client.RedisMovedException;
import org.redisson.client.RedisTimeoutException;
import org.redisson.client.WriteRedisConnectionException;
import org.redisson.client.codec.Codec;
import org.redisson.client.codec.StringCodec;
import org.redisson.client.protocol.CommandData;
import org.redisson.client.protocol.CommandsData;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.client.protocol.RedisCommands;
import org.redisson.connection.ConnectionManager;
import org.redisson.connection.NodeSource;
import org.redisson.connection.NodeSource.Redirect;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;
import io.netty.util.concurrent.Promise;
import io.netty.util.internal.PlatformDependent;
public class CommandBatchService extends CommandReactiveService {
public static class CommandEntry implements Comparable {
final CommandData, ?> command;
final int index;
public CommandEntry(CommandData, ?> command, int index) {
super();
this.command = command;
this.index = index;
}
public CommandData, ?> getCommand() {
return command;
}
@Override
public int compareTo(CommandEntry o) {
return index - o.index;
}
}
public static class Entry {
Queue commands = PlatformDependent.newMpscQueue();
volatile boolean readOnlyMode = true;
public Queue getCommands() {
return commands;
}
public void setReadOnlyMode(boolean readOnlyMode) {
this.readOnlyMode = readOnlyMode;
}
public boolean isReadOnlyMode() {
return readOnlyMode;
}
}
private final AtomicInteger index = new AtomicInteger();
private ConcurrentMap commands = PlatformDependent.newConcurrentHashMap();
private boolean executed;
public CommandBatchService(ConnectionManager connectionManager) {
super(connectionManager);
}
@Override
protected void async(boolean readOnlyMode, NodeSource nodeSource,
Codec codec, RedisCommand command, Object[] params, Promise mainPromise, int attempt) {
if (executed) {
throw new IllegalStateException("Batch already executed!");
}
Entry entry = commands.get(nodeSource.getSlot());
if (entry == null) {
entry = new Entry();
Entry oldEntry = commands.putIfAbsent(nodeSource.getSlot(), entry);
if (oldEntry != null) {
entry = oldEntry;
}
}
if (!readOnlyMode) {
entry.setReadOnlyMode(false);
}
entry.getCommands().add(new CommandEntry(new CommandData(mainPromise, codec, command, params), index.incrementAndGet()));
}
public List> execute() {
return get(executeAsync());
}
public Future executeAsyncVoid() {
if (executed) {
throw new IllegalStateException("Batch already executed!");
}
if (commands.isEmpty()) {
return connectionManager.newSucceededFuture(null);
}
executed = true;
Promise voidPromise = connectionManager.newPromise();
voidPromise.addListener(new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
commands = null;
}
});
AtomicInteger slots = new AtomicInteger(commands.size());
for (java.util.Map.Entry e : commands.entrySet()) {
execute(e.getValue(), new NodeSource(e.getKey()), voidPromise, slots, 0);
}
return voidPromise;
}
public Future> executeAsync() {
if (executed) {
throw new IllegalStateException("Batch already executed!");
}
if (commands.isEmpty()) {
return connectionManager.newSucceededFuture(null);
}
executed = true;
Promise voidPromise = connectionManager.newPromise();
final Promise> promise = connectionManager.newPromise();
voidPromise.addListener(new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
promise.setFailure(future.cause());
commands = null;
return;
}
List entries = new ArrayList();
for (Entry e : commands.values()) {
entries.addAll(e.getCommands());
}
Collections.sort(entries);
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy