Exemple #1
0
        /// <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));
        }
Exemple #3
0
        /// <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);
        }