/// <summary>
        /// Process a config response (no longer supported or encouraged; for backwards-compatibility)
        /// </summary>
        /// <param name="response">Legacy config response</param>
        /// <returns>Asynchronous task</returns>
        public static async Task ProcessLegacyConfigResponse(byte[] response)
        {
            using JsonDocument jsonDocument = JsonDocument.Parse(response);
            using (await _monitor.EnterAsync(Program.CancellationToken))
            {
                if (jsonDocument.RootElement.TryGetProperty("boardName", out JsonElement boardName))
                {
                    using (await Provider.AccessReadWriteAsync())
                    {
                        Provider.Get.Boards.Add(new Board
                        {
                            IapFileNameSBC   = $"Duet3_SBCiap_{boardName.GetString()}.bin",
                            FirmwareFileName = $"Duet3Firmware_{boardName.GetString()}.bin"
                        });
                    }
                    _logger.Warn("Deprecated firmware detected, please update it in order to use DSF");
                }
                else
                {
                    // boardName field is not present - this must be a really old firmware version
                    using (await Provider.AccessReadWriteAsync())
                    {
                        Provider.Get.Boards.Add(new Board
                        {
                            IapFileNameSBC   = $"Duet3_SDiap_MB6HC.bin",
                            FirmwareFileName = "Duet3Firmware_MB6HC.bin"
                        });
                    }
                    _logger.Warn("Deprecated firmware detected, assuming legacy firmware files. You may have to use bossa to update it");
                }

                // Cannot perform any further updates...
                _monitor.PulseAll();

                // Check if the firmware is supposed to be updated
                if (Settings.UpdateOnly && !_updatingFirmware)
                {
                    _updatingFirmware = true;
                    _ = Task.Run(UpdateFirmware);
                }
            }
        }
        /// <summary>
        /// Process status updates in the background
        /// </summary>
        /// <returns>Asynchronous task</returns>
        public static async Task Run()
        {
            CancellationToken cancellationToken = Program.CancelSource.Token;

            do
            {
                // Wait for the next status response
                using (await _monitor.EnterAsync(cancellationToken))
                {
                    await _monitor.WaitAsync(cancellationToken);

                    cancellationToken.ThrowIfCancellationRequested();

                    // Process it
                    try
                    {
                        ReadOnlyMemory <byte> json = _json.AsMemory().Slice(0, _jsonLength);
                        switch (_module)
                        {
                        case 2:
                            await ProcessAdvancedResponse(json);

                            break;

                        case 3:
                            await ProcessPrintResponse(json);

                            break;

                        case 5:
                            await ProcessConfigResponse(json);

                            break;
                        }

                        // Notify waiting clients about the model update
                        if (_module == 2)
                        {
                            _updateEvent.PulseAll();
                        }
                    }
                    catch (JsonException e)
                    {
                        _logger.Error(e, "Failed to merge JSON (module {0})", _module);
                    }
                }
            }while (true);
        }
