Search in sources :

Example 1 with KeyException

use of com.pingcap.tikv.exception.KeyException in project tispark by pingcap.

the class KVErrorHandler method handleResponseError.

// Referenced from TiDB
// store/tikv/region_request.go - onRegionError
/**
 * @return true: client should retry
 */
@Override
public boolean handleResponseError(BackOffer backOffer, RespT resp) {
    if (resp == null) {
        String msg = String.format("Request Failed with unknown reason for region region [%s]", recv.getRegion());
        logger.warn(msg);
        return handleRequestError(backOffer, new GrpcException(msg));
    }
    // Region error handling logic
    Errorpb.Error error = getRegionError(resp);
    if (error != null) {
        if (error.hasNotLeader()) {
            // this error is reported from raftstore:
            // peer of current request is not leader, the following might be its causes:
            // 1. cache is outdated, region has changed its leader, can be solved by re-fetching from PD
            // 2. leader of current region is missing, need to wait and then fetch region info from PD
            long newStoreId = error.getNotLeader().getLeader().getStoreId();
            boolean retry;
            // update Leader here
            logger.warn(String.format("NotLeader Error with region id %d and store id %d, new store id %d", recv.getRegion().getId(), recv.getRegion().getLeader().getStoreId(), newStoreId));
            BackOffFunction.BackOffFuncType backOffFuncType;
            // since issuing store = NO_LEADER_STORE_ID requests to pd will definitely fail.
            if (newStoreId != NO_LEADER_STORE_ID) {
                // If update leader fails, we need to fetch new region info from pd,
                // and re-split key range for new region. Setting retry to false will
                // stop retry and enter handleCopResponse logic, which would use RegionMiss
                // backOff strategy to wait, fetch new region and re-split key range.
                // onNotLeader is only needed when updateLeader succeeds, thus switch
                // to a new store address.
                TiRegion newRegion = this.regionManager.updateLeader(recv.getRegion(), newStoreId);
                retry = newRegion != null && recv.onNotLeader(this.regionManager.getStoreById(newStoreId), newRegion);
                if (!retry) {
                    notifyRegionStoreCacheInvalidate(recv.getRegion(), CacheInvalidateEvent.CacheType.LEADER);
                }
                backOffFuncType = BackOffFunction.BackOffFuncType.BoUpdateLeader;
            } else {
                logger.info(String.format("Received zero store id, from region %d try next time", recv.getRegion().getId()));
                backOffFuncType = BackOffFunction.BackOffFuncType.BoRegionMiss;
                retry = false;
            }
            if (!retry) {
                this.regionManager.invalidateRegion(recv.getRegion());
            }
            backOffer.doBackOff(backOffFuncType, new GrpcException(error.toString()));
            return retry;
        } else if (error.hasStoreNotMatch()) {
            // this error is reported from raftstore:
            // store_id requested at the moment is inconsistent with that expected
            // Solution:re-fetch from PD
            long storeId = recv.getRegion().getLeader().getStoreId();
            long actualStoreId = error.getStoreNotMatch().getActualStoreId();
            logger.warn(String.format("Store Not Match happened with region id %d, store id %d, actual store id %d", recv.getRegion().getId(), storeId, actualStoreId));
            invalidateRegionStoreCache(recv.getRegion());
            recv.onStoreNotMatch(this.regionManager.getStoreById(storeId));
            // throwing it out.
            return false;
        } else if (error.hasEpochNotMatch()) {
            // this error is reported from raftstore:
            // region has outdated version,please try later.
            logger.warn(String.format("Stale Epoch encountered for region [%s]", recv.getRegion()));
            this.regionManager.onRegionStale(recv.getRegion());
            notifyRegionCacheInvalidate(recv.getRegion());
            return false;
        } else if (error.hasServerIsBusy()) {
            // this error is reported from kv:
            // will occur when write pressure is high. Please try later.
            logger.warn(String.format("Server is busy for region [%s], reason: %s", recv.getRegion(), error.getServerIsBusy().getReason()));
            backOffer.doBackOff(BackOffFunction.BackOffFuncType.BoServerBusy, new StatusRuntimeException(Status.fromCode(Status.Code.UNAVAILABLE).withDescription(error.toString())));
            backOffer.doBackOff(BackOffFunction.BackOffFuncType.BoRegionMiss, new GrpcException(error.getMessage()));
            return true;
        } else if (error.hasRegionNotFound()) {
            backOffer.doBackOff(BackOffFunction.BackOffFuncType.BoRegionMiss, new GrpcException(error.getMessage()));
            this.regionManager.onRegionStale(recv.getRegion());
            notifyRegionCacheInvalidate(recv.getRegion());
            return false;
        } else if (error.hasStaleCommand()) {
            // this error is reported from raftstore:
            // command outdated, please try later
            logger.warn(String.format("Stale command for region [%s]", recv.getRegion()));
            backOffer.doBackOff(BackOffFunction.BackOffFuncType.BoRegionMiss, new GrpcException(error.getMessage()));
            return true;
        } else if (error.hasRaftEntryTooLarge()) {
            logger.warn(String.format("Raft too large for region [%s]", recv.getRegion()));
            throw new StatusRuntimeException(Status.fromCode(Status.Code.UNAVAILABLE).withDescription(error.toString()));
        } else if (error.hasKeyNotInRegion()) {
            // this error is reported from raftstore:
            // key requested is not in current region
            // should not happen here.
            ByteString invalidKey = error.getKeyNotInRegion().getKey();
            logger.error(String.format("Key not in region [%s] for key [%s], this error should not happen here.", recv.getRegion(), KeyUtils.formatBytesUTF8(invalidKey)));
            throw new StatusRuntimeException(Status.UNKNOWN.withDescription(error.toString()));
        }
        logger.warn(String.format("Unknown error %s for region [%s]", error, recv.getRegion()));
        // For other errors, we only drop cache here.
        // Upper level may split this task.
        invalidateRegionStoreCache(recv.getRegion());
        // retry if raft proposal is dropped, it indicates the store is in the middle of transition
        if (error.getMessage().contains("Raft ProposalDropped") || error.getMessage().contains("is missing")) {
            backOffer.doBackOff(BackOffFunction.BackOffFuncType.BoRegionMiss, new GrpcException(error.getMessage()));
            return true;
        }
    }
    boolean retry = false;
    if (resp instanceof ScanResponse) {
        List<KvPair> kvPairs = ((ScanResponse) resp).getPairsList();
        List<Lock> locks = new ArrayList<>();
        for (KvPair kvPair : kvPairs) {
            if (kvPair.hasError()) {
                Lock lock = AbstractLockResolverClient.extractLockFromKeyErr(kvPair.getError());
                locks.add(lock);
            }
        }
        if (!locks.isEmpty()) {
            try {
                resolveLocks(backOffer, locks);
                retry = true;
            } catch (KeyException e) {
                logger.warn("Unable to handle KeyExceptions other than LockException", e);
            }
        }
    } else {
        // Key error handling logic
        Kvrpcpb.KeyError keyError = getKeyError.apply(resp);
        if (keyError != null) {
            try {
                Lock lock = AbstractLockResolverClient.extractLockFromKeyErr(keyError);
                resolveLock(backOffer, lock);
                retry = true;
            } catch (KeyException e) {
                logger.warn("Unable to handle KeyExceptions other than LockException", e);
            }
        }
    }
    return retry;
}
Also used : KvPair(org.tikv.kvproto.Kvrpcpb.KvPair) ByteString(com.google.protobuf.ByteString) Kvrpcpb(org.tikv.kvproto.Kvrpcpb) ScanResponse(org.tikv.kvproto.Kvrpcpb.ScanResponse) ArrayList(java.util.ArrayList) BackOffFunction(com.pingcap.tikv.util.BackOffFunction) ByteString(com.google.protobuf.ByteString) Errorpb(org.tikv.kvproto.Errorpb) KeyException(com.pingcap.tikv.exception.KeyException) Lock(com.pingcap.tikv.txn.Lock) TiRegion(com.pingcap.tikv.region.TiRegion) GrpcException(com.pingcap.tikv.exception.GrpcException) StatusRuntimeException(io.grpc.StatusRuntimeException)

