use of com.pingcap.tikv.operation.KVErrorHandler in project tispark by pingcap.
the class LockResolverClientV3 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;
}
}
use of com.pingcap.tikv.operation.KVErrorHandler in project tispark by pingcap.
the class LockResolverClientV3 method getTxnStatus.
private TxnStatus getTxnStatus(BackOffer bo, Long txnID, ByteString primary, Long currentTS) {
TxnStatus status = getResolved(txnID);
if (status != null) {
return status;
}
Supplier<CleanupRequest> factory = () -> {
TiRegion primaryKeyRegion = regionManager.getRegionByKey(primary);
return CleanupRequest.newBuilder().setContext(primaryKeyRegion.getContext()).setKey(primary).setStartVersion(txnID).setCurrentTs(currentTS).build();
};
status = new TxnStatus();
while (true) {
// new RegionStoreClient for PrimaryKey
RegionStoreClient primaryKeyRegionStoreClient = clientBuilder.build(primary);
TiRegion primaryKeyRegion = primaryKeyRegionStoreClient.getRegion();
KVErrorHandler<CleanupResponse> handler = new KVErrorHandler<>(regionManager, primaryKeyRegionStoreClient, primaryKeyRegionStoreClient.lockResolverClient, resp -> resp.hasRegionError() ? resp.getRegionError() : null, resp -> resp.hasError() ? resp.getError() : null, resolveLockResult -> null, 0L, false);
CleanupResponse resp = primaryKeyRegionStoreClient.callWithRetry(bo, TikvGrpc.getKvCleanupMethod(), factory, handler);
if (resp == null) {
logger.error("getKvCleanupMethod failed without a cause");
regionManager.onRequestFail(primaryKeyRegion);
bo.doBackOff(BoRegionMiss, new TiClientInternalException("getKvCleanupMethod failed without a cause"));
continue;
}
if (resp.hasRegionError()) {
bo.doBackOff(BoRegionMiss, new RegionException(resp.getRegionError()));
continue;
}
if (resp.hasError()) {
Kvrpcpb.KeyError keyError = resp.getError();
// the TTL.
if (keyError.hasLocked()) {
Kvrpcpb.LockInfo lockInfo = keyError.getLocked();
return new TxnStatus(lockInfo.getLockTtl(), 0L);
}
logger.error(String.format("unexpected cleanup err: %s, tid: %d", keyError, txnID));
throw new KeyException(keyError);
}
if (resp.getCommitVersion() != 0) {
status = new TxnStatus(0L, resp.getCommitVersion());
}
saveResolved(txnID, status);
return status;
}
}
use of com.pingcap.tikv.operation.KVErrorHandler in project tispark by pingcap.
the class LockResolverClientV4 method getTxnStatus.
/**
* getTxnStatus sends the CheckTxnStatus request to the TiKV server. When rollbackIfNotExist is
* false, the caller should be careful with the TxnNotFoundException error.
*/
private TxnStatus getTxnStatus(BackOffer bo, Long txnID, ByteString primary, Long callerStartTS, Long currentTS, boolean rollbackIfNotExist, Lock lock) {
TxnStatus status = getResolved(txnID);
if (status != null) {
return status;
}
// CheckTxnStatus may meet the following cases:
// 1. LOCK
// 1.1 Lock expired -- orphan lock, fail to update TTL, crash recovery etc.
// 1.2 Lock TTL -- active transaction holding the lock.
// 2. NO LOCK
// 2.1 Txn Committed
// 2.2 Txn Rollbacked -- rollback itself, rollback by others, GC tomb etc.
// 2.3 No lock -- pessimistic lock rollback, concurrence prewrite.
Supplier<Kvrpcpb.CheckTxnStatusRequest> factory = () -> {
TiRegion primaryKeyRegion = regionManager.getRegionByKey(primary);
return Kvrpcpb.CheckTxnStatusRequest.newBuilder().setContext(primaryKeyRegion.getContext()).setPrimaryKey(primary).setLockTs(txnID).setCallerStartTs(callerStartTS).setCurrentTs(currentTS).setRollbackIfNotExist(rollbackIfNotExist).build();
};
while (true) {
// new RegionStoreClient for PrimaryKey
RegionStoreClient primaryKeyRegionStoreClient = clientBuilder.build(primary);
TiRegion primaryKeyRegion = primaryKeyRegionStoreClient.getRegion();
KVErrorHandler<Kvrpcpb.CheckTxnStatusResponse> handler = new KVErrorHandler<>(regionManager, primaryKeyRegionStoreClient, primaryKeyRegionStoreClient.lockResolverClient, resp -> resp.hasRegionError() ? resp.getRegionError() : null, resp -> resp.hasError() ? resp.getError() : null, resolveLockResult -> null, callerStartTS, false);
Kvrpcpb.CheckTxnStatusResponse resp = primaryKeyRegionStoreClient.callWithRetry(bo, TikvGrpc.getKvCheckTxnStatusMethod(), factory, handler);
if (resp == null) {
logger.error("getKvCheckTxnStatusMethod failed without a cause");
regionManager.onRequestFail(primaryKeyRegion);
bo.doBackOff(BoRegionMiss, new TiClientInternalException("getKvCheckTxnStatusMethod failed without a cause"));
continue;
}
if (resp.hasRegionError()) {
bo.doBackOff(BoRegionMiss, new RegionException(resp.getRegionError()));
continue;
}
if (resp.hasError()) {
Kvrpcpb.KeyError keyError = resp.getError();
if (keyError.hasTxnNotFound()) {
throw new TxnNotFoundException();
}
logger.error(String.format("unexpected cleanup err: %s, tid: %d", keyError, txnID));
throw new KeyException(keyError);
}
status = new TxnStatus();
status.setAction(resp.getAction());
status.setPrimaryLock(resp.getLockInfo());
if (status.getPrimaryLock() != null && status.getPrimaryLock().getUseAsyncCommit()) {
if (!TsoUtils.isExpired(txnID, resp.getLockTtl())) {
status.setTtl(resp.getLockTtl());
}
} else if (resp.getLockTtl() != 0) {
status.setTtl(resp.getLockTtl());
} else {
status.setCommitTS(resp.getCommitVersion());
// change.
if (status.isCommitted() || (lock != null && lock.getLockType() != org.tikv.kvproto.Kvrpcpb.Op.PessimisticLock)) {
saveResolved(txnID, status);
}
}
return status;
}
}
use of com.pingcap.tikv.operation.KVErrorHandler in project tispark by pingcap.
the class LockResolverClientV4 method resolvePessimisticLock.
private void resolvePessimisticLock(BackOffer bo, Lock lock, Set<RegionVerID> cleanRegion) {
while (true) {
region = regionManager.getRegionByKey(lock.getKey());
if (cleanRegion.contains(region.getVerID())) {
return;
}
final long forUpdateTS = lock.getLockForUpdateTs() == 0L ? Long.MAX_VALUE : lock.getLockForUpdateTs();
Supplier<Kvrpcpb.PessimisticRollbackRequest> factory = () -> Kvrpcpb.PessimisticRollbackRequest.newBuilder().setContext(region.getContext()).setStartVersion(lock.getTxnID()).setForUpdateTs(forUpdateTS).addKeys(lock.getKey()).build();
KVErrorHandler<Kvrpcpb.PessimisticRollbackResponse> handler = new KVErrorHandler<>(regionManager, this, this, resp -> resp.hasRegionError() ? resp.getRegionError() : null, resp -> resp.getErrorsCount() > 0 ? resp.getErrorsList().get(0) : null, resolveLockResult -> null, 0L, false);
Kvrpcpb.PessimisticRollbackResponse resp = callWithRetry(bo, TikvGrpc.getKVPessimisticRollbackMethod(), factory, handler);
if (resp == null) {
logger.error("getKVPessimisticRollbackMethod failed without a cause");
regionManager.onRequestFail(region);
bo.doBackOff(BoRegionMiss, new TiClientInternalException("getKVPessimisticRollbackMethod failed without a cause"));
continue;
}
if (resp.hasRegionError()) {
bo.doBackOff(BoRegionMiss, new RegionException(resp.getRegionError()));
continue;
}
if (resp.getErrorsCount() > 0) {
logger.error(String.format("unexpected resolveLock err: %s, lock: %s", resp.getErrorsList().get(0), lock));
throw new KeyException(resp.getErrorsList().get(0));
}
}
}
use of com.pingcap.tikv.operation.KVErrorHandler in project tispark by pingcap.
the class LockResolverClientV4 method checkSecondaries.
private boolean checkSecondaries(BackOffer bo, long txnID, List<ByteString> curKeys, TiRegion tiRegion, AsyncResolveData shared) {
RegionStoreClient regionStoreClient = clientBuilder.build(tiRegion);
Supplier<Kvrpcpb.CheckSecondaryLocksRequest> factory = () -> Kvrpcpb.CheckSecondaryLocksRequest.newBuilder().setContext(tiRegion.getContext()).setStartVersion(txnID).addAllKeys(curKeys).build();
KVErrorHandler<Kvrpcpb.CheckSecondaryLocksResponse> handler = new KVErrorHandler<>(regionManager, regionStoreClient, regionStoreClient.lockResolverClient, resp -> null, resp -> null, resolveLockResult -> null, 0L, false);
Kvrpcpb.CheckSecondaryLocksResponse resp = regionStoreClient.callWithRetry(bo, TikvGrpc.getKvCheckSecondaryLocksMethod(), factory, handler);
if (resp == null) {
logger.error("getKvCheckSecondaryLocksMethod failed without a cause");
regionManager.onRequestFail(tiRegion);
bo.doBackOff(BoRegionMiss, new TiClientInternalException("getKvCheckSecondaryLocksMethod failed without a cause"));
logger.debug(String.format("checkSecondaries: region error, regrouping, txnID=%d, regionId=%d", txnID, tiRegion.getId()));
// If regions have changed, then we might need to regroup the keys. Since this should be rare
// and for the sake of simplicity, we will resolve regions sequentially.
Map<TiRegion, List<ByteString>> groupResult = groupKeysByRegion(this.regionManager, curKeys, bo);
for (Map.Entry<TiRegion, List<ByteString>> entry : groupResult.entrySet()) {
TiRegion region = entry.getKey();
List<ByteString> keys = entry.getValue();
checkSecondaries(bo, txnID, keys, region, shared);
}
}
shared.addKeys(resp.getLocksList(), curKeys.size(), txnID, resp.getCommitTs());
return true;
}
Aggregations