Author: alanmc
Date: 2008-02-09 16:47:50 -0500 (Sat, 09 Feb 2008)
New Revision: 95344

Modified:
   trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/ClientEngine.cs
   trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/DiskManager.cs
   trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/PieceManager.cs
   trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/TorrentManager.cs
   trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/DiskWriter.cs
   trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/IPieceWriter.cs
   trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/MemoryWriter.cs
Log:
Implemented memory buffer for disk writes - disabled by default. It's sweet as 
a nut.

Modified: trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/ClientEngine.cs
===================================================================
--- trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/ClientEngine.cs   
2008-02-09 20:43:15 UTC (rev 95343)
+++ trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/ClientEngine.cs   
2008-02-09 21:47:50 UTC (rev 95344)
@@ -41,6 +41,7 @@
 using MonoTorrent.Common;
 using MonoTorrent.Client.Managers;
 using MonoTorrent.Client.Tracker;
+using MonoTorrent.Client.PieceWriter;
 
 namespace MonoTorrent.Client
 {
@@ -187,11 +188,15 @@
             if (listener == null && !createListener)
                 throw new ArgumentNullException("listener");
 
+            // Wrap a memory buffer around the disk writer
+            IPieceWriter writer = new DiskWriter(engineSettings.MaxOpenFiles);
+            //writer = new MemoryWriter(writer);
+
             this.settings = engineSettings;
 
             this.asyncCompletionLock = new object();
             this.connectionManager = new ConnectionManager(this);
-            this.diskManager = new DiskManager(this);
+            this.diskManager = new DiskManager(this, writer);
             this.listenManager = new ListenManager(this);
             this.peerId = GeneratePeerId();
             this.timer = new System.Timers.Timer(TickLength);

Modified: 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/DiskManager.cs
===================================================================
--- trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/DiskManager.cs   
2008-02-09 20:43:15 UTC (rev 95343)
+++ trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/DiskManager.cs   
2008-02-09 21:47:50 UTC (rev 95344)
@@ -6,6 +6,7 @@
 using System.IO;
 using MonoTorrent.Common;
 using MonoTorrent.Client.Messages.Standard;
+using MonoTorrent.Client.PieceWriter;
 
 namespace MonoTorrent.Client.Managers
 {
@@ -19,9 +20,8 @@
 
         private ConnectionMonitor monitor;
         internal RateLimiter rateLimiter;
-        private FileStreamBuffer streamsBuffer;
+        private IPieceWriter writer;
 
-
         #endregion Member Variables
 
 
@@ -43,11 +43,6 @@
             get { return monitor; }
         }
 
-        public int OpenFiles
-        {
-            get { return streamsBuffer.Count; }
-        }
-
         public int QueuedWrites
         {
             get { return this.bufferedWrites.Count; }
@@ -78,7 +73,7 @@
 
         #region Constructors
 
-        public DiskManager(ClientEngine engine)
+        internal DiskManager(ClientEngine engine, IPieceWriter writer)
         {
             this.bufferedReads = new Queue<BufferedFileRead>();
             this.bufferedWrites = new Queue<BufferedIO>();
@@ -88,9 +83,9 @@
             this.monitor = new ConnectionMonitor();
             this.queueLock = new object();
             this.rateLimiter = new RateLimiter();
-            this.streamsBuffer = new 
FileStreamBuffer(engine.Settings.MaxOpenFiles);
             this.streamsLock = new ReaderWriterLock();
             this.threadWait = new ManualResetEvent(false);
+            this.writer = writer;
             this.ioThread.Start();
         }
 
@@ -101,43 +96,20 @@
 
         internal void CloseFileStreams(TorrentManager manager)
         {
-            Array.ForEach<TorrentFile>(manager.Torrent.Files, 
delegate(TorrentFile f) { streamsBuffer.CloseStream(f); });
+            writer.CloseFileStreams(manager);
         }
 
 
-        /// <summary>
-        /// Generates the full path to the supplied TorrentFile
-        /// </summary>
-        /// <param name="file">The TorrentFile to generate the full path 
to</param>
-        /// <param name="baseDirectory">The name of the directory that the 
files are contained in</param>
-        /// <param name="savePath">The path to the directory that contains the 
BaseDirectory</param>
-        /// <returns>The full path to the TorrentFile</returns>
-        private static string GenerateFilePath(TorrentFile file, string 
baseDirectory, string savePath)
+        public void Dispose()
         {
-            string path;
-
-            path = Path.Combine(savePath, baseDirectory);
-            path = Path.Combine(path, file.Path);
-
-            if (!Directory.Exists(Path.GetDirectoryName(path)) && 
!string.IsNullOrEmpty(Path.GetDirectoryName(path)))
-                Directory.CreateDirectory(Path.GetDirectoryName(path));
-
-            return path;
+            ioActive = false;
+            this.threadWait.Set();
+            this.ioThread.Join();
+            this.writer.Dispose();
         }
 
 
         /// <summary>
-        /// Opens all the filestreams with the specified file access
-        /// </summary>
-        /// <param name="fileAccess"></param>
-        internal TorrentFileStream GetStream(FileManager manager, TorrentFile 
file, FileAccess access)
-        {
-            string filePath = GenerateFilePath(file, manager.BaseDirectory, 
manager.SavePath);
-            return streamsBuffer.GetStream(file, filePath, access);
-        }
-
-
-        /// <summary>
         /// Performs the buffered write
         /// </summary>
         /// <param name="bufferedFileIO"></param>
@@ -156,14 +128,15 @@
             {
                 // Calculate the index where we will start to write the data
                 long writeIndex = (long)message.PieceIndex * 
message.PieceLength + message.StartOffset;
-                Write(bufferedFileIO, recieveBuffer.Array, 
recieveBuffer.Offset, writeIndex, message.RequestLength);
+                writer.Write(bufferedFileIO, recieveBuffer.Array, 
recieveBuffer.Offset, writeIndex, message.RequestLength);
             }
 
             piece.Blocks[index].Written = true;
             id.TorrentManager.FileManager.RaiseBlockWritten(new 
BlockEventArgs(id.TorrentManager, piece.Blocks[index], piece, id));
 
             // Release the buffer back into the buffer manager.
-            ClientEngine.BufferManager.FreeBuffer(ref bufferedFileIO.Buffer);
+            //ClientEngine.BufferManager.FreeBuffer(ref bufferedFileIO.Buffer);
+#warning FIX THIS - don't free the buffer here anymore
 
             // If we haven't written all the pieces to disk, there's no point 
in hash checking
             if (!piece.AllBlocksWritten)
@@ -199,11 +172,17 @@
         /// <param name="bufferedFileIO"></param>
         private void PerformRead(BufferedFileRead io)
         {
-            io.BytesRead = Read(io.Manager, io.Buffer, io.BufferOffset, 
io.PieceStartIndex, io.Count);
+            io.BytesRead = writer.Read(io.Manager, io.Buffer, io.BufferOffset, 
io.PieceStartIndex, io.Count);
             io.WaitHandle.Set();
         }
 
 
+        internal int Read(FileManager fileManager, byte[] buffer, int 
bufferOffset, long pieceStartIndex, int bytesToRead)
+        {
+            return writer.Read(fileManager, buffer, bufferOffset, 
pieceStartIndex, bytesToRead);
+        }
+
+
         /// <summary>
         /// Queues a block of data to be written asynchronously
         /// </summary>
@@ -239,55 +218,6 @@
 
 
         /// <summary>
-        /// This method reads 'count' number of bytes from the filestream 
starting at index 'offset'.
-        /// The bytes are read into the buffer starting at index 
'bufferOffset'.
-        /// </summary>
-        /// <param name="buffer">The byte[] containing the bytes to 
write</param>
-        /// <param name="bufferOffset">The offset in the byte[] at which to 
save the data</param>
-        /// <param name="offset">The offset in the file at which to start 
reading the data</param>
-        /// <param name="count">The number of bytes to read</param>
-        /// <returns>The number of bytes successfully read</returns>
-        internal int Read(FileManager manager, byte[] buffer, int 
bufferOffset, long offset, int count)
-        {
-            if (buffer == null)
-                throw new ArgumentNullException("buffer");
-
-            if (offset < 0 || offset + count > manager.FileSize)
-                throw new ArgumentOutOfRangeException("offset");
-
-            int i = 0;
-            int bytesRead = 0;
-            int totalRead = 0;
-
-            for (i = 0; i < manager.Files.Length; i++)       // This section 
loops through all the available
-            {                                                   // files until 
we find the file which contains
-                if (offset < manager.Files[i].Length)              // the 
start of the data we want to read
-                    break;
-
-                offset -= manager.Files[i].Length;           // Offset now 
contains the index of the data we want
-            }                                                   // to read 
from fileStream[i].
-
-            while (totalRead < count)                           // We keep 
reading until we have read 'count' bytes.
-            {
-                if (i == manager.Files.Length)
-                    break;
-
-                lock (manager.Files[i])
-                {
-                    TorrentFileStream s = GetStream(manager, manager.Files[i], 
FileAccess.Read);
-                    s.Seek(offset, SeekOrigin.Begin);
-                    offset = 0; // Any further files need to be read from the 
beginning
-                    bytesRead = s.Read(buffer, bufferOffset + totalRead, count 
- totalRead);
-                    totalRead += bytesRead;
-                    i++;
-                }
-            }
-            monitor.BytesSent(totalRead, TransferType.Data);
-            return totalRead;
-        }
-
-
-        /// <summary>
         /// This method runs in a dedicated thread. It performs all the async 
reads and writes as they are queued
         /// </summary>
         private void RunIO()
@@ -345,74 +275,11 @@
                 this.threadWait.Reset();
         }
 
-
-        /// <summary>
-        /// This method reads 'count' number of bytes starting at the position 
'offset' into the
-        /// byte[] 'buffer'. The data gets written in the buffer starting at 
index 'bufferOffset'
-        /// </summary>
-        /// <param name="buffer">The byte[] to read the data into</param>
-        /// <param name="bufferOffset">The offset within the array to save the 
data</param>
-        /// <param name="offset">The offset in the file from which to read the 
data</param>
-        /// <param name="count">The number of bytes to read</param>
-        private void Write(BufferedIO io, byte[] buffer, int bufferOffset, 
long offset, int count)
-        {
-            FileManager manager = io.Id.TorrentManager.FileManager;
-            if (buffer == null)
-                throw new ArgumentNullException("buffer");
-
-            if (offset < 0 || offset + count > manager.FileSize)
-                throw new ArgumentOutOfRangeException("offset");
-
-            int i = 0;
-            long bytesWritten = 0;
-            long totalWritten = 0;
-            long bytesWeCanWrite = 0;
-
-            for (i = 0; i < manager.Files.Length; i++)          // This 
section loops through all the available
-            {                                                   // files until 
we find the file which contains
-                if (offset < manager.Files[i].Length)           // the start 
of the data we want to write
-                    break;
-
-                offset -= manager.Files[i].Length;              // Offset now 
contains the index of the data we want
-            }                                                   // to write to 
fileStream[i].
-
-            while (totalWritten < count)                        // We keep 
writing  until we have written 'count' bytes.
-            {
-                lock (manager.Files[i])
-                {
-                    TorrentFileStream stream = GetStream(manager, 
manager.Files[i], FileAccess.ReadWrite);
-                    stream.Seek(offset, SeekOrigin.Begin);
-
-                    // Find the maximum number of bytes we can write before we 
reach the end of the file
-                    bytesWeCanWrite = manager.Files[i].Length - offset;
-
-                    // Any further files need to be written from the beginning 
of the file
-                    offset = 0;
-
-                    // If the amount of data we are going to write is larger 
than the amount we can write, just write the allowed
-                    // amount and let the rest of the data be written with the 
next filestream
-                    bytesWritten = ((count - totalWritten) > bytesWeCanWrite) 
? bytesWeCanWrite : (count - totalWritten);
-
-                    // Write the data
-                    stream.Write(buffer, bufferOffset + (int)totalWritten, 
(int)bytesWritten);
-
-                    // Any further data should be written to the next 
available file
-                    totalWritten += bytesWritten;
-                    i++;
-                }
-            }
-
-            monitor.BytesReceived((int)totalWritten, TransferType.Data);
-        }
-
         #endregion
 
-        public void Dispose()
+        internal void Flush(TorrentManager manager)
         {
-            ioActive = false;
-            this.threadWait.Set();
-            this.ioThread.Join();
-            this.streamsBuffer.Dispose();
+            writer.Flush(manager);
         }
     }
 }

