Exemple #1
0
        public TItem Dequeue(CancellationToken cancellationToken = default)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                lock (_syncRoot)
                {
                    if (_items.Count > 0)
                    {
                        var item = _items.First.Value;
                        _items.RemoveFirst();

                        return(item);
                    }

                    if (_items.Count == 0)
                    {
                        _gate?.Reset();
                    }
                }

                _gate?.Wait(cancellationToken);
            }

            throw new OperationCanceledException();
        }
        // Validates init, set, reset state transitions.
        private static void RunManualResetEventSlimTest0_StateTrans(bool init)
        {
            ManualResetEventSlim ev = new ManualResetEventSlim(init);
            if (ev.IsSet != init)
            {
                Debug.WriteLine("* RunManualResetEventSlimTest0_StateTrans(init={0})", init);
                Assert.True(false, string.Format("  > FAILED.  expected IsSet=={0}, but it's {1}", init, ev.IsSet));
            }

            for (int i = 0; i < 50; i++)
            {
                ev.Set();
                if (!ev.IsSet)
                {
                    Debug.WriteLine("* RunManualResetEventSlimTest0_StateTrans(init={0})", init);
                    Assert.True(false, string.Format("  > FAILED.  expected IsSet, but it's false"));
                }

                ev.Reset();
                if (ev.IsSet)
                {
                    Debug.WriteLine("* RunManualResetEventSlimTest0_StateTrans(init={0})", init);
                    Assert.True(false, string.Format("  > FAILED.  expected !IsSet, but it's true"));
                }
            }
        }
 private unsafe void Receive(byte[] data)
 {
     // Schedule the processing to happen on the queue.  Out of order
     // messages cause checksum errors!
     _queue.DispatchAsync(() =>
     {
         _receivedBytesPending += (uint)data.Length;
         WriteLog.To.Sync.V(Tag, $"<<< received {data.Length} bytes [now {_receivedBytesPending} pending]");
         var socket = _socket;
         _c4Queue.DispatchAsync(() =>
         {
             // Guard against closure / disposal
             if (!_closed)
             {
                 Native.c4socket_received(socket, data);
                 WriteLog.To.Sync.V(Tag, "c4Socket received.");
                 if (_receivedBytesPending >= MaxReceivedBytesPending)
                 {
                     WriteLog.To.Sync.V(Tag, "Too much pending data, throttling Receive...");
                     _receivePause?.Reset();
                 }
             }
         });
     });
 }
        // Validates init, set, reset state transitions.
        private static void RunManualResetEventSlimTest0_StateTrans(bool init)
        {
            ManualResetEventSlim ev = new ManualResetEventSlim(init);
            Assert.Equal(init, ev.IsSet);

            for (int i = 0; i < 50; i++)
            {
                ev.Set();
                Assert.True(ev.IsSet);

                ev.Reset();
                Assert.False(ev.IsSet);
            }
        }
Exemple #5
0
        /// <summary>
        /// Disconnects from the server. The server is actively notified about disconnection.
        /// </summary>
        public void Disconnect()
        {
            if (_channel != null && HasSession)
            {
                if (_keepSessionAliveTimer != null)
                {
                    _keepSessionAliveTimer.Stop();
                    _keepSessionAliveTimer.Dispose();
                    _keepSessionAliveTimer = null;
                }

                byte[] sharedSecret =
                    MessageEncryption
                        ? _sessionId.ToByteArray()
                        : null;

                var goodbyeMessage =
                    new GoodbyeMessage()
                {
                    SessionId = _sessionId
                };

                var wireMessage =
                    MessageEncryptionManager.CreateWireMessage(
                        messageType: "goodbye",
                        serializer: Serializer,
                        serializedMessage: Serializer.Serialize(goodbyeMessage),
                        keyPair: _keyPair,
                        sharedSecret: sharedSecret);

                byte[] rawData = Serializer.Serialize(wireMessage);

                _goodbyeCompletedWaitHandle.Reset();

                _channel.RawMessageTransport.SendMessage(rawData);

                _goodbyeCompletedWaitHandle.Wait(10000);
            }

            _channel?.Disconnect();
            _handshakeCompletedWaitHandle?.Reset();
            _authenticationCompletedWaitHandle?.Reset();
            Identity = null;
        }
        public static void RunManualResetEventSlimTest5_Dispose_Negative()
        {
            ManualResetEventSlim mres = new ManualResetEventSlim(false);
            mres.Dispose();

            Assert.Throws<ObjectDisposedException>(() => mres.Reset());
            // Failure Case: The object has been disposed, should throw ObjectDisposedException.

            Assert.Throws<ObjectDisposedException>(() => mres.Wait(0));
            // Failure Case: The object has been disposed, should throw ObjectDisposedException.

            Assert.Throws<ObjectDisposedException>(
                () =>
                {
                    WaitHandle handle = mres.WaitHandle;
                });
            // Failure Case: The object has been disposed, should throw ObjectDisposedException.

            mres = new ManualResetEventSlim(false);

            ManualResetEvent mre = (ManualResetEvent)mres.WaitHandle;
            mres.Dispose();

            Assert.Throws<ObjectDisposedException>(() => mre.WaitOne(0));
            // Failure Case: The underlying event object has been disposed, should throw ObjectDisposedException.

        }
 public void WaitForWorkers()
 {
     endHandle.Wait();
     endHandle.Reset();
 }
