use of com.alipay.sofa.jraft.rhea.util.ByteArray in project sofa-jraft by sofastack.
the class MemoryRawKVStore method tryLockWith.
@Override
public void tryLockWith(final byte[] key, final byte[] fencingKey, final boolean keepLease, final DistributedLock.Acquirer acquirer, final KVStoreClosure closure) {
final Timer.Context timeCtx = getTimeContext("TRY_LOCK");
try {
// The algorithm relies on the assumption that while there is no
// synchronized clock across the processes, still the local time in
// every process flows approximately at the same rate, with an error
// which is small compared to the auto-release time of the lock.
final long now = acquirer.getLockingTimestamp();
final long timeoutMillis = acquirer.getLeaseMillis();
final ByteArray wrappedKey = ByteArray.wrap(key);
final DistributedLock.Owner prevOwner = this.lockerDB.get(wrappedKey);
final DistributedLock.Owner owner;
// noinspection ConstantConditions
do {
final DistributedLock.OwnerBuilder builder = DistributedLock.newOwnerBuilder();
if (prevOwner == null) {
// no others own this lock
if (keepLease) {
// it wants to keep the lease but too late, will return failure
owner = //
builder.id(acquirer.getId()).remainingMillis(DistributedLock.OwnerBuilder.KEEP_LEASE_FAIL).success(false).build();
break;
}
// is first time to try lock (another possibility is that this lock has been deleted),
// will return successful
owner = //
builder.id(acquirer.getId()).deadlineMillis(now + timeoutMillis).remainingMillis(DistributedLock.OwnerBuilder.FIRST_TIME_SUCCESS).fencingToken(getNextFencingToken(fencingKey)).acquires(1).context(acquirer.getContext()).success(true).build();
this.lockerDB.put(wrappedKey, owner);
break;
}
// this lock has an owner, check if it has expired
final long remainingMillis = prevOwner.getDeadlineMillis() - now;
if (remainingMillis < 0) {
// the previous owner is out of lease
if (keepLease) {
// it wants to keep the lease but too late, will return failure
owner = //
builder.id(prevOwner.getId()).deadlineMillis(prevOwner.getDeadlineMillis()).remainingMillis(DistributedLock.OwnerBuilder.KEEP_LEASE_FAIL).context(prevOwner.getContext()).success(false).build();
break;
}
// create new lock owner
owner = //
builder.id(acquirer.getId()).deadlineMillis(now + timeoutMillis).remainingMillis(DistributedLock.OwnerBuilder.NEW_ACQUIRE_SUCCESS).fencingToken(getNextFencingToken(fencingKey)).acquires(1).context(acquirer.getContext()).success(true).build();
this.lockerDB.put(wrappedKey, owner);
break;
}
// the previous owner is not out of lease (remainingMillis >= 0)
final boolean isReentrant = prevOwner.isSameAcquirer(acquirer);
if (isReentrant) {
// is the same old friend come back (reentrant lock)
if (keepLease) {
// the old friend only wants to keep lease of lock
owner = //
builder.id(prevOwner.getId()).deadlineMillis(now + timeoutMillis).remainingMillis(DistributedLock.OwnerBuilder.KEEP_LEASE_SUCCESS).fencingToken(prevOwner.getFencingToken()).acquires(prevOwner.getAcquires()).context(prevOwner.getContext()).success(true).build();
this.lockerDB.put(wrappedKey, owner);
break;
}
// now we are sure that is an old friend who is back again (reentrant lock)
owner = //
builder.id(prevOwner.getId()).deadlineMillis(now + timeoutMillis).remainingMillis(DistributedLock.OwnerBuilder.REENTRANT_SUCCESS).fencingToken(prevOwner.getFencingToken()).acquires(prevOwner.getAcquires() + 1).context(acquirer.getContext()).success(true).build();
this.lockerDB.put(wrappedKey, owner);
break;
}
// the lock is exist and also prev locker is not the same as current
owner = //
builder.id(prevOwner.getId()).remainingMillis(remainingMillis).context(prevOwner.getContext()).success(false).build();
LOG.debug("Another locker [{}] is trying the existed lock [{}].", acquirer, prevOwner);
} while (false);
setSuccess(closure, owner);
} catch (final Exception e) {
LOG.error("Fail to [TRY_LOCK], [{}, {}], {}.", BytesUtil.toHex(key), acquirer, StackTraceUtil.stackTrace(e));
setCriticalError(closure, "Fail to [TRY_LOCK]", e);
} finally {
timeCtx.stop();
}
}
use of com.alipay.sofa.jraft.rhea.util.ByteArray in project sofa-jraft by sofastack.
the class DefaultMetadataStore method unsafeGetStoreIdsByEndpoints.
@Override
public Map<Long, Endpoint> unsafeGetStoreIdsByEndpoints(final long clusterId, final List<Endpoint> endpoints) {
if (endpoints == null || endpoints.isEmpty()) {
return Collections.emptyMap();
}
final List<byte[]> storeIdKeyList = Lists.newArrayListWithCapacity(endpoints.size());
final Map<ByteArray, Endpoint> keyToEndpointMap = Maps.newHashMapWithExpectedSize(endpoints.size());
for (final Endpoint endpoint : endpoints) {
final byte[] keyBytes = BytesUtil.writeUtf8(MetadataKeyHelper.getStoreIdKey(clusterId, endpoint));
storeIdKeyList.add(keyBytes);
keyToEndpointMap.put(ByteArray.wrap(keyBytes), endpoint);
}
final Map<ByteArray, byte[]> storeIdBytes = this.rheaKVStore.bMultiGet(storeIdKeyList);
final Map<Long, Endpoint> ids = Maps.newHashMapWithExpectedSize(storeIdBytes.size());
for (final Map.Entry<ByteArray, byte[]> entry : storeIdBytes.entrySet()) {
final Long storeId = Bits.getLong(entry.getValue(), 0);
final Endpoint endpoint = keyToEndpointMap.get(entry.getKey());
ids.put(storeId, endpoint);
}
return ids;
}
use of com.alipay.sofa.jraft.rhea.util.ByteArray in project sofa-jraft by sofastack.
the class DefaultRheaKVStore method internalRegionMultiGet.
private void internalRegionMultiGet(final Region region, final List<byte[]> subKeys, final boolean readOnlySafe, final CompletableFuture<Map<ByteArray, byte[]>> future, final int retriesLeft, final Errors lastCause, final boolean requireLeader) {
final RegionEngine regionEngine = getRegionEngine(region.getId(), requireLeader);
// require leader on retry
final RetryRunner retryRunner = retryCause -> internalRegionMultiGet(region, subKeys, readOnlySafe, future, retriesLeft - 1, retryCause, true);
final FailoverClosure<Map<ByteArray, byte[]>> closure = new FailoverClosureImpl<>(future, false, retriesLeft, retryRunner);
if (regionEngine != null) {
if (ensureOnValidEpoch(region, regionEngine, closure)) {
final RawKVStore rawKVStore = getRawKVStore(regionEngine);
if (this.kvDispatcher == null) {
rawKVStore.multiGet(subKeys, readOnlySafe, closure);
} else {
this.kvDispatcher.execute(() -> rawKVStore.multiGet(subKeys, readOnlySafe, closure));
}
}
} else {
final MultiGetRequest request = new MultiGetRequest();
request.setKeys(subKeys);
request.setReadOnlySafe(readOnlySafe);
request.setRegionId(region.getId());
request.setRegionEpoch(region.getRegionEpoch());
this.rheaKVRpcService.callAsyncWithRpc(request, closure, lastCause, requireLeader);
}
}
use of com.alipay.sofa.jraft.rhea.util.ByteArray in project sofa-jraft by sofastack.
the class DefaultRheaKVStore method internalMultiGet.
private FutureGroup<Map<ByteArray, byte[]>> internalMultiGet(final List<byte[]> keys, final boolean readOnlySafe, final int retriesLeft, final Throwable lastCause) {
final Map<Region, List<byte[]>> regionMap = this.pdClient.findRegionsByKeys(keys, ApiExceptionHelper.isInvalidEpoch(lastCause));
final List<CompletableFuture<Map<ByteArray, byte[]>>> futures = Lists.newArrayListWithCapacity(regionMap.size());
final Errors lastError = lastCause == null ? null : Errors.forException(lastCause);
for (final Map.Entry<Region, List<byte[]>> entry : regionMap.entrySet()) {
final Region region = entry.getKey();
final List<byte[]> subKeys = entry.getValue();
final RetryCallable<Map<ByteArray, byte[]>> retryCallable = retryCause -> internalMultiGet(subKeys, readOnlySafe, retriesLeft - 1, retryCause);
final MapFailoverFuture<ByteArray, byte[]> future = new MapFailoverFuture<>(retriesLeft, retryCallable);
internalRegionMultiGet(region, subKeys, readOnlySafe, future, retriesLeft, lastError, this.onlyLeaderRead);
futures.add(future);
}
return new FutureGroup<>(futures);
}
Aggregations