public async Task ExceedReadRate()
        {
            // Ensure the read rate is smaller than a block
            await diskManager.UpdateSettingsAsync(new EngineSettingsBuilder { MaximumDiskReadRate = 1 }.ToSettings());

            await diskManager.Tick(1000).WithTimeout();

            // Queue up 6 reads, none should process.
            var buffer = new byte[Piece.BlockSize];
            int count  = 6;
            var tasks  = new List <Task> ();

            for (int i = 0; i < count; i++)
            {
                tasks.Add(diskManager.ReadAsync(fileData, new BlockInfo(0, 0, buffer.Length), buffer).AsTask());
            }

            Assert.AreEqual(buffer.Length * count, diskManager.PendingReadBytes, "#1");

            // We should still process none.
            await diskManager.Tick(1000).WithTimeout();

            Assert.AreEqual(buffer.Length * count, diskManager.PendingReadBytes, "#2");

            // Give a proper max read rate.
            await diskManager.UpdateSettingsAsync(new EngineSettingsBuilder { MaximumDiskReadRate = Piece.BlockSize * 2 }.ToSettings());

            for (int i = 0; i < 2; i++)
            {
                await diskManager.Tick(1000).WithTimeout();

                for (int t = 0; t < 2; t++)
                {
                    var completed = await Task.WhenAny(tasks).WithTimeout();

                    await completed;
                    tasks.Remove(completed);
                }
                Assert.IsFalse(tasks.Any(t => t.IsCompleted));

                count -= 2;
                Assert.AreEqual(buffer.Length * count, diskManager.PendingReadBytes, "#3." + i);
            }

            // If we add more reads after we used up our allowance they still won't process.
            for (int i = 0; i < 2; i++)
            {
                count++;
                tasks.Add(diskManager.ReadAsync(fileData, new BlockInfo(0, 0, buffer.Length), buffer).AsTask());
            }
            Assert.AreEqual(buffer.Length * count, diskManager.PendingReadBytes, "#4." + count);
            while (count > 0)
            {
                await diskManager.Tick(1000).WithTimeout();

                for (int t = 0; t < 2; t++)
                {
                    var completed = await Task.WhenAny(tasks).WithTimeout();

                    await completed;
                    tasks.Remove(completed);
                }
                Assert.IsFalse(tasks.Any(t => t.IsCompleted));

                count -= 2;
                Assert.AreEqual(buffer.Length * count, diskManager.PendingReadBytes, "#5." + count);
            }
        }
Example #2
0
        async Task UpdateSettingsAsync(EngineSettings oldSettings, EngineSettings newSettings)
        {
            await DiskManager.UpdateSettingsAsync(newSettings);

            if (newSettings.DiskCacheBytes != oldSettings.DiskCacheBytes)
            {
                await Task.WhenAll(Torrents.Select(t => DiskManager.FlushAsync(t)));
            }

            ConnectionManager.Settings = newSettings;

            if (oldSettings.AllowPortForwarding != newSettings.AllowPortForwarding)
            {
                if (newSettings.AllowPortForwarding)
                {
                    await PortForwarder.StartAsync(CancellationToken.None);
                }
                else
                {
                    await PortForwarder.StopAsync(removeExistingMappings : true, CancellationToken.None);
                }
            }

            if (oldSettings.DhtPort != newSettings.DhtPort)
            {
                if (DhtListener.EndPoint != null)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Udp, DhtListener.EndPoint.Port), CancellationToken.None);
                }
                else if (oldSettings.DhtPort > 0)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Udp, oldSettings.DhtPort), CancellationToken.None);
                }

                DhtListener = DhtListenerFactory.CreateUdp(newSettings.DhtPort);

                if (oldSettings.DhtPort == -1)
                {
                    await RegisterDht(DhtEngineFactory.Create(DhtListener));
                }
                else if (newSettings.DhtPort == -1)
                {
                    await RegisterDht(new NullDhtEngine());
                }

                DhtEngine.SetListener(DhtListener);

                if (IsRunning)
                {
                    DhtListener.Start();
                    if (Listener is ISocketListener newDhtListener)
                    {
                        await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Udp, newDhtListener.EndPoint.Port));
                    }
                    else
                    {
                        await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Udp, newSettings.DhtPort));
                    }
                }
            }

            if (oldSettings.ListenPort != newSettings.ListenPort)
            {
                if (Listener is ISocketListener oldListener)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Tcp, oldListener.EndPoint.Port), CancellationToken.None);
                }
                else if (oldSettings.ListenPort > 0)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Tcp, oldSettings.ListenPort), CancellationToken.None);
                }

                Listener.Stop();
                Listener = PeerListenerFactory.CreateTcp(newSettings.ListenPort);
                listenManager.SetListener(Listener);

                if (IsRunning)
                {
                    Listener.Start();
                    // The settings could say to listen at port 0, which means 'choose one dynamically'
                    if (Listener is ISocketListener peerListener)
                    {
                        await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Tcp, peerListener.EndPoint.Port));
                    }
                    else
                    {
                        await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Tcp, newSettings.ListenPort));
                    }
                }
            }

            // This depends on the Listener binding to it's local port.
            var localPort = newSettings.ListenPort;

            if (Listener is ISocketListener newListener)
            {
                localPort = newListener.EndPoint.Port;
            }

            if ((oldSettings.AllowLocalPeerDiscovery != newSettings.AllowLocalPeerDiscovery) ||
                (oldSettings.ListenPort != newSettings.ListenPort))
            {
                RegisterLocalPeerDiscovery(newSettings.AllowLocalPeerDiscovery && localPort > 0 ? new LocalPeerDiscovery(localPort) : null);
            }
        }