Exemple #8
0
        /// <summary>
        /// Returns an enumerable which provides the data to stream to the algorithm
        /// </summary>
        public override IEnumerable <TimeSlice> StreamData(CancellationToken cancellationToken)
        {
            PostInitialize();

            var shouldSendExtraEmptyPacket = false;
            var nextEmit      = DateTime.MinValue;
            var lastLoopStart = DateTime.UtcNow;

            var enumerator = SubscriptionSynchronizer
                             .Sync(SubscriptionManager.DataFeedSubscriptions, cancellationToken)
                             .GetEnumerator();

            var previousWasTimePulse = false;

            while (!cancellationToken.IsCancellationRequested)
            {
                var now = DateTime.UtcNow;
                if (!previousWasTimePulse)
                {
                    if (!_newLiveDataEmitted.IsSet)
                    {
                        // if we just crossed into the next second let's loop again, we will flush any consolidator bar
                        // else we will wait to be notified by the subscriptions or our scheduled event service every second
                        if (lastLoopStart.Second == now.Second)
                        {
                            _realTimeScheduleEventService.ScheduleEvent(TimeSpan.FromMilliseconds(GetPulseDueTime(now)), now);
                            _newLiveDataEmitted.Wait();
                        }
                    }
                    _newLiveDataEmitted.Reset();
                }

                lastLoopStart = now;

                TimeSlice timeSlice;
                try
                {
                    if (!enumerator.MoveNext())
                    {
                        // the enumerator ended
                        break;
                    }
                    timeSlice = enumerator.Current;
                }
                catch (Exception err)
                {
                    Log.Error(err);
                    // notify the algorithm about the error, so it can be reported to the user
                    Algorithm.RunTimeError     = err;
                    Algorithm.Status           = AlgorithmStatus.RuntimeError;
                    shouldSendExtraEmptyPacket = true;
                    break;
                }

                // check for cancellation
                if (timeSlice == null || cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                var frontierUtc = FrontierTimeProvider.GetUtcNow();
                // emit on data or if we've elapsed a full second since last emit or there are security changes
                if (timeSlice.SecurityChanges != SecurityChanges.None ||
                    timeSlice.IsTimePulse ||
                    timeSlice.Data.Count != 0 ||
                    frontierUtc >= nextEmit)
                {
                    previousWasTimePulse = timeSlice.IsTimePulse;
                    yield return(timeSlice);

                    // force emitting every second since the data feed is
                    // the heartbeat of the application
                    nextEmit = frontierUtc.RoundDown(Time.OneSecond).Add(Time.OneSecond);
                }
            }

            if (shouldSendExtraEmptyPacket)
            {
                // send last empty packet list before terminating,
                // so the algorithm manager has a chance to detect the runtime error
                // and exit showing the correct error instead of a timeout
                nextEmit = FrontierTimeProvider.GetUtcNow().RoundDown(Time.OneSecond);
                if (!cancellationToken.IsCancellationRequested)
                {
                    var timeSlice = TimeSliceFactory.Create(
                        nextEmit,
                        new List <DataFeedPacket>(),
                        SecurityChanges.None,
                        new Dictionary <Universe, BaseDataCollection>());
                    yield return(timeSlice);
                }
            }

            enumerator.DisposeSafely();
            Log.Trace("LiveSynchronizer.GetEnumerator(): Exited thread.");
        }
Exemple #9
0
 public void Reset()
 {
     _mre.Reset();
 }
Exemple #10
0
 public IntCode Run(Action <long> output = null)
 {
     idle.Reset();
     Running = true;
     while (pc >= 0 && pc < memory.Length && memory[pc] != 99)
     {
         int op = PCReadOpCode();
         if (op == 1)
         {
             long arg1 = PCReadValue();
             long arg2 = PCReadValue();
             long dest = PCReadAddr();
             memory[dest] = arg1 + arg2;
         }
         else if (op == 2)
         {
             long arg1 = PCReadValue();
             long arg2 = PCReadValue();
             long dest = PCReadAddr();
             memory[dest] = arg1 * arg2;
         }
         else if (op == 3)
         {
             long dest = PCReadAddr();
             idle.Set();
             memory[dest] = PopInput();
             idle.Reset();
         }
         else if (op == 4)
         {
             long arg1 = PCReadValue();
             output(arg1);
         }
         else if (op == 5)
         {
             long arg1 = PCReadValue();
             long dest = PCReadValue();
             if (arg1 != 0)
             {
                 pc = (int)dest;
             }
         }
         else if (op == 6)
         {
             long arg1 = PCReadValue();
             long dest = PCReadValue();
             if (arg1 == 0)
             {
                 pc = (int)dest;
             }
         }
         else if (op == 7)
         {
             long arg1 = PCReadValue();
             long arg2 = PCReadValue();
             long dest = PCReadAddr();
             memory[dest] = (arg1 < arg2) ? 1 : 0;
         }
         else if (op == 8)
         {
             long arg1 = PCReadValue();
             long arg2 = PCReadValue();
             long dest = PCReadAddr();
             memory[dest] = (arg1 == arg2) ? 1 : 0;
         }
         else if (op == 9)
         {
             relbase += PCReadValue();
         }
         else
         {
             throw new Exception("Intcode opcode error");
         }
     }
     if (memory[pc] != 99)
     {
         throw new Exception("Intcode pc address error");
     }
     Running = false;
     return(this);
 }
Exemple #11
0
        /// <summary>
        /// Dequeue a WorkItem for processing
        /// </summary>
        /// <returns>A WorkItem or null if the queue has stopped</returns>
        public WorkItem Dequeue()
        {
            SpinWait sw = new SpinWait();

            do
            {
                WorkItemQueueState cachedState = State;

                if (cachedState == WorkItemQueueState.Stopped)
                {
                    return(null); // Tell worker to terminate
                }
                int cachedRemoveId = _removeId;
                int cachedAddId    = _addId;

                // Empty case (or paused)
                if (cachedRemoveId == cachedAddId || cachedState == WorkItemQueueState.Paused)
                {
                    // Spin a few times to see if something changes
                    if (sw.Count <= SPIN_COUNT)
                    {
                        sw.SpinOnce();
                    }
                    else
                    {
                        // Reset to wait for an enqueue
                        _mreAdd.Reset();

                        // Recheck for an enqueue to avoid a Wait
                        if ((cachedRemoveId != _removeId || cachedAddId != _addId) && cachedState != WorkItemQueueState.Paused)
                        {
                            // Queue is not empty, set the event
                            _mreAdd.Set();
                            continue;
                        }

                        // Wait for something to happen
                        _mreAdd.Wait(500);
                    }

                    continue;
                }

                // Validate that we are the current dequeuer
                if (Interlocked.CompareExchange(ref _removeId, cachedRemoveId + 1, cachedRemoveId) != cachedRemoveId)
                {
                    continue;
                }


                // Dequeue our work item
                WorkItem work = null;
                while (work == null)
                {
                    foreach (var q in _innerQueues)
                    {
                        if (q.TryDequeue(out work))
                        {
                            break;
                        }
                    }
                }

                // Add to items processed using CAS
                Interlocked.Increment(ref _itemsProcessed);

                return(work);
            } while (true);
        }
 public static void Reset()
 {
     TriggeredCount = 0;
     triggered.Reset();
 }
Exemple #13
0
 public void Pausar()
 {
     _pauseEvent.Reset();
     _pauseEvent.Wait(TokenSource.Token);
 }
Exemple #14
0
        private void WorkerWorker()
        {
            var  flushMessages  = new Queue <WorkerMessage>();
            bool changed        = false;
            var  lastUpdateTime = DateTime.Now;

            while (_workerQueueChanged.Wait(1000))
            {
                // Reset event and handle all messages in the queue
                _workerQueueChanged.Reset();

                while (true)
                {
                    WorkerMessage msg;
                    lock (_workerQueue) {
                        if (_workerQueue.Count == 0)
                        {
                            break;
                        }
                        msg = _workerQueue.Dequeue();
                        Debug.WriteLine(string.Format("{2} Processing msg... {0} {1}", DateTime.Now, msg, GetType()));
                    }

                    if (msg is WorkerMessage.FlushMessage)
                    {
                        // Keep flush messages until we've exited the loop
                        flushMessages.Enqueue(msg);
                    }
                    else
                    {
                        // Apply the message to our collection
                        changed |= msg.Apply(_items, _itemsLock);
                    }
                    Debug.WriteLine(string.Format("{2} Done processing msg... {0} {1}", DateTime.Now, msg, GetType()));
                    // Every second, we want to force another update
                    if (changed)
                    {
                        var currentTime = DateTime.Now;
                        if ((currentTime - lastUpdateTime).TotalMilliseconds > 1000)
                        {
                            if (Refresh())
                            {
                                lastUpdateTime = currentTime;
                                changed        = false;
                            }
                        }
                    }
                }
                Debug.WriteLine(string.Format("Looping to wait... {0}", DateTime.Now));
            }

            // Handle any changes that weren't handled in the loop
            if (changed)
            {
                Debug.WriteLine(string.Format("Refreshing... {0}", DateTime.Now));
                Refresh();
            }

            // Notify all the flush messages we received
            Debug.WriteLine(string.Format("Flushing... {0}", DateTime.Now));
            while (flushMessages.Any())
            {
                var msg = flushMessages.Dequeue();
                msg.Apply(_items, _itemsLock);
            }
            Debug.WriteLine(string.Format("Done flushing... {0}", DateTime.Now));
        }
Exemple #15
0
        void RACWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            UInt64 deltaTimeInQueue;

            String threadName = "RossiAlphaAnalyzer_" + rossiAlphaGateWidth;

            Thread.CurrentThread.Name = threadName;

#if USE_SPINTIME
            spinTimeReady = false;
#endif

            while (keepRunning == true)
            {
                isReadyToAnalyze = true;

#if USE_SPINTIME
                if (spinTimeReady)
                {
                    StartSpinCount();
                }
#endif

                waitingForMessage.Wait();  //wait for some other thread to place neutron data in this object and signal this worker to analyze

#if USE_SPINTIME
                if (spinTimeReady)
                {
                    EndSpinCount();
                }
                else
                {
                    spinTimeReady = true;
                }
#endif

                if (keepRunning == true)
                {
                    UInt64 eventTime;
                    UInt32 eventNeutrons;
                    UInt32 eventNumNeutrons;
                    int    j;

                    for (j = 0; j < numEventsThisBlock; j++)
                    {
                        eventTime        = inputEventTime[j];
                        eventNeutrons    = inputEventNeutrons[j];
                        eventNumNeutrons = inputEventNumNeutrons[j];

                        //fill in these new data at the tail of the circular linked list,
                        //remembering that endOfNeutronEventList points to the next EMPTY struct in the list
                        //INCLUDING at the beginning when the head and tail point to the same struct
                        endOfList.FillEventWithData(eventTime, eventNeutrons, eventNumNeutrons);

                        //check to see if the circular list will overflow
                        if (endOfList.next.serialNumber == startOfList.serialNumber)
                        {
                            int i;
                            RossiAlphaCircularNeutronEvent anEvent;
                            RossiAlphaCircularNeutronEvent nextEvent;

                            //if stack would overflow, add RawAnalysisProperties.circularListBlockIncrement neutron events at this spot in the stack...
                            anEvent   = endOfList;
                            nextEvent = endOfList.next;
                            for (i = 0; i < RawAnalysisProperties.circularListBlockIncrement; i++)
                            {
                                anEvent.next = new RossiAlphaCircularNeutronEvent(i + numObjectsInCircularLinkedList);
                                anEvent      = anEvent.next;
                            }
                            anEvent.next = nextEvent;                                                           //patch the circular linked list back together
                            numObjectsInCircularLinkedList += RawAnalysisProperties.circularListBlockIncrement; //increase the record of the number of structs in the circular list
                        }

                        //move endOfNeutronEventList to the next empty struct
                        endOfList = endOfList.next;

                        //for fun, count how many times we have lapped the circular list in this experiment
                        if (endOfList.serialNumber == 0)
                        {
                            numCircuits++;
                        }

                        //see if oldest event in the queue is expiring,
                        //and while there are expiring events calculate the RossiAlpha statistics for those events
                        deltaTimeInQueue = eventTime - startOfList.eventTime;
                        while (deltaTimeInQueue > rossiAlphaWindowWidth)
                        {
                            //record the time of the expiring gate from the startOfList event, the total measured time for this experiment
                            totalRossiAlphaAnalysisTime = startOfList.eventTime + rossiAlphaWindowWidth;

                            //do RossiAlpha analysis here, accumulating statistics
                            //add up how many neutrons there were in each RossiAlpha gate from the time of the expiring event
                            int    whichBin;
                            UInt64 deltaTime;
                            RossiAlphaCircularNeutronEvent anEvent;

                            //skip the event at the head of the list.
                            //To match data from the legacy code, start with the neutron event following this expiring head event.
                            anEvent = startOfList.next;
                            while (anEvent.serialNumber != endOfList.serialNumber)  //...that is, until we reach the end of the list...
                            {
                                //Find the lowest bin with end time greater than the time of anEvent.
                                deltaTime = anEvent.eventTime - startOfList.eventTime;
                                whichBin  = (int)(Math.Ceiling((double)deltaTime / (double)rossiAlphaGateWidth) + 0.1);

                                if (whichBin < RawAnalysisProperties.numRAGatesPerWindow)  //then this event falls into a bin; add this event's neutrons to that bin
                                {
                                    neutronsPerRossiAlphaGate[whichBin] += anEvent.numNeutrons;
                                    //go to the next event
                                    anEvent = anEvent.next;
                                }
                                else
                                {
                                    anEvent = endOfList;  //abort the loop by going to the end of the list
                                }
                            }

                            //remove expiring oldest event from the stack
                            startOfList = startOfList.next;

                            //re-calculate the delta time in the stack
                            deltaTimeInQueue = eventTime - startOfList.eventTime;
                        } //END of handling an individual NeutronEvent
                    }     //END of handling this block of events

                    //prepare this thread's wait condition so will wait for a message
                    //before telling master thread this thread's analysis is complete
                    waitingForMessage.Reset();
                }  //END of if(keepRunning)
                else
                {
                    //The master thread has cleared the keepRunning flag, so this worker is exiting
                    //Do any cleanup etc. here.
                }
            }  //END of while(keepRunning)
        }
