com.alipay.sofa.jraft.test.atomic.client.AtomicClient Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 com.alipay.sofa.jraft.test.atomic.client;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alipay.sofa.jraft.RouteTable;
import com.alipay.sofa.jraft.conf.Configuration;
import com.alipay.sofa.jraft.entity.PeerId;
import com.alipay.sofa.jraft.option.CliOptions;
import com.alipay.sofa.jraft.rpc.RpcClient;
import com.alipay.sofa.jraft.rpc.impl.cli.CliClientServiceImpl;
import com.alipay.sofa.jraft.test.atomic.HashUtils;
import com.alipay.sofa.jraft.test.atomic.KeyNotFoundException;
import com.alipay.sofa.jraft.test.atomic.command.BooleanCommand;
import com.alipay.sofa.jraft.test.atomic.command.CompareAndSetCommand;
import com.alipay.sofa.jraft.test.atomic.command.GetCommand;
import com.alipay.sofa.jraft.test.atomic.command.GetSlotsCommand;
import com.alipay.sofa.jraft.test.atomic.command.IncrementAndGetCommand;
import com.alipay.sofa.jraft.test.atomic.command.SetCommand;
import com.alipay.sofa.jraft.test.atomic.command.SlotsResponseCommand;
import com.alipay.sofa.jraft.test.atomic.command.ValueCommand;
/**
* A counter client
* @author boyan ([email protected])
*
* 2018-Apr-25 4:08:14 PM
*/
public class AtomicClient {
static final Logger LOG = LoggerFactory.getLogger(AtomicClient.class);
private final Configuration conf;
private final CliClientServiceImpl cliClientService;
private RpcClient rpcClient;
private CliOptions cliOptions;
private TreeMap groups = new TreeMap<>();
public AtomicClient(String groupId, Configuration conf) {
super();
this.conf = conf;
this.cliClientService = new CliClientServiceImpl();
}
public void shutdown() {
this.cliClientService.shutdown();
for (final String groupId : groups.values()) {
RouteTable.getInstance().removeGroup(groupId);
}
}
public void start() throws InterruptedException, TimeoutException {
cliOptions = new CliOptions();
this.cliClientService.init(cliOptions);
this.rpcClient = this.cliClientService.getRpcClient();
if (conf != null) {
final Set peers = conf.getPeerSet();
for (final PeerId peer : peers) {
try {
final BooleanCommand cmd = (BooleanCommand) this.rpcClient.invokeSync(peer.getEndpoint(),
new GetSlotsCommand(), cliOptions.getRpcDefaultTimeout());
if (cmd instanceof SlotsResponseCommand) {
groups = ((SlotsResponseCommand) cmd).getMap();
break;
} else {
LOG.warn("Fail to get slots from peer {}, error: {}", peer, cmd.getErrorMsg());
}
} catch (final Throwable t) {
LOG.warn("Fail to get slots from peer {}, error: {}", peer, t.getMessage());
//continue;
}
}
if (groups == null || groups.isEmpty()) {
throw new IllegalArgumentException("Can't get slots from any peers");
} else {
LOG.info("All groups is {}", groups);
}
for (final String groupId : groups.values()) {
RouteTable.getInstance().updateConfiguration(groupId, conf);
refreshLeader(groupId);
refreshConf(groupId);
}
}
}
private void refreshConf(String groupId) throws InterruptedException, TimeoutException {
RouteTable.getInstance().refreshConfiguration(cliClientService, groupId, cliOptions.getRpcDefaultTimeout());
}
private void refreshLeader(String groupId) throws InterruptedException, TimeoutException {
RouteTable.getInstance().refreshLeader(cliClientService, groupId, cliOptions.getRpcDefaultTimeout());
}
private String getGroupId(String key) {
return groups.get(HashUtils.getHeadKey(groups, key));
}
public long get(String key) throws InterruptedException, KeyNotFoundException, TimeoutException {
return this.get(getLeaderByKey(key), key, false, false);
}
private PeerId getLeaderByKey(String key) throws InterruptedException, TimeoutException {
return getLeader(getGroupId(key));
}
private PeerId getLeader(String key) throws InterruptedException, TimeoutException {
final String groupId = getGroupId(key);
refreshLeader(groupId);
return RouteTable.getInstance().selectLeader(groupId);
}
private PeerId getPeer(String key) throws InterruptedException, TimeoutException {
final String groupId = getGroupId(key);
this.refreshConf(groupId);
final List peers = RouteTable.getInstance().getConfiguration(groupId).getPeers();
return peers.get(ThreadLocalRandom.current().nextInt(peers.size()));
}
public long get(String key, boolean readFromQuorum) throws KeyNotFoundException, InterruptedException,
TimeoutException {
if (readFromQuorum) {
return get(getPeer(key), key, true, false);
} else {
//read from leader
return get(key);
}
}
public long get(PeerId peer, String key, boolean readFromQuorum, boolean readByStateMachine)
throws KeyNotFoundException,
InterruptedException {
try {
final GetCommand request = new GetCommand(key);
request.setReadFromQuorum(readFromQuorum);
request.setReadByStateMachine(readByStateMachine);
final Object response = this.rpcClient.invokeSync(peer.getEndpoint(), request,
cliOptions.getRpcDefaultTimeout());
final BooleanCommand cmd = (BooleanCommand) response;
if (cmd.isSuccess()) {
return ((ValueCommand) cmd).getVlaue();
} else {
if (cmd.getErrorMsg().equals("key not found")) {
throw new KeyNotFoundException();
} else {
throw new IllegalStateException("Server error:" + cmd.getErrorMsg());
}
}
} catch (final Throwable t) {
t.printStackTrace();
throw new IllegalStateException("Remoting error:" + t.getMessage());
}
}
public long addAndGet(String key, long delta) throws InterruptedException, TimeoutException {
return this.addAndGet(getLeaderByKey(key), key, delta);
}
public long addAndGet(PeerId peer, String key, long delta) throws InterruptedException {
try {
final IncrementAndGetCommand request = new IncrementAndGetCommand();
request.setKey(key);
request.setDetal(delta);
final Object response = this.rpcClient.invokeSync(peer.getEndpoint(), request,
cliOptions.getRpcDefaultTimeout());
final BooleanCommand cmd = (BooleanCommand) response;
if (cmd.isSuccess()) {
return ((ValueCommand) cmd).getVlaue();
} else {
throw new IllegalStateException("Server error:" + cmd.getErrorMsg());
}
} catch (final Throwable t) {
throw new IllegalStateException("Remoting error:" + t.getMessage());
}
}
public boolean set(String key, long value) throws InterruptedException, TimeoutException {
return this.set(getLeaderByKey(key), key, value);
}
public boolean set(PeerId peer, String key, long value) throws InterruptedException {
try {
final SetCommand request = new SetCommand();
request.setKey(key);
request.setValue(value);
final Object response = this.rpcClient.invokeSync(peer.getEndpoint(), request,
cliOptions.getRpcDefaultTimeout());
final BooleanCommand cmd = (BooleanCommand) response;
return cmd.isSuccess();
} catch (final Throwable t) {
throw new IllegalStateException("Remoting error:" + t.getMessage());
}
}
public boolean compareAndSet(String key, long expect, long newVal) throws InterruptedException, TimeoutException {
return this.compareAndSet(getLeaderByKey(key), key, expect, newVal);
}
public boolean compareAndSet(PeerId peer, String key, long expect, long newVal) throws InterruptedException {
try {
final CompareAndSetCommand request = new CompareAndSetCommand();
request.setKey(key);
request.setNewValue(newVal);
request.setExpect(expect);
final Object response = this.rpcClient.invokeSync(peer.getEndpoint(), request,
cliOptions.getRpcDefaultTimeout());
final BooleanCommand cmd = (BooleanCommand) response;
return cmd.isSuccess();
} catch (final Throwable t) {
throw new IllegalStateException("Remoting error:" + t.getMessage());
}
}
}