/// <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> /// Observes a set of keys at a specified interval and timeout. /// </summary> /// <param name="observe">The func to call at the specific interval</param> /// <param name="observeParams">The parameters to pass in.</param> /// <param name="op">The <see cref="Observe"/> operation.</param> /// <param name="interval">The interval to check.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use to terminate the observation at the specified timeout.</param> /// <returns>True if the durability requirements specified by <see cref="PersistTo"/> and <see cref="ReplicateTo"/> have been satisfied.</returns> static async Task <bool> ObserveEvery(Func <ObserveParams, Task <bool> > observe, ObserveParams observeParams, Observe op, int interval, CancellationToken cancellationToken) { while (true) { var result = await observe(observeParams).ContinueOnAnyContext(); if (result) { return(true); } var task = Task.Delay(interval, cancellationToken).ContinueOnAnyContext(); try { await task; } catch (TaskCanceledException) { return(false); } //prepare for another attempt observeParams.Reset(); op = (Observe)op.Clone(); } }
/// <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); }
public void Test_Clone() { var operation = new Observe("key", GetVBucket(), Transcoder, OperationLifespanTimeout) { Cas = 1123 }; var cloned = operation.Clone(); Assert.AreEqual(operation.CreationTime, cloned.CreationTime); Assert.AreEqual(operation.Cas, cloned.Cas); Assert.AreEqual(operation.VBucket.Index, cloned.VBucket.Index); Assert.AreEqual(operation.Key, cloned.Key); Assert.AreEqual(operation.Opaque, cloned.Opaque); }
/// <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)); }
public override Action Clone() { ParametrizedAction aNew = new ParametrizedAction(Name); aNew.Parameters = Parameters; if (Preconditions != null) { aNew.Preconditions = Preconditions.Clone(); } if (Effects != null) { aNew.SetEffects(Effects.Clone()); } if (Observe != null) { aNew.Observe = Observe.Clone(); } aNew.HasConditionalEffects = HasConditionalEffects; aNew.ContainsNonDeterministicEffect = ContainsNonDeterministicEffect; return(aNew); }
/// <summary> /// Observes a set of keys at a specified interval and timeout. /// </summary> /// <param name="observe">The func to call at the specific interval</param> /// <param name="observeParams">The parameters to pass in.</param> /// <param name="op">The <see cref="Observe"/> operation.</param> /// <param name="interval">The interval to check.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use to terminate the observation at the specified timeout.</param> /// <returns>True if the durability requirements specified by <see cref="PersistTo"/> and <see cref="ReplicateTo"/> have been satisfied.</returns> static async Task<bool> ObserveEvery(Func<ObserveParams, Task<bool>> observe, ObserveParams observeParams, Observe op, int interval, CancellationToken cancellationToken) { while (true) { var result = await observe(observeParams).ContinueOnAnyContext(); if (result) { return true; } var task = Task.Delay(interval, cancellationToken).ContinueOnAnyContext(); try { await task; } catch (TaskCanceledException) { return false; } //prepare for another attempt observeParams.Reset(); op = (Observe)op.Clone(); } }
/// <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; }