Exemple #16
0
        public void MultiAccessSerializationAsync()
        {
            var cache1  = new MockTokenCache();
            var helper1 = new MsalCacheHelper(
                cache1,
                new MsalCacheStorage(s_storageCreationProperties, _logger),
                _logger);

            var cache2  = new MockTokenCache();
            var helper2 = new MsalCacheHelper(
                cache2,
                new MsalCacheStorage(s_storageCreationProperties, _logger),
                _logger);

            //Test signalling thread 1
            var resetEvent1 = new ManualResetEventSlim(initialState: false);

            //Test signalling thread 2
            var resetEvent2 = new ManualResetEventSlim(initialState: false);

            //Thread 1 signalling test
            var resetEvent3 = new ManualResetEventSlim(initialState: false);

            // Thread 2 signalling test
            var resetEvent4 = new ManualResetEventSlim(initialState: false);

            var thread1 = new Thread(() =>
            {
                var args = new TokenCacheNotificationArgs
                {
                    TokenCache = cache1
                };

                helper1.BeforeAccessNotification(args);
                resetEvent3.Set();
                resetEvent1.Wait();
                helper1.AfterAccessNotification(args);
            });

            var thread2 = new Thread(() =>
            {
                var args = new TokenCacheNotificationArgs
                {
                    TokenCache = cache2
                };

                helper2.BeforeAccessNotification(args);
                resetEvent4.Set();
                resetEvent2.Wait();
                helper2.AfterAccessNotification(args);
                resetEvent4.Set();
            });

            // Let thread 1 start and get the lock
            thread1.Start();
            resetEvent3.Wait();

            // Start thread 2 and give it enough time to get blocked on the lock
            thread2.Start();
            Thread.Sleep(5000);

            // Make sure helper1 has the lock still, and helper2 doesn't
            Assert.IsNotNull(helper1.CacheLock);
            Assert.IsNull(helper2.CacheLock);

            // Allow thread1 to give up the lock, and wait for helper2 to get it
            resetEvent1.Set();
            resetEvent4.Wait();
            resetEvent4.Reset();

            // Make sure helper1 gave it up properly, and helper2 now owns the lock
            Assert.IsNull(helper1.CacheLock);
            Assert.IsNotNull(helper2.CacheLock);

            // Allow thread2 to give up the lock, and wait for it to complete
            resetEvent2.Set();
            resetEvent4.Wait();

            // Make sure thread2 cleaned up after itself as well
            Assert.IsNull(helper2.CacheLock);
        }
