示例#1
0
        /// <summary>
        /// Tests basic ringmaster functionality
        /// </summary>
        /// <param name="ringMaster">RingMaster client</param>
        /// <param name="instanceRootPath">Root path that must be used by this instance for creating nodes</param>
        /// <param name="iteration">Current iteration</param>
        /// <returns><c>true</c> if the functionality test passed, <c>false</c> otherwise</returns>
        private async Task <bool> TestRingMasterFunctionality(IRingMasterRequestHandler ringMaster, string instanceRootPath, long iteration)
        {
            var timer = Stopwatch.StartNew();

            try
            {
                var random = new Random();

                string nodePath = string.Format($"{instanceRootPath}/Node");
                RingMasterWatchdogEventSource.Log.Create(iteration, nodePath);
                await ringMaster.Create(nodePath, null, null, CreateMode.PersistentAllowPathCreation, throwIfNodeExists : false);

                RingMasterWatchdogEventSource.Log.Exists(iteration, nodePath);
                var nodeStat = await ringMaster.Exists(nodePath, watcher : null);

                int    nodeDataLength = random.Next(RingMasterWatchdog.DefaultMaxNodeDataLength);
                byte[] nodeData       = new byte[nodeDataLength];
                random.NextBytes(nodeData);

                RingMasterWatchdogEventSource.Log.SetData(iteration, nodePath, nodeData.Length);
                await ringMaster.SetData(nodePath, nodeData, nodeStat.Version);

                RingMasterWatchdogEventSource.Log.GetData(iteration, nodePath);
                var retrievedData = await ringMaster.GetData(nodePath, watcher : null);

                if (retrievedData == null)
                {
                    RingMasterWatchdogEventSource.Log.GetDataFailed_RetrievedDataIsNull(iteration, nodePath, nodeData.Length);
                    throw new InvalidOperationException($"Node {nodePath}: Retrieved data is null. expectedDataLength={nodeData.Length}");
                }

                if (retrievedData.Length != nodeData.Length)
                {
                    RingMasterWatchdogEventSource.Log.GetDataFailed_RetrievedDataLengthMismatch(iteration, nodePath, nodeData.Length, retrievedData.Length);
                    throw new InvalidOperationException($"Node {nodePath}: Retrieved data length mismatch retrievedDataLength={retrievedData.Length} expectedDataLength={nodeData.Length}");
                }

                if (!retrievedData.SequenceEqual(nodeData))
                {
                    RingMasterWatchdogEventSource.Log.GetDataFailed_RetrievedDataIsDifferent(iteration, nodePath, nodeData.Length);
                    throw new InvalidOperationException($"Node {nodePath}: Retrieved data is different");
                }

                RingMasterWatchdogEventSource.Log.Delete(iteration, nodePath, nodeStat.Version);
                await ringMaster.Delete(nodePath, -1);

                RingMasterWatchdogEventSource.Log.TestRingMasterFunctionalitySucceeded(iteration, timer.ElapsedMilliseconds);
                return(true);
            }
            catch (System.Exception ex)
            {
                RingMasterWatchdogEventSource.Log.TestRingMasterFunctionalityFailed(iteration, timer.ElapsedMilliseconds, ex.ToString());
            }

            return(false);
        }
示例#2
0
        /// <summary>
        /// Work load for testing Create method
        /// </summary>
        /// <param name="client">RingMasterClient object</param>
        /// <param name="token">Cancellation token</param>
        /// <param name="threadId">Thread sequence number</param>
        /// <returns>Async task</returns>
        private Task DeleteNodeThread(IRingMasterRequestHandler client, CancellationToken token, int threadId)
        {
            int taskCount = 0;
            var clock     = Stopwatch.StartNew();

            while (!token.IsCancellationRequested)
            {
                while (this.QueuedNodes.TryDequeue(out string path) && !token.IsCancellationRequested)
                {
                    SpinWait.SpinUntil(() => taskCount < this.AsyncTaskCount || token.IsCancellationRequested);
                    var startTime = clock.Elapsed;
                    var task      = client.Delete(path, -1, DeleteMode.None)
                                    .ContinueWith(
                        t =>
                    {
                        Interlocked.Decrement(ref taskCount);
                        if (!t.Result)
                        {
                            this.Log($"Failed to delete {path}.");
                            if (t.Exception != null)
                            {
                                this.Log($"Exception: {t.Exception.Message}");
                                this.IncrementTotalFailures();
                            }
                        }
                        else
                        {
                            this.IncrementTotalDataCount();

                            var duration = clock.Elapsed - startTime;
                            MdmHelper.LogOperationDuration((long)duration.TotalMilliseconds, OperationType.Delete);
                        }
                    });

                    Interlocked.Increment(ref taskCount);
                }
            }

            SpinWait.SpinUntil(() => taskCount == 0);

            return(Task.FromResult(0));
        }