Beispiel #3
0
        public void PulseAll_ReleasesAllWaiters()
        {
            AsyncContext.Run(async() =>
            {
                var monitor    = new AsyncMonitor();
                int completed  = 0;
                var task1Ready = new TaskCompletionSource();
                var task2Ready = new TaskCompletionSource();
                Task <IDisposable> lockTask1 = null;
                Task waitTask1 = null;
                var task1      = Task.Run(async() =>
                {
                    lockTask1 = monitor.EnterAsync();
                    using (await lockTask1)
                    {
                        waitTask1 = monitor.WaitAsync();
                        task1Ready.SetResult();
                        await waitTask1;
                        Interlocked.Increment(ref completed);
                    }
                });
                await task1Ready.Task;
                Task <IDisposable> lockTask2 = null;
                Task waitTask2 = null;
                var task2      = Task.Run(async() =>
                {
                    lockTask2 = monitor.EnterAsync();
                    using (await lockTask2)
                    {
                        waitTask2 = monitor.WaitAsync();
                        task2Ready.SetResult();
                        await waitTask2;
                        Interlocked.Increment(ref completed);
                    }
                });
                await task2Ready.Task;

                var lockTask3 = monitor.EnterAsync();
                using (await lockTask3)
                {
                    monitor.PulseAll();
                }
                await Task.WhenAll(task1, task2);
                var result = Interlocked.CompareExchange(ref completed, 0, 0);

                Assert.AreEqual(2, result);
            });
        }
        public async Task PulseAll_ReleasesAllWaiters()
        {
            AsyncMonitor monitor = new AsyncMonitor();

            int[] completed = { 0 };
            TaskCompletionSource <object> task1Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            TaskCompletionSource <object> task2Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            Task waitTask1 = null;
            Task task1     = Task.Run(async() =>
            {
                using (await monitor.EnterAsync())
                {
                    waitTask1 = monitor.WaitAsync();
                    task1Ready.SetResult(null);
                    await waitTask1;
                    Interlocked.Increment(ref completed[0]);
                }
            });
            await task1Ready.Task;
            Task waitTask2 = null;
            Task task2     = Task.Run(async() =>
            {
                using (await monitor.EnterAsync())
                {
                    waitTask2 = monitor.WaitAsync();
                    task2Ready.SetResult(null);
                    await waitTask2;
                    Interlocked.Increment(ref completed[0]);
                }
            });
            await task2Ready.Task;

            AwaitableDisposable <IDisposable> lockTask3 = monitor.EnterAsync();

            using (await lockTask3)
            {
                monitor.PulseAll();
            }
            await Task.WhenAll(task1, task2).ConfigureAwait(false);

            int result = Interlocked.CompareExchange(ref completed[0], 0, 0);

            Assert.Equal(2, result);
        }
        public async Task PulseAll_ReleasesAllWaiters()
        {
            var  monitor    = new AsyncMonitor();
            int  completed  = 0;
            var  task1Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            var  task2Ready = TaskCompletionSourceExtensions.CreateAsyncTaskSource <object>();
            Task waitTask1  = null;
            var  task1      = Task.Run(async() =>
            {
                using (await monitor.EnterAsync())
                {
                    waitTask1 = monitor.WaitAsync();
                    task1Ready.SetResult(null);
                    await waitTask1;
                    Interlocked.Increment(ref completed);
                }
            });
            await task1Ready.Task;
            Task waitTask2 = null;
            var  task2     = Task.Run(async() =>
            {
                using (await monitor.EnterAsync())
                {
                    waitTask2 = monitor.WaitAsync();
                    task2Ready.SetResult(null);
                    await waitTask2;
                    Interlocked.Increment(ref completed);
                }
            });
            await task2Ready.Task;

            var lockTask3 = monitor.EnterAsync();

            using (await lockTask3)
            {
                monitor.PulseAll();
            }
            await Task.WhenAll(task1, task2);

            var result = Interlocked.CompareExchange(ref completed, 0, 0);

            Assert.Equal(2, result);
        }
Beispiel #6
0
        public async Task <IPipelineStatus> AddJobs(IPipelineRunManager pipelineRunManager, IEnumerable <BuildJob> jobs, int buildNum, CancellationToken cancellationToken)
        {
            var dependentJobs = new HashSet <BuildJob>();
            var jobMap        = new Dictionary <BuildJob, IJobStatus>();

            var runnableJobs = new List <RunnableJob>();

            foreach (var job in jobs)
            {
                AddBuildJob(pipelineRunManager, job, runnableJobs, dependentJobs, jobMap);
            }

            var jobIds = new HashSet <string>(jobMap.Count);

            foreach (var buildJob in jobMap.Keys)
            {
                if (!jobIds.Add(buildJob.Id))
                {
                    throw new Exception("Duplicate job id.");
                }
            }

            runnableJobs.Reverse();

            using (await monitor.EnterAsync(cancellationToken)) {
                foreach (var jobRun in runnableJobs)
                {
                    await jobRun.Status.WriteBuildJobFile();

                    jobQueue.AddLast(jobRun);
                }

                monitor.PulseAll();
            }

            return(new PipelineStatus(
                       new ReadOnlyDictionary <string, IJobStatus>(jobMap.ToDictionary(kvp => kvp.Key.Id, kvp => kvp.Value)),
                       buildNum,
                       pipelineRunManager.PipelineDir
                       ));
        }
        ///    <summary>
        ///    MoveNext the enumerator
        ///    </summary>
        ///    <returns></returns>
        public async ValueTask <bool> MoveNextAsync()
        {
            using (await monitor.EnterAsync())
            {
                if (Interlocked.Increment(ref callsToMoveNext) == numberOfConsumers)
                {
                    callsToMoveNext = 0;
                    moveNext        = await innerEnumerator.MoveNextAsync();

                    current = innerEnumerator.Current;

                    Debug("Pulsing all waiting threads");

                    monitor.PulseAll();
                }
                else
                {
                    await monitor.WaitAsync();
                }
            }
            return(moveNext);
        }