Exemple #17
0
        /// <summary>
        /// Loops forever, reading data from client.
        /// Fires event for each complete game packet received.
        /// </summary>
        private void Read_Thread()
        {
            try
            {
                //vars
                byte[]        buffer = new byte[8192];
                NetworkStream stream = _client.GetStream();

                //internal async callback function
                void callback(IAsyncResult ar)
                {
                    try
                    {
                        //stop reading?
                        if (_stop)
                        {
                            return;
                        }

                        //end read
                        int bytesRead = stream.EndRead(ar);

                        //lock queue
                        lock (_incomingQueue)
                        {
                            //add new bytes to queue
                            for (int i = 0; i < bytesRead; i++)
                            {
                                _incomingQueue.Add(buffer[i]);
                            }

                            //set signal
                            if (bytesRead > 0)
                            {
                                _readSignal.Set();
                            }
                        }

                        //begin next read
                        stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(callback), null);
                    }
                    catch (IOException ioex)
                    {
                        _stop = true;
                        if ((ioex.InnerException != null) && (ioex.InnerException is SocketException sex))
                        {
                            Log.Write($"Connection to '{_remoteIP}' closed: {sex.SocketErrorCode}");
                        }
                        else
                        {
                            ErrorHandler.LogError(ioex);
                        }
                    }
                    catch (Exception ex)
                    {
                        _stop = true;
                        ErrorHandler.LogError(ex);
                    }
                }

                //begin first read
                stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(callback), null);

                //loop forever, pulling complete packets out of incoming queue
                while (true)
                {
                    //wait new data in queue, or one second
                    _readSignal.Wait(1000);
                    _readSignal.Reset();

                    //read data, if it exists
                    ReadData();

                    //end thread?
                    if (_stop)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                _stop = true;
                Log.Write("ReadThread: Reading or processing data");
                ErrorHandler.LogError(ex);
            }
        }
        public static void WaitNotificationTest()
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                var tsc = new TestSynchronizationContext();
                SynchronizationContext.SetSynchronizationContext(tsc);
                Assert.Same(tsc, SynchronizationContext.Current);

                var e = new ManualResetEvent(false);
                tsc.WaitAction = () => e.Set();
                Assert.False(tsc.IsWaitNotificationRequired());
                Assert.False(e.WaitOne(0));
                tsc.SetWaitNotificationRequired();
                Assert.True(tsc.IsWaitNotificationRequired());
                Assert.True(e.WaitOne(0));

                var mres = new ManualResetEventSlim();
                tsc.WaitAction = () => mres.Set();
                mres.Reset();
                mres.CheckedWait();

                e.Reset();
                tsc.WaitAction = () => e.Set();
                SynchronizationContext.SetSynchronizationContext(new TestSynchronizationContext());
                Assert.False(e.WaitOne(0));
                SynchronizationContext.SetSynchronizationContext(tsc);
                Assert.True(e.WaitOne(0));
                e.Reset();
                e.CheckedWait();

                e.Reset();
                var lockObj = new object();
                var lockAcquiredFromBackground = new AutoResetEvent(false);
                Action waitForThread;
                Thread t =
                    ThreadTestHelpers.CreateGuardedThread(out waitForThread, () =>
                    {
                        lock (lockObj)
                        {
                            lockAcquiredFromBackground.Set();
                            e.CheckedWait();
                        }
                    });
                t.IsBackground = true;
                t.Start();
                lockAcquiredFromBackground.CheckedWait();
                Assert.True(Monitor.TryEnter(lockObj, ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                Monitor.Exit(lockObj);
                waitForThread();

                e.Reset();
                var m = new Mutex();
                t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () =>
                {
                    m.CheckedWait();
                    try
                    {
                        lockAcquiredFromBackground.Set();
                        e.CheckedWait();
                    }
                    finally
                    {
                        m.ReleaseMutex();
                    }
                });
                t.IsBackground = true;
                t.Start();
                lockAcquiredFromBackground.CheckedWait();
                m.CheckedWait();
                m.ReleaseMutex();
                waitForThread();
            });
        }
        public static void WaitNotificationTest()
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                var tsc = new TestSynchronizationContext();
                SynchronizationContext.SetSynchronizationContext(tsc);
                Assert.Same(tsc, SynchronizationContext.Current);

                var e          = new ManualResetEvent(false);
                tsc.WaitAction = () => e.Set();
                Assert.False(tsc.IsWaitNotificationRequired());
                Assert.False(e.WaitOne(0));
                tsc.SetWaitNotificationRequired();
                Assert.True(tsc.IsWaitNotificationRequired());
                Assert.True(e.WaitOne(0));

                var mres       = new ManualResetEventSlim();
                tsc.WaitAction = () => mres.Set();
                mres.Reset();
                mres.CheckedWait();

                e.Reset();
                tsc.WaitAction = () => e.Set();
                SynchronizationContext.SetSynchronizationContext(new TestSynchronizationContext());
                Assert.False(e.WaitOne(0));
                SynchronizationContext.SetSynchronizationContext(tsc);
                Assert.True(e.WaitOne(0));
                e.Reset();
                e.CheckedWait();

                e.Reset();
                var lockObj = new object();
                var lockAcquiredFromBackground = new AutoResetEvent(false);
                Action waitForThread;
                Thread t =
                    ThreadTestHelpers.CreateGuardedThread(out waitForThread, () =>
                {
                    lock (lockObj)
                    {
                        lockAcquiredFromBackground.Set();
                        e.CheckedWait();
                    }
                });
                t.IsBackground = true;
                t.Start();
                lockAcquiredFromBackground.CheckedWait();
                Assert.True(Monitor.TryEnter(lockObj, ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                Monitor.Exit(lockObj);
                waitForThread();

                e.Reset();
                var m = new Mutex();
                t     = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () =>
                {
                    m.CheckedWait();
                    try
                    {
                        lockAcquiredFromBackground.Set();
                        e.CheckedWait();
                    }
                    finally
                    {
                        m.ReleaseMutex();
                    }
                });
                t.IsBackground = true;
                t.Start();
                lockAcquiredFromBackground.CheckedWait();
                m.CheckedWait();
                m.ReleaseMutex();
                waitForThread();
            });
        }
 internal void SetNotComplete()
 {
     Interlocked.Exchange(ref _awaitableState, _awaitableIsNotCompleted);
     _manualResetEvent.Reset();
 }
Exemple #21
0
        internal void SetState(RaftEngineState state)
        {
            if (state == State)
            {
                return;
            }

            if (State == RaftEngineState.Leader)
            {
                _leaderSelectedEvent.Reset();
            }

            var oldState = State;

            if (StateBehavior != null)
            {
                StateBehavior.Dispose();
            }
            switch (state)
            {
            case RaftEngineState.Follower:
            case RaftEngineState.FollowerAfterStepDown:
                StateBehavior = new FollowerStateBehavior(this, state == RaftEngineState.FollowerAfterStepDown);
                break;

            case RaftEngineState.CandidateByRequest:
                StateBehavior = new CandidateStateBehavior(this, true);
                //setting state before calling election because the state may change to leader before
                //we set it to CandidateByRequest
                AssertStateAndRaiseStateChanged(state, oldState);
                StateBehavior.HandleTimeout();
                return;

            case RaftEngineState.Candidate:
                StateBehavior = new CandidateStateBehavior(this, false);
                //setting state before calling election because the state may change to leader before
                //we set it to CandidateStateBehavior
                AssertStateAndRaiseStateChanged(state, oldState);
                StateBehavior.HandleTimeout();
                return;

            case RaftEngineState.SnapshotInstallation:
                StateBehavior = new SnapshotInstallationStateBehavior(this);
                break;

            case RaftEngineState.Leader:
                StateBehavior = new LeaderStateBehavior(this);
                CurrentLeader = Name;
                OnElectedAsLeader();
                break;

            case RaftEngineState.SteppingDown:
                StateBehavior = new SteppingDownStateBehavior(this);
                CurrentLeader = Name;
                break;

            default:
                throw new ArgumentOutOfRangeException(state.ToString());
            }

            AssertStateAndRaiseStateChanged(state, oldState);
        }
Exemple #22
0
 /// <summary>
 /// 安全停止接收消费
 /// </summary>
 public void SafeStopReceive()
 {
     RabbitChannel.BasicCancel(consumerTag);
     StopLock.Wait();
     StopLock.Reset();
 }
Exemple #23
0
        public int Run(
            string cmd,
            string arguments,
            Action <string> onStandardOutput,
            Action <string> onStandardError,
            string workingDirectory,
            TimeSpan watchDogTimeout
            )
        {
            Log($"Running command: {cmd} {arguments.ToString()}");

            ProcessStartInfo startInfo = new ProcessStartInfo
            {
                CreateNoWindow         = true,
                UseShellExecute        = false,
                RedirectStandardOutput = true,
                RedirectStandardError  = true,
                FileName  = cmd,
                Arguments = arguments
            };

            if (!string.IsNullOrWhiteSpace(workingDirectory))
            {
                startInfo.WorkingDirectory = workingDirectory;
            }

            using (ManualResetEventSlim progressMadeEvent = new ManualResetEventSlim(false))
            {
                using (Process commandProcess = new Process())
                {
                    commandProcess.StartInfo = startInfo;

                    commandProcess.OutputDataReceived += (s, e) =>
                    {
                        if (string.IsNullOrEmpty(e.Data))
                        {
                            return;
                        }

                        progressMadeEvent.Set();
                        Console.WriteLine(e.Data);
                        onStandardOutput?.Invoke(e.Data);
                    };

                    commandProcess.ErrorDataReceived += (s, e) =>
                    {
                        if (string.IsNullOrEmpty(e.Data))
                        {
                            return;
                        }

                        progressMadeEvent.Set();
                        Console.Error.WriteLine(e.Data);
                        onStandardError?.Invoke(e.Data);
                    };

                    bool   keepGoing     = true;
                    object keepGoingLock = new object();

                    bool GetKeepGoing()
                    {
                        lock ( keepGoingLock )
                        {
                            return(keepGoing);
                        }
                    }

                    commandProcess.EnableRaisingEvents = true;
                    commandProcess.Exited += (s, e) =>
                    {
                        Log($"Process '{startInfo.FileName} {startInfo.Arguments}' exited");
                        lock ( keepGoingLock )
                        {
                            keepGoing = false;
                        }
                        progressMadeEvent.Set();
                    };

                    int exitCode = -1;
                    try
                    {
                        commandProcess.Start();
                        commandProcess.BeginOutputReadLine();
                        commandProcess.BeginErrorReadLine();

                        while (GetKeepGoing())
                        {
                            if (progressMadeEvent.Wait(watchDogTimeout, this._cancelToken) == false)
                            {
                                throw new TimeoutException(
                                          $"It has been more than {watchDogTimeout.TotalSeconds} seconds since we got an update from the Process.  Possible broken Pipe.  Killing process"
                                          );
                            }
                            progressMadeEvent.Reset();

                            // So we don't eat our CPU, do a delay.
                            Task.Delay(500, this._cancelToken);
                        }

                        commandProcess.WaitForExit();
                    }
                    catch (Win32Exception)
                    {
                        throw new MigrateException($"Command {cmd} does not exit. Did you install it or add it to the Environment path?");
                    }
                    catch (OperationCanceledException)
                    {
                        Log("CTRL+C Received");
                        commandProcess.Kill(true);
                        commandProcess.WaitForExit();
                        throw;
                    }
                    catch (TimeoutException)
                    {
                        commandProcess.Kill(true);
                        commandProcess.WaitForExit();
                        throw;
                    }
                    finally
                    {
                        exitCode = commandProcess.ExitCode;
                        commandProcess.Close();
                        commandProcess.Dispose();
                    }

                    return(exitCode);
                }
            }
        }
