use of io.dingodb.store.row.storage.KVClosureAdapter 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.store.row.storage.KVClosureAdapter in project dingo by dingodb.
the class CoordinatorStateMachine method onApply.
@Override
public void onApply(final Iterator it) {
int index = 0;
int applied = 0;
try {
KVStateOutputList kvStates = KVStateOutputList.newInstance();
while (it.hasNext()) {
KVOperation kvOp;
final KVClosureAdapter done = (KVClosureAdapter) it.done();
if (done != null) {
kvOp = done.getOperation();
} else {
final ByteBuffer buf = it.getData();
try {
if (buf.hasArray()) {
kvOp = this.serializer.readObject(buf.array(), KVOperation.class);
} else {
kvOp = this.serializer.readObject(buf, KVOperation.class);
}
} catch (final Throwable t) {
++index;
throw new StoreCodecException("Decode operation error", t);
}
}
final KVState first = kvStates.getFirstElement();
if (first != null && !first.isSameOp(kvOp)) {
applied += batchApplyAndRecycle(first.getOpByte(), kvStates);
kvStates = KVStateOutputList.newInstance();
}
kvStates.add(KVState.of(kvOp, done));
++index;
it.next();
}
if (!kvStates.isEmpty()) {
final KVState first = kvStates.getFirstElement();
assert first != null;
applied += batchApplyAndRecycle(first.getOpByte(), kvStates);
}
} catch (final Throwable t) {
log.error("StateMachine meet critical error: {}.", StackTraceUtil.stackTrace(t));
it.setErrorAndRollback(index - applied, new Status(RaftError.ESTATEMACHINE, "StateMachine meet critical error: %s.", t.getMessage()));
} finally {
// metrics: qps
this.applyMeter.mark(applied);
}
}
Aggregations