Example 2 with KeyException

use of com.pingcap.tikv.exception.KeyException in project tispark by pingcap.

the class RegionStoreClient method isPrewriteSuccess.

/**
 * @param backOffer backOffer
 * @param resp response
 * @return Return true means the rpc call success. Return false means the rpc call fail,
 *     RegionStoreClient should retry. Throw an Exception means the rpc call fail,
 *     RegionStoreClient cannot handle this kind of error
 * @throws TiClientInternalException
 * @throws RegionException
 * @throws KeyException
 */
private boolean isPrewriteSuccess(BackOffer backOffer, PrewriteResponse resp, long startTs) throws TiClientInternalException, KeyException, RegionException {
    boolean forWrite = true;
    if (resp == null) {
        this.regionManager.onRequestFail(region);
        throw new TiClientInternalException("Prewrite Response failed without a cause");
    }
    if (resp.hasRegionError()) {
        throw new RegionException(resp.getRegionError());
    }
    boolean isSuccess = true;
    List<Lock> locks = new ArrayList<>();
    for (KeyError err : resp.getErrorsList()) {
        if (err.hasLocked()) {
            isSuccess = false;
            Lock lock = new Lock(err.getLocked());
            locks.add(lock);
        } else {
            throw new KeyException(err.toString());
        }
    }
    if (isSuccess) {
        return true;
    }
    ResolveLockResult resolveLockResult = lockResolverClient.resolveLocks(backOffer, startTs, locks, forWrite);
    addResolvedLocks(startTs, resolveLockResult.getResolvedLocks());
    long msBeforeExpired = resolveLockResult.getMsBeforeTxnExpired();
    if (msBeforeExpired > 0) {
        backOffer.doBackOffWithMaxSleep(BoTxnLock, msBeforeExpired, new KeyException(resp.getErrorsList().get(0)));
    }
    return false;
}
Also used : KeyError(org.tikv.kvproto.Kvrpcpb.KeyError) TiClientInternalException(com.pingcap.tikv.exception.TiClientInternalException) ArrayList(java.util.ArrayList) ResolveLockResult(com.pingcap.tikv.txn.ResolveLockResult) RegionException(com.pingcap.tikv.exception.RegionException) KeyException(com.pingcap.tikv.exception.KeyException) Lock(com.pingcap.tikv.txn.Lock) BoTxnLock(com.pingcap.tikv.util.BackOffFunction.BackOffFuncType.BoTxnLock)