Exemple #24
0
        public void DocumentRetrieverSubscribtionsShouldWork()
        {
            using (NewRemoteDocumentStore(databaseName: "Northwind"))
            {
                var manualResetEventSlim = new ManualResetEventSlim();

                var server         = servers[0];
                var systemDatabase = server.SystemDatabase;
                var database       = AsyncHelpers.RunSync(() => server.Server.GetDatabaseInternal("Northwind"));
                var retriever      = database.ConfigurationRetriever;

                retriever.SubscribeToConfigurationDocumentChanges(PeriodicExportSetup.RavenDocumentKey, manualResetEventSlim.Set);

                systemDatabase
                .Documents
                .Put(
                    Constants.Global.PeriodicExportDocumentName,
                    null,
                    RavenJObject.FromObject(new PeriodicExportSetup
                {
                    AwsRegionEndpoint     = "e1",
                    AzureStorageContainer = "c1",
                    Disabled = true,
                    FullBackupIntervalMilliseconds = 17,
                    GlacierVaultName     = "g1",
                    IntervalMilliseconds = 12,
                    LocalFolderName      = "f1",
                    S3BucketName         = "s1"
                }),
                    new RavenJObject(),
                    null);

                if (manualResetEventSlim.Wait(TimeSpan.FromSeconds(10)) == false)
                {
                    throw new InvalidOperationException("Waited for 10 seconds for notification.");
                }

                manualResetEventSlim.Reset();

                database
                .Documents
                .Put(
                    PeriodicExportSetup.RavenDocumentKey,
                    null,
                    RavenJObject.FromObject(new PeriodicExportSetup
                {
                    AwsRegionEndpoint     = "e2",
                    AzureStorageContainer = "c2",
                    Disabled = false,
                    FullBackupIntervalMilliseconds = 2,
                    GlacierVaultName     = "g2",
                    IntervalMilliseconds = 16,
                    LocalFolderName      = "f2",
                    S3BucketName         = "s2"
                }),
                    new RavenJObject(),
                    null);

                if (manualResetEventSlim.Wait(TimeSpan.FromSeconds(10)) == false)
                {
                    throw new InvalidOperationException("Waited for 10 seconds for notification.");
                }
            }
        }
Exemple #25
0
        public async Task RavenDB_3172()
        {
            using (var store = GetDocumentStore())
            {
                CreateRdbmsSchema(store);

                var eventSlim = new ManualResetEventSlim(false);
                var database  = await GetDatabase(store.DefaultDatabase);

                database.SqlReplicationLoader.AfterReplicationCompleted += statistics =>
                {
                    if (statistics.SuccessCount != 0)
                    {
                        eventSlim.Set();
                    }
                };

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new Order
                    {
                        Id         = "orders/1",
                        OrderLines = new List <OrderLine>
                        {
                            new OrderLine {
                                Cost = 3, Product = "Milk", Quantity = 3
                            },
                            new OrderLine {
                                Cost = 4, Product = "Bear", Quantity = 2
                            },
                        }
                    });

                    await session.SaveChangesAsync();
                }

                await SetupSqlReplication(store, defaultScript, insertOnly : true);

                eventSlim.Wait(TimeSpan.FromMinutes(5));

                AssertCounts(1, 2, store);

                eventSlim.Reset();

                using (var session = store.OpenAsyncSession())
                {
                    var order = await session.LoadAsync <Order>("orders/1");

                    order.OrderLines.Add(new OrderLine
                    {
                        Cost     = 5,
                        Product  = "Sugar",
                        Quantity = 7
                    });
                    await session.SaveChangesAsync();
                }

                eventSlim.Wait(TimeSpan.FromMinutes(5));
                // we end up with duplicates
                AssertCounts(2, 5, store);
            }
        }
