diff --git a/ZeroLevel/Services/Network/FileTransfer/FileReader.cs b/ZeroLevel/Services/Network/FileTransfer/FileReader.cs index d275fbc..128dbb2 100644 --- a/ZeroLevel/Services/Network/FileTransfer/FileReader.cs +++ b/ZeroLevel/Services/Network/FileTransfer/FileReader.cs @@ -33,7 +33,7 @@ namespace ZeroLevel.Services.Network.FileTransfer { var fragment = new FileFrame { - UploadTaskId = _startInfo.FileUploadTaskId, + UploadFileTaskId = _startInfo.UploadFileTaskId, Offset = offset * CHUNK_SIZE, Payload = new byte[bytesRead] }; @@ -47,7 +47,7 @@ namespace ZeroLevel.Services.Network.FileTransfer public FileEndFrame GetCompleteInfo() { - return new FileEndFrame { FileUploadTaskId = _startInfo.FileUploadTaskId }; + return new FileEndFrame { UploadFileTaskId = _startInfo.UploadFileTaskId }; } } } diff --git a/ZeroLevel/Services/Network/FileTransfer/FileReceiver.cs b/ZeroLevel/Services/Network/FileTransfer/FileReceiver.cs index c9a13d3..f707247 100644 --- a/ZeroLevel/Services/Network/FileTransfer/FileReceiver.cs +++ b/ZeroLevel/Services/Network/FileTransfer/FileReceiver.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using ZeroLevel.Models; using ZeroLevel.Services.Network.FileTransfer.Model; namespace ZeroLevel.Services.Network.FileTransfer @@ -40,10 +41,12 @@ namespace ZeroLevel.Services.Network.FileTransfer private string _basePath; private string _disk_prefix; - private readonly Dictionary _incoming = new Dictionary(); + private readonly Dictionary _incoming = new Dictionary(); private readonly object _locker = new object(); private long _cleanErrorsTaskId; + private readonly Dictionary _incomingLocks = new Dictionary(); + public FileReceiver(string path, string disk_prefix = "DRIVE_") { _disk_prefix = disk_prefix; @@ -68,37 +71,65 @@ namespace ZeroLevel.Services.Network.FileTransfer public void Incoming(FileStartFrame info, string clientFolderName) { - if (false == _incoming.ContainsKey(info.FileUploadTaskId)) + try { - lock (_locker) + if (false == _incoming.ContainsKey(info.UploadFileTaskId)) { - if (false == _incoming.ContainsKey(info.FileUploadTaskId)) + lock (_locker) { - string path = BuildFilePath(clientFolderName, info.FilePath); - _incoming.Add(info.FileUploadTaskId, new FileWriter(path)); + if (false == _incoming.ContainsKey(info.UploadFileTaskId)) + { + _incomingLocks.Add(info.UploadFileTaskId, new object()); + lock (_incomingLocks[info.UploadFileTaskId]) + { + string path = BuildFilePath(clientFolderName, info.FilePath); + _incoming.Add(info.UploadFileTaskId, new FileWriter(path)); + } + } } } } + catch (Exception ex) + { + Log.Error("[FileReceiver]", ex); + } } public void Incoming(FileFrame chunk) { - FileWriter stream; - if (_incoming.TryGetValue(chunk.UploadTaskId, out stream)) + try { - stream.Write(chunk.Offset, chunk.Payload); + FileWriter stream; + if (_incoming.TryGetValue(chunk.UploadFileTaskId, out stream)) + { + lock (_incomingLocks[chunk.UploadFileTaskId]) + { + stream.Write(chunk.Offset, chunk.Payload); + } + } + } + catch (Exception ex) + { + Log.Error("[FileReceiver]", ex); } } public void Incoming(FileEndFrame info) { - lock (_locker) + try + { + lock (_locker) + { + Remove(info.UploadFileTaskId); + } + } + catch (Exception ex) { - Remove(info.FileUploadTaskId); + Log.Error("[FileReceiver]", ex); } } - private void Remove(int uploadTaskId) + private void Remove(long uploadTaskId) { FileWriter stream; if (_incoming.TryGetValue(uploadTaskId, out stream)) diff --git a/ZeroLevel/Services/Network/FileTransfer/FileServer.cs b/ZeroLevel/Services/Network/FileTransfer/FileServer.cs index bf6a56a..0494359 100644 --- a/ZeroLevel/Services/Network/FileTransfer/FileServer.cs +++ b/ZeroLevel/Services/Network/FileTransfer/FileServer.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using ZeroLevel.Models; using ZeroLevel.Network; using ZeroLevel.Services.Network.FileTransfer.Model; diff --git a/ZeroLevel/Services/Network/FileTransfer/Model/FileEndFrame.cs b/ZeroLevel/Services/Network/FileTransfer/Model/FileEndFrame.cs index e6ef3e9..a6a7cda 100644 --- a/ZeroLevel/Services/Network/FileTransfer/Model/FileEndFrame.cs +++ b/ZeroLevel/Services/Network/FileTransfer/Model/FileEndFrame.cs @@ -3,18 +3,19 @@ namespace ZeroLevel.Services.Network.FileTransfer.Model { public sealed class FileEndFrame - : IBinarySerializable + : IBinarySerializable, IFileTransferInfo { - public int FileUploadTaskId; + public FileTransferInfoType TransferInfoType => FileTransferInfoType.End; + public long UploadFileTaskId { get; set; } public void Serialize(IBinaryWriter writer) { - writer.WriteInt32(this.FileUploadTaskId); + writer.WriteLong(this.UploadFileTaskId); } public void Deserialize(IBinaryReader reader) { - this.FileUploadTaskId = reader.ReadInt32(); + this.UploadFileTaskId = reader.ReadLong(); } } } diff --git a/ZeroLevel/Services/Network/FileTransfer/Model/FileFrame.cs b/ZeroLevel/Services/Network/FileTransfer/Model/FileFrame.cs index 2eb52dd..71be19d 100644 --- a/ZeroLevel/Services/Network/FileTransfer/Model/FileFrame.cs +++ b/ZeroLevel/Services/Network/FileTransfer/Model/FileFrame.cs @@ -3,22 +3,24 @@ namespace ZeroLevel.Services.Network.FileTransfer.Model { public sealed class FileFrame : - IBinarySerializable + IBinarySerializable, IFileTransferInfo { - public int UploadTaskId { get; set; } + public FileTransferInfoType TransferInfoType => FileTransferInfoType.Frame; + + public long UploadFileTaskId { get; set; } public long Offset { get; set; } public byte[] Payload { get; set; } public void Serialize(IBinaryWriter writer) { - writer.WriteInt32(this.UploadTaskId); + writer.WriteLong(this.UploadFileTaskId); writer.WriteLong(this.Offset); writer.WriteBytes(this.Payload); } public void Deserialize(IBinaryReader reader) { - this.UploadTaskId = reader.ReadInt32(); + this.UploadFileTaskId = reader.ReadLong(); this.Offset = reader.ReadLong(); this.Payload = reader.ReadBytes(); } diff --git a/ZeroLevel/Services/Network/FileTransfer/Model/FileStartFrame.cs b/ZeroLevel/Services/Network/FileTransfer/Model/FileStartFrame.cs index 957d65f..ba16844 100644 --- a/ZeroLevel/Services/Network/FileTransfer/Model/FileStartFrame.cs +++ b/ZeroLevel/Services/Network/FileTransfer/Model/FileStartFrame.cs @@ -4,24 +4,26 @@ using ZeroLevel.Services.Serialization; namespace ZeroLevel.Services.Network.FileTransfer.Model { public sealed class FileStartFrame - : IBinarySerializable + : IBinarySerializable, IFileTransferInfo { - private static int _uploadTaskIdCounter = 0; + private static long _uploadTaskIdCounter = 0; - public int FileUploadTaskId; + public FileTransferInfoType TransferInfoType => FileTransferInfoType.Start; + + public long UploadFileTaskId { get; set; } public string FilePath; public long Size; public void Serialize(IBinaryWriter writer) { - writer.WriteInt32(this.FileUploadTaskId); + writer.WriteLong(this.UploadFileTaskId); writer.WriteString(this.FilePath); writer.WriteLong(this.Size); } public void Deserialize(IBinaryReader reader) { - this.FileUploadTaskId = reader.ReadInt32(); + this.UploadFileTaskId = reader.ReadLong(); this.FilePath = reader.ReadString(); this.Size = reader.ReadLong(); } @@ -32,7 +34,7 @@ namespace ZeroLevel.Services.Network.FileTransfer.Model return new FileStartFrame { FilePath = fi.FullName, - FileUploadTaskId = Interlocked.Increment(ref _uploadTaskIdCounter), + UploadFileTaskId = Interlocked.Increment(ref _uploadTaskIdCounter), Size = fi.Length }; } diff --git a/ZeroLevel/Services/Network/FileTransfer/Model/IFileTransferInfo.cs b/ZeroLevel/Services/Network/FileTransfer/Model/IFileTransferInfo.cs new file mode 100644 index 0000000..c80da97 --- /dev/null +++ b/ZeroLevel/Services/Network/FileTransfer/Model/IFileTransferInfo.cs @@ -0,0 +1,15 @@ +namespace ZeroLevel.Services.Network.FileTransfer.Model +{ + public enum FileTransferInfoType + { + Start, + Frame, + End + } + + public interface IFileTransferInfo + { + long UploadFileTaskId { get; } + FileTransferInfoType TransferInfoType { get; } + } +}