Example #3
0
        async Task UpdateSettingsAsync(EngineSettings oldSettings, EngineSettings newSettings)
        {
            await DiskManager.UpdateSettingsAsync(newSettings);

            if (newSettings.DiskCacheBytes != oldSettings.DiskCacheBytes)
            {
                await Task.WhenAll(Torrents.Select(t => DiskManager.FlushAsync(t)));
            }

            ConnectionManager.Settings = newSettings;

            if (oldSettings.UsePartialFiles != newSettings.UsePartialFiles)
            {
                foreach (var manager in Torrents)
                {
                    await manager.UpdateUsePartialFiles(newSettings.UsePartialFiles);
                }
            }
            if (oldSettings.AllowPortForwarding != newSettings.AllowPortForwarding)
            {
                if (newSettings.AllowPortForwarding)
                {
                    await PortForwarder.StartAsync(CancellationToken.None);
                }
                else
                {
                    await PortForwarder.StopAsync(removeExistingMappings : true, CancellationToken.None);
                }
            }

            if (oldSettings.DhtEndPoint != newSettings.DhtEndPoint)
            {
                if (DhtListener.LocalEndPoint != null)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Udp, DhtListener.LocalEndPoint.Port), CancellationToken.None);
                }
                DhtListener.Stop();

                if (newSettings.DhtEndPoint == null)
                {
                    DhtListener = new NullDhtListener();
                    await RegisterDht(new NullDhtEngine());
                }
                else
                {
                    DhtListener = Factories.CreateDhtListener(Settings.DhtEndPoint) ?? new NullDhtListener();
                    if (IsRunning)
                    {
                        DhtListener.Start();
                    }

                    if (oldSettings.DhtEndPoint == null)
                    {
                        var dht = Factories.CreateDht();
                        await dht.SetListenerAsync(DhtListener);
                        await RegisterDht(dht);
                    }
                    else
                    {
                        await DhtEngine.SetListenerAsync(DhtListener);
                    }
                }

                if (DhtListener.LocalEndPoint != null)
                {
                    await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Udp, DhtListener.LocalEndPoint.Port));
                }
            }

            if (!Equals(oldSettings.ListenEndPoint, newSettings.ListenEndPoint))
            {
                if (PeerListener.LocalEndPoint != null)
                {
                    await PortForwarder.UnregisterMappingAsync(new Mapping (Protocol.Tcp, PeerListener.LocalEndPoint.Port), CancellationToken.None);
                }

                PeerListener.Stop();
                PeerListener = (newSettings.ListenEndPoint == null ? null : Factories.CreatePeerConnectionListener(newSettings.ListenEndPoint)) ?? new NullPeerListener();
                listenManager.SetListener(PeerListener);

                if (IsRunning)
                {
                    PeerListener.Start();
                    // The settings could say to listen at port 0, which means 'choose one dynamically'
                    if (PeerListener.LocalEndPoint != null)
                    {
                        await PortForwarder.RegisterMappingAsync(new Mapping (Protocol.Tcp, PeerListener.LocalEndPoint.Port));
                    }
                }
            }

            if (oldSettings.AllowLocalPeerDiscovery != newSettings.AllowLocalPeerDiscovery)
            {
                RegisterLocalPeerDiscovery(!newSettings.AllowLocalPeerDiscovery ? null : Factories.CreateLocalPeerDiscovery());
            }
        }