Exemple #26
0
        private void ReadFromQueue(object o)
        {
            try{
                _queueStats.Start();
                Thread.BeginThreadAffinity(); // ensure we are not switching between OS threads. Required at least for v8.

                while (!_stop)
                {
                    Message msg = null;
                    try
                    {
                        if (!_queue.TryDequeue(out msg))
                        {
                            _starving = true;

                            _queueStats.EnterIdle();
                            _msgAddEvent.Wait(100);
                            _msgAddEvent.Reset();

                            _starving = false;
                        }
                        else
                        {
                            _queueStats.EnterBusy();
#if DEBUG
                            _queueStats.Dequeued(msg);
#endif

                            var cnt = _queue.Count;
                            _queueStats.ProcessingStarted(msg.GetType(), cnt);

                            if (_watchSlowMsg)
                            {
                                var start = DateTime.UtcNow;

                                _consumer.Handle(msg);

                                var elapsed = DateTime.UtcNow - start;
                                if (elapsed > _slowMsgThreshold)
                                {
                                    Log.Trace("SLOW QUEUE MSG [{queue}]: {message} - {elapsed}ms. Q: {prevQueueCount}/{curQueueCount}.",
                                              Name, _queueStats.InProgressMessage.Name, (int)elapsed.TotalMilliseconds, cnt, _queue.Count);
                                    if (elapsed > QueuedHandler.VerySlowMsgThreshold && !(msg is SystemMessage.SystemInit))
                                    {
                                        Log.Error("---!!! VERY SLOW QUEUE MSG [{queue}]: {message} - {elapsed}ms. Q: {prevQueueCount}/{curQueueCount}.",
                                                  Name, _queueStats.InProgressMessage.Name, (int)elapsed.TotalMilliseconds, cnt, _queue.Count);
                                    }
                                }
                            }
                            else
                            {
                                _consumer.Handle(msg);
                            }

                            _queueStats.ProcessingEnded(1);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.ErrorException(ex, "Error while processing message {message} in queued handler '{queue}'.", msg, Name);
#if DEBUG
                        throw;
#endif
                    }
                }
            }
            catch (Exception ex) {
                _tcs.TrySetException(ex);
                throw;
            }
            finally{
                _queueStats.Stop();

                _stopped.Set();
                _queueMonitor.Unregister(this);
                Thread.EndThreadAffinity();
            }
        }
        public ulong Evaluate(ulong n, ulong x0, ulong xmax)
        {
            if (x0 > xmax)
            {
                return(0);
            }

            if (n <= nMaxSimple)
            {
                return((ulong)manualAlgorithm.Evaluate(n, x0, xmax));
            }

            if (threads == 0)
            {
                stack = new Stack <Region>();
            }
            else
            {
                queue = new BlockingCollection <Region>();
            }
            sum = 0;
#if RECORD_SIZES
            amax = 0;
            bmax = 0;
            cmax = 0;
#endif

            if (threads == 0)
            {
                AddToSum(EvaluateInternal(n, x0, xmax));
                if (xmanual > 1)
                {
                    AddToSum((ulong)manualAlgorithm.Evaluate(n, x0, 2 * xmanual - 3));
                }
                return(sum);
            }

            // Create consumers.
            var consumers = threads;
            var tasks     = new Task[consumers];
            for (var consumer = 0; consumer < consumers; consumer++)
            {
                var thread = consumer;
                tasks[consumer] = Task.Factory.StartNew(() => ConsumeRegions(thread));
            }

            // Produce work items.
            unprocessed = 1;
            finished.Reset();
            AddToSum(Processed(EvaluateInternal(n, x0, xmax)));
            finished.Wait();
            queue.CompleteAdding();

            // Add manual portion.
            if (xmanual > 1)
            {
                AddToSum((ulong)manualAlgorithm.Evaluate(n, x0, 2 * xmanual - 3));
            }

            // Wait for completion.
            Task.WaitAll(tasks);

#if RECORD_SIZES
            Console.WriteLine("amax = {0}, bmax = {1}, cmax = {2}", amax, bmax, cmax);
#endif
            return(sum);
        }
Exemple #28
0
 public void Execute(int task)
 {
     this.task = task;
     waitFlag.Reset();
     runFlag.Set();
 }
Exemple #29
0
 /// <summary>
 /// Immediately puts the thread to sleep.
 /// No actions can be dequeued until a call to <see cref="Wake"/> is made.
 /// </summary>
 public void Sleep()
 {
     threadSleepEvent.Reset();
 }
Exemple #30
0
        private async Task RunPeerUpdateLoop()
        {
            int  loopCount = 0;
            long previousActivePeersCount = 0;

            while (true)
            {
                try
                {
                    if (loopCount++ % 100 == 0)
                    {
                        if (_logger.IsTrace)
                        {
                            _logger.Trace($"Running peer update loop {loopCount - 1} - active: {_activePeers.Count} | candidates : {_peerPool.CandidatePeerCount}");
                        }
                    }

                    try
                    {
                        CleanupCandidatePeers();
                    }
                    catch (Exception e)
                    {
                        if (_logger.IsDebug)
                        {
                            _logger.Error("Candidate peers cleanup failed", e);
                        }
                    }

                    _peerUpdateRequested.Wait(_cancellationTokenSource.Token);
                    _peerUpdateRequested.Reset();

                    if (!_isStarted)
                    {
                        continue;
                    }

                    if (AvailableActivePeersCount == 0)
                    {
                        continue;
                    }

                    Interlocked.Exchange(ref _tryCount, 0);
                    Interlocked.Exchange(ref _newActiveNodes, 0);
                    Interlocked.Exchange(ref _failedInitialConnect, 0);
                    Interlocked.Exchange(ref _connectionRounds, 0);

                    SelectAndRankCandidates();
                    List <Peer> remainingCandidates = _currentSelection.Candidates;
                    if (!remainingCandidates.Any())
                    {
                        continue;
                    }

                    if (_cancellationTokenSource.IsCancellationRequested)
                    {
                        break;
                    }

                    int currentPosition = 0;
                    while (true)
                    {
                        if (_cancellationTokenSource.IsCancellationRequested)
                        {
                            break;
                        }

                        int nodesToTry = Math.Min(remainingCandidates.Count - currentPosition, AvailableActivePeersCount);
                        if (nodesToTry <= 0)
                        {
                            break;
                        }

                        ActionBlock <Peer> workerBlock = new ActionBlock <Peer>(
                            SetupPeerConnection,
                            new ExecutionDataflowBlockOptions
                        {
                            MaxDegreeOfParallelism = _parallelism,
                            CancellationToken      = _cancellationTokenSource.Token
                        });

                        for (int i = 0; i < nodesToTry; i++)
                        {
                            await workerBlock.SendAsync(remainingCandidates[currentPosition + i]);
                        }

                        currentPosition += nodesToTry;

                        workerBlock.Complete();

                        // Wait for all messages to propagate through the network.
                        workerBlock.Completion.Wait();

                        Interlocked.Increment(ref _connectionRounds);
                    }

                    if (_logger.IsTrace)
                    {
                        int activePeersCount = _activePeers.Count;
                        if (activePeersCount != previousActivePeersCount)
                        {
                            string countersLog = string.Join(", ", _currentSelection.Counters.Select(x => $"{x.Key.ToString()}: {x.Value}"));
                            _logger.Trace($"RunPeerUpdate | {countersLog}, Incompatible: {GetIncompatibleDesc(_currentSelection.Incompatible)}, EligibleCandidates: {_currentSelection.Candidates.Count()}, " +
                                          $"Tried: {_tryCount}, Rounds: {_connectionRounds}, Failed initial connect: {_failedInitialConnect}, Established initial connect: {_newActiveNodes}, " +
                                          $"Current candidate peers: {_peerPool.CandidatePeerCount}, Current active peers: {_activePeers.Count} " +
                                          $"[InOut: {_activePeers.Count(x => x.Value.OutSession != null && x.Value.InSession != null)} | " +
                                          $"[Out: {_activePeers.Count(x => x.Value.OutSession != null)} | " +
                                          $"In: {_activePeers.Count(x => x.Value.InSession != null)}]");
                        }

                        previousActivePeersCount = activePeersCount;
                    }

                    if (_logger.IsTrace)
                    {
                        if (_logCounter % 5 == 0)
                        {
                            string nl = Environment.NewLine;
                            _logger.Trace($"{nl}{nl}All active peers: {nl} {string.Join(nl, _activePeers.Values.Select(x => $"{x.Node:s} | P2P: {_stats.GetOrAdd(x.Node).DidEventHappen(NodeStatsEventType.P2PInitialized)} | Eth62: {_stats.GetOrAdd(x.Node).DidEventHappen(NodeStatsEventType.Eth62Initialized)} | {_stats.GetOrAdd(x.Node).P2PNodeDetails?.ClientId} | {_stats.GetOrAdd(x.Node).ToString()}"))} {nl}{nl}");
                        }

                        _logCounter++;
                    }

                    if (_activePeers.Count < MaxActivePeers)
                    {
                        _peerUpdateRequested.Set();
                    }
                }
                catch (AggregateException e) when(e.InnerExceptions.Any(inner => inner is OperationCanceledException))
                {
                    if (_logger.IsInfo)
                    {
                        _logger.Info("Peer update loop canceled.");
                    }
                    break;
                }
                catch (OperationCanceledException)
                {
                    if (_logger.IsInfo)
                    {
                        _logger.Info("Peer update loop canceled");
                    }
                    break;
                }
                catch (Exception e)
                {
                    if (_logger.IsError)
                    {
                        _logger.Error("Peer update loop failure", e);
                    }
                    break;
                }
            }
        }
Exemple #31
0
        public void ExecuteReaderWithUpdates(Action <IDataRecord, DbOperation> processRecord)
        {
            lock (_stopLocker)
            {
                if (_disposing)
                {
                    return;
                }
                _stopHandle.Reset();
            }

            var useNotifications = _dbBehavior.StartSqlDependencyListener();

            var delays = _dbBehavior.UpdateLoopRetryDelays;

            for (var i = 0; i < delays.Count; i++)
            {
                if (i == 0 && useNotifications)
                {
                    // Reset the state to ProcessingUpdates if this is the start of the loop.
                    // This should be safe to do here without Interlocked because the state is protected
                    // in the other two cases using Interlocked, i.e. there should only be one instance of
                    // this running at any point in time.
                    _notificationState = NotificationState.ProcessingUpdates;
                }

                Tuple <int, int> retry = delays[i];
                var retryDelay         = retry.Item1;
                var retryCount         = retry.Item2;

                for (var j = 0; j < retryCount; j++)
                {
                    if (_disposing)
                    {
                        Stop(null);
                        return;
                    }

                    if (retryDelay > 0)
                    {
                        Trace.TraceVerbose("{0}Waiting {1}ms before checking for messages again", TracePrefix, retryDelay);

                        Thread.Sleep(retryDelay);
                    }

                    var recordCount = 0;
                    try
                    {
                        recordCount = ExecuteReader(processRecord);

                        Queried();
                    }
                    catch (Exception ex)
                    {
                        Trace.TraceError("{0}Error in SQL receive loop: {1}", TracePrefix, ex);

                        Faulted(ex);
                    }

                    if (recordCount > 0)
                    {
                        Trace.TraceVerbose("{0}{1} records received", TracePrefix, recordCount);

                        // We got records so start the retry loop again
                        i = -1;
                        break;
                    }

                    Trace.TraceVerbose("{0}No records received", TracePrefix);

                    var isLastRetry = i == delays.Count - 1 && j == retryCount - 1;

                    if (isLastRetry)
                    {
                        // Last retry loop iteration
                        if (!useNotifications)
                        {
                            // Last retry loop and we're not using notifications so just stay looping on the last retry delay
                            j = j - 1;
                        }
                        else
                        {
                            // No records after all retries, set up a SQL notification
                            try
                            {
                                Trace.TraceVerbose("{0}Setting up SQL notification", TracePrefix);

                                recordCount = ExecuteReader(processRecord, command =>
                                {
                                    _dbBehavior.AddSqlDependency(command, e => SqlDependency_OnChange(e, processRecord));
                                });

                                Queried();

                                if (recordCount > 0)
                                {
                                    Trace.TraceVerbose("{0}Records were returned by the command that sets up the SQL notification, restarting the receive loop", TracePrefix);

                                    i = -1;
                                    break; // break the inner for loop
                                }
                                else
                                {
                                    var previousState = Interlocked.CompareExchange(ref _notificationState, NotificationState.AwaitingNotification,
                                                                                    NotificationState.ProcessingUpdates);

                                    if (previousState == NotificationState.AwaitingNotification)
                                    {
                                        Trace.TraceError("{0}A SQL notification was already running. Overlapping receive loops detected, this should never happen. BUG!", TracePrefix);

                                        return;
                                    }

                                    if (previousState == NotificationState.NotificationReceived)
                                    {
                                        // Failed to change _notificationState from ProcessingUpdates to AwaitingNotification, it was already NotificationReceived

                                        Trace.TraceVerbose("{0}The SQL notification fired before the receive loop returned, restarting the receive loop", TracePrefix);

                                        i = -1;
                                        break; // break the inner for loop
                                    }
                                }

                                Trace.TraceVerbose("{0}No records received while setting up SQL notification", TracePrefix);

                                // We're in a wait state for a notification now so check if we're disposing
                                lock (_stopLocker)
                                {
                                    if (_disposing)
                                    {
                                        _stopHandle.Set();
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                Trace.TraceError("{0}Error in SQL receive loop: {1}", TracePrefix, ex);
                                Faulted(ex);

                                // Re-enter the loop on the last retry delay
                                j = j - 1;

                                if (retryDelay > 0)
                                {
                                    Trace.TraceVerbose("{0}Waiting {1}ms before checking for messages again", TracePrefix, retryDelay);

                                    Thread.Sleep(retryDelay);
                                }
                            }
                        }
                    }
                }
            }

            Trace.TraceVerbose("{0}Receive loop exiting", TracePrefix);
        }
        private async Task CopyModelAsCsvToStreamAsync(SecurityPrincipal securityPrincipal, NameValueCollection requestParameters, Stream responseStream, CancellationToken cancellationToken)
        {
            const double DefaultFrameRate     = 30;
            const int    DefaultTimestampSnap = 0;

            string dateTimeFormat = Program.Host.Model.Global.DateTimeFormat;

            // TODO: Improve operation for large point lists:
            // Pick-up "POST"ed parameters with a "genurl" param, then cache parameters
            // in a memory cache and return the unique URL (a string instead of a file)
            // with a "download" param and unique ID associated with cached parameters.
            // Then extract params based on unique ID and follow normal steps...

            // Note TSTolerance is in ms
            string pointIDsParam              = requestParameters["PointIDs"];
            string startTimeParam             = requestParameters["StartTime"];
            string endTimeParam               = requestParameters["EndTime"];
            string timestampSnapParam         = requestParameters["TSSnap"];
            string frameRateParam             = requestParameters["FrameRate"];
            string alignTimestampsParam       = requestParameters["AlignTimestamps"];
            string missingAsNaNParam          = requestParameters["MissingAsNaN"];
            string fillMissingTimestampsParam = requestParameters["FillMissingTimestamps"];
            string instanceName               = requestParameters["InstanceName"];
            string toleranceParam             = requestParameters["TSTolerance"];

            ulong[] pointIDs;
            string  headers;

            if (string.IsNullOrEmpty(pointIDsParam))
            {
                throw new ArgumentNullException("PointIDs", "Cannot export data: no values were provided in \"PointIDs\" parameter.");
            }

            try
            {
                pointIDs = pointIDsParam.Split(',').Select(ulong.Parse).ToArray();
                Array.Sort(pointIDs);
            }
            catch (Exception ex)
            {
                throw new ArgumentNullException("PointIDs", $"Cannot export data: failed to parse \"PointIDs\" parameter value \"{pointIDsParam}\": {ex.Message}");
            }

            if (string.IsNullOrEmpty(startTimeParam))
            {
                throw new ArgumentNullException("StartTime", "Cannot export data: no \"StartTime\" parameter value was specified.");
            }

            if (string.IsNullOrEmpty(pointIDsParam))
            {
                throw new ArgumentNullException("EndTime", "Cannot export data: no \"EndTime\" parameter value was specified.");
            }

            DateTime startTime, endTime;

            try
            {
                startTime = DateTime.ParseExact(startTimeParam, dateTimeFormat, null, DateTimeStyles.AdjustToUniversal);
            }
            catch (Exception ex)
            {
                throw new ArgumentException($"Cannot export data: failed to parse \"StartTime\" parameter value \"{startTimeParam}\". Expected format is \"{dateTimeFormat}\". Error message: {ex.Message}", "StartTime", ex);
            }

            try
            {
                endTime = DateTime.ParseExact(endTimeParam, dateTimeFormat, null, DateTimeStyles.AdjustToUniversal);
            }
            catch (Exception ex)
            {
                throw new ArgumentException($"Cannot export data: failed to parse \"EndTime\" parameter value \"{endTimeParam}\". Expected format is \"{dateTimeFormat}\". Error message: {ex.Message}", "EndTime", ex);
            }

            if (startTime > endTime)
            {
                throw new ArgumentOutOfRangeException("StartTime", "Cannot export data: start time exceeds end time.");
            }

            using (DataContext dataContext = new DataContext())
            {
                // Validate current user has access to requested data
                if (!dataContext.UserIsInRole(securityPrincipal, s_minimumRequiredRoles))
                {
                    throw new SecurityException($"Cannot export data: access is denied for user \"{Thread.CurrentPrincipal.Identity?.Name ?? "Undefined"}\", minimum required roles = {s_minimumRequiredRoles.ToDelimitedString(", ")}.");
                }

                headers = GetHeaders(dataContext, pointIDs.Select(id => (int)id));
            }

            if (!double.TryParse(frameRateParam, out double frameRate))
            {
                frameRate = DefaultFrameRate;
            }
            if (!int.TryParse(timestampSnapParam, out int timestampSnap))
            {
                timestampSnap = DefaultTimestampSnap;
            }
            if (!double.TryParse(toleranceParam, out double tolerance))
            {
                tolerance = 0.5;
            }

            int  toleranceTicks        = (int)Math.Ceiling(tolerance * Ticks.PerMillisecond);
            bool alignTimestamps       = alignTimestampsParam?.ParseBoolean() ?? true;
            bool missingAsNaN          = missingAsNaNParam?.ParseBoolean() ?? true;
            bool fillMissingTimestamps = alignTimestamps && (fillMissingTimestampsParam?.ParseBoolean() ?? false);

            if (string.IsNullOrEmpty(instanceName))
            {
                instanceName = TrendValueAPI.DefaultInstanceName;
            }

            LocalOutputAdapter.Instances.TryGetValue(instanceName, out LocalOutputAdapter adapter);
            HistorianServer serverInstance = adapter?.Server;

            if (serverInstance == null)
            {
                throw new InvalidOperationException($"Cannot export data: failed to access internal historian server instance \"{instanceName}\".");
            }

            const int TargetBufferSize = 524288;

            StringBuilder        readBuffer  = new StringBuilder(TargetBufferSize * 2);
            ManualResetEventSlim bufferReady = new ManualResetEventSlim(false);
            List <string>        writeBuffer = new List <string>();
            object writeBufferLock           = new object();
            bool   readComplete = false;

            Task readTask = Task.Factory.StartNew(() =>
            {
                try
                {
                    using (SnapClient connection = SnapClient.Connect(serverInstance.Host))
                    {
                        Dictionary <ulong, int> pointIDIndex = new Dictionary <ulong, int>(pointIDs.Length);
                        float[] values = new float[pointIDs.Length];

                        for (int i = 0; i < pointIDs.Length; i++)
                        {
                            pointIDIndex.Add(pointIDs[i], i);
                        }

                        for (int i = 0; i < values.Length; i++)
                        {
                            values[i] = float.NaN;
                        }

                        ulong interval;

                        if (Math.Abs(frameRate % 1) <= (double.Epsilon * 100))
                        {
                            Ticks[] subseconds = Ticks.SubsecondDistribution((int)frameRate);

                            interval = (ulong)(subseconds.Length > 1 ? subseconds[1].Value : Ticks.PerSecond);
                        }
                        else
                        {
                            interval = (ulong)(Math.Floor(1.0d / frameRate) * Ticks.PerSecond);
                        }


                        ulong lastTimestamp = 0;

                        // Write data pages
                        SeekFilterBase <HistorianKey> timeFilter = TimestampSeekFilter.CreateFromRange <HistorianKey>(startTime, endTime);
                        MatchFilterBase <HistorianKey, HistorianValue> pointFilter = PointIdMatchFilter.CreateFromList <HistorianKey, HistorianValue>(pointIDs);
                        HistorianKey historianKey     = new HistorianKey();
                        HistorianValue historianValue = new HistorianValue();

                        // Write row values function
                        Action bufferValues = () =>
                        {
                            readBuffer.Append(missingAsNaN ? string.Join(",", values) : string.Join(",", values.Select(val => float.IsNaN(val) ? "" : $"{val}")));

                            if (readBuffer.Length < TargetBufferSize)
                            {
                                return;
                            }

                            lock (writeBufferLock)
                                writeBuffer.Add(readBuffer.ToString());

                            readBuffer.Clear();
                            bufferReady.Set();
                        };

                        using (ClientDatabaseBase <HistorianKey, HistorianValue> database = connection.GetDatabase <HistorianKey, HistorianValue>(instanceName))
                        {
                            // Start stream reader for the provided time window and selected points
                            TreeStream <HistorianKey, HistorianValue> stream = database.Read(SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter);
                            ulong timestamp = 0;

                            // Adjust timestamp to use first timestamp as base
                            bool adjustTimeStamp = true;
                            long baseTime        = startTime.Ticks;

                            if (timestampSnap == 0)
                            {
                                adjustTimeStamp = false;
                                baseTime        = Ticks.RoundToSecondDistribution(startTime.Ticks, frameRate, startTime.Ticks - startTime.Ticks % Ticks.PerSecond);
                            }
                            else if (timestampSnap == 1)
                            {
                                adjustTimeStamp = true;
                            }
                            else if (timestampSnap == 2)
                            {
                                adjustTimeStamp = false;
                                baseTime        = startTime.Ticks;
                            }

                            while (stream.Read(historianKey, historianValue) && !cancellationToken.IsCancellationRequested)
                            {
                                if (alignTimestamps)
                                {
                                    if (adjustTimeStamp)
                                    {
                                        adjustTimeStamp = false;
                                        baseTime        = (long)historianKey.Timestamp;
                                    }

                                    // Make sure the timestamp is actually close enough to the distribution
                                    Ticks ticks = Ticks.ToSecondDistribution((long)historianKey.Timestamp, frameRate, baseTime, toleranceTicks);
                                    if (ticks == Ticks.MinValue)
                                    {
                                        continue;
                                    }

                                    timestamp = (ulong)ticks.Value;
                                }
                                else
                                {
                                    timestamp = historianKey.Timestamp;
                                }

                                // Start a new row for each encountered new timestamp
                                if (timestamp != lastTimestamp)
                                {
                                    if (lastTimestamp > 0)
                                    {
                                        bufferValues();
                                    }

                                    for (int i = 0; i < values.Length; i++)
                                    {
                                        values[i] = float.NaN;
                                    }

                                    if (fillMissingTimestamps && lastTimestamp > 0 && timestamp > lastTimestamp)
                                    {
                                        ulong difference = timestamp - lastTimestamp;

                                        if (difference > interval)
                                        {
                                            ulong interpolated = lastTimestamp;

                                            for (ulong i = 1; i < difference / interval; i++)
                                            {
                                                interpolated = (ulong)Ticks.RoundToSecondDistribution((long)(interpolated + interval), frameRate, startTime.Ticks).Value;
                                                readBuffer.Append($"{Environment.NewLine}{new DateTime((long)interpolated, DateTimeKind.Utc).ToString(dateTimeFormat)},");
                                                bufferValues();
                                            }
                                        }
                                    }

                                    readBuffer.Append($"{Environment.NewLine}{new DateTime((long)timestamp, DateTimeKind.Utc).ToString(dateTimeFormat)},");
                                    lastTimestamp = timestamp;
                                }

                                // Save value to its column
                                values[pointIDIndex[historianKey.PointID]] = historianValue.AsSingle;
                            }

                            if (timestamp > 0)
                            {
                                bufferValues();
                            }

                            if (readBuffer.Length > 0)
                            {
                                lock (writeBufferLock)
                                    writeBuffer.Add(readBuffer.ToString());
                            }
                        }
                    }
                }
                finally
                {
                    readComplete = true;
                    bufferReady.Set();
                }
            }, cancellationToken);

            Task writeTask = Task.Factory.StartNew(() =>
            {
                using (StreamWriter writer = new StreamWriter(responseStream))
                {
                    //Ticks exportStart = DateTime.UtcNow.Ticks;
                    string[] localBuffer;

                    // Write column headers
                    writer.Write(headers);

                    while ((writeBuffer.Count > 0 || !readComplete) && !cancellationToken.IsCancellationRequested)
                    {
                        bufferReady.Wait(cancellationToken);
                        bufferReady.Reset();

                        lock (writeBufferLock)
                        {
                            localBuffer = writeBuffer.ToArray();
                            writeBuffer.Clear();
                        }

                        foreach (string buffer in localBuffer)
                        {
                            writer.Write(buffer);
                        }
                    }

                    // Flush stream
                    writer.Flush();

                    //Debug.WriteLine("Export time: " + (DateTime.UtcNow.Ticks - exportStart).ToElapsedTimeString(3));
                }
            }, cancellationToken);

            await readTask;
            await writeTask;
        }
 /// <summary>
 /// Enters the state in which waiters need to wait.
 /// All future waiters will block when they call the Wait method
 /// </summary>
 public void Begin() => Event?.Reset();
Exemple #34
0
        /// <summary>
        /// Mains the periodic task action.
        /// </summary>
        /// <param name="state">state object</param>
        /// <param name="intervalInMilliseconds">The interval in milliseconds.</param>
        /// <param name="delayInMilliseconds">The delay in milliseconds.</param>
        /// <param name="duration">The duration.</param>
        /// <param name="maxIterations">The max iterations.</param>
        /// <param name="cancelToken">The cancel token.</param>
        /// <param name="stopWatch">The stop watch.</param>
        /// <param name="synchronous">if set to <c>true</c> executes each period in a blocking fashion and each periodic execution of the task
        /// is included in the total duration of the Task.</param>
        /// <param name="wrapperAction">The wrapper action.</param>
        /// <param name="periodicTaskCreationOptions"><see cref="TaskCreationOptions"/> used to create a sub task for executing the <see cref="Action"/>.</param>
        private static void MainPeriodicTaskAction(object state,
                                                   int intervalInMilliseconds,
                                                   int delayInMilliseconds,
                                                   int duration,
                                                   int maxIterations,
                                                   CancellationToken cancelToken,
                                                   Stopwatch stopWatch,
                                                   bool synchronous,
                                                   Action <object> wrapperAction,
                                                   TaskCreationOptions periodicTaskCreationOptions)
        {
            TaskCreationOptions subTaskCreationOptions = TaskCreationOptions.AttachedToParent | periodicTaskCreationOptions;

            CheckIfCancelled(cancelToken);

            if (delayInMilliseconds > 0)
            {
                Thread.Sleep(delayInMilliseconds);
            }

            if (maxIterations == 0)
            {
                return;
            }

            int iteration = 0;

            ////////////////////////////////////////////////////////////////////////////
            // using a ManualResetEventSlim as it is more efficient in small intervals.
            // In the case where longer intervals are used, it will automatically use
            // a standard WaitHandle....
            // see http://msdn.microsoft.com/en-us/library/vstudio/5hbefs30(v=vs.100).aspx
            using (ManualResetEventSlim periodResetEvent = new ManualResetEventSlim(false))
            {
                ////////////////////////////////////////////////////////////
                // Main periodic logic. Basically loop through this block
                // executing the action
                while (true)
                {
                    CheckIfCancelled(cancelToken);

                    Task subTask = Task.Factory.StartNew(wrapperAction, state, cancelToken, subTaskCreationOptions, TaskScheduler.Current);

                    if (synchronous)
                    {
                        stopWatch.Start();
                        try
                        {
                            subTask.Wait(cancelToken);
                        }
                        catch { /* do not let an errant subtask to kill the periodic task...*/ }
                        stopWatch.Stop();
                    }

                    // use the same Timeout setting as the System.Threading.Timer, infinite timeout will execute only one iteration.
                    if (intervalInMilliseconds == Timeout.Infinite)
                    {
                        break;
                    }

                    iteration++;

                    if (maxIterations > 0 && iteration >= maxIterations)
                    {
                        break;
                    }

                    try
                    {
                        stopWatch.Start();
                        periodResetEvent.Wait(intervalInMilliseconds, cancelToken);
                        stopWatch.Stop();
                    }
                    finally
                    {
                        periodResetEvent.Reset();
                    }

                    CheckIfCancelled(cancelToken);

                    if (duration > 0 && stopWatch.ElapsedMilliseconds >= duration)
                    {
                        break;
                    }
                }
            }
        }