/// <summary> /// Asynchronously checks the replications status of a key. /// </summary> /// <param name="observeParams">The <see cref="ObserveParams"/> object.</param> /// <param name="replicaIndex">The replicaIndex of the replica within the <see cref="IVBucket"/></param> /// <returns>True if the durability requirements specified by <see cref="PersistTo"/> and <see cref="ReplicateTo"/> have been satisfied.</returns> private async Task <bool> CheckReplicaAsync(ObserveParams observeParams, int replicaIndex) { if (observeParams.IsDurabilityMet()) { return(true); } var operation = new Observe(observeParams.Key, observeParams.VBucket, _clusterController.Transcoder, (uint)_timeout); var tcs = new TaskCompletionSource <IOperationResult <ObserveState> >(); operation.Completed = CallbackFactory.CompletedFuncForRetry(_pending, _clusterController, tcs); _pending.TryAdd(operation.Opaque, operation); var replica = observeParams.VBucket.LocateReplica(replicaIndex); await replica.SendAsync(operation).ContinueOnAnyContext(); var result = await tcs.Task.ContinueOnAnyContext(); Log.Debug("Replica {0} - {1} {2} - opaque: {3} key:{4}", replica.EndPoint, result.Value.KeyState, replicaIndex, operation.Opaque, observeParams.Key); var state = result.Value; if (state.KeyState == observeParams.Criteria.PersistState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); Interlocked.Increment(ref observeParams.PersistedToCount); } else if (state.KeyState == observeParams.Criteria.ReplicateState) { Interlocked.Increment(ref observeParams.ReplicatedToCount); } return(!observeParams.HasMutated(state.Cas)); }
private async Task <bool> CheckPersistToAsync(ObserveParams observeParams) { if (observeParams.PersistTo == PersistTo.Zero) { return(true); } var op = new ObserveSeqno(observeParams.Token, _clusterController.Transcoder, _timeout); observeParams.Operation = op; var tcs = new TaskCompletionSource <IOperationResult <ObserveSeqnoResponse> >(); op.Completed = CallbackFactory.CompletedFuncForRetry(_pending, _clusterController, tcs); _pending.TryAdd(op.Opaque, op); var server = await GetServerAsync(observeParams); await server.SendAsync(op).ContinueOnAnyContext(); var response = await tcs.Task.ContinueOnAnyContext(); observeParams.CheckMutationLost(response); observeParams.CheckPersisted(response); return(observeParams.IsDurabilityMet()); }
/// <summary> /// Checks the primary node for the key, if a NMV is encountered, will retry on each replica, asynchronously. /// </summary> /// <typeparam name="T">The Type of the body of the request.</typeparam> /// <param name="operation">The <see cref="IOperation" /> to execiute.</param> /// <returns> /// The <see cref="Task{IOperationResult}" /> object representing asynchcronous operation. /// </returns> /// <exception cref="System.NotImplementedException"></exception> public async Task <IOperationResult <T> > ReadFromReplicaAsync <T>(ReplicaRead <T> operation) { var tcs = new TaskCompletionSource <IOperationResult <T> >(); var cts = new CancellationTokenSource(OperationLifeSpan); cts.CancelAfter(OperationLifeSpan); var keyMapper = ConfigInfo.GetKeyMapper(); var vBucket = (IVBucket)keyMapper.MapKey(operation.Key); operation.VBucket = vBucket; operation.Completed = CallbackFactory.CompletedFuncForRetry(this, Pending, ClusterController, tcs); Pending.TryAdd(operation.Opaque, operation); IOperationResult <T> result = new OperationResult <T>(); foreach (var index in vBucket.Replicas) { var replica = vBucket.LocateReplica(index); if (replica == null) { continue; } await replica.SendAsync(operation).ConfigureAwait(false); result = await tcs.Task; if (result.Success && !result.IsNmv()) { return(result); } } return(result); }
/// <summary> /// Checks the primary node for the key, if a NMV is encountered, will retry on each replica, asynchronously. /// </summary> /// <typeparam name="T">The Type of the body of the request.</typeparam> /// <param name="operation">The <see cref="IOperation" /> to execiute.</param> /// <returns> /// The <see cref="Task{IOperationResult}" /> object representing asynchcronous operation. /// </returns> public async Task <IOperationResult <T> > ReadFromReplicaAsync <T>(ReplicaRead <T> operation) { var tcs = new TaskCompletionSource <IOperationResult <T> >(); var cts = new CancellationTokenSource(OperationLifeSpan); cts.CancelAfter(OperationLifeSpan); var keyMapper = ConfigInfo.GetKeyMapper(); var vBucket = (IVBucket)keyMapper.MapKey(operation.Key); operation.VBucket = vBucket; operation.Completed = CallbackFactory.CompletedFuncForRetry(Pending, ClusterController, tcs); Pending.TryAdd(operation.Opaque, operation); IOperationResult <T> result = null; if (vBucket.HasReplicas) { foreach (var index in vBucket.Replicas) { var replica = vBucket.LocateReplica(index); if (replica == null) { continue; } await replica.SendAsync(operation).ContinueOnAnyContext(); result = await tcs.Task; if (result.Success && !result.IsNmv()) { return(result); } } } else { result = new OperationResult <T> { Id = operation.Key, Status = ResponseStatus.NoReplicasFound, Message = "No replicas found; have you configured the bucket for replica reads?", Success = false }; } return(result); }
public Task <IOperationResult <ObserveState> > ObserveAsync(Observe operation) { var tcs = new TaskCompletionSource <IOperationResult <ObserveState> >(); var cts = new CancellationTokenSource(OperationLifeSpan); cts.CancelAfter(OperationLifeSpan); var keyMapper = ConfigInfo.GetKeyMapper(); var vBucket = (IVBucket)keyMapper.MapKey(operation.Key); operation.VBucket = vBucket; operation.Completed = CallbackFactory.CompletedFuncForRetry(Pending, ClusterController, tcs); Pending.TryAdd(operation.Opaque, operation); var server = vBucket.LocatePrimary(); server.SendAsync(operation); return(tcs.Task); }
private async Task <bool> CheckPersistToAsync(ObserveParams observeParams) { if (observeParams.PersistTo == PersistTo.Zero) { return(true); } var tcs = new TaskCompletionSource <IOperationResult <ObserveState> >(); var operation = new Observe(observeParams.Key, observeParams.VBucket, _clusterController.Transcoder, (uint)_timeout); operation.Completed = CallbackFactory.CompletedFuncForRetry(_pending, _clusterController, tcs); _pending.TryAdd(operation.Opaque, operation); var server = await GetServerAsync(observeParams); await server.SendAsync(operation).ContinueOnAnyContext(); var result = await tcs.Task.ContinueOnAnyContext(); Log.Debug("Master {0} - {1} key:{2}", server.EndPoint, result.Value, observeParams.Key); var state = result.Value; if (state.KeyState == observeParams.Criteria.PersistState) { Interlocked.Increment(ref observeParams.PersistedToCount); } //Key mutation detected so fail if (observeParams.HasMutated(state.Cas)) { Log.Debug("Mutation detected {0} - {1} - opaque: {2} key:{3}", server.EndPoint, result.Value, operation.Opaque, observeParams.Key); throw new DocumentMutationException(string.Format("Document mutation detected during observe for key '{0}'", observeParams.Key)); } //Check if durability requirements have been met if (observeParams.IsDurabilityMet()) { Log.Debug("Durability met {0} - {1} - opaque: {2} key:{3}", server.EndPoint, result.Value, operation.Opaque, observeParams.Key); return(true); } return(false); }
private async Task <bool> CheckReplicaAsync(ObserveParams observeParams, int replicaId) { var op = new ObserveSeqno(observeParams.Token, _clusterController.Transcoder, _timeout); observeParams.Operation = op; var tcs = new TaskCompletionSource <IOperationResult <ObserveSeqnoResponse> >(); op.Completed = CallbackFactory.CompletedFuncForRetry(_pending, _clusterController, tcs); _pending.TryAdd(op.Opaque, op); Log.Debug("checking replica {0} - opaque: {1}", replicaId, op.Opaque); var replica = observeParams.VBucket.LocateReplica(replicaId); await replica.SendAsync(op).ContinueOnAnyContext(); var response = await tcs.Task.ContinueOnAnyContext(); observeParams.CheckMutationLost(response); observeParams.CheckPersisted(response); observeParams.CheckReplicated(response); return(observeParams.IsDurabilityMet()); }