Modified: 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/PieceManager.cs
===================================================================
--- trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/PieceManager.cs  
2008-02-09 20:43:15 UTC (rev 95343)
+++ trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/PieceManager.cs  
2008-02-09 21:47:50 UTC (rev 95344)
@@ -78,7 +78,7 @@
         /// </summary>
         public bool LinearPickingEnabled
         {
-            get { return piecePicker.LinearPickingEnabled; }
+            get { return true;}// piecePicker.LinearPickingEnabled; }
             set { piecePicker.LinearPickingEnabled = value; }
         }
 

Modified: 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/TorrentManager.cs
===================================================================
--- 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/TorrentManager.cs    
    2008-02-09 20:43:15 UTC (rev 95343)
+++ 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/Managers/TorrentManager.cs    
    2008-02-09 21:47:50 UTC (rev 95344)
@@ -737,6 +737,7 @@
 
         internal void RaiseTorrentStateChanged(TorrentStateChangedEventArgs e)
         {
+            engine.DiskManager.Flush(this);
             ThreadPool.QueueUserWorkItem(delegate {
                 EventHandler<TorrentStateChangedEventArgs> h = 
TorrentStateChanged;
                 if (h != null)

Modified: 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/DiskWriter.cs
===================================================================
--- trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/DiskWriter.cs 
2008-02-09 20:43:15 UTC (rev 95343)
+++ trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/DiskWriter.cs 
2008-02-09 21:47:50 UTC (rev 95344)
@@ -8,31 +8,28 @@
 {
     public class DiskWriter : IPieceWriter
     {
-        public void Dispose()
+        private FileStreamBuffer streamsBuffer;
+
+        public int OpenFiles
         {
+            get { return streamsBuffer.Count; }
         }
 
-        public DiskWriter()
+        public DiskWriter(int maxOpenFiles)
         {
-            //this.streamsBuffer = new 
FileStreamBuffer(engine.Settings.MaxOpenFiles);
+            this.streamsBuffer = new FileStreamBuffer(maxOpenFiles);
         }
-        internal void CloseFileStreams(TorrentManager manager)
+
+        public void CloseFileStreams(TorrentManager manager)
         {
             Array.ForEach<TorrentFile>(manager.Torrent.Files, 
delegate(TorrentFile f) { streamsBuffer.CloseStream(f); });
         }
-        private FileStreamBuffer streamsBuffer;
 
-        public int OpenFiles
+        public void Dispose()
         {
-            get { return streamsBuffer.Count; }
+            streamsBuffer.Dispose();
         }
-        /// <summary>
-        /// Generates the full path to the supplied TorrentFile
-        /// </summary>
-        /// <param name="file">The TorrentFile to generate the full path 
to</param>
-        /// <param name="baseDirectory">The name of the directory that the 
files are contained in</param>
-        /// <param name="savePath">The path to the directory that contains the 
BaseDirectory</param>
-        /// <returns>The full path to the TorrentFile</returns>
+
         private static string GenerateFilePath(TorrentFile file, string 
baseDirectory, string savePath)
         {
             string path;
@@ -46,18 +43,12 @@
             return path;
         }
 
-
-        /// <summary>
-        /// Opens all the filestreams with the specified file access
-        /// </summary>
-        /// <param name="fileAccess"></param>
         internal TorrentFileStream GetStream(FileManager manager, TorrentFile 
file, FileAccess access)
         {
             string filePath = GenerateFilePath(file, manager.BaseDirectory, 
manager.SavePath);
             return streamsBuffer.GetStream(file, filePath, access);
         }
 
-
         public int Read(FileManager manager, byte[] buffer, int bufferOffset, 
long offset, int count)
         {
             if (buffer == null)
@@ -70,12 +61,12 @@
             int bytesRead = 0;
             int totalRead = 0;
 
-            for (i = 0; i < manager.Files.Length; i++)       // This section 
loops through all the available
+            for (i = 0; i < manager.Files.Length; i++)          // This 
section loops through all the available
             {                                                   // files until 
we find the file which contains
-                if (offset < manager.Files[i].Length)              // the 
start of the data we want to read
+                if (offset < manager.Files[i].Length)           // the start 
of the data we want to read
                     break;
 
-                offset -= manager.Files[i].Length;           // Offset now 
contains the index of the data we want
+                offset -= manager.Files[i].Length;              // Offset now 
contains the index of the data we want
             }                                                   // to read 
from fileStream[i].
 
             while (totalRead < count)                           // We keep 
reading until we have read 'count' bytes.
@@ -138,6 +129,7 @@
 
                     // Write the data
                     stream.Write(buffer, bufferOffset + (int)totalWritten, 
(int)bytesWritten);
+                    stream.Flush();
 
                     // Any further data should be written to the next 
available file
                     totalWritten += bytesWritten;
@@ -147,5 +139,10 @@
 
             //monitor.BytesReceived((int)totalWritten, TransferType.Data);
         }
+
+        public void Flush(TorrentManager manager)
+        {
+            // No buffering done here
+        }
     }
 }

Modified: 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/IPieceWriter.cs
===================================================================
--- 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/IPieceWriter.cs   
    2008-02-09 20:43:15 UTC (rev 95343)
+++ 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/IPieceWriter.cs   
    2008-02-09 21:47:50 UTC (rev 95344)
@@ -1,13 +1,18 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using MonoTorrent.Common;
 
 namespace MonoTorrent.Client.PieceWriter
 {
     interface IPieceWriter : IDisposable
     {
         int Read(FileManager manager, byte[] buffer, int bufferOffset, long 
offset, int count);
+        
+        void Write(BufferedIO io, byte[] buffer, int bufferOffset, long 
offset, int count);
 
-        void Write(BufferedIO io, byte[] buffer, int bufferOffset, long 
offset, int count);
+        void CloseFileStreams(TorrentManager manager);
+
+        void Flush(TorrentManager manager);
     }
 }

Modified: 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/MemoryWriter.cs
===================================================================
--- 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/MemoryWriter.cs   
    2008-02-09 20:43:15 UTC (rev 95343)
+++ 
trunk/bitsharp/src/MonoTorrent/MonoTorrent.Client/PieceWriter/MemoryWriter.cs   
    2008-02-09 21:47:50 UTC (rev 95344)
@@ -6,120 +6,142 @@
 
 namespace MonoTorrent.Client.PieceWriter
 {
+    internal class MemIO
+    {
+        public FileManager manager;
+        public byte[] buffer;
+        public int bufferOffset;
+        public long offset;
+        public int count;
+        public BufferedIO io;
+
+        public MemIO(FileManager manager, BufferedIO io, byte[] buffer, int 
bufferOffset, long offset, int count)
+        {
+            this.manager = manager;
+            this.io = io;
+            this.buffer = buffer;
+            this.bufferOffset = bufferOffset;
+            this.offset = offset;
+            this.count = count;
+        }
+    }
     public class MemoryWriter : IPieceWriter
     {
-        public void Dispose()
+        private int capacity;
+        private List<MemIO> memoryBuffer;
+        private IPieceWriter writer;
+
+
+        public int Capacity
         {
+            get { return capacity; }
         }
-        private int bufferSize;
-        private List <BufferedIO> memoryBuffer;
-        public int BufferSize = 8 * 1024 * 1024;
 
         public int Used
         {
             get
             {
                 int count = 0;
-                memoryBuffer.ForEach(delegate(BufferedIO i) { count += 
i.Buffer.Count; });
+                memoryBuffer.ForEach(delegate(MemIO i) { count += i.count; });
                 return count;
             }
         }
 
-        public MemoryWriter()
+        internal MemoryWriter(IPieceWriter writer)
+            : this(writer, 8 * 1024 * 1024)
         {
-            memoryBuffer = new List<BufferedIO>();
+
         }
 
+        internal MemoryWriter(IPieceWriter writer, int capacity)
+        {
+            if (writer == null)
+                throw new ArgumentNullException("writer");
 
-        public int Read(FileManager manager, byte[] buffer, int bufferOffset, 
long offset, int count)
-        {/*
-            if (buffer == null)
-                throw new ArgumentNullException("buffer");
+            if (capacity < 0)
+                throw new ArgumentOutOfRangeException("capacity");
 
-            if (offset < 0 || offset + count > manager.FileSize)
-                throw new ArgumentOutOfRangeException("offset");
+            memoryBuffer = new List<MemIO>();
+            this.capacity = capacity;
+            this.writer = writer;
+        }
 
-            int i = 0;
-            int bytesRead = 0;
-            int totalRead = 0;
+        public void Dispose()
+        {
 
-            for (i = 0; i < manager.Files.Length; i++)       // This section 
loops through all the available
-            {                                                   // files until 
we find the file which contains
-                if (offset < manager.Files[i].Length)              // the 
start of the data we want to read
-                    break;
+        }
 
-                offset -= manager.Files[i].Length;           // Offset now 
contains the index of the data we want
-            }                                                   // to read 
from fileStream[i].
 
-            while (totalRead < count)                           // We keep 
reading until we have read 'count' bytes.
+        public int Read(FileManager manager, byte[] buffer, int bufferOffset, 
long offset, int count)
+        {
+            int origCount = count;
+            while (count != 0)
             {
-                if (i == manager.Files.Length)
-                    break;
-
-                lock (manager.Files[i])
+                memoryBuffer.Sort(delegate(MemIO left, MemIO right) { return 
left.offset.CompareTo(right.offset); });
+                MemIO io = memoryBuffer.Find(delegate(MemIO m) { return 
((offset >= m.offset) && (offset < (m.offset + m.count))); });
+                if (io != null)
                 {
-                    TorrentFileStream s = GetStream(manager, manager.Files[i], 
FileAccess.Read);
-                    s.Seek(offset, SeekOrigin.Begin);
-                    offset = 0; // Any further files need to be read from the 
beginning
-                    bytesRead = s.Read(buffer, bufferOffset + totalRead, count 
- totalRead);
-                    totalRead += bytesRead;
-                    i++;
+                    int toCopy = Math.Min(count, io.count + (int)(io.offset - 
offset));
+                    Buffer.BlockCopy(io.buffer, io.bufferOffset + 
(int)(io.offset - offset), buffer, bufferOffset + (origCount - count), toCopy);
+                    offset += toCopy;
+                    count -= toCopy;
                 }
+                else
+                    break;
             }
-            monitor.BytesSent(totalRead, TransferType.Data);
-            return totalRead;*/
-            return 1;
+            if(count == 0)
+                return origCount;
+
+            return writer.Read(manager, buffer, bufferOffset, offset, count) + 
(origCount - count);
         }
 
+        private void Write(MemIO m)
+        {
+            Write(m.io, m.buffer, m.bufferOffset, m.offset, m.count, true);
+        }
+
+
         public void Write(BufferedIO io, byte[] buffer, int bufferOffset, long 
offset, int count)
-        {/*
-            FileManager manager = io.Id.TorrentManager.FileManager;
-            if (buffer == null)
-                throw new ArgumentNullException("buffer");
+        {
+            Write(io, buffer, bufferOffset, offset, count, false);
+        }
 
-            if (offset < 0 || offset + count > manager.FileSize)
-                throw new ArgumentOutOfRangeException("offset");
+        public void Write(BufferedIO io, byte[] buffer, int bufferOffset, long 
offset, int count, bool forceWrite)
+        {
+            if (forceWrite)
+            {
+                writer.Write(io, buffer, bufferOffset, offset, count);
+                return;
+            }
 
-            int i = 0;
-            long bytesWritten = 0;
-            long totalWritten = 0;
-            long bytesWeCanWrite = 0;
+            if (Used >= (Capacity - count))
+                FlushSome();
 
-            for (i = 0; i < manager.Files.Length; i++)          // This 
section loops through all the available
-            {                                                   // files until 
we find the file which contains
-                if (offset < manager.Files[i].Length)           // the start 
of the data we want to write
-                    break;
+            memoryBuffer.Add(new MemIO(io.Id.TorrentManager.FileManager, io, 
buffer, bufferOffset, offset, count));
+        }
 
-                offset -= manager.Files[i].Length;              // Offset now 
contains the index of the data we want
-            }                                                   // to write to 
fileStream[i].
+        private void FlushSome()
+        {
+            int count = Math.Min(5, memoryBuffer.Count);
+            for (int i = 0; i < count; i++)
+                Write(memoryBuffer[i]);
 
-            while (totalWritten < count)                        // We keep 
writing  until we have written 'count' bytes.
-            {
-                lock (manager.Files[i])
-                {
-                    TorrentFileStream stream = GetStream(manager, 
manager.Files[i], FileAccess.ReadWrite);
-                    stream.Seek(offset, SeekOrigin.Begin);
+            memoryBuffer.RemoveRange(0, count);
+        }
 
-                    // Find the maximum number of bytes we can write before we 
reach the end of the file
-                    bytesWeCanWrite = manager.Files[i].Length - offset;
 
-                    // Any further files need to be written from the beginning 
of the file
-                    offset = 0;
 
-                    // If the amount of data we are going to write is larger 
than the amount we can write, just write the allowed
-                    // amount and let the rest of the data be written with the 
next filestream
-                    bytesWritten = ((count - totalWritten) > bytesWeCanWrite) 
? bytesWeCanWrite : (count - totalWritten);
+        public void CloseFileStreams(TorrentManager manager)
+        {
+            Flush(manager);
+            writer.CloseFileStreams(manager);
+        }
 
-                    // Write the data
-                    stream.Write(buffer, bufferOffset + (int)totalWritten, 
(int)bytesWritten);
 
-                    // Any further data should be written to the next 
available file
-                    totalWritten += bytesWritten;
-                    i++;
-                }
-            }
-
-            monitor.BytesReceived((int)totalWritten, TransferType.Data);*/
+        public void Flush(TorrentManager manager)
+        {
+            memoryBuffer.ForEach(delegate(MemIO io) { if (io.manager == 
manager.FileManager) Write(io); });
+            memoryBuffer.RemoveAll(delegate(MemIO io) { return io.manager == 
manager.FileManager; });
         }
     }
 }

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to