示例#3
0
        /// <summary>
        /// Registers to notifications for any change under the given path.
        /// </summary>
        /// <param name="ringMaster">The ringmaster handler to use.</param>
        /// <param name="timeout">The timeout for retries on setting the watcher.</param>
        /// <param name="pathToWatch">The path to watch.</param>
        /// <param name="oneuse">if set to <c>true</c> there will be just one notification triggered, and the watcher will be removed then.</param>
        /// <param name="sessionlocal">if set to <c>true</c> we will use a local session for this on the server.</param>
        /// <param name="onChange">The notification callback.</param>
        /// <returns>an async task indicating a boolean where true means the callback will be invoked</returns>
        public static async Task <bool> RegisterOnAnySubPathChange(
            this IRingMasterRequestHandler ringMaster,
            int timeout,
            string pathToWatch,
            bool oneuse,
            bool sessionlocal,
            RegisterOnAnySubPathChangeDelegate onChange)
        {
            if (ringMaster == null)
            {
                throw new ArgumentNullException("rm");
            }

            if (pathToWatch == null)
            {
                throw new ArgumentNullException("pathToWatch");
            }

            if (onChange == null)
            {
                throw new ArgumentNullException("onChange");
            }

            string path = GetBulkWatcherName(pathToWatch.Replace('/', '_')) + "_" + Guid.NewGuid().ToString();

            byte[] data = Encoding.UTF8.GetBytes("$startswith:" + pathToWatch + ",$sessionlocal:" + sessionlocal);

            DelegateWatcher watcher = new DelegateWatcher(
                ev =>
            {
                // if the event was signaled because the bulkwatcher node was deleted, this means the watcher is removed as well.
                if (ev.EventType == WatchedEvent.WatchedEventType.NodeDeleted && string.Equals(ev.Path, path))
                {
                    return;
                }

                onChange(RingMasterException.Code.Ok, ev);

                if (ev.EventType == WatchedEvent.WatchedEventType.WatcherRemoved && ev.KeeperState == WatchedEvent.WatchedEventKeeperState.SyncConnected)
                {
                    ringMaster.Delete(path, -1, DeleteMode.None).Wait();
                }
            },
                oneuse ? WatcherKind.OneUse : default(WatcherKind));

            DateTime maxTime = DateTime.UtcNow + TimeSpan.FromMilliseconds(timeout);

            while (true)
            {
                try
                {
                    await ringMaster.Create(GetBulkWatcherName(null), null, null, CreateMode.Persistent);

                    break;
                }
                catch (RingMasterException ex)
                {
                    if (ex.ErrorCode == RingMasterException.Code.Connectionloss || ex.ErrorCode == RingMasterException.Code.Operationtimeout)
                    {
                        if (DateTime.UtcNow > maxTime)
                        {
                            return(false);
                        }

                        continue;
                    }

                    if (ex.ErrorCode == RingMasterException.Code.Nodeexists)
                    {
                        break;
                    }

                    onChange(ex.ErrorCode, null);
                    return(true);
                }
            }

            while (true)
            {
                try
                {
                    await ringMaster.Create(path, data, null, CreateMode.Ephemeral);

                    break;
                }
                catch (RingMasterException ex)
                {
                    if (ex.ErrorCode == RingMasterException.Code.Connectionloss || ex.ErrorCode == RingMasterException.Code.Operationtimeout)
                    {
                        if (DateTime.UtcNow > maxTime)
                        {
                            return(false);
                        }

                        continue;
                    }

                    if (ex.ErrorCode == RingMasterException.Code.Nodeexists)
                    {
                        break;
                    }

                    onChange(ex.ErrorCode, null);
                    return(true);
                }
            }

            while (true)
            {
                try
                {
                    await ringMaster.Exists(path, watcher, false);

                    break;
                }
                catch (RingMasterException ex)
                {
                    if (ex.ErrorCode == RingMasterException.Code.Connectionloss)
                    {
                        if (DateTime.UtcNow > maxTime)
                        {
                            return(false);
                        }

                        continue;
                    }

                    onChange(ex.ErrorCode, null);
                    return(true);
                }
            }

            return(true);
        }
示例#4
0
 public static async Task <bool> Delete(this IRingMasterRequestHandler ringMaster, string path, int version, bool isRecursive)
 {
     return(await ringMaster.Delete(path, version, isRecursive?DeleteMode.CascadeDelete : DeleteMode.None));
 }