use of io.dingodb.raft.Status in project dingo by dingodb.
the class ClosureQueueImpl method clear.
@Override
public void clear() {
List<Closure> savedQueue;
this.lock.lock();
try {
this.firstIndex = 0;
savedQueue = this.queue;
this.queue = new LinkedList<>();
} finally {
this.lock.unlock();
}
final Status status = new Status(RaftError.EPERM, "Leader stepped down");
Utils.runInThread(() -> {
for (final Closure done : savedQueue) {
if (done != null) {
done.run(status);
}
}
});
}
use of io.dingodb.raft.Status in project dingo by dingodb.
the class StoreEngine method applySplit.
public void applySplit(final String regionId, final String newRegionId, final KVStoreClosure closure) {
Requires.requireNonNull(regionId, "regionId");
Requires.requireNonNull(newRegionId, "newRegionId");
if (this.regionEngineTable.containsKey(newRegionId)) {
closure.setError(Errors.CONFLICT_REGION_ID);
closure.run(new Status(-1, "Conflict region id %d", newRegionId));
return;
}
if (!this.splitting.compareAndSet(false, true)) {
closure.setError(Errors.SERVER_BUSY);
closure.run(new Status(-1, "Server is busy now"));
return;
}
final RegionEngine parentEngine = getRegionEngine(regionId);
if (parentEngine == null) {
closure.setError(Errors.NO_REGION_FOUND);
closure.run(new Status(-1, "RegionEngine[%s] not found", regionId));
this.splitting.set(false);
return;
}
if (!parentEngine.isLeader()) {
closure.setError(Errors.NOT_LEADER);
closure.run(new Status(-1, "RegionEngine[%s] not leader", regionId));
this.splitting.set(false);
return;
}
final Region parentRegion = parentEngine.getRegion();
final byte[] startKey = BytesUtil.nullToEmpty(parentRegion.getStartKey());
final byte[] endKey = parentRegion.getEndKey();
ApproximateKVStats stats = this.rawKVStore.getApproximateKVStatsInRange(startKey, endKey);
final long approximateKeys = stats.keysCnt;
final long approximateBytes = stats.sizeInBytes / 1024 / 1024;
final long leastKeysOnSplit = this.storeOpts.getLeastKeysOnSplit();
boolean isSplitOK = (approximateBytes >= 64 || approximateKeys > leastKeysOnSplit);
LOG.info("Region:{} Split Condition is {}!. Disk Used:{} >= 64M, Write Keys:{} >= Expected Keys:{}", parentEngine, isSplitOK, approximateBytes, approximateKeys, leastKeysOnSplit);
if (!isSplitOK) {
closure.setError(Errors.TOO_SMALL_TO_SPLIT);
closure.run(new Status(-1, "RegionEngine[%s]'s split condition is not OK!. " + "Write Keys:%d bytes(M): %d, Expected: keys:%d, bytes: 64M", regionId, approximateKeys, approximateBytes, leastKeysOnSplit));
this.splitting.set(false);
return;
}
final byte[] splitKey = this.rawKVStore.jumpOver(startKey, approximateKeys >> 1);
if (splitKey == null) {
closure.setError(Errors.STORAGE_ERROR);
closure.run(new Status(-1, "Fail to scan split key"));
this.splitting.set(false);
return;
}
final KVOperation op = KVOperation.createRangeSplit(splitKey, regionId, newRegionId);
LOG.info("Store receive region split instruction: Old Region:{}, oldStartKey:{}, oldEndKey:{}, " + "approximateKeys:{}, newRegionId:{}, splitKey:{}", parentEngine.toString(), startKey != null ? BytesUtil.toHex(startKey) : "null", endKey != null ? BytesUtil.toHex(endKey) : "null", approximateKeys, newRegionId, splitKey != null ? BytesUtil.toHex(splitKey) : "null");
final Task task = new Task();
task.setData(ByteBuffer.wrap(Serializers.getDefault().writeObject(op)));
task.setDone(new KVClosureAdapter(closure, op));
parentEngine.getNode().apply(task);
}
use of io.dingodb.raft.Status in project dingo by dingodb.
the class DefaultDingoRowStore method ensureOnValidEpoch.
private static boolean ensureOnValidEpoch(final Region region, final RegionEngine engine, final KVStoreClosure closure) {
if (isValidEpoch(region, engine)) {
return true;
}
// will retry on this error and status
closure.setError(Errors.INVALID_REGION_EPOCH);
closure.run(new Status(-1, "Invalid region epoch: %s", region));
return false;
}
use of io.dingodb.raft.Status in project dingo by dingodb.
the class DefaultDingoRowStoreCliService method rangeSplit.
@Override
public Status rangeSplit(final String regionId, final String newRegionId, final String groupId, final Configuration conf) {
final PeerId leaderId = new PeerId();
final Status st = this.cliService.getLeader(groupId, conf, leaderId);
if (!st.isOk()) {
throw new IllegalStateException(st.getErrorMsg());
}
final RangeSplitRequest request = new RangeSplitRequest();
request.setRegionId(regionId);
request.setNewRegionId(newRegionId);
try {
final BaseResponse<?> response = (BaseResponse<?>) this.rpcClient.invokeSync(leaderId.getEndpoint(), request, this.opts.getTimeoutMs());
if (response.isSuccess()) {
return Status.OK();
}
return new Status(-1, "Fail to range split on region %d, error: %s", regionId, response);
} catch (final Exception e) {
LOG.error("Fail to range split on exception: {}.", StackTraceUtil.stackTrace(e));
return new Status(-1, "fail to range split on region %d", regionId);
}
}
use of io.dingodb.raft.Status in project dingo by dingodb.
the class DefaultRegionKVService method handleGetAndPutRequest.
@Override
public void handleGetAndPutRequest(final GetAndPutRequest request, final RequestProcessClosure<BaseRequest, BaseResponse<?>> closure) {
final GetAndPutResponse response = new GetAndPutResponse();
response.setRegionId(getRegionId());
response.setRegionEpoch(getRegionEpoch());
try {
KVParameterRequires.requireSameEpoch(request, getRegionEpoch());
final byte[] key = KVParameterRequires.requireNonNull(request.getKey(), "getAndPut.key");
final byte[] value = KVParameterRequires.requireNonNull(request.getValue(), "getAndPut.value");
this.rawKVStore.getAndPut(key, value, new BaseKVStoreClosure() {
@Override
public void run(final Status status) {
if (status.isOk()) {
response.setValue((byte[]) getData());
} else {
setFailure(request, response, status, getError());
}
closure.sendResponse(response);
}
});
} catch (final Throwable t) {
LOG.error("Failed to handle: {}, {}.", request, StackTraceUtil.stackTrace(t));
response.setError(Errors.forException(t));
closure.sendResponse(response);
}
}
Aggregations