Example 3 with KeyException

use of com.pingcap.tikv.exception.KeyException in project tispark by pingcap.

the class LockResolverClientV4 method resolveLock.

private void resolveLock(BackOffer bo, Lock lock, TxnStatus txnStatus, Set<RegionVerID> cleanRegion) {
    boolean cleanWholeRegion = lock.getTxnSize() >= BIG_TXN_THRESHOLD;
    while (true) {
        region = regionManager.getRegionByKey(lock.getKey());
        if (cleanRegion.contains(region.getVerID())) {
            return;
        }
        Kvrpcpb.ResolveLockRequest.Builder builder = Kvrpcpb.ResolveLockRequest.newBuilder().setContext(region.getContext()).setStartVersion(lock.getTxnID());
        if (txnStatus.isCommitted()) {
            // txn is committed with commitTS txnStatus
            builder.setCommitVersion(txnStatus.getCommitTS());
        }
        if (lock.getTxnSize() < BIG_TXN_THRESHOLD) {
            // Only resolve specified keys when it is a small transaction,
            // prevent from scanning the whole region in this case.
            builder.addKeys(lock.getKey());
        }
        Supplier<Kvrpcpb.ResolveLockRequest> factory = builder::build;
        KVErrorHandler<Kvrpcpb.ResolveLockResponse> handler = new KVErrorHandler<>(regionManager, this, this, resp -> resp.hasRegionError() ? resp.getRegionError() : null, resp -> resp.hasError() ? resp.getError() : null, resolveLockResult -> null, 0L, false);
        Kvrpcpb.ResolveLockResponse resp = callWithRetry(bo, TikvGrpc.getKvResolveLockMethod(), factory, handler);
        if (resp == null) {
            logger.error("getKvResolveLockMethod failed without a cause");
            regionManager.onRequestFail(region);
            bo.doBackOff(BoRegionMiss, new TiClientInternalException("getKvResolveLockMethod failed without a cause"));
            continue;
        }
        if (resp.hasRegionError()) {
            bo.doBackOff(BoRegionMiss, new RegionException(resp.getRegionError()));
            continue;
        }
        if (resp.hasError()) {
            logger.error(String.format("unexpected resolveLock err: %s, lock: %s", resp.getError(), lock));
            throw new KeyException(resp.getError());
        }
        if (cleanWholeRegion) {
            cleanRegion.add(region.getVerID());
        }
        return;
    }
}
Also used : TiClientInternalException(com.pingcap.tikv.exception.TiClientInternalException) Kvrpcpb(org.tikv.kvproto.Kvrpcpb) KVErrorHandler(com.pingcap.tikv.operation.KVErrorHandler) RegionException(com.pingcap.tikv.exception.RegionException) KeyException(com.pingcap.tikv.exception.KeyException)

Example 4 with KeyException

use of com.pingcap.tikv.exception.KeyException in project tispark by pingcap.

the class ConcreteScanIterator method resolveCurrentLock.