Beispiel #8
0
        public void ProcessIncoming(Message msg, NetworkConnection conn, WeakReference <NetworkConnection> connWeak)
        {
            IDisposable monitor = null;

            try
            {
                monitor = m_monitor.Enter();
                IDisposable     monitorToUnlock;
                Message.MsgType type = msg.Type;
                SequenceNumber  seqNum;
                Entry           entry;
                uint            id;

                switch (type)
                {
                case KeepAlive:
                    break;     // ignore

                case ClientHello:
                case ProtoUnsup:
                case ServerHelloDone:
                case ServerHello:
                case ClientHelloDone:
                    // shouldn't get these, but ignore if we do
                    break;

                case EntryAssign:
                {
                    id = msg.Id;
                    string name          = msg.Str;
                    bool   mayNeedUpdate = false;
                    if (m_server)
                    {
                        if (id == 0xffff)
                        {
                            if (m_entries.ContainsKey(name))
                            {
                                return;
                            }


                            id    = (uint)m_idMap.Count;
                            entry = new Entry(name)
                            {
                                Value = msg.Val,
                                Flags = (EntryFlags)msg.Flags,
                                Id    = id
                            };
                            m_entries[name] = entry;
                            m_idMap.Add(entry);

                            if (entry.IsPersistent())
                            {
                                m_persistentDirty = true;
                            }

                            m_notifier.NotifyEntry(name, entry.Value, NotifyFlags.NotifyNew);

                            if (m_queueOutgoing != null)
                            {
                                var queueOutgoing = m_queueOutgoing;
                                var outMsg        = Message.EntryAssign(name, id, entry.SeqNum.Value, msg.Val, (EntryFlags)msg.Flags);
                                monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                                monitorToUnlock.Dispose();
                                queueOutgoing(outMsg, null, null);
                            }

                            return;
                        }
                        if (id >= m_idMap.Count || m_idMap[(int)id] == null)
                        {
                            monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                            monitorToUnlock.Dispose();
                            Debug("server: received assignment to unknown entry");
                            return;
                        }
                        entry = m_idMap[(int)id];
                    }
                    else
                    {
                        if (id == 0xffff)
                        {
                            monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                            monitorToUnlock.Dispose();
                            Debug("client: received entry assignment request?");
                            return;
                        }
                        if (id >= m_idMap.Count)
                        {
                            ResizeIdMap(id + 1);
                        }
                        entry = m_idMap[(int)id];
                        if (entry == null)
                        {
                            Entry newEntry;
                            if (!m_entries.ContainsKey(name))
                            {
                                //Entry didn't exist at all.
                                newEntry = new Entry(name)
                                {
                                    Value = msg.Val,
                                    Flags = (EntryFlags)msg.Flags,
                                    Id    = id
                                };
                                m_idMap[(int)id] = newEntry;
                                m_entries[name]  = newEntry;

                                m_notifier.NotifyEntry(name, newEntry.Value, NotifyFlags.NotifyNew);
                                return;
                            }
                            else
                            {
                                newEntry = m_entries[name];
                            }
                            mayNeedUpdate    = true;
                            entry            = newEntry;
                            entry.Id         = id;
                            m_idMap[(int)id] = entry;

                            if ((EntryFlags)msg.Flags != entry.Flags)
                            {
                                var queueOutgoing = m_queueOutgoing;
                                var outmsg        = Message.FlagsUpdate(id, entry.Flags);
                                monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                                monitorToUnlock.Dispose();
                                queueOutgoing(outmsg, null, null);
                                Interlocked.Exchange(ref monitor, m_monitor.Enter());
                            }
                        }
                    }

                    seqNum = new SequenceNumber(msg.SeqNumUid);
                    if (seqNum < entry.SeqNum)
                    {
                        if (mayNeedUpdate)
                        {
                            var queueOutgoing = m_queueOutgoing;
                            var outmsg        = Message.EntryUpdate(entry.Id, entry.SeqNum.Value, entry.Value);
                            monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                            monitorToUnlock.Dispose();
                            queueOutgoing(outmsg, null, null);
                        }
                        return;
                    }
                    //Sanity check. Name should match id
                    if (msg.Str != entry.Name)
                    {
                        monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                        monitorToUnlock.Dispose();
                        Debug("entry assignment for same id with different name?");
                        return;
                    }

                    NotifyFlags notifyFlags = NotifyFlags.NotifyUpdate;

                    if (!mayNeedUpdate && conn.ProtoRev >= 0x0300)
                    {
                        if ((entry.Flags & EntryFlags.Persistent) != ((EntryFlags)msg.Flags & EntryFlags.Persistent))
                        {
                            m_persistentDirty = true;
                        }
                        if (entry.Flags != (EntryFlags)msg.Flags)
                        {
                            notifyFlags |= NotifyFlags.NotifyFlagsChanged;
                        }
                        entry.Flags = (EntryFlags)msg.Flags;
                    }

                    if (entry.IsPersistent() && entry.Value != msg.Val)
                    {
                        m_persistentDirty = true;
                    }

                    entry.Value  = msg.Val;
                    entry.SeqNum = seqNum;

                    m_notifier.NotifyEntry(name, entry.Value, notifyFlags);

                    if (m_server && m_queueOutgoing != null)
                    {
                        var queueOutgoing = m_queueOutgoing;
                        var outmsg        = Message.EntryAssign(entry.Name, id, msg.SeqNumUid, msg.Val, entry.Flags);
                        monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                        monitorToUnlock.Dispose();
                        queueOutgoing(outmsg, null, conn);
                    }
                    break;
                }

                case EntryUpdate:
                    id = msg.Id;
                    if (id >= m_idMap.Count || m_idMap[(int)id] == null)
                    {
                        monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                        monitorToUnlock.Dispose();
                        Debug("received update to unknown entyr");
                        return;
                    }

                    entry = m_idMap[(int)id];

                    seqNum = new SequenceNumber(msg.SeqNumUid);

                    if (seqNum <= entry.SeqNum)
                    {
                        return;
                    }

                    entry.Value  = msg.Val;
                    entry.SeqNum = seqNum;

                    if (entry.IsPersistent())
                    {
                        m_persistentDirty = true;
                    }
                    m_notifier.NotifyEntry(entry.Name, entry.Value, NotifyFlags.NotifyUpdate);

                    if (m_server && m_queueOutgoing != null)
                    {
                        var queueOutgoing = m_queueOutgoing;
                        monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                        monitorToUnlock.Dispose();
                        queueOutgoing(msg, null, conn);
                    }
                    break;

                case FlagsUpdate:
                {
                    id = msg.Id;
                    if (id >= m_idMap.Count || m_idMap[(int)id] == null)
                    {
                        monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                        monitorToUnlock.Dispose();
                        Debug("reeived flags update to unknown entry");
                        return;
                    }

                    entry = m_idMap[(int)id];

                    if (entry.Flags == (EntryFlags)msg.Flags)
                    {
                        return;
                    }

                    if ((entry.Flags & EntryFlags.Persistent) != ((EntryFlags)msg.Flags & EntryFlags.Persistent))
                    {
                        m_persistentDirty = true;
                    }

                    entry.Flags = (EntryFlags)msg.Flags;

                    m_notifier.NotifyEntry(entry.Name, entry.Value, NotifyFlags.NotifyFlagsChanged);

                    if (m_server && m_queueOutgoing != null)
                    {
                        var queueOutgoing = m_queueOutgoing;
                        monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                        monitorToUnlock.Dispose();
                        queueOutgoing(msg, null, conn);
                    }
                    break;
                }

                case EntryDelete:
                {
                    id = msg.Id;
                    if (id >= m_idMap.Count || m_idMap[(int)id] == null)
                    {
                        monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                        monitorToUnlock.Dispose();
                        Debug("received delete to unknown entry");
                        return;
                    }


                    entry = m_idMap[(int)id];

                    if (entry.IsPersistent())
                    {
                        m_persistentDirty = true;
                    }

                    m_idMap[(int)id] = null;

                    if (m_entries.TryGetValue(entry.Name, out entry))
                    {
                        m_entries.Remove(entry.Name);

                        m_notifier.NotifyEntry(entry.Name, entry.Value, NotifyFlags.NotifyDelete);
                    }

                    if (m_server && m_queueOutgoing != null)
                    {
                        var queueOutgoing = m_queueOutgoing;
                        monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                        monitorToUnlock.Dispose();
                        queueOutgoing(msg, null, conn);
                    }
                    break;
                }

                case ClearEntries:
                {
                    DeleteAllEntriesImpl();

                    if (m_server && m_queueOutgoing != null)
                    {
                        var queueOutgoing = m_queueOutgoing;
                        monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                        monitorToUnlock.Dispose();
                        queueOutgoing(msg, null, conn);
                    }
                    break;
                }

                case ExecuteRpc:
                    if (!m_server)
                    {
                        return;
                    }
                    id = msg.Id;
                    if (id >= m_idMap.Count || m_idMap[(int)id] == null)
                    {
                        monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                        monitorToUnlock.Dispose();
                        Debug("received RPC call to unknown entry");
                        return;
                    }
                    entry = m_idMap[(int)id];
                    if (!entry.Value.IsRpc())
                    {
                        monitorToUnlock = Interlocked.Exchange(ref monitor, null);
                        monitorToUnlock.Dispose();
                        Debug("received RPC call to non-RPC entry");
                        return;
                    }
                    m_rpcServer.ProcessRpc(entry.Name, msg, entry.RpcCallback, conn.Uid, message =>
                    {
                        NetworkConnection c;
                        connWeak.TryGetTarget(out c);
                        if (c != null && !c.Disposed)
                        {
                            c.QueueOutgoing(message);
                        }
                    });
                    break;

                case RpcResponse:
                    if (m_server)
                    {
                        return;
                    }
                    if (!msg.Val.IsRpc())
                    {
                        return;                       //Not an RPC message
                    }
                    m_rpcResults.Add(new ImmutablePair <uint, uint>(msg.Id, msg.SeqNumUid), msg.Val.GetRpc());
                    m_monitor.PulseAll();
                    break;
                }
            }
            finally
            {
                monitor?.Dispose();
            }
        }