use of io.dingodb.store.row.metadata.Region in project dingo by dingodb.
the class DefaultDingoRowStore method internalSingleRegionScan.
private void internalSingleRegionScan(final byte[] startKey, final byte[] endKey, final int limit, final boolean readOnlySafe, final boolean returnValue, final CompletableFuture<List<KVEntry>> future, final int retriesLeft, final Errors lastCause, final boolean requireLeader) {
Requires.requireNonNull(startKey, "startKey");
final Region region = this.pdClient.findRegionByKey(startKey, ErrorsHelper.isInvalidEpoch(lastCause));
final byte[] regionEndKey = region.getEndKey();
final byte[] realEndKey = regionEndKey == null ? endKey : (endKey == null ? regionEndKey : BytesUtil.min(regionEndKey, endKey));
final RegionEngine regionEngine = getRegionEngine(region.getId(), requireLeader);
// require leader on retry
final RetryRunner retryRunner = retryCause -> internalSingleRegionScan(startKey, endKey, limit, readOnlySafe, returnValue, future, retriesLeft - 1, retryCause, true);
final FailoverClosure<List<KVEntry>> closure = new FailoverClosureImpl<>(future, retriesLeft, retryRunner);
if (regionEngine != null) {
if (ensureOnValidEpoch(region, regionEngine, closure)) {
getRawKVStore(regionEngine).scan(startKey, realEndKey, limit, readOnlySafe, returnValue, closure);
}
} else {
final ScanRequest request = new ScanRequest();
request.setStartKey(startKey);
request.setEndKey(realEndKey);
request.setLimit(limit);
request.setReadOnlySafe(readOnlySafe);
request.setReturnValue(returnValue);
request.setRegionId(region.getId());
request.setRegionEpoch(region.getRegionEpoch());
this.dingoRowStoreRpcService.callAsyncWithRpc(request, closure, lastCause, requireLeader);
}
}
use of io.dingodb.store.row.metadata.Region in project dingo by dingodb.
the class DefaultDingoRowStore method internalTryLockWith.
private void internalTryLockWith(final byte[] key, final boolean keepLease, final DistributedLock.Acquirer acquirer, final CompletableFuture<DistributedLock.Owner> future, final int retriesLeft, final Errors lastCause) {
final Region region = this.pdClient.findRegionByKey(key, ErrorsHelper.isInvalidEpoch(lastCause));
final RegionEngine regionEngine = getRegionEngine(region.getId(), true);
final RetryRunner retryRunner = retryCause -> internalTryLockWith(key, keepLease, acquirer, future, retriesLeft - 1, retryCause);
final FailoverClosure<DistributedLock.Owner> closure = new FailoverClosureImpl<>(future, retriesLeft, retryRunner);
if (regionEngine != null) {
if (ensureOnValidEpoch(region, regionEngine, closure)) {
getRawKVStore(regionEngine).tryLockWith(key, region.getStartKey(), keepLease, acquirer, closure);
}
} else {
final KeyLockRequest request = new KeyLockRequest();
request.setKey(key);
request.setKeepLease(keepLease);
request.setAcquirer(acquirer);
request.setRegionId(region.getId());
request.setRegionEpoch(region.getRegionEpoch());
this.dingoRowStoreRpcService.callAsyncWithRpc(request, closure, lastCause);
}
}
use of io.dingodb.store.row.metadata.Region in project dingo by dingodb.
the class DefaultDingoRowStore method internalCompareAndPut.
private void internalCompareAndPut(final byte[] key, final byte[] expect, final byte[] update, final CompletableFuture<Boolean> future, final int retriesLeft, final Errors lastCause) {
final Region region = this.pdClient.findRegionByKey(key, ErrorsHelper.isInvalidEpoch(lastCause));
final RegionEngine regionEngine = getRegionEngine(region.getId(), true);
final RetryRunner retryRunner = retryCause -> internalCompareAndPut(key, expect, update, future, retriesLeft - 1, retryCause);
final FailoverClosure<Boolean> closure = new FailoverClosureImpl<>(future, retriesLeft, retryRunner);
if (regionEngine != null) {
if (ensureOnValidEpoch(region, regionEngine, closure)) {
getRawKVStore(regionEngine).compareAndPut(key, expect, update, closure);
}
} else {
final CompareAndPutRequest request = new CompareAndPutRequest();
request.setKey(key);
request.setExpect(expect);
request.setUpdate(update);
request.setRegionId(region.getId());
request.setRegionEpoch(region.getRegionEpoch());
this.dingoRowStoreRpcService.callAsyncWithRpc(request, closure, lastCause);
}
}
use of io.dingodb.store.row.metadata.Region in project dingo by dingodb.
the class DefaultDingoRowStore method internalPut.
private FutureGroup<Boolean> internalPut(final List<KVEntry> entries, final int retriesLeft, final Throwable lastCause) {
final Map<Region, List<KVEntry>> regionMap = this.pdClient.findRegionsByKvEntries(entries, ApiExceptionHelper.isInvalidEpoch(lastCause));
final List<CompletableFuture<Boolean>> futures = Lists.newArrayListWithCapacity(regionMap.size());
final Errors lastError = lastCause == null ? null : Errors.forException(lastCause);
for (final Map.Entry<Region, List<KVEntry>> entry : regionMap.entrySet()) {
final Region region = entry.getKey();
final List<KVEntry> subEntries = entry.getValue();
final RetryCallable<Boolean> retryCallable = retryCause -> internalPut(subEntries, retriesLeft - 1, retryCause);
final BoolFailoverFuture future = new BoolFailoverFuture(retriesLeft, retryCallable);
internalRegionPut(region, subEntries, future, retriesLeft, lastError);
futures.add(future);
}
return new FutureGroup<>(futures);
}
use of io.dingodb.store.row.metadata.Region 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);
}
Aggregations