private ByteString resolveCurrentLock(Kvrpcpb.KvPair current) {
    logger.warn(String.format("resolve current key error %s", current.getError().toString()));
    Pair<TiRegion, Metapb.Store> pair = builder.getRegionManager().getRegionStorePairByKey(current.getKey());
    TiRegion region = pair.first;
    Metapb.Store store = pair.second;
    BackOffer backOffer = ConcreteBackOffer.newGetBackOff();
    try (RegionStoreClient client = builder.build(region, store)) {
        return client.get(backOffer, current.getKey(), version);
    } catch (Exception e) {
        throw new KeyException(current.getError());
    }
}
Also used : TiRegion(com.pingcap.tikv.region.TiRegion) ConcreteBackOffer(com.pingcap.tikv.util.ConcreteBackOffer) BackOffer(com.pingcap.tikv.util.BackOffer) Metapb(org.tikv.kvproto.Metapb) RegionStoreClient(com.pingcap.tikv.region.RegionStoreClient) GrpcException(com.pingcap.tikv.exception.GrpcException) TiKVException(com.pingcap.tikv.exception.TiKVException) KeyException(com.pingcap.tikv.exception.KeyException) KeyException(com.pingcap.tikv.exception.KeyException)

Example 5 with KeyException

use of com.pingcap.tikv.exception.KeyException in project tispark by pingcap.

the class LockResolverClientV2 method resolveLock.

private void resolveLock(BackOffer bo, Lock lock, long txnStatus, Set<RegionVerID> cleanRegion) {
    while (true) {
        region = regionManager.getRegionByKey(lock.getKey());
        if (cleanRegion.contains(region.getVerID())) {
            return;
        }
        Supplier<ResolveLockRequest> factory;
        if (txnStatus > 0) {
            // txn is committed with commitTS txnStatus
            factory = () -> ResolveLockRequest.newBuilder().setContext(region.getContext()).setStartVersion(lock.getTxnID()).setCommitVersion(txnStatus).build();
        } else {
            factory = () -> ResolveLockRequest.newBuilder().setContext(region.getContext()).setStartVersion(lock.getTxnID()).build();
        }
        KVErrorHandler<ResolveLockResponse> handler = new KVErrorHandler<>(regionManager, this, this, resp -> resp.hasRegionError() ? resp.getRegionError() : null, resp -> resp.hasError() ? resp.getError() : null, resolveLockResult -> null, 0L, false);
        ResolveLockResponse resp = callWithRetry(bo, TikvGrpc.getKvResolveLockMethod(), factory, handler);
        if (resp == null) {
            logger.error("getKvResolveLockMethod failed without a cause");
            regionManager.onRequestFail(region);
            bo.doBackOff(BoRegionMiss, new TiClientInternalException("getKvResolveLockMethod failed without a cause"));
            continue;
        }
        if (resp.hasRegionError()) {
            bo.doBackOff(BoRegionMiss, new RegionException(resp.getRegionError()));
            continue;
        }
        if (resp.hasError()) {
            logger.error(String.format("unexpected resolveLock err: %s, lock: %s", resp.getError(), lock));
            throw new KeyException(resp.getError());
        }
        cleanRegion.add(region.getVerID());
        return;
    }
}
Also used : TiClientInternalException(com.pingcap.tikv.exception.TiClientInternalException) ResolveLockRequest(org.tikv.kvproto.Kvrpcpb.ResolveLockRequest) KVErrorHandler(com.pingcap.tikv.operation.KVErrorHandler) RegionException(com.pingcap.tikv.exception.RegionException) ResolveLockResponse(org.tikv.kvproto.Kvrpcpb.ResolveLockResponse) KeyException(com.pingcap.tikv.exception.KeyException)

Aggregations

KeyException (com.pingcap.tikv.exception.KeyException)15 TiClientInternalException (com.pingcap.tikv.exception.TiClientInternalException)10 RegionException (com.pingcap.tikv.exception.RegionException)9 KVErrorHandler (com.pingcap.tikv.operation.KVErrorHandler)8 TiRegion (com.pingcap.tikv.region.TiRegion)7 Kvrpcpb (org.tikv.kvproto.Kvrpcpb)7 RegionStoreClient (com.pingcap.tikv.region.RegionStoreClient)6 ArrayList (java.util.ArrayList)4 ByteString (com.google.protobuf.ByteString)3 AbstractRegionStoreClient (com.pingcap.tikv.region.AbstractRegionStoreClient)3 Lock (com.pingcap.tikv.txn.Lock)3 ResolveLockResult (com.pingcap.tikv.txn.ResolveLockResult)3 BackOffer (com.pingcap.tikv.util.BackOffer)3 ConcreteBackOffer (com.pingcap.tikv.util.ConcreteBackOffer)3 GrpcException (com.pingcap.tikv.exception.GrpcException)2 TiKVException (com.pingcap.tikv.exception.TiKVException)2 TiTimestamp (com.pingcap.tikv.meta.TiTimestamp)2 BoTxnLock (com.pingcap.tikv.util.BackOffFunction.BackOffFuncType.BoTxnLock)2 Test (org.junit.Test)2 CleanupRequest (org.tikv.kvproto.Kvrpcpb.CleanupRequest)2