Author: alanmc
Date: 2008-01-03 11:58:11 -0500 (Thu, 03 Jan 2008)
New Revision: 92190
Modified:
trunk/bitsharp/src/MonoTorrent/Client/BufferedFileRead.cs
trunk/bitsharp/src/MonoTorrent/Client/BufferedFileWrite.cs
trunk/bitsharp/src/MonoTorrent/Client/Managers/DiskManager.cs
trunk/bitsharp/src/MonoTorrent/Client/Managers/FileManager.cs
trunk/bitsharp/src/MonoTorrent/Client/Managers/TorrentManager.cs
Log:
Implemented initial read rate limiting. Now both read and write limiting are
supported. Huzzah!
Modified: trunk/bitsharp/src/MonoTorrent/Client/BufferedFileRead.cs
===================================================================
--- trunk/bitsharp/src/MonoTorrent/Client/BufferedFileRead.cs 2008-01-03
16:46:00 UTC (rev 92189)
+++ trunk/bitsharp/src/MonoTorrent/Client/BufferedFileRead.cs 2008-01-03
16:58:11 UTC (rev 92190)
@@ -1,10 +1,28 @@
using System;
using System.Collections.Generic;
using System.Text;
+using System.Threading;
namespace MonoTorrent.Client
{
public class BufferedFileRead
{
+ public ManualResetEvent WaitHandle;
+ public FileManager Manager;
+ public byte[] Buffer;
+ public int BufferOffset;
+ public long PieceStartIndex;
+ public int Count;
+
+
+ public BufferedFileRead(FileManager manager, byte[] buffer, int
bufferOffset, long pieceStartIndex, int count)
+ {
+ this.Manager = manager;
+ this.Buffer = buffer;
+ this.BufferOffset = bufferOffset;
+ this.PieceStartIndex = pieceStartIndex;
+ this.Count = count;
+ this.WaitHandle = new ManualResetEvent(false);
+ }
}
}
Modified: trunk/bitsharp/src/MonoTorrent/Client/BufferedFileWrite.cs
===================================================================
--- trunk/bitsharp/src/MonoTorrent/Client/BufferedFileWrite.cs 2008-01-03
16:46:00 UTC (rev 92189)
+++ trunk/bitsharp/src/MonoTorrent/Client/BufferedFileWrite.cs 2008-01-03
16:58:11 UTC (rev 92190)
@@ -3,6 +3,7 @@
using System.Text;
using MonoTorrent.Client.PeerMessages;
using MonoTorrent.Common;
+using System.Threading;
namespace MonoTorrent.Client
{
@@ -14,6 +15,7 @@
public PeerIdInternal Id;
public IPeerMessageInternal Message;
public Piece Piece;
+ public ManualResetEvent WaitHandle;
#endregion Fields
@@ -21,11 +23,18 @@
#region Constructors
public BufferedIO(PeerIdInternal id, ArraySegment<byte> buffer,
IPeerMessageInternal message, Piece piece)
+ : this(id, buffer, message, piece, null)
{
+
+ }
+
+ public BufferedIO(PeerIdInternal id, ArraySegment<byte> buffer,
IPeerMessageInternal message, Piece piece, ManualResetEvent handle)
+ {
this.Id = id;
this.Buffer = buffer;
this.Message = message;
this.Piece = piece;
+ this.WaitHandle = handle;
}
#endregion Constructors
Modified: trunk/bitsharp/src/MonoTorrent/Client/Managers/DiskManager.cs
===================================================================
--- trunk/bitsharp/src/MonoTorrent/Client/Managers/DiskManager.cs
2008-01-03 16:46:00 UTC (rev 92189)
+++ trunk/bitsharp/src/MonoTorrent/Client/Managers/DiskManager.cs
2008-01-03 16:58:11 UTC (rev 92190)
@@ -13,6 +13,7 @@
{
#region Member Variables
+ Queue<BufferedFileRead> bufferedReads;
Queue<BufferedIO> bufferedWrites;
private ClientEngine engine;
private int maxOpenStreams;
@@ -29,7 +30,6 @@
#region Old Variables
- //private FileStream[] fileStreams; // The
filestreams used to read/write to the files on disk
private bool ioActive; // Used to
signal when the IO thread is running
private Thread ioThread; // The
dedicated thread used for reading/writing
private object queueLock; // Used to
synchronise access on the IO thread
@@ -96,6 +96,7 @@
public DiskManager(ClientEngine engine)
{
+ this.bufferedReads = new Queue<BufferedFileRead>();
this.bufferedWrites = new Queue<BufferedIO>();
this.engine = engine;
this.ioActive = true;
@@ -105,7 +106,7 @@
this.rateLimiter = new RateLimiter();
this.streamsLock = new ReaderWriterLock();
this.threadWait = new ManualResetEvent(false);
- this.MaxWriteRate = 50;
+ this.MaxReadRate = 1000;
this.ioThread.Start();
}
@@ -134,6 +135,17 @@
/// <summary>
+ ///
+ /// </summary>
+ /// <param name="torrentManager"></param>
+ internal void CloseFileStreams(TorrentManager torrentManager)
+ {
+#warning Buffer the Filestreams
+ return;
+ }
+
+
+ /// <summary>
/// Disposes all necessary objects
/// </summary>
internal void Dispose()
@@ -178,8 +190,11 @@
/// <param name="s"></param>
internal void FreeStream(Stream s)
{
- s.Dispose();
- Interlocked.Decrement(ref openStreams);
+ if (s != null)
+ {
+ s.Dispose();
+ Interlocked.Decrement(ref openStreams);
+ }
}
@@ -260,9 +275,10 @@
/// Performs the buffered read
/// </summary>
/// <param name="bufferedFileIO"></param>
- private void PerformRead(BufferedIO bufferedFileIO)
+ private void PerformRead(BufferedFileRead io)
{
- throw new Exception("The method or operation is not implemented.");
+ Read(io.Manager, io.Buffer, io.BufferOffset, io.PieceStartIndex,
io.Count);
+ io.WaitHandle.Set();
}
@@ -290,22 +306,13 @@
}
- /// <summary>
- /// Queues a read request to be completed asynchronously
- /// </summary>
- /// <param name="id">The peer which the write request is for</param>
- /// <param name="recieveBuffer">The buffer to read the data
into</param>
- /// <param name="message">The RequestMessage</param>
- /// <param name="piece"></param>
- internal void QueueRead(PeerIdInternal id, ArraySegment<byte>
recieveBuffer, RequestMessage message, Piece piece)
+ internal void QueueRead(BufferedFileRead io)
{
- throw new NotImplementedException();
-
- /*lock (this.queueLock)
+ lock (this.queueLock)
{
- this.bufferedReads.Enqueue(new BufferedIO(id, recieveBuffer,
message, piece));
+ bufferedReads.Enqueue(io);
SetHandleState(true);
- }*/
+ }
}
@@ -372,11 +379,11 @@
private void RunIO()
{
BufferedIO write;
- //BufferedIO read;
+ BufferedFileRead read;
while (ioActive)
{
write = null;
- //read = null;
+ read = null;
// Take a lock on the queue and dequeue any reads/writes that
are available. Then lose the lock before
// performing the actual read/write to avoid blocking other
threads
@@ -387,19 +394,26 @@
write = this.bufferedWrites.Dequeue();
Interlocked.Add(ref rateLimiter.DownloadChunks,
-write.Buffer.Count / ConnectionManager.ChunkLength);
}
- //if (this.bufferedReads.Count > 0)
- // read = this.bufferedReads.Dequeue();
- // If there are no more reads available and no more writes
available, set the handle to wait
- if (this.bufferedWrites.Count == 0 || write == null) //
this.bufferedReads.Count == 0 &&
+ if (this.bufferedReads.Count > 0 &&
(rateLimiter.UploadChunks > 0))
+ {
+ read = this.bufferedReads.Dequeue();
+ Interlocked.Add(ref rateLimiter.UploadChunks,
-read.Count / ConnectionManager.ChunkLength);
+ }
+
+ // If both the read queue and write queue are empty, then
we unset the handle.
+ // Or if we have reached the max read/write rate and can't
dequeue something, we unset the handle
+ if ((this.bufferedWrites.Count == 0 &&
this.bufferedReads.Count == 0) || (write == null) && (read == null))
SetHandleState(false);
}
if (write != null)
PerformWrite(write);
- //if (read != null)
- // PerformRead(read);
+ if (read != null)
+ PerformRead(read);
+
+ // Wait ~100 ms before trying to read/write something again to
give the rate limiting a chance to recover
this.threadWait.WaitOne(100, false);
}
}
@@ -487,10 +501,5 @@
#endregion
- internal void CloseFileStreams(TorrentManager torrentManager)
- {
-#warning Buffer the Filestreams
- return;
- }
}
}
Modified: trunk/bitsharp/src/MonoTorrent/Client/Managers/FileManager.cs
===================================================================
--- trunk/bitsharp/src/MonoTorrent/Client/Managers/FileManager.cs
2008-01-03 16:46:00 UTC (rev 92189)
+++ trunk/bitsharp/src/MonoTorrent/Client/Managers/FileManager.cs
2008-01-03 16:58:11 UTC (rev 92190)
@@ -214,8 +214,10 @@
if ((pieceStartIndex + bytesToRead) > this.fileSize)
bytesToRead -= (int)((pieceStartIndex +
bytesToRead) - fileSize);
- //using (new ReaderLock(this.streamsLock))
- bytesRead = manager.Engine.DiskManager.Read(this,
hashBuffer.Array, hashBuffer.Offset, pieceStartIndex, bytesToRead);
+ BufferedFileRead read = new BufferedFileRead(this,
hashBuffer.Array, hashBuffer.Offset, pieceStartIndex, bytesToRead);
+ manager.Engine.DiskManager.QueueRead(read);
+ read.WaitHandle.WaitOne();
+ read.WaitHandle.Close();
hasher.TransformBlock(hashBuffer.Array,
hashBuffer.Offset, bytesRead, hashBuffer.Array, hashBuffer.Offset);
totalRead += bytesRead;
Modified: trunk/bitsharp/src/MonoTorrent/Client/Managers/TorrentManager.cs
===================================================================
--- trunk/bitsharp/src/MonoTorrent/Client/Managers/TorrentManager.cs
2008-01-03 16:46:00 UTC (rev 92189)
+++ trunk/bitsharp/src/MonoTorrent/Client/Managers/TorrentManager.cs
2008-01-03 16:58:11 UTC (rev 92190)
@@ -384,6 +384,7 @@
/// </summary>
public void Start()
{
+ this.engine.Start();
lock (this.engine.asyncCompletionLock)
{
// If the torrent was "paused", then just update the state to
Downloading and forcefully
@@ -422,7 +423,6 @@
engine.ConnectionManager.RegisterManager(this);
this.pieceManager.Reset();
- this.engine.Start();
}
}
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches