Search in sources :

Example 1 with KVOperation

use of io.dingodb.store.row.storage.KVOperation 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);
}
Also used : Status(io.dingodb.raft.Status) Task(io.dingodb.raft.entity.Task) KVClosureAdapter(io.dingodb.store.row.storage.KVClosureAdapter) KVOperation(io.dingodb.store.row.storage.KVOperation) Region(io.dingodb.store.row.metadata.Region)

Example 2 with KVOperation

use of io.dingodb.store.row.storage.KVOperation 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);
    }
}
Also used : Status(io.dingodb.raft.Status) KVClosureAdapter(io.dingodb.store.row.storage.KVClosureAdapter) StoreCodecException(io.dingodb.store.row.errors.StoreCodecException) KVStateOutputList(io.dingodb.store.row.storage.KVStateOutputList) KVOperation(io.dingodb.store.row.storage.KVOperation) ByteBuffer(java.nio.ByteBuffer) KVState(io.dingodb.store.row.storage.KVState)

Aggregations

Status (io.dingodb.raft.Status)2 KVClosureAdapter (io.dingodb.store.row.storage.KVClosureAdapter)2 KVOperation (io.dingodb.store.row.storage.KVOperation)2 Task (io.dingodb.raft.entity.Task)1 StoreCodecException (io.dingodb.store.row.errors.StoreCodecException)1 Region (io.dingodb.store.row.metadata.Region)1 KVState (io.dingodb.store.row.storage.KVState)1 KVStateOutputList (io.dingodb.store.row.storage.KVStateOutputList)1 ByteBuffer (java.nio.ByteBuffer)1