/// <summary> /// Asynchronously checks the replications status of a key. /// </summary> /// <param name="op">The <see cref="ObserveParams"/> object.</param> /// <param name="replicaIndex">The index 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> static async Task <bool> CheckReplica(ObserveParams op, int replicaIndex) { Log.Debug(m => m("checking replica {0}", replicaIndex)); if (op.IsDurabilityMet()) { return(true); } var replica = op.VBucket.LocateReplica(replicaIndex); var result = await Task.Run(() => replica.Send(new Observe(op.Key, op.VBucket, new AutoByteConverter()))) .ConfigureAwait(false); Log.Debug(m => m("Replica {0} - {1} [0]", replica.EndPoint, result.Value, replicaIndex)); var state = result.Value; if (state.KeyState == op.Criteria.PersistState) { Interlocked.Increment(ref op.ReplicatedToCount); Interlocked.Increment(ref op.PersistedToCount); } else if (state.KeyState == op.Criteria.ReplicateState) { Interlocked.Increment(ref op.ReplicatedToCount); } return(op.IsDurabilityMet() && !op.HasMutated(state.Cas)); }
/// <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)); }
/// <summary> /// Asynchronously checks the replications status of a key. /// </summary> /// <param name="observeParams">The <see cref="ObserveParams"/> object.</param> /// <param name="operation">The Observe operation.</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> static async Task <bool> CheckReplicaAsync(ObserveParams observeParams, Observe operation, int replicaIndex) { Log.Debug(m => m("checking replica {0}", replicaIndex)); if (observeParams.IsDurabilityMet()) { return(true); } //clone the operation since we already checked the primary and we want to maintain internal state (opaque, timer, etc) operation = (Observe)operation.Clone(); var replica = observeParams.VBucket.LocateReplica(replicaIndex); var result = await Task.Run(() => replica.Send(operation)).ContinueOnAnyContext(); Log.Debug(m => m("Replica {0} - {1} [0]", replica.EndPoint, result.Value, replicaIndex)); 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)); }
/// <summary> /// Performs an observe event on the durability requirements specified on a key. /// </summary> /// <param name="key">The key to observe.</param> /// <param name="cas">The 'Check and Set' value of the key.</param> /// <param name="deletion">True if this is a delete operation.</param> /// <param name="replicateTo">The number of replicas that the key must be replicated to to satisfy the durability constraint.</param> /// <param name="persistTo">The number of replicas that the key must be persisted to to satisfy the durability constraint.</param> /// <returns>True if the durability constraints have been met.</returns> /// <exception cref="ReplicaNotConfiguredException">Thrown if the number of replicas requested /// in the ReplicateTo parameter does not match the # of replicas configured on the server.</exception> public bool Observe(string key, ulong cas, bool deletion, ReplicateTo replicateTo, PersistTo persistTo) { var criteria = GetDurabilityCriteria(deletion); var keyMapper = _configInfo.GetKeyMapper(); var vBucket = (IVBucket)keyMapper.MapKey(key); var p = new ObserveParams { Cas = cas, Criteria = criteria, Key = key, PersistTo = persistTo, ReplicateTo = replicateTo, VBucket = vBucket }; p.CheckConfiguredReplicas(); var operation = new Observe(key, vBucket, _clusterController.Transcoder, (uint)_timeout); do { var master = p.VBucket.LocatePrimary(); var result = master.Send(operation); var state = result.Value; if (state.KeyState == p.Criteria.PersistState) { Interlocked.Increment(ref p.PersistedToCount); } if (!deletion && p.HasMutated(state.Cas)) { return(false); } //First check if durability has already been met if (p.IsDurabilityMet()) { return(true); } //If not check each replica if (CheckReplicas(p, operation)) { return(true); } //prepare for another attempt operation = (Observe)operation.Clone(); p.Reset(); } while (!operation.TimedOut()); return(false); }
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); }
/// <summary> /// Checks the replica at a given replicaIndex for the durability constraints. /// </summary> /// <param name="observeParams">The observe parameters - stateful - gather info with each request.</param> /// <param name="operation">The observe operation.</param> /// <param name="replicaIndex">Index of the replica.</param> /// <returns>True if the key has not mutated.</returns> private static bool CheckReplica(ObserveParams observeParams, Observe operation, int replicaIndex) { //clone the operation since we already checked the primary and we want to maintain internal state (opaque, timer, etc) operation = (Observe)operation.Clone(); var replica = observeParams.VBucket.LocateReplica(replicaIndex); var result = replica.Send(operation); //Check the result and update the counters 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)); }
/// <summary> /// Asynchronously checks the replications status of a key. /// </summary> /// <param name="observeParams">The <see cref="ObserveParams"/> object.</param> /// <param name="operation">The Observe operation.</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> static async Task<bool> CheckReplicaAsync(ObserveParams observeParams, Observe operation, int replicaIndex) { Log.Debug(m=>m("checking replica {0}", replicaIndex)); if (observeParams.IsDurabilityMet()) return true; //clone the operation since we already checked the primary and we want to maintain internal state (opaque, timer, etc) operation = (Observe)operation.Clone(); var replica = observeParams.VBucket.LocateReplica(replicaIndex); var result = await Task.Run(()=>replica.Send(operation)).ContinueOnAnyContext(); Log.Debug(m=>m("Replica {0} - {1} [0]", replica.EndPoint, result.Value, replicaIndex)); 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); }
/// <summary> /// Checks the replica at a given replicaIndex for the durability constraints. /// </summary> /// <param name="observeParams">The observe parameters - stateful - gather info with each request.</param> /// <param name="operation">The observe operation.</param> /// <param name="replicaIndex">Index of the replica.</param> /// <returns>True if the key has not mutated.</returns> static bool CheckReplica(ObserveParams observeParams, Observe operation, int replicaIndex) { //clone the operation since we already checked the primary and we want to maintain internal state (opaque, timer, etc) operation = (Observe)operation.Clone(); var replica = observeParams.VBucket.LocateReplica(replicaIndex); var result = replica.Send(operation); //Check the result and update the counters 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); }
/// <summary> /// Performs an observe event on the durability requirements specified on a key. /// </summary> /// <param name="key">The key to observe.</param> /// <param name="cas">The 'Check and Set' value of the key.</param> /// <param name="deletion">True if this is a delete operation.</param> /// <param name="replicateTo">The number of replicas that the key must be replicated to to satisfy the durability constraint.</param> /// <param name="persistTo">The number of replicas that the key must be persisted to to satisfy the durability constraint.</param> /// <returns>True if the durability constraints have been met.</returns> /// <exception cref="ReplicaNotConfiguredException">Thrown if the number of replicas requested /// in the ReplicateTo parameter does not match the # of replicas configured on the server.</exception> public bool Observe(string key, ulong cas, bool deletion, ReplicateTo replicateTo, PersistTo persistTo) { var criteria = GetDurabilityCriteria(deletion); var keyMapper = _configInfo.GetKeyMapper(); var vBucket = (IVBucket)keyMapper.MapKey(key); var p = new ObserveParams { Cas = cas, Criteria = criteria, Key = key, PersistTo = persistTo, ReplicateTo = replicateTo, VBucket = vBucket }; p.CheckConfiguredReplicas(); var operation = new Observe(key, vBucket, _transcoder, (uint)_timeout); do { var master = p.VBucket.LocatePrimary(); var result = master.Send(operation); var state = result.Value; if (state.KeyState == p.Criteria.PersistState) { Interlocked.Increment(ref p.PersistedToCount); } if (!deletion && p.HasMutated(state.Cas)) { return false; } //First check if durability has already been met if (p.IsDurabilityMet()) { return true; } //If not check each replica if (CheckReplicas(p, operation)) { return true; } //prepare for another attempt operation = (Observe)operation.Clone(); p.Reset(); } while (!operation.TimedOut()); return false; }
/// <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(m=>m("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 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(m => m("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(m => m("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(m => m("Durability met {0} - {1} - opaque: {2} key:{3}", server.EndPoint, result.Value, operation.Opaque, observeParams.Key)); return true; } return false; }
/// <summary> /// Asynchronously checks the replications status of a key. /// </summary> /// <param name="op">The <see cref="ObserveParams"/> object.</param> /// <param name="replicaIndex">The index 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> static async Task<bool> CheckReplica(ObserveParams op, int replicaIndex) { Log.Debug(m=>m("checking replica {0}", replicaIndex)); if (op.IsDurabilityMet()) return true; var replica = op.VBucket.LocateReplica(replicaIndex); var result = await Task.Run(()=>replica.Send(new Observe(op.Key, op.VBucket, new AutoByteConverter()))); Log.Debug(m=>m("Replica {0} - {1} [0]", replica.EndPoint, result.Value, replicaIndex)); var state = result.Value; if (state.KeyState == op.Criteria.PersistState) { Interlocked.Increment(ref op.ReplicatedToCount); Interlocked.Increment(ref op.PersistedToCount); } else if (state.KeyState == op.Criteria.ReplicateState) { Interlocked.Increment(ref op.ReplicatedToCount); } return op.IsDurabilityMet() && !op.HasMutated